Commit 58acfd71 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

ipv6: Honor specified parameters in fibmatch lookup

Currently, parameters such as oif and source address are not taken into
account during fibmatch lookup. Example (IPv4 for reference) before
patch:

$ ip -4 route show
192.0.2.0/24 dev dummy0 proto kernel scope link src 192.0.2.1
198.51.100.0/24 dev dummy1 proto kernel scope link src 198.51.100.1

$ ip -6 route show
2001:db8:1::/64 dev dummy0 proto kernel metric 256 pref medium
2001:db8:2::/64 dev dummy1 proto kernel metric 256 pref medium
fe80::/64 dev dummy0 proto kernel metric 256 pref medium
fe80::/64 dev dummy1 proto kernel metric 256 pref medium

$ ip -4 route get fibmatch 192.0.2.2 oif dummy0
192.0.2.0/24 dev dummy0 proto kernel scope link src 192.0.2.1
$ ip -4 route get fibmatch 192.0.2.2 oif dummy1
RTNETLINK answers: No route to host

$ ip -6 route get fibmatch 2001:db8:1::2 oif dummy0
2001:db8:1::/64 dev dummy0 proto kernel metric 256 pref medium
$ ip -6 route get fibmatch 2001:db8:1::2 oif dummy1
2001:db8:1::/64 dev dummy0 proto kernel metric 256 pref medium

After:

$ ip -6 route get fibmatch 2001:db8:1::2 oif dummy0
2001:db8:1::/64 dev dummy0 proto kernel metric 256 pref medium
$ ip -6 route get fibmatch 2001:db8:1::2 oif dummy1
RTNETLINK answers: Network is unreachable

The problem stems from the fact that the necessary route lookup flags
are not set based on these parameters.

Instead of duplicating the same logic for fibmatch, we can simply
resolve the original route from its copy and dump it instead.

Fixes: 18c3a61c ("net: ipv6: RTM_GETROUTE: return matched fib result when requested")
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b6ca2bf
...@@ -4298,19 +4298,13 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, ...@@ -4298,19 +4298,13 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
if (!ipv6_addr_any(&fl6.saddr)) if (!ipv6_addr_any(&fl6.saddr))
flags |= RT6_LOOKUP_F_HAS_SADDR; flags |= RT6_LOOKUP_F_HAS_SADDR;
if (!fibmatch) dst = ip6_route_input_lookup(net, dev, &fl6, flags);
dst = ip6_route_input_lookup(net, dev, &fl6, flags);
else
dst = ip6_route_lookup(net, &fl6, 0);
rcu_read_unlock(); rcu_read_unlock();
} else { } else {
fl6.flowi6_oif = oif; fl6.flowi6_oif = oif;
if (!fibmatch) dst = ip6_route_output(net, NULL, &fl6);
dst = ip6_route_output(net, NULL, &fl6);
else
dst = ip6_route_lookup(net, &fl6, 0);
} }
...@@ -4327,6 +4321,15 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, ...@@ -4327,6 +4321,15 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
goto errout; goto errout;
} }
if (fibmatch && rt->dst.from) {
struct rt6_info *ort = container_of(rt->dst.from,
struct rt6_info, dst);
dst_hold(&ort->dst);
ip6_rt_put(rt);
rt = ort;
}
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb) { if (!skb) {
ip6_rt_put(rt); ip6_rt_put(rt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment