aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/fib6_rules.c
diff options
context:
space:
mode:
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