netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering
@ 2018-12-20  3:54 David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 01/12] libnetlink: dump extack string in done message David Ahern
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Refactorings and updates to use the new strict checking in the kernel
along with the new kernel side filtering.

David Ahern (12):
  libnetlink: dump extack string in done message
  libnetlink: Use NLMSG_LENGTH to set nlmsg_len
  libnetlink: linkdump_req: Only AF_UNSPEC family expects an
    ext_filter_mask
  ip route: Remove rtnl_rtcache_request
  ip route: Add protocol, table id and device to dump request
  mroute: fix up family handling
  mroute: Add table id attribute for kernel side filtering
  ip address: Split ip_linkaddr_list into link and addr functions
  ip address: Set device index in dump request
  ip bridge: Set NETLINK_DUMP_STRICT_CHK on socket
  ip route: Rename do_ipv6 to dump_family
  neighbor: Add support for protocol attribute

 bridge/bridge.c      |   4 ++
 include/libnetlink.h |  11 +--
 ip/ip.c              |   2 +
 ip/ip_common.h       |   3 +-
 ip/ipaddress.c       |  92 ++++++++++++++++++------
 ip/ipmroute.c        |  31 ++++++---
 ip/ipneigh.c         |  39 ++++++++++-
 ip/iproute.c         |  89 ++++++++++++------------
 ip/ipvrf.c           |   2 +-
 lib/libnetlink.c     | 192 ++++++++++++++++++++++++++++++++++++++-------------
 10 files changed, 330 insertions(+), 135 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 01/12] libnetlink: dump extack string in done message
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 02/12] libnetlink: Use NLMSG_LENGTH to set nlmsg_len David Ahern
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Print any extack message that has been appended to a NLMSG_DONE message.
To avoid duplication, move the existing print code to a new helper.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 lib/libnetlink.c | 44 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 954571097ea8..e28e1ab6da5e 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -67,6 +67,14 @@ static int err_attr_cb(const struct nlattr *attr, void *data)
 	return MNL_CB_OK;
 }
 
+static void print_ext_ack_msg(bool is_err, const char *msg)
+{
+	fprintf(stderr, "%s: %s", is_err ? "Error" : "Warning", msg);
+	if (msg[strlen(msg) - 1] != '.')
+		fprintf(stderr, ".");
+	fprintf(stderr, "\n");
+}
+
 /* dump netlink extended ack error message */
 int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
 {
@@ -108,12 +116,29 @@ int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
 	if (msg && *msg != '\0') {
 		bool is_err = !!err->error;
 
-		fprintf(stderr, "%s: %s",
-			is_err ? "Error" : "Warning", msg);
-		if (msg[strlen(msg) - 1] != '.')
-			fprintf(stderr, ".");
-		fprintf(stderr, "\n");
+		print_ext_ack_msg(is_err, msg);
+		return is_err ? 1 : 0;
+	}
 
+	return 0;
+}
+
+static int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error)
+{
+	struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
+	unsigned int hlen = sizeof(int);
+	const char *msg = NULL;
+
+	if (mnl_attr_parse(nlh, hlen, err_attr_cb, tb) != MNL_CB_OK)
+		return 0;
+
+	if (tb[NLMSGERR_ATTR_MSG])
+		msg = mnl_attr_get_str(tb[NLMSGERR_ATTR_MSG]);
+
+	if (msg && *msg != '\0') {
+		bool is_err = !!error;
+
+		print_ext_ack_msg(is_err, msg);
 		return is_err ? 1 : 0;
 	}
 
@@ -127,6 +152,11 @@ int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn)
 {
 	return 0;
 }
+
+static int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error)
+{
+	return 0;
+}
 #endif
 
 void rtnl_close(struct rtnl_handle *rth)
@@ -512,6 +542,10 @@ static int rtnl_dump_done(struct nlmsghdr *h)
 	}
 
 	if (len < 0) {
+		/* check for any messages returned from kernel */
+		if (nl_dump_ext_ack_done(h, len))
+			return len;
+
 		errno = -len;
 		switch (errno) {
 		case ENOENT:
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 02/12] libnetlink: Use NLMSG_LENGTH to set nlmsg_len
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 01/12] libnetlink: dump extack string in done message David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 03/12] libnetlink: linkdump_req: Only AF_UNSPEC family expects an ext_filter_mask David Ahern
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Change nlmsg_len from sizeof(req) to use NLMSG_LENGTH on the header.
2 of the inner headers are not 4-byte aligned, so add a 0-length buf
after the header with the __aligned(NLMSG_ALIGNTO) to ensure the size
of the request is large enough. Use NLMSG_ALIGN in NLMSG_LENGTH to set
nlmsg_len.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 lib/libnetlink.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index e28e1ab6da5e..8ab2355fc26b 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -28,6 +28,8 @@
 
 #include "libnetlink.h"
 
+#define __aligned(x)		__attribute__((aligned(x)))
+
 #ifndef SOL_NETLINK
 #define SOL_NETLINK 270
 #endif
@@ -238,7 +240,7 @@ int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct ifaddrmsg ifm;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
 		.nlh.nlmsg_type = RTM_GETADDR,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -254,7 +256,7 @@ int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct ifaddrlblmsg ifal;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg)),
 		.nlh.nlmsg_type = RTM_GETADDRLABEL,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -270,7 +272,7 @@ int rtnl_routedump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct rtmsg rtm;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
 		.nlh.nlmsg_type = RTM_GETROUTE,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -286,7 +288,7 @@ int rtnl_ruledump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct fib_rule_hdr frh;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)),
 		.nlh.nlmsg_type = RTM_GETRULE,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -302,7 +304,7 @@ int rtnl_neighdump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct ndmsg ndm;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
 		.nlh.nlmsg_type = RTM_GETNEIGH,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -318,7 +320,7 @@ int rtnl_neightbldump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct ndtmsg ndtmsg;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg)),
 		.nlh.nlmsg_type = RTM_GETNEIGHTBL,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -334,7 +336,7 @@ int rtnl_mdbdump_req(struct rtnl_handle *rth, int family)
 		struct nlmsghdr nlh;
 		struct br_port_msg bpm;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_port_msg)),
 		.nlh.nlmsg_type = RTM_GETMDB,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -349,8 +351,9 @@ int rtnl_netconfdump_req(struct rtnl_handle *rth, int family)
 	struct {
 		struct nlmsghdr nlh;
 		struct netconfmsg ncm;
+		char buf[0] __aligned(NLMSG_ALIGNTO);
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct netconfmsg))),
 		.nlh.nlmsg_type = RTM_GETNETCONF,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -365,8 +368,9 @@ int rtnl_nsiddump_req(struct rtnl_handle *rth, int family)
 	struct {
 		struct nlmsghdr nlh;
 		struct rtgenmsg rtm;
+		char buf[0] __aligned(NLMSG_ALIGNTO);
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct rtgenmsg))),
 		.nlh.nlmsg_type = RTM_GETNSID,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
@@ -388,7 +392,7 @@ int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int family,
 		struct nlmsghdr nlh;
 		struct ifinfomsg ifm;
 		/* attribute has to be NLMSG aligned */
-		struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO)));
+		struct rtattr ext_req __aligned(NLMSG_ALIGNTO);
 		__u32 ext_filter_mask;
 	} req = {
 		.nlh.nlmsg_len = sizeof(req),
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 03/12] libnetlink: linkdump_req: Only AF_UNSPEC family expects an ext_filter_mask
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 01/12] libnetlink: dump extack string in done message David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 02/12] libnetlink: Use NLMSG_LENGTH to set nlmsg_len David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 04/12] ip route: Remove rtnl_rtcache_request David Ahern
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Only AF_UNSPEC handled by rtnl_dump_ifinfo expects an ext_filter_mask
on a dump request. Update the linkdump request functions to only set
and send ext_filter_mask for AF_UNSPEC.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 lib/libnetlink.c | 93 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 33 deletions(-)

diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 8ab2355fc26b..b9c37fd36211 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -380,58 +380,85 @@ int rtnl_nsiddump_req(struct rtnl_handle *rth, int family)
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
-int rtnl_linkdump_req(struct rtnl_handle *rth, int family)
-{
-	return rtnl_linkdump_req_filter(rth, family, RTEXT_FILTER_VF);
-}
-
-int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int family,
-			    __u32 filt_mask)
+static int __rtnl_linkdump_req(struct rtnl_handle *rth, int family)
 {
 	struct {
 		struct nlmsghdr nlh;
 		struct ifinfomsg ifm;
-		/* attribute has to be NLMSG aligned */
-		struct rtattr ext_req __aligned(NLMSG_ALIGNTO);
-		__u32 ext_filter_mask;
 	} req = {
-		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 		.nlh.nlmsg_type = RTM_GETLINK,
 		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
 		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
 		.ifm.ifi_family = family,
-		.ext_req.rta_type = IFLA_EXT_MASK,
-		.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)),
-		.ext_filter_mask = filt_mask,
 	};
 
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
+int rtnl_linkdump_req(struct rtnl_handle *rth, int family)
+{
+	if (family == AF_UNSPEC)
+		return rtnl_linkdump_req_filter(rth, family, RTEXT_FILTER_VF);
+
+	return __rtnl_linkdump_req(rth, family);
+}
+
+int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int family,
+			    __u32 filt_mask)
+{
+	if (family == AF_UNSPEC) {
+		struct {
+			struct nlmsghdr nlh;
+			struct ifinfomsg ifm;
+			/* attribute has to be NLMSG aligned */
+			struct rtattr ext_req __aligned(NLMSG_ALIGNTO);
+			__u32 ext_filter_mask;
+		} req = {
+			.nlh.nlmsg_len = sizeof(req),
+			.nlh.nlmsg_type = RTM_GETLINK,
+			.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+			.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+			.ifm.ifi_family = family,
+			.ext_req.rta_type = IFLA_EXT_MASK,
+			.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)),
+			.ext_filter_mask = filt_mask,
+		};
+
+		return send(rth->fd, &req, sizeof(req), 0);
+	}
+
+	return __rtnl_linkdump_req(rth, family);
+}
+
 int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int family,
 				req_filter_fn_t filter_fn)
 {
-	struct {
-		struct nlmsghdr nlh;
-		struct ifinfomsg ifm;
-		char buf[1024];
-	} req = {
-		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-		.nlh.nlmsg_type = RTM_GETLINK,
-		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
-		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
-		.ifm.ifi_family = family,
-	};
-	int err;
-
-	if (!filter_fn)
-		return -EINVAL;
+	if (family == AF_UNSPEC) {
+		struct {
+			struct nlmsghdr nlh;
+			struct ifinfomsg ifm;
+			char buf[1024];
+		} req = {
+			.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+			.nlh.nlmsg_type = RTM_GETLINK,
+			.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+			.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+			.ifm.ifi_family = family,
+		};
+		int err;
+
+		if (!filter_fn)
+			return -EINVAL;
+
+		err = filter_fn(&req.nlh, sizeof(req));
+		if (err)
+			return err;
 
-	err = filter_fn(&req.nlh, sizeof(req));
-	if (err)
-		return err;
+		return send(rth->fd, &req, req.nlh.nlmsg_len, 0);
+	}
 
-	return send(rth->fd, &req, req.nlh.nlmsg_len, 0);
+	return __rtnl_linkdump_req(rth, family);
 }
 
 int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 04/12] ip route: Remove rtnl_rtcache_request
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (2 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 03/12] libnetlink: linkdump_req: Only AF_UNSPEC family expects an ext_filter_mask David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 05/12] ip route: Add protocol, table id and device to dump request David Ahern
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Add a filter option to rtnl_routedump_req and use it to set rtm_flags
removing the need for rtnl_rtcache_request for dump requests.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/libnetlink.h |  7 ++++---
 ip/ipmroute.c        |  2 +-
 ip/iproute.c         | 43 ++++++++++++++-----------------------------
 lib/libnetlink.c     | 12 +++++++++++-
 4 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index 138840d5c892..b0051f390980 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -47,11 +47,14 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions,
 
 void rtnl_close(struct rtnl_handle *rth);
 
+typedef int (*req_filter_fn_t)(struct nlmsghdr *nlh, int reqlen);
+
 int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
 int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
-int rtnl_routedump_req(struct rtnl_handle *rth, int family)
+int rtnl_routedump_req(struct rtnl_handle *rth, int family,
+		       req_filter_fn_t filter_fn)
 	__attribute__((warn_unused_result));
 int rtnl_ruledump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
@@ -71,8 +74,6 @@ int rtnl_linkdump_req(struct rtnl_handle *rth, int fam)
 int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask)
 	__attribute__((warn_unused_result));
 
-typedef int (*req_filter_fn_t)(struct nlmsghdr *nlh, int reqlen);
-
 int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int fam,
 				req_filter_fn_t fn)
 	__attribute__((warn_unused_result));
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index 4d8867d3219f..de7a035f852f 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -283,7 +283,7 @@ static int mroute_list(int argc, char **argv)
 		filter.iif = idx;
 	}
 
-	if (rtnl_routedump_req(&rth, filter.af) < 0) {
+	if (rtnl_routedump_req(&rth, filter.af, NULL) < 0) {
 		perror("Cannot send dump request");
 		return 1;
 	}
diff --git a/ip/iproute.c b/ip/iproute.c
index d34724692553..3c0be0a96d4e 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1535,24 +1535,6 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
 	return 0;
 }
 
-static int rtnl_rtcache_request(struct rtnl_handle *rth, int family)
-{
-	struct {
-		struct nlmsghdr nlh;
-		struct rtmsg rtm;
-	} req = {
-		.nlh.nlmsg_len = sizeof(req),
-		.nlh.nlmsg_type = RTM_GETROUTE,
-		.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST,
-		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
-		.rtm.rtm_family = family,
-		.rtm.rtm_flags = RTM_F_CLONED,
-	};
-	struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
-
-	return sendto(rth->fd, (void *)&req, sizeof(req), 0, (struct sockaddr *)&nladdr, sizeof(nladdr));
-}
-
 static int iproute_flush_cache(void)
 {
 #define ROUTE_FLUSH_PATH "/proc/sys/net/ipv4/route/flush"
@@ -1644,7 +1626,7 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 	filter.flushe = sizeof(flushb);
 
 	for (;;) {
-		if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
+		if (rtnl_routedump_req(&rth, do_ipv6, NULL) < 0) {
 			perror("Cannot send dump request");
 			return -2;
 		}
@@ -1684,6 +1666,16 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 	}
 }
 
+static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+	struct rtmsg *rtm = NLMSG_DATA(nlh);
+
+	if (filter.cloned)
+		rtm->rtm_flags |= RTM_F_CLONED;
+
+	return 0;
+}
+
 static int iproute_list_flush_or_save(int argc, char **argv, int action)
 {
 	int do_ipv6 = preferred_family;
@@ -1889,16 +1881,9 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 	if (action == IPROUTE_FLUSH)
 		return iproute_flush(do_ipv6, filter_fn);
 
-	if (!filter.cloned) {
-		if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
-			perror("Cannot send dump request");
-			return -2;
-		}
-	} else {
-		if (rtnl_rtcache_request(&rth, do_ipv6) < 0) {
-			perror("Cannot send dump request");
-			return -2;
-		}
+	if (rtnl_routedump_req(&rth, do_ipv6, iproute_dump_filter) < 0) {
+		perror("Cannot send dump request");
+		return -2;
 	}
 
 	new_json_obj(json);
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index b9c37fd36211..56a1cadeb3db 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -266,11 +266,13 @@ int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
-int rtnl_routedump_req(struct rtnl_handle *rth, int family)
+int rtnl_routedump_req(struct rtnl_handle *rth, int family,
+		       req_filter_fn_t filter_fn)
 {
 	struct {
 		struct nlmsghdr nlh;
 		struct rtmsg rtm;
+		char buf[128];
 	} req = {
 		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
 		.nlh.nlmsg_type = RTM_GETROUTE,
@@ -279,6 +281,14 @@ int rtnl_routedump_req(struct rtnl_handle *rth, int family)
 		.rtm.rtm_family = family,
 	};
 
+	if (filter_fn) {
+		int err;
+
+		err = filter_fn(&req.nlh, sizeof(req));
+		if (err)
+			return err;
+	}
+
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 05/12] ip route: Add protocol, table id and device to dump request
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (3 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 04/12] ip route: Remove rtnl_rtcache_request David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 06/12] mroute: fix up family handling David Ahern
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Add protocol, table id and device to dump request if set in filter. If
kernel side filtering is supported it is used to reduce the amount of
data sent to userspace.

Older kernels do not parse attributes on a route dump request, so these
are silently ignored and ip will do the filtering in userspace.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/iproute.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/ip/iproute.c b/ip/iproute.c
index 3c0be0a96d4e..5bffb9d88b58 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1669,10 +1669,24 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
 {
 	struct rtmsg *rtm = NLMSG_DATA(nlh);
+	int err;
 
+	rtm->rtm_protocol = filter.protocol;
 	if (filter.cloned)
 		rtm->rtm_flags |= RTM_F_CLONED;
 
+	if (filter.tb) {
+		err = addattr32(nlh, reqlen, RTA_TABLE, filter.tb);
+		if (err)
+			return err;
+	}
+
+	if (filter.oif) {
+		err = addattr32(nlh, reqlen, RTA_OIF, filter.oif);
+		if (err)
+			return err;
+	}
+
 	return 0;
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 06/12] mroute: fix up family handling
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (4 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 05/12] ip route: Add protocol, table id and device to dump request David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 07/12] mroute: Add table id attribute for kernel side filtering David Ahern
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Only ipv4 and ipv6 have multicast routing. Set family
accordingly and just return for other cases.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/ipmroute.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index de7a035f852f..b8f0bc49b92e 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -223,18 +223,20 @@ void ipmroute_reset_filter(int ifindex)
 static int mroute_list(int argc, char **argv)
 {
 	char *id = NULL;
-	int family;
+	int family = preferred_family;
 
 	ipmroute_reset_filter(0);
-	if (preferred_family == AF_UNSPEC)
-		family = AF_INET;
-	else
-		family = AF_INET6;
-	if (family == AF_INET) {
+	if (family == AF_INET || family == AF_UNSPEC) {
+		family = RTNL_FAMILY_IPMR;
 		filter.af = RTNL_FAMILY_IPMR;
 		filter.tb = RT_TABLE_DEFAULT;  /* for backward compatibility */
-	} else
+	} else if (family == AF_INET6) {
+		family = RTNL_FAMILY_IP6MR;
 		filter.af = RTNL_FAMILY_IP6MR;
+	} else {
+		/* family does not have multicast routing */
+		return 0;
+	}
 
 	filter.msrc.family = filter.mdst.family = family;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 07/12] mroute: Add table id attribute for kernel side filtering
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (5 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 06/12] mroute: fix up family handling David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 08/12] ip address: Split ip_linkaddr_list into link and addr functions David Ahern
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Similar to 'ip route' add the table id to the dump request for
kernel side filtering if it is supported.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/ipmroute.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index b8f0bc49b92e..b29c78e4cc86 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -220,6 +220,19 @@ void ipmroute_reset_filter(int ifindex)
 	filter.iif = ifindex;
 }
 
+static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+	int err;
+
+	if (filter.tb) {
+		err = addattr32(nlh, reqlen, RTA_TABLE, filter.tb);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int mroute_list(int argc, char **argv)
 {
 	char *id = NULL;
@@ -285,7 +298,7 @@ static int mroute_list(int argc, char **argv)
 		filter.iif = idx;
 	}
 
-	if (rtnl_routedump_req(&rth, filter.af, NULL) < 0) {
+	if (rtnl_routedump_req(&rth, filter.af, iproute_dump_filter) < 0) {
 		perror("Cannot send dump request");
 		return 1;
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 08/12] ip address: Split ip_linkaddr_list into link and addr functions
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (6 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 07/12] mroute: Add table id attribute for kernel side filtering David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 09/12] ip address: Set device index in dump request David Ahern
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Split ip_linkaddr_list into one function that generates a list of devices
and a second that generates the list of addresses.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/ip_common.h |  3 +--
 ip/ipaddress.c | 39 ++++++++++++++++++++-------------------
 ip/ipvrf.c     |  2 +-
 3 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/ip/ip_common.h b/ip/ip_common.h
index 53668f598cd2..d67575c63c24 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -84,8 +84,7 @@ int do_seg6(int argc, char **argv);
 int iplink_get(char *name, __u32 filt_mask);
 int iplink_ifla_xstats(int argc, char **argv);
 
-int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
-		     struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo);
+int ip_link_list(req_filter_fn_t filter_fn, struct nlmsg_chain *linfo);
 void free_nlmsg_chain(struct nlmsg_chain *info);
 
 static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 016662e910e9..746dbfc58627 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1766,8 +1766,7 @@ static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
  * caller can walk lists as desired and must call free_nlmsg_chain for
  * both when done
  */
-int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
-		     struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
+int ip_link_list(req_filter_fn_t filter_fn, struct nlmsg_chain *linfo)
 {
 	if (rtnl_linkdump_req_filter_fn(&rth, preferred_family,
 					filter_fn) < 0) {
@@ -1780,16 +1779,19 @@ int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
 		return 1;
 	}
 
-	if (ainfo) {
-		if (rtnl_addrdump_req(&rth, family) < 0) {
-			perror("Cannot send dump request");
-			return 1;
-		}
+	return 0;
+}
 
-		if (rtnl_dump_filter(&rth, store_nlmsg, ainfo) < 0) {
-			fprintf(stderr, "Dump terminated\n");
-			return 1;
-		}
+static int ip_addr_list(struct nlmsg_chain *ainfo)
+{
+	if (rtnl_addrdump_req(&rth, filter.family) < 0) {
+		perror("Cannot send dump request");
+		return 1;
+	}
+
+	if (rtnl_dump_filter(&rth, store_nlmsg, ainfo) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		return 1;
 	}
 
 	return 0;
@@ -1798,7 +1800,7 @@ int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
 static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 {
 	struct nlmsg_chain linfo = { NULL, NULL};
-	struct nlmsg_chain _ainfo = { NULL, NULL}, *ainfo = NULL;
+	struct nlmsg_chain _ainfo = { NULL, NULL}, *ainfo = &_ainfo;
 	struct nlmsg_list *l;
 	char *filter_dev = NULL;
 	int no_link = 0;
@@ -1940,19 +1942,18 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 		goto out;
 	}
 
-	if (filter.family != AF_PACKET) {
-		ainfo = &_ainfo;
+	if (ip_link_list(iplink_filter_req, &linfo) != 0)
+		goto out;
 
+	if (filter.family != AF_PACKET) {
 		if (filter.oneline)
 			no_link = 1;
-	}
 
-	if (ip_linkaddr_list(filter.family, iplink_filter_req,
-			     &linfo, ainfo) != 0)
-		goto out;
+		if (ip_addr_list(ainfo) != 0)
+			goto out;
 
-	if (filter.family != AF_PACKET)
 		ipaddr_filter(&linfo, ainfo);
+	}
 
 	for (l = linfo.head; l; l = l->next) {
 		struct nlmsghdr *n = &l->h;
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index 8a6b7f977b14..08a0d45b2570 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -589,7 +589,7 @@ static int ipvrf_show(int argc, char **argv)
 		return 0;
 	}
 
-	if (ip_linkaddr_list(0, ipvrf_filter_req, &linfo, NULL) == 0) {
+	if (ip_link_list(ipvrf_filter_req, &linfo) == 0) {
 		struct nlmsg_list *l;
 		unsigned nvrf = 0;
 		int n;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 09/12] ip address: Set device index in dump request
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (7 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 08/12] ip address: Split ip_linkaddr_list into link and addr functions David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 10/12] ip bridge: Set NETLINK_DUMP_STRICT_CHK on socket David Ahern
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Add a filter function to rtnl_addrdump_req to set device index in the
address dump request if the user is filtering addresses by device. In
addition, add a new ipaddr_link_get to do a single RTM_GETLINK request
instead of a device dump yet still store the data in the linfo list.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/libnetlink.h |  3 ++-
 ip/ipaddress.c       | 59 +++++++++++++++++++++++++++++++++++++++++++++-------
 lib/libnetlink.c     | 12 ++++++++++-
 3 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index b0051f390980..2621bc99ce7b 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -49,7 +49,8 @@ void rtnl_close(struct rtnl_handle *rth);
 
 typedef int (*req_filter_fn_t)(struct nlmsghdr *nlh, int reqlen);
 
-int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
+int rtnl_addrdump_req(struct rtnl_handle *rth, int family,
+		      req_filter_fn_t filter_fn)
 	__attribute__((warn_unused_result));
 int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 746dbfc58627..2bc33f3a3b3f 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1679,6 +1679,15 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
 	}
 }
 
+static int ipaddr_dump_filter(struct nlmsghdr *nlh, int reqlen)
+{
+	struct ifaddrmsg *ifa = NLMSG_DATA(nlh);
+
+	ifa->ifa_index = filter.ifindex;
+
+	return 0;
+}
+
 static int ipaddr_flush(void)
 {
 	int round = 0;
@@ -1689,7 +1698,8 @@ static int ipaddr_flush(void)
 	filter.flushe = sizeof(flushb);
 
 	while ((max_flush_loops == 0) || (round < max_flush_loops)) {
-		if (rtnl_addrdump_req(&rth, filter.family) < 0) {
+		if (rtnl_addrdump_req(&rth, filter.family,
+				      ipaddr_dump_filter) < 0) {
 			perror("Cannot send dump request");
 			exit(1);
 		}
@@ -1762,6 +1772,36 @@ static int iplink_filter_req(struct nlmsghdr *nlh, int reqlen)
 	return 0;
 }
 
+static int ipaddr_link_get(int index, struct nlmsg_chain *linfo)
+{
+	struct iplink_req req = {
+		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+		.n.nlmsg_flags = NLM_F_REQUEST,
+		.n.nlmsg_type = RTM_GETLINK,
+		.i.ifi_family = filter.family,
+		.i.ifi_index = index,
+	};
+	__u32 filt_mask = RTEXT_FILTER_VF;
+	struct nlmsghdr *answer;
+
+	if (!show_stats)
+		filt_mask |= RTEXT_FILTER_SKIP_STATS;
+
+	addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
+
+	if (rtnl_talk(&rth, &req.n, &answer) < 0) {
+		perror("Cannot send link request");
+		return 1;
+	}
+
+	if (store_nlmsg(answer, linfo) < 0) {
+		fprintf(stderr, "Failed to process link information\n");
+		return 1;
+	}
+
+	return 0;
+}
+
 /* fills in linfo with link data and optionally ainfo with address info
  * caller can walk lists as desired and must call free_nlmsg_chain for
  * both when done
@@ -1784,7 +1824,7 @@ int ip_link_list(req_filter_fn_t filter_fn, struct nlmsg_chain *linfo)
 
 static int ip_addr_list(struct nlmsg_chain *ainfo)
 {
-	if (rtnl_addrdump_req(&rth, filter.family) < 0) {
+	if (rtnl_addrdump_req(&rth, filter.family, ipaddr_dump_filter) < 0) {
 		perror("Cannot send dump request");
 		return 1;
 	}
@@ -1908,7 +1948,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 		if (ipadd_save_prep())
 			exit(1);
 
-		if (rtnl_addrdump_req(&rth, preferred_family) < 0) {
+		if (rtnl_addrdump_req(&rth, preferred_family,
+				      ipaddr_dump_filter) < 0) {
 			perror("Cannot send dump request");
 			exit(1);
 		}
@@ -1942,8 +1983,13 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 		goto out;
 	}
 
-	if (ip_link_list(iplink_filter_req, &linfo) != 0)
-		goto out;
+	if (filter.ifindex) {
+		if (ipaddr_link_get(filter.ifindex, &linfo) != 0)
+			goto out;
+	} else {
+		if (ip_link_list(iplink_filter_req, &linfo) != 0)
+			goto out;
+	}
 
 	if (filter.family != AF_PACKET) {
 		if (filter.oneline)
@@ -1972,8 +2018,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 	fflush(stdout);
 
 out:
-	if (ainfo)
-		free_nlmsg_chain(ainfo);
+	free_nlmsg_chain(ainfo);
 	free_nlmsg_chain(&linfo);
 	delete_json_obj();
 	return 0;
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 56a1cadeb3db..0ddd646a8775 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -234,11 +234,13 @@ int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions)
 	return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
 }
 
-int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
+int rtnl_addrdump_req(struct rtnl_handle *rth, int family,
+		      req_filter_fn_t filter_fn)
 {
 	struct {
 		struct nlmsghdr nlh;
 		struct ifaddrmsg ifm;
+		char buf[128];
 	} req = {
 		.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
 		.nlh.nlmsg_type = RTM_GETADDR,
@@ -247,6 +249,14 @@ int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
 		.ifm.ifa_family = family,
 	};
 
+	if (filter_fn) {
+		int err;
+
+		err = filter_fn(&req.nlh, sizeof(req));
+		if (err)
+			return err;
+	}
+
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 10/12] ip bridge: Set NETLINK_DUMP_STRICT_CHK on socket
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (8 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 09/12] ip address: Set device index in dump request David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 11/12] ip route: Rename do_ipv6 to dump_family David Ahern
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

iproute2 has been updated for the new strict policy in the kernel. Add a
helper to call setsockopt to enable the feature. Add a call to ip.c and
bridge.c

The setsockopt fails on older kernels and the error can be safely ignored
- any new fields or attributes are ignored by the older kernel.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 bridge/bridge.c      | 4 ++++
 include/libnetlink.h | 1 +
 ip/ip.c              | 2 ++
 lib/libnetlink.c     | 9 +++++++++
 4 files changed, 16 insertions(+)

diff --git a/bridge/bridge.c b/bridge/bridge.c
index a3d8154be898..a50d9d59b4c5 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -97,6 +97,8 @@ static int batch(const char *name)
 		return EXIT_FAILURE;
 	}
 
+	rtnl_set_strict_dump(&rth);
+
 	cmdlineno = 0;
 	while (getcmdline(&line, &len, stdin) != -1) {
 		char *largv[100];
@@ -205,6 +207,8 @@ main(int argc, char **argv)
 	if (rtnl_open(&rth, 0) < 0)
 		exit(1);
 
+	rtnl_set_strict_dump(&rth);
+
 	if (argc > 1)
 		return do_cmd(argv[1], argc-1, argv+1);
 
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 2621bc99ce7b..dc0c9c4eb3f5 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -46,6 +46,7 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions,
 	__attribute__((warn_unused_result));
 
 void rtnl_close(struct rtnl_handle *rth);
+void rtnl_set_strict_dump(struct rtnl_handle *rth);
 
 typedef int (*req_filter_fn_t)(struct nlmsghdr *nlh, int reqlen);
 
diff --git a/ip/ip.c b/ip/ip.c
index a5bbacb4bb0f..e4131714018f 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -308,6 +308,8 @@ int main(int argc, char **argv)
 	if (rtnl_open(&rth, 0) < 0)
 		exit(1);
 
+	rtnl_set_strict_dump(&rth);
+
 	if (strlen(basename) > 2)
 		return do_cmd(basename+2, argc, argv);
 
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 0ddd646a8775..7b02c754c1d0 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -161,6 +161,15 @@ static int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error)
 }
 #endif
 
+/* Older kernels may not support strict dump and filtering */
+void rtnl_set_strict_dump(struct rtnl_handle *rth)
+{
+	int one = 1;
+
+	setsockopt(rth->fd, SOL_NETLINK, NETLINK_DUMP_STRICT_CHK,
+		   &one, sizeof(one));
+}
+
 void rtnl_close(struct rtnl_handle *rth)
 {
 	if (rth->fd >= 0) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 11/12] ip route: Rename do_ipv6 to dump_family
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (9 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 10/12] ip bridge: Set NETLINK_DUMP_STRICT_CHK on socket David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-20  3:54 ` [PATCH iproute2-next 12/12] neighbor: Add support for protocol attribute David Ahern
  2018-12-30 14:17 ` [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering Ido Schimmel
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

do_ipv6 is really the preferred dump family. Rename it to make
that apparent.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/iproute.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index 5bffb9d88b58..0440366ee26a 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1604,7 +1604,7 @@ static int save_route_prep(void)
 	return 0;
 }
 
-static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
+static int iproute_flush(int family, rtnl_filter_t filter_fn)
 {
 	time_t start = time(0);
 	char flushb[4096-512];
@@ -1612,12 +1612,12 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 	int ret;
 
 	if (filter.cloned) {
-		if (do_ipv6 != AF_INET6) {
+		if (family != AF_INET6) {
 			iproute_flush_cache();
 			if (show_stats)
 				printf("*** IPv4 routing cache is flushed.\n");
 		}
-		if (do_ipv6 == AF_INET)
+		if (family == AF_INET)
 			return 0;
 	}
 
@@ -1626,7 +1626,7 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 	filter.flushe = sizeof(flushb);
 
 	for (;;) {
-		if (rtnl_routedump_req(&rth, do_ipv6, NULL) < 0) {
+		if (rtnl_routedump_req(&rth, family, NULL) < 0) {
 			perror("Cannot send dump request");
 			return -2;
 		}
@@ -1638,7 +1638,7 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 		if (filter.flushed == 0) {
 			if (show_stats) {
 				if (round == 0 &&
-				    (!filter.cloned || do_ipv6 == AF_INET6))
+				    (!filter.cloned || family == AF_INET6))
 					printf("Nothing to flush.\n");
 				else
 					printf("*** Flush is complete after %d round%s ***\n",
@@ -1692,7 +1692,7 @@ static int iproute_dump_filter(struct nlmsghdr *nlh, int reqlen)
 
 static int iproute_list_flush_or_save(int argc, char **argv, int action)
 {
-	int do_ipv6 = preferred_family;
+	int dump_family = preferred_family;
 	char *id = NULL;
 	char *od = NULL;
 	unsigned int mark = 0;
@@ -1811,13 +1811,13 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 			NEXT_ARG();
 			family = read_family(*argv);
 			if (family == AF_UNSPEC)
-				family = do_ipv6;
+				family = dump_family;
 			else
 				NEXT_ARG();
 			get_prefix(&filter.rvia, *argv, family);
 		} else if (strcmp(*argv, "src") == 0) {
 			NEXT_ARG();
-			get_prefix(&filter.rprefsrc, *argv, do_ipv6);
+			get_prefix(&filter.rprefsrc, *argv, dump_family);
 		} else if (matches(*argv, "realms") == 0) {
 			__u32 realm;
 
@@ -1837,15 +1837,15 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 			NEXT_ARG();
 			if (matches(*argv, "root") == 0) {
 				NEXT_ARG();
-				get_prefix(&filter.rsrc, *argv, do_ipv6);
+				get_prefix(&filter.rsrc, *argv, dump_family);
 			} else if (matches(*argv, "match") == 0) {
 				NEXT_ARG();
-				get_prefix(&filter.msrc, *argv, do_ipv6);
+				get_prefix(&filter.msrc, *argv, dump_family);
 			} else {
 				if (matches(*argv, "exact") == 0) {
 					NEXT_ARG();
 				}
-				get_prefix(&filter.msrc, *argv, do_ipv6);
+				get_prefix(&filter.msrc, *argv, dump_family);
 				filter.rsrc = filter.msrc;
 			}
 		} else {
@@ -1854,23 +1854,23 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 			}
 			if (matches(*argv, "root") == 0) {
 				NEXT_ARG();
-				get_prefix(&filter.rdst, *argv, do_ipv6);
+				get_prefix(&filter.rdst, *argv, dump_family);
 			} else if (matches(*argv, "match") == 0) {
 				NEXT_ARG();
-				get_prefix(&filter.mdst, *argv, do_ipv6);
+				get_prefix(&filter.mdst, *argv, dump_family);
 			} else {
 				if (matches(*argv, "exact") == 0) {
 					NEXT_ARG();
 				}
-				get_prefix(&filter.mdst, *argv, do_ipv6);
+				get_prefix(&filter.mdst, *argv, dump_family);
 				filter.rdst = filter.mdst;
 			}
 		}
 		argc--; argv++;
 	}
 
-	if (do_ipv6 == AF_UNSPEC && filter.tb)
-		do_ipv6 = AF_INET;
+	if (dump_family == AF_UNSPEC && filter.tb)
+		dump_family = AF_INET;
 
 	if (id || od)  {
 		int idx;
@@ -1893,9 +1893,9 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 	filter.mark = mark;
 
 	if (action == IPROUTE_FLUSH)
-		return iproute_flush(do_ipv6, filter_fn);
+		return iproute_flush(dump_family, filter_fn);
 
-	if (rtnl_routedump_req(&rth, do_ipv6, iproute_dump_filter) < 0) {
+	if (rtnl_routedump_req(&rth, dump_family, iproute_dump_filter) < 0) {
 		perror("Cannot send dump request");
 		return -2;
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH iproute2-next 12/12] neighbor: Add support for protocol attribute
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (10 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 11/12] ip route: Rename do_ipv6 to dump_family David Ahern
@ 2018-12-20  3:54 ` David Ahern
  2018-12-30 14:17 ` [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering Ido Schimmel
  12 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-20  3:54 UTC (permalink / raw)
  To: netdev; +Cc: stephen, David Ahern

From: David Ahern <dsahern@gmail.com>

Add support to set protocol on neigh entries and to print the protocol
on dumps.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 ip/ipneigh.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 6041c467749c..26ac2d1be21f 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -40,6 +40,7 @@ static struct
 	int flushp;
 	int flushe;
 	int master;
+	int protocol;
 } filter;
 
 static void usage(void) __attribute__((noreturn));
@@ -48,7 +49,7 @@ static void usage(void)
 {
 	fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n"
 			"                { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]\n");
-	fprintf(stderr, "                                 [ router ] [ extern_learn ]\n\n");
+	fprintf(stderr, "                [ router ] [ extern_learn ] [ protocol PROTO ]\n\n");
 	fprintf(stderr, "       ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n");
 	fprintf(stderr, "                                 [ vrf NAME ]\n\n");
 	fprintf(stderr, "STATE := { permanent | noarp | stale | reachable | none |\n"
@@ -148,6 +149,14 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
 			NEXT_ARG();
 			dev = *argv;
 			dev_ok = 1;
+		} else if (matches(*argv, "protocol") == 0) {
+			__u32 proto;
+
+			NEXT_ARG();
+			if (rtnl_rtprot_a2n(&proto, *argv))
+				invarg("\"protocol\" value is invalid\n", *argv);
+			if (addattr8(&req.n, sizeof(req), NDA_PROTOCOL, proto))
+				return -1;
 		} else {
 			if (strcmp(*argv, "to") == 0) {
 				NEXT_ARG();
@@ -244,6 +253,7 @@ int print_neigh(struct nlmsghdr *n, void *arg)
 	int len = n->nlmsg_len;
 	struct rtattr *tb[NDA_MAX+1];
 	static int logit = 1;
+	__u8 protocol = 0;
 
 	if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
 	    n->nlmsg_type != RTM_GETNEIGH) {
@@ -285,6 +295,12 @@ int print_neigh(struct nlmsghdr *n, void *arg)
 	if (inet_addr_match_rta(&filter.pfx, tb[NDA_DST]))
 		return 0;
 
+	if (tb[NDA_PROTOCOL])
+		protocol = rta_getattr_u8(tb[NDA_PROTOCOL]);
+
+	if (filter.protocol && filter.protocol != protocol)
+		return 0;
+
 	if (filter.unused_only && tb[NDA_CACHEINFO]) {
 		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
 
@@ -371,6 +387,13 @@ int print_neigh(struct nlmsghdr *n, void *arg)
 	if (r->ndm_state)
 		print_neigh_state(r->ndm_state);
 
+	if (protocol) {
+		SPRINT_BUF(b1);
+
+		print_string(PRINT_ANY, "protocol", " proto %s ",
+			     rtnl_rtprot_n2a(protocol, b1, sizeof(b1)));
+	}
+
 	print_string(PRINT_FP, NULL, "\n", "");
 	close_json_object();
 	fflush(stdout);
@@ -458,9 +481,19 @@ static int do_show_or_flush(int argc, char **argv, int flush)
 			if (state == 0)
 				state = 0x100;
 			filter.state |= state;
-		} else if (strcmp(*argv, "proxy") == 0)
+		} else if (strcmp(*argv, "proxy") == 0) {
 			req.ndm.ndm_flags = NTF_PROXY;
-		else {
+		} else if (matches(*argv, "protocol") == 0) {
+			__u32 prot;
+
+			NEXT_ARG();
+			if (rtnl_rtprot_a2n(&prot, *argv)) {
+				if (strcmp(*argv, "all"))
+					invarg("invalid \"protocol\"\n", *argv);
+				prot = 0;
+			}
+			filter.protocol = prot;
+		} else {
 			if (strcmp(*argv, "to") == 0) {
 				NEXT_ARG();
 			}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering
  2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
                   ` (11 preceding siblings ...)
  2018-12-20  3:54 ` [PATCH iproute2-next 12/12] neighbor: Add support for protocol attribute David Ahern
@ 2018-12-30 14:17 ` Ido Schimmel
  2018-12-30 15:10   ` David Ahern
  12 siblings, 1 reply; 15+ messages in thread
From: Ido Schimmel @ 2018-12-30 14:17 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev, stephen, David Ahern

On Wed, Dec 19, 2018 at 07:54:15PM -0800, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
> 
> Refactorings and updates to use the new strict checking in the kernel
> along with the new kernel side filtering.

David,

Since this was applied to iproute2-next I get:

bash-4.4# bridge/bridge fdb show                                                                                                                                            
[ 5365.137224] netlink: 4 bytes leftover after parsing attributes in process `bridge'.
Error: bytes leftover after parsing attributes.
Dump terminated

And a lot of tests are failing. Given you enabled strict checking, I
assume we should be using 'struct ndmsg' in FDB dump? Following patch
fixes it for me. I can submit formally if you don't already have a
patch.

diff --git a/bridge/fdb.c b/bridge/fdb.c
index a5abc1b6c78d..a7a0d8052307 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -260,16 +260,16 @@ static int fdb_show(int argc, char **argv)
 {
 	struct {
 		struct nlmsghdr	n;
-		struct ifinfomsg	ifm;
+		struct ndmsg		ndm;
 		char			buf[256];
 	} req = {
-		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
-		.ifm.ifi_family = PF_BRIDGE,
+		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
+		.ndm.ndm_family = PF_BRIDGE,
 	};
 
 	char *filter_dev = NULL;
 	char *br = NULL;
-	int msg_size = sizeof(struct ifinfomsg);
+	int msg_size = sizeof(struct ndmsg);
 
 	while (argc > 0) {
 		if ((strcmp(*argv, "brport") == 0) || strcmp(*argv, "dev") == 0) {
@@ -313,10 +313,10 @@ static int fdb_show(int argc, char **argv)
 		filter_index = ll_name_to_index(filter_dev);
 		if (!filter_index)
 			return nodev(filter_dev);
-		req.ifm.ifi_index = filter_index;
+		req.ndm.ndm_ifindex = filter_index;
 	}
 
-	if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ifm, msg_size) < 0) {
+	if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ndm, msg_size) < 0) {
 		perror("Cannot send dump request");
 		exit(1);
 	}

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering
  2018-12-30 14:17 ` [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering Ido Schimmel
@ 2018-12-30 15:10   ` David Ahern
  0 siblings, 0 replies; 15+ messages in thread
From: David Ahern @ 2018-12-30 15:10 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: David Ahern, netdev, stephen



> On Dec 30, 2018, at 9:17 AM, Ido Schimmel <idosch@idosch.org> wrote:
> 
>> On Wed, Dec 19, 2018 at 07:54:15PM -0800, David Ahern wrote:
>> From: David Ahern <dsahern@gmail.com>
>> 
>> Refactorings and updates to use the new strict checking in the kernel
>> along with the new kernel side filtering.
> 
> David,
> 
> Since this was applied to iproute2-next I get:
> 
> bash-4.4# bridge/bridge fdb show                                                                                                                                            
> [ 5365.137224] netlink: 4 bytes leftover after parsing attributes in process `bridge'.
> Error: bytes leftover after parsing attributes.
> Dump terminated
> 
> And a lot of tests are failing. Given you enabled strict checking, I
> assume we should be using 'struct ndmsg' in FDB dump? Following patch
> fixes it for me. I can submit formally if you don't already have a
> patch.


Please submit formally. Thanks for the fix


> 
> diff --git a/bridge/fdb.c b/bridge/fdb.c
> index a5abc1b6c78d..a7a0d8052307 100644
> --- a/bridge/fdb.c
> +++ b/bridge/fdb.c
> @@ -260,16 +260,16 @@ static int fdb_show(int argc, char **argv)
> {
>    struct {
>        struct nlmsghdr    n;
> -        struct ifinfomsg    ifm;
> +        struct ndmsg        ndm;
>        char            buf[256];
>    } req = {
> -        .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
> -        .ifm.ifi_family = PF_BRIDGE,
> +        .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
> +        .ndm.ndm_family = PF_BRIDGE,
>    };
> 
>    char *filter_dev = NULL;
>    char *br = NULL;
> -    int msg_size = sizeof(struct ifinfomsg);
> +    int msg_size = sizeof(struct ndmsg);
> 
>    while (argc > 0) {
>        if ((strcmp(*argv, "brport") == 0) || strcmp(*argv, "dev") == 0) {
> @@ -313,10 +313,10 @@ static int fdb_show(int argc, char **argv)
>        filter_index = ll_name_to_index(filter_dev);
>        if (!filter_index)
>            return nodev(filter_dev);
> -        req.ifm.ifi_index = filter_index;
> +        req.ndm.ndm_ifindex = filter_index;
>    }
> 
> -    if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ifm, msg_size) < 0) {
> +    if (rtnl_dump_request(&rth, RTM_GETNEIGH, &req.ndm, msg_size) < 0) {
>        perror("Cannot send dump request");
>        exit(1);
>    }

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-12-30 15:10 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-20  3:54 [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 01/12] libnetlink: dump extack string in done message David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 02/12] libnetlink: Use NLMSG_LENGTH to set nlmsg_len David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 03/12] libnetlink: linkdump_req: Only AF_UNSPEC family expects an ext_filter_mask David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 04/12] ip route: Remove rtnl_rtcache_request David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 05/12] ip route: Add protocol, table id and device to dump request David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 06/12] mroute: fix up family handling David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 07/12] mroute: Add table id attribute for kernel side filtering David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 08/12] ip address: Split ip_linkaddr_list into link and addr functions David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 09/12] ip address: Set device index in dump request David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 10/12] ip bridge: Set NETLINK_DUMP_STRICT_CHK on socket David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 11/12] ip route: Rename do_ipv6 to dump_family David Ahern
2018-12-20  3:54 ` [PATCH iproute2-next 12/12] neighbor: Add support for protocol attribute David Ahern
2018-12-30 14:17 ` [PATCH iproute2-next 00/12] Updates for strict checking and kernel side filtering Ido Schimmel
2018-12-30 15:10   ` David Ahern

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).