aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/route.c18
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 }
536out: 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);
2154restart: 2162restart:
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)