aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/route.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8d00a9d77f01..bd4cf175ff10 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -481,17 +481,23 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
481} 481}
482#endif 482#endif
483 483
484#define BACKTRACK() \ 484#define BACKTRACK(saddr) \
485if (rt == &ip6_null_entry && flags & RT6_F_STRICT) { \ 485do { \
486 while ((fn = fn->parent) != NULL) { \ 486 if (rt == &ip6_null_entry) { \
487 if (fn->fn_flags & RTN_TL_ROOT) { \ 487 struct fib6_node *pn; \
488 dst_hold(&rt->u.dst); \ 488 while (fn) { \
489 goto out; \ 489 if (fn->fn_flags & RTN_TL_ROOT) \
490 goto out; \
491 pn = fn->parent; \
492 if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
493 fn = fib6_lookup(pn->subtree, NULL, saddr); \
494 else \
495 fn = pn; \
496 if (fn->fn_flags & RTN_RTINFO) \
497 goto restart; \
490 } \ 498 } \
491 if (fn->fn_flags & RTN_RTINFO) \
492 goto restart; \
493 } \ 499 } \
494} 500} while(0)
495 501
496static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, 502static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
497 struct flowi *fl, int flags) 503 struct flowi *fl, int flags)
@@ -504,7 +510,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table,
504restart: 510restart:
505 rt = fn->leaf; 511 rt = fn->leaf;
506 rt = rt6_device_match(rt, fl->oif, flags & RT6_F_STRICT); 512 rt = rt6_device_match(rt, fl->oif, flags & RT6_F_STRICT);
507 BACKTRACK(); 513 BACKTRACK(&fl->fl6_src);
508 dst_hold(&rt->u.dst); 514 dst_hold(&rt->u.dst);
509out: 515out:
510 read_unlock_bh(&table->tb6_lock); 516 read_unlock_bh(&table->tb6_lock);
@@ -638,7 +644,7 @@ restart_2:
638 644
639restart: 645restart:
640 rt = rt6_select(&fn->leaf, fl->iif, strict | reachable); 646 rt = rt6_select(&fn->leaf, fl->iif, strict | reachable);
641 BACKTRACK(); 647 BACKTRACK(&fl->fl6_src);
642 if (rt == &ip6_null_entry || 648 if (rt == &ip6_null_entry ||
643 rt->rt6i_flags & RTF_CACHE) 649 rt->rt6i_flags & RTF_CACHE)
644 goto out; 650 goto out;
@@ -733,7 +739,7 @@ restart_2:
733 739
734restart: 740restart:
735 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); 741 rt = rt6_select(&fn->leaf, fl->oif, strict | reachable);
736 BACKTRACK(); 742 BACKTRACK(&fl->fl6_src);
737 if (rt == &ip6_null_entry || 743 if (rt == &ip6_null_entry ||
738 rt->rt6i_flags & RTF_CACHE) 744 rt->rt6i_flags & RTF_CACHE)
739 goto out; 745 goto out;