From edbae5e0b21d915015fa87c16690171ca71b79bf Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 5 Jan 2017 16:22:21 -0800 Subject: [PATCH 01/10] ip vrf: Fix run-on error message on mkdir failure Andy reported a missing newline if a non-root user attempts to run 'ip vrf exec': $ ./ip/ip vrf exec default /bin/echo asdf mkdir failed for /var/run/cgroup2: Permission deniedFailed to setup vrf cgroup2 directory Reported-by: Andy Lutomirski Signed-off-by: David Ahern --- lib/fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fs.c b/lib/fs.c index 39cc96dc..644bb486 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -121,7 +121,7 @@ int make_path(const char *path, mode_t mode) if (mkdir(dir, mode) != 0) { fprintf(stderr, - "mkdir failed for %s: %s", + "mkdir failed for %s: %s\n", dir, strerror(errno)); goto out; } From 2bbc5b0726611d0faf7895ec01a42286e26c8ca4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 5 Jan 2017 16:22:22 -0800 Subject: [PATCH 02/10] ip vrf: Improve cgroup2 error messages Currently, if a non-root user attempts to run ip vrf exec a non-helpful error is returned: $ ip vrf exec mgmt bash Failed to mount cgroup2. Are CGROUPS enabled in your kernel? Only show the CGROUPS kernel hint for the ENODEV error and for the rest show the strerror for the errno. So now: $ ip/ip vrf exec mgmt bash Failed to mount cgroup2: Operation not permitted Signed-off-by: David Ahern --- lib/fs.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/fs.c b/lib/fs.c index 644bb486..12a4657a 100644 --- a/lib/fs.c +++ b/lib/fs.c @@ -80,13 +80,21 @@ char *find_cgroup2_mount(void) if (mount("none", mnt, CGROUP2_FS_NAME, 0, NULL)) { /* EBUSY means already mounted */ - if (errno != EBUSY) { + if (errno == EBUSY) + goto out; + + if (errno == ENODEV) { fprintf(stderr, "Failed to mount cgroup2. Are CGROUPS enabled in your kernel?\n"); - free(mnt); - return NULL; + } else { + fprintf(stderr, + "Failed to mount cgroup2: %s\n", + strerror(errno)); } + free(mnt); + return NULL; } +out: return mnt; } From 9b036afd3cb067d722817765a120a8221096b196 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 5 Jan 2017 16:22:23 -0800 Subject: [PATCH 03/10] ip vrf: Improve bpf error messages Next up a non-root user gets various bpf related error messages: $ ip vrf exec mgmt bash Failed to load BPF prog: 'Operation not permitted' Kernel compiled with CGROUP_BPF enabled? Catch the EPERM error and do not show the kernel config option. Signed-off-by: David Ahern --- ip/ipvrf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ip/ipvrf.c b/ip/ipvrf.c index dc8364a4..8bd99d62 100644 --- a/ip/ipvrf.c +++ b/ip/ipvrf.c @@ -181,7 +181,11 @@ static int vrf_configure_cgroup(const char *path, int ifindex) if (prog_fd < 0) { fprintf(stderr, "Failed to load BPF prog: '%s'\n", strerror(errno)); - fprintf(stderr, "Kernel compiled with CGROUP_BPF enabled?\n"); + + if (errno != EPERM) { + fprintf(stderr, + "Kernel compiled with CGROUP_BPF enabled?\n"); + } goto out; } From 719e331ff6190add96a60479df95e791411e5fa4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 9 Jan 2017 15:43:09 -0800 Subject: [PATCH 04/10] Add support for rt_protos.d Add support for reading proto id/name mappings from rt_protos.d directory. Allows users to have custom protocol values converted to human friendly names. Each file under rt_protos.d has the 'id name' format used by rt_protos. Only .conf files are read and parsed. Signed-off-by: David Ahern --- etc/iproute2/rt_protos.d/README | 2 ++ etc/iproute2/rt_tables.d/README | 1 - lib/rt_names.c | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 etc/iproute2/rt_protos.d/README diff --git a/etc/iproute2/rt_protos.d/README b/etc/iproute2/rt_protos.d/README new file mode 100644 index 00000000..f9c599c6 --- /dev/null +++ b/etc/iproute2/rt_protos.d/README @@ -0,0 +1,2 @@ +Each file in this directory is an rt_protos configuration file. iproute2 +commands scan this directory processing all files that end in '.conf'. diff --git a/etc/iproute2/rt_tables.d/README b/etc/iproute2/rt_tables.d/README index 79386f89..0920cb16 100644 --- a/etc/iproute2/rt_tables.d/README +++ b/etc/iproute2/rt_tables.d/README @@ -1,3 +1,2 @@ Each file in this directory is an rt_tables configuration file. iproute2 commands scan this directory processing all files that end in '.conf'. - diff --git a/lib/rt_names.c b/lib/rt_names.c index c66cb1e4..7553288e 100644 --- a/lib/rt_names.c +++ b/lib/rt_names.c @@ -142,9 +142,36 @@ static int rtnl_rtprot_init; static void rtnl_rtprot_initialize(void) { + struct dirent *de; + DIR *d; + rtnl_rtprot_init = 1; rtnl_tab_initialize(CONFDIR "/rt_protos", rtnl_rtprot_tab, 256); + + d = opendir(CONFDIR "/rt_protos.d"); + if (!d) + return; + + while ((de = readdir(d)) != NULL) { + char path[PATH_MAX]; + size_t len; + + if (*de->d_name == '.') + continue; + + /* only consider filenames ending in '.conf' */ + len = strlen(de->d_name); + if (len <= 5) + continue; + if (strcmp(de->d_name + len - 5, ".conf")) + continue; + + snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s", + de->d_name); + rtnl_tab_initialize(path, rtnl_rtprot_tab, 256); + } + closedir(d); } const char *rtnl_rtprot_n2a(int id, char *buf, int len) From 3bad1dbb2065bf40b7a561fef751ce96f1d2b122 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 12 Jan 2017 17:29:41 -0800 Subject: [PATCH 05/10] whitespace cleanup Get rid of blanks at end of line and extra lines at eof Signed-off-by: Stephen Hemminger --- bridge/Makefile | 3 +-- etc/iproute2/nl_protos | 4 ++-- lib/Makefile | 1 - man/man3/libnetlink.3 | 38 +++++++++++++++++++------------------- man/man8/.gitignore | 1 - netem/Makefile | 2 +- 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/bridge/Makefile b/bridge/Makefile index 7203f70b..634c370a 100644 --- a/bridge/Makefile +++ b/bridge/Makefile @@ -8,7 +8,7 @@ endif all: bridge -bridge: $(BROBJ) $(LIBNETLINK) +bridge: $(BROBJ) $(LIBNETLINK) $(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@ install: all @@ -16,4 +16,3 @@ install: all clean: rm -f $(BROBJ) bridge - diff --git a/etc/iproute2/nl_protos b/etc/iproute2/nl_protos index 43418f36..7c17cf0f 100644 --- a/etc/iproute2/nl_protos +++ b/etc/iproute2/nl_protos @@ -12,7 +12,7 @@ 9 audit 10 fiblookup 11 connector -12 nft +12 nft 13 ip6fw 14 dec-rt 15 uevent @@ -20,4 +20,4 @@ 18 scsi-trans 19 ecryptfs 20 rdma -21 crypto +21 crypto diff --git a/lib/Makefile b/lib/Makefile index 0c57662b..1d24ca24 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -24,4 +24,3 @@ install: clean: rm -f $(NLOBJ) $(UTILOBJ) $(ADDLIB) libnetlink.a libutil.a - diff --git a/man/man3/libnetlink.3 b/man/man3/libnetlink.3 index 99be9cc9..8e3dc620 100644 --- a/man/man3/libnetlink.3 +++ b/man/man3/libnetlink.3 @@ -32,12 +32,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, .br void *jarg) .sp -int rtnl_listen(struct rtnl_handle *rtnl, +int rtnl_listen(struct rtnl_handle *rtnl, int (*handler)(struct sockaddr_nl *, struct rtnl_ctrl_data *, struct nlmsghdr *n, void *), void *jarg) .sp -int rtnl_from_file(FILE *rtnl, +int rtnl_from_file(FILE *rtnl, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *), void *jarg) .sp @@ -49,35 +49,35 @@ int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) .sp int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen) .SH DESCRIPTION -libnetlink provides a higher level interface to -.BR rtnetlink(7). +libnetlink provides a higher level interface to +.BR rtnetlink(7). The read functions return 0 on success and a negative errno on failure. The send functions return the amount of data sent, or -1 on error. -.TP +.TP rtnl_open Open a rtnetlink socket and save the state into the .B rth -handle. This handle is passed to all subsequent calls. +handle. This handle is passed to all subsequent calls. .B subscriptions is a bitmap of the rtnetlink multicast groups the socket will be a member of. .TP rtnl_wilddump_request -Request a full dump of the +Request a full dump of the .B type database for .B family addresses. .B type -is a rtnetlink message type. +is a rtnetlink message type. .\" XXX .TP rtnl_dump_request -Request a full dump of the -.B type -data buffer into +Request a full dump of the +.B type +data buffer into .B buf with maximum length of .B len. @@ -91,12 +91,12 @@ The .B filter callback checks if the received message is wanted. It gets the source address of the message, the message itself and -.B arg1 +.B arg1 as arguments. 0 as return means that the filter passed, a negative value is returned by -.I rtnl_dump_filter -in case of error. NULL for +.I rtnl_dump_filter +in case of error. NULL for .I filter means to not use a filter. .B junk @@ -106,7 +106,7 @@ pending, this function does not block. .TP rtnl_listen -Receive netlink data after a request and pass it to +Receive netlink data after a request and pass it to .I handler. .B handler is a callback that gets the message source address, anscillary data, the message @@ -118,8 +118,8 @@ pending this function does not block. .TP rtnl_from_file -Works like -.I rtnl_listen, +Works like +.I rtnl_listen, but reads a netlink message bundle from the file .B file and passes the messages to @@ -134,7 +134,7 @@ and .BR netlink(3) on how to generate a rtnetlink message. The following utility functions require a continuous buffer that already contains a netlink message header -and a rtnetlink request. +and a rtnetlink request. .TP rtnl_send @@ -168,7 +168,7 @@ length to netlink message .B n, which is part of a buffer of length .B maxlen. -.B data +.B data is copied. .TP diff --git a/man/man8/.gitignore b/man/man8/.gitignore index 4f1a476d..0c3d1504 100644 --- a/man/man8/.gitignore +++ b/man/man8/.gitignore @@ -2,4 +2,3 @@ ip-address.8 ip-link.8 ip-route.8 - diff --git a/netem/Makefile b/netem/Makefile index e52e125e..a68e2fdb 100644 --- a/netem/Makefile +++ b/netem/Makefile @@ -3,7 +3,7 @@ DISTDATA = normal.dist pareto.dist paretonormal.dist experimental.dist HOSTCC ?= $(CC) CCOPTS = $(CBUILD_CFLAGS) -LDLIBS += -lm +LDLIBS += -lm all: $(DISTGEN) $(DISTDATA) From 97a02cabefb2e2dcfe27f89943709afa84be5525 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 12 Jan 2017 15:22:49 +0100 Subject: [PATCH 06/10] tc: m_xt: Fix segfault with iptables-1.6.0 Said iptables version introduced struct xtables_globals field 'compat_rev', a function pointer. Initializing it is mandatory as libxtables calls it without existence check. Without this, tc segfaults when using the xt action like so: | tc filter add dev d0 parent ffff: u32 match u32 0 0 \ | action xt -j MARK --set-mark 20 Signed-off-by: Phil Sutter --- tc/m_xt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tc/m_xt.c b/tc/m_xt.c index dbb54981..57ed40d7 100644 --- a/tc/m_xt.c +++ b/tc/m_xt.c @@ -77,6 +77,9 @@ static struct xtables_globals tcipt_globals = { .orig_opts = original_opts, .opts = original_opts, .exit_err = NULL, +#if (XTABLES_VERSION_CODE >= 11) + .compat_rev = xtables_compatible_revision, +#endif }; /* From 40f9070d94f945bbba6baf48ebf65ac0d25bac0a Mon Sep 17 00:00:00 2001 From: David Forster Date: Tue, 10 Jan 2017 10:45:54 +0000 Subject: [PATCH 07/10] ip6tunnel: Align ipv6 tunnel key display with ipv4 Show ipv6 tunnel keys on presence of GRE_KEY flag for tunnel types other than GRE. Aligns ipv6 behaviour with ipv4. Signed-off-by: dforster@brocade.com --- ip/ip6tunnel.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c index b1c0ae62..b4a7def1 100644 --- a/ip/ip6tunnel.c +++ b/ip/ip6tunnel.c @@ -111,16 +111,17 @@ static void print_tunnel(struct ip6_tnl_parm2 *p) if (p->flags & IP6_TNL_F_RCV_DSCP_COPY) printf(" dscp inherit"); - if (p->proto == IPPROTO_GRE) { - if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && p->o_key == p->i_key) - printf(" key %u", ntohl(p->i_key)); - else if ((p->i_flags | p->o_flags) & GRE_KEY) { - if (p->i_flags & GRE_KEY) - printf(" ikey %u", ntohl(p->i_key)); - if (p->o_flags & GRE_KEY) - printf(" okey %u", ntohl(p->o_key)); - } + if ((p->i_flags & GRE_KEY) && (p->o_flags & GRE_KEY) && + p->o_key == p->i_key) + printf(" key %u", ntohl(p->i_key)); + else { + if (p->i_flags & GRE_KEY) + printf(" ikey %u", ntohl(p->i_key)); + if (p->o_flags & GRE_KEY) + printf(" okey %u", ntohl(p->o_key)); + } + if (p->proto == IPPROTO_GRE) { if (p->i_flags & GRE_SEQ) printf("%s Drop packets out of sequence.", _SL_); if (p->i_flags & GRE_CSUM) From 5ffbf4508cc7da4c1a0e53569228f6e4a17dca5b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 10 Jan 2017 15:33:55 -0800 Subject: [PATCH 08/10] rttable: Fix invalid range checking when table id is converted to u32 Frank reported that table ids for very large numbers are not properly detected: $ ip li add foobar type vrf table 98765432100123456789 command succeeds and resulting table id is actually: 21: foobar: mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether da:ea:d4:77:38:2a brd ff:ff:ff:ff:ff:ff promiscuity 0 vrf table 4294967295 addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 Make the temp variable 'i' unsigned long and let the typecast to u32 happen on assignment to id. Reported-by: Frank Kellermann Signed-off-by: David Ahern --- lib/rt_names.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rt_names.c b/lib/rt_names.c index 7553288e..3a16d5cf 100644 --- a/lib/rt_names.c +++ b/lib/rt_names.c @@ -431,7 +431,7 @@ int rtnl_rttable_a2n(__u32 *id, const char *arg) static unsigned long res; struct rtnl_hash_entry *entry; char *end; - __u32 i; + unsigned long i; if (cache && strcmp(cache, arg) == 0) { *id = res; From 7f10090b9f2f254121fbd07cee3d2a9144532ae7 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Thu, 12 Jan 2017 17:47:39 +0100 Subject: [PATCH 09/10] bridge: fdb: add state filter support This patch adds a new argument to the bridge fdb show command that allows to filter by entry state. Also update the man page to include all available show arguments. Signed-off-by: Nikolay Aleksandrov --- bridge/fdb.c | 32 ++++++++++++++++++++++++++++++-- man/man8/bridge.8 | 10 +++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/bridge/fdb.c b/bridge/fdb.c index a9152177..a71a78f2 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -29,7 +29,7 @@ #include "rt_names.h" #include "utils.h" -static unsigned int filter_index, filter_vlan; +static unsigned int filter_index, filter_vlan, filter_state; json_writer_t *jw_global; @@ -39,7 +39,7 @@ static void usage(void) " [ self ] [ master ] [ use ] [ router ]\n" " [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n" " [ port PORT] [ vni VNI ] [ via DEV ]\n"); - fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] ]\n"); + fprintf(stderr, " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n"); exit(-1); } @@ -63,6 +63,24 @@ static const char *state_n2a(unsigned int s) return buf; } +static int state_a2n(unsigned int *s, const char *arg) +{ + if (matches(arg, "permanent") == 0) + *s = NUD_PERMANENT; + else if (matches(arg, "static") == 0 || matches(arg, "temp") == 0) + *s = NUD_NOARP; + else if (matches(arg, "stale") == 0) + *s = NUD_STALE; + else if (matches(arg, "reachable") == 0 || matches(arg, "dynamic") == 0) + *s = NUD_REACHABLE; + else if (strcmp(arg, "all") == 0) + *s = ~0; + else if (get_unsigned(s, arg, 0)) + return -1; + + return 0; +} + static void start_json_fdb_flags_array(bool *fdb_flags) { if (*fdb_flags) @@ -100,6 +118,9 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (filter_index && filter_index != r->ndm_ifindex) return 0; + if (filter_state && !(r->ndm_state & filter_state)) + return 0; + parse_rtattr(tb, NDA_MAX, NDA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); @@ -310,6 +331,13 @@ static int fdb_show(int argc, char **argv) if (filter_vlan) duparg("vlan", *argv); filter_vlan = atoi(*argv); + } else if (strcmp(*argv, "state") == 0) { + unsigned int state; + + NEXT_ARG(); + if (state_a2n(&state, *argv)) + invarg("invalid state", *argv); + filter_state |= state; } else { if (matches(*argv, "help") == 0) usage(); diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 index 6617e188..9c5f855d 100644 --- a/man/man8/bridge.8 +++ b/man/man8/bridge.8 @@ -70,7 +70,15 @@ bridge \- show / manipulate bridge addresses and devices .ti -8 .BR "bridge fdb" " [ " show " ] [ " .B dev -.IR DEV " ]" +.IR DEV " ] [ " +.B br +.IR BRDEV " ] [ " +.B brport +.IR DEV " ] [ " +.B vlan +.IR VID " ] [ " +.B state +.IR STATE " ]" .ti -8 .BR "bridge mdb" " { " add " | " del " } " From aeeaae2fa99c79f168df7cfc1db1824d0bf006c3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 11 Jan 2017 14:10:16 +0100 Subject: [PATCH 10/10] tc: ife: correct spelling of prio in example Correct typo in example in ife man page. Fixes: 06f9a59170c0 ("man: tc-ife.8: man page for ife action") Cc: Lucas Bates Signed-off-by: Simon Horman --- man/man8/tc-ife.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/tc-ife.8 b/man/man8/tc-ife.8 index aaf0f97d..dae8b9be 100644 --- a/man/man8/tc-ife.8 +++ b/man/man8/tc-ife.8 @@ -99,7 +99,7 @@ classification so that it will match ICMP on the next rule, at prio 3: # tc filter add dev eth0 parent ffff: prio 2 protocol 0xdead \\ u32 match u32 0 0 flowid 1:1 \\ action ife decode reclassify -# tc filter add dev eth0 parent ffff: priod 3 protocol ip \\ +# tc filter add dev eth0 parent ffff: prio 3 protocol ip \\ u32 match ip protocol 0xff flowid 1:1 \\ action continue .EE