diff options
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 29 | 
1 files changed, 14 insertions, 15 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b08879e97f2..05ebd783304 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -40,6 +40,7 @@  #include <linux/proc_fs.h>  #include <linux/seq_file.h>  #include <linux/nsproxy.h> +#include <linux/slab.h>  #include <net/net_namespace.h>  #include <net/snmp.h>  #include <net/ipv6.h> @@ -814,20 +815,13 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,  {  	int flags = 0; -	if (rt6_need_strict(&fl->fl6_dst)) +	if (fl->oif || rt6_need_strict(&fl->fl6_dst))  		flags |= RT6_LOOKUP_F_IFACE;  	if (!ipv6_addr_any(&fl->fl6_src))  		flags |= RT6_LOOKUP_F_HAS_SADDR; -	else if (sk) { -		unsigned int prefs = inet6_sk(sk)->srcprefs; -		if (prefs & IPV6_PREFER_SRC_TMP) -			flags |= RT6_LOOKUP_F_SRCPREF_TMP; -		if (prefs & IPV6_PREFER_SRC_PUBLIC) -			flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; -		if (prefs & IPV6_PREFER_SRC_COA) -			flags |= RT6_LOOKUP_F_SRCPREF_COA; -	} +	else if (sk) +		flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);  	return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output);  } @@ -886,7 +880,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)  	rt = (struct rt6_info *) dst; -	if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) +	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))  		return dst;  	return NULL; @@ -897,12 +891,17 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)  	struct rt6_info *rt = (struct rt6_info *) dst;  	if (rt) { -		if (rt->rt6i_flags & RTF_CACHE) -			ip6_del_rt(rt); -		else +		if (rt->rt6i_flags & RTF_CACHE) { +			if (rt6_check_expired(rt)) { +				ip6_del_rt(rt); +				dst = NULL; +			} +		} else {  			dst_release(dst); +			dst = NULL; +		}  	} -	return NULL; +	return dst;  }  static void ip6_link_failure(struct sk_buff *skb)  |