diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-08-25 19:05:43 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:18:08 -0400 |
commit | cd9d742622fbc2190221e0b2aca80596bfd17733 (patch) | |
tree | 4734f16bf89a5e7c24427058e494a5815ec6fca6 | |
parent | 2613aad5ab28579687519918cdc353af0eed5a3f (diff) |
[IPV6] ROUTE: Add support for fwmask in routing rules.
Add support for fwmark masks.
A mask of 0xFFFFFFFF is used when a mark value != 0 is sent without a mask.
Based on patch for net/ipv4/fib_rules.c by Patrick McHardy <kaber@trash.net>.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/fib6_rules.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 3d64c71f52de..ee4aa43ad973 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -28,6 +28,7 @@ struct fib6_rule | |||
28 | struct rt6key dst; | 28 | struct rt6key dst; |
29 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 29 | #ifdef CONFIG_IPV6_ROUTE_FWMARK |
30 | u32 fwmark; | 30 | u32 fwmark; |
31 | u32 fwmask; | ||
31 | #endif | 32 | #endif |
32 | u8 tclass; | 33 | u8 tclass; |
33 | }; | 34 | }; |
@@ -128,7 +129,7 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
128 | return 0; | 129 | return 0; |
129 | 130 | ||
130 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 131 | #ifdef CONFIG_IPV6_ROUTE_FWMARK |
131 | if (r->fwmark && (r->fwmark != fl->fl6_fwmark)) | 132 | if ((r->fwmark ^ fl->fl6_fwmark) / r->fwmask) |
132 | return 0; | 133 | return 0; |
133 | #endif | 134 | #endif |
134 | 135 | ||
@@ -141,6 +142,7 @@ static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { | |||
141 | [FRA_SRC] = { .minlen = sizeof(struct in6_addr) }, | 142 | [FRA_SRC] = { .minlen = sizeof(struct in6_addr) }, |
142 | [FRA_DST] = { .minlen = sizeof(struct in6_addr) }, | 143 | [FRA_DST] = { .minlen = sizeof(struct in6_addr) }, |
143 | [FRA_FWMARK] = { .type = NLA_U32 }, | 144 | [FRA_FWMARK] = { .type = NLA_U32 }, |
145 | [FRA_FWMASK] = { .type = NLA_U32 }, | ||
144 | [FRA_TABLE] = { .type = NLA_U32 }, | 146 | [FRA_TABLE] = { .type = NLA_U32 }, |
145 | }; | 147 | }; |
146 | 148 | ||
@@ -174,8 +176,20 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
174 | sizeof(struct in6_addr)); | 176 | sizeof(struct in6_addr)); |
175 | 177 | ||
176 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 178 | #ifdef CONFIG_IPV6_ROUTE_FWMARK |
177 | if (tb[FRA_FWMARK]) | 179 | if (tb[FRA_FWMARK]) { |
178 | rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); | 180 | rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); |
181 | if (rule6->fwmark) { | ||
182 | /* | ||
183 | * if the mark value is non-zero, | ||
184 | * all bits are compared by default | ||
185 | * unless a mask is explicitly specified. | ||
186 | */ | ||
187 | rule6->fwmask = 0xFFFFFFFF; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | if (tb[FRA_FWMASK]) | ||
192 | rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); | ||
179 | #endif | 193 | #endif |
180 | 194 | ||
181 | rule6->src.plen = frh->src_len; | 195 | rule6->src.plen = frh->src_len; |
@@ -212,6 +226,9 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
212 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 226 | #ifdef CONFIG_IPV6_ROUTE_FWMARK |
213 | if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) | 227 | if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) |
214 | return 0; | 228 | return 0; |
229 | |||
230 | if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) | ||
231 | return 0; | ||
215 | #endif | 232 | #endif |
216 | 233 | ||
217 | return 1; | 234 | return 1; |
@@ -238,6 +255,9 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
238 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 255 | #ifdef CONFIG_IPV6_ROUTE_FWMARK |
239 | if (rule6->fwmark) | 256 | if (rule6->fwmark) |
240 | NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); | 257 | NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); |
258 | |||
259 | if (rule6->fwmask) | ||
260 | NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); | ||
241 | #endif | 261 | #endif |
242 | 262 | ||
243 | return 0; | 263 | return 0; |