diff options
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 19 | 
1 files changed, 12 insertions, 7 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 53617d715188..cb32ce250db0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1193,7 +1193,8 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,  	fl6->flowi6_iif = LOOPBACK_IFINDEX; -	if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) +	if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) || +	    fl6->flowi6_oif)  		flags |= RT6_LOOKUP_F_IFACE;  	if (!ipv6_addr_any(&fl6->saddr)) @@ -1322,8 +1323,7 @@ static void ip6_link_failure(struct sk_buff *skb)  	if (rt) {  		if (rt->rt6i_flags & RTF_CACHE) {  			dst_hold(&rt->dst); -			if (ip6_del_rt(rt)) -				dst_free(&rt->dst); +			ip6_del_rt(rt);  		} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {  			rt->rt6i_node->fn_sernum = -1;  		} @@ -1886,9 +1886,11 @@ int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret)  			rt->dst.input = ip6_pkt_prohibit;  			break;  		case RTN_THROW: +		case RTN_UNREACHABLE:  		default:  			rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN -					: -ENETUNREACH; +					: (cfg->fc_type == RTN_UNREACHABLE) +					? -EHOSTUNREACH : -ENETUNREACH;  			rt->dst.output = ip6_pkt_discard_out;  			rt->dst.input = ip6_pkt_discard;  			break; @@ -2028,7 +2030,8 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)  	struct fib6_table *table;  	struct net *net = dev_net(rt->dst.dev); -	if (rt == net->ipv6.ip6_null_entry) { +	if (rt == net->ipv6.ip6_null_entry || +	    rt->dst.flags & DST_NOCACHE) {  		err = -ENOENT;  		goto out;  	} @@ -2515,6 +2518,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,  	rt->rt6i_dst.addr = *addr;  	rt->rt6i_dst.plen = 128;  	rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); +	rt->dst.flags |= DST_NOCACHE;  	atomic_set(&rt->dst.__refcnt, 1); @@ -3303,7 +3307,8 @@ errout:  	return err;  } -void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) +void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info, +		     unsigned int nlm_flags)  {  	struct sk_buff *skb;  	struct net *net = info->nl_net; @@ -3318,7 +3323,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)  		goto errout;  	err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, -				event, info->portid, seq, 0, 0, 0); +				event, info->portid, seq, 0, 0, nlm_flags);  	if (err < 0) {  		/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */  		WARN_ON(err == -EMSGSIZE);  |