diff options
Diffstat (limited to 'networking/libiproute/iproute.c')
-rw-r--r-- | networking/libiproute/iproute.c | 236 |
1 files changed, 210 insertions, 26 deletions
diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 0f2b89682..cc3443a92 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c | |||
@@ -322,16 +322,31 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |||
322 | return 0; | 322 | return 0; |
323 | } | 323 | } |
324 | 324 | ||
325 | static int str_is_lock(const char *str) | ||
326 | { | ||
327 | return strcmp(str, "lock") == 0; | ||
328 | } | ||
329 | |||
325 | /* Return value becomes exitcode. It's okay to not return at all */ | 330 | /* Return value becomes exitcode. It's okay to not return at all */ |
326 | static int iproute_modify(int cmd, unsigned flags, char **argv) | 331 | static int iproute_modify(int cmd, unsigned flags, char **argv) |
327 | { | 332 | { |
333 | /* If you add stuff here, update iproute_full_usage */ | ||
328 | static const char keywords[] ALIGN1 = | 334 | static const char keywords[] ALIGN1 = |
329 | "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0") | 335 | "src\0""via\0" |
336 | "mtu\0""advmss\0" | ||
337 | "scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0") | ||
330 | "dev\0""oif\0""to\0""metric\0""onlink\0"; | 338 | "dev\0""oif\0""to\0""metric\0""onlink\0"; |
339 | #define keyword_via (keywords + sizeof("src")) | ||
340 | #define keyword_mtu (keyword_via + sizeof("via")) | ||
341 | #define keyword_advmss (keyword_mtu + sizeof("mtu")) | ||
342 | #define keyword_scope (keyword_advmss + sizeof("advmss")) | ||
343 | #define keyword_proto (keyword_scope + sizeof("scope")) | ||
344 | #define keyword_table (keyword_proto + sizeof("protocol")) | ||
331 | enum { | 345 | enum { |
332 | ARG_src, | 346 | ARG_src, |
333 | ARG_via, | 347 | ARG_via, |
334 | ARG_mtu, PARM_lock, | 348 | ARG_mtu, |
349 | ARG_advmss, | ||
335 | ARG_scope, | 350 | ARG_scope, |
336 | ARG_protocol, | 351 | ARG_protocol, |
337 | IF_FEATURE_IP_RULE(ARG_table,) | 352 | IF_FEATURE_IP_RULE(ARG_table,) |
@@ -404,24 +419,33 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
404 | } else if (arg == ARG_mtu) { | 419 | } else if (arg == ARG_mtu) { |
405 | unsigned mtu; | 420 | unsigned mtu; |
406 | NEXT_ARG(); | 421 | NEXT_ARG(); |
407 | if (index_in_strings(keywords, *argv) == PARM_lock) { | 422 | if (str_is_lock(*argv)) { |
408 | mxlock |= (1 << RTAX_MTU); | 423 | mxlock |= (1 << RTAX_MTU); |
409 | NEXT_ARG(); | 424 | NEXT_ARG(); |
410 | } | 425 | } |
411 | mtu = get_unsigned(*argv, "mtu"); | 426 | mtu = get_unsigned(*argv, keyword_mtu); |
412 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); | 427 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_MTU, mtu); |
428 | } else if (arg == ARG_advmss) { | ||
429 | unsigned mss; | ||
430 | NEXT_ARG(); | ||
431 | if (str_is_lock(*argv)) { | ||
432 | mxlock |= (1 << RTAX_ADVMSS); | ||
433 | NEXT_ARG(); | ||
434 | } | ||
435 | mss = get_unsigned(*argv, keyword_advmss); | ||
436 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss); | ||
413 | } else if (arg == ARG_scope) { | 437 | } else if (arg == ARG_scope) { |
414 | uint32_t scope; | 438 | uint32_t scope; |
415 | NEXT_ARG(); | 439 | NEXT_ARG(); |
416 | if (rtnl_rtscope_a2n(&scope, *argv)) | 440 | if (rtnl_rtscope_a2n(&scope, *argv)) |
417 | invarg_1_to_2(*argv, "scope"); | 441 | invarg_1_to_2(*argv, keyword_scope); |
418 | req.r.rtm_scope = scope; | 442 | req.r.rtm_scope = scope; |
419 | scope_ok = 1; | 443 | scope_ok = 1; |
420 | } else if (arg == ARG_protocol) { | 444 | } else if (arg == ARG_protocol) { |
421 | uint32_t prot; | 445 | uint32_t prot; |
422 | NEXT_ARG(); | 446 | NEXT_ARG(); |
423 | if (rtnl_rtprot_a2n(&prot, *argv)) | 447 | if (rtnl_rtprot_a2n(&prot, *argv)) |
424 | invarg_1_to_2(*argv, "protocol"); | 448 | invarg_1_to_2(*argv, keyword_proto); |
425 | req.r.rtm_protocol = prot; | 449 | req.r.rtm_protocol = prot; |
426 | ok |= proto_ok; | 450 | ok |= proto_ok; |
427 | #if ENABLE_FEATURE_IP_RULE | 451 | #if ENABLE_FEATURE_IP_RULE |
@@ -429,7 +453,7 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
429 | uint32_t tid; | 453 | uint32_t tid; |
430 | NEXT_ARG(); | 454 | NEXT_ARG(); |
431 | if (rtnl_rttable_a2n(&tid, *argv)) | 455 | if (rtnl_rttable_a2n(&tid, *argv)) |
432 | invarg_1_to_2(*argv, "table"); | 456 | invarg_1_to_2(*argv, keyword_table); |
433 | if (tid < 256) | 457 | if (tid < 256) |
434 | req.r.rtm_table = tid; | 458 | req.r.rtm_table = tid; |
435 | else { | 459 | else { |
@@ -441,6 +465,7 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
441 | NEXT_ARG(); | 465 | NEXT_ARG(); |
442 | d = *argv; | 466 | d = *argv; |
443 | } else if (arg == ARG_metric) { | 467 | } else if (arg == ARG_metric) { |
468 | //TODO: "metric", "priority" and "preference" are synonyms | ||
444 | uint32_t metric; | 469 | uint32_t metric; |
445 | NEXT_ARG(); | 470 | NEXT_ARG(); |
446 | metric = get_u32(*argv, "metric"); | 471 | metric = get_u32(*argv, "metric"); |
@@ -475,6 +500,158 @@ IF_FEATURE_IP_RULE(ARG_table,) | |||
475 | addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); | 500 | addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); |
476 | } | 501 | } |
477 | } | 502 | } |
503 | /* Other keywords recognized by iproute2-3.19.0: */ | ||
504 | #if 0 | ||
505 | } else if (strcmp(*argv, "from") == 0) { | ||
506 | inet_prefix addr; | ||
507 | NEXT_ARG(); | ||
508 | get_prefix(&addr, *argv, req.r.rtm_family); | ||
509 | if (req.r.rtm_family == AF_UNSPEC) | ||
510 | req.r.rtm_family = addr.family; | ||
511 | if (addr.bytelen) | ||
512 | addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); | ||
513 | req.r.rtm_src_len = addr.bitlen; | ||
514 | } else if (strcmp(*argv, "tos") == 0 || | ||
515 | matches(*argv, "dsfield") == 0) { | ||
516 | __u32 tos; | ||
517 | NEXT_ARG(); | ||
518 | if (rtnl_dsfield_a2n(&tos, *argv)) | ||
519 | invarg("\"tos\" value is invalid\n", *argv); | ||
520 | req.r.rtm_tos = tos; | ||
521 | } else if (strcmp(*argv, "hoplimit") == 0) { | ||
522 | unsigned hoplimit; | ||
523 | NEXT_ARG(); | ||
524 | if (strcmp(*argv, "lock") == 0) { | ||
525 | mxlock |= (1<<RTAX_HOPLIMIT); | ||
526 | NEXT_ARG(); | ||
527 | } | ||
528 | if (get_unsigned(&hoplimit, *argv, 0)) | ||
529 | invarg("\"hoplimit\" value is invalid\n", *argv); | ||
530 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit); | ||
531 | } else if (matches(*argv, "reordering") == 0) { | ||
532 | unsigned reord; | ||
533 | NEXT_ARG(); | ||
534 | if (strcmp(*argv, "lock") == 0) { | ||
535 | mxlock |= (1<<RTAX_REORDERING); | ||
536 | NEXT_ARG(); | ||
537 | } | ||
538 | if (get_unsigned(&reord, *argv, 0)) | ||
539 | invarg("\"reordering\" value is invalid\n", *argv); | ||
540 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord); | ||
541 | } else if (strcmp(*argv, "rtt") == 0) { | ||
542 | unsigned rtt; | ||
543 | NEXT_ARG(); | ||
544 | if (strcmp(*argv, "lock") == 0) { | ||
545 | mxlock |= (1<<RTAX_RTT); | ||
546 | NEXT_ARG(); | ||
547 | } | ||
548 | if (get_time_rtt(&rtt, *argv, &raw)) | ||
549 | invarg("\"rtt\" value is invalid\n", *argv); | ||
550 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, | ||
551 | (raw) ? rtt : rtt * 8); | ||
552 | } else if (strcmp(*argv, "rto_min") == 0) { | ||
553 | unsigned rto_min; | ||
554 | NEXT_ARG(); | ||
555 | mxlock |= (1<<RTAX_RTO_MIN); | ||
556 | if (get_time_rtt(&rto_min, *argv, &raw)) | ||
557 | invarg("\"rto_min\" value is invalid\n", | ||
558 | *argv); | ||
559 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN, | ||
560 | rto_min); | ||
561 | } else if (matches(*argv, "window") == 0) { | ||
562 | unsigned win; | ||
563 | NEXT_ARG(); | ||
564 | if (strcmp(*argv, "lock") == 0) { | ||
565 | mxlock |= (1<<RTAX_WINDOW); | ||
566 | NEXT_ARG(); | ||
567 | } | ||
568 | if (get_unsigned(&win, *argv, 0)) | ||
569 | invarg("\"window\" value is invalid\n", *argv); | ||
570 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win); | ||
571 | } else if (matches(*argv, "cwnd") == 0) { | ||
572 | unsigned win; | ||
573 | NEXT_ARG(); | ||
574 | if (strcmp(*argv, "lock") == 0) { | ||
575 | mxlock |= (1<<RTAX_CWND); | ||
576 | NEXT_ARG(); | ||
577 | } | ||
578 | if (get_unsigned(&win, *argv, 0)) | ||
579 | invarg("\"cwnd\" value is invalid\n", *argv); | ||
580 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win); | ||
581 | } else if (matches(*argv, "initcwnd") == 0) { | ||
582 | unsigned win; | ||
583 | NEXT_ARG(); | ||
584 | if (strcmp(*argv, "lock") == 0) { | ||
585 | mxlock |= (1<<RTAX_INITCWND); | ||
586 | NEXT_ARG(); | ||
587 | } | ||
588 | if (get_unsigned(&win, *argv, 0)) | ||
589 | invarg("\"initcwnd\" value is invalid\n", *argv); | ||
590 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, win); | ||
591 | } else if (matches(*argv, "initrwnd") == 0) { | ||
592 | unsigned win; | ||
593 | NEXT_ARG(); | ||
594 | if (strcmp(*argv, "lock") == 0) { | ||
595 | mxlock |= (1<<RTAX_INITRWND); | ||
596 | NEXT_ARG(); | ||
597 | } | ||
598 | if (get_unsigned(&win, *argv, 0)) | ||
599 | invarg("\"initrwnd\" value is invalid\n", *argv); | ||
600 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); | ||
601 | } else if (matches(*argv, "features") == 0) { | ||
602 | unsigned int features = 0; | ||
603 | |||
604 | while (argc > 0) { | ||
605 | NEXT_ARG(); | ||
606 | |||
607 | if (strcmp(*argv, "ecn") == 0) | ||
608 | features |= RTAX_FEATURE_ECN; | ||
609 | else | ||
610 | invarg("\"features\" value not valid\n", *argv); | ||
611 | break; | ||
612 | } | ||
613 | |||
614 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features); | ||
615 | } else if (matches(*argv, "quickack") == 0) { | ||
616 | unsigned quickack; | ||
617 | NEXT_ARG(); | ||
618 | if (get_unsigned(&quickack, *argv, 0)) | ||
619 | invarg("\"quickack\" value is invalid\n", *argv); | ||
620 | if (quickack != 1 && quickack != 0) | ||
621 | invarg("\"quickack\" value should be 0 or 1\n", *argv); | ||
622 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack); | ||
623 | } else if (matches(*argv, "rttvar") == 0) { | ||
624 | unsigned win; | ||
625 | NEXT_ARG(); | ||
626 | if (strcmp(*argv, "lock") == 0) { | ||
627 | mxlock |= (1<<RTAX_RTTVAR); | ||
628 | NEXT_ARG(); | ||
629 | } | ||
630 | if (get_time_rtt(&win, *argv, &raw)) | ||
631 | invarg("\"rttvar\" value is invalid\n", *argv); | ||
632 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR, | ||
633 | (raw) ? win : win * 4); | ||
634 | } else if (matches(*argv, "ssthresh") == 0) { | ||
635 | unsigned win; | ||
636 | NEXT_ARG(); | ||
637 | if (strcmp(*argv, "lock") == 0) { | ||
638 | mxlock |= (1<<RTAX_SSTHRESH); | ||
639 | NEXT_ARG(); | ||
640 | } | ||
641 | if (get_unsigned(&win, *argv, 0)) | ||
642 | invarg("\"ssthresh\" value is invalid\n", *argv); | ||
643 | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win); | ||
644 | } else if (matches(*argv, "realms") == 0) { | ||
645 | __u32 realm; | ||
646 | NEXT_ARG(); | ||
647 | if (get_rt_realms(&realm, *argv)) | ||
648 | invarg("\"realm\" value is invalid\n", *argv); | ||
649 | addattr32(&req.n, sizeof(req), RTA_FLOW, realm); | ||
650 | } else if (strcmp(*argv, "nexthop") == 0) { | ||
651 | nhs_ok = 1; | ||
652 | break; | ||
653 | } | ||
654 | #endif | ||
478 | argv++; | 655 | argv++; |
479 | } | 656 | } |
480 | 657 | ||
@@ -912,9 +1089,15 @@ static int iproute_get(char **argv) | |||
912 | int FAST_FUNC do_iproute(char **argv) | 1089 | int FAST_FUNC do_iproute(char **argv) |
913 | { | 1090 | { |
914 | static const char ip_route_commands[] ALIGN1 = | 1091 | static const char ip_route_commands[] ALIGN1 = |
915 | /*0-3*/ "add\0""append\0""change\0""chg\0" | 1092 | "a\0""add\0""append\0""change\0""chg\0" |
916 | /*4-7*/ "delete\0""get\0""list\0""show\0" | 1093 | "delete\0""get\0""list\0""show\0" |
917 | /*8..*/ "prepend\0""replace\0""test\0""flush\0"; | 1094 | "prepend\0""replace\0""test\0""flush\0" |
1095 | ; | ||
1096 | enum { | ||
1097 | CMD_a = 0, CMD_add, CMD_append, CMD_change, CMD_chg, | ||
1098 | CMD_delete, CMD_get, CMD_list, CMD_show, | ||
1099 | CMD_prepend, CMD_replace, CMD_test, CMD_flush, | ||
1100 | }; | ||
918 | int command_num; | 1101 | int command_num; |
919 | unsigned flags = 0; | 1102 | unsigned flags = 0; |
920 | int cmd = RTM_NEWROUTE; | 1103 | int cmd = RTM_NEWROUTE; |
@@ -929,38 +1112,39 @@ int FAST_FUNC do_iproute(char **argv) | |||
929 | command_num = index_in_substrings(ip_route_commands, *argv); | 1112 | command_num = index_in_substrings(ip_route_commands, *argv); |
930 | 1113 | ||
931 | switch (command_num) { | 1114 | switch (command_num) { |
932 | case 0: /* add */ | 1115 | case CMD_a: |
1116 | case CMD_add: | ||
933 | flags = NLM_F_CREATE|NLM_F_EXCL; | 1117 | flags = NLM_F_CREATE|NLM_F_EXCL; |
934 | break; | 1118 | break; |
935 | case 1: /* append */ | 1119 | case CMD_append: |
936 | flags = NLM_F_CREATE|NLM_F_APPEND; | 1120 | flags = NLM_F_CREATE|NLM_F_APPEND; |
937 | break; | 1121 | break; |
938 | case 2: /* change */ | 1122 | case CMD_change: |
939 | case 3: /* chg */ | 1123 | case CMD_chg: |
940 | flags = NLM_F_REPLACE; | 1124 | flags = NLM_F_REPLACE; |
941 | break; | 1125 | break; |
942 | case 4: /* delete */ | 1126 | case CMD_delete: |
943 | cmd = RTM_DELROUTE; | 1127 | cmd = RTM_DELROUTE; |
944 | break; | 1128 | break; |
945 | case 5: /* get */ | 1129 | case CMD_get: |
946 | return iproute_get(argv+1); | 1130 | return iproute_get(argv + 1); |
947 | case 6: /* list */ | 1131 | case CMD_list: |
948 | case 7: /* show */ | 1132 | case CMD_show: |
949 | return iproute_list_or_flush(argv+1, 0); | 1133 | return iproute_list_or_flush(argv + 1, 0); |
950 | case 8: /* prepend */ | 1134 | case CMD_prepend: |
951 | flags = NLM_F_CREATE; | 1135 | flags = NLM_F_CREATE; |
952 | break; | 1136 | break; |
953 | case 9: /* replace */ | 1137 | case CMD_replace: |
954 | flags = NLM_F_CREATE|NLM_F_REPLACE; | 1138 | flags = NLM_F_CREATE|NLM_F_REPLACE; |
955 | break; | 1139 | break; |
956 | case 10: /* test */ | 1140 | case CMD_test: |
957 | flags = NLM_F_EXCL; | 1141 | flags = NLM_F_EXCL; |
958 | break; | 1142 | break; |
959 | case 11: /* flush */ | 1143 | case CMD_flush: |
960 | return iproute_list_or_flush(argv+1, 1); | 1144 | return iproute_list_or_flush(argv + 1, 1); |
961 | default: | 1145 | default: |
962 | invarg_1_to_2(*argv, applet_name); | 1146 | invarg_1_to_2(*argv, applet_name); |
963 | } | 1147 | } |
964 | 1148 | ||
965 | return iproute_modify(cmd, flags, argv+1); | 1149 | return iproute_modify(cmd, flags, argv + 1); |
966 | } | 1150 | } |