aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/fib6_rules.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 6547fc6491a6..d040c4bff3a0 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -96,6 +96,31 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
96 return &net->ipv6.ip6_null_entry->dst; 96 return &net->ipv6.ip6_null_entry->dst;
97} 97}
98 98
99static int fib6_rule_saddr(struct net *net, struct fib_rule *rule, int flags,
100 struct flowi6 *flp6, const struct net_device *dev)
101{
102 struct fib6_rule *r = (struct fib6_rule *)rule;
103
104 /* If we need to find a source address for this traffic,
105 * we check the result if it meets requirement of the rule.
106 */
107 if ((rule->flags & FIB_RULE_FIND_SADDR) &&
108 r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {
109 struct in6_addr saddr;
110
111 if (ipv6_dev_get_saddr(net, dev, &flp6->daddr,
112 rt6_flags2srcprefs(flags), &saddr))
113 return -EAGAIN;
114
115 if (!ipv6_prefix_equal(&saddr, &r->src.addr, r->src.plen))
116 return -EAGAIN;
117
118 flp6->saddr = saddr;
119 }
120
121 return 0;
122}
123
99static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, 124static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
100 int flags, struct fib_lookup_arg *arg) 125 int flags, struct fib_lookup_arg *arg)
101{ 126{
@@ -134,27 +159,12 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
134 159
135 rt = lookup(net, table, flp6, arg->lookup_data, flags); 160 rt = lookup(net, table, flp6, arg->lookup_data, flags);
136 if (rt != net->ipv6.ip6_null_entry) { 161 if (rt != net->ipv6.ip6_null_entry) {
137 struct fib6_rule *r = (struct fib6_rule *)rule; 162 err = fib6_rule_saddr(net, rule, flags, flp6,
138 163 ip6_dst_idev(&rt->dst)->dev);
139 /* 164
140 * If we need to find a source address for this traffic, 165 if (err == -EAGAIN)
141 * we check the result if it meets requirement of the rule. 166 goto again;
142 */ 167
143 if ((rule->flags & FIB_RULE_FIND_SADDR) &&
144 r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) {
145 struct in6_addr saddr;
146
147 if (ipv6_dev_get_saddr(net,
148 ip6_dst_idev(&rt->dst)->dev,
149 &flp6->daddr,
150 rt6_flags2srcprefs(flags),
151 &saddr))
152 goto again;
153 if (!ipv6_prefix_equal(&saddr, &r->src.addr,
154 r->src.plen))
155 goto again;
156 flp6->saddr = saddr;
157 }
158 err = rt->dst.error; 168 err = rt->dst.error;
159 if (err != -EAGAIN) 169 if (err != -EAGAIN)
160 goto out; 170 goto out;