1 /* 2 * Copyright (c) 2014 Chelsio, Inc. All rights reserved. 3 * Copyright (c) 2014 Intel Corporation. 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 #define IWPM_MAPINFO_HASH_SIZE 512 37 #define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1) 38 #define IWPM_REMINFO_HASH_SIZE 64 39 #define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1) 40 #define IWPM_MSG_SIZE 512 41 42 static LIST_HEAD(iwpm_nlmsg_req_list); 43 static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock); 44 45 static struct hlist_head *iwpm_hash_bucket; 46 static DEFINE_SPINLOCK(iwpm_mapinfo_lock); 47 48 static struct hlist_head *iwpm_reminfo_bucket; 49 static DEFINE_SPINLOCK(iwpm_reminfo_lock); 50 51 static DEFINE_MUTEX(iwpm_admin_lock); 52 static struct iwpm_admin_data iwpm_admin; 53 54 /** 55 * iwpm_init - Allocate resources for the iwarp port mapper 56 * @nl_client: The index of the netlink client 57 * 58 * Should be called when network interface goes up. 59 */ 60 int iwpm_init(u8 nl_client) 61 { 62 int ret = 0; 63 mutex_lock(&iwpm_admin_lock); 64 if (atomic_read(&iwpm_admin.refcount) == 0) { 65 iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE, 66 sizeof(struct hlist_head), 67 GFP_KERNEL); 68 if (!iwpm_hash_bucket) { 69 ret = -ENOMEM; 70 goto init_exit; 71 } 72 iwpm_reminfo_bucket = kcalloc(IWPM_REMINFO_HASH_SIZE, 73 sizeof(struct hlist_head), 74 GFP_KERNEL); 75 if (!iwpm_reminfo_bucket) { 76 kfree(iwpm_hash_bucket); 77 ret = -ENOMEM; 78 goto init_exit; 79 } 80 } 81 atomic_inc(&iwpm_admin.refcount); 82 init_exit: 83 mutex_unlock(&iwpm_admin_lock); 84 if (!ret) { 85 iwpm_set_valid(nl_client, 1); 86 iwpm_set_registration(nl_client, IWPM_REG_UNDEF); 87 pr_debug("%s: Mapinfo and reminfo tables are created\n", 88 __func__); 89 } 90 return ret; 91 } 92 93 static void free_hash_bucket(void); 94 static void free_reminfo_bucket(void); 95 96 /** 97 * iwpm_exit - Deallocate resources for the iwarp port mapper 98 * @nl_client: The index of the netlink client 99 * 100 * Should be called when network interface goes down. 101 */ 102 int iwpm_exit(u8 nl_client) 103 { 104 105 if (!iwpm_valid_client(nl_client)) 106 return -EINVAL; 107 mutex_lock(&iwpm_admin_lock); 108 if (atomic_read(&iwpm_admin.refcount) == 0) { 109 mutex_unlock(&iwpm_admin_lock); 110 pr_err("%s Incorrect usage - negative refcount\n", __func__); 111 return -EINVAL; 112 } 113 if (atomic_dec_and_test(&iwpm_admin.refcount)) { 114 free_hash_bucket(); 115 free_reminfo_bucket(); 116 pr_debug("%s: Resources are destroyed\n", __func__); 117 } 118 mutex_unlock(&iwpm_admin_lock); 119 iwpm_set_valid(nl_client, 0); 120 iwpm_set_registration(nl_client, IWPM_REG_UNDEF); 121 return 0; 122 } 123 124 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *, 125 struct sockaddr_storage *); 126 127 /** 128 * iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address 129 * info in a hash table 130 * @local_addr: Local ip/tcp address 131 * @mapped_addr: Mapped local ip/tcp address 132 * @nl_client: The index of the netlink client 133 * @map_flags: IWPM mapping flags 134 */ 135 int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr, 136 struct sockaddr_storage *mapped_sockaddr, 137 u8 nl_client, u32 map_flags) 138 { 139 struct hlist_head *hash_bucket_head = NULL; 140 struct iwpm_mapping_info *map_info; 141 unsigned long flags; 142 int ret = -EINVAL; 143 144 if (!iwpm_valid_client(nl_client)) 145 return ret; 146 map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL); 147 if (!map_info) 148 return -ENOMEM; 149 150 memcpy(&map_info->local_sockaddr, local_sockaddr, 151 sizeof(struct sockaddr_storage)); 152 memcpy(&map_info->mapped_sockaddr, mapped_sockaddr, 153 sizeof(struct sockaddr_storage)); 154 map_info->nl_client = nl_client; 155 map_info->map_flags = map_flags; 156 157 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 158 if (iwpm_hash_bucket) { 159 hash_bucket_head = get_mapinfo_hash_bucket( 160 &map_info->local_sockaddr, 161 &map_info->mapped_sockaddr); 162 if (hash_bucket_head) { 163 hlist_add_head(&map_info->hlist_node, hash_bucket_head); 164 ret = 0; 165 } 166 } 167 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 168 169 if (!hash_bucket_head) 170 kfree(map_info); 171 return ret; 172 } 173 174 /** 175 * iwpm_remove_mapinfo - Remove local and mapped IPv4/IPv6 address 176 * info from the hash table 177 * @local_addr: Local ip/tcp address 178 * @mapped_local_addr: Mapped local ip/tcp address 179 * 180 * Returns err code if mapping info is not found in the hash table, 181 * otherwise returns 0 182 */ 183 int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr, 184 struct sockaddr_storage *mapped_local_addr) 185 { 186 struct hlist_node *tmp_hlist_node; 187 struct hlist_head *hash_bucket_head; 188 struct iwpm_mapping_info *map_info = NULL; 189 unsigned long flags; 190 int ret = -EINVAL; 191 192 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 193 if (iwpm_hash_bucket) { 194 hash_bucket_head = get_mapinfo_hash_bucket( 195 local_sockaddr, 196 mapped_local_addr); 197 if (!hash_bucket_head) 198 goto remove_mapinfo_exit; 199 200 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 201 hash_bucket_head, hlist_node) { 202 203 if (!iwpm_compare_sockaddr(&map_info->mapped_sockaddr, 204 mapped_local_addr)) { 205 206 hlist_del_init(&map_info->hlist_node); 207 kfree(map_info); 208 ret = 0; 209 break; 210 } 211 } 212 } 213 remove_mapinfo_exit: 214 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 215 return ret; 216 } 217 218 static void free_hash_bucket(void) 219 { 220 struct hlist_node *tmp_hlist_node; 221 struct iwpm_mapping_info *map_info; 222 unsigned long flags; 223 int i; 224 225 /* remove all the mapinfo data from the list */ 226 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 227 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 228 hlist_for_each_entry_safe(map_info, tmp_hlist_node, 229 &iwpm_hash_bucket[i], hlist_node) { 230 231 hlist_del_init(&map_info->hlist_node); 232 kfree(map_info); 233 } 234 } 235 /* free the hash list */ 236 kfree(iwpm_hash_bucket); 237 iwpm_hash_bucket = NULL; 238 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 239 } 240 241 static void free_reminfo_bucket(void) 242 { 243 struct hlist_node *tmp_hlist_node; 244 struct iwpm_remote_info *rem_info; 245 unsigned long flags; 246 int i; 247 248 /* remove all the remote info from the list */ 249 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 250 for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) { 251 hlist_for_each_entry_safe(rem_info, tmp_hlist_node, 252 &iwpm_reminfo_bucket[i], hlist_node) { 253 254 hlist_del_init(&rem_info->hlist_node); 255 kfree(rem_info); 256 } 257 } 258 /* free the hash list */ 259 kfree(iwpm_reminfo_bucket); 260 iwpm_reminfo_bucket = NULL; 261 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 262 } 263 264 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *, 265 struct sockaddr_storage *); 266 267 void iwpm_add_remote_info(struct iwpm_remote_info *rem_info) 268 { 269 struct hlist_head *hash_bucket_head; 270 unsigned long flags; 271 272 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 273 if (iwpm_reminfo_bucket) { 274 hash_bucket_head = get_reminfo_hash_bucket( 275 &rem_info->mapped_loc_sockaddr, 276 &rem_info->mapped_rem_sockaddr); 277 if (hash_bucket_head) 278 hlist_add_head(&rem_info->hlist_node, hash_bucket_head); 279 } 280 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 281 } 282 283 /** 284 * iwpm_get_remote_info - Get the remote connecting peer address info 285 * 286 * @mapped_loc_addr: Mapped local address of the listening peer 287 * @mapped_rem_addr: Mapped remote address of the connecting peer 288 * @remote_addr: To store the remote address of the connecting peer 289 * @nl_client: The index of the netlink client 290 * 291 * The remote address info is retrieved and provided to the client in 292 * the remote_addr. After that it is removed from the hash table 293 */ 294 int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr, 295 struct sockaddr_storage *mapped_rem_addr, 296 struct sockaddr_storage *remote_addr, 297 u8 nl_client) 298 { 299 struct hlist_node *tmp_hlist_node; 300 struct hlist_head *hash_bucket_head; 301 struct iwpm_remote_info *rem_info = NULL; 302 unsigned long flags; 303 int ret = -EINVAL; 304 305 if (!iwpm_valid_client(nl_client)) { 306 pr_info("%s: Invalid client = %d\n", __func__, nl_client); 307 return ret; 308 } 309 spin_lock_irqsave(&iwpm_reminfo_lock, flags); 310 if (iwpm_reminfo_bucket) { 311 hash_bucket_head = get_reminfo_hash_bucket( 312 mapped_loc_addr, 313 mapped_rem_addr); 314 if (!hash_bucket_head) 315 goto get_remote_info_exit; 316 hlist_for_each_entry_safe(rem_info, tmp_hlist_node, 317 hash_bucket_head, hlist_node) { 318 319 if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr, 320 mapped_loc_addr) && 321 !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr, 322 mapped_rem_addr)) { 323 324 memcpy(remote_addr, &rem_info->remote_sockaddr, 325 sizeof(struct sockaddr_storage)); 326 iwpm_print_sockaddr(remote_addr, 327 "get_remote_info: Remote sockaddr:"); 328 329 hlist_del_init(&rem_info->hlist_node); 330 kfree(rem_info); 331 ret = 0; 332 break; 333 } 334 } 335 } 336 get_remote_info_exit: 337 spin_unlock_irqrestore(&iwpm_reminfo_lock, flags); 338 return ret; 339 } 340 341 struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq, 342 u8 nl_client, gfp_t gfp) 343 { 344 struct iwpm_nlmsg_request *nlmsg_request = NULL; 345 unsigned long flags; 346 347 nlmsg_request = kzalloc(sizeof(struct iwpm_nlmsg_request), gfp); 348 if (!nlmsg_request) 349 return NULL; 350 351 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 352 list_add_tail(&nlmsg_request->inprocess_list, &iwpm_nlmsg_req_list); 353 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 354 355 kref_init(&nlmsg_request->kref); 356 kref_get(&nlmsg_request->kref); 357 nlmsg_request->nlmsg_seq = nlmsg_seq; 358 nlmsg_request->nl_client = nl_client; 359 nlmsg_request->request_done = 0; 360 nlmsg_request->err_code = 0; 361 sema_init(&nlmsg_request->sem, 1); 362 down(&nlmsg_request->sem); 363 return nlmsg_request; 364 } 365 366 void iwpm_free_nlmsg_request(struct kref *kref) 367 { 368 struct iwpm_nlmsg_request *nlmsg_request; 369 unsigned long flags; 370 371 nlmsg_request = container_of(kref, struct iwpm_nlmsg_request, kref); 372 373 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 374 list_del_init(&nlmsg_request->inprocess_list); 375 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 376 377 if (!nlmsg_request->request_done) 378 pr_debug("%s Freeing incomplete nlmsg request (seq = %u).\n", 379 __func__, nlmsg_request->nlmsg_seq); 380 kfree(nlmsg_request); 381 } 382 383 struct iwpm_nlmsg_request *iwpm_find_nlmsg_request(__u32 echo_seq) 384 { 385 struct iwpm_nlmsg_request *nlmsg_request; 386 struct iwpm_nlmsg_request *found_request = NULL; 387 unsigned long flags; 388 389 spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags); 390 list_for_each_entry(nlmsg_request, &iwpm_nlmsg_req_list, 391 inprocess_list) { 392 if (nlmsg_request->nlmsg_seq == echo_seq) { 393 found_request = nlmsg_request; 394 kref_get(&nlmsg_request->kref); 395 break; 396 } 397 } 398 spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags); 399 return found_request; 400 } 401 402 int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request) 403 { 404 int ret; 405 406 ret = down_timeout(&nlmsg_request->sem, IWPM_NL_TIMEOUT); 407 if (ret) { 408 ret = -EINVAL; 409 pr_info("%s: Timeout %d sec for netlink request (seq = %u)\n", 410 __func__, (IWPM_NL_TIMEOUT/HZ), nlmsg_request->nlmsg_seq); 411 } else { 412 ret = nlmsg_request->err_code; 413 } 414 kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request); 415 return ret; 416 } 417 418 int iwpm_get_nlmsg_seq(void) 419 { 420 return atomic_inc_return(&iwpm_admin.nlmsg_seq); 421 } 422 423 int iwpm_valid_client(u8 nl_client) 424 { 425 return iwpm_admin.client_list[nl_client]; 426 } 427 428 void iwpm_set_valid(u8 nl_client, int valid) 429 { 430 iwpm_admin.client_list[nl_client] = valid; 431 } 432 433 /* valid client */ 434 u32 iwpm_get_registration(u8 nl_client) 435 { 436 return iwpm_admin.reg_list[nl_client]; 437 } 438 439 /* valid client */ 440 void iwpm_set_registration(u8 nl_client, u32 reg) 441 { 442 iwpm_admin.reg_list[nl_client] = reg; 443 } 444 445 /* valid client */ 446 u32 iwpm_check_registration(u8 nl_client, u32 reg) 447 { 448 return (iwpm_get_registration(nl_client) & reg); 449 } 450 451 int iwpm_compare_sockaddr(struct sockaddr_storage *a_sockaddr, 452 struct sockaddr_storage *b_sockaddr) 453 { 454 if (a_sockaddr->ss_family != b_sockaddr->ss_family) 455 return 1; 456 if (a_sockaddr->ss_family == AF_INET) { 457 struct sockaddr_in *a4_sockaddr = 458 (struct sockaddr_in *)a_sockaddr; 459 struct sockaddr_in *b4_sockaddr = 460 (struct sockaddr_in *)b_sockaddr; 461 if (!memcmp(&a4_sockaddr->sin_addr, 462 &b4_sockaddr->sin_addr, sizeof(struct in_addr)) 463 && a4_sockaddr->sin_port == b4_sockaddr->sin_port) 464 return 0; 465 466 } else if (a_sockaddr->ss_family == AF_INET6) { 467 struct sockaddr_in6 *a6_sockaddr = 468 (struct sockaddr_in6 *)a_sockaddr; 469 struct sockaddr_in6 *b6_sockaddr = 470 (struct sockaddr_in6 *)b_sockaddr; 471 if (!memcmp(&a6_sockaddr->sin6_addr, 472 &b6_sockaddr->sin6_addr, sizeof(struct in6_addr)) 473 && a6_sockaddr->sin6_port == b6_sockaddr->sin6_port) 474 return 0; 475 476 } else { 477 pr_err("%s: Invalid sockaddr family\n", __func__); 478 } 479 return 1; 480 } 481 482 struct sk_buff *iwpm_create_nlmsg(u32 nl_op, struct nlmsghdr **nlh, 483 int nl_client) 484 { 485 struct sk_buff *skb = NULL; 486 487 skb = dev_alloc_skb(IWPM_MSG_SIZE); 488 if (!skb) 489 goto create_nlmsg_exit; 490 491 if (!(ibnl_put_msg(skb, nlh, 0, 0, nl_client, nl_op, 492 NLM_F_REQUEST))) { 493 pr_warn("%s: Unable to put the nlmsg header\n", __func__); 494 dev_kfree_skb(skb); 495 skb = NULL; 496 } 497 create_nlmsg_exit: 498 return skb; 499 } 500 501 int iwpm_parse_nlmsg(struct netlink_callback *cb, int policy_max, 502 const struct nla_policy *nlmsg_policy, 503 struct nlattr *nltb[], const char *msg_type) 504 { 505 int nlh_len = 0; 506 int ret; 507 const char *err_str = ""; 508 509 ret = nlmsg_validate_deprecated(cb->nlh, nlh_len, policy_max - 1, 510 nlmsg_policy, NULL); 511 if (ret) { 512 err_str = "Invalid attribute"; 513 goto parse_nlmsg_error; 514 } 515 ret = nlmsg_parse_deprecated(cb->nlh, nlh_len, nltb, policy_max - 1, 516 nlmsg_policy, NULL); 517 if (ret) { 518 err_str = "Unable to parse the nlmsg"; 519 goto parse_nlmsg_error; 520 } 521 ret = iwpm_validate_nlmsg_attr(nltb, policy_max); 522 if (ret) { 523 err_str = "Invalid NULL attribute"; 524 goto parse_nlmsg_error; 525 } 526 return 0; 527 parse_nlmsg_error: 528 pr_warn("%s: %s (msg type %s ret = %d)\n", 529 __func__, err_str, msg_type, ret); 530 return ret; 531 } 532 533 void iwpm_print_sockaddr(struct sockaddr_storage *sockaddr, char *msg) 534 { 535 struct sockaddr_in6 *sockaddr_v6; 536 struct sockaddr_in *sockaddr_v4; 537 538 switch (sockaddr->ss_family) { 539 case AF_INET: 540 sockaddr_v4 = (struct sockaddr_in *)sockaddr; 541 pr_debug("%s IPV4 %pI4: %u(0x%04X)\n", 542 msg, &sockaddr_v4->sin_addr, 543 ntohs(sockaddr_v4->sin_port), 544 ntohs(sockaddr_v4->sin_port)); 545 break; 546 case AF_INET6: 547 sockaddr_v6 = (struct sockaddr_in6 *)sockaddr; 548 pr_debug("%s IPV6 %pI6: %u(0x%04X)\n", 549 msg, &sockaddr_v6->sin6_addr, 550 ntohs(sockaddr_v6->sin6_port), 551 ntohs(sockaddr_v6->sin6_port)); 552 break; 553 default: 554 break; 555 } 556 } 557 558 static u32 iwpm_ipv6_jhash(struct sockaddr_in6 *ipv6_sockaddr) 559 { 560 u32 ipv6_hash = jhash(&ipv6_sockaddr->sin6_addr, sizeof(struct in6_addr), 0); 561 u32 hash = jhash_2words(ipv6_hash, (__force u32) ipv6_sockaddr->sin6_port, 0); 562 return hash; 563 } 564 565 static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr) 566 { 567 u32 ipv4_hash = jhash(&ipv4_sockaddr->sin_addr, sizeof(struct in_addr), 0); 568 u32 hash = jhash_2words(ipv4_hash, (__force u32) ipv4_sockaddr->sin_port, 0); 569 return hash; 570 } 571 572 static int get_hash_bucket(struct sockaddr_storage *a_sockaddr, 573 struct sockaddr_storage *b_sockaddr, u32 *hash) 574 { 575 u32 a_hash, b_hash; 576 577 if (a_sockaddr->ss_family == AF_INET) { 578 a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr); 579 b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr); 580 581 } else if (a_sockaddr->ss_family == AF_INET6) { 582 a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr); 583 b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr); 584 } else { 585 pr_err("%s: Invalid sockaddr family\n", __func__); 586 return -EINVAL; 587 } 588 589 if (a_hash == b_hash) /* if port mapper isn't available */ 590 *hash = a_hash; 591 else 592 *hash = jhash_2words(a_hash, b_hash, 0); 593 return 0; 594 } 595 596 static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage 597 *local_sockaddr, struct sockaddr_storage 598 *mapped_sockaddr) 599 { 600 u32 hash; 601 int ret; 602 603 ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash); 604 if (ret) 605 return NULL; 606 return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK]; 607 } 608 609 static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage 610 *mapped_loc_sockaddr, struct sockaddr_storage 611 *mapped_rem_sockaddr) 612 { 613 u32 hash; 614 int ret; 615 616 ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash); 617 if (ret) 618 return NULL; 619 return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK]; 620 } 621 622 static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid) 623 { 624 struct sk_buff *skb = NULL; 625 struct nlmsghdr *nlh; 626 u32 msg_seq; 627 const char *err_str = ""; 628 int ret = -EINVAL; 629 630 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_MAPINFO_NUM, &nlh, nl_client); 631 if (!skb) { 632 err_str = "Unable to create a nlmsg"; 633 goto mapinfo_num_error; 634 } 635 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 636 msg_seq = 0; 637 err_str = "Unable to put attribute of mapinfo number nlmsg"; 638 ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_MAPINFO_SEQ); 639 if (ret) 640 goto mapinfo_num_error; 641 ret = ibnl_put_attr(skb, nlh, sizeof(u32), 642 &mapping_num, IWPM_NLA_MAPINFO_SEND_NUM); 643 if (ret) 644 goto mapinfo_num_error; 645 646 nlmsg_end(skb, nlh); 647 648 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid); 649 if (ret) { 650 skb = NULL; 651 err_str = "Unable to send a nlmsg"; 652 goto mapinfo_num_error; 653 } 654 pr_debug("%s: Sent mapping number = %d\n", __func__, mapping_num); 655 return 0; 656 mapinfo_num_error: 657 pr_info("%s: %s\n", __func__, err_str); 658 dev_kfree_skb(skb); 659 return ret; 660 } 661 662 static int send_nlmsg_done(struct sk_buff *skb, u8 nl_client, int iwpm_pid) 663 { 664 struct nlmsghdr *nlh = NULL; 665 int ret = 0; 666 667 if (!skb) 668 return ret; 669 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client, 670 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) { 671 pr_warn("%s Unable to put NLMSG_DONE\n", __func__); 672 dev_kfree_skb(skb); 673 return -ENOMEM; 674 } 675 nlh->nlmsg_type = NLMSG_DONE; 676 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid); 677 if (ret) 678 pr_warn("%s Unable to send a nlmsg\n", __func__); 679 return ret; 680 } 681 682 int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid) 683 { 684 struct iwpm_mapping_info *map_info; 685 struct sk_buff *skb = NULL; 686 struct nlmsghdr *nlh; 687 int skb_num = 0, mapping_num = 0; 688 int i = 0, nlmsg_bytes = 0; 689 unsigned long flags; 690 const char *err_str = ""; 691 int ret; 692 693 skb = dev_alloc_skb(NLMSG_GOODSIZE); 694 if (!skb) { 695 ret = -ENOMEM; 696 err_str = "Unable to allocate skb"; 697 goto send_mapping_info_exit; 698 } 699 skb_num++; 700 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 701 ret = -EINVAL; 702 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 703 hlist_for_each_entry(map_info, &iwpm_hash_bucket[i], 704 hlist_node) { 705 if (map_info->nl_client != nl_client) 706 continue; 707 nlh = NULL; 708 if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client, 709 RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) { 710 ret = -ENOMEM; 711 err_str = "Unable to put the nlmsg header"; 712 goto send_mapping_info_unlock; 713 } 714 err_str = "Unable to put attribute of the nlmsg"; 715 ret = ibnl_put_attr(skb, nlh, 716 sizeof(struct sockaddr_storage), 717 &map_info->local_sockaddr, 718 IWPM_NLA_MAPINFO_LOCAL_ADDR); 719 if (ret) 720 goto send_mapping_info_unlock; 721 722 ret = ibnl_put_attr(skb, nlh, 723 sizeof(struct sockaddr_storage), 724 &map_info->mapped_sockaddr, 725 IWPM_NLA_MAPINFO_MAPPED_ADDR); 726 if (ret) 727 goto send_mapping_info_unlock; 728 729 if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) { 730 ret = ibnl_put_attr(skb, nlh, sizeof(u32), 731 &map_info->map_flags, 732 IWPM_NLA_MAPINFO_FLAGS); 733 if (ret) 734 goto send_mapping_info_unlock; 735 } 736 737 nlmsg_end(skb, nlh); 738 739 iwpm_print_sockaddr(&map_info->local_sockaddr, 740 "send_mapping_info: Local sockaddr:"); 741 iwpm_print_sockaddr(&map_info->mapped_sockaddr, 742 "send_mapping_info: Mapped local sockaddr:"); 743 mapping_num++; 744 nlmsg_bytes += nlh->nlmsg_len; 745 746 /* check if all mappings can fit in one skb */ 747 if (NLMSG_GOODSIZE - nlmsg_bytes < nlh->nlmsg_len * 2) { 748 /* and leave room for NLMSG_DONE */ 749 nlmsg_bytes = 0; 750 skb_num++; 751 spin_unlock_irqrestore(&iwpm_mapinfo_lock, 752 flags); 753 /* send the skb */ 754 ret = send_nlmsg_done(skb, nl_client, iwpm_pid); 755 skb = NULL; 756 if (ret) { 757 err_str = "Unable to send map info"; 758 goto send_mapping_info_exit; 759 } 760 if (skb_num == IWPM_MAPINFO_SKB_COUNT) { 761 ret = -ENOMEM; 762 err_str = "Insufficient skbs for map info"; 763 goto send_mapping_info_exit; 764 } 765 skb = dev_alloc_skb(NLMSG_GOODSIZE); 766 if (!skb) { 767 ret = -ENOMEM; 768 err_str = "Unable to allocate skb"; 769 goto send_mapping_info_exit; 770 } 771 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 772 } 773 } 774 } 775 send_mapping_info_unlock: 776 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 777 send_mapping_info_exit: 778 if (ret) { 779 pr_warn("%s: %s (ret = %d)\n", __func__, err_str, ret); 780 dev_kfree_skb(skb); 781 return ret; 782 } 783 send_nlmsg_done(skb, nl_client, iwpm_pid); 784 return send_mapinfo_num(mapping_num, nl_client, iwpm_pid); 785 } 786 787 int iwpm_mapinfo_available(void) 788 { 789 unsigned long flags; 790 int full_bucket = 0, i = 0; 791 792 spin_lock_irqsave(&iwpm_mapinfo_lock, flags); 793 if (iwpm_hash_bucket) { 794 for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) { 795 if (!hlist_empty(&iwpm_hash_bucket[i])) { 796 full_bucket = 1; 797 break; 798 } 799 } 800 } 801 spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); 802 return full_bucket; 803 } 804 805 int iwpm_send_hello(u8 nl_client, int iwpm_pid, u16 abi_version) 806 { 807 struct sk_buff *skb = NULL; 808 struct nlmsghdr *nlh; 809 const char *err_str = ""; 810 int ret = -EINVAL; 811 812 skb = iwpm_create_nlmsg(RDMA_NL_IWPM_HELLO, &nlh, nl_client); 813 if (!skb) { 814 err_str = "Unable to create a nlmsg"; 815 goto hello_num_error; 816 } 817 nlh->nlmsg_seq = iwpm_get_nlmsg_seq(); 818 err_str = "Unable to put attribute of abi_version into nlmsg"; 819 ret = ibnl_put_attr(skb, nlh, sizeof(u16), &abi_version, 820 IWPM_NLA_HELLO_ABI_VERSION); 821 if (ret) 822 goto hello_num_error; 823 nlmsg_end(skb, nlh); 824 825 ret = rdma_nl_unicast(&init_net, skb, iwpm_pid); 826 if (ret) { 827 skb = NULL; 828 err_str = "Unable to send a nlmsg"; 829 goto hello_num_error; 830 } 831 pr_debug("%s: Sent hello abi_version = %u\n", __func__, abi_version); 832 return 0; 833 hello_num_error: 834 pr_info("%s: %s\n", __func__, err_str); 835 dev_kfree_skb(skb); 836 return ret; 837 } 838