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 two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * 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 OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34#include "iwpm_util.h" 35 36static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser"; 37static int iwpm_ulib_version = 3; 38static int iwpm_user_pid = IWPM_PID_UNDEFINED; 39static atomic_t echo_nlmsg_seq; 40 41int iwpm_valid_pid(void) 42{ 43 return iwpm_user_pid > 0; 44} 45EXPORT_SYMBOL(iwpm_valid_pid); 46 47/* 48 * iwpm_register_pid - Send a netlink query to user space 49 * for the iwarp port mapper pid 50 * 51 * nlmsg attributes: 52 * [IWPM_NLA_REG_PID_SEQ] 53 * [IWPM_NLA_REG_IF_NAME] 54 * [IWPM_NLA_REG_IBDEV_NAME] 55 * [IWPM_NLA_REG_ULIB_NAME] 56 */ 57int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) 58{ 59 struct sk_buff *skb = NULL; 60 struct iwpm_nlmsg_request *nlmsg_request = NULL; 61 struct nlmsghdr *nlh; 62 u32 msg_seq; 63 const char *err_str = ""; 64 int ret = -EINVAL; 65 66 if (!iwpm_valid_client(nl_client)) { 67 err_str = "Invalid port mapper client"; 68 goto pid_query_error; 69 } 70 if (iwpm_check_registration(nl_client, IWPM_REG_VALID) || 71 iwpm_user_pid == IWPM_PID_UNAVAILABLE) 72 return 0; 73 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client); 74 if (!skb) { 75 err_str = "Unable to create a nlmsg"; 76 goto pid_query_error; 77 } 78 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 79 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL); 80 if (!nlmsg_request) { 81 err_str = "Unable to allocate netlink request"; 82 goto pid_query_error; 83 } 84 msg_seq = atomic_read(&echo_nlmsg_seq); 85 86 /* fill in the pid request message */ 87 err_str = "Unable to put attribute of the nlmsg"; 88 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ); 89 if (ret) 90 goto pid_query_error; 91 ret = ibnl_put_attr(skb, nlh, IWPM_IFNAME_SIZE, 92 pm_msg->if_name, IWPM_NLA_REG_IF_NAME); 93 if (ret) 94 goto pid_query_error; 95 ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE, 96 pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME); 97 if (ret) 98 goto pid_query_error; 99 ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE, 100 (char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME); 101 if (ret) 102 goto pid_query_error; 103 104 pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n", 105 __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name); 106 107 ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_IWPM, GFP_KERNEL); 108 if (ret) { 109 skb = NULL; /* skb is freed in the netlink send-op handling */ 110 iwpm_user_pid = IWPM_PID_UNAVAILABLE; 111 err_str = "Unable to send a nlmsg"; 112 goto pid_query_error; 113 } 114 nlmsg_request->req_buffer = pm_msg; 115 ret = iwpm_wait_complete_req(nlmsg_request); 116 return ret; 117pid_query_error: 118 pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client); 119 if (skb) 120 dev_kfree_skb(skb); 121 if (nlmsg_request) 122 iwpm_free_nlmsg_request(&nlmsg_request->kref); 123 return ret; 124} 125EXPORT_SYMBOL(iwpm_register_pid); 126 127/* 128 * iwpm_add_mapping - Send a netlink add mapping message 129 * to the port mapper 130 * nlmsg attributes: 131 * [IWPM_NLA_MANAGE_MAPPING_SEQ] 132 * [IWPM_NLA_MANAGE_ADDR] 133 */ 134int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) 135{ 136 struct sk_buff *skb = NULL; 137 struct iwpm_nlmsg_request *nlmsg_request = NULL; 138 struct nlmsghdr *nlh; 139 u32 msg_seq; 140 const char *err_str = ""; 141 int ret = -EINVAL; 142 143 if (!iwpm_valid_client(nl_client)) { 144 err_str = "Invalid port mapper client"; 145 goto add_mapping_error; 146 } 147 if (!iwpm_valid_pid()) 148 return 0; 149 if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { 150 err_str = "Unregistered port mapper client"; 151 goto add_mapping_error; 152 } 153 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client); 154 if (!skb) { 155 err_str = "Unable to create a nlmsg"; 156 goto add_mapping_error; 157 } 158 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 159 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL); 160 if (!nlmsg_request) { 161 err_str = "Unable to allocate netlink request"; 162 goto add_mapping_error; 163 } 164 msg_seq = atomic_read(&echo_nlmsg_seq); 165 /* fill in the add mapping message */ 166 err_str = "Unable to put attribute of the nlmsg"; 167 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, 168 IWPM_NLA_MANAGE_MAPPING_SEQ); 169 if (ret) 170 goto add_mapping_error; 171 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage), 172 &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR); 173 if (ret) 174 goto add_mapping_error; 175 nlmsg_request->req_buffer = pm_msg; 176 177 ret = ibnl_unicast(skb, nlh, iwpm_user_pid); 178 if (ret) { 179 skb = NULL; /* skb is freed in the netlink send-op handling */ 180 iwpm_user_pid = IWPM_PID_UNDEFINED; 181 err_str = "Unable to send a nlmsg"; 182 goto add_mapping_error; 183 } 184 ret = iwpm_wait_complete_req(nlmsg_request); 185 return ret; 186add_mapping_error: 187 pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client); 188 if (skb) 189 dev_kfree_skb(skb); 190 if (nlmsg_request) 191 iwpm_free_nlmsg_request(&nlmsg_request->kref); 192 return ret; 193} 194EXPORT_SYMBOL(iwpm_add_mapping); 195 196/* 197 * iwpm_add_and_query_mapping - Send a netlink add and query 198 * mapping message to the port mapper 199 * nlmsg attributes: 200 * [IWPM_NLA_QUERY_MAPPING_SEQ] 201 * [IWPM_NLA_QUERY_LOCAL_ADDR] 202 * [IWPM_NLA_QUERY_REMOTE_ADDR] 203 */ 204int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) 205{ 206 struct sk_buff *skb = NULL; 207 struct iwpm_nlmsg_request *nlmsg_request = NULL; 208 struct nlmsghdr *nlh; 209 u32 msg_seq; 210 const char *err_str = ""; 211 int ret = -EINVAL; 212 213 if (!iwpm_valid_client(nl_client)) { 214 err_str = "Invalid port mapper client"; 215 goto query_mapping_error; 216 } 217 if (!iwpm_valid_pid()) 218 return 0; 219 if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) { 220 err_str = "Unregistered port mapper client"; 221 goto query_mapping_error; 222 } 223 ret = -ENOMEM; 224 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client); 225 if (!skb) { 226 err_str = "Unable to create a nlmsg"; 227 goto query_mapping_error; 228 } 229 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 230 nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, 231 nl_client, GFP_KERNEL); 232 if (!nlmsg_request) { 233 err_str = "Unable to allocate netlink request"; 234 goto query_mapping_error; 235 } 236 msg_seq = atomic_read(&echo_nlmsg_seq); 237 238 /* fill in the query message */ 239 err_str = "Unable to put attribute of the nlmsg"; 240 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, 241 IWPM_NLA_QUERY_MAPPING_SEQ); 242 if (ret) 243 goto query_mapping_error; 244 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage), 245 &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR); 246 if (ret) 247 goto query_mapping_error; 248 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage), 249 &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR); 250 if (ret) 251 goto query_mapping_error; 252 nlmsg_request->req_buffer = pm_msg; 253 254 ret = ibnl_unicast(skb, nlh, iwpm_user_pid); 255 if (ret) { 256 skb = NULL; /* skb is freed in the netlink send-op handling */ 257 err_str = "Unable to send a nlmsg"; 258 goto query_mapping_error; 259 } 260 ret = iwpm_wait_complete_req(nlmsg_request); 261 return ret; 262query_mapping_error: 263 pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client); 264 if (skb) 265 dev_kfree_skb(skb); 266 if (nlmsg_request) 267 iwpm_free_nlmsg_request(&nlmsg_request->kref); 268 return ret; 269} 270EXPORT_SYMBOL(iwpm_add_and_query_mapping); 271 272/* 273 * iwpm_remove_mapping - Send a netlink remove mapping message 274 * to the port mapper 275 * nlmsg attributes: 276 * [IWPM_NLA_MANAGE_MAPPING_SEQ] 277 * [IWPM_NLA_MANAGE_ADDR] 278 */ 279int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client) 280{ 281 struct sk_buff *skb = NULL; 282 struct nlmsghdr *nlh; 283 u32 msg_seq; 284 const char *err_str = ""; 285 int ret = -EINVAL; 286 287 if (!iwpm_valid_client(nl_client)) { 288 err_str = "Invalid port mapper client"; 289 goto remove_mapping_error; 290 } 291 if (!iwpm_valid_pid()) 292 return 0; 293 if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) { 294 err_str = "Unregistered port mapper client"; 295 goto remove_mapping_error; 296 } 297 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client); 298 if (!skb) { 299 ret = -ENOMEM; 300 err_str = "Unable to create a nlmsg"; 301 goto remove_mapping_error; 302 } 303 msg_seq = atomic_read(&echo_nlmsg_seq); 304 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 305 err_str = "Unable to put attribute of the nlmsg"; 306 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, 307 IWPM_NLA_MANAGE_MAPPING_SEQ); 308 if (ret) 309 goto remove_mapping_error; 310 ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage), 311 local_addr, IWPM_NLA_MANAGE_ADDR); 312 if (ret) 313 goto remove_mapping_error; 314 315 ret = ibnl_unicast(skb, nlh, iwpm_user_pid); 316 if (ret) { 317 skb = NULL; /* skb is freed in the netlink send-op handling */ 318 iwpm_user_pid = IWPM_PID_UNDEFINED; 319 err_str = "Unable to send a nlmsg"; 320 goto remove_mapping_error; 321 } 322 iwpm_print_sockaddr(local_addr, 323 "remove_mapping: Local sockaddr:"); 324 return 0; 325remove_mapping_error: 326 pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client); 327 if (skb) 328 dev_kfree_skb_any(skb); 329 return ret; 330} 331EXPORT_SYMBOL(iwpm_remove_mapping); 332 333/* netlink attribute policy for the received response to register pid request */ 334static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = { 335 [IWPM_NLA_RREG_PID_SEQ] = { .type = NLA_U32 }, 336 [IWPM_NLA_RREG_IBDEV_NAME] = { .type = NLA_STRING, 337 .len = IWPM_DEVNAME_SIZE - 1 }, 338 [IWPM_NLA_RREG_ULIB_NAME] = { .type = NLA_STRING, 339 .len = IWPM_ULIBNAME_SIZE - 1 }, 340 [IWPM_NLA_RREG_ULIB_VER] = { .type = NLA_U16 }, 341 [IWPM_NLA_RREG_PID_ERR] = { .type = NLA_U16 } 342}; 343 344/* 345 * iwpm_register_pid_cb - Process a port mapper response to 346 * iwpm_register_pid() 347 */ 348int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb) 349{ 350 struct iwpm_nlmsg_request *nlmsg_request = NULL; 351 struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX]; 352 struct iwpm_dev_data *pm_msg; 353 char *dev_name, *iwpm_name; 354 u32 msg_seq; 355 u8 nl_client; 356 u16 iwpm_version; 357 const char *msg_type = "Register Pid response"; 358 359 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX, 360 resp_reg_policy, nltb, msg_type)) 361 return -EINVAL; 362 363 msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]); 364 nlmsg_request = iwpm_find_nlmsg_request(msg_seq); 365 if (!nlmsg_request) { 366 pr_info("%s: Could not find a matching request (seq = %u)\n", 367 __func__, msg_seq); 368 return -EINVAL; 369 } 370 pm_msg = nlmsg_request->req_buffer; 371 nl_client = nlmsg_request->nl_client; 372 dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]); 373 iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]); 374 iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]); 375 376 /* check device name, ulib name and version */ 377 if (strcmp(pm_msg->dev_name, dev_name) || 378 strcmp(iwpm_ulib_name, iwpm_name) || 379 iwpm_version != iwpm_ulib_version) { 380 381 pr_info("%s: Incorrect info (dev = %s name = %s version = %d)\n", 382 __func__, dev_name, iwpm_name, iwpm_version); 383 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR; 384 goto register_pid_response_exit; 385 } 386 iwpm_user_pid = cb->nlh->nlmsg_pid; 387 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 388 pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", 389 __func__, iwpm_user_pid); 390 if (iwpm_valid_client(nl_client)) 391 iwpm_set_registration(nl_client, IWPM_REG_VALID); 392register_pid_response_exit: 393 nlmsg_request->request_done = 1; 394 /* always for found nlmsg_request */ 395 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 396 barrier(); 397 wake_up(&nlmsg_request->waitq); 398 return 0; 399} 400EXPORT_SYMBOL(iwpm_register_pid_cb); 401 402/* netlink attribute policy for the received response to add mapping request */ 403static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = { 404 [IWPM_NLA_MANAGE_MAPPING_SEQ] = { .type = NLA_U32 }, 405 [IWPM_NLA_MANAGE_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 406 [IWPM_NLA_MANAGE_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 407 [IWPM_NLA_RMANAGE_MAPPING_ERR] = { .type = NLA_U16 } 408}; 409 410/* 411 * iwpm_add_mapping_cb - Process a port mapper response to 412 * iwpm_add_mapping() 413 */ 414int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb) 415{ 416 struct iwpm_sa_data *pm_msg; 417 struct iwpm_nlmsg_request *nlmsg_request = NULL; 418 struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX]; 419 struct sockaddr_storage *local_sockaddr; 420 struct sockaddr_storage *mapped_sockaddr; 421 const char *msg_type; 422 u32 msg_seq; 423 424 msg_type = "Add Mapping response"; 425 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX, 426 resp_add_policy, nltb, msg_type)) 427 return -EINVAL; 428 429 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 430 431 msg_seq = nla_get_u32(nltb[IWPM_NLA_MANAGE_MAPPING_SEQ]); 432 nlmsg_request = iwpm_find_nlmsg_request(msg_seq); 433 if (!nlmsg_request) { 434 pr_info("%s: Could not find a matching request (seq = %u)\n", 435 __func__, msg_seq); 436 return -EINVAL; 437 } 438 pm_msg = nlmsg_request->req_buffer; 439 local_sockaddr = (struct sockaddr_storage *) 440 nla_data(nltb[IWPM_NLA_MANAGE_ADDR]); 441 mapped_sockaddr = (struct sockaddr_storage *) 442 nla_data(nltb[IWPM_NLA_MANAGE_MAPPED_LOC_ADDR]); 443 444 if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) { 445 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR; 446 goto add_mapping_response_exit; 447 } 448 if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) { 449 pr_info("%s: Sockaddr family doesn't match the requested one\n", 450 __func__); 451 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR; 452 goto add_mapping_response_exit; 453 } 454 memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr, 455 sizeof(*mapped_sockaddr)); 456 iwpm_print_sockaddr(&pm_msg->loc_addr, 457 "add_mapping: Local sockaddr:"); 458 iwpm_print_sockaddr(&pm_msg->mapped_loc_addr, 459 "add_mapping: Mapped local sockaddr:"); 460 461add_mapping_response_exit: 462 nlmsg_request->request_done = 1; 463 /* always for found request */ 464 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 465 barrier(); 466 wake_up(&nlmsg_request->waitq); 467 return 0; 468} 469EXPORT_SYMBOL(iwpm_add_mapping_cb); 470 471/* netlink attribute policy for the response to add and query mapping request 472 * and response with remote address info */ 473static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = { 474 [IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 }, 475 [IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 476 [IWPM_NLA_QUERY_REMOTE_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 477 [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 478 [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = { .len = sizeof(struct sockaddr_storage) }, 479 [IWPM_NLA_RQUERY_MAPPING_ERR] = { .type = NLA_U16 } 480}; 481 482/* 483 * iwpm_add_and_query_mapping_cb - Process a port mapper response to 484 * iwpm_add_and_query_mapping() 485 */ 486int iwpm_add_and_query_mapping_cb(struct sk_buff *skb, 487 struct netlink_callback *cb) 488{ 489 struct iwpm_sa_data *pm_msg; 490 struct iwpm_nlmsg_request *nlmsg_request = NULL; 491 struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX]; 492 struct sockaddr_storage *local_sockaddr, *remote_sockaddr; 493 struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr; 494 const char *msg_type; 495 u32 msg_seq; 496 u16 err_code; 497 498 msg_type = "Query Mapping response"; 499 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX, 500 resp_query_policy, nltb, msg_type)) 501 return -EINVAL; 502 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 503 504 msg_seq = nla_get_u32(nltb[IWPM_NLA_QUERY_MAPPING_SEQ]); 505 nlmsg_request = iwpm_find_nlmsg_request(msg_seq); 506 if (!nlmsg_request) { 507 pr_info("%s: Could not find a matching request (seq = %u)\n", 508 __func__, msg_seq); 509 return -EINVAL; 510 } 511 pm_msg = nlmsg_request->req_buffer; 512 local_sockaddr = (struct sockaddr_storage *) 513 nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]); 514 remote_sockaddr = (struct sockaddr_storage *) 515 nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]); 516 mapped_loc_sockaddr = (struct sockaddr_storage *) 517 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]); 518 mapped_rem_sockaddr = (struct sockaddr_storage *) 519 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]); 520 521 err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]); 522 if (err_code == IWPM_REMOTE_QUERY_REJECT) { 523 pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n", 524 __func__, cb->nlh->nlmsg_pid, msg_seq); 525 nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT; 526 } 527 if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) || 528 iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) { 529 pr_info("%s: Incorrect local sockaddr\n", __func__); 530 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR; 531 goto query_mapping_response_exit; 532 } 533 if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family || 534 mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) { 535 pr_info("%s: Sockaddr family doesn't match the requested one\n", 536 __func__); 537 nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR; 538 goto query_mapping_response_exit; 539 } 540 memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr, 541 sizeof(*mapped_loc_sockaddr)); 542 memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr, 543 sizeof(*mapped_rem_sockaddr)); 544 545 iwpm_print_sockaddr(&pm_msg->loc_addr, 546 "query_mapping: Local sockaddr:"); 547 iwpm_print_sockaddr(&pm_msg->mapped_loc_addr, 548 "query_mapping: Mapped local sockaddr:"); 549 iwpm_print_sockaddr(&pm_msg->rem_addr, 550 "query_mapping: Remote sockaddr:"); 551 iwpm_print_sockaddr(&pm_msg->mapped_rem_addr, 552 "query_mapping: Mapped remote sockaddr:"); 553query_mapping_response_exit: 554 nlmsg_request->request_done = 1; 555 /* always for found request */ 556 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 557 barrier(); 558 wake_up(&nlmsg_request->waitq); 559 return 0; 560} 561EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb); 562 563/* 564 * iwpm_remote_info_cb - Process a port mapper message, containing 565 * the remote connecting peer address info 566 */ 567int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb) 568{ 569 struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX]; 570 struct sockaddr_storage *local_sockaddr, *remote_sockaddr; 571 struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr; 572 struct iwpm_remote_info *rem_info; 573 const char *msg_type; 574 u8 nl_client; 575 int ret = -EINVAL; 576 577 msg_type = "Remote Mapping info"; 578 if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX, 579 resp_query_policy, nltb, msg_type)) 580 return ret; 581 582 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type); 583 if (!iwpm_valid_client(nl_client)) { 584 pr_info("%s: Invalid port mapper client = %d\n", 585 __func__, nl_client); 586 return ret; 587 } 588 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 589 590 local_sockaddr = (struct sockaddr_storage *) 591 nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]); 592 remote_sockaddr = (struct sockaddr_storage *) 593 nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]); 594 mapped_loc_sockaddr = (struct sockaddr_storage *) 595 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]); 596 mapped_rem_sockaddr = (struct sockaddr_storage *) 597 nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]); 598 599 if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family || 600 mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) { 601 pr_info("%s: Sockaddr family doesn't match the requested one\n", 602 __func__); 603 return ret; 604 } 605 rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC); 606 if (!rem_info) { 607 pr_err("%s: Unable to allocate a remote info\n", __func__); 608 ret = -ENOMEM; 609 return ret; 610 } 611 memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr, 612 sizeof(struct sockaddr_storage)); 613 memcpy(&rem_info->remote_sockaddr, remote_sockaddr, 614 sizeof(struct sockaddr_storage)); 615 memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr, 616 sizeof(struct sockaddr_storage)); 617 rem_info->nl_client = nl_client; 618 619 iwpm_add_remote_info(rem_info); 620 621 iwpm_print_sockaddr(local_sockaddr, 622 "remote_info: Local sockaddr:"); 623 iwpm_print_sockaddr(mapped_loc_sockaddr, 624 "remote_info: Mapped local sockaddr:"); 625 iwpm_print_sockaddr(remote_sockaddr, 626 "remote_info: Remote sockaddr:"); 627 iwpm_print_sockaddr(mapped_rem_sockaddr, 628 "remote_info: Mapped remote sockaddr:"); 629 return ret; 630} 631EXPORT_SYMBOL(iwpm_remote_info_cb); 632 633/* netlink attribute policy for the received request for mapping info */ 634static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = { 635 [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING, 636 .len = IWPM_ULIBNAME_SIZE - 1 }, 637 [IWPM_NLA_MAPINFO_ULIB_VER] = { .type = NLA_U16 } 638}; 639 640/* 641 * iwpm_mapping_info_cb - Process a port mapper request for mapping info 642 */ 643int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) 644{ 645 struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX]; 646 const char *msg_type = "Mapping Info response"; 647 u8 nl_client; 648 char *iwpm_name; 649 u16 iwpm_version; 650 int ret = -EINVAL; 651 652 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX, 653 resp_mapinfo_policy, nltb, msg_type)) { 654 pr_info("%s: Unable to parse nlmsg\n", __func__); 655 return ret; 656 } 657 iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]); 658 iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]); 659 if (strcmp(iwpm_ulib_name, iwpm_name) || 660 iwpm_version != iwpm_ulib_version) { 661 pr_info("%s: Invalid port mapper name = %s version = %d\n", 662 __func__, iwpm_name, iwpm_version); 663 return ret; 664 } 665 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type); 666 if (!iwpm_valid_client(nl_client)) { 667 pr_info("%s: Invalid port mapper client = %d\n", 668 __func__, nl_client); 669 return ret; 670 } 671 iwpm_set_registration(nl_client, IWPM_REG_INCOMPL); 672 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 673 iwpm_user_pid = cb->nlh->nlmsg_pid; 674 if (!iwpm_mapinfo_available()) 675 return 0; 676 pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", 677 __func__, iwpm_user_pid); 678 ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid); 679 return ret; 680} 681EXPORT_SYMBOL(iwpm_mapping_info_cb); 682 683/* netlink attribute policy for the received mapping info ack */ 684static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = { 685 [IWPM_NLA_MAPINFO_SEQ] = { .type = NLA_U32 }, 686 [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 }, 687 [IWPM_NLA_MAPINFO_ACK_NUM] = { .type = NLA_U32 } 688}; 689 690/* 691 * iwpm_ack_mapping_info_cb - Process a port mapper ack for 692 * the provided mapping info records 693 */ 694int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) 695{ 696 struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX]; 697 u32 mapinfo_send, mapinfo_ack; 698 const char *msg_type = "Mapping Info Ack"; 699 700 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX, 701 ack_mapinfo_policy, nltb, msg_type)) 702 return -EINVAL; 703 mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]); 704 mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]); 705 if (mapinfo_ack != mapinfo_send) 706 pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n", 707 __func__, mapinfo_send, mapinfo_ack); 708 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 709 return 0; 710} 711EXPORT_SYMBOL(iwpm_ack_mapping_info_cb); 712 713/* netlink attribute policy for the received port mapper error message */ 714static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = { 715 [IWPM_NLA_ERR_SEQ] = { .type = NLA_U32 }, 716 [IWPM_NLA_ERR_CODE] = { .type = NLA_U16 }, 717}; 718 719/* 720 * iwpm_mapping_error_cb - Process a port mapper error message 721 */ 722int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb) 723{ 724 struct iwpm_nlmsg_request *nlmsg_request = NULL; 725 int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type); 726 struct nlattr *nltb[IWPM_NLA_ERR_MAX]; 727 u32 msg_seq; 728 u16 err_code; 729 const char *msg_type = "Mapping Error Msg"; 730 731 if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX, 732 map_error_policy, nltb, msg_type)) 733 return -EINVAL; 734 735 msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]); 736 err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]); 737 pr_info("%s: Received msg seq = %u err code = %u client = %d\n", 738 __func__, msg_seq, err_code, nl_client); 739 /* look for nlmsg_request */ 740 nlmsg_request = iwpm_find_nlmsg_request(msg_seq); 741 if (!nlmsg_request) { 742 /* not all errors have associated requests */ 743 pr_debug("Could not find matching req (seq = %u)\n", msg_seq); 744 return 0; 745 } 746 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 747 nlmsg_request->err_code = err_code; 748 nlmsg_request->request_done = 1; 749 /* always for found request */ 750 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 751 barrier(); 752 wake_up(&nlmsg_request->waitq); 753 return 0; 754} 755EXPORT_SYMBOL(iwpm_mapping_error_cb); 756