847 lines · c
1/*2 * Copyright (c) 2014 Intel Corporation. All rights reserved.3 * Copyright (c) 2014 Chelsio, Inc. All rights reserved.4 *5 * This software is available to you under a choice of one of two6 * licenses. You may choose to be licensed under the terms of the GNU7 * General Public License (GPL) Version 2, available from the file8 * COPYING in the main directory of this source tree, or the9 * OpenIB.org BSD license below:10 *11 * Redistribution and use in source and binary forms, with or12 * without modification, are permitted provided that the following13 * conditions are met:14 *15 * - Redistributions of source code must retain the above16 * copyright notice, this list of conditions and the following17 * disclaimer.18 *19 * - Redistributions in binary form must reproduce the above20 * copyright notice, this list of conditions and the following21 * disclaimer in the documentation and/or other materials22 * provided with the distribution.23 *24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE31 * SOFTWARE.32 */33 34#include "iwpm_util.h"35 36static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";37u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN;38static int iwpm_user_pid = IWPM_PID_UNDEFINED;39static atomic_t echo_nlmsg_seq;40 41/**42 * iwpm_valid_pid - Check if the userspace iwarp port mapper pid is valid43 *44 * Returns true if the pid is greater than zero, otherwise returns false45 */46int iwpm_valid_pid(void)47{48 return iwpm_user_pid > 0;49}50 51/**52 * iwpm_register_pid - Send a netlink query to userspace53 * to get the iwarp port mapper pid54 * @pm_msg: Contains driver info to send to the userspace port mapper55 * @nl_client: The index of the netlink client56 *57 * nlmsg attributes:58 * [IWPM_NLA_REG_PID_SEQ]59 * [IWPM_NLA_REG_IF_NAME]60 * [IWPM_NLA_REG_IBDEV_NAME]61 * [IWPM_NLA_REG_ULIB_NAME]62 */63int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)64{65 struct sk_buff *skb = NULL;66 struct iwpm_nlmsg_request *nlmsg_request = NULL;67 struct nlmsghdr *nlh;68 u32 msg_seq;69 const char *err_str = "";70 int ret = -EINVAL;71 72 if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||73 iwpm_user_pid == IWPM_PID_UNAVAILABLE)74 return 0;75 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);76 if (!skb) {77 err_str = "Unable to create a nlmsg";78 goto pid_query_error;79 }80 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();81 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);82 if (!nlmsg_request) {83 err_str = "Unable to allocate netlink request";84 goto pid_query_error;85 }86 msg_seq = atomic_read(&echo_nlmsg_seq);87 88 /* fill in the pid request message */89 err_str = "Unable to put attribute of the nlmsg";90 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);91 if (ret)92 goto pid_query_error;93 ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,94 pm_msg->if_name, IWPM_NLA_REG_IF_NAME);95 if (ret)96 goto pid_query_error;97 ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE,98 pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME);99 if (ret)100 goto pid_query_error;101 ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE,102 (char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME);103 if (ret)104 goto pid_query_error;105 106 nlmsg_end(skb, nlh);107 108 pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",109 __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);110 111 ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);112 if (ret) {113 skb = NULL; /* skb is freed in the netlink send-op handling */114 iwpm_user_pid = IWPM_PID_UNAVAILABLE;115 err_str = "Unable to send a nlmsg";116 goto pid_query_error;117 }118 nlmsg_request->req_buffer = pm_msg;119 ret = iwpm_wait_complete_req(nlmsg_request);120 return ret;121pid_query_error:122 pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);123 dev_kfree_skb(skb);124 if (nlmsg_request)125 iwpm_free_nlmsg_request(&nlmsg_request->kref);126 return ret;127}128 129/**130 * iwpm_add_mapping - Send a netlink add mapping request to131 * the userspace port mapper132 * @pm_msg: Contains the local ip/tcp address info to send133 * @nl_client: The index of the netlink client134 *135 * nlmsg attributes:136 * [IWPM_NLA_MANAGE_MAPPING_SEQ]137 * [IWPM_NLA_MANAGE_ADDR]138 * [IWPM_NLA_MANAGE_FLAGS]139 *140 * If the request is successful, the pm_msg stores141 * the port mapper response (mapped address info)142 */143int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)144{145 struct sk_buff *skb = NULL;146 struct iwpm_nlmsg_request *nlmsg_request = NULL;147 struct nlmsghdr *nlh;148 u32 msg_seq;149 const char *err_str = "";150 int ret = -EINVAL;151 152 if (!iwpm_valid_pid())153 return 0;154 if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {155 err_str = "Unregistered port mapper client";156 goto add_mapping_error;157 }158 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);159 if (!skb) {160 err_str = "Unable to create a nlmsg";161 goto add_mapping_error;162 }163 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();164 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);165 if (!nlmsg_request) {166 err_str = "Unable to allocate netlink request";167 goto add_mapping_error;168 }169 msg_seq = atomic_read(&echo_nlmsg_seq);170 /* fill in the add mapping message */171 err_str = "Unable to put attribute of the nlmsg";172 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,173 IWPM_NLA_MANAGE_MAPPING_SEQ);174 if (ret)175 goto add_mapping_error;176 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),177 &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);178 if (ret)179 goto add_mapping_error;180 181 /* If flags are required and we're not V4, then return a quiet error */182 if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {183 ret = -EINVAL;184 goto add_mapping_error_nowarn;185 }186 if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {187 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,188 IWPM_NLA_MANAGE_FLAGS);189 if (ret)190 goto add_mapping_error;191 }192 193 nlmsg_end(skb, nlh);194 nlmsg_request->req_buffer = pm_msg;195 196 ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);197 if (ret) {198 skb = NULL; /* skb is freed in the netlink send-op handling */199 iwpm_user_pid = IWPM_PID_UNDEFINED;200 err_str = "Unable to send a nlmsg";201 goto add_mapping_error;202 }203 ret = iwpm_wait_complete_req(nlmsg_request);204 return ret;205add_mapping_error:206 pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);207add_mapping_error_nowarn:208 dev_kfree_skb(skb);209 if (nlmsg_request)210 iwpm_free_nlmsg_request(&nlmsg_request->kref);211 return ret;212}213 214/**215 * iwpm_add_and_query_mapping - Process the port mapper response to216 * iwpm_add_and_query_mapping request217 * @pm_msg: Contains the local ip/tcp address info to send218 * @nl_client: The index of the netlink client219 *220 * nlmsg attributes:221 * [IWPM_NLA_QUERY_MAPPING_SEQ]222 * [IWPM_NLA_QUERY_LOCAL_ADDR]223 * [IWPM_NLA_QUERY_REMOTE_ADDR]224 * [IWPM_NLA_QUERY_FLAGS]225 */226int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)227{228 struct sk_buff *skb = NULL;229 struct iwpm_nlmsg_request *nlmsg_request = NULL;230 struct nlmsghdr *nlh;231 u32 msg_seq;232 const char *err_str = "";233 int ret = -EINVAL;234 235 if (!iwpm_valid_pid())236 return 0;237 if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {238 err_str = "Unregistered port mapper client";239 goto query_mapping_error;240 }241 ret = -ENOMEM;242 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);243 if (!skb) {244 err_str = "Unable to create a nlmsg";245 goto query_mapping_error;246 }247 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();248 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,249 nl_client, GFP_KERNEL);250 if (!nlmsg_request) {251 err_str = "Unable to allocate netlink request";252 goto query_mapping_error;253 }254 msg_seq = atomic_read(&echo_nlmsg_seq);255 256 /* fill in the query message */257 err_str = "Unable to put attribute of the nlmsg";258 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,259 IWPM_NLA_QUERY_MAPPING_SEQ);260 if (ret)261 goto query_mapping_error;262 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),263 &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);264 if (ret)265 goto query_mapping_error;266 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),267 &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);268 if (ret)269 goto query_mapping_error;270 271 /* If flags are required and we're not V4, then return a quite error */272 if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {273 ret = -EINVAL;274 goto query_mapping_error_nowarn;275 }276 if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {277 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,278 IWPM_NLA_QUERY_FLAGS);279 if (ret)280 goto query_mapping_error;281 }282 283 nlmsg_end(skb, nlh);284 nlmsg_request->req_buffer = pm_msg;285 286 ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);287 if (ret) {288 skb = NULL; /* skb is freed in the netlink send-op handling */289 err_str = "Unable to send a nlmsg";290 goto query_mapping_error;291 }292 ret = iwpm_wait_complete_req(nlmsg_request);293 return ret;294query_mapping_error:295 pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);296query_mapping_error_nowarn:297 dev_kfree_skb(skb);298 if (nlmsg_request)299 iwpm_free_nlmsg_request(&nlmsg_request->kref);300 return ret;301}302 303/**304 * iwpm_remove_mapping - Send a netlink remove mapping request305 * to the userspace port mapper306 *307 * @local_addr: Local ip/tcp address to remove308 * @nl_client: The index of the netlink client309 *310 * nlmsg attributes:311 * [IWPM_NLA_MANAGE_MAPPING_SEQ]312 * [IWPM_NLA_MANAGE_ADDR]313 */314int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)315{316 struct sk_buff *skb = NULL;317 struct nlmsghdr *nlh;318 u32 msg_seq;319 const char *err_str = "";320 int ret = -EINVAL;321 322 if (!iwpm_valid_pid())323 return 0;324 if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {325 err_str = "Unregistered port mapper client";326 goto remove_mapping_error;327 }328 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);329 if (!skb) {330 ret = -ENOMEM;331 err_str = "Unable to create a nlmsg";332 goto remove_mapping_error;333 }334 msg_seq = atomic_read(&echo_nlmsg_seq);335 nlh->nlmsg_seq = iwpm_get_nlmsg_seq();336 err_str = "Unable to put attribute of the nlmsg";337 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,338 IWPM_NLA_MANAGE_MAPPING_SEQ);339 if (ret)340 goto remove_mapping_error;341 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),342 local_addr, IWPM_NLA_MANAGE_ADDR);343 if (ret)344 goto remove_mapping_error;345 346 nlmsg_end(skb, nlh);347 348 ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);349 if (ret) {350 skb = NULL; /* skb is freed in the netlink send-op handling */351 iwpm_user_pid = IWPM_PID_UNDEFINED;352 err_str = "Unable to send a nlmsg";353 goto remove_mapping_error;354 }355 iwpm_print_sockaddr(local_addr,356 "remove_mapping: Local sockaddr:");357 return 0;358remove_mapping_error:359 pr_info("%s: %s (client = %u)\n", __func__, err_str, nl_client);360 if (skb)361 dev_kfree_skb_any(skb);362 return ret;363}364 365/* netlink attribute policy for the received response to register pid request */366static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {367 [IWPM_NLA_RREG_PID_SEQ] = { .type = NLA_U32 },368 [IWPM_NLA_RREG_IBDEV_NAME] = { .type = NLA_STRING,369 .len = IWPM_DEVNAME_SIZE - 1 },370 [IWPM_NLA_RREG_ULIB_NAME] = { .type = NLA_STRING,371 .len = IWPM_ULIBNAME_SIZE - 1 },372 [IWPM_NLA_RREG_ULIB_VER] = { .type = NLA_U16 },373 [IWPM_NLA_RREG_PID_ERR] = { .type = NLA_U16 }374};375 376/**377 * iwpm_register_pid_cb - Process the port mapper response to378 * iwpm_register_pid query379 * @skb: The socket buffer380 * @cb: Contains the received message (payload and netlink header)381 *382 * If successful, the function receives the userspace port mapper pid383 * which is used in future communication with the port mapper384 */385int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)386{387 struct iwpm_nlmsg_request *nlmsg_request = NULL;388 struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];389 struct iwpm_dev_data *pm_msg;390 char *dev_name, *iwpm_name;391 u32 msg_seq;392 u8 nl_client;393 u16 iwpm_version;394 const char *msg_type = "Register Pid response";395 396 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,397 resp_reg_policy, nltb, msg_type))398 return -EINVAL;399 400 msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);401 nlmsg_request = iwpm_find_nlmsg_request(msg_seq);402 if (!nlmsg_request) {403 pr_info("%s: Could not find a matching request (seq = %u)\n",404 __func__, msg_seq);405 return -EINVAL;406 }407 pm_msg = nlmsg_request->req_buffer;408 nl_client = nlmsg_request->nl_client;409 dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);410 iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);411 iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);412 413 /* check device name, ulib name and version */414 if (strcmp(pm_msg->dev_name, dev_name) ||415 strcmp(iwpm_ulib_name, iwpm_name) ||416 iwpm_version < IWPM_UABI_VERSION_MIN) {417 418 pr_info("%s: Incorrect info (dev = %s name = %s version = %u)\n",419 __func__, dev_name, iwpm_name, iwpm_version);420 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;421 goto register_pid_response_exit;422 }423 iwpm_user_pid = cb->nlh->nlmsg_pid;424 iwpm_ulib_version = iwpm_version;425 if (iwpm_ulib_version < IWPM_UABI_VERSION)426 pr_warn_once("%s: Down level iwpmd/pid %d. Continuing...",427 __func__, iwpm_user_pid);428 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);429 pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",430 __func__, iwpm_user_pid);431 iwpm_set_registration(nl_client, IWPM_REG_VALID);432register_pid_response_exit:433 nlmsg_request->request_done = 1;434 /* always for found nlmsg_request */435 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);436 barrier();437 up(&nlmsg_request->sem);438 return 0;439}440 441/* netlink attribute policy for the received response to add mapping request */442static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {443 [IWPM_NLA_RMANAGE_MAPPING_SEQ] = { .type = NLA_U32 },444 [IWPM_NLA_RMANAGE_ADDR] = {445 .len = sizeof(struct sockaddr_storage) },446 [IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR] = {447 .len = sizeof(struct sockaddr_storage) },448 [IWPM_NLA_RMANAGE_MAPPING_ERR] = { .type = NLA_U16 }449};450 451/**452 * iwpm_add_mapping_cb - Process the port mapper response to453 * iwpm_add_mapping request454 * @skb: The socket buffer455 * @cb: Contains the received message (payload and netlink header)456 */457int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)458{459 struct iwpm_sa_data *pm_msg;460 struct iwpm_nlmsg_request *nlmsg_request = NULL;461 struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];462 struct sockaddr_storage *local_sockaddr;463 struct sockaddr_storage *mapped_sockaddr;464 const char *msg_type;465 u32 msg_seq;466 467 msg_type = "Add Mapping response";468 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,469 resp_add_policy, nltb, msg_type))470 return -EINVAL;471 472 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);473 474 msg_seq = nla_get_u32(nltb[IWPM_NLA_RMANAGE_MAPPING_SEQ]);475 nlmsg_request = iwpm_find_nlmsg_request(msg_seq);476 if (!nlmsg_request) {477 pr_info("%s: Could not find a matching request (seq = %u)\n",478 __func__, msg_seq);479 return -EINVAL;480 }481 pm_msg = nlmsg_request->req_buffer;482 local_sockaddr = (struct sockaddr_storage *)483 nla_data(nltb[IWPM_NLA_RMANAGE_ADDR]);484 mapped_sockaddr = (struct sockaddr_storage *)485 nla_data(nltb[IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR]);486 487 if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {488 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;489 goto add_mapping_response_exit;490 }491 if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {492 pr_info("%s: Sockaddr family doesn't match the requested one\n",493 __func__);494 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;495 goto add_mapping_response_exit;496 }497 memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,498 sizeof(*mapped_sockaddr));499 iwpm_print_sockaddr(&pm_msg->loc_addr,500 "add_mapping: Local sockaddr:");501 iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,502 "add_mapping: Mapped local sockaddr:");503 504add_mapping_response_exit:505 nlmsg_request->request_done = 1;506 /* always for found request */507 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);508 barrier();509 up(&nlmsg_request->sem);510 return 0;511}512 513/* netlink attribute policy for the response to add and query mapping request514 * and response with remote address info515 */516static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {517 [IWPM_NLA_RQUERY_MAPPING_SEQ] = { .type = NLA_U32 },518 [IWPM_NLA_RQUERY_LOCAL_ADDR] = {519 .len = sizeof(struct sockaddr_storage) },520 [IWPM_NLA_RQUERY_REMOTE_ADDR] = {521 .len = sizeof(struct sockaddr_storage) },522 [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = {523 .len = sizeof(struct sockaddr_storage) },524 [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = {525 .len = sizeof(struct sockaddr_storage) },526 [IWPM_NLA_RQUERY_MAPPING_ERR] = { .type = NLA_U16 }527};528 529/**530 * iwpm_add_and_query_mapping_cb - Process the port mapper response to531 * iwpm_add_and_query_mapping request532 * @skb: The socket buffer533 * @cb: Contains the received message (payload and netlink header)534 */535int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,536 struct netlink_callback *cb)537{538 struct iwpm_sa_data *pm_msg;539 struct iwpm_nlmsg_request *nlmsg_request = NULL;540 struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];541 struct sockaddr_storage *local_sockaddr, *remote_sockaddr;542 struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;543 const char *msg_type;544 u32 msg_seq;545 u16 err_code;546 547 msg_type = "Query Mapping response";548 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,549 resp_query_policy, nltb, msg_type))550 return -EINVAL;551 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);552 553 msg_seq = nla_get_u32(nltb[IWPM_NLA_RQUERY_MAPPING_SEQ]);554 nlmsg_request = iwpm_find_nlmsg_request(msg_seq);555 if (!nlmsg_request) {556 pr_info("%s: Could not find a matching request (seq = %u)\n",557 __func__, msg_seq);558 return -EINVAL;559 }560 pm_msg = nlmsg_request->req_buffer;561 local_sockaddr = (struct sockaddr_storage *)562 nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);563 remote_sockaddr = (struct sockaddr_storage *)564 nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);565 mapped_loc_sockaddr = (struct sockaddr_storage *)566 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);567 mapped_rem_sockaddr = (struct sockaddr_storage *)568 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);569 570 err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);571 if (err_code == IWPM_REMOTE_QUERY_REJECT) {572 pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",573 __func__, cb->nlh->nlmsg_pid, msg_seq);574 nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;575 }576 if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||577 iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {578 pr_info("%s: Incorrect local sockaddr\n", __func__);579 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;580 goto query_mapping_response_exit;581 }582 if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||583 mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {584 pr_info("%s: Sockaddr family doesn't match the requested one\n",585 __func__);586 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;587 goto query_mapping_response_exit;588 }589 memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,590 sizeof(*mapped_loc_sockaddr));591 memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,592 sizeof(*mapped_rem_sockaddr));593 594 iwpm_print_sockaddr(&pm_msg->loc_addr,595 "query_mapping: Local sockaddr:");596 iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,597 "query_mapping: Mapped local sockaddr:");598 iwpm_print_sockaddr(&pm_msg->rem_addr,599 "query_mapping: Remote sockaddr:");600 iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,601 "query_mapping: Mapped remote sockaddr:");602query_mapping_response_exit:603 nlmsg_request->request_done = 1;604 /* always for found request */605 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);606 barrier();607 up(&nlmsg_request->sem);608 return 0;609}610 611/**612 * iwpm_remote_info_cb - Process remote connecting peer address info, which613 * the port mapper has received from the connecting peer614 * @skb: The socket buffer615 * @cb: Contains the received message (payload and netlink header)616 *617 * Stores the IPv4/IPv6 address info in a hash table618 */619int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)620{621 struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];622 struct sockaddr_storage *local_sockaddr, *remote_sockaddr;623 struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;624 struct iwpm_remote_info *rem_info;625 const char *msg_type;626 u8 nl_client;627 int ret = -EINVAL;628 629 msg_type = "Remote Mapping info";630 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,631 resp_query_policy, nltb, msg_type))632 return ret;633 634 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);635 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);636 637 local_sockaddr = (struct sockaddr_storage *)638 nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);639 remote_sockaddr = (struct sockaddr_storage *)640 nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);641 mapped_loc_sockaddr = (struct sockaddr_storage *)642 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);643 mapped_rem_sockaddr = (struct sockaddr_storage *)644 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);645 646 if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||647 mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {648 pr_info("%s: Sockaddr family doesn't match the requested one\n",649 __func__);650 return ret;651 }652 rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);653 if (!rem_info) {654 ret = -ENOMEM;655 return ret;656 }657 memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,658 sizeof(struct sockaddr_storage));659 memcpy(&rem_info->remote_sockaddr, remote_sockaddr,660 sizeof(struct sockaddr_storage));661 memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,662 sizeof(struct sockaddr_storage));663 rem_info->nl_client = nl_client;664 665 iwpm_add_remote_info(rem_info);666 667 iwpm_print_sockaddr(local_sockaddr,668 "remote_info: Local sockaddr:");669 iwpm_print_sockaddr(mapped_loc_sockaddr,670 "remote_info: Mapped local sockaddr:");671 iwpm_print_sockaddr(remote_sockaddr,672 "remote_info: Remote sockaddr:");673 iwpm_print_sockaddr(mapped_rem_sockaddr,674 "remote_info: Mapped remote sockaddr:");675 return ret;676}677 678/* netlink attribute policy for the received request for mapping info */679static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {680 [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,681 .len = IWPM_ULIBNAME_SIZE - 1 },682 [IWPM_NLA_MAPINFO_ULIB_VER] = { .type = NLA_U16 }683};684 685/**686 * iwpm_mapping_info_cb - Process a notification that the userspace687 * port mapper daemon is started688 * @skb: The socket buffer689 * @cb: Contains the received message (payload and netlink header)690 *691 * Using the received port mapper pid, send all the local mapping692 * info records to the userspace port mapper693 */694int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)695{696 struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];697 const char *msg_type = "Mapping Info response";698 u8 nl_client;699 char *iwpm_name;700 u16 iwpm_version;701 int ret = -EINVAL;702 703 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,704 resp_mapinfo_policy, nltb, msg_type)) {705 pr_info("%s: Unable to parse nlmsg\n", __func__);706 return ret;707 }708 iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);709 iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);710 if (strcmp(iwpm_ulib_name, iwpm_name) ||711 iwpm_version < IWPM_UABI_VERSION_MIN) {712 pr_info("%s: Invalid port mapper name = %s version = %u\n",713 __func__, iwpm_name, iwpm_version);714 return ret;715 }716 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);717 iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);718 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);719 iwpm_user_pid = cb->nlh->nlmsg_pid;720 721 if (iwpm_ulib_version < IWPM_UABI_VERSION)722 pr_warn_once("%s: Down level iwpmd/pid %d. Continuing...",723 __func__, iwpm_user_pid);724 725 if (!iwpm_mapinfo_available())726 return 0;727 pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",728 __func__, iwpm_user_pid);729 ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);730 return ret;731}732 733/* netlink attribute policy for the received mapping info ack */734static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {735 [IWPM_NLA_MAPINFO_SEQ] = { .type = NLA_U32 },736 [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },737 [IWPM_NLA_MAPINFO_ACK_NUM] = { .type = NLA_U32 }738};739 740/**741 * iwpm_ack_mapping_info_cb - Process the port mapper ack for742 * the provided local mapping info records743 * @skb: The socket buffer744 * @cb: Contains the received message (payload and netlink header)745 */746int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)747{748 struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];749 u32 mapinfo_send, mapinfo_ack;750 const char *msg_type = "Mapping Info Ack";751 752 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,753 ack_mapinfo_policy, nltb, msg_type))754 return -EINVAL;755 mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);756 mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);757 if (mapinfo_ack != mapinfo_send)758 pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",759 __func__, mapinfo_send, mapinfo_ack);760 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);761 return 0;762}763 764/* netlink attribute policy for the received port mapper error message */765static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {766 [IWPM_NLA_ERR_SEQ] = { .type = NLA_U32 },767 [IWPM_NLA_ERR_CODE] = { .type = NLA_U16 },768};769 770/**771 * iwpm_mapping_error_cb - Process port mapper notification for error772 *773 * @skb: The socket buffer774 * @cb: Contains the received message (payload and netlink header)775 */776int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)777{778 struct iwpm_nlmsg_request *nlmsg_request = NULL;779 int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);780 struct nlattr *nltb[IWPM_NLA_ERR_MAX];781 u32 msg_seq;782 u16 err_code;783 const char *msg_type = "Mapping Error Msg";784 785 if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,786 map_error_policy, nltb, msg_type))787 return -EINVAL;788 789 msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);790 err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);791 pr_info("%s: Received msg seq = %u err code = %u client = %d\n",792 __func__, msg_seq, err_code, nl_client);793 /* look for nlmsg_request */794 nlmsg_request = iwpm_find_nlmsg_request(msg_seq);795 if (!nlmsg_request) {796 /* not all errors have associated requests */797 pr_debug("Could not find matching req (seq = %u)\n", msg_seq);798 return 0;799 }800 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);801 nlmsg_request->err_code = err_code;802 nlmsg_request->request_done = 1;803 /* always for found request */804 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);805 barrier();806 up(&nlmsg_request->sem);807 return 0;808}809 810/* netlink attribute policy for the received hello request */811static const struct nla_policy hello_policy[IWPM_NLA_HELLO_MAX] = {812 [IWPM_NLA_HELLO_ABI_VERSION] = { .type = NLA_U16 }813};814 815/**816 * iwpm_hello_cb - Process a hello message from iwpmd817 *818 * @skb: The socket buffer819 * @cb: Contains the received message (payload and netlink header)820 *821 * Using the received port mapper pid, send the kernel's abi_version822 * after adjusting it to support the iwpmd version.823 */824int iwpm_hello_cb(struct sk_buff *skb, struct netlink_callback *cb)825{826 struct nlattr *nltb[IWPM_NLA_HELLO_MAX];827 const char *msg_type = "Hello request";828 u8 nl_client;829 u16 abi_version;830 int ret = -EINVAL;831 832 if (iwpm_parse_nlmsg(cb, IWPM_NLA_HELLO_MAX, hello_policy, nltb,833 msg_type)) {834 pr_info("%s: Unable to parse nlmsg\n", __func__);835 return ret;836 }837 abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]);838 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);839 iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);840 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);841 iwpm_ulib_version = min_t(u16, IWPM_UABI_VERSION, abi_version);842 pr_debug("Using ABI version %u\n", iwpm_ulib_version);843 iwpm_user_pid = cb->nlh->nlmsg_pid;844 ret = iwpm_send_hello(nl_client, iwpm_user_pid, iwpm_ulib_version);845 return ret;846}847