aboutsummaryrefslogtreecommitdiff
path: root/networking/libiproute/iproute.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/libiproute/iproute.c')
-rw-r--r--networking/libiproute/iproute.c236
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
325static 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 */
326static int iproute_modify(int cmd, unsigned flags, char **argv) 331static 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,
337IF_FEATURE_IP_RULE(ARG_table,) 352IF_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)
912int FAST_FUNC do_iproute(char **argv) 1089int 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}