diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/route.c | 28 |
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 | ||
420 | relookup: | 421 | relookup: |
421 | read_lock_bh(&rt6_lock); | 422 | read_lock_bh(&rt6_lock); |
422 | 423 | ||
424 | restart_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 | ||
426 | restart: | 428 | restart: |
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 | ||
469 | out: | 468 | out: |
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); |
472 | out2: | 475 | out2: |
@@ -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 | ||
489 | relookup: | 493 | relookup: |
490 | read_lock_bh(&rt6_lock); | 494 | read_lock_bh(&rt6_lock); |
491 | 495 | ||
496 | restart_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 | ||
494 | restart: | 499 | restart: |
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 | ||
535 | out: | 539 | out: |
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); |
538 | out2: | 546 | out2: |