Fixes rt6_lookup() to provide the source address in the flow
and sets RT6_LOOKUP_F_HAS_SADDR whenever it is present in
the flow.

Avoids unnecessary prefix comparisons by checking for a prefix
length first.

Fixes the rule logic to not match packets if a source selector
has been specified but no source address is available.

Thanks to Kim Nordlund <[EMAIL PROTECTED]> for working
on this patch with me.

Signed-off-by: Thomas Graf <[EMAIL PROTECTED]>

Index: net-2.6/net/ipv6/fib6_rules.c
===================================================================
--- net-2.6.orig/net/ipv6/fib6_rules.c  2006-10-11 22:29:50.000000000 +0200
+++ net-2.6/net/ipv6/fib6_rules.c       2006-10-12 11:01:00.000000000 +0200
@@ -117,12 +117,15 @@
 {
        struct fib6_rule *r = (struct fib6_rule *) rule;
 
-       if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
+       if (r->dst.plen &&
+           !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
                return 0;
 
-       if ((flags & RT6_LOOKUP_F_HAS_SADDR) &&
-           !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
-               return 0;
+       if (r->src.plen) {
+               if (!(flags & RT6_LOOKUP_F_HAS_SADDR) ||
+                   !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen))
+                       return 0;
+       }
 
        if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
                return 0;
Index: net-2.6/net/ipv6/route.c
===================================================================
--- net-2.6.orig/net/ipv6/route.c       2006-10-11 22:29:50.000000000 +0200
+++ net-2.6/net/ipv6/route.c    2006-10-12 10:59:13.000000000 +0200
@@ -529,13 +529,17 @@
                .nl_u = {
                        .ip6_u = {
                                .daddr = *daddr,
-                               /* TODO: saddr */
                        },
                },
        };
        struct dst_entry *dst;
        int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
 
+       if (saddr) {
+               memcpy(&fl.fl6_src, saddr, sizeof(*saddr));
+               flags |= RT6_LOOKUP_F_HAS_SADDR;
+       }
+
        dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup);
        if (dst->error == 0)
                return (struct rt6_info *) dst;
@@ -697,6 +701,7 @@
 void ip6_route_input(struct sk_buff *skb)
 {
        struct ipv6hdr *iph = skb->nh.ipv6h;
+       int flags = RT6_LOOKUP_F_HAS_SADDR;
        struct flowi fl = {
                .iif = skb->dev->ifindex,
                .nl_u = {
@@ -711,7 +716,9 @@
                },
                .proto = iph->nexthdr,
        };
-       int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0;
+
+       if (rt6_need_strict(&iph->daddr))
+               flags |= RT6_LOOKUP_F_IFACE;
 
        skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input);
 }
@@ -794,6 +801,9 @@
        if (rt6_need_strict(&fl->fl6_dst))
                flags |= RT6_LOOKUP_F_IFACE;
 
+       if (!ipv6_addr_any(&fl->fl6_src))
+               flags |= RT6_LOOKUP_F_HAS_SADDR;
+
        return fib6_rule_lookup(fl, flags, ip6_pol_route_output);
 }
 
@@ -1345,6 +1355,7 @@
                                           struct in6_addr *gateway,
                                           struct net_device *dev)
 {
+       int flags = RT6_LOOKUP_F_HAS_SADDR;
        struct ip6rd_flowi rdfl = {
                .fl = {
                        .oif = dev->ifindex,
@@ -1357,7 +1368,9 @@
                },
                .gateway = *gateway,
        };
-       int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0;
+
+       if (rt6_need_strict(dest))
+               flags |= RT6_LOOKUP_F_IFACE;
 
        return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, 
flags, __ip6_route_redirect);
 }
-
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

Reply via email to