diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c index 320d2539..1737d884 100644 --- a/ip/ip6tunnel.c +++ b/ip/ip6tunnel.c @@ -354,7 +354,7 @@ static int do_tunnels_list(struct ip6_tnl_parm2 *p) fprintf(stderr, "Wrong format for /proc/net/dev. Giving up.\n"); goto end; } - if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld", + if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu", &rx_bytes, &rx_packets, &rx_errs, &rx_drops, &rx_fifo, &rx_frame, &rx_multi, &tx_bytes, &tx_packets, &tx_errs, &tx_drops, diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c index 913a2892..9b4b7728 100644 --- a/ip/iplink_vrf.c +++ b/ip/iplink_vrf.c @@ -28,12 +28,6 @@ static void explain(void) vrf_explain(stderr); } -static int table_arg(void) -{ - fprintf(stderr,"Error: argument of \"table\" must be 0-32767 and currently unused\n"); - return -1; -} - static int vrf_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { @@ -43,9 +37,8 @@ static int vrf_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); - table = atoi(*argv); - if (table > 32767) - return table_arg(); + if (rtnl_rttable_a2n(&table, *argv)) + invarg("invalid table ID\n", *argv); addattr32(n, 1024, IFLA_VRF_TABLE, table); } else if (matches(*argv, "help") == 0) { explain(); diff --git a/ip/iproute.c b/ip/iproute.c index aed1038e..c42ea0b9 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -577,24 +577,23 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (mxrta[i] == NULL) continue; - if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i]) - fprintf(fp, " %s", mx_names[i]); - else - fprintf(fp, " metric %d", i); - if (mxlock & (1<iph.protocol && p->iph.protocol != proto) { - fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); + fprintf(stderr, + "You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = proto; @@ -91,7 +92,8 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) set_tunnel_proto(p, IPPROTO_IPIP); p->i_flags |= VTI_ISVTI; } else { - fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv); + fprintf(stderr, + "Unknown tunnel mode \"%s\"\n", *argv); exit(-1); } } else if (strcmp(*argv, "key") == 0) { @@ -144,6 +146,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) strcmp(*argv, "hoplimit") == 0 || strcmp(*argv, "hlim") == 0) { __u8 uval; + NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_u8(&uval, *argv, 0)) @@ -155,6 +158,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) matches(*argv, "dsfield") == 0) { char *dsfield; __u32 uval; + NEXT_ARG(); dsfield = *argv; strsep(&dsfield, "/"); @@ -169,15 +173,17 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->iph.tos |= uval; } } else { - if (strcmp(*argv, "name") == 0) { + if (strcmp(*argv, "name") == 0) NEXT_ARG(); - } else if (matches(*argv, "help") == 0) + else if (matches(*argv, "help") == 0) usage(); + if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ - 1); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; + memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; @@ -268,8 +274,10 @@ static int do_add(int cmd, int argc, char **argv) return -1; } - if (!(basedev = tnl_defname(&p))) { - fprintf(stderr, "cannot determine tunnel mode (ipip, gre, vti or sit)\n"); + basedev = tnl_defname(&p); + if (!basedev) { + fprintf(stderr, + "cannot determine tunnel mode (ipip, gre, vti or sit)\n"); return -1; } @@ -312,18 +320,18 @@ static void print_tunnel(struct ip_tunnel_parm *p) prl[0].addr = htonl(INADDR_ANY); if (!tnl_prl_ioctl(SIOCGETPRL, p->name, prl)) - for (i = 1; i < sizeof(prl) / sizeof(prl[0]); i++) - { - if (prl[i].addr != htonl(INADDR_ANY)) { - printf(" %s %s ", - (prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr", - format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1))); + for (i = 1; i < ARRAY_SIZE(prl); i++) { + if (prl[i].addr != htonl(INADDR_ANY)) { + printf(" %s %s ", + (prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr", + format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1))); + } } - } } if (p->link) { const char *n = ll_index_to_name(p->link); + if (n) printf(" dev %s", n); } @@ -381,6 +389,7 @@ static int do_tunnels_list(struct ip_tunnel_parm *p) char buf[512]; int err = -1; FILE *fp = fopen("/proc/net/dev", "r"); + if (fp == NULL) { perror("fopen"); return -1; @@ -404,12 +413,13 @@ static int do_tunnels_list(struct ip_tunnel_parm *p) char *ptr; buf[sizeof(buf) - 1] = 0; - if ((ptr = strchr(buf, ':')) == NULL || + ptr = strchr(buf, ':'); + if (ptr == NULL || (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) { fprintf(stderr, "Wrong format for /proc/net/dev. Giving up.\n"); goto end; } - if (sscanf(ptr, "%ld%ld%ld%ld%ld%ld%ld%*d%ld%ld%ld%ld%ld%ld%ld", + if (sscanf(ptr, "%lu%lu%lu%lu%lu%lu%lu%*d%lu%lu%lu%lu%lu%lu%lu", &rx_bytes, &rx_packets, &rx_errs, &rx_drops, &rx_fifo, &rx_frame, &rx_multi, &tx_bytes, &tx_packets, &tx_errs, &tx_drops, @@ -463,7 +473,8 @@ static int do_show(int argc, char **argv) if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0) return -1; - if (!(basedev = tnl_defname(&p))) + basedev = tnl_defname(&p); + if (!basedev) return do_tunnels_list(&p); if (tnl_get_ioctl(p.name[0] ? p.name : basedev, &p)) @@ -507,11 +518,13 @@ static int do_prl(int argc, char **argv) strncpy(medium, *argv, IFNAMSIZ-1); devname++; } else { - fprintf(stderr,"Invalid PRL parameter \"%s\"\n", *argv); + fprintf(stderr, + "Invalid PRL parameter \"%s\"\n", *argv); exit(-1); } if (count > 1) { - fprintf(stderr,"One PRL entry at a time\n"); + fprintf(stderr, + "One PRL entry at a time\n"); exit(-1); } argc--; argv++; @@ -557,7 +570,8 @@ static int do_6rd(int argc, char **argv) strncpy(medium, *argv, IFNAMSIZ-1); devname++; } else { - fprintf(stderr,"Invalid 6RD parameter \"%s\"\n", *argv); + fprintf(stderr, + "Invalid 6RD parameter \"%s\"\n", *argv); exit(-1); } argc--; argv++; @@ -570,8 +584,35 @@ static int do_6rd(int argc, char **argv) return tnl_6rd_ioctl(cmd, medium, &ip6rd); } +static int tunnel_mode_is_ipv6(char *tunnel_mode) +{ + static const char * const ipv6_modes[] = { + "ipv6/ipv6", "ip6ip6", + "vti6", + "ip/ipv6", "ipv4/ipv6", "ipip6", "ip4ip6", + "ip6gre", "gre/ipv6", + "any/ipv6", "any" + }; + int i; + + for (i = 0; i < ARRAY_SIZE(ipv6_modes); i++) { + if (strcmp(ipv6_modes[i], tunnel_mode) == 0) + return 1; + } + return 0; +} + int do_iptunnel(int argc, char **argv) { + int i; + + for (i = 0; i < argc - 1; i++) { + if (strcmp(argv[i], "mode") == 0) { + if (tunnel_mode_is_ipv6(argv[i + 1])) + preferred_family = AF_INET6; + break; + } + } switch (preferred_family) { case AF_UNSPEC: preferred_family = AF_INET; diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 922ec2d9..16582144 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -332,7 +332,7 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, } int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, - struct nlmsghdr *answer, size_t len) + struct nlmsghdr *answer, size_t maxlen) { int status; unsigned seq; @@ -415,7 +415,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, } else if (!err->error) { if (answer) memcpy(answer, h, - MIN(len, h->nlmsg_len)); + MIN(maxlen, h->nlmsg_len)); return 0; } @@ -427,7 +427,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, if (answer) { memcpy(answer, h, - MIN(len, h->nlmsg_len)); + MIN(maxlen, h->nlmsg_len)); return 0; } diff --git a/man/man8/tc.8 b/man/man8/tc.8 index 6275c4b3..4e99dcad 100644 --- a/man/man8/tc.8 +++ b/man/man8/tc.8 @@ -181,7 +181,7 @@ Match Resource Reservation Protocol (RSVP) packets. .TP tcindex Filter packets based on traffic control index. See -.BR tc-index (8). +.BR tc-tcindex (8). .TP u32 Generic filtering on arbitrary packet data, assisted by syntax to abstract common operations. See diff --git a/testsuite/tests/ip/tunnel/add_tunnel.t b/testsuite/tests/ip/tunnel/add_tunnel.t new file mode 100755 index 00000000..18f6e370 --- /dev/null +++ b/testsuite/tests/ip/tunnel/add_tunnel.t @@ -0,0 +1,14 @@ +#!/bin/sh + +source lib/generic.sh + +TUNNEL_NAME="tunnel_test_ip" + +ts_log "[Testing add/del tunnels]" + +ts_ip "$0" "Add GRE tunnel over IPv4" tunnel add name $TUNNEL_NAME mode gre local 1.1.1.1 remote 2.2.2.2 +ts_ip "$0" "Del GRE tunnel over IPv4" tunnel del $TUNNEL_NAME + +ts_ip "$0" "Add GRE tunnel over IPv6" tunnel add name $TUNNEL_NAME mode ip6gre local dead:beef::1 remote dead:beef::2 +ts_ip "$0" "Del GRE tunnel over IPv6" tunnel del $TUNNEL_NAME +