aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/fib6_rules.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2007-04-06 14:45:39 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:35 -0400
commit29f6af7712c40045e7886d0fa356d97a6f9aba49 (patch)
tree2b475a62ee778bd425150cd33352ca2df5c97c61 /net/ipv6/fib6_rules.c
parentea2f10a3c81724701fe6a754789eafd50b33909f (diff)
[IPV6] FIB6RULE: Find source address during looking up route.
When looking up route for destination with rules with source address restrictions, we may need to find a source address for the traffic if not given. Based on patch from Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/fib6_rules.c')
-rw-r--r--net/ipv6/fib6_rules.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index dd9720e700ef..fc3882c90604 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -17,6 +17,7 @@
17 17
18#include <net/fib_rules.h> 18#include <net/fib_rules.h>
19#include <net/ipv6.h> 19#include <net/ipv6.h>
20#include <net/addrconf.h>
20#include <net/ip6_route.h> 21#include <net/ip6_route.h>
21#include <net/netlink.h> 22#include <net/netlink.h>
22 23
@@ -95,8 +96,27 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
95 if (table) 96 if (table)
96 rt = lookup(table, flp, flags); 97 rt = lookup(table, flp, flags);
97 98
98 if (rt != &ip6_null_entry) 99 if (rt != &ip6_null_entry) {
100 struct fib6_rule *r = (struct fib6_rule *)rule;
101
102 /*
103 * If we need to find a source address for this traffic,
104 * we check the result if it meets requirement of the rule.
105 */
106 if ((rule->flags & FIB_RULE_FIND_SADDR) &&
107 r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {
108 struct in6_addr saddr;
109 if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst,
110 &saddr))
111 goto again;
112 if (!ipv6_prefix_equal(&saddr, &r->src.addr,
113 r->src.plen))
114 goto again;
115 ipv6_addr_copy(&flp->fl6_src, &saddr);
116 }
99 goto out; 117 goto out;
118 }
119again:
100 dst_release(&rt->u.dst); 120 dst_release(&rt->u.dst);
101 rt = NULL; 121 rt = NULL;
102 goto out; 122 goto out;
@@ -117,9 +137,17 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
117 !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) 137 !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
118 return 0; 138 return 0;
119 139
140 /*
141 * If FIB_RULE_FIND_SADDR is set and we do not have a
142 * source address for the traffic, we defer check for
143 * source address.
144 */
120 if (r->src.plen) { 145 if (r->src.plen) {
121 if (!(flags & RT6_LOOKUP_F_HAS_SADDR) || 146 if (flags & RT6_LOOKUP_F_HAS_SADDR) {
122 !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) 147 if (!ipv6_prefix_equal(&fl->fl6_src, &r->src.addr,
148 r->src.plen))
149 return 0;
150 } else if (!(r->common.flags & FIB_RULE_FIND_SADDR))
123 return 0; 151 return 0;
124 } 152 }
125 153