Skip to content

Commit 18c3a61

Browse files
roopa-prabhudavem330
authored andcommitted
net: ipv6: RTM_GETROUTE: return matched fib result when requested
This patch adds support to return matched fib result when RTM_F_FIB_MATCH flag is specified in RTM_GETROUTE request. This is useful for user-space applications/controllers wanting to query a matching route. Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b617981 commit 18c3a61

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

net/ipv6/route.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3607,11 +3607,13 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
36073607
{
36083608
struct net *net = sock_net(in_skb->sk);
36093609
struct nlattr *tb[RTA_MAX+1];
3610+
int err, iif = 0, oif = 0;
3611+
struct dst_entry *dst;
36103612
struct rt6_info *rt;
36113613
struct sk_buff *skb;
36123614
struct rtmsg *rtm;
36133615
struct flowi6 fl6;
3614-
int err, iif = 0, oif = 0;
3616+
bool fibmatch;
36153617

36163618
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy,
36173619
extack);
@@ -3622,6 +3624,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
36223624
memset(&fl6, 0, sizeof(fl6));
36233625
rtm = nlmsg_data(nlh);
36243626
fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
3627+
fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH);
36253628

36263629
if (tb[RTA_SRC]) {
36273630
if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
@@ -3667,12 +3670,23 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
36673670
if (!ipv6_addr_any(&fl6.saddr))
36683671
flags |= RT6_LOOKUP_F_HAS_SADDR;
36693672

3670-
rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
3671-
flags);
3673+
if (!fibmatch)
3674+
dst = ip6_route_input_lookup(net, dev, &fl6, flags);
36723675
} else {
36733676
fl6.flowi6_oif = oif;
36743677

3675-
rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
3678+
if (!fibmatch)
3679+
dst = ip6_route_output(net, NULL, &fl6);
3680+
}
3681+
3682+
if (fibmatch)
3683+
dst = ip6_route_lookup(net, &fl6, 0);
3684+
3685+
rt = container_of(dst, struct rt6_info, dst);
3686+
if (rt->dst.error) {
3687+
err = rt->dst.error;
3688+
ip6_rt_put(rt);
3689+
goto errout;
36763690
}
36773691

36783692
if (rt == net->ipv6.ip6_null_entry) {
@@ -3689,10 +3703,14 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
36893703
}
36903704

36913705
skb_dst_set(skb, &rt->dst);
3692-
3693-
err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
3694-
RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
3695-
nlh->nlmsg_seq, 0);
3706+
if (fibmatch)
3707+
err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
3708+
RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
3709+
nlh->nlmsg_seq, 0);
3710+
else
3711+
err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
3712+
RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
3713+
nlh->nlmsg_seq, 0);
36963714
if (err < 0) {
36973715
kfree_skb(skb);
36983716
goto errout;

0 commit comments

Comments
 (0)