Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2014 Intel Corporation. All rights reserved.
0003  * Copyright (c) 2014 Chelsio, Inc. All rights reserved.
0004  *
0005  * This software is available to you under a choice of one of two
0006  * licenses.  You may choose to be licensed under the terms of the GNU
0007  * General Public License (GPL) Version 2, available from the file
0008  * COPYING in the main directory of this source tree, or the
0009  * OpenIB.org BSD license below:
0010  *
0011  *     Redistribution and use in source and binary forms, with or
0012  *     without modification, are permitted provided that the following
0013  *     conditions are met:
0014  *
0015  *      - Redistributions of source code must retain the above
0016  *        copyright notice, this list of conditions and the following
0017  *        disclaimer.
0018  *
0019  *      - Redistributions in binary form must reproduce the above
0020  *        copyright notice, this list of conditions and the following
0021  *        disclaimer in the documentation and/or other materials
0022  *        provided with the distribution.
0023  *
0024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0026  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0027  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0028  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0029  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0030  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0031  * SOFTWARE.
0032  */
0033 
0034 #include "iwpm_util.h"
0035 
0036 static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";
0037 u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN;
0038 static int iwpm_user_pid = IWPM_PID_UNDEFINED;
0039 static atomic_t echo_nlmsg_seq;
0040 
0041 /**
0042  * iwpm_valid_pid - Check if the userspace iwarp port mapper pid is valid
0043  *
0044  * Returns true if the pid is greater than zero, otherwise returns false
0045  */
0046 int iwpm_valid_pid(void)
0047 {
0048     return iwpm_user_pid > 0;
0049 }
0050 
0051 /**
0052  * iwpm_register_pid - Send a netlink query to userspace
0053  *                     to get the iwarp port mapper pid
0054  * @pm_msg: Contains driver info to send to the userspace port mapper
0055  * @nl_client: The index of the netlink client
0056  *
0057  * nlmsg attributes:
0058  *  [IWPM_NLA_REG_PID_SEQ]
0059  *  [IWPM_NLA_REG_IF_NAME]
0060  *  [IWPM_NLA_REG_IBDEV_NAME]
0061  *  [IWPM_NLA_REG_ULIB_NAME]
0062  */
0063 int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
0064 {
0065     struct sk_buff *skb = NULL;
0066     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0067     struct nlmsghdr *nlh;
0068     u32 msg_seq;
0069     const char *err_str = "";
0070     int ret = -EINVAL;
0071 
0072     if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
0073             iwpm_user_pid == IWPM_PID_UNAVAILABLE)
0074         return 0;
0075     skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
0076     if (!skb) {
0077         err_str = "Unable to create a nlmsg";
0078         goto pid_query_error;
0079     }
0080     nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0081     nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
0082     if (!nlmsg_request) {
0083         err_str = "Unable to allocate netlink request";
0084         goto pid_query_error;
0085     }
0086     msg_seq = atomic_read(&echo_nlmsg_seq);
0087 
0088     /* fill in the pid request message */
0089     err_str = "Unable to put attribute of the nlmsg";
0090     ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
0091     if (ret)
0092         goto pid_query_error;
0093     ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,
0094                 pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
0095     if (ret)
0096         goto pid_query_error;
0097     ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE,
0098                 pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME);
0099     if (ret)
0100         goto pid_query_error;
0101     ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE,
0102                 (char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME);
0103     if (ret)
0104         goto pid_query_error;
0105 
0106     nlmsg_end(skb, nlh);
0107 
0108     pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
0109         __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
0110 
0111     ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
0112     if (ret) {
0113         skb = NULL; /* skb is freed in the netlink send-op handling */
0114         iwpm_user_pid = IWPM_PID_UNAVAILABLE;
0115         err_str = "Unable to send a nlmsg";
0116         goto pid_query_error;
0117     }
0118     nlmsg_request->req_buffer = pm_msg;
0119     ret = iwpm_wait_complete_req(nlmsg_request);
0120     return ret;
0121 pid_query_error:
0122     pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
0123     dev_kfree_skb(skb);
0124     if (nlmsg_request)
0125         iwpm_free_nlmsg_request(&nlmsg_request->kref);
0126     return ret;
0127 }
0128 
0129 /**
0130  * iwpm_add_mapping - Send a netlink add mapping request to
0131  *                    the userspace port mapper
0132  * @pm_msg: Contains the local ip/tcp address info to send
0133  * @nl_client: The index of the netlink client
0134  *
0135  * nlmsg attributes:
0136  *  [IWPM_NLA_MANAGE_MAPPING_SEQ]
0137  *  [IWPM_NLA_MANAGE_ADDR]
0138  *  [IWPM_NLA_MANAGE_FLAGS]
0139  *
0140  * If the request is successful, the pm_msg stores
0141  * the port mapper response (mapped address info)
0142  */
0143 int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
0144 {
0145     struct sk_buff *skb = NULL;
0146     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0147     struct nlmsghdr *nlh;
0148     u32 msg_seq;
0149     const char *err_str = "";
0150     int ret = -EINVAL;
0151 
0152     if (!iwpm_valid_pid())
0153         return 0;
0154     if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
0155         err_str = "Unregistered port mapper client";
0156         goto add_mapping_error;
0157     }
0158     skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
0159     if (!skb) {
0160         err_str = "Unable to create a nlmsg";
0161         goto add_mapping_error;
0162     }
0163     nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0164     nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
0165     if (!nlmsg_request) {
0166         err_str = "Unable to allocate netlink request";
0167         goto add_mapping_error;
0168     }
0169     msg_seq = atomic_read(&echo_nlmsg_seq);
0170     /* fill in the add mapping message */
0171     err_str = "Unable to put attribute of the nlmsg";
0172     ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
0173                 IWPM_NLA_MANAGE_MAPPING_SEQ);
0174     if (ret)
0175         goto add_mapping_error;
0176     ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
0177                 &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
0178     if (ret)
0179         goto add_mapping_error;
0180 
0181     /* If flags are required and we're not V4, then return a quiet error */
0182     if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
0183         ret = -EINVAL;
0184         goto add_mapping_error_nowarn;
0185     }
0186     if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
0187         ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
0188                 IWPM_NLA_MANAGE_FLAGS);
0189         if (ret)
0190             goto add_mapping_error;
0191     }
0192 
0193     nlmsg_end(skb, nlh);
0194     nlmsg_request->req_buffer = pm_msg;
0195 
0196     ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
0197     if (ret) {
0198         skb = NULL; /* skb is freed in the netlink send-op handling */
0199         iwpm_user_pid = IWPM_PID_UNDEFINED;
0200         err_str = "Unable to send a nlmsg";
0201         goto add_mapping_error;
0202     }
0203     ret = iwpm_wait_complete_req(nlmsg_request);
0204     return ret;
0205 add_mapping_error:
0206     pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
0207 add_mapping_error_nowarn:
0208     dev_kfree_skb(skb);
0209     if (nlmsg_request)
0210         iwpm_free_nlmsg_request(&nlmsg_request->kref);
0211     return ret;
0212 }
0213 
0214 /**
0215  * iwpm_add_and_query_mapping - Process the port mapper response to
0216  *                              iwpm_add_and_query_mapping request
0217  * @pm_msg: Contains the local ip/tcp address info to send
0218  * @nl_client: The index of the netlink client
0219  *
0220  * nlmsg attributes:
0221  *  [IWPM_NLA_QUERY_MAPPING_SEQ]
0222  *  [IWPM_NLA_QUERY_LOCAL_ADDR]
0223  *  [IWPM_NLA_QUERY_REMOTE_ADDR]
0224  *  [IWPM_NLA_QUERY_FLAGS]
0225  */
0226 int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
0227 {
0228     struct sk_buff *skb = NULL;
0229     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0230     struct nlmsghdr *nlh;
0231     u32 msg_seq;
0232     const char *err_str = "";
0233     int ret = -EINVAL;
0234 
0235     if (!iwpm_valid_pid())
0236         return 0;
0237     if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
0238         err_str = "Unregistered port mapper client";
0239         goto query_mapping_error;
0240     }
0241     ret = -ENOMEM;
0242     skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
0243     if (!skb) {
0244         err_str = "Unable to create a nlmsg";
0245         goto query_mapping_error;
0246     }
0247     nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0248     nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,
0249                 nl_client, GFP_KERNEL);
0250     if (!nlmsg_request) {
0251         err_str = "Unable to allocate netlink request";
0252         goto query_mapping_error;
0253     }
0254     msg_seq = atomic_read(&echo_nlmsg_seq);
0255 
0256     /* fill in the query message */
0257     err_str = "Unable to put attribute of the nlmsg";
0258     ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
0259                 IWPM_NLA_QUERY_MAPPING_SEQ);
0260     if (ret)
0261         goto query_mapping_error;
0262     ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
0263                 &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);
0264     if (ret)
0265         goto query_mapping_error;
0266     ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
0267                 &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
0268     if (ret)
0269         goto query_mapping_error;
0270 
0271     /* If flags are required and we're not V4, then return a quite error */
0272     if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
0273         ret = -EINVAL;
0274         goto query_mapping_error_nowarn;
0275     }
0276     if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
0277         ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
0278                 IWPM_NLA_QUERY_FLAGS);
0279         if (ret)
0280             goto query_mapping_error;
0281     }
0282 
0283     nlmsg_end(skb, nlh);
0284     nlmsg_request->req_buffer = pm_msg;
0285 
0286     ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
0287     if (ret) {
0288         skb = NULL; /* skb is freed in the netlink send-op handling */
0289         err_str = "Unable to send a nlmsg";
0290         goto query_mapping_error;
0291     }
0292     ret = iwpm_wait_complete_req(nlmsg_request);
0293     return ret;
0294 query_mapping_error:
0295     pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
0296 query_mapping_error_nowarn:
0297     dev_kfree_skb(skb);
0298     if (nlmsg_request)
0299         iwpm_free_nlmsg_request(&nlmsg_request->kref);
0300     return ret;
0301 }
0302 
0303 /**
0304  * iwpm_remove_mapping - Send a netlink remove mapping request
0305  *                       to the userspace port mapper
0306  *
0307  * @local_addr: Local ip/tcp address to remove
0308  * @nl_client: The index of the netlink client
0309  *
0310  * nlmsg attributes:
0311  *  [IWPM_NLA_MANAGE_MAPPING_SEQ]
0312  *  [IWPM_NLA_MANAGE_ADDR]
0313  */
0314 int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
0315 {
0316     struct sk_buff *skb = NULL;
0317     struct nlmsghdr *nlh;
0318     u32 msg_seq;
0319     const char *err_str = "";
0320     int ret = -EINVAL;
0321 
0322     if (!iwpm_valid_pid())
0323         return 0;
0324     if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
0325         err_str = "Unregistered port mapper client";
0326         goto remove_mapping_error;
0327     }
0328     skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
0329     if (!skb) {
0330         ret = -ENOMEM;
0331         err_str = "Unable to create a nlmsg";
0332         goto remove_mapping_error;
0333     }
0334     msg_seq = atomic_read(&echo_nlmsg_seq);
0335     nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
0336     err_str = "Unable to put attribute of the nlmsg";
0337     ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
0338                 IWPM_NLA_MANAGE_MAPPING_SEQ);
0339     if (ret)
0340         goto remove_mapping_error;
0341     ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
0342                 local_addr, IWPM_NLA_MANAGE_ADDR);
0343     if (ret)
0344         goto remove_mapping_error;
0345 
0346     nlmsg_end(skb, nlh);
0347 
0348     ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
0349     if (ret) {
0350         skb = NULL; /* skb is freed in the netlink send-op handling */
0351         iwpm_user_pid = IWPM_PID_UNDEFINED;
0352         err_str = "Unable to send a nlmsg";
0353         goto remove_mapping_error;
0354     }
0355     iwpm_print_sockaddr(local_addr,
0356             "remove_mapping: Local sockaddr:");
0357     return 0;
0358 remove_mapping_error:
0359     pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);
0360     if (skb)
0361         dev_kfree_skb_any(skb);
0362     return ret;
0363 }
0364 
0365 /* netlink attribute policy for the received response to register pid request */
0366 static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {
0367     [IWPM_NLA_RREG_PID_SEQ]     = { .type = NLA_U32 },
0368     [IWPM_NLA_RREG_IBDEV_NAME]  = { .type = NLA_STRING,
0369                     .len = IWPM_DEVNAME_SIZE - 1 },
0370     [IWPM_NLA_RREG_ULIB_NAME]   = { .type = NLA_STRING,
0371                     .len = IWPM_ULIBNAME_SIZE - 1 },
0372     [IWPM_NLA_RREG_ULIB_VER]    = { .type = NLA_U16 },
0373     [IWPM_NLA_RREG_PID_ERR]     = { .type = NLA_U16 }
0374 };
0375 
0376 /**
0377  * iwpm_register_pid_cb - Process the port mapper response to
0378  *                        iwpm_register_pid query
0379  * @skb: The socket buffer
0380  * @cb: Contains the received message (payload and netlink header)
0381  *
0382  * If successful, the function receives the userspace port mapper pid
0383  * which is used in future communication with the port mapper
0384  */
0385 int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
0386 {
0387     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0388     struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
0389     struct iwpm_dev_data *pm_msg;
0390     char *dev_name, *iwpm_name;
0391     u32 msg_seq;
0392     u8 nl_client;
0393     u16 iwpm_version;
0394     const char *msg_type = "Register Pid response";
0395 
0396     if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
0397                 resp_reg_policy, nltb, msg_type))
0398         return -EINVAL;
0399 
0400     msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
0401     nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
0402     if (!nlmsg_request) {
0403         pr_info("%s: Could not find a matching request (seq = %u)\n",
0404                  __func__, msg_seq);
0405         return -EINVAL;
0406     }
0407     pm_msg = nlmsg_request->req_buffer;
0408     nl_client = nlmsg_request->nl_client;
0409     dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
0410     iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
0411     iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);
0412 
0413     /* check device name, ulib name and version */
0414     if (strcmp(pm_msg->dev_name, dev_name) ||
0415             strcmp(iwpm_ulib_name, iwpm_name) ||
0416             iwpm_version < IWPM_UABI_VERSION_MIN) {
0417 
0418         pr_info("%s: Incorrect info (dev = %s name = %s version = %u)\n",
0419                 __func__, dev_name, iwpm_name, iwpm_version);
0420         nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
0421         goto register_pid_response_exit;
0422     }
0423     iwpm_user_pid = cb->nlh->nlmsg_pid;
0424     iwpm_ulib_version = iwpm_version;
0425     if (iwpm_ulib_version < IWPM_UABI_VERSION)
0426         pr_warn_once("%s: Down level iwpmd/pid %d.  Continuing...",
0427             __func__, iwpm_user_pid);
0428     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0429     pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
0430             __func__, iwpm_user_pid);
0431     iwpm_set_registration(nl_client, IWPM_REG_VALID);
0432 register_pid_response_exit:
0433     nlmsg_request->request_done = 1;
0434     /* always for found nlmsg_request */
0435     kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
0436     barrier();
0437     up(&nlmsg_request->sem);
0438     return 0;
0439 }
0440 
0441 /* netlink attribute policy for the received response to add mapping request */
0442 static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {
0443     [IWPM_NLA_RMANAGE_MAPPING_SEQ]     = { .type = NLA_U32 },
0444     [IWPM_NLA_RMANAGE_ADDR]            = {
0445                 .len = sizeof(struct sockaddr_storage) },
0446     [IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR] = {
0447                 .len = sizeof(struct sockaddr_storage) },
0448     [IWPM_NLA_RMANAGE_MAPPING_ERR]     = { .type = NLA_U16 }
0449 };
0450 
0451 /**
0452  * iwpm_add_mapping_cb - Process the port mapper response to
0453  *                       iwpm_add_mapping request
0454  * @skb: The socket buffer
0455  * @cb: Contains the received message (payload and netlink header)
0456  */
0457 int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)
0458 {
0459     struct iwpm_sa_data *pm_msg;
0460     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0461     struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];
0462     struct sockaddr_storage *local_sockaddr;
0463     struct sockaddr_storage *mapped_sockaddr;
0464     const char *msg_type;
0465     u32 msg_seq;
0466 
0467     msg_type = "Add Mapping response";
0468     if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,
0469                 resp_add_policy, nltb, msg_type))
0470         return -EINVAL;
0471 
0472     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0473 
0474     msg_seq = nla_get_u32(nltb[IWPM_NLA_RMANAGE_MAPPING_SEQ]);
0475     nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
0476     if (!nlmsg_request) {
0477         pr_info("%s: Could not find a matching request (seq = %u)\n",
0478                  __func__, msg_seq);
0479         return -EINVAL;
0480     }
0481     pm_msg = nlmsg_request->req_buffer;
0482     local_sockaddr = (struct sockaddr_storage *)
0483             nla_data(nltb[IWPM_NLA_RMANAGE_ADDR]);
0484     mapped_sockaddr = (struct sockaddr_storage *)
0485             nla_data(nltb[IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR]);
0486 
0487     if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {
0488         nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
0489         goto add_mapping_response_exit;
0490     }
0491     if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {
0492         pr_info("%s: Sockaddr family doesn't match the requested one\n",
0493                 __func__);
0494         nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
0495         goto add_mapping_response_exit;
0496     }
0497     memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,
0498             sizeof(*mapped_sockaddr));
0499     iwpm_print_sockaddr(&pm_msg->loc_addr,
0500             "add_mapping: Local sockaddr:");
0501     iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
0502             "add_mapping: Mapped local sockaddr:");
0503 
0504 add_mapping_response_exit:
0505     nlmsg_request->request_done = 1;
0506     /* always for found request */
0507     kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
0508     barrier();
0509     up(&nlmsg_request->sem);
0510     return 0;
0511 }
0512 
0513 /* netlink attribute policy for the response to add and query mapping request
0514  * and response with remote address info
0515  */
0516 static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
0517     [IWPM_NLA_RQUERY_MAPPING_SEQ]     = { .type = NLA_U32 },
0518     [IWPM_NLA_RQUERY_LOCAL_ADDR]      = {
0519                 .len = sizeof(struct sockaddr_storage) },
0520     [IWPM_NLA_RQUERY_REMOTE_ADDR]     = {
0521                 .len = sizeof(struct sockaddr_storage) },
0522     [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = {
0523                 .len = sizeof(struct sockaddr_storage) },
0524     [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = {
0525                 .len = sizeof(struct sockaddr_storage) },
0526     [IWPM_NLA_RQUERY_MAPPING_ERR]     = { .type = NLA_U16 }
0527 };
0528 
0529 /**
0530  * iwpm_add_and_query_mapping_cb - Process the port mapper response to
0531  *                                 iwpm_add_and_query_mapping request
0532  * @skb: The socket buffer
0533  * @cb: Contains the received message (payload and netlink header)
0534  */
0535 int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
0536                 struct netlink_callback *cb)
0537 {
0538     struct iwpm_sa_data *pm_msg;
0539     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0540     struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
0541     struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
0542     struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
0543     const char *msg_type;
0544     u32 msg_seq;
0545     u16 err_code;
0546 
0547     msg_type = "Query Mapping response";
0548     if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
0549                 resp_query_policy, nltb, msg_type))
0550         return -EINVAL;
0551     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0552 
0553     msg_seq = nla_get_u32(nltb[IWPM_NLA_RQUERY_MAPPING_SEQ]);
0554     nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
0555     if (!nlmsg_request) {
0556         pr_info("%s: Could not find a matching request (seq = %u)\n",
0557                  __func__, msg_seq);
0558         return -EINVAL;
0559     }
0560     pm_msg = nlmsg_request->req_buffer;
0561     local_sockaddr = (struct sockaddr_storage *)
0562             nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
0563     remote_sockaddr = (struct sockaddr_storage *)
0564             nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
0565     mapped_loc_sockaddr = (struct sockaddr_storage *)
0566             nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
0567     mapped_rem_sockaddr = (struct sockaddr_storage *)
0568             nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
0569 
0570     err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);
0571     if (err_code == IWPM_REMOTE_QUERY_REJECT) {
0572         pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",
0573             __func__, cb->nlh->nlmsg_pid, msg_seq);
0574         nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;
0575     }
0576     if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||
0577         iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {
0578         pr_info("%s: Incorrect local sockaddr\n", __func__);
0579         nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
0580         goto query_mapping_response_exit;
0581     }
0582     if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
0583         mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
0584         pr_info("%s: Sockaddr family doesn't match the requested one\n",
0585                 __func__);
0586         nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
0587         goto query_mapping_response_exit;
0588     }
0589     memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,
0590             sizeof(*mapped_loc_sockaddr));
0591     memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,
0592             sizeof(*mapped_rem_sockaddr));
0593 
0594     iwpm_print_sockaddr(&pm_msg->loc_addr,
0595             "query_mapping: Local sockaddr:");
0596     iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
0597             "query_mapping: Mapped local sockaddr:");
0598     iwpm_print_sockaddr(&pm_msg->rem_addr,
0599             "query_mapping: Remote sockaddr:");
0600     iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,
0601             "query_mapping: Mapped remote sockaddr:");
0602 query_mapping_response_exit:
0603     nlmsg_request->request_done = 1;
0604     /* always for found request */
0605     kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
0606     barrier();
0607     up(&nlmsg_request->sem);
0608     return 0;
0609 }
0610 
0611 /**
0612  * iwpm_remote_info_cb - Process remote connecting peer address info, which
0613  *                       the port mapper has received from the connecting peer
0614  * @skb: The socket buffer
0615  * @cb: Contains the received message (payload and netlink header)
0616  *
0617  * Stores the IPv4/IPv6 address info in a hash table
0618  */
0619 int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
0620 {
0621     struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
0622     struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
0623     struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
0624     struct iwpm_remote_info *rem_info;
0625     const char *msg_type;
0626     u8 nl_client;
0627     int ret = -EINVAL;
0628 
0629     msg_type = "Remote Mapping info";
0630     if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
0631                 resp_query_policy, nltb, msg_type))
0632         return ret;
0633 
0634     nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
0635     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0636 
0637     local_sockaddr = (struct sockaddr_storage *)
0638             nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
0639     remote_sockaddr = (struct sockaddr_storage *)
0640             nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
0641     mapped_loc_sockaddr = (struct sockaddr_storage *)
0642             nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
0643     mapped_rem_sockaddr = (struct sockaddr_storage *)
0644             nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
0645 
0646     if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
0647         mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
0648         pr_info("%s: Sockaddr family doesn't match the requested one\n",
0649                 __func__);
0650         return ret;
0651     }
0652     rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
0653     if (!rem_info) {
0654         ret = -ENOMEM;
0655         return ret;
0656     }
0657     memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
0658            sizeof(struct sockaddr_storage));
0659     memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
0660            sizeof(struct sockaddr_storage));
0661     memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
0662            sizeof(struct sockaddr_storage));
0663     rem_info->nl_client = nl_client;
0664 
0665     iwpm_add_remote_info(rem_info);
0666 
0667     iwpm_print_sockaddr(local_sockaddr,
0668             "remote_info: Local sockaddr:");
0669     iwpm_print_sockaddr(mapped_loc_sockaddr,
0670             "remote_info: Mapped local sockaddr:");
0671     iwpm_print_sockaddr(remote_sockaddr,
0672             "remote_info: Remote sockaddr:");
0673     iwpm_print_sockaddr(mapped_rem_sockaddr,
0674             "remote_info: Mapped remote sockaddr:");
0675     return ret;
0676 }
0677 
0678 /* netlink attribute policy for the received request for mapping info */
0679 static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
0680     [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
0681                     .len = IWPM_ULIBNAME_SIZE - 1 },
0682     [IWPM_NLA_MAPINFO_ULIB_VER]  = { .type = NLA_U16 }
0683 };
0684 
0685 /**
0686  * iwpm_mapping_info_cb - Process a notification that the userspace
0687  *                        port mapper daemon is started
0688  * @skb: The socket buffer
0689  * @cb: Contains the received message (payload and netlink header)
0690  *
0691  * Using the received port mapper pid, send all the local mapping
0692  * info records to the userspace port mapper
0693  */
0694 int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
0695 {
0696     struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
0697     const char *msg_type = "Mapping Info response";
0698     u8 nl_client;
0699     char *iwpm_name;
0700     u16 iwpm_version;
0701     int ret = -EINVAL;
0702 
0703     if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
0704                 resp_mapinfo_policy, nltb, msg_type)) {
0705         pr_info("%s: Unable to parse nlmsg\n", __func__);
0706         return ret;
0707     }
0708     iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
0709     iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
0710     if (strcmp(iwpm_ulib_name, iwpm_name) ||
0711             iwpm_version < IWPM_UABI_VERSION_MIN) {
0712         pr_info("%s: Invalid port mapper name = %s version = %u\n",
0713                 __func__, iwpm_name, iwpm_version);
0714         return ret;
0715     }
0716     nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
0717     iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
0718     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0719     iwpm_user_pid = cb->nlh->nlmsg_pid;
0720 
0721     if (iwpm_ulib_version < IWPM_UABI_VERSION)
0722         pr_warn_once("%s: Down level iwpmd/pid %d.  Continuing...",
0723             __func__, iwpm_user_pid);
0724 
0725     if (!iwpm_mapinfo_available())
0726         return 0;
0727     pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
0728          __func__, iwpm_user_pid);
0729     ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
0730     return ret;
0731 }
0732 
0733 /* netlink attribute policy for the received mapping info ack */
0734 static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {
0735     [IWPM_NLA_MAPINFO_SEQ]    =   { .type = NLA_U32 },
0736     [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },
0737     [IWPM_NLA_MAPINFO_ACK_NUM] =  { .type = NLA_U32 }
0738 };
0739 
0740 /**
0741  * iwpm_ack_mapping_info_cb - Process the port mapper ack for
0742  *                            the provided local mapping info records
0743  * @skb: The socket buffer
0744  * @cb: Contains the received message (payload and netlink header)
0745  */
0746 int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
0747 {
0748     struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];
0749     u32 mapinfo_send, mapinfo_ack;
0750     const char *msg_type = "Mapping Info Ack";
0751 
0752     if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,
0753                 ack_mapinfo_policy, nltb, msg_type))
0754         return -EINVAL;
0755     mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);
0756     mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);
0757     if (mapinfo_ack != mapinfo_send)
0758         pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",
0759             __func__, mapinfo_send, mapinfo_ack);
0760     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0761     return 0;
0762 }
0763 
0764 /* netlink attribute policy for the received port mapper error message */
0765 static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {
0766     [IWPM_NLA_ERR_SEQ]        = { .type = NLA_U32 },
0767     [IWPM_NLA_ERR_CODE]       = { .type = NLA_U16 },
0768 };
0769 
0770 /**
0771  * iwpm_mapping_error_cb - Process port mapper notification for error
0772  *
0773  * @skb: The socket buffer
0774  * @cb: Contains the received message (payload and netlink header)
0775  */
0776 int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)
0777 {
0778     struct iwpm_nlmsg_request *nlmsg_request = NULL;
0779     int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
0780     struct nlattr *nltb[IWPM_NLA_ERR_MAX];
0781     u32 msg_seq;
0782     u16 err_code;
0783     const char *msg_type = "Mapping Error Msg";
0784 
0785     if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,
0786                 map_error_policy, nltb, msg_type))
0787         return -EINVAL;
0788 
0789     msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);
0790     err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);
0791     pr_info("%s: Received msg seq = %u err code = %u client = %d\n",
0792                 __func__, msg_seq, err_code, nl_client);
0793     /* look for nlmsg_request */
0794     nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
0795     if (!nlmsg_request) {
0796         /* not all errors have associated requests */
0797         pr_debug("Could not find matching req (seq = %u)\n", msg_seq);
0798         return 0;
0799     }
0800     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0801     nlmsg_request->err_code = err_code;
0802     nlmsg_request->request_done = 1;
0803     /* always for found request */
0804     kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
0805     barrier();
0806     up(&nlmsg_request->sem);
0807     return 0;
0808 }
0809 
0810 /* netlink attribute policy for the received hello request */
0811 static const struct nla_policy hello_policy[IWPM_NLA_HELLO_MAX] = {
0812     [IWPM_NLA_HELLO_ABI_VERSION]     = { .type = NLA_U16 }
0813 };
0814 
0815 /**
0816  * iwpm_hello_cb - Process a hello message from iwpmd
0817  *
0818  * @skb: The socket buffer
0819  * @cb: Contains the received message (payload and netlink header)
0820  *
0821  * Using the received port mapper pid, send the kernel's abi_version
0822  * after adjusting it to support the iwpmd version.
0823  */
0824 int iwpm_hello_cb(struct sk_buff *skb, struct netlink_callback *cb)
0825 {
0826     struct nlattr *nltb[IWPM_NLA_HELLO_MAX];
0827     const char *msg_type = "Hello request";
0828     u8 nl_client;
0829     u16 abi_version;
0830     int ret = -EINVAL;
0831 
0832     if (iwpm_parse_nlmsg(cb, IWPM_NLA_HELLO_MAX, hello_policy, nltb,
0833                  msg_type)) {
0834         pr_info("%s: Unable to parse nlmsg\n", __func__);
0835         return ret;
0836     }
0837     abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]);
0838     nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
0839     iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
0840     atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
0841     iwpm_ulib_version = min_t(u16, IWPM_UABI_VERSION, abi_version);
0842     pr_debug("Using ABI version %u\n", iwpm_ulib_version);
0843     iwpm_user_pid = cb->nlh->nlmsg_pid;
0844     ret = iwpm_send_hello(nl_client, iwpm_user_pid, iwpm_ulib_version);
0845     return ret;
0846 }