aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/route.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d8f3637952a2..6a068e7f81f1 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -414,23 +414,22 @@ void ip6_route_input(struct sk_buff *skb)
414 int strict; 414 int strict;
415 int attempts = 3; 415 int attempts = 3;
416 int err; 416 int err;
417 int reachable = RT6_SELECT_F_REACHABLE;
417 418
418 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; 419 strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
419 420
420relookup: 421relookup:
421 read_lock_bh(&rt6_lock); 422 read_lock_bh(&rt6_lock);
422 423
424restart_2:
423 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, 425 fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr,
424 &skb->nh.ipv6h->saddr); 426 &skb->nh.ipv6h->saddr);
425 427
426restart: 428restart:
427 rt = fn->leaf; 429 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable);
428
429 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | RT6_SELECT_F_REACHABLE);
430 if (rt == &ip6_null_entry)
431 rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict);
432 BACKTRACK(); 430 BACKTRACK();
433 if ((rt->rt6i_flags & RTF_CACHE)) 431 if (rt == &ip6_null_entry ||
432 rt->rt6i_flags & RTF_CACHE)
434 goto out; 433 goto out;
435 434
436 dst_hold(&rt->u.dst); 435 dst_hold(&rt->u.dst);
@@ -467,6 +466,10 @@ restart:
467 goto relookup; 466 goto relookup;
468 467
469out: 468out:
469 if (reachable) {
470 reachable = 0;
471 goto restart_2;
472 }
470 dst_hold(&rt->u.dst); 473 dst_hold(&rt->u.dst);
471 read_unlock_bh(&rt6_lock); 474 read_unlock_bh(&rt6_lock);
472out2: 475out2:
@@ -483,20 +486,21 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
483 int strict; 486 int strict;
484 int attempts = 3; 487 int attempts = 3;
485 int err; 488 int err;
489 int reachable = RT6_SELECT_F_REACHABLE;
486 490
487 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; 491 strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0;
488 492
489relookup: 493relookup:
490 read_lock_bh(&rt6_lock); 494 read_lock_bh(&rt6_lock);
491 495
496restart_2:
492 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src); 497 fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src);
493 498
494restart: 499restart:
495 rt = rt6_select(&fn->leaf, fl->oif, strict | RT6_SELECT_F_REACHABLE); 500 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
496 if (rt == &ip6_null_entry)
497 rt = rt6_select(&fn->leaf, fl->oif, strict);
498 BACKTRACK(); 501 BACKTRACK();
499 if ((rt->rt6i_flags & RTF_CACHE)) 502 if (rt == &ip6_null_entry ||
503 rt->rt6i_flags & RTF_CACHE)
500 goto out; 504 goto out;
501 505
502 dst_hold(&rt->u.dst); 506 dst_hold(&rt->u.dst);
@@ -533,6 +537,10 @@ restart:
533 goto relookup; 537 goto relookup;
534 538
535out: 539out:
540 if (reachable) {
541 reachable = 0;
542 goto restart_2;
543 }
536 dst_hold(&rt->u.dst); 544 dst_hold(&rt->u.dst);
537 read_unlock_bh(&rt6_lock); 545 read_unlock_bh(&rt6_lock);
538out2: 546out2: