From: David Ahern <dsah...@gmail.com>

Add struct fib_dump_filter for options on limiting which routes are
returned in a dump request. The current list is table id, protocol,
route type, rtm_flags and nexthop device index. struct net is needed
to lookup the net_device from the index.

Declare the filter for each route dump handler and plumb the new
arguments from dump handlers to ip_valid_fib_dump_req.

Signed-off-by: David Ahern <dsah...@gmail.com>
---
 include/net/ip6_route.h |  1 +
 include/net/ip_fib.h    | 13 ++++++++++++-
 net/ipv4/fib_frontend.c |  6 ++++--
 net/ipv4/ipmr.c         |  6 +++++-
 net/ipv6/ip6_fib.c      |  5 +++--
 net/ipv6/ip6mr.c        |  5 ++++-
 net/mpls/af_mpls.c      | 12 ++++++++----
 7 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index cef186dbd2ce..7ab119936e69 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -174,6 +174,7 @@ struct rt6_rtnl_dump_arg {
        struct sk_buff *skb;
        struct netlink_callback *cb;
        struct net *net;
+       struct fib_dump_filter filter;
 };
 
 int rt6_dump_route(struct fib6_info *f6i, void *p_arg);
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 852e4ebf2209..667013bf4266 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -222,6 +222,16 @@ struct fib_table {
        unsigned long           __data[0];
 };
 
+struct fib_dump_filter {
+       u32                     table_id;
+       /* filter_set is an optimization that an entry is set */
+       bool                    filter_set;
+       unsigned char           protocol;
+       unsigned char           rt_type;
+       unsigned int            flags;
+       struct net_device       *dev;
+};
+
 int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
                     struct fib_result *res, int fib_flags);
 int fib_table_insert(struct net *, struct fib_table *, struct fib_config *,
@@ -453,6 +463,7 @@ static inline void fib_proc_exit(struct net *net)
 
 u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
 
-int ip_valid_fib_dump_req(const struct nlmsghdr *nlh,
+int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
+                         struct fib_dump_filter *filter,
                          struct netlink_ext_ack *extack);
 #endif  /* _NET_FIB_H */
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 0f1beceb47d5..850850dd80e1 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -802,7 +802,8 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct 
nlmsghdr *nlh,
        return err;
 }
 
-int ip_valid_fib_dump_req(const struct nlmsghdr *nlh,
+int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
+                         struct fib_dump_filter *filter,
                          struct netlink_ext_ack *extack)
 {
        struct rtmsg *rtm;
@@ -837,6 +838,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct 
netlink_callback *cb)
 {
        const struct nlmsghdr *nlh = cb->nlh;
        struct net *net = sock_net(skb->sk);
+       struct fib_dump_filter filter = {};
        unsigned int h, s_h;
        unsigned int e = 0, s_e;
        struct fib_table *tb;
@@ -844,7 +846,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct 
netlink_callback *cb)
        int dumped = 0, err;
 
        if (cb->strict_check) {
-               err = ip_valid_fib_dump_req(nlh, cb->extack);
+               err = ip_valid_fib_dump_req(net, nlh, &filter, cb->extack);
                if (err < 0)
                        return err;
        }
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 91b0d5671649..44d777058960 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2527,9 +2527,13 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, 
struct nlmsghdr *nlh,
 
 static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct fib_dump_filter filter = {};
+
        if (cb->strict_check) {
-               int err = ip_valid_fib_dump_req(cb->nlh, cb->extack);
+               int err;
 
+               err = ip_valid_fib_dump_req(sock_net(skb->sk), cb->nlh,
+                                           &filter, cb->extack);
                if (err < 0)
                        return err;
        }
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 0783af11b0b7..94e61fe47ff8 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -569,17 +569,18 @@ static int inet6_dump_fib(struct sk_buff *skb, struct 
netlink_callback *cb)
 {
        const struct nlmsghdr *nlh = cb->nlh;
        struct net *net = sock_net(skb->sk);
+       struct rt6_rtnl_dump_arg arg = {};
        unsigned int h, s_h;
        unsigned int e = 0, s_e;
-       struct rt6_rtnl_dump_arg arg;
        struct fib6_walker *w;
        struct fib6_table *tb;
        struct hlist_head *head;
        int res = 0;
 
        if (cb->strict_check) {
-               int err = ip_valid_fib_dump_req(nlh, cb->extack);
+               int err;
 
+               err = ip_valid_fib_dump_req(net, nlh, &arg.filter, cb->extack);
                if (err < 0)
                        return err;
        }
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d7563ef76518..dbd5166c5599 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -2458,10 +2458,13 @@ static void mrt6msg_netlink_event(struct mr_table *mrt, 
struct sk_buff *pkt)
 static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback 
*cb)
 {
        const struct nlmsghdr *nlh = cb->nlh;
+       struct fib_dump_filter filter = {};
 
        if (cb->strict_check) {
-               int err = ip_valid_fib_dump_req(nlh, cb->extack);
+               int err;
 
+               err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh,
+                                           &filter, cb->extack);
                if (err < 0)
                        return err;
        }
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 5fe274c47c41..bfcb4759c9ee 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -2032,13 +2032,15 @@ static int mpls_dump_route(struct sk_buff *skb, u32 
portid, u32 seq, int event,
 }
 
 #if IS_ENABLED(CONFIG_INET)
-static int mpls_valid_fib_dump_req(const struct nlmsghdr *nlh,
+static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
+                                  struct fib_dump_filter *filter,
                                   struct netlink_ext_ack *extack)
 {
-       return ip_valid_fib_dump_req(nlh, extack);
+       return ip_valid_fib_dump_req(net, nlh, filter, extack);
 }
 #else
-static int mpls_valid_fib_dump_req(const struct nlmsghdr *nlh,
+static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
+                                  struct fib_dump_filter *filter,
                                   struct netlink_ext_ack *extack)
 {
        struct rtmsg *rtm;
@@ -2070,14 +2072,16 @@ static int mpls_dump_routes(struct sk_buff *skb, struct 
netlink_callback *cb)
        const struct nlmsghdr *nlh = cb->nlh;
        struct net *net = sock_net(skb->sk);
        struct mpls_route __rcu **platform_label;
+       struct fib_dump_filter filter = {};
        size_t platform_labels;
        unsigned int index;
 
        ASSERT_RTNL();
 
        if (cb->strict_check) {
-               int err = mpls_valid_fib_dump_req(nlh, cb->extack);
+               int err;
 
+               err = mpls_valid_fib_dump_req(net, nlh, &filter, cb->extack);
                if (err < 0)
                        return err;
        }
-- 
2.11.0

Reply via email to