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 36 static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser"; 37 static int iwpm_ulib_version = 3; 38 static int iwpm_user_pid = IWPM_PID_UNDEFINED; 39 static atomic_t echo_nlmsg_seq; 40 41 int iwpm_valid_pid(void) 42 { 43 return iwpm_user_pid > 0; 44 } 45 EXPORT_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 */ 57 int 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, IFNAMSIZ, 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; 117 pid_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 } 125 EXPORT_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 */ 134 int 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; 186 add_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 } 194 EXPORT_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 */ 204 int 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; 262 query_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 } 270 EXPORT_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 */ 279 int 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; 325 remove_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 } 331 EXPORT_SYMBOL(iwpm_remove_mapping); 332 333 /* netlink attribute policy for the received response to register pid request */ 334 static 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 */ 348 int 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); 392 register_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 up(&nlmsg_request->sem); 398 return 0; 399 } 400 EXPORT_SYMBOL(iwpm_register_pid_cb); 401 402 /* netlink attribute policy for the received response to add mapping request */ 403 static 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 */ 414 int 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 461 add_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 up(&nlmsg_request->sem); 467 return 0; 468 } 469 EXPORT_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 */ 473 static 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 */ 486 int 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:"); 553 query_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 up(&nlmsg_request->sem); 559 return 0; 560 } 561 EXPORT_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 */ 567 int 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 ret = -ENOMEM; 608 return ret; 609 } 610 memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr, 611 sizeof(struct sockaddr_storage)); 612 memcpy(&rem_info->remote_sockaddr, remote_sockaddr, 613 sizeof(struct sockaddr_storage)); 614 memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr, 615 sizeof(struct sockaddr_storage)); 616 rem_info->nl_client = nl_client; 617 618 iwpm_add_remote_info(rem_info); 619 620 iwpm_print_sockaddr(local_sockaddr, 621 "remote_info: Local sockaddr:"); 622 iwpm_print_sockaddr(mapped_loc_sockaddr, 623 "remote_info: Mapped local sockaddr:"); 624 iwpm_print_sockaddr(remote_sockaddr, 625 "remote_info: Remote sockaddr:"); 626 iwpm_print_sockaddr(mapped_rem_sockaddr, 627 "remote_info: Mapped remote sockaddr:"); 628 return ret; 629 } 630 EXPORT_SYMBOL(iwpm_remote_info_cb); 631 632 /* netlink attribute policy for the received request for mapping info */ 633 static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = { 634 [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING, 635 .len = IWPM_ULIBNAME_SIZE - 1 }, 636 [IWPM_NLA_MAPINFO_ULIB_VER] = { .type = NLA_U16 } 637 }; 638 639 /* 640 * iwpm_mapping_info_cb - Process a port mapper request for mapping info 641 */ 642 int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) 643 { 644 struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX]; 645 const char *msg_type = "Mapping Info response"; 646 u8 nl_client; 647 char *iwpm_name; 648 u16 iwpm_version; 649 int ret = -EINVAL; 650 651 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX, 652 resp_mapinfo_policy, nltb, msg_type)) { 653 pr_info("%s: Unable to parse nlmsg\n", __func__); 654 return ret; 655 } 656 iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]); 657 iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]); 658 if (strcmp(iwpm_ulib_name, iwpm_name) || 659 iwpm_version != iwpm_ulib_version) { 660 pr_info("%s: Invalid port mapper name = %s version = %d\n", 661 __func__, iwpm_name, iwpm_version); 662 return ret; 663 } 664 nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type); 665 if (!iwpm_valid_client(nl_client)) { 666 pr_info("%s: Invalid port mapper client = %d\n", 667 __func__, nl_client); 668 return ret; 669 } 670 iwpm_set_registration(nl_client, IWPM_REG_INCOMPL); 671 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 672 iwpm_user_pid = cb->nlh->nlmsg_pid; 673 if (!iwpm_mapinfo_available()) 674 return 0; 675 pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n", 676 __func__, iwpm_user_pid); 677 ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid); 678 return ret; 679 } 680 EXPORT_SYMBOL(iwpm_mapping_info_cb); 681 682 /* netlink attribute policy for the received mapping info ack */ 683 static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = { 684 [IWPM_NLA_MAPINFO_SEQ] = { .type = NLA_U32 }, 685 [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 }, 686 [IWPM_NLA_MAPINFO_ACK_NUM] = { .type = NLA_U32 } 687 }; 688 689 /* 690 * iwpm_ack_mapping_info_cb - Process a port mapper ack for 691 * the provided mapping info records 692 */ 693 int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb) 694 { 695 struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX]; 696 u32 mapinfo_send, mapinfo_ack; 697 const char *msg_type = "Mapping Info Ack"; 698 699 if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX, 700 ack_mapinfo_policy, nltb, msg_type)) 701 return -EINVAL; 702 mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]); 703 mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]); 704 if (mapinfo_ack != mapinfo_send) 705 pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n", 706 __func__, mapinfo_send, mapinfo_ack); 707 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 708 return 0; 709 } 710 EXPORT_SYMBOL(iwpm_ack_mapping_info_cb); 711 712 /* netlink attribute policy for the received port mapper error message */ 713 static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = { 714 [IWPM_NLA_ERR_SEQ] = { .type = NLA_U32 }, 715 [IWPM_NLA_ERR_CODE] = { .type = NLA_U16 }, 716 }; 717 718 /* 719 * iwpm_mapping_error_cb - Process a port mapper error message 720 */ 721 int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb) 722 { 723 struct iwpm_nlmsg_request *nlmsg_request = NULL; 724 int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type); 725 struct nlattr *nltb[IWPM_NLA_ERR_MAX]; 726 u32 msg_seq; 727 u16 err_code; 728 const char *msg_type = "Mapping Error Msg"; 729 730 if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX, 731 map_error_policy, nltb, msg_type)) 732 return -EINVAL; 733 734 msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]); 735 err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]); 736 pr_info("%s: Received msg seq = %u err code = %u client = %d\n", 737 __func__, msg_seq, err_code, nl_client); 738 /* look for nlmsg_request */ 739 nlmsg_request = iwpm_find_nlmsg_request(msg_seq); 740 if (!nlmsg_request) { 741 /* not all errors have associated requests */ 742 pr_debug("Could not find matching req (seq = %u)\n", msg_seq); 743 return 0; 744 } 745 atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq); 746 nlmsg_request->err_code = err_code; 747 nlmsg_request->request_done = 1; 748 /* always for found request */ 749 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 750 barrier(); 751 up(&nlmsg_request->sem); 752 return 0; 753 } 754 EXPORT_SYMBOL(iwpm_mapping_error_cb); 755