iproute: update help text, add commented-out code for unsupported options
No binary (build failed)
—
(log yok)
| @@ -162,11 +162,42 @@ | |
| //usage: "list|flush|add|del|change|append|replace|test ROUTE" | |
| //usage:#define iproute_full_usage "\n\n" | |
| //usage: "iproute list|flush SELECTOR\n" | |
| - | //usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n" |
| - | //usage: " [oif STRING] [tos TOS]\n" |
| - | //usage: "iproute add|del|change|append|replace|test ROUTE\n" |
| //usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" | |
| - | //usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" |
| + | //usage: " PREFIX := default|ADDRESS/MASK\n" |
| + | //usage: "iproute get ADDRESS [from ADDRESS iif IFACE]\n" |
| + | //usage: " [oif IFACE] [tos TOS]\n" |
| + | //usage: "iproute add|del|change|append|replace|test ROUTE\n" |
| + | //usage: " ROUTE := NODE_SPEC [INFO_SPEC]\n" |
| + | //usage: " NODE_SPEC := PREFIX"IF_FEATURE_IP_RULE(" [table TABLE_ID]")" [proto RTPROTO] [scope SCOPE] [metric METRIC]\n" |
| + | //usage: " INFO_SPEC := NH OPTIONS\n" |
| + | //usage: " NH := [via [inet|inet6] ADDRESS] [dev IFACE] [src ADDRESS] [onlink]\n" |
| + | //usage: " OPTIONS := [mtu NUM]" |
| + | //upstream man ip-route: |
| + | //====================== |
| + | //ip route { show | flush } SELECTOR |
| + | //ip route save SELECTOR |
| + | //ip route restore |
| + | //ip route get ADDRESS [ from ADDRESS iif STRING ] [ oif STRING ] [ tos TOS ] |
| + | //ip route { add | del | change | append | replace } ROUTE |
| + | //SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ] [ table TABLE_ID ] [ proto RTPROTO ] [ type TYPE ] [ scope SCOPE ] |
| + | //ROUTE := NODE_SPEC [ INFO_SPEC ] |
| + | //NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ] [ table TABLE_ID ] [ proto RTPROTO ] [ scope SCOPE ] [ metric METRIC ] |
| + | //INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ] ... |
| + | //NH := [ encap ENCAP ] [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS |
| + | // ..............................................................^ I guess [src ADDRESS] should be here |
| + | //FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ] |
| + | //OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ] rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ] [ window NUMBER ] [ cwnd NUMBER ] [ ssthresh REALM ] [ realms REALM ] |
| + | // [ rto_min TIME ] [ initcwnd NUMBER ] [ initrwnd NUMBER ] [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ] [ pref PREF ] [ expires TIME ] |
| + | //TYPE := [ unicast | local | broadcast | multicast | throw | unreachable | prohibit | blackhole | nat ] |
| + | //TABLE_ID := [ local | main | default | all | NUMBER ] |
| + | //SCOPE := [ host | link | global | NUMBER ] |
| + | //NHFLAGS := [ onlink | pervasive ] |
| + | //RTPROTO := [ kernel | boot | static | NUMBER ] |
| + | //FEATURES := [ ecn | ] |
| + | //PREF := [ low | medium | high ] |
| + | //ENCAP := [ MPLS | IP ] |
| + | //ENCAP_MPLS := mpls [ LABEL ] |
| + | //ENCAP_IP := ip id TUNNEL_ID dst REMOTE_IP [ tos TOS ] [ ttl TTL ] |
| //usage: | |
| //usage:#define iprule_trivial_usage | |
| //usage: "[list] | add|del SELECTOR ACTION" | |
| @@ -325,13 +325,14 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, | |
| /* Return value becomes exitcode. It's okay to not return at all */ | |
| static int iproute_modify(int cmd, unsigned flags, char **argv) | |
| { | |
| + | /* If you add stuff here, update iproute_full_usage */ |
| static const char keywords[] ALIGN1 = | |
| - | "src\0""via\0""mtu\0""lock\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0") |
| + | "src\0""via\0""mtu\0""scope\0""protocol\0"IF_FEATURE_IP_RULE("table\0") |
| "dev\0""oif\0""to\0""metric\0""onlink\0"; | |
| enum { | |
| ARG_src, | |
| ARG_via, | |
| - | ARG_mtu, PARM_lock, |
| + | ARG_mtu, |
| ARG_scope, | |
| ARG_protocol, | |
| IF_FEATURE_IP_RULE(ARG_table,) | |
| @@ -404,7 +405,7 @@ IF_FEATURE_IP_RULE(ARG_table,) | |
| } else if (arg == ARG_mtu) { | |
| unsigned mtu; | |
| NEXT_ARG(); | |
| - | if (index_in_strings(keywords, *argv) == PARM_lock) { |
| + | if (strcmp(*argv, "lock") == 0) { |
| mxlock |= (1 << RTAX_MTU); | |
| NEXT_ARG(); | |
| } | |
| @@ -441,6 +442,7 @@ IF_FEATURE_IP_RULE(ARG_table,) | |
| NEXT_ARG(); | |
| d = *argv; | |
| } else if (arg == ARG_metric) { | |
| + | //TODO: "metric", "priority" and "preference" are synonyms |
| uint32_t metric; | |
| NEXT_ARG(); | |
| metric = get_u32(*argv, "metric"); | |
| @@ -475,6 +477,168 @@ IF_FEATURE_IP_RULE(ARG_table,) | |
| addattr_l(&req.n, sizeof(req), RTA_DST, &dst.data, dst.bytelen); | |
| } | |
| } | |
| + | /* Other keywords recognized by iproute2-3.19.0: */ |
| + | #if 0 |
| + | } else if (strcmp(*argv, "from") == 0) { |
| + | inet_prefix addr; |
| + | NEXT_ARG(); |
| + | get_prefix(&addr, *argv, req.r.rtm_family); |
| + | if (req.r.rtm_family == AF_UNSPEC) |
| + | req.r.rtm_family = addr.family; |
| + | if (addr.bytelen) |
| + | addattr_l(&req.n, sizeof(req), RTA_SRC, &addr.data, addr.bytelen); |
| + | req.r.rtm_src_len = addr.bitlen; |
| + | } else if (strcmp(*argv, "tos") == 0 || |
| + | matches(*argv, "dsfield") == 0) { |
| + | __u32 tos; |
| + | NEXT_ARG(); |
| + | if (rtnl_dsfield_a2n(&tos, *argv)) |
| + | invarg("\"tos\" value is invalid\n", *argv); |
| + | req.r.rtm_tos = tos; |
| + | } else if (strcmp(*argv, "hoplimit") == 0) { |
| + | unsigned hoplimit; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_HOPLIMIT); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&hoplimit, *argv, 0)) |
| + | invarg("\"hoplimit\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit); |
| + | } else if (strcmp(*argv, "advmss") == 0) { |
| + | unsigned mss; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_ADVMSS); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&mss, *argv, 0)) |
| + | invarg("\"mss\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_ADVMSS, mss); |
| + | } else if (matches(*argv, "reordering") == 0) { |
| + | unsigned reord; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_REORDERING); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&reord, *argv, 0)) |
| + | invarg("\"reordering\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_REORDERING, reord); |
| + | } else if (strcmp(*argv, "rtt") == 0) { |
| + | unsigned rtt; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_RTT); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_time_rtt(&rtt, *argv, &raw)) |
| + | invarg("\"rtt\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, |
| + | (raw) ? rtt : rtt * 8); |
| + | } else if (strcmp(*argv, "rto_min") == 0) { |
| + | unsigned rto_min; |
| + | NEXT_ARG(); |
| + | mxlock |= (1<<RTAX_RTO_MIN); |
| + | if (get_time_rtt(&rto_min, *argv, &raw)) |
| + | invarg("\"rto_min\" value is invalid\n", |
| + | *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTO_MIN, |
| + | rto_min); |
| + | } else if (matches(*argv, "window") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_WINDOW); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&win, *argv, 0)) |
| + | invarg("\"window\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_WINDOW, win); |
| + | } else if (matches(*argv, "cwnd") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_CWND); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&win, *argv, 0)) |
| + | invarg("\"cwnd\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_CWND, win); |
| + | } else if (matches(*argv, "initcwnd") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_INITCWND); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&win, *argv, 0)) |
| + | invarg("\"initcwnd\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITCWND, win); |
| + | } else if (matches(*argv, "initrwnd") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_INITRWND); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&win, *argv, 0)) |
| + | invarg("\"initrwnd\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); |
| + | } else if (matches(*argv, "features") == 0) { |
| + | unsigned int features = 0; |
| + | |
| + | while (argc > 0) { |
| + | NEXT_ARG(); |
| + | |
| + | if (strcmp(*argv, "ecn") == 0) |
| + | features |= RTAX_FEATURE_ECN; |
| + | else |
| + | invarg("\"features\" value not valid\n", *argv); |
| + | break; |
| + | } |
| + | |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features); |
| + | } else if (matches(*argv, "quickack") == 0) { |
| + | unsigned quickack; |
| + | NEXT_ARG(); |
| + | if (get_unsigned(&quickack, *argv, 0)) |
| + | invarg("\"quickack\" value is invalid\n", *argv); |
| + | if (quickack != 1 && quickack != 0) |
| + | invarg("\"quickack\" value should be 0 or 1\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack); |
| + | } else if (matches(*argv, "rttvar") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_RTTVAR); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_time_rtt(&win, *argv, &raw)) |
| + | invarg("\"rttvar\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTTVAR, |
| + | (raw) ? win : win * 4); |
| + | } else if (matches(*argv, "ssthresh") == 0) { |
| + | unsigned win; |
| + | NEXT_ARG(); |
| + | if (strcmp(*argv, "lock") == 0) { |
| + | mxlock |= (1<<RTAX_SSTHRESH); |
| + | NEXT_ARG(); |
| + | } |
| + | if (get_unsigned(&win, *argv, 0)) |
| + | invarg("\"ssthresh\" value is invalid\n", *argv); |
| + | rta_addattr32(mxrta, sizeof(mxbuf), RTAX_SSTHRESH, win); |
| + | } else if (matches(*argv, "realms") == 0) { |
| + | __u32 realm; |
| + | NEXT_ARG(); |
| + | if (get_rt_realms(&realm, *argv)) |
| + | invarg("\"realm\" value is invalid\n", *argv); |
| + | addattr32(&req.n, sizeof(req), RTA_FLOW, realm); |
| + | } else if (strcmp(*argv, "nexthop") == 0) { |
| + | nhs_ok = 1; |
| + | break; |
| + | } |
| + | #endif |
| argv++; | |
| } | |