Commit f8a1b43b authored by David Ahern's avatar David Ahern Committed by David S. Miller

net/ipv6: Create a neigh_lookup for FIB entries

The router discovery code has a FIB entry and wants to validate the
gateway has a neighbor entry. Refactor the existing dst_neigh_lookup
for IPv6 and create a new function that takes the gateway and device
and returns a neighbor entry. Use the new function in
ndisc_router_discovery to validate the gateway.
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3b6761d1
...@@ -279,4 +279,7 @@ static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b) ...@@ -279,4 +279,7 @@ static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b)
!lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate); !lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate);
} }
struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
struct net_device *dev, struct sk_buff *skb,
const void *daddr);
#endif #endif
...@@ -1276,7 +1276,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1276,7 +1276,9 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev); rt = rt6_get_dflt_router(net, &ipv6_hdr(skb)->saddr, skb->dev);
if (rt) { if (rt) {
neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr); neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
rt->fib6_nh.nh_dev, NULL,
&ipv6_hdr(skb)->saddr);
if (!neigh) { if (!neigh) {
ND_PRINTK(0, err, ND_PRINTK(0, err,
"RA: %s got default router without neighbour\n", "RA: %s got default router without neighbour\n",
...@@ -1304,7 +1306,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1304,7 +1306,9 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return; return;
} }
neigh = dst_neigh_lookup(&rt->dst, &ipv6_hdr(skb)->saddr); neigh = ip6_neigh_lookup(&rt->fib6_nh.nh_gw,
rt->fib6_nh.nh_dev, NULL,
&ipv6_hdr(skb)->saddr);
if (!neigh) { if (!neigh) {
ND_PRINTK(0, err, ND_PRINTK(0, err,
"RA: %s got default router without neighbour\n", "RA: %s got default router without neighbour\n",
......
...@@ -182,12 +182,10 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev) ...@@ -182,12 +182,10 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
} }
} }
static inline const void *choose_neigh_daddr(struct rt6_info *rt, static inline const void *choose_neigh_daddr(const struct in6_addr *p,
struct sk_buff *skb, struct sk_buff *skb,
const void *daddr) const void *daddr)
{ {
struct in6_addr *p = &rt->rt6i_gateway;
if (!ipv6_addr_any(p)) if (!ipv6_addr_any(p))
return (const void *) p; return (const void *) p;
else if (skb) else if (skb)
...@@ -195,18 +193,27 @@ static inline const void *choose_neigh_daddr(struct rt6_info *rt, ...@@ -195,18 +193,27 @@ static inline const void *choose_neigh_daddr(struct rt6_info *rt,
return daddr; return daddr;
} }
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
struct sk_buff *skb, struct net_device *dev,
const void *daddr) struct sk_buff *skb,
const void *daddr)
{ {
struct rt6_info *rt = (struct rt6_info *) dst;
struct neighbour *n; struct neighbour *n;
daddr = choose_neigh_daddr(rt, skb, daddr); daddr = choose_neigh_daddr(gw, skb, daddr);
n = __ipv6_neigh_lookup(dst->dev, daddr); n = __ipv6_neigh_lookup(dev, daddr);
if (n) if (n)
return n; return n;
return neigh_create(&nd_tbl, daddr, dst->dev); return neigh_create(&nd_tbl, daddr, dev);
}
static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{
const struct rt6_info *rt = container_of(dst, struct rt6_info, dst);
return ip6_neigh_lookup(&rt->rt6i_gateway, dst->dev, skb, daddr);
} }
static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr) static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
...@@ -214,7 +221,7 @@ static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr) ...@@ -214,7 +221,7 @@ static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
struct rt6_info *rt = (struct rt6_info *)dst; struct rt6_info *rt = (struct rt6_info *)dst;
daddr = choose_neigh_daddr(rt, NULL, daddr); daddr = choose_neigh_daddr(&rt->rt6i_gateway, NULL, daddr);
if (!daddr) if (!daddr)
return; return;
if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
...@@ -239,7 +246,7 @@ static struct dst_ops ip6_dst_ops_template = { ...@@ -239,7 +246,7 @@ static struct dst_ops ip6_dst_ops_template = {
.update_pmtu = ip6_rt_update_pmtu, .update_pmtu = ip6_rt_update_pmtu,
.redirect = rt6_do_redirect, .redirect = rt6_do_redirect,
.local_out = __ip6_local_out, .local_out = __ip6_local_out,
.neigh_lookup = ip6_neigh_lookup, .neigh_lookup = ip6_dst_neigh_lookup,
.confirm_neigh = ip6_confirm_neigh, .confirm_neigh = ip6_confirm_neigh,
}; };
...@@ -269,7 +276,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { ...@@ -269,7 +276,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
.update_pmtu = ip6_rt_blackhole_update_pmtu, .update_pmtu = ip6_rt_blackhole_update_pmtu,
.redirect = ip6_rt_blackhole_redirect, .redirect = ip6_rt_blackhole_redirect,
.cow_metrics = dst_cow_metrics_generic, .cow_metrics = dst_cow_metrics_generic,
.neigh_lookup = ip6_neigh_lookup, .neigh_lookup = ip6_dst_neigh_lookup,
}; };
static const u32 ip6_template_metrics[RTAX_MAX] = { static const u32 ip6_template_metrics[RTAX_MAX] = {
......
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