Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18c3a61c authored by Roopa Prabhu's avatar Roopa Prabhu Committed by David S. Miller
Browse files

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: default avatarRoopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b6179813
Loading
Loading
Loading
Loading
+26 −8
Original line number Diff line number Diff line
@@ -3607,11 +3607,13 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
{
	struct net *net = sock_net(in_skb->sk);
	struct nlattr *tb[RTA_MAX+1];
	int err, iif = 0, oif = 0;
	struct dst_entry *dst;
	struct rt6_info *rt;
	struct sk_buff *skb;
	struct rtmsg *rtm;
	struct flowi6 fl6;
	int err, iif = 0, oif = 0;
	bool fibmatch;

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

	if (tb[RTA_SRC]) {
		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,
		if (!ipv6_addr_any(&fl6.saddr))
			flags |= RT6_LOOKUP_F_HAS_SADDR;

		rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
							       flags);
		if (!fibmatch)
			dst = ip6_route_input_lookup(net, dev, &fl6, flags);
	} else {
		fl6.flowi6_oif = oif;

		rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
		if (!fibmatch)
			dst = ip6_route_output(net, NULL, &fl6);
	}

	if (fibmatch)
		dst = ip6_route_lookup(net, &fl6, 0);

	rt = container_of(dst, struct rt6_info, dst);
	if (rt->dst.error) {
		err = rt->dst.error;
		ip6_rt_put(rt);
		goto errout;
	}

	if (rt == net->ipv6.ip6_null_entry) {
@@ -3689,7 +3703,11 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
	}

	skb_dst_set(skb, &rt->dst);

	if (fibmatch)
		err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
				    nlh->nlmsg_seq, 0);
	else
		err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
				    nlh->nlmsg_seq, 0);