diff options
| -rw-r--r-- | networking/libiproute/iplink.c | 190 |
1 files changed, 188 insertions, 2 deletions
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 506fb3c7e..5c27c2de3 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c | |||
| @@ -46,6 +46,12 @@ struct ifla_vlan_flags { | |||
| 46 | /* taken from linux/sockios.h */ | 46 | /* taken from linux/sockios.h */ |
| 47 | #define SIOCSIFNAME 0x8923 /* set interface name */ | 47 | #define SIOCSIFNAME 0x8923 /* set interface name */ |
| 48 | 48 | ||
| 49 | #if 0 | ||
| 50 | # define dbg(...) bb_error_msg(__VA_ARGS__) | ||
| 51 | #else | ||
| 52 | # define dbg(...) ((void)0) | ||
| 53 | #endif | ||
| 54 | |||
| 49 | /* Exits on error */ | 55 | /* Exits on error */ |
| 50 | static int get_ctl_fd(void) | 56 | static int get_ctl_fd(void) |
| 51 | { | 57 | { |
| @@ -401,12 +407,13 @@ static void vlan_parse_opt(char **argv, struct nlmsghdr *n, unsigned int size) | |||
| 401 | static int do_add_or_delete(char **argv, const unsigned rtm) | 407 | static int do_add_or_delete(char **argv, const unsigned rtm) |
| 402 | { | 408 | { |
| 403 | static const char keywords[] ALIGN1 = | 409 | static const char keywords[] ALIGN1 = |
| 404 | "link\0""name\0""type\0""dev\0"; | 410 | "link\0""name\0""type\0""dev\0""address\0"; |
| 405 | enum { | 411 | enum { |
| 406 | ARG_link, | 412 | ARG_link, |
| 407 | ARG_name, | 413 | ARG_name, |
| 408 | ARG_type, | 414 | ARG_type, |
| 409 | ARG_dev, | 415 | ARG_dev, |
| 416 | ARG_address, | ||
| 410 | }; | 417 | }; |
| 411 | struct rtnl_handle rth; | 418 | struct rtnl_handle rth; |
| 412 | struct { | 419 | struct { |
| @@ -415,7 +422,11 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
| 415 | char buf[1024]; | 422 | char buf[1024]; |
| 416 | } req; | 423 | } req; |
| 417 | smalluint arg; | 424 | smalluint arg; |
| 418 | char *name_str = NULL, *link_str = NULL, *type_str = NULL, *dev_str = NULL; | 425 | char *name_str = NULL; |
| 426 | char *link_str = NULL; | ||
| 427 | char *type_str = NULL; | ||
| 428 | char *dev_str = NULL; | ||
| 429 | char *address_str = NULL; | ||
| 419 | 430 | ||
| 420 | memset(&req, 0, sizeof(req)); | 431 | memset(&req, 0, sizeof(req)); |
| 421 | 432 | ||
| @@ -431,14 +442,21 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
| 431 | if (arg == ARG_type) { | 442 | if (arg == ARG_type) { |
| 432 | NEXT_ARG(); | 443 | NEXT_ARG(); |
| 433 | type_str = *argv++; | 444 | type_str = *argv++; |
| 445 | dbg("type_str:'%s'", type_str); | ||
| 434 | break; | 446 | break; |
| 435 | } | 447 | } |
| 436 | if (arg == ARG_link) { | 448 | if (arg == ARG_link) { |
| 437 | NEXT_ARG(); | 449 | NEXT_ARG(); |
| 438 | link_str = *argv; | 450 | link_str = *argv; |
| 451 | dbg("link_str:'%s'", link_str); | ||
| 439 | } else if (arg == ARG_name) { | 452 | } else if (arg == ARG_name) { |
| 440 | NEXT_ARG(); | 453 | NEXT_ARG(); |
| 441 | name_str = *argv; | 454 | name_str = *argv; |
| 455 | dbg("name_str:'%s'", name_str); | ||
| 456 | } else if (arg == ARG_address) { | ||
| 457 | NEXT_ARG(); | ||
| 458 | address_str = *argv; | ||
| 459 | dbg("address_str:'%s'", name_str); | ||
| 442 | } else { | 460 | } else { |
| 443 | if (arg == ARG_dev) { | 461 | if (arg == ARG_dev) { |
| 444 | if (dev_str) | 462 | if (dev_str) |
| @@ -446,6 +464,7 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
| 446 | NEXT_ARG(); | 464 | NEXT_ARG(); |
| 447 | } | 465 | } |
| 448 | dev_str = *argv; | 466 | dev_str = *argv; |
| 467 | dbg("dev_str:'%s'", dev_str); | ||
| 449 | } | 468 | } |
| 450 | argv++; | 469 | argv++; |
| 451 | } | 470 | } |
| @@ -481,6 +500,14 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
| 481 | int idx = xll_name_to_index(link_str); | 500 | int idx = xll_name_to_index(link_str); |
| 482 | addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4); | 501 | addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4); |
| 483 | } | 502 | } |
| 503 | if (address_str) { | ||
| 504 | unsigned char abuf[32]; | ||
| 505 | int len = ll_addr_a2n(abuf, sizeof(abuf), address_str); | ||
| 506 | dbg("address len:%d", len); | ||
| 507 | if (len < 0) | ||
| 508 | return -1; | ||
| 509 | addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len); | ||
| 510 | } | ||
| 484 | } | 511 | } |
| 485 | if (name_str) { | 512 | if (name_str) { |
| 486 | const size_t name_len = strlen(name_str) + 1; | 513 | const size_t name_len = strlen(name_str) + 1; |
| @@ -493,6 +520,165 @@ static int do_add_or_delete(char **argv, const unsigned rtm) | |||
| 493 | return 0; | 520 | return 0; |
| 494 | } | 521 | } |
| 495 | 522 | ||
| 523 | /* Other keywords recognized by iproute2-3.12.0: */ | ||
| 524 | #if 0 | ||
| 525 | } else if (matches(*argv, "broadcast") == 0 || | ||
| 526 | strcmp(*argv, "brd") == 0) { | ||
| 527 | NEXT_ARG(); | ||
| 528 | len = ll_addr_a2n(abuf, sizeof(abuf), *argv); | ||
| 529 | if (len < 0) | ||
| 530 | return -1; | ||
| 531 | addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len); | ||
| 532 | } else if (matches(*argv, "txqueuelen") == 0 || | ||
| 533 | strcmp(*argv, "qlen") == 0 || | ||
| 534 | matches(*argv, "txqlen") == 0) { | ||
| 535 | NEXT_ARG(); | ||
| 536 | if (qlen != -1) | ||
| 537 | duparg("txqueuelen", *argv); | ||
| 538 | if (get_integer(&qlen, *argv, 0)) | ||
| 539 | invarg("Invalid \"txqueuelen\" value\n", *argv); | ||
| 540 | addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4); | ||
| 541 | } else if (strcmp(*argv, "mtu") == 0) { | ||
| 542 | NEXT_ARG(); | ||
| 543 | if (mtu != -1) | ||
| 544 | duparg("mtu", *argv); | ||
| 545 | if (get_integer(&mtu, *argv, 0)) | ||
| 546 | invarg("Invalid \"mtu\" value\n", *argv); | ||
| 547 | addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); | ||
| 548 | } else if (strcmp(*argv, "netns") == 0) { | ||
| 549 | NEXT_ARG(); | ||
| 550 | if (netns != -1) | ||
| 551 | duparg("netns", *argv); | ||
| 552 | if ((netns = get_netns_fd(*argv)) >= 0) | ||
| 553 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); | ||
| 554 | else if (get_integer(&netns, *argv, 0) == 0) | ||
| 555 | addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); | ||
| 556 | else | ||
| 557 | invarg("Invalid \"netns\" value\n", *argv); | ||
| 558 | } else if (strcmp(*argv, "multicast") == 0) { | ||
| 559 | NEXT_ARG(); | ||
| 560 | req->i.ifi_change |= IFF_MULTICAST; | ||
| 561 | if (strcmp(*argv, "on") == 0) { | ||
| 562 | req->i.ifi_flags |= IFF_MULTICAST; | ||
| 563 | } else if (strcmp(*argv, "off") == 0) { | ||
| 564 | req->i.ifi_flags &= ~IFF_MULTICAST; | ||
| 565 | } else | ||
| 566 | return on_off("multicast", *argv); | ||
| 567 | } else if (strcmp(*argv, "allmulticast") == 0) { | ||
| 568 | NEXT_ARG(); | ||
| 569 | req->i.ifi_change |= IFF_ALLMULTI; | ||
| 570 | if (strcmp(*argv, "on") == 0) { | ||
| 571 | req->i.ifi_flags |= IFF_ALLMULTI; | ||
| 572 | } else if (strcmp(*argv, "off") == 0) { | ||
| 573 | req->i.ifi_flags &= ~IFF_ALLMULTI; | ||
| 574 | } else | ||
| 575 | return on_off("allmulticast", *argv); | ||
| 576 | } else if (strcmp(*argv, "promisc") == 0) { | ||
| 577 | NEXT_ARG(); | ||
| 578 | req->i.ifi_change |= IFF_PROMISC; | ||
| 579 | if (strcmp(*argv, "on") == 0) { | ||
| 580 | req->i.ifi_flags |= IFF_PROMISC; | ||
| 581 | } else if (strcmp(*argv, "off") == 0) { | ||
| 582 | req->i.ifi_flags &= ~IFF_PROMISC; | ||
| 583 | } else | ||
| 584 | return on_off("promisc", *argv); | ||
| 585 | } else if (strcmp(*argv, "trailers") == 0) { | ||
| 586 | NEXT_ARG(); | ||
| 587 | req->i.ifi_change |= IFF_NOTRAILERS; | ||
| 588 | if (strcmp(*argv, "off") == 0) { | ||
| 589 | req->i.ifi_flags |= IFF_NOTRAILERS; | ||
| 590 | } else if (strcmp(*argv, "on") == 0) { | ||
| 591 | req->i.ifi_flags &= ~IFF_NOTRAILERS; | ||
| 592 | } else | ||
| 593 | return on_off("trailers", *argv); | ||
| 594 | } else if (strcmp(*argv, "arp") == 0) { | ||
| 595 | NEXT_ARG(); | ||
| 596 | req->i.ifi_change |= IFF_NOARP; | ||
| 597 | if (strcmp(*argv, "on") == 0) { | ||
| 598 | req->i.ifi_flags &= ~IFF_NOARP; | ||
| 599 | } else if (strcmp(*argv, "off") == 0) { | ||
| 600 | req->i.ifi_flags |= IFF_NOARP; | ||
| 601 | } else | ||
| 602 | return on_off("noarp", *argv); | ||
| 603 | } else if (strcmp(*argv, "vf") == 0) { | ||
| 604 | struct rtattr *vflist; | ||
| 605 | NEXT_ARG(); | ||
| 606 | if (get_integer(&vf, *argv, 0)) { | ||
| 607 | invarg("Invalid \"vf\" value\n", *argv); | ||
| 608 | } | ||
| 609 | vflist = addattr_nest(&req->n, sizeof(*req), | ||
| 610 | IFLA_VFINFO_LIST); | ||
| 611 | len = iplink_parse_vf(vf, &argc, &argv, req); | ||
| 612 | if (len < 0) | ||
| 613 | return -1; | ||
| 614 | addattr_nest_end(&req->n, vflist); | ||
| 615 | } else if (matches(*argv, "master") == 0) { | ||
| 616 | int ifindex; | ||
| 617 | NEXT_ARG(); | ||
| 618 | ifindex = ll_name_to_index(*argv); | ||
| 619 | if (!ifindex) | ||
| 620 | invarg("Device does not exist\n", *argv); | ||
| 621 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
| 622 | &ifindex, 4); | ||
| 623 | } else if (matches(*argv, "nomaster") == 0) { | ||
| 624 | int ifindex = 0; | ||
| 625 | addattr_l(&req->n, sizeof(*req), IFLA_MASTER, | ||
| 626 | &ifindex, 4); | ||
| 627 | } else if (matches(*argv, "dynamic") == 0) { | ||
| 628 | NEXT_ARG(); | ||
| 629 | req->i.ifi_change |= IFF_DYNAMIC; | ||
| 630 | if (strcmp(*argv, "on") == 0) { | ||
| 631 | req->i.ifi_flags |= IFF_DYNAMIC; | ||
| 632 | } else if (strcmp(*argv, "off") == 0) { | ||
| 633 | req->i.ifi_flags &= ~IFF_DYNAMIC; | ||
| 634 | } else | ||
| 635 | return on_off("dynamic", *argv); | ||
| 636 | } else if (matches(*argv, "alias") == 0) { | ||
| 637 | NEXT_ARG(); | ||
| 638 | addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, | ||
| 639 | *argv, strlen(*argv)); | ||
| 640 | argc--; argv++; | ||
| 641 | break; | ||
| 642 | } else if (strcmp(*argv, "group") == 0) { | ||
| 643 | NEXT_ARG(); | ||
| 644 | if (*group != -1) | ||
| 645 | duparg("group", *argv); | ||
| 646 | if (rtnl_group_a2n(group, *argv)) | ||
| 647 | invarg("Invalid \"group\" value\n", *argv); | ||
| 648 | } else if (strcmp(*argv, "mode") == 0) { | ||
| 649 | int mode; | ||
| 650 | NEXT_ARG(); | ||
| 651 | mode = get_link_mode(*argv); | ||
| 652 | if (mode < 0) | ||
| 653 | invarg("Invalid link mode\n", *argv); | ||
| 654 | addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode); | ||
| 655 | } else if (strcmp(*argv, "state") == 0) { | ||
| 656 | int state; | ||
| 657 | NEXT_ARG(); | ||
| 658 | state = get_operstate(*argv); | ||
| 659 | if (state < 0) | ||
| 660 | invarg("Invalid operstate\n", *argv); | ||
| 661 | |||
| 662 | addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state); | ||
| 663 | } else if (matches(*argv, "numtxqueues") == 0) { | ||
| 664 | NEXT_ARG(); | ||
| 665 | if (numtxqueues != -1) | ||
| 666 | duparg("numtxqueues", *argv); | ||
| 667 | if (get_integer(&numtxqueues, *argv, 0)) | ||
| 668 | invarg("Invalid \"numtxqueues\" value\n", *argv); | ||
| 669 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES, | ||
| 670 | &numtxqueues, 4); | ||
| 671 | } else if (matches(*argv, "numrxqueues") == 0) { | ||
| 672 | NEXT_ARG(); | ||
| 673 | if (numrxqueues != -1) | ||
| 674 | duparg("numrxqueues", *argv); | ||
| 675 | if (get_integer(&numrxqueues, *argv, 0)) | ||
| 676 | invarg("Invalid \"numrxqueues\" value\n", *argv); | ||
| 677 | addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, | ||
| 678 | &numrxqueues, 4); | ||
| 679 | } | ||
| 680 | #endif | ||
| 681 | |||
| 496 | /* Return value becomes exitcode. It's okay to not return at all */ | 682 | /* Return value becomes exitcode. It's okay to not return at all */ |
| 497 | int FAST_FUNC do_iplink(char **argv) | 683 | int FAST_FUNC do_iplink(char **argv) |
| 498 | { | 684 | { |
