This patch moves the normal source address selection from ip6_dst_lookup() into ip6_pol_route_output(), but shouldn't change the routing or source address selection behavior in any way.
Signed-off-by: Ville Nuorvala <[EMAIL PROTECTED]> --- net/ipv6/ip6_output.c | 6 ------ net/ipv6/route.c | 37 ++++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 6671691..0019007 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -855,12 +855,6 @@ static int ip6_dst_lookup_tail(struct so if ((err = (*dst)->error)) goto out_err_release; - if (ipv6_addr_any(&fl->fl6_src)) { - err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); - if (err) - goto out_err_release; - } - return 0; out_err_release: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aa96be8..b7b8148 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -536,7 +536,7 @@ struct rt6_info *rt6_lookup(struct in6_a int flags = strict ? RT6_LOOKUP_F_IFACE : 0; if (saddr) { - memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); + ipv6_addr_copy(&fl.fl6_src, saddr); flags |= RT6_LOOKUP_F_HAS_SADDR; } @@ -629,13 +629,11 @@ static struct rt6_info *ip6_pol_route_in { struct fib6_node *fn; struct rt6_info *rt, *nrt; - int strict = 0; + int strict = flags & RT6_LOOKUP_F_IFACE; int attempts = 3; int err; int reachable = RT6_LOOKUP_F_REACHABLE; - strict |= flags & RT6_LOOKUP_F_IFACE; - relookup: read_lock_bh(&table->tb6_lock); @@ -726,22 +724,22 @@ static struct rt6_info *ip6_pol_route_ou { struct fib6_node *fn; struct rt6_info *rt, *nrt; - int strict = 0; - int attempts = 3; - int err; + int has_saddr = flags & RT6_LOOKUP_F_HAS_SADDR; + int strict = flags & RT6_LOOKUP_F_IFACE; int reachable = RT6_LOOKUP_F_REACHABLE; + int attempts = 3; + struct in6_addr saddr; - strict |= flags & RT6_LOOKUP_F_IFACE; - + ipv6_addr_copy(&saddr, &fl->fl6_src); relookup: read_lock_bh(&table->tb6_lock); restart_2: - fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &saddr); restart: rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); - BACKTRACK(&fl->fl6_src); + BACKTRACK(&saddr); if (rt == &ip6_null_entry || rt->rt6i_flags & RTF_CACHE) goto out; @@ -749,6 +747,13 @@ restart: dst_hold(&rt->u.dst); read_unlock_bh(&table->tb6_lock); + if (!has_saddr) { + /* policy rule doesn't restrict source address */ + if (ipv6_get_saddr(&rt->u.dst, &fl->fl6_dst, &saddr)) + goto no_saddr; + has_saddr = RT6_LOOKUP_F_HAS_SADDR; + ipv6_addr_copy(&fl->fl6_src, &saddr); + } if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); else { @@ -764,8 +769,7 @@ #endif dst_hold(&rt->u.dst); if (nrt) { - err = ip6_ins_rt(nrt); - if (!err) + if (!ip6_ins_rt(nrt)) goto out2; } @@ -778,7 +782,6 @@ #endif */ dst_release(&rt->u.dst); goto relookup; - out: if (reachable) { reachable = 0; @@ -790,6 +793,10 @@ out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; return rt; +no_saddr: + rt = &ip6_null_entry; + dst_hold(&rt->u.dst); + goto out2; } struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) @@ -2044,7 +2051,7 @@ #endif NLA_PUT_U32(skb, RTA_IIF, iif); else if (dst) { struct in6_addr saddr_buf; - if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) + if (!ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf)) NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } -- 1.4.2.3 - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html