Skip to content

Commit 13e3890

Browse files
dsaherndavem330
authored andcommitted
net/ipv6: Plumb support for filtering route dumps
Implement kernel side filtering of routes by table id, egress device index, protocol, and route type. If the table id is given in the filter, lookup the table and call fib6_dump_table directly for it. Move the existing route flags check for prefix only routes to the new filter. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 18a8021 commit 13e3890

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

net/ipv6/ip6_fib.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,12 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
583583
err = ip_valid_fib_dump_req(net, nlh, &arg.filter, cb->extack);
584584
if (err < 0)
585585
return err;
586-
}
586+
} else if (nlmsg_len(nlh) >= sizeof(struct rtmsg)) {
587+
struct rtmsg *rtm = nlmsg_data(nlh);
587588

588-
s_h = cb->args[0];
589-
s_e = cb->args[1];
589+
if (rtm->rtm_flags & RTM_F_PREFIX)
590+
arg.filter.flags = RTM_F_PREFIX;
591+
}
590592

591593
w = (void *)cb->args[2];
592594
if (!w) {
@@ -612,6 +614,20 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
612614
arg.net = net;
613615
w->args = &arg;
614616

617+
if (arg.filter.table_id) {
618+
tb = fib6_get_table(net, arg.filter.table_id);
619+
if (!tb) {
620+
NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist");
621+
return -ENOENT;
622+
}
623+
624+
res = fib6_dump_table(tb, skb, cb);
625+
goto out;
626+
}
627+
628+
s_h = cb->args[0];
629+
s_e = cb->args[1];
630+
615631
rcu_read_lock();
616632
for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
617633
e = 0;
@@ -621,16 +637,16 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
621637
goto next;
622638
res = fib6_dump_table(tb, skb, cb);
623639
if (res != 0)
624-
goto out;
640+
goto out_unlock;
625641
next:
626642
e++;
627643
}
628644
}
629-
out:
645+
out_unlock:
630646
rcu_read_unlock();
631647
cb->args[1] = e;
632648
cb->args[0] = h;
633-
649+
out:
634650
res = res < 0 ? res : skb->len;
635651
if (res <= 0)
636652
fib6_dump_end(cb);

net/ipv6/route.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4767,28 +4767,52 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
47674767
return -EMSGSIZE;
47684768
}
47694769

4770+
static bool fib6_info_uses_dev(const struct fib6_info *f6i,
4771+
const struct net_device *dev)
4772+
{
4773+
if (f6i->fib6_nh.nh_dev == dev)
4774+
return true;
4775+
4776+
if (f6i->fib6_nsiblings) {
4777+
struct fib6_info *sibling, *next_sibling;
4778+
4779+
list_for_each_entry_safe(sibling, next_sibling,
4780+
&f6i->fib6_siblings, fib6_siblings) {
4781+
if (sibling->fib6_nh.nh_dev == dev)
4782+
return true;
4783+
}
4784+
}
4785+
4786+
return false;
4787+
}
4788+
47704789
int rt6_dump_route(struct fib6_info *rt, void *p_arg)
47714790
{
47724791
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
4792+
struct fib_dump_filter *filter = &arg->filter;
4793+
unsigned int flags = NLM_F_MULTI;
47734794
struct net *net = arg->net;
47744795

47754796
if (rt == net->ipv6.fib6_null_entry)
47764797
return 0;
47774798

4778-
if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
4779-
struct rtmsg *rtm = nlmsg_data(arg->cb->nlh);
4780-
4781-
/* user wants prefix routes only */
4782-
if (rtm->rtm_flags & RTM_F_PREFIX &&
4783-
!(rt->fib6_flags & RTF_PREFIX_RT)) {
4784-
/* success since this is not a prefix route */
4799+
if ((filter->flags & RTM_F_PREFIX) &&
4800+
!(rt->fib6_flags & RTF_PREFIX_RT)) {
4801+
/* success since this is not a prefix route */
4802+
return 1;
4803+
}
4804+
if (filter->filter_set) {
4805+
if ((filter->rt_type && rt->fib6_type != filter->rt_type) ||
4806+
(filter->dev && !fib6_info_uses_dev(rt, filter->dev)) ||
4807+
(filter->protocol && rt->fib6_protocol != filter->protocol)) {
47854808
return 1;
47864809
}
4810+
flags |= NLM_F_DUMP_FILTERED;
47874811
}
47884812

47894813
return rt6_fill_node(net, arg->skb, rt, NULL, NULL, NULL, 0,
47904814
RTM_NEWROUTE, NETLINK_CB(arg->cb->skb).portid,
4791-
arg->cb->nlh->nlmsg_seq, NLM_F_MULTI);
4815+
arg->cb->nlh->nlmsg_seq, flags);
47924816
}
47934817

47944818
static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,

0 commit comments

Comments
 (0)