From 2c6aaad94956f947c3c46e05d5f2d189bebf0b00 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 16 Dec 2017 10:00:43 -0800 Subject: [PATCH 01/33] include: qdisc offload defines UAPI changes from upstream: net: sched: Add TCA_HW_OFFLOAD pkt_sched: Remove TC_RED_OFFLOADED from uapi Signed-off-by: Stephen Hemminger --- include/uapi/linux/pkt_sched.h | 1 - include/uapi/linux/rtnetlink.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h index af3cc2f4..37b5096a 100644 --- a/include/uapi/linux/pkt_sched.h +++ b/include/uapi/linux/pkt_sched.h @@ -256,7 +256,6 @@ struct tc_red_qopt { #define TC_RED_ECN 1 #define TC_RED_HARDDROP 2 #define TC_RED_ADAPTATIVE 4 -#define TC_RED_OFFLOADED 8 }; struct tc_red_xstats { diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index b8335b5a..13bf56fc 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -557,6 +557,7 @@ enum { TCA_PAD, TCA_DUMP_INVISIBLE, TCA_CHAIN, + TCA_HW_OFFLOAD, __TCA_MAX }; From 3d791a326bb6c857c5fd6db2b89695bc37295c43 Mon Sep 17 00:00:00 2001 From: Roman Mashak Date: Fri, 15 Dec 2017 09:27:42 -0500 Subject: [PATCH 02/33] ss: add missing path MTU parameter v3: Rebase and use out() instead of printf(). v2: Print the path MTU immediately after the MSS, as it is easier to parse for humans (suggested by Neal Cardwell). Signed-off-by: Roman Mashak Signed-off-by: Stephen Hemminger --- man/man8/ss.8 | 4 ++++ misc/ss.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 6d06383b..0d526734 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -184,6 +184,10 @@ max segment size congestion window size .P .TP +.B pmtu: +path MTU value +.P +.TP .B ssthresh: tcp congestion window slow start threshold .P diff --git a/misc/ss.c b/misc/ss.c index 9d21ed7a..1abf43d0 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -790,6 +790,7 @@ struct tcpstat { int mss; int rcv_mss; int advmss; + unsigned int pmtu; unsigned int cwnd; unsigned int lastsnd; unsigned int lastrcv; @@ -2360,6 +2361,8 @@ static void tcp_stats_print(struct tcpstat *s) if (s->mss) out(" mss:%d", s->mss); + if (s->pmtu) + out(" pmtu:%u", s->pmtu); if (s->rcv_mss) out(" rcvmss:%d", s->rcv_mss); if (s->advmss) @@ -2707,6 +2710,7 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, s.reordering = info->tcpi_reordering; s.rcv_ssthresh = info->tcpi_rcv_ssthresh; s.cwnd = info->tcpi_snd_cwnd; + s.pmtu = info->tcpi_pmtu; if (info->tcpi_snd_ssthresh < 0xFFFF) s.ssthresh = info->tcpi_snd_ssthresh; From 1eccc5734148c9e4e1e4db7aaa33bccaa24c2257 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 16 Dec 2017 12:38:57 +0100 Subject: [PATCH 03/33] ip: add vxcan/veth to ip-link man page veth and vxcan both create a vitual tunnel between a pair of virtual network devices. This patch adds the content for the now supported vxcan netdevices and the documentation to create peer devices for vxcan and veth. Additional remove 'can' that accidently was on the list of link types which can be created by 'ip link add' as 'can' devices are real network devices. Signed-off-by: Oliver Hartkopp Signed-off-by: Stephen Hemminger --- man/man8/ip-link.8.in | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index a6a10e57..94ecbece 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -194,6 +194,7 @@ ip-link \- network device configuration .BR macvlan " | " .BR macvtap " | " .BR vcan " | " +.BR vxcan " | " .BR veth " | " .BR vlan " | " .BR vxlan " |" @@ -252,9 +253,6 @@ Link types: .B bond - Bonding device .sp -.B can -- Controller Area Network interface -.sp .B dummy - Dummy network interface .sp @@ -276,6 +274,9 @@ Link types: .B vcan - Virtual Controller Area Network interface .sp +.B vxcan +- Virtual Controller Area Network tunnel interface +.sp .B veth - Virtual ethernet interface .sp @@ -651,6 +652,29 @@ keyword. .in -8 +.TP +VETH, VXCAN Type Support +For a link of types +.I VETH/VXCAN +the following additional arguments are supported: + +.BI "ip link add " DEVICE +.BR type " { " veth " | " vxcan " }" +[ +.BR peer +.BI "name " NAME +] + +.in +8 +.sp +.BR peer +.BI "name " NAME +- specifies the virtual pair device name of the +.I VETH/VXCAN +tunnel. + +.in -8 + .TP GRE, IPIP, SIT, ERSPAN Type Support For a link of types From 57daab1e701e5853870bb43e0ff7c151dbddfe9f Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 13 Dec 2017 21:36:00 +0200 Subject: [PATCH 04/33] ip/tunnel: Unify setup and accept zero address for local/remote endpoints It is fully legal to submit zero (INADDR_ANY/IN6ADDR_ANY_INIT) value for local and/or remote endpoints for all tunnel drivers: no need additionally check this in userspace. Note that all tunnel specific code already can pass zero address to the kernel. Signed-off-by: Serhey Popovych --- ip/iptunnel.c | 10 ++-------- ip/link_gre.c | 6 ++---- ip/link_iptnl.c | 10 ++-------- ip/link_vti.c | 14 ++------------ ip/link_vti6.c | 26 ++++++++------------------ 5 files changed, 16 insertions(+), 50 deletions(-) diff --git a/ip/iptunnel.c b/ip/iptunnel.c index 208a1f06..ce610f84 100644 --- a/ip/iptunnel.c +++ b/ip/iptunnel.c @@ -127,16 +127,10 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); - if (strcmp(*argv, "any")) - p->iph.daddr = get_addr32(*argv); - else - p->iph.daddr = htonl(INADDR_ANY); + p->iph.daddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); - if (strcmp(*argv, "any")) - p->iph.saddr = get_addr32(*argv); - else - p->iph.saddr = htonl(INADDR_ANY); + p->iph.saddr = get_addr32(*argv); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); medium = *argv; diff --git a/ip/link_gre.c b/ip/link_gre.c index 43cb1af6..6f82fb4e 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -251,12 +251,10 @@ get_failed: pmtudisc = 1; } else if (!matches(*argv, "remote")) { NEXT_ARG(); - if (strcmp(*argv, "any")) - daddr = get_addr32(*argv); + daddr = get_addr32(*argv); } else if (!matches(*argv, "local")) { NEXT_ARG(); - if (strcmp(*argv, "any")) - saddr = get_addr32(*argv); + saddr = get_addr32(*argv); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 2804b8f4..5e4dffa6 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -195,16 +195,10 @@ get_failed: while (argc > 0) { if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); - if (strcmp(*argv, "any")) - raddr = get_addr32(*argv); - else - raddr = 0; + raddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); - if (strcmp(*argv, "any")) - laddr = get_addr32(*argv); - else - laddr = 0; + laddr = get_addr32(*argv); } else if (matches(*argv, "dev") == 0) { NEXT_ARG(); link = if_nametoindex(*argv); diff --git a/ip/link_vti.c b/ip/link_vti.c index 07ac94e7..05aefa32 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -167,20 +167,10 @@ get_failed: okey = uval; } else if (!matches(*argv, "remote")) { NEXT_ARG(); - if (!strcmp(*argv, "any")) { - fprintf(stderr, "invalid value for \"remote\": \"%s\"\n", *argv); - exit(-1); - } else { - daddr = get_addr32(*argv); - } + daddr = get_addr32(*argv); } else if (!matches(*argv, "local")) { NEXT_ARG(); - if (!strcmp(*argv, "any")) { - fprintf(stderr, "invalid value for \"local\": \"%s\"\n", *argv); - exit(-1); - } else { - saddr = get_addr32(*argv); - } + saddr = get_addr32(*argv); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 6d08bfe0..f665520f 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -161,27 +161,17 @@ get_failed: } okey = uval; } else if (!matches(*argv, "remote")) { - NEXT_ARG(); - if (!strcmp(*argv, "any")) { - fprintf(stderr, "invalid value for \"remote\": \"%s\"\n", *argv); - exit(-1); - } else { - inet_prefix addr; + inet_prefix addr; - get_prefix(&addr, *argv, AF_INET6); - memcpy(&daddr, addr.data, addr.bytelen); - } + NEXT_ARG(); + get_prefix(&addr, *argv, AF_INET6); + memcpy(&daddr, addr.data, addr.bytelen); } else if (!matches(*argv, "local")) { - NEXT_ARG(); - if (!strcmp(*argv, "any")) { - fprintf(stderr, "invalid value for \"local\": \"%s\"\n", *argv); - exit(-1); - } else { - inet_prefix addr; + inet_prefix addr; - get_prefix(&addr, *argv, AF_INET6); - memcpy(&saddr, addr.data, addr.bytelen); - } + NEXT_ARG(); + get_prefix(&addr, *argv, AF_INET6); + memcpy(&saddr, addr.data, addr.bytelen); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); From 9aceaad71b6693b8464cef6370fc78efaf455f7f Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 13 Dec 2017 21:36:01 +0200 Subject: [PATCH 05/33] ip/tunnel: Use get_addr() instead of get_prefix() for local/remote endpoints Manual page ip-link(8) states that both local and remote accept IPADDR not PREFIX. Use get_addr() instead of get_prefix() to parse local/remote endpoint address correctly. Force corresponding address family instead of using preferred_family to catch weired cases as shown below. Before this patch it is possible to create tunnel with commands: ip li add dev ip6gre2 type ip6gre local fe80::1/64 remote fe80::2/64 ip -4 li add dev ip6gre2 type ip6gre local 10.0.0.1/24 remote 10.0.0.2/24 Signed-off-by: Serhey Popovych --- ip/ip6tunnel.c | 8 ++------ ip/link_gre6.c | 8 ++------ ip/link_ip6tnl.c | 12 ++++-------- ip/link_vti6.c | 8 ++++---- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c index 4563e1e0..b8db49c9 100644 --- a/ip/ip6tunnel.c +++ b/ip/ip6tunnel.c @@ -170,17 +170,13 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p) inet_prefix raddr; NEXT_ARG(); - get_prefix(&raddr, *argv, preferred_family); - if (raddr.family == AF_UNSPEC) - invarg("\"remote\" address family is AF_UNSPEC", *argv); + get_addr(&raddr, *argv, AF_INET6); memcpy(&p->raddr, &raddr.data, sizeof(p->raddr)); } else if (strcmp(*argv, "local") == 0) { inet_prefix laddr; NEXT_ARG(); - get_prefix(&laddr, *argv, preferred_family); - if (laddr.family == AF_UNSPEC) - invarg("\"local\" address family is AF_UNSPEC", *argv); + get_addr(&laddr, *argv, AF_INET6); memcpy(&p->laddr, &laddr.data, sizeof(p->laddr)); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 0a82eaec..c22fdedb 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -257,17 +257,13 @@ get_failed: inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, preferred_family); - if (addr.family == AF_UNSPEC) - invarg("\"remote\" address family is AF_UNSPEC", *argv); + get_addr(&addr, *argv, AF_INET6); memcpy(&raddr, &addr.data, sizeof(raddr)); } else if (!matches(*argv, "local")) { inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, preferred_family); - if (addr.family == AF_UNSPEC) - invarg("\"local\" address family is AF_UNSPEC", *argv); + get_addr(&addr, *argv, AF_INET6); memcpy(&laddr, &addr.data, sizeof(laddr)); } else if (!matches(*argv, "dev")) { NEXT_ARG(); diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index af796c30..83a43203 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -184,18 +184,14 @@ get_failed: inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, preferred_family); - if (addr.family == AF_UNSPEC) - invarg("\"remote\" address family is AF_UNSPEC", *argv); - memcpy(&raddr, addr.data, addr.bytelen); + get_addr(&addr, *argv, AF_INET6); + memcpy(&raddr, addr.data, sizeof(raddr)); } else if (strcmp(*argv, "local") == 0) { inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, preferred_family); - if (addr.family == AF_UNSPEC) - invarg("\"local\" address family is AF_UNSPEC", *argv); - memcpy(&laddr, addr.data, addr.bytelen); + get_addr(&addr, *argv, AF_INET6); + memcpy(&laddr, addr.data, sizeof(laddr)); } else if (matches(*argv, "dev") == 0) { NEXT_ARG(); link = if_nametoindex(*argv); diff --git a/ip/link_vti6.c b/ip/link_vti6.c index f665520f..84824a5d 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -164,14 +164,14 @@ get_failed: inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, AF_INET6); - memcpy(&daddr, addr.data, addr.bytelen); + get_addr(&addr, *argv, AF_INET6); + memcpy(&daddr, addr.data, sizeof(daddr)); } else if (!matches(*argv, "local")) { inet_prefix addr; NEXT_ARG(); - get_prefix(&addr, *argv, AF_INET6); - memcpy(&saddr, addr.data, addr.bytelen); + get_addr(&addr, *argv, AF_INET6); + memcpy(&saddr, addr.data, sizeof(saddr)); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); From a6addd5cdcec2391732c6b4fc076f3319e45296e Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 13 Dec 2017 21:36:02 +0200 Subject: [PATCH 06/33] ip: gre: fix IFLA_GRE_LINK attribute sizing Attribute IFLA_GRE_LINK is 32 bit long, not 8 bit. Signed-off-by: Serhey Popovych --- ip/link_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index 6f82fb4e..09f1e441 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -155,7 +155,7 @@ get_failed: tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]); if (greinfo[IFLA_GRE_LINK]) - link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]); + link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]); if (greinfo[IFLA_GRE_ENCAP_TYPE]) encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]); From ae8e1cb83bf86f7474350f73f2ef323273969f71 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 14 Dec 2017 18:17:43 -0800 Subject: [PATCH 07/33] ip: validate vlan value for vlan info The VLAN tag must be 0..4095 to be valid. Better to trap it here. Signed-off-by: Stephen Hemminger --- ip/iplink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ip/iplink.c b/ip/iplink.c index e83f1477..1e685cc2 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -276,11 +276,13 @@ static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp, { int argc = *argcp; char **argv = *argvp; + unsigned int vci; NEXT_ARG(); - if (get_unsigned(&ivvip->vlan, *argv, 0)) + if (get_unsigned(&vci, *argv, 0) || vci > 4095) invarg("Invalid \"vlan\" value\n", *argv); + ivvip->vlan = vci; ivvip->vf = vf; ivvip->qos = 0; ivvip->vlan_proto = htons(ETH_P_8021Q); From 507358183576b44a2f6c825b35441a9549d385c7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Dec 2017 09:51:02 -0800 Subject: [PATCH 08/33] ss: fix crash with invalid command input file If given an invalid input file with -F flag, ss would crash. Examples of invalid input are line to long, or null file. Found by fuzzing with ASAN. Reported-by:Bug Basher Signed-off-by: Stephen Hemminger --- misc/ssfilter.y | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/misc/ssfilter.y b/misc/ssfilter.y index ba82b65f..4db3c95f 100644 --- a/misc/ssfilter.y +++ b/misc/ssfilter.y @@ -202,15 +202,23 @@ int yylex(void) argc++; } else if (yy_fp) { while (tokptr == NULL) { - if (fgets(argbuf, sizeof(argbuf)-1, yy_fp) == NULL) + size_t len; + + if (fgets(argbuf, sizeof(argbuf), yy_fp) == NULL) return 0; - argbuf[sizeof(argbuf)-1] = 0; - if (strlen(argbuf) == sizeof(argbuf) - 1) { - fprintf(stderr, "Too long line in filter"); + + len = strnlen(argbuf, sizeof(argbuf)); + if (len == 0) { + fprintf(stderr, "Invalid line\n"); exit(-1); } - if (argbuf[strlen(argbuf)-1] == '\n') - argbuf[strlen(argbuf)-1] = 0; + + if (len >= sizeof(argbuf) - 1) { + fprintf(stderr, "Too long line in filter\n"); + exit(-1); + } + if (argbuf[len - 1] == '\n') + argbuf[len-1] = 0; if (argbuf[0] == '#' || argbuf[0] == '0') continue; tokptr = argbuf; From bd9cea5d8c9dc6266f9529e1be6bc7dab4519d9c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Dec 2017 11:10:53 -0800 Subject: [PATCH 09/33] utils: fix makeargs stack overflow The makeargs() function did not handle end of string correctly and would reference past end of string. Found by fuzzing with ASAN. Reported-by:Bug Basher Signed-off-by: Stephen Hemminger --- lib/utils.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 7ced8c06..df1f3b12 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -1206,10 +1206,16 @@ ssize_t getcmdline(char **linep, size_t *lenp, FILE *in) int makeargs(char *line, char *argv[], int maxargs) { static const char ws[] = " \t\r\n"; - char *cp; + char *cp = line; int argc = 0; - for (cp = line + strspn(line, ws); *cp; cp += strspn(cp, ws)) { + while (*cp) { + /* skip leading whitespace */ + cp += strspn(cp, ws); + + if (*cp == '\0') + break; + if (argc >= (maxargs - 1)) { fprintf(stderr, "Too many arguments to command\n"); exit(1); @@ -1226,13 +1232,16 @@ int makeargs(char *line, char *argv[], int maxargs) fprintf(stderr, "Unterminated quoted string\n"); exit(1); } - *cp++ = 0; - continue; + } else { + argv[argc++] = cp; + + /* find end of word */ + cp += strcspn(cp, ws); + if (*cp == '\0') + break; } - argv[argc++] = cp; - /* find end of word */ - cp += strcspn(cp, ws); + /* seperate words */ *cp++ = 0; } argv[argc] = NULL; From b7ea12ae4399461d18442cfcecec3e2e908fb61b Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 20:54:06 +0200 Subject: [PATCH 10/33] iplink: Improve index parameter handling Correctly check for valid network device index supplied on command line: indexes are always greather than zero. Check for duplicate "index" argument. Initialize @index to 0 to simplify handling it in iplink_modify(). Other callers (link_veth.c, iplink_vxcan.c) already did so. No need to initialize ifi_index with 0 since it is already initialized at the @struct req initialization time and not modified in iplink_parse(). Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ip/iplink.c b/ip/iplink.c index 1e685cc2..4f9c169a 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -586,8 +586,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, *name = *argv; } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); + if (*index) + duparg("index", *argv); *index = atoi(*argv); - if (*index < 0) + if (*index <= 0) invarg("Invalid \"index\" value", *argv); } else if (matches(*argv, "link") == 0) { NEXT_ARG(); @@ -886,7 +888,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) char *name = NULL; char *link = NULL; char *type = NULL; - int index = -1; + int index = 0; int group; struct link_util *lu = NULL; struct iplink_req req = { @@ -922,7 +924,6 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) return -1; } - req.i.ifi_index = 0; addattr32(&req.n, sizeof(req), IFLA_GROUP, group); if (rtnl_talk(&rth, &req.n, NULL) < 0) return -2; @@ -936,7 +937,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) "Not enough information: \"dev\" argument is required.\n"); exit(-1); } - if (cmd == RTM_NEWLINK && index != -1) { + if (cmd == RTM_NEWLINK && index) { fprintf(stderr, "index can be used only when creating devices.\n"); exit(-1); @@ -964,10 +965,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4); } - if (index == -1) - req.i.ifi_index = 0; - else - req.i.ifi_index = index; + req.i.ifi_index = index; } if (name) { From f88becf35e087b184d9e667d51ff1e192c1236bc Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 20:54:07 +0200 Subject: [PATCH 11/33] iplink: Process "alias" parameter correctly Do not stop parameters processing after "alias" parameter: it might not be a last one. Seems copy pasted from "type" parameter code. Check it's length does not exceed IFALIASZ - 1. Better we warn than get RTNL error. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ip/iplink.c b/ip/iplink.c index 4f9c169a..4c967112 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -770,11 +770,12 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, argc--; argv++; break; } else if (matches(*argv, "alias") == 0) { + len = strlen(*argv); + if (len >= IFALIASZ) + invarg("alias too long\n", *argv); NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS, - *argv, strlen(*argv)); - argc--; argv++; - break; + *argv, len); } else if (strcmp(*argv, "group") == 0) { NEXT_ARG(); if (*group != -1) From dac9ff35ea302124f440c87c68b3dd896712e92a Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 20:54:08 +0200 Subject: [PATCH 12/33] iplink: Kill redundant network device name checks Since commit 625df645b703 (Check user supplied interface name lengths) iplink_parse() validates network device name using check_ifname() helpers. Remove redundant "name" length checks from iplink_parse() callers. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink_vxcan.c | 8 +++----- ip/link_veth.c | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c index 680f640f..c13224c3 100644 --- a/ip/iplink_vxcan.c +++ b/ip/iplink_vxcan.c @@ -38,7 +38,7 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv, char *link = NULL; char *type = NULL; int index = 0; - int err, len; + int err; struct rtattr *data; int group; struct ifinfomsg *ifm, *peer_ifm; @@ -66,10 +66,8 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv, return err; if (name) { - len = strlen(name) + 1; - if (len > IFNAMSIZ) - invarg("\"name\" too long\n", *argv); - addattr_l(hdr, 1024, IFLA_IFNAME, name, len); + addattr_l(hdr, 1024, + IFLA_IFNAME, name, strlen(name) + 1); } peer_ifm = RTA_DATA(data); diff --git a/ip/link_veth.c b/ip/link_veth.c index a3688274..fcfd1ef3 100644 --- a/ip/link_veth.c +++ b/ip/link_veth.c @@ -36,7 +36,7 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv, char *link = NULL; char *type = NULL; int index = 0; - int err, len; + int err; struct rtattr *data; int group; struct ifinfomsg *ifm, *peer_ifm; @@ -64,10 +64,8 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv, return err; if (name) { - len = strlen(name) + 1; - if (len > IFNAMSIZ) - invarg("\"name\" too long\n", *argv); - addattr_l(hdr, 1024, IFLA_IFNAME, name, len); + addattr_l(hdr, 1024, + IFLA_IFNAME, name, strlen(name) + 1); } peer_ifm = RTA_DATA(data); From 1f44b93744f11f2a8249e3c13751ab7debebaa5f Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 19:48:03 +0200 Subject: [PATCH 13/33] ip/tunnel: Use tnl_parse_key() to parse tunnel key It is added with commit a7ed1520ee96 ("ip/tunnel: introduce tnl_parse_key()") to avoid code duplication in ip6?tunnel.c. Reuse it for gre/gre6 and vti/vti6 tunnel rtnl configuration interface with the same purpose it is used in tunnel ioctl interface in ip6?tunnel.c. While there change type of key variables from unsigned integer to __be32 to reflect nature of the value they store and place error message in tnl_parse_key() on a single line to make single call to fprintf(). Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_gre.c | 45 +++++---------------------------------------- ip/link_gre6.c | 45 +++++---------------------------------------- ip/link_vti.c | 45 +++++---------------------------------------- ip/link_vti6.c | 45 +++++---------------------------------------- ip/tunnel.c | 5 +++-- 5 files changed, 23 insertions(+), 162 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index 09f1e441..2397920a 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -81,8 +81,8 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct rtattr *greinfo[IFLA_GRE_MAX + 1]; __u16 iflags = 0; __u16 oflags = 0; - unsigned int ikey = 0; - unsigned int okey = 0; + __be32 ikey = 0; + __be32 okey = 0; unsigned int saddr = 0; unsigned int daddr = 0; unsigned int link = 0; @@ -184,53 +184,18 @@ get_failed: while (argc > 0) { if (!matches(*argv, "key")) { - unsigned int uval; - NEXT_ARG(); iflags |= GRE_KEY; oflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, - "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - - ikey = okey = uval; + ikey = okey = tnl_parse_key("key", *argv); } else if (!matches(*argv, "ikey")) { - unsigned int uval; - NEXT_ARG(); iflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - ikey = uval; + ikey = tnl_parse_key("ikey", *argv); } else if (!matches(*argv, "okey")) { - unsigned int uval; - NEXT_ARG(); oflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - okey = uval; + okey = tnl_parse_key("okey", *argv); } else if (!matches(*argv, "seq")) { iflags |= GRE_SEQ; oflags |= GRE_SEQ; diff --git a/ip/link_gre6.c b/ip/link_gre6.c index c22fdedb..7190ada9 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -92,8 +92,8 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct rtattr *greinfo[IFLA_GRE_MAX + 1]; __u16 iflags = 0; __u16 oflags = 0; - unsigned int ikey = 0; - unsigned int okey = 0; + __be32 ikey = 0; + __be32 okey = 0; struct in6_addr raddr = IN6ADDR_ANY_INIT; struct in6_addr laddr = IN6ADDR_ANY_INIT; unsigned int link = 0; @@ -192,53 +192,18 @@ get_failed: while (argc > 0) { if (!matches(*argv, "key")) { - unsigned int uval; - NEXT_ARG(); iflags |= GRE_KEY; oflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, - "Invalid value for \"key\"\n"); - exit(-1); - } - uval = htonl(uval); - } - - ikey = okey = uval; + ikey = okey = tnl_parse_key("key", *argv); } else if (!matches(*argv, "ikey")) { - unsigned int uval; - NEXT_ARG(); iflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value of \"ikey\"\n"); - exit(-1); - } - uval = htonl(uval); - } - ikey = uval; + ikey = tnl_parse_key("ikey", *argv); } else if (!matches(*argv, "okey")) { - unsigned int uval; - NEXT_ARG(); oflags |= GRE_KEY; - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value of \"okey\"\n"); - exit(-1); - } - uval = htonl(uval); - } - okey = uval; + okey = tnl_parse_key("okey", *argv); } else if (!matches(*argv, "seq")) { iflags |= GRE_SEQ; oflags |= GRE_SEQ; diff --git a/ip/link_vti.c b/ip/link_vti.c index 05aefa32..6c5469ff 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -64,8 +64,8 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *vtiinfo[IFLA_VTI_MAX + 1]; - unsigned int ikey = 0; - unsigned int okey = 0; + __be32 ikey = 0; + __be32 okey = 0; unsigned int saddr = 0; unsigned int daddr = 0; unsigned int link = 0; @@ -122,49 +122,14 @@ get_failed: while (argc > 0) { if (!matches(*argv, "key")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, - "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - - ikey = okey = uval; + ikey = okey = tnl_parse_key("key", *argv); } else if (!matches(*argv, "ikey")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - ikey = uval; + ikey = tnl_parse_key("ikey", *argv); } else if (!matches(*argv, "okey")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - okey = uval; + okey = tnl_parse_key("okey", *argv); } else if (!matches(*argv, "remote")) { NEXT_ARG(); daddr = get_addr32(*argv); diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 84824a5d..f631839a 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -61,8 +61,8 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, struct rtattr *vtiinfo[IFLA_VTI_MAX + 1]; struct in6_addr saddr = IN6ADDR_ANY_INIT; struct in6_addr daddr = IN6ADDR_ANY_INIT; - unsigned int ikey = 0; - unsigned int okey = 0; + __be32 ikey = 0; + __be32 okey = 0; unsigned int link = 0; __u32 fwmark = 0; int len; @@ -117,49 +117,14 @@ get_failed: while (argc > 0) { if (!matches(*argv, "key")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, - "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - - ikey = okey = uval; + ikey = okey = tnl_parse_key("key", *argv); } else if (!matches(*argv, "ikey")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - ikey = uval; + ikey = tnl_parse_key("ikey", *argv); } else if (!matches(*argv, "okey")) { - unsigned int uval; - NEXT_ARG(); - if (strchr(*argv, '.')) - uval = get_addr32(*argv); - else { - if (get_unsigned(&uval, *argv, 0) < 0) { - fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); - exit(-1); - } - uval = htonl(uval); - } - okey = uval; + okey = tnl_parse_key("okey", *argv); } else if (!matches(*argv, "remote")) { inet_prefix addr; diff --git a/ip/tunnel.c b/ip/tunnel.c index d359eb95..f8601038 100644 --- a/ip/tunnel.c +++ b/ip/tunnel.c @@ -192,8 +192,9 @@ __be32 tnl_parse_key(const char *name, const char *key) return get_addr32(key); if (get_unsigned(&uval, key, 0) < 0) { - fprintf(stderr, "invalid value for \"%s\": \"%s\";", name, key); - fprintf(stderr, " it should be an unsigned integer\n"); + fprintf(stderr, + "invalid value for \"%s\": \"%s\"; it should be an unsigned integer\n", + name, key); exit(-1); } return htonl(uval); From 95614cc8a3340713964e282d2a6cffbb87895d10 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 19:48:04 +0200 Subject: [PATCH 14/33] link_ip6tnl: Use IN6ADDR_ANY_INIT to initialize local/remote endpoints Use specialized helper to initialize endpoint addresses with zeros instead of open coding this. This unifies initialization style with other ipv6 tunnel variants (i.e. gre6 and vti6). Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_ip6tnl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 83a43203..f11ddd59 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -88,8 +88,8 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; int len; - struct in6_addr laddr = {}; - struct in6_addr raddr = {}; + struct in6_addr laddr = IN6ADDR_ANY_INIT; + struct in6_addr raddr = IN6ADDR_ANY_INIT; __u8 hop_limit = DEFAULT_TNL_HOP_LIMIT; __u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; __u32 flowinfo = 0; From 560cf612531ffa12fc10fc3fbbaee7dc5d8eafdc Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Mon, 18 Dec 2017 19:48:05 +0200 Subject: [PATCH 15/33] link_vti6: Always add local/remote endpoint attributes All tunnels already support for parsing/adding zero endpoints and vti6 isn't an exception. This check was added as part of commit 2a80154fde40 (vti6: fix local/remote any addr handling) and looks too restrictive as purpose of change is to avoid endpoint configuration from uninitialized data. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/link_vti6.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ip/link_vti6.c b/ip/link_vti6.c index f631839a..4136b0e7 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -154,10 +154,8 @@ get_failed: addattr32(n, 1024, IFLA_VTI_IKEY, ikey); addattr32(n, 1024, IFLA_VTI_OKEY, okey); - if (memcmp(&saddr, &in6addr_any, sizeof(in6addr_any))) - addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr)); - if (memcmp(&daddr, &in6addr_any, sizeof(in6addr_any))) - addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr)); + addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr)); + addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr)); addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark); if (link) addattr32(n, 1024, IFLA_VTI_LINK, link); From ed7fdc950d641376352061f2799dd2d0dd72accd Mon Sep 17 00:00:00 2001 From: Alexander Zubkov Date: Sun, 17 Dec 2017 13:02:11 +0100 Subject: [PATCH 16/33] iproute: list/flush/save filter also by metric Metric is one of the "unique key" fields of the route in Linux. But still one can not use its value in filter while running ip list. Because of this writing checks in scripts for example is incovenient. Signed-off-by: Alexander Zubkov Signed-off-by: Stephen Hemminger --- ip/iproute.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ip/iproute.c b/ip/iproute.c index 16eadab1..32c93ed5 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -126,6 +126,7 @@ static struct int oif, oifmask; int mark, markmask; int realm, realmmask; + __u32 metric, metricmask; inet_prefix rprefsrc; inet_prefix rvia; inet_prefix rdst; @@ -288,6 +289,14 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) if ((mark ^ filter.mark) & filter.markmask) return 0; } + if (filter.metricmask) { + __u32 metric = 0; + + if (tb[RTA_PRIORITY]) + metric = rta_getattr_u32(tb[RTA_PRIORITY]); + if ((metric ^ filter.metric) & filter.metricmask) + return 0; + } if (filter.flushb && r->rtm_family == AF_INET6 && r->rtm_dst_len == 0 && @@ -441,7 +450,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) fprintf(fp, "src %s ", rt_addr_n2a_rta(r->rtm_family, tb[RTA_PREFSRC])); } - if (tb[RTA_PRIORITY]) + if (tb[RTA_PRIORITY] && filter.metricmask != -1) fprintf(fp, "metric %u ", rta_getattr_u32(tb[RTA_PRIORITY])); if (r->rtm_flags & RTNH_F_DEAD) fprintf(fp, "dead "); @@ -1518,6 +1527,16 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action) if (get_unsigned(&mark, *argv, 0)) invarg("invalid mark value", *argv); filter.markmask = -1; + } else if (matches(*argv, "metric") == 0 || + matches(*argv, "priority") == 0 || + strcmp(*argv, "preference") == 0) { + __u32 metric; + + NEXT_ARG(); + if (get_u32(&metric, *argv, 0)) + invarg("\"metric\" value is invalid\n", *argv); + filter.metric = metric; + filter.metricmask = -1; } else if (strcmp(*argv, "via") == 0) { int family; From 9135c4d6037ff9f1818507bac0049fc44db8c3d2 Mon Sep 17 00:00:00 2001 From: Alexander Zubkov Date: Sun, 17 Dec 2017 12:09:00 +0100 Subject: [PATCH 17/33] iproute: "list/flush/save default" selected all of the routes When running "ip route list default" and not specifying address family, one will get all of the routes instead of just default only. The same is for "exact default" and "match default". It behaves in such a way because default route with unspecified family has the same all-zeroes value like no prefix specified at all. Thus following code blindly ignores the fact, that prefix was actually specified. This patch adds the flag PREFIXLEN_SPECIFIED to the default route too. And then checks its value when filtering routes. Signed-off-by: Alexander Zubkov Signed-off-by: Stephen Hemminger --- ip/iproute.c | 65 +++++++++++++++++++++++++++++++++++++--------------- lib/utils.c | 1 + 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index 32c93ed5..bf886fda 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -191,20 +191,42 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) return 0; if ((filter.tos^r->rtm_tos)&filter.tosmask) return 0; - if (filter.rdst.family && - (r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len)) - return 0; - if (filter.mdst.family && - (r->rtm_family != filter.mdst.family || - (filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len))) - return 0; - if (filter.rsrc.family && - (r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len)) - return 0; - if (filter.msrc.family && - (r->rtm_family != filter.msrc.family || - (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len))) - return 0; + if (filter.rdst.family) { + if (r->rtm_family != filter.rdst.family || + filter.rdst.bitlen > r->rtm_dst_len) + return 0; + } else if (filter.rdst.flags & PREFIXLEN_SPECIFIED) { + if (filter.rdst.bitlen > r->rtm_dst_len) + return 0; + } + if (filter.mdst.family) { + if (r->rtm_family != filter.mdst.family || + (filter.mdst.bitlen >= 0 && + filter.mdst.bitlen < r->rtm_dst_len)) + return 0; + } else if (filter.mdst.flags & PREFIXLEN_SPECIFIED) { + if (filter.mdst.bitlen >= 0 && + filter.mdst.bitlen < r->rtm_dst_len) + return 0; + } + if (filter.rsrc.family) { + if (r->rtm_family != filter.rsrc.family || + filter.rsrc.bitlen > r->rtm_src_len) + return 0; + } else if (filter.rsrc.flags & PREFIXLEN_SPECIFIED) { + if (filter.rsrc.bitlen > r->rtm_src_len) + return 0; + } + if (filter.msrc.family) { + if (r->rtm_family != filter.msrc.family || + (filter.msrc.bitlen >= 0 && + filter.msrc.bitlen < r->rtm_src_len)) + return 0; + } else if (filter.msrc.flags & PREFIXLEN_SPECIFIED) { + if (filter.msrc.bitlen >= 0 && + filter.msrc.bitlen < r->rtm_src_len) + return 0; + } if (filter.rvia.family) { int family = r->rtm_family; @@ -221,7 +243,9 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) if (tb[RTA_DST]) memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8); - if (filter.rsrc.family || filter.msrc.family) { + if (filter.rsrc.family || filter.msrc.family || + filter.rsrc.flags & PREFIXLEN_SPECIFIED || + filter.msrc.flags & PREFIXLEN_SPECIFIED) { if (tb[RTA_SRC]) memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8); } @@ -241,15 +265,18 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8); } - if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen)) + if ((filter.rdst.family || filter.rdst.flags & PREFIXLEN_SPECIFIED) && + inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen)) return 0; - if (filter.mdst.family && filter.mdst.bitlen >= 0 && + if ((filter.mdst.family || filter.mdst.flags & PREFIXLEN_SPECIFIED) && inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len)) return 0; - if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen)) + if ((filter.rsrc.family || filter.rsrc.flags & PREFIXLEN_SPECIFIED) && + inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen)) return 0; - if (filter.msrc.family && filter.msrc.bitlen >= 0 && + if ((filter.msrc.family || filter.msrc.flags & PREFIXLEN_SPECIFIED) && + filter.msrc.bitlen >= 0 && inet_addr_match(&src, &filter.msrc, r->rtm_src_len)) return 0; diff --git a/lib/utils.c b/lib/utils.c index df1f3b12..9fa52204 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -658,6 +658,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family) dst->family = family; dst->bytelen = 0; dst->bitlen = 0; + dst->flags |= PREFIXLEN_SPECIFIED; return 0; } From 1ed8a5ca87c3dc913b3fa438ac2248edd9140616 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 20 Dec 2017 09:57:09 +0200 Subject: [PATCH 18/33] utils: ll_addr: Handle ARPHRD_IP6GRE in ll_addr_n2a() ll_addr_n2a() correctly prints tunnel endpoints for gre, ipip, sit and ip6tnl, but not for ip6gre. Fix this by adding ARPHRD_IP6GRE to IPv6 tunnel endpoing address conversion. Before: ------- $ ip link show ... 18: ip6tnl0: mtu 1452 qdisc noop state DOWN mode DEFAULT group default link/tunnel6 :: brd :: 19: ip6gre0: mtu 1456 qdisc noop state DOWN mode DEFAULT group default link/gre6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd \ 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 After: ------ $ ip link show ... 18: ip6tnl0: mtu 1452 qdisc noop state DOWN mode DEFAULT group default link/tunnel6 :: brd :: 19: ip6gre0: mtu 1456 qdisc noop state DOWN mode DEFAULT group default link/gre6 :: brd :: Signed-off-by: Serhey Popovych --- lib/ll_addr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ll_addr.c b/lib/ll_addr.c index c03523d5..84de64e2 100644 --- a/lib/ll_addr.c +++ b/lib/ll_addr.c @@ -36,7 +36,8 @@ const char *ll_addr_n2a(const unsigned char *addr, int alen, int type, char *buf (type == ARPHRD_TUNNEL || type == ARPHRD_SIT || type == ARPHRD_IPGRE)) { return inet_ntop(AF_INET, addr, buf, blen); } - if (alen == 16 && type == ARPHRD_TUNNEL6) { + if (alen == 16 && + (type == ARPHRD_TUNNEL6 || type == ARPHRD_IP6GRE)) { return inet_ntop(AF_INET6, addr, buf, blen); } snprintf(buf, blen, "%02x", addr[0]); From 08ede25fdaa1d338c1b12e297be2246cb8a3897d Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 20 Dec 2017 09:57:10 +0200 Subject: [PATCH 19/33] ip/tunnel: No need to free answer after rtnl_talk() on error Since rtnl_talk() never returns with answer buffer allocated on error we do not need to release it manually. After this initializing answer with NULL before rtnl_talk() is useless. Signed-off-by: Serhey Popovych --- ip/link_gre.c | 3 +-- ip/link_gre6.c | 3 +-- ip/link_ip6tnl.c | 3 +-- ip/link_iptnl.c | 3 +-- ip/link_vti.c | 3 +-- ip/link_vti6.c | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index 2397920a..f55c40c7 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -75,7 +75,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *greinfo[IFLA_GRE_MAX + 1]; @@ -104,7 +104,6 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 7190ada9..a3e8e088 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -86,7 +86,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *greinfo[IFLA_GRE_MAX + 1]; @@ -114,7 +114,6 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index f11ddd59..0a471c2d 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -83,7 +83,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; @@ -108,7 +108,6 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 5e4dffa6..8a8f5dd0 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -83,7 +83,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; @@ -112,7 +112,6 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } diff --git a/ip/link_vti.c b/ip/link_vti.c index 6c5469ff..2b0fab27 100644 --- a/ip/link_vti.c +++ b/ip/link_vti.c @@ -60,7 +60,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *vtiinfo[IFLA_VTI_MAX + 1]; @@ -77,7 +77,6 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } diff --git a/ip/link_vti6.c b/ip/link_vti6.c index 4136b0e7..74c246d3 100644 --- a/ip/link_vti6.c +++ b/ip/link_vti6.c @@ -55,7 +55,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; - struct nlmsghdr *answer = NULL; + struct nlmsghdr *answer; struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *vtiinfo[IFLA_VTI_MAX + 1]; @@ -72,7 +72,6 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); - free(answer); return -1; } From 147ade01b036aa0b4d6041ea0ef92608a4ded72c Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 27 Dec 2017 13:28:14 +0200 Subject: [PATCH 20/33] gre,ip6tnl/tunnel: Fix noencap- support We must clear bit, not set all but given bit. Fixes: 858dbb208e39 ("ip link: Add support for remote checksum offload to IP tunnels") Fixes: 73516e128a5a ("ip6tnl: Support for fou encapsulation" Signed-off-by: Serhey Popovych --- ip/link_gre.c | 4 ++-- ip/link_ip6tnl.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ip/link_gre.c b/ip/link_gre.c index f55c40c7..896bb19a 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -281,11 +281,11 @@ get_failed: } else if (strcmp(*argv, "encap-udp6-csum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "noencap-udp6-csum") == 0) { - encapflags |= ~TUNNEL_ENCAP_FLAG_CSUM6; + encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "encap-remcsum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "noencap-remcsum") == 0) { - encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM; + encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "external") == 0) { metadata = 1; } else if (strcmp(*argv, "ignore-df") == 0) { diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c index 0a471c2d..84205b12 100644 --- a/ip/link_ip6tnl.c +++ b/ip/link_ip6tnl.c @@ -301,7 +301,7 @@ get_failed: } else if (strcmp(*argv, "encap-remcsum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "noencap-remcsum") == 0) { - encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM; + encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "external") == 0) { metadata = 1; } else From afdf9277eb216c923e2ed729d045c07b99be2a3c Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Wed, 27 Dec 2017 13:28:15 +0200 Subject: [PATCH 21/33] gre6/tunnel: Do not submit garbage in flowinfo We always send flowinfo to the kernel. If flowlabel/tclass was set first to non-inherit value and then reset to inherit we do not clear flowlabel/tclass part in flowinfo, send it to kernel and can get from the kernel back. Even if we check for IP6_TNL_F_USE_ORIG_TCLASS and IP6_TNL_F_USE_ORIG_FLOWLABEL when printing options sending invalid flowlabel/tclass to the kernel seems bad idea. Note that ip6tnl always clean corresponding flowinfo parts on inherit. Signed-off-by: Serhey Popovych --- ip/link_gre6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ip/link_gre6.c b/ip/link_gre6.c index a3e8e088..7ae4b492 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -251,12 +251,12 @@ get_failed: __u8 uval; NEXT_ARG(); + flowinfo &= ~IP6_FLOWINFO_TCLASS; if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_TCLASS; else { if (get_u8(&uval, *argv, 16)) invarg("invalid TClass", *argv); - flowinfo &= ~IP6_FLOWINFO_TCLASS; flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; } @@ -265,6 +265,7 @@ get_failed: __u32 uval; NEXT_ARG(); + flowinfo &= ~IP6_FLOWINFO_FLOWLABEL; if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; else { @@ -272,7 +273,6 @@ get_failed: invarg("invalid Flowlabel", *argv); if (uval > 0xFFFFF) invarg("invalid Flowlabel", *argv); - flowinfo &= ~IP6_FLOWINFO_FLOWLABEL; flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; } From b97c6fa71d8ff2329bba3d655c115da78149f035 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 26 Dec 2017 11:48:45 +0200 Subject: [PATCH 22/33] qdisc: print offload indication Use the newly added TCA_HW_OFFLOAD indication from kernel to print a consistent 'offloaded' message to user when listing qdiscs. Signed-off-by: Yuval Mintz Reviewed-by: Jiri Pirko Signed-off-by: Stephen Hemminger --- tc/tc_qdisc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c index 4431d5fd..70279b9d 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -266,6 +266,10 @@ int print_qdisc(const struct sockaddr_nl *who, if (t->tcm_info != 1) print_uint(PRINT_ANY, "refcnt", "refcnt %u ", t->tcm_info); + if (tb[TCA_HW_OFFLOAD] && + (rta_getattr_u8(tb[TCA_HW_OFFLOAD]))) + print_bool(PRINT_ANY, "offloaded", "offloaded ", true); + /* pfifo_fast is generic enough to warrant the hardcoding --JHS */ if (strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])) == 0) q = get_qdisc_kind("prio"); From 8c0b19d178fe97cd991b7501a9fa051ff701d6c5 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 28 Dec 2017 13:01:04 +0200 Subject: [PATCH 23/33] vxcan,veth: Forbid "type" for peer device It is already given for original device we configure this peer for. Results from following command before/after change applied are shown below: $ ip link add dev veth1a type veth peer name veth1b \ type veth peer name veth1c Before: ------- After: ------ Error: duplicate "type": "veth" is the second value. Signed-off-by: Serhey Popovych Signed-off-by: Stephen Hemminger --- ip/iplink_vxcan.c | 3 +++ ip/link_veth.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c index c13224c3..ed0ad8b9 100644 --- a/ip/iplink_vxcan.c +++ b/ip/iplink_vxcan.c @@ -65,6 +65,9 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv, if (err < 0) return err; + if (type) + duparg("type", argv[err]); + if (name) { addattr_l(hdr, 1024, IFLA_IFNAME, name, strlen(name) + 1); diff --git a/ip/link_veth.c b/ip/link_veth.c index fcfd1ef3..fddb7ac3 100644 --- a/ip/link_veth.c +++ b/ip/link_veth.c @@ -63,6 +63,9 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv, if (err < 0) return err; + if (type) + duparg("type", argv[err]); + if (name) { addattr_l(hdr, 1024, IFLA_IFNAME, name, strlen(name) + 1); From b760a8823a297a5dc9a9170e637b826dca9c4545 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Thu, 28 Dec 2017 13:11:42 +0200 Subject: [PATCH 24/33] ip/tunnel: Document "external" parameter Add it to ip-link(8) "type gre" output help message as well as to ip-link(8) page. Signed-off-by: Serhey Popovych --- ip/link_gre.c | 1 + man/man8/ip-link.8.in | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/ip/link_gre.c b/ip/link_gre.c index 896bb19a..3c0b6d67 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -43,6 +43,7 @@ static void print_usage(FILE *f) " [ [no]encap-csum ]\n" " [ [no]encap-csum6 ]\n" " [ [no]encap-remcsum ]\n" + " [ external ]\n" " [ fwmark MARK ]\n" " [ erspan IDX ]\n" "\n" diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 94ecbece..9ddf0ffb 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -698,6 +698,8 @@ the following additional arguments are supported: .I " mode " { ip6ip | ipip | mplsip | any } " ] [ .BR erspan " \fIIDX " +] [ +.BR external ] .in +8 @@ -749,6 +751,11 @@ IPv6-Over-IPv4 is not supported for IPIP. indicates a 20 bit index/port number associated with the ERSPAN traffic's source port and direction. +.sp +.BR external +- make this tunnel externally controlled +.RB "(e.g. " "ip route encap" ). + .in -8 .TP From cd25876440aa34819db247ef10a40987f3a8fb7c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 30 Dec 2017 11:31:14 +0100 Subject: [PATCH 25/33] man: drop references to Debian-specific paths Documentation should be distribution-agnostic - any specific quirks should be handled by downstream maintainers, if necessary. Remove mentions of Debian paths and package names. Signed-off-by: Luca Boccassi Signed-off-by: Stephen Hemminger --- man/man8/lnstat.8 | 3 +-- man/man8/ss.8 | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/man/man8/lnstat.8 b/man/man8/lnstat.8 index acd5f4a2..b98241bf 100644 --- a/man/man8/lnstat.8 +++ b/man/man8/lnstat.8 @@ -254,8 +254,7 @@ Number of hash table list traversals for output traffic. Deprecated since IP route cache removal, therefore always zero. .SH SEE ALSO -.BR ip (8), -and /usr/share/doc/iproute-doc/README.lnstat (package iproute-doc on Debian) +.BR ip (8) .br .SH AUTHOR lnstat was written by Harald Welte . diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 0d526734..973afbe0 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -327,7 +327,7 @@ Read filter information from FILE. Each line of FILE is interpreted like single command line option. If FILE is - stdin is used. .TP .B FILTER := [ state STATE-FILTER ] [ EXPRESSION ] -Please take a look at the official documentation (Debian package iproute-doc) for details regarding filters. +Please take a look at the official documentation for details regarding filters. .SH STATE-FILTER @@ -382,7 +382,6 @@ Find all local processes connected to X server. List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7/24 and look at their timers. .SH SEE ALSO .BR ip (8), -.BR /usr/share/doc/iproute-doc/ss.html " (package iproute­doc)", .br .BR RFC " 793 " - https://tools.ietf.org/rfc/rfc793.txt (TCP states) From be78fade553b727a7c5bdb17e140dbc161fad85a Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 30 Dec 2017 11:31:15 +0100 Subject: [PATCH 26/33] man: add more keywords to ip.8 short description A Debian user suggested adding more network-related keywords to the ip manpage, so that manpage-scraping and indexing software like apropos can do a better job of categorizing the programs. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=877983 Suggested-by: Lynoure Braakman Signed-off-by: Luca Boccassi Signed-off-by: Stephen Hemminger --- man/man8/ip.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/ip.8 b/man/man8/ip.8 index ae018fdf..7f26582d 100644 --- a/man/man8/ip.8 +++ b/man/man8/ip.8 @@ -1,6 +1,6 @@ .TH IP 8 "20 Dec 2011" "iproute2" "Linux" .SH NAME -ip \- show / manipulate routing, devices, policy routing and tunnels +ip \- show / manipulate routing, network devices, interfaces and tunnels .SH SYNOPSIS .ad l From fe2ab15d2c9542ffd86de1d6ebe1ea5163489aa8 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 30 Dec 2017 11:31:16 +0100 Subject: [PATCH 27/33] man: ip-address: document 15-char limit for LABEL Trying to set a label longer than 15 characters returns an error: RTNETLINK answers: Numerical result out of range Document the limit in the manpage. Originally reported as a Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=661886 Reported-by: Gabor Kiss Signed-off-by: Luca Boccassi Signed-off-by: Stephen Hemminger --- man/man8/ip-address.8.in | 1 + 1 file changed, 1 insertion(+) diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in index eaa179c6..7ebf0bc9 100644 --- a/man/man8/ip-address.8.in +++ b/man/man8/ip-address.8.in @@ -190,6 +190,7 @@ Each address may be tagged with a label string. In order to preserve compatibility with Linux-2.0 net aliases, this string must coincide with the name of the device or must be prefixed with the device name followed by colon. +The maximum allowed total length of label is 15 characters. .TP .BI scope " SCOPE_VALUE" From 36c1d2383a5ffa29392bc6b0b1514e897cb3f194 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 30 Dec 2017 11:31:17 +0100 Subject: [PATCH 28/33] man: routel/routef: don't mention filesystem paths The filesytem paths to these scripts might be different on various distros, so don't mention it in the manpages. It is not really useful information anyway. Originally submitted as Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=561424 Reported-by: jidanni@jidanni.org Signed-off-by: Luca Boccassi Signed-off-by: Stephen Hemminger --- man/man8/routel.8 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/man/man8/routel.8 b/man/man8/routel.8 index 82d580fb..2270eacb 100644 --- a/man/man8/routel.8 +++ b/man/man8/routel.8 @@ -17,11 +17,6 @@ The routel script will list routes in a format that some might consider easier t .br The routef script does not take any arguments and will simply flush the routing table down the drain. Beware! This means deleting all routes which will make your network unusable! -.SH "FILES" -.LP -\fI/usr/bin/routef\fP -.br -\fI/usr/bin/routel\fP .SH "AUTHORS" .LP The routel script was written by Stephen R. van den Berg , 1999/04/18 and donated to the public domain. From c7d6cbaf8593a4b3cf674fa14b15e7c67788b675 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 2 Jan 2018 18:42:16 +0100 Subject: [PATCH 29/33] man: fix small formatting errors Lintian detected the following formatting errors: man/man8/devlink-sb.8.gz 230: warning: macro `b' not defined man/man8/ip-link.8.gz 1243: warning: macro `in-8' not defined (possibly missing space after `in') man/man8/tc-u32.8.gz `R' is a string (producing the registered sign), not a macro. Signed-off-by: Luca Boccassi Acked-by: Jiri Pirko Signed-off-by: Stephen Hemminger --- man/man8/devlink-sb.8 | 2 +- man/man8/ip-link.8.in | 2 +- man/man8/tc-u32.8 | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/man/man8/devlink-sb.8 b/man/man8/devlink-sb.8 index ffb5553e..1882833a 100644 --- a/man/man8/devlink-sb.8 +++ b/man/man8/devlink-sb.8 @@ -227,7 +227,7 @@ This command is used to browse shared buffer occupancy values. Values are showed current_value/max_value .in -16 Note that before showing values, one has to issue -.b occupancy snapshot +.B occupancy snapshot command first. .PP diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 9ddf0ffb..ff6bb9a2 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -1275,7 +1275,7 @@ or disable arptables hooks on the bridge. -.in-8 +.in -8 .TP MACsec Type Support diff --git a/man/man8/tc-u32.8 b/man/man8/tc-u32.8 index e9475a93..2bf2e3e9 100644 --- a/man/man8/tc-u32.8 +++ b/man/man8/tc-u32.8 @@ -29,10 +29,8 @@ u32 \- universal 32bit traffic control filter .IR HANDLE " ] [ " .B indev .IR ifname " ] [ " -.B skip_hw -.R "|" -.B skip_sw -.R " ] [ " +.BR skip_hw " | " +.BR skip_sw " ] [ " .BR help " ]" .ti -8 From cfd6ccbfd0311d01a29b490c472ad79b6ad8036b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 3 Jan 2018 16:28:52 +0100 Subject: [PATCH 30/33] devlink, rdma, tipc: properly define TARGETS without HAVE_MNL Leaving a variable with a generic name such as TARGETS undefined would lead to Make picking up its value from the environment. Avoid this by always defining TARGETS in the Makefiles. Signed-off-by: Matthias Schiffer --- devlink/Makefile | 4 +++- rdma/Makefile | 4 +++- tipc/Makefile | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/devlink/Makefile b/devlink/Makefile index 3afda65e..ace34c7b 100644 --- a/devlink/Makefile +++ b/devlink/Makefile @@ -1,10 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk +TARGETS := + ifeq ($(HAVE_MNL),y) DEVLINKOBJ = devlink.o mnlg.o -TARGETS=devlink +TARGETS += devlink CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags) LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs) diff --git a/rdma/Makefile b/rdma/Makefile index c8966bfd..454f25f8 100644 --- a/rdma/Makefile +++ b/rdma/Makefile @@ -1,11 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk +TARGETS := + ifeq ($(HAVE_MNL),y) RDMA_OBJ = rdma.o utils.o dev.o link.o -TARGETS=rdma +TARGETS += rdma endif all: $(TARGETS) $(LIBS) diff --git a/tipc/Makefile b/tipc/Makefile index abd33ab0..fdb18d39 100644 --- a/tipc/Makefile +++ b/tipc/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk +TARGETS := + ifeq ($(HAVE_MNL),y) TIPCOBJ=bearer.o \ @@ -10,7 +12,7 @@ TIPCOBJ=bearer.o \ node.o socket.o \ peer.o tipc.o -TARGETS=tipc +TARGETS += tipc endif From 68a7f5ed47257eb5291f41433404313cc6813ae9 Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Tue, 2 Jan 2018 23:27:57 +0200 Subject: [PATCH 31/33] link_iptnl: Kill code duplication Both sit and ipip "mode" parameter handling nearly the same. Except for sit we have "ip6ip" mode: check it only when configuring sit. Note that there is no need strcmp(lu->id, "ipip"): if it is not sit it is "ipip" because we have only these two link util defined in module. Signed-off-by: Serhey Popovych --- ip/link_iptnl.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 8a8f5dd0..d4d935bb 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -230,11 +230,11 @@ get_failed: } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "isatap") == 0) { iflags |= SIT_ISATAP; - } else if (strcmp(lu->id, "sit") == 0 && - strcmp(*argv, "mode") == 0) { + } else if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); - if (strcmp(*argv, "ipv6/ipv4") == 0 || - strcmp(*argv, "ip6ip") == 0) + if (strcmp(lu->id, "sit") == 0 && + (strcmp(*argv, "ipv6/ipv4") == 0 || + strcmp(*argv, "ip6ip") == 0)) proto = IPPROTO_IPV6; else if (strcmp(*argv, "ipv4/ipv4") == 0 || strcmp(*argv, "ipip") == 0 || @@ -248,21 +248,6 @@ get_failed: proto = 0; else invarg("Cannot guess tunnel mode.", *argv); - } else if (strcmp(lu->id, "ipip") == 0 && - strcmp(*argv, "mode") == 0) { - NEXT_ARG(); - if (strcmp(*argv, "ipv4/ipv4") == 0 || - strcmp(*argv, "ipip") == 0 || - strcmp(*argv, "ip4ip4") == 0) - proto = IPPROTO_IPIP; - else if (strcmp(*argv, "mpls/ipv4") == 0 || - strcmp(*argv, "mplsip") == 0) - proto = IPPROTO_MPLS; - else if (strcmp(*argv, "any/ipv4") == 0 || - strcmp(*argv, "any") == 0) - proto = 0; - else - invarg("Cannot guess tunnel mode.", *argv); } else if (strcmp(*argv, "noencap") == 0) { encaptype = TUNNEL_ENCAP_NONE; } else if (strcmp(*argv, "encap") == 0) { @@ -337,6 +322,7 @@ get_failed: exit(-1); } + addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); if (metadata) { addattr_l(n, 1024, IFLA_IPTUN_COLLECT_METADATA, NULL, 0); return 0; @@ -355,9 +341,6 @@ get_failed: addattr16(n, 1024, IFLA_IPTUN_ENCAP_SPORT, htons(encapsport)); addattr16(n, 1024, IFLA_IPTUN_ENCAP_DPORT, htons(encapdport)); - if (strcmp(lu->id, "ipip") == 0 || strcmp(lu->id, "sit") == 0) - addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); - if (strcmp(lu->id, "sit") == 0) { addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags); if (ip6rdprefixlen) { From d9aefbc0b865a8038883334ca8f913dc307390ea Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Tue, 2 Jan 2018 23:27:58 +0200 Subject: [PATCH 32/33] link_iptnl: Print tunnel mode Tunnel mode does not appear in parameters print for iptnl supported tunnels like ipip and sit, while printed for ip6tnl. Print tunnel mode as "proto" field name for JSON and without any name when printing to cli to follow ip6tnl behaviour. For non JSON output we have: $ ip -d link show dev sit1 Before: ------- 17: sit1@NONE: mtu 1480 qdisc noop state DOWN ... link/sit X.X.X.X brd 0.0.0.0 promiscuity 0 sit remote any local X.X.X.X ... ~~~ After: ------ 17: sit1@NONE: mtu 1480 qdisc noop state DOWN ... link/sit X.X.X.X brd 0.0.0.0 promiscuity 0 sit any remote any local X.X.X.X ... ^^^ Signed-off-by: Serhey Popovych --- ip/link_iptnl.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index d4d935bb..b6ef95df 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -372,6 +372,23 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ if (tb[IFLA_IPTUN_COLLECT_METADATA]) print_bool(PRINT_ANY, "external", "external ", true); + if (tb[IFLA_IPTUN_PROTO]) { + switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) { + case IPPROTO_IPIP: + print_string(PRINT_ANY, "proto", "%s ", "ipip"); + break; + case IPPROTO_IPV6: + print_string(PRINT_ANY, "proto", "%s ", "ip6ip"); + break; + case IPPROTO_MPLS: + print_string(PRINT_ANY, "proto", "%s ", "mplsip"); + break; + case 0: + print_string(PRINT_ANY, "proto", "%s ", "any"); + break; + } + } + if (tb[IFLA_IPTUN_REMOTE]) { unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]); From 9deb75428362de5d7cf5e971be37c6a205015e8d Mon Sep 17 00:00:00 2001 From: Serhey Popovych Date: Tue, 2 Jan 2018 23:27:59 +0200 Subject: [PATCH 33/33] link_iptnl: Open "encap" JSON object It seems missing pair of open_json_object()/close_json_object() in iptnl implementation. Note that we open "encap" JSON object in ip6tnl. Signed-off-by: Serhey Popovych --- ip/link_iptnl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index b6ef95df..24a0f0cd 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -498,6 +498,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ __u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]); __u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]); + open_json_object("encap"); print_string(PRINT_FP, NULL, "encap ", NULL); switch (type) { case TUNNEL_ENCAP_FOU: