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