forked from mirrors/linux
		
	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: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									3b6761d18b
								
							
						
					
					
						commit
						f8a1b43b70
					
				
					 3 changed files with 29 additions and 15 deletions
				
			
		| 
						 | 
					@ -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)
 | 
				
			||||||
	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",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 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)
 | 
				
			||||||
	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] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue