diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-10-13 18:01:03 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-16 02:14:19 -0400 |
commit | adaa70bbdfbc725e485179b06c8b23a20fbb7952 (patch) | |
tree | c402d42c660163902e1667fd67a00de409ac4a68 /net | |
parent | 918049f0135854a1583f9b3b88f44dbf2b027329 (diff) |
[IPv6] rules: Use RT6_LOOKUP_F_HAS_SADDR and fix source based selectors
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 <kim.nordlund@nokia.com> for working
on this patch with me.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Acked-by: Ville Nuorvala <vnuorval@tcs.hut.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/fib6_rules.c | 11 | ||||
-rw-r--r-- | net/ipv6/route.c | 19 |
2 files changed, 23 insertions, 7 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index d8c1057e8b00..1896ecb52899 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -117,12 +117,15 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
117 | { | 117 | { |
118 | struct fib6_rule *r = (struct fib6_rule *) rule; | 118 | struct fib6_rule *r = (struct fib6_rule *) rule; |
119 | 119 | ||
120 | if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) | 120 | if (r->dst.plen && |
121 | !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) | ||
121 | return 0; | 122 | return 0; |
122 | 123 | ||
123 | if ((flags & RT6_LOOKUP_F_HAS_SADDR) && | 124 | if (r->src.plen) { |
124 | !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) | 125 | if (!(flags & RT6_LOOKUP_F_HAS_SADDR) || |
125 | return 0; | 126 | !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) |
127 | return 0; | ||
128 | } | ||
126 | 129 | ||
127 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) | 130 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) |
128 | return 0; | 131 | return 0; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d6b4b4f48d18..a1b0f075462e 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -529,13 +529,17 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | |||
529 | .nl_u = { | 529 | .nl_u = { |
530 | .ip6_u = { | 530 | .ip6_u = { |
531 | .daddr = *daddr, | 531 | .daddr = *daddr, |
532 | /* TODO: saddr */ | ||
533 | }, | 532 | }, |
534 | }, | 533 | }, |
535 | }; | 534 | }; |
536 | struct dst_entry *dst; | 535 | struct dst_entry *dst; |
537 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; | 536 | int flags = strict ? RT6_LOOKUP_F_IFACE : 0; |
538 | 537 | ||
538 | if (saddr) { | ||
539 | memcpy(&fl.fl6_src, saddr, sizeof(*saddr)); | ||
540 | flags |= RT6_LOOKUP_F_HAS_SADDR; | ||
541 | } | ||
542 | |||
539 | dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); | 543 | dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); |
540 | if (dst->error == 0) | 544 | if (dst->error == 0) |
541 | return (struct rt6_info *) dst; | 545 | return (struct rt6_info *) dst; |
@@ -697,6 +701,7 @@ out2: | |||
697 | void ip6_route_input(struct sk_buff *skb) | 701 | void ip6_route_input(struct sk_buff *skb) |
698 | { | 702 | { |
699 | struct ipv6hdr *iph = skb->nh.ipv6h; | 703 | struct ipv6hdr *iph = skb->nh.ipv6h; |
704 | int flags = RT6_LOOKUP_F_HAS_SADDR; | ||
700 | struct flowi fl = { | 705 | struct flowi fl = { |
701 | .iif = skb->dev->ifindex, | 706 | .iif = skb->dev->ifindex, |
702 | .nl_u = { | 707 | .nl_u = { |
@@ -711,7 +716,9 @@ void ip6_route_input(struct sk_buff *skb) | |||
711 | }, | 716 | }, |
712 | .proto = iph->nexthdr, | 717 | .proto = iph->nexthdr, |
713 | }; | 718 | }; |
714 | int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0; | 719 | |
720 | if (rt6_need_strict(&iph->daddr)) | ||
721 | flags |= RT6_LOOKUP_F_IFACE; | ||
715 | 722 | ||
716 | skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); | 723 | skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); |
717 | } | 724 | } |
@@ -794,6 +801,9 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
794 | if (rt6_need_strict(&fl->fl6_dst)) | 801 | if (rt6_need_strict(&fl->fl6_dst)) |
795 | flags |= RT6_LOOKUP_F_IFACE; | 802 | flags |= RT6_LOOKUP_F_IFACE; |
796 | 803 | ||
804 | if (!ipv6_addr_any(&fl->fl6_src)) | ||
805 | flags |= RT6_LOOKUP_F_HAS_SADDR; | ||
806 | |||
797 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); | 807 | return fib6_rule_lookup(fl, flags, ip6_pol_route_output); |
798 | } | 808 | } |
799 | 809 | ||
@@ -1345,6 +1355,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1345 | struct in6_addr *gateway, | 1355 | struct in6_addr *gateway, |
1346 | struct net_device *dev) | 1356 | struct net_device *dev) |
1347 | { | 1357 | { |
1358 | int flags = RT6_LOOKUP_F_HAS_SADDR; | ||
1348 | struct ip6rd_flowi rdfl = { | 1359 | struct ip6rd_flowi rdfl = { |
1349 | .fl = { | 1360 | .fl = { |
1350 | .oif = dev->ifindex, | 1361 | .oif = dev->ifindex, |
@@ -1357,7 +1368,9 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1357 | }, | 1368 | }, |
1358 | .gateway = *gateway, | 1369 | .gateway = *gateway, |
1359 | }; | 1370 | }; |
1360 | int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0; | 1371 | |
1372 | if (rt6_need_strict(dest)) | ||
1373 | flags |= RT6_LOOKUP_F_IFACE; | ||
1361 | 1374 | ||
1362 | return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); | 1375 | return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); |
1363 | } | 1376 | } |