1 // SPDX-License-Identifier: GPL-2.0 2 /* Multipath TCP 3 * 4 * Copyright (c) 2022, Intel Corporation. 5 */ 6 7 #include "protocol.h" 8 #include "mib.h" 9 #include "mptcp_pm_gen.h" 10 11 void mptcp_free_local_addr_list(struct mptcp_sock *msk) 12 { 13 struct mptcp_pm_addr_entry *entry, *tmp; 14 struct sock *sk = (struct sock *)msk; 15 LIST_HEAD(free_list); 16 17 if (!mptcp_pm_is_userspace(msk)) 18 return; 19 20 spin_lock_bh(&msk->pm.lock); 21 list_splice_init(&msk->pm.userspace_pm_local_addr_list, &free_list); 22 spin_unlock_bh(&msk->pm.lock); 23 24 list_for_each_entry_safe(entry, tmp, &free_list, list) { 25 sock_kfree_s(sk, entry, sizeof(*entry)); 26 } 27 } 28 29 static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, 30 struct mptcp_pm_addr_entry *entry, 31 bool needs_id) 32 { 33 DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1); 34 struct mptcp_pm_addr_entry *match = NULL; 35 struct sock *sk = (struct sock *)msk; 36 struct mptcp_pm_addr_entry *e; 37 bool addr_match = false; 38 bool id_match = false; 39 int ret = -EINVAL; 40 41 bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1); 42 43 spin_lock_bh(&msk->pm.lock); 44 list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) { 45 addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true); 46 if (addr_match && entry->addr.id == 0 && needs_id) 47 entry->addr.id = e->addr.id; 48 id_match = (e->addr.id == entry->addr.id); 49 if (addr_match && id_match) { 50 match = e; 51 break; 52 } else if (addr_match || id_match) { 53 break; 54 } 55 __set_bit(e->addr.id, id_bitmap); 56 } 57 58 if (!match && !addr_match && !id_match) { 59 /* Memory for the entry is allocated from the 60 * sock option buffer. 61 */ 62 e = sock_kmalloc(sk, sizeof(*e), GFP_ATOMIC); 63 if (!e) { 64 ret = -ENOMEM; 65 goto append_err; 66 } 67 68 *e = *entry; 69 if (!e->addr.id && needs_id) 70 e->addr.id = find_next_zero_bit(id_bitmap, 71 MPTCP_PM_MAX_ADDR_ID + 1, 72 1); 73 list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list); 74 msk->pm.local_addr_used++; 75 ret = e->addr.id; 76 } else if (match) { 77 ret = entry->addr.id; 78 } 79 80 append_err: 81 spin_unlock_bh(&msk->pm.lock); 82 return ret; 83 } 84 85 /* If the subflow is closed from the other peer (not via a 86 * subflow destroy command then), we want to keep the entry 87 * not to assign the same ID to another address and to be 88 * able to send RM_ADDR after the removal of the subflow. 89 */ 90 static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk, 91 struct mptcp_pm_addr_entry *addr) 92 { 93 struct mptcp_pm_addr_entry *entry, *tmp; 94 95 list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) { 96 if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) { 97 /* TODO: a refcount is needed because the entry can 98 * be used multiple times (e.g. fullmesh mode). 99 */ 100 list_del_rcu(&entry->list); 101 kfree(entry); 102 msk->pm.local_addr_used--; 103 return 0; 104 } 105 } 106 107 return -EINVAL; 108 } 109 110 static struct mptcp_pm_addr_entry * 111 mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id) 112 { 113 struct mptcp_pm_addr_entry *entry; 114 115 list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 116 if (entry->addr.id == id) 117 return entry; 118 } 119 return NULL; 120 } 121 122 int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, 123 unsigned int id, 124 u8 *flags, int *ifindex) 125 { 126 struct mptcp_pm_addr_entry *match; 127 128 spin_lock_bh(&msk->pm.lock); 129 match = mptcp_userspace_pm_lookup_addr_by_id(msk, id); 130 spin_unlock_bh(&msk->pm.lock); 131 if (match) { 132 *flags = match->flags; 133 *ifindex = match->ifindex; 134 } 135 136 return 0; 137 } 138 139 int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, 140 struct mptcp_addr_info *skc) 141 { 142 struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry; 143 __be16 msk_sport = ((struct inet_sock *) 144 inet_sk((struct sock *)msk))->inet_sport; 145 146 spin_lock_bh(&msk->pm.lock); 147 list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) { 148 if (mptcp_addresses_equal(&e->addr, skc, false)) { 149 entry = e; 150 break; 151 } 152 } 153 spin_unlock_bh(&msk->pm.lock); 154 if (entry) 155 return entry->addr.id; 156 157 memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry)); 158 new_entry.addr = *skc; 159 new_entry.addr.id = 0; 160 new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; 161 162 if (new_entry.addr.port == msk_sport) 163 new_entry.addr.port = 0; 164 165 return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true); 166 } 167 168 bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, 169 struct mptcp_addr_info *skc) 170 { 171 struct mptcp_pm_addr_entry *entry; 172 bool backup = false; 173 174 spin_lock_bh(&msk->pm.lock); 175 list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 176 if (mptcp_addresses_equal(&entry->addr, skc, false)) { 177 backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); 178 break; 179 } 180 } 181 spin_unlock_bh(&msk->pm.lock); 182 183 return backup; 184 } 185 186 int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info) 187 { 188 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 189 struct nlattr *addr = info->attrs[MPTCP_PM_ATTR_ADDR]; 190 struct mptcp_pm_addr_entry addr_val; 191 struct mptcp_sock *msk; 192 int err = -EINVAL; 193 struct sock *sk; 194 u32 token_val; 195 196 if (!addr || !token) { 197 GENL_SET_ERR_MSG(info, "missing required inputs"); 198 return err; 199 } 200 201 token_val = nla_get_u32(token); 202 203 msk = mptcp_token_get_sock(sock_net(skb->sk), token_val); 204 if (!msk) { 205 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 206 return err; 207 } 208 209 sk = (struct sock *)msk; 210 211 if (!mptcp_pm_is_userspace(msk)) { 212 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 213 goto announce_err; 214 } 215 216 err = mptcp_pm_parse_entry(addr, info, true, &addr_val); 217 if (err < 0) { 218 GENL_SET_ERR_MSG(info, "error parsing local address"); 219 goto announce_err; 220 } 221 222 if (addr_val.addr.id == 0 || !(addr_val.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) { 223 GENL_SET_ERR_MSG(info, "invalid addr id or flags"); 224 err = -EINVAL; 225 goto announce_err; 226 } 227 228 err = mptcp_userspace_pm_append_new_local_addr(msk, &addr_val, false); 229 if (err < 0) { 230 GENL_SET_ERR_MSG(info, "did not match address and id"); 231 goto announce_err; 232 } 233 234 lock_sock(sk); 235 spin_lock_bh(&msk->pm.lock); 236 237 if (mptcp_pm_alloc_anno_list(msk, &addr_val.addr)) { 238 msk->pm.add_addr_signaled++; 239 mptcp_pm_announce_addr(msk, &addr_val.addr, false); 240 mptcp_pm_nl_addr_send_ack(msk); 241 } 242 243 spin_unlock_bh(&msk->pm.lock); 244 release_sock(sk); 245 246 err = 0; 247 announce_err: 248 sock_put(sk); 249 return err; 250 } 251 252 static int mptcp_userspace_pm_remove_id_zero_address(struct mptcp_sock *msk, 253 struct genl_info *info) 254 { 255 struct mptcp_rm_list list = { .nr = 0 }; 256 struct mptcp_subflow_context *subflow; 257 struct sock *sk = (struct sock *)msk; 258 bool has_id_0 = false; 259 int err = -EINVAL; 260 261 lock_sock(sk); 262 mptcp_for_each_subflow(msk, subflow) { 263 if (READ_ONCE(subflow->local_id) == 0) { 264 has_id_0 = true; 265 break; 266 } 267 } 268 if (!has_id_0) { 269 GENL_SET_ERR_MSG(info, "address with id 0 not found"); 270 goto remove_err; 271 } 272 273 list.ids[list.nr++] = 0; 274 275 spin_lock_bh(&msk->pm.lock); 276 mptcp_pm_remove_addr(msk, &list); 277 spin_unlock_bh(&msk->pm.lock); 278 279 err = 0; 280 281 remove_err: 282 release_sock(sk); 283 return err; 284 } 285 286 int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info) 287 { 288 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 289 struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID]; 290 struct mptcp_pm_addr_entry *match; 291 struct mptcp_pm_addr_entry *entry; 292 struct mptcp_sock *msk; 293 LIST_HEAD(free_list); 294 int err = -EINVAL; 295 struct sock *sk; 296 u32 token_val; 297 u8 id_val; 298 299 if (!id || !token) { 300 GENL_SET_ERR_MSG(info, "missing required inputs"); 301 return err; 302 } 303 304 id_val = nla_get_u8(id); 305 token_val = nla_get_u32(token); 306 307 msk = mptcp_token_get_sock(sock_net(skb->sk), token_val); 308 if (!msk) { 309 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 310 return err; 311 } 312 313 sk = (struct sock *)msk; 314 315 if (!mptcp_pm_is_userspace(msk)) { 316 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 317 goto out; 318 } 319 320 if (id_val == 0) { 321 err = mptcp_userspace_pm_remove_id_zero_address(msk, info); 322 goto out; 323 } 324 325 lock_sock(sk); 326 327 match = mptcp_userspace_pm_lookup_addr_by_id(msk, id_val); 328 if (!match) { 329 GENL_SET_ERR_MSG(info, "address with specified id not found"); 330 release_sock(sk); 331 goto out; 332 } 333 334 list_move(&match->list, &free_list); 335 336 mptcp_pm_remove_addrs(msk, &free_list); 337 338 release_sock(sk); 339 340 list_for_each_entry_safe(match, entry, &free_list, list) { 341 sock_kfree_s(sk, match, sizeof(*match)); 342 } 343 344 err = 0; 345 out: 346 sock_put(sk); 347 return err; 348 } 349 350 int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info) 351 { 352 struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE]; 353 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 354 struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR]; 355 struct mptcp_pm_addr_entry local = { 0 }; 356 struct mptcp_addr_info addr_r; 357 struct mptcp_sock *msk; 358 int err = -EINVAL; 359 struct sock *sk; 360 u32 token_val; 361 362 if (!laddr || !raddr || !token) { 363 GENL_SET_ERR_MSG(info, "missing required inputs"); 364 return err; 365 } 366 367 token_val = nla_get_u32(token); 368 369 msk = mptcp_token_get_sock(genl_info_net(info), token_val); 370 if (!msk) { 371 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 372 return err; 373 } 374 375 sk = (struct sock *)msk; 376 377 if (!mptcp_pm_is_userspace(msk)) { 378 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 379 goto create_err; 380 } 381 382 err = mptcp_pm_parse_entry(laddr, info, true, &local); 383 if (err < 0) { 384 NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr"); 385 goto create_err; 386 } 387 388 if (local.flags & MPTCP_PM_ADDR_FLAG_SIGNAL) { 389 GENL_SET_ERR_MSG(info, "invalid addr flags"); 390 err = -EINVAL; 391 goto create_err; 392 } 393 local.flags |= MPTCP_PM_ADDR_FLAG_SUBFLOW; 394 395 err = mptcp_pm_parse_addr(raddr, info, &addr_r); 396 if (err < 0) { 397 NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); 398 goto create_err; 399 } 400 401 if (!mptcp_pm_addr_families_match(sk, &local.addr, &addr_r)) { 402 GENL_SET_ERR_MSG(info, "families mismatch"); 403 err = -EINVAL; 404 goto create_err; 405 } 406 407 err = mptcp_userspace_pm_append_new_local_addr(msk, &local, false); 408 if (err < 0) { 409 GENL_SET_ERR_MSG(info, "did not match address and id"); 410 goto create_err; 411 } 412 413 lock_sock(sk); 414 415 err = __mptcp_subflow_connect(sk, &local.addr, &addr_r); 416 417 release_sock(sk); 418 419 spin_lock_bh(&msk->pm.lock); 420 if (err) 421 mptcp_userspace_pm_delete_local_addr(msk, &local); 422 else 423 msk->pm.subflows++; 424 spin_unlock_bh(&msk->pm.lock); 425 426 create_err: 427 sock_put(sk); 428 return err; 429 } 430 431 static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk, 432 const struct mptcp_addr_info *local, 433 const struct mptcp_addr_info *remote) 434 { 435 struct mptcp_subflow_context *subflow; 436 437 if (local->family != remote->family) 438 return NULL; 439 440 mptcp_for_each_subflow(msk, subflow) { 441 const struct inet_sock *issk; 442 struct sock *ssk; 443 444 ssk = mptcp_subflow_tcp_sock(subflow); 445 446 if (local->family != ssk->sk_family) 447 continue; 448 449 issk = inet_sk(ssk); 450 451 switch (ssk->sk_family) { 452 case AF_INET: 453 if (issk->inet_saddr != local->addr.s_addr || 454 issk->inet_daddr != remote->addr.s_addr) 455 continue; 456 break; 457 #if IS_ENABLED(CONFIG_MPTCP_IPV6) 458 case AF_INET6: { 459 const struct ipv6_pinfo *pinfo = inet6_sk(ssk); 460 461 if (!ipv6_addr_equal(&local->addr6, &pinfo->saddr) || 462 !ipv6_addr_equal(&remote->addr6, &ssk->sk_v6_daddr)) 463 continue; 464 break; 465 } 466 #endif 467 default: 468 continue; 469 } 470 471 if (issk->inet_sport == local->port && 472 issk->inet_dport == remote->port) 473 return ssk; 474 } 475 476 return NULL; 477 } 478 479 int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info) 480 { 481 struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE]; 482 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 483 struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR]; 484 struct mptcp_addr_info addr_l; 485 struct mptcp_addr_info addr_r; 486 struct mptcp_sock *msk; 487 struct sock *sk, *ssk; 488 int err = -EINVAL; 489 u32 token_val; 490 491 if (!laddr || !raddr || !token) { 492 GENL_SET_ERR_MSG(info, "missing required inputs"); 493 return err; 494 } 495 496 token_val = nla_get_u32(token); 497 498 msk = mptcp_token_get_sock(genl_info_net(info), token_val); 499 if (!msk) { 500 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 501 return err; 502 } 503 504 sk = (struct sock *)msk; 505 506 if (!mptcp_pm_is_userspace(msk)) { 507 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 508 goto destroy_err; 509 } 510 511 err = mptcp_pm_parse_addr(laddr, info, &addr_l); 512 if (err < 0) { 513 NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr"); 514 goto destroy_err; 515 } 516 517 err = mptcp_pm_parse_addr(raddr, info, &addr_r); 518 if (err < 0) { 519 NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); 520 goto destroy_err; 521 } 522 523 #if IS_ENABLED(CONFIG_MPTCP_IPV6) 524 if (addr_l.family == AF_INET && ipv6_addr_v4mapped(&addr_r.addr6)) { 525 ipv6_addr_set_v4mapped(addr_l.addr.s_addr, &addr_l.addr6); 526 addr_l.family = AF_INET6; 527 } 528 if (addr_r.family == AF_INET && ipv6_addr_v4mapped(&addr_l.addr6)) { 529 ipv6_addr_set_v4mapped(addr_r.addr.s_addr, &addr_r.addr6); 530 addr_r.family = AF_INET6; 531 } 532 #endif 533 if (addr_l.family != addr_r.family) { 534 GENL_SET_ERR_MSG(info, "address families do not match"); 535 err = -EINVAL; 536 goto destroy_err; 537 } 538 539 if (!addr_l.port || !addr_r.port) { 540 GENL_SET_ERR_MSG(info, "missing local or remote port"); 541 err = -EINVAL; 542 goto destroy_err; 543 } 544 545 lock_sock(sk); 546 ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r); 547 if (ssk) { 548 struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); 549 struct mptcp_pm_addr_entry entry = { .addr = addr_l }; 550 551 spin_lock_bh(&msk->pm.lock); 552 mptcp_userspace_pm_delete_local_addr(msk, &entry); 553 spin_unlock_bh(&msk->pm.lock); 554 mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN); 555 mptcp_close_ssk(sk, ssk, subflow); 556 MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW); 557 err = 0; 558 } else { 559 err = -ESRCH; 560 } 561 release_sock(sk); 562 563 destroy_err: 564 sock_put(sk); 565 return err; 566 } 567 568 int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info) 569 { 570 struct mptcp_pm_addr_entry loc = { .addr = { .family = AF_UNSPEC }, }; 571 struct mptcp_pm_addr_entry rem = { .addr = { .family = AF_UNSPEC }, }; 572 struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE]; 573 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 574 struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR]; 575 struct net *net = sock_net(skb->sk); 576 struct mptcp_sock *msk; 577 int ret = -EINVAL; 578 struct sock *sk; 579 u32 token_val; 580 u8 bkup = 0; 581 582 token_val = nla_get_u32(token); 583 584 msk = mptcp_token_get_sock(net, token_val); 585 if (!msk) { 586 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 587 return ret; 588 } 589 590 sk = (struct sock *)msk; 591 592 if (!mptcp_pm_is_userspace(msk)) { 593 GENL_SET_ERR_MSG(info, "userspace PM not selected"); 594 goto set_flags_err; 595 } 596 597 ret = mptcp_pm_parse_entry(attr, info, false, &loc); 598 if (ret < 0) 599 goto set_flags_err; 600 601 if (attr_rem) { 602 ret = mptcp_pm_parse_entry(attr_rem, info, false, &rem); 603 if (ret < 0) 604 goto set_flags_err; 605 } 606 607 if (loc.addr.family == AF_UNSPEC || 608 rem.addr.family == AF_UNSPEC) { 609 GENL_SET_ERR_MSG(info, "invalid address families"); 610 ret = -EINVAL; 611 goto set_flags_err; 612 } 613 614 if (loc.flags & MPTCP_PM_ADDR_FLAG_BACKUP) 615 bkup = 1; 616 617 lock_sock(sk); 618 ret = mptcp_pm_nl_mp_prio_send_ack(msk, &loc.addr, &rem.addr, bkup); 619 release_sock(sk); 620 621 set_flags_err: 622 sock_put(sk); 623 return ret; 624 } 625 626 int mptcp_userspace_pm_dump_addr(struct sk_buff *msg, 627 struct netlink_callback *cb) 628 { 629 struct id_bitmap { 630 DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1); 631 } *bitmap; 632 const struct genl_info *info = genl_info_dump(cb); 633 struct net *net = sock_net(msg->sk); 634 struct mptcp_pm_addr_entry *entry; 635 struct mptcp_sock *msk; 636 struct nlattr *token; 637 int ret = -EINVAL; 638 struct sock *sk; 639 void *hdr; 640 641 bitmap = (struct id_bitmap *)cb->ctx; 642 token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 643 644 msk = mptcp_token_get_sock(net, nla_get_u32(token)); 645 if (!msk) { 646 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 647 return ret; 648 } 649 650 sk = (struct sock *)msk; 651 652 if (!mptcp_pm_is_userspace(msk)) { 653 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 654 goto out; 655 } 656 657 lock_sock(sk); 658 spin_lock_bh(&msk->pm.lock); 659 list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { 660 if (test_bit(entry->addr.id, bitmap->map)) 661 continue; 662 663 hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid, 664 cb->nlh->nlmsg_seq, &mptcp_genl_family, 665 NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR); 666 if (!hdr) 667 break; 668 669 if (mptcp_nl_fill_addr(msg, entry) < 0) { 670 genlmsg_cancel(msg, hdr); 671 break; 672 } 673 674 __set_bit(entry->addr.id, bitmap->map); 675 genlmsg_end(msg, hdr); 676 } 677 spin_unlock_bh(&msk->pm.lock); 678 release_sock(sk); 679 ret = msg->len; 680 681 out: 682 sock_put(sk); 683 return ret; 684 } 685 686 int mptcp_userspace_pm_get_addr(struct sk_buff *skb, 687 struct genl_info *info) 688 { 689 struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR]; 690 struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN]; 691 struct mptcp_pm_addr_entry addr, *entry; 692 struct net *net = sock_net(skb->sk); 693 struct mptcp_sock *msk; 694 struct sk_buff *msg; 695 int ret = -EINVAL; 696 struct sock *sk; 697 void *reply; 698 699 msk = mptcp_token_get_sock(net, nla_get_u32(token)); 700 if (!msk) { 701 NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token"); 702 return ret; 703 } 704 705 sk = (struct sock *)msk; 706 707 if (!mptcp_pm_is_userspace(msk)) { 708 GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected"); 709 goto out; 710 } 711 712 ret = mptcp_pm_parse_entry(attr, info, false, &addr); 713 if (ret < 0) 714 goto out; 715 716 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 717 if (!msg) { 718 ret = -ENOMEM; 719 goto out; 720 } 721 722 reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0, 723 info->genlhdr->cmd); 724 if (!reply) { 725 GENL_SET_ERR_MSG(info, "not enough space in Netlink message"); 726 ret = -EMSGSIZE; 727 goto fail; 728 } 729 730 lock_sock(sk); 731 spin_lock_bh(&msk->pm.lock); 732 entry = mptcp_userspace_pm_lookup_addr_by_id(msk, addr.addr.id); 733 if (!entry) { 734 GENL_SET_ERR_MSG(info, "address not found"); 735 ret = -EINVAL; 736 goto unlock_fail; 737 } 738 739 ret = mptcp_nl_fill_addr(msg, entry); 740 if (ret) 741 goto unlock_fail; 742 743 genlmsg_end(msg, reply); 744 ret = genlmsg_reply(msg, info); 745 spin_unlock_bh(&msk->pm.lock); 746 release_sock(sk); 747 sock_put(sk); 748 return ret; 749 750 unlock_fail: 751 spin_unlock_bh(&msk->pm.lock); 752 release_sock(sk); 753 fail: 754 nlmsg_free(msg); 755 out: 756 sock_put(sk); 757 return ret; 758 } 759
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.