From 264be1d887102d47d725b299a1b74393259015dc Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 25 Jan 2019 17:09:17 +0000 Subject: [PATCH] bridge: fdb: Fix FDB dump with strict checking disabled While iproute2 correctly uses ifinfomsg struct as the ancillary header when requesting an FDB dump on old kernels, it sets the message type to RTM_GETLINK. This results in wrong reply being returned. Fix this by using RTM_GETNEIGH instead. Before: $ bridge fdb show brport dummy0 Not RTM_NEWNEIGH: 00000158 00000010 00000002 After: $ bridge fdb show brport dummy0 2a:0b:41:1c:92:d3 vlan 1 master br0 permanent 2a:0b:41:1c:92:d3 master br0 permanent 33:33:00:00:00:01 self permanent 01:00:5e:00:00:01 self permanent Fixes: 05880354c2cf ("bridge: fdb: Fix filtering with strict checking disabled") Signed-off-by: Ido Schimmel Reported-by: LiLiang Acked-by: David Ahern Acked-by: Ivan Vecera Signed-off-by: Stephen Hemminger --- bridge/fdb.c | 3 +-- include/libnetlink.h | 3 +++ lib/libnetlink.c | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/bridge/fdb.c b/bridge/fdb.c index f75e953a..c4bf4039 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -346,8 +346,7 @@ static int fdb_show(int argc, char **argv) if (rth.flags & RTNL_HANDLE_F_STRICT_CHK) rc = rtnl_neighdump_req(&rth, PF_BRIDGE, fdb_dump_filter); else - rc = rtnl_linkdump_req_filter_fn(&rth, PF_BRIDGE, - fdb_linkdump_filter); + rc = rtnl_fdb_linkdump_req_filter_fn(&rth, fdb_linkdump_filter); if (rc < 0) { perror("Cannot send dump request"); exit(1); diff --git a/include/libnetlink.h b/include/libnetlink.h index 0854d6ad..503b3ec1 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -81,6 +81,9 @@ int rtnl_linkdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask) int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int fam, req_filter_fn_t fn) __attribute__((warn_unused_result)); +int rtnl_fdb_linkdump_req_filter_fn(struct rtnl_handle *rth, + req_filter_fn_t filter_fn) + __attribute__((warn_unused_result)); int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask) __attribute__((warn_unused_result)); int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, diff --git a/lib/libnetlink.c b/lib/libnetlink.c index 3beb4342..1892a02a 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -503,6 +503,29 @@ int rtnl_linkdump_req_filter_fn(struct rtnl_handle *rth, int family, return __rtnl_linkdump_req(rth, family); } +int rtnl_fdb_linkdump_req_filter_fn(struct rtnl_handle *rth, + req_filter_fn_t filter_fn) +{ + struct { + struct nlmsghdr nlh; + struct ifinfomsg ifm; + char buf[128]; + } req = { + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .nlh.nlmsg_type = RTM_GETNEIGH, + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, + .nlh.nlmsg_seq = rth->dump = ++rth->seq, + .ifm.ifi_family = PF_BRIDGE, + }; + int err; + + err = filter_fn(&req.nlh, sizeof(req)); + if (err) + return err; + + return send(rth->fd, &req, sizeof(req), 0); +} + int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask) { struct { -- 2.39.2