diff options
| -rw-r--r-- | net/ipv6/route.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f980f904d6ea..c00156805bf0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -474,6 +474,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, | |||
| 474 | if (route_choosen == 0) { | 474 | if (route_choosen == 0) { |
| 475 | struct inet6_dev *idev = sibling->rt6i_idev; | 475 | struct inet6_dev *idev = sibling->rt6i_idev; |
| 476 | 476 | ||
| 477 | if (sibling->rt6i_nh_flags & RTNH_F_DEAD) | ||
| 478 | break; | ||
| 477 | if (sibling->rt6i_nh_flags & RTNH_F_LINKDOWN && | 479 | if (sibling->rt6i_nh_flags & RTNH_F_LINKDOWN && |
| 478 | idev->cnf.ignore_routes_with_linkdown) | 480 | idev->cnf.ignore_routes_with_linkdown) |
| 479 | break; | 481 | break; |
| @@ -499,12 +501,15 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
| 499 | struct rt6_info *local = NULL; | 501 | struct rt6_info *local = NULL; |
| 500 | struct rt6_info *sprt; | 502 | struct rt6_info *sprt; |
| 501 | 503 | ||
| 502 | if (!oif && ipv6_addr_any(saddr)) | 504 | if (!oif && ipv6_addr_any(saddr) && !(rt->rt6i_nh_flags & RTNH_F_DEAD)) |
| 503 | goto out; | 505 | return rt; |
| 504 | 506 | ||
| 505 | for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) { | 507 | for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) { |
| 506 | struct net_device *dev = sprt->dst.dev; | 508 | struct net_device *dev = sprt->dst.dev; |
| 507 | 509 | ||
| 510 | if (sprt->rt6i_nh_flags & RTNH_F_DEAD) | ||
| 511 | continue; | ||
| 512 | |||
| 508 | if (oif) { | 513 | if (oif) { |
| 509 | if (dev->ifindex == oif) | 514 | if (dev->ifindex == oif) |
| 510 | return sprt; | 515 | return sprt; |
| @@ -533,8 +538,8 @@ static inline struct rt6_info *rt6_device_match(struct net *net, | |||
| 533 | if (flags & RT6_LOOKUP_F_IFACE) | 538 | if (flags & RT6_LOOKUP_F_IFACE) |
| 534 | return net->ipv6.ip6_null_entry; | 539 | return net->ipv6.ip6_null_entry; |
| 535 | } | 540 | } |
| 536 | out: | 541 | |
| 537 | return rt; | 542 | return rt->rt6i_nh_flags & RTNH_F_DEAD ? net->ipv6.ip6_null_entry : rt; |
| 538 | } | 543 | } |
| 539 | 544 | ||
| 540 | #ifdef CONFIG_IPV6_ROUTER_PREF | 545 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| @@ -680,6 +685,9 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, | |||
| 680 | bool match_do_rr = false; | 685 | bool match_do_rr = false; |
| 681 | struct inet6_dev *idev = rt->rt6i_idev; | 686 | struct inet6_dev *idev = rt->rt6i_idev; |
| 682 | 687 | ||
| 688 | if (rt->rt6i_nh_flags & RTNH_F_DEAD) | ||
| 689 | goto out; | ||
| 690 | |||
| 683 | if (idev->cnf.ignore_routes_with_linkdown && | 691 | if (idev->cnf.ignore_routes_with_linkdown && |
| 684 | rt->rt6i_nh_flags & RTNH_F_LINKDOWN && | 692 | rt->rt6i_nh_flags & RTNH_F_LINKDOWN && |
| 685 | !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE)) | 693 | !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE)) |
| @@ -2153,6 +2161,8 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, | |||
| 2153 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); | 2161 | fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
| 2154 | restart: | 2162 | restart: |
| 2155 | for_each_fib6_node_rt_rcu(fn) { | 2163 | for_each_fib6_node_rt_rcu(fn) { |
| 2164 | if (rt->rt6i_nh_flags & RTNH_F_DEAD) | ||
| 2165 | continue; | ||
| 2156 | if (rt6_check_expired(rt)) | 2166 | if (rt6_check_expired(rt)) |
| 2157 | continue; | 2167 | continue; |
| 2158 | if (rt->dst.error) | 2168 | if (rt->dst.error) |
