diff options
-rw-r--r-- | include/linux/fib_rules.h | 3 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 21 |
2 files changed, 21 insertions, 3 deletions
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index 2987549d6044..4418c8d9d479 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h | |||
@@ -34,12 +34,13 @@ enum | |||
34 | FRA_UNUSED3, | 34 | FRA_UNUSED3, |
35 | FRA_UNUSED4, | 35 | FRA_UNUSED4, |
36 | FRA_UNUSED5, | 36 | FRA_UNUSED5, |
37 | FRA_FWMARK, /* netfilter mark (IPv4/IPv6) */ | 37 | FRA_FWMARK, /* netfilter mark */ |
38 | FRA_FLOW, /* flow/class id */ | 38 | FRA_FLOW, /* flow/class id */ |
39 | FRA_UNUSED6, | 39 | FRA_UNUSED6, |
40 | FRA_UNUSED7, | 40 | FRA_UNUSED7, |
41 | FRA_UNUSED8, | 41 | FRA_UNUSED8, |
42 | FRA_TABLE, /* Extended table id */ | 42 | FRA_TABLE, /* Extended table id */ |
43 | FRA_FWMASK, /* mask for netfilter mark */ | ||
43 | __FRA_MAX | 44 | __FRA_MAX |
44 | }; | 45 | }; |
45 | 46 | ||
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index ce185ac6f260..280f424ca9c9 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
@@ -46,6 +46,7 @@ struct fib4_rule | |||
46 | u32 dstmask; | 46 | u32 dstmask; |
47 | #ifdef CONFIG_IP_ROUTE_FWMARK | 47 | #ifdef CONFIG_IP_ROUTE_FWMARK |
48 | u32 fwmark; | 48 | u32 fwmark; |
49 | u32 fwmask; | ||
49 | #endif | 50 | #endif |
50 | #ifdef CONFIG_NET_CLS_ROUTE | 51 | #ifdef CONFIG_NET_CLS_ROUTE |
51 | u32 tclassid; | 52 | u32 tclassid; |
@@ -160,7 +161,7 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
160 | return 0; | 161 | return 0; |
161 | 162 | ||
162 | #ifdef CONFIG_IP_ROUTE_FWMARK | 163 | #ifdef CONFIG_IP_ROUTE_FWMARK |
163 | if (r->fwmark && (r->fwmark != fl->fl4_fwmark)) | 164 | if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask) |
164 | return 0; | 165 | return 0; |
165 | #endif | 166 | #endif |
166 | 167 | ||
@@ -183,6 +184,7 @@ static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { | |||
183 | [FRA_SRC] = { .type = NLA_U32 }, | 184 | [FRA_SRC] = { .type = NLA_U32 }, |
184 | [FRA_DST] = { .type = NLA_U32 }, | 185 | [FRA_DST] = { .type = NLA_U32 }, |
185 | [FRA_FWMARK] = { .type = NLA_U32 }, | 186 | [FRA_FWMARK] = { .type = NLA_U32 }, |
187 | [FRA_FWMASK] = { .type = NLA_U32 }, | ||
186 | [FRA_FLOW] = { .type = NLA_U32 }, | 188 | [FRA_FLOW] = { .type = NLA_U32 }, |
187 | [FRA_TABLE] = { .type = NLA_U32 }, | 189 | [FRA_TABLE] = { .type = NLA_U32 }, |
188 | }; | 190 | }; |
@@ -219,8 +221,17 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
219 | rule4->dst = nla_get_u32(tb[FRA_DST]); | 221 | rule4->dst = nla_get_u32(tb[FRA_DST]); |
220 | 222 | ||
221 | #ifdef CONFIG_IP_ROUTE_FWMARK | 223 | #ifdef CONFIG_IP_ROUTE_FWMARK |
222 | if (tb[FRA_FWMARK]) | 224 | if (tb[FRA_FWMARK]) { |
223 | rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); | 225 | rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); |
226 | if (rule4->fwmark) | ||
227 | /* compatibility: if the mark value is non-zero all bits | ||
228 | * are compared unless a mask is explicitly specified. | ||
229 | */ | ||
230 | rule4->fwmask = 0xFFFFFFFF; | ||
231 | } | ||
232 | |||
233 | if (tb[FRA_FWMASK]) | ||
234 | rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]); | ||
224 | #endif | 235 | #endif |
225 | 236 | ||
226 | #ifdef CONFIG_NET_CLS_ROUTE | 237 | #ifdef CONFIG_NET_CLS_ROUTE |
@@ -256,6 +267,9 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
256 | #ifdef CONFIG_IP_ROUTE_FWMARK | 267 | #ifdef CONFIG_IP_ROUTE_FWMARK |
257 | if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) | 268 | if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) |
258 | return 0; | 269 | return 0; |
270 | |||
271 | if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK]))) | ||
272 | return 0; | ||
259 | #endif | 273 | #endif |
260 | 274 | ||
261 | #ifdef CONFIG_NET_CLS_ROUTE | 275 | #ifdef CONFIG_NET_CLS_ROUTE |
@@ -285,6 +299,9 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
285 | #ifdef CONFIG_IP_ROUTE_FWMARK | 299 | #ifdef CONFIG_IP_ROUTE_FWMARK |
286 | if (rule4->fwmark) | 300 | if (rule4->fwmark) |
287 | NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); | 301 | NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); |
302 | |||
303 | if (rule4->fwmask || rule4->fwmark) | ||
304 | NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask); | ||
288 | #endif | 305 | #endif |
289 | 306 | ||
290 | if (rule4->dst_len) | 307 | if (rule4->dst_len) |