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 | { |