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

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -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
+6 −2
Original line number Original line Diff line number Diff line
@@ -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)
			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",
+20 −13
Original line number Original line Diff line number Diff line
@@ -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,
	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 net_device *dev,
				   struct sk_buff *skb,
				   struct sk_buff *skb,
				   const void *daddr)
				   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)
	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 = {
	.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 = {
	.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] = {