diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 118f8fa1a809..6fbf6fdde7e7 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1298,8 +1298,7 @@ static void ip6_link_failure(struct sk_buff *skb) | |||
1298 | if (rt) { | 1298 | if (rt) { |
1299 | if (rt->rt6i_flags & RTF_CACHE) { | 1299 | if (rt->rt6i_flags & RTF_CACHE) { |
1300 | dst_hold(&rt->dst); | 1300 | dst_hold(&rt->dst); |
1301 | if (ip6_del_rt(rt)) | 1301 | ip6_del_rt(rt); |
1302 | dst_free(&rt->dst); | ||
1303 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { | 1302 | } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { |
1304 | rt->rt6i_node->fn_sernum = -1; | 1303 | rt->rt6i_node->fn_sernum = -1; |
1305 | } | 1304 | } |
@@ -1862,9 +1861,11 @@ int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret) | |||
1862 | rt->dst.input = ip6_pkt_prohibit; | 1861 | rt->dst.input = ip6_pkt_prohibit; |
1863 | break; | 1862 | break; |
1864 | case RTN_THROW: | 1863 | case RTN_THROW: |
1864 | case RTN_UNREACHABLE: | ||
1865 | default: | 1865 | default: |
1866 | rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN | 1866 | rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN |
1867 | : -ENETUNREACH; | 1867 | : (cfg->fc_type == RTN_UNREACHABLE) |
1868 | ? -EHOSTUNREACH : -ENETUNREACH; | ||
1868 | rt->dst.output = ip6_pkt_discard_out; | 1869 | rt->dst.output = ip6_pkt_discard_out; |
1869 | rt->dst.input = ip6_pkt_discard; | 1870 | rt->dst.input = ip6_pkt_discard; |
1870 | break; | 1871 | break; |
@@ -2004,7 +2005,8 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
2004 | struct fib6_table *table; | 2005 | struct fib6_table *table; |
2005 | struct net *net = dev_net(rt->dst.dev); | 2006 | struct net *net = dev_net(rt->dst.dev); |
2006 | 2007 | ||
2007 | if (rt == net->ipv6.ip6_null_entry) { | 2008 | if (rt == net->ipv6.ip6_null_entry || |
2009 | rt->dst.flags & DST_NOCACHE) { | ||
2008 | err = -ENOENT; | 2010 | err = -ENOENT; |
2009 | goto out; | 2011 | goto out; |
2010 | } | 2012 | } |
@@ -2491,6 +2493,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2491 | rt->rt6i_dst.addr = *addr; | 2493 | rt->rt6i_dst.addr = *addr; |
2492 | rt->rt6i_dst.plen = 128; | 2494 | rt->rt6i_dst.plen = 128; |
2493 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 2495 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |
2496 | rt->dst.flags |= DST_NOCACHE; | ||
2494 | 2497 | ||
2495 | atomic_set(&rt->dst.__refcnt, 1); | 2498 | atomic_set(&rt->dst.__refcnt, 1); |
2496 | 2499 | ||
@@ -3279,7 +3282,8 @@ errout: | |||
3279 | return err; | 3282 | return err; |
3280 | } | 3283 | } |
3281 | 3284 | ||
3282 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | 3285 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info, |
3286 | unsigned int nlm_flags) | ||
3283 | { | 3287 | { |
3284 | struct sk_buff *skb; | 3288 | struct sk_buff *skb; |
3285 | struct net *net = info->nl_net; | 3289 | struct net *net = info->nl_net; |
@@ -3294,7 +3298,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
3294 | goto errout; | 3298 | goto errout; |
3295 | 3299 | ||
3296 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, | 3300 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, |
3297 | event, info->portid, seq, 0, 0, 0); | 3301 | event, info->portid, seq, 0, 0, nlm_flags); |
3298 | if (err < 0) { | 3302 | if (err < 0) { |
3299 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ | 3303 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ |
3300 | WARN_ON(err == -EMSGSIZE); | 3304 | WARN_ON(err == -EMSGSIZE); |