diff options
Diffstat (limited to 'net/ipv4/route.c')
| -rw-r--r-- | net/ipv4/route.c | 56 | 
1 files changed, 49 insertions, 7 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 621f83434b24..87e979f2b74a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -139,7 +139,8 @@ static unsigned int	 ipv4_mtu(const struct dst_entry *dst);  static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);  static void		 ipv4_link_failure(struct sk_buff *skb);  static void		 ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, -					   struct sk_buff *skb, u32 mtu); +					   struct sk_buff *skb, u32 mtu, +					   bool confirm_neigh);  static void		 ip_do_redirect(struct dst_entry *dst, struct sock *sk,  					struct sk_buff *skb);  static void		ipv4_dst_destroy(struct dst_entry *dst); @@ -1043,7 +1044,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)  }  static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, -			      struct sk_buff *skb, u32 mtu) +			      struct sk_buff *skb, u32 mtu, +			      bool confirm_neigh)  {  	struct rtable *rt = (struct rtable *) dst;  	struct flowi4 fl4; @@ -1894,10 +1896,7 @@ static void ip_multipath_l3_keys(const struct sk_buff *skb,  	if (!icmph)  		goto out; -	if (icmph->type != ICMP_DEST_UNREACH && -	    icmph->type != ICMP_REDIRECT && -	    icmph->type != ICMP_TIME_EXCEEDED && -	    icmph->type != ICMP_PARAMETERPROB) +	if (!icmp_is_err(icmph->type))  		goto out;  	inner_iph = skb_header_pointer(skb, @@ -2022,10 +2021,52 @@ static int ip_mkroute_input(struct sk_buff *skb,  	return __mkroute_input(skb, res, in_dev, daddr, saddr, tos);  } +/* Implements all the saddr-related checks as ip_route_input_slow(), + * assuming daddr is valid and the destination is not a local broadcast one. + * Uses the provided hint instead of performing a route lookup. + */ +int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr, +		      u8 tos, struct net_device *dev, +		      const struct sk_buff *hint) +{ +	struct in_device *in_dev = __in_dev_get_rcu(dev); +	struct rtable *rt = (struct rtable *)hint; +	struct net *net = dev_net(dev); +	int err = -EINVAL; +	u32 tag = 0; + +	if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr)) +		goto martian_source; + +	if (ipv4_is_zeronet(saddr)) +		goto martian_source; + +	if (ipv4_is_loopback(saddr) && !IN_DEV_NET_ROUTE_LOCALNET(in_dev, net)) +		goto martian_source; + +	if (rt->rt_type != RTN_LOCAL) +		goto skip_validate_source; + +	tos &= IPTOS_RT_MASK; +	err = fib_validate_source(skb, saddr, daddr, tos, 0, dev, in_dev, &tag); +	if (err < 0) +		goto martian_source; + +skip_validate_source: +	skb_dst_copy(skb, hint); +	return 0; + +martian_source: +	ip_handle_martian_source(dev, in_dev, skb, daddr, saddr); +	return err; +} +  /*   *	NOTE. We drop all the packets that has local source   *	addresses, because every properly looped back packet   *	must have correct destination already attached by output routine. + *	Changes in the enforced policies must be applied also to + *	ip_route_use_hint().   *   *	Such approach solves two big problems:   *	1. Not simplex devices are handled properly. @@ -2648,7 +2689,8 @@ static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst)  }  static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, -					  struct sk_buff *skb, u32 mtu) +					  struct sk_buff *skb, u32 mtu, +					  bool confirm_neigh)  {  }  |