aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-10-13 18:01:03 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-10-16 02:14:19 -0400
commitadaa70bbdfbc725e485179b06c8b23a20fbb7952 (patch)
treec402d42c660163902e1667fd67a00de409ac4a68 /net/ipv6
parent918049f0135854a1583f9b3b88f44dbf2b027329 (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/ipv6')
-rw-r--r--net/ipv6/fib6_rules.c11
-rw-r--r--net/ipv6/route.c19
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:
697void ip6_route_input(struct sk_buff *skb) 701void 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}