mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: Add optional SKB arg to dst_ops->neigh_lookup().
Causes the handler to use the daddr in the ipv4/ipv6 header when the route gateway is unspecified (local subnet). Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5110effee8
								
							
						
					
					
						commit
						f894cbf847
					
				
					 7 changed files with 43 additions and 15 deletions
				
			
		| 
						 | 
					@ -420,7 +420,13 @@ static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return dst->ops->neigh_lookup(dst, daddr);
 | 
						return dst->ops->neigh_lookup(dst, NULL, daddr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
 | 
				
			||||||
 | 
											     struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return dst->ops->neigh_lookup(dst, skb, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void dst_link_failure(struct sk_buff *skb)
 | 
					static inline void dst_link_failure(struct sk_buff *skb)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,9 @@ struct dst_ops {
 | 
				
			||||||
	void			(*link_failure)(struct sk_buff *);
 | 
						void			(*link_failure)(struct sk_buff *);
 | 
				
			||||||
	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
 | 
						void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
 | 
				
			||||||
	int			(*local_out)(struct sk_buff *skb);
 | 
						int			(*local_out)(struct sk_buff *skb);
 | 
				
			||||||
	struct neighbour *	(*neigh_lookup)(const struct dst_entry *dst, const void *daddr);
 | 
						struct neighbour *	(*neigh_lookup)(const struct dst_entry *dst,
 | 
				
			||||||
 | 
											struct sk_buff *skb,
 | 
				
			||||||
 | 
											const void *daddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct kmem_cache	*kmem_cachep;
 | 
						struct kmem_cache	*kmem_cachep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,9 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										   struct sk_buff *skb,
 | 
				
			||||||
 | 
										   const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,9 @@ static void dn_dst_destroy(struct dst_entry *);
 | 
				
			||||||
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 | 
					static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 | 
				
			||||||
static void dn_dst_link_failure(struct sk_buff *);
 | 
					static void dn_dst_link_failure(struct sk_buff *);
 | 
				
			||||||
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
 | 
					static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
 | 
				
			||||||
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr);
 | 
					static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										     struct sk_buff *skb,
 | 
				
			||||||
 | 
										     const void *daddr);
 | 
				
			||||||
static int dn_route_input(struct sk_buff *);
 | 
					static int dn_route_input(struct sk_buff *);
 | 
				
			||||||
static void dn_run_flush(unsigned long dummy);
 | 
					static void dn_run_flush(unsigned long dummy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -828,7 +830,9 @@ static unsigned int dn_dst_mtu(const struct dst_entry *dst)
 | 
				
			||||||
	return mtu ? : dst->dev->mtu;
 | 
						return mtu ? : dst->dev->mtu;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										     struct sk_buff *skb,
 | 
				
			||||||
 | 
										     const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
 | 
						return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,7 +188,9 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
 | 
				
			||||||
	return p;
 | 
						return p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
 | 
					static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										   struct sk_buff *skb,
 | 
				
			||||||
 | 
										   const void *daddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dst_ops ipv4_dst_ops = {
 | 
					static struct dst_ops ipv4_dst_ops = {
 | 
				
			||||||
	.family =		AF_INET,
 | 
						.family =		AF_INET,
 | 
				
			||||||
| 
						 | 
					@ -1088,7 +1090,9 @@ static int slow_chain_length(const struct rtable *head)
 | 
				
			||||||
	return length >> FRACT_BITS;
 | 
						return length >> FRACT_BITS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										   struct sk_buff *skb,
 | 
				
			||||||
 | 
										   const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_device *dev = dst->dev;
 | 
						struct net_device *dev = dst->dev;
 | 
				
			||||||
	const __be32 *pkey = daddr;
 | 
						const __be32 *pkey = daddr;
 | 
				
			||||||
| 
						 | 
					@ -1098,6 +1102,8 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
 | 
				
			||||||
	rt = (const struct rtable *) dst;
 | 
						rt = (const struct rtable *) dst;
 | 
				
			||||||
	if (rt->rt_gateway)
 | 
						if (rt->rt_gateway)
 | 
				
			||||||
		pkey = (const __be32 *) &rt->rt_gateway;
 | 
							pkey = (const __be32 *) &rt->rt_gateway;
 | 
				
			||||||
 | 
						else if (skb)
 | 
				
			||||||
 | 
							pkey = &ip_hdr(skb)->daddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
 | 
						n = __ipv4_neigh_lookup(dev, *(__force u32 *)pkey);
 | 
				
			||||||
	if (n)
 | 
						if (n)
 | 
				
			||||||
| 
						 | 
					@ -1107,7 +1113,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rt_bind_neighbour(struct rtable *rt)
 | 
					static int rt_bind_neighbour(struct rtable *rt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
 | 
						struct neighbour *n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
 | 
				
			||||||
	if (IS_ERR(n))
 | 
						if (IS_ERR(n))
 | 
				
			||||||
		return PTR_ERR(n);
 | 
							return PTR_ERR(n);
 | 
				
			||||||
	dst_set_neighbour(&rt->dst, n);
 | 
						dst_set_neighbour(&rt->dst, n);
 | 
				
			||||||
| 
						 | 
					@ -1388,7 +1394,7 @@ static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rt->rt_gateway = peer->redirect_learned.a4;
 | 
						rt->rt_gateway = peer->redirect_learned.a4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
 | 
						n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
 | 
				
			||||||
	if (IS_ERR(n)) {
 | 
						if (IS_ERR(n)) {
 | 
				
			||||||
		rt->rt_gateway = orig_gw;
 | 
							rt->rt_gateway = orig_gw;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,21 +120,27 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
 | 
				
			||||||
	return p;
 | 
						return p;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr)
 | 
					static inline const void *choose_neigh_daddr(struct rt6_info *rt,
 | 
				
			||||||
 | 
										     struct sk_buff *skb,
 | 
				
			||||||
 | 
										     const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct in6_addr *p = &rt->rt6i_gateway;
 | 
						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)
 | 
				
			||||||
 | 
							return &ipv6_hdr(skb)->daddr;
 | 
				
			||||||
	return daddr;
 | 
						return daddr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										  struct sk_buff *skb,
 | 
				
			||||||
 | 
										  const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rt6_info *rt = (struct rt6_info *) dst;
 | 
						struct rt6_info *rt = (struct rt6_info *) dst;
 | 
				
			||||||
	struct neighbour *n;
 | 
						struct neighbour *n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	daddr = choose_neigh_daddr(rt, daddr);
 | 
						daddr = choose_neigh_daddr(rt, skb, daddr);
 | 
				
			||||||
	n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
 | 
						n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
 | 
				
			||||||
	if (n)
 | 
						if (n)
 | 
				
			||||||
		return n;
 | 
							return n;
 | 
				
			||||||
| 
						 | 
					@ -1162,7 +1168,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
 | 
				
			||||||
	if (neigh)
 | 
						if (neigh)
 | 
				
			||||||
		neigh_hold(neigh);
 | 
							neigh_hold(neigh);
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		neigh = ip6_neigh_lookup(&rt->dst, &fl6->daddr);
 | 
							neigh = ip6_neigh_lookup(&rt->dst, NULL, &fl6->daddr);
 | 
				
			||||||
		if (IS_ERR(neigh)) {
 | 
							if (IS_ERR(neigh)) {
 | 
				
			||||||
			in6_dev_put(idev);
 | 
								in6_dev_put(idev);
 | 
				
			||||||
			dst_free(&rt->dst);
 | 
								dst_free(&rt->dst);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2404,9 +2404,11 @@ static unsigned int xfrm_mtu(const struct dst_entry *dst)
 | 
				
			||||||
	return mtu ? : dst_mtu(dst->path);
 | 
						return mtu ? : dst_mtu(dst->path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 | 
					static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
 | 
				
			||||||
 | 
										   struct sk_buff *skb,
 | 
				
			||||||
 | 
										   const void *daddr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return dst_neigh_lookup(dst->path, daddr);
 | 
						return dst->path->ops->neigh_lookup(dst, skb, daddr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 | 
					int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue