diff options
Diffstat (limited to 'net/sched/cls_fw.c')
-rw-r--r-- | net/sched/cls_fw.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index e6973d9b686d..e54acc6bcccd 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -50,6 +50,7 @@ | |||
50 | struct fw_head | 50 | struct fw_head |
51 | { | 51 | { |
52 | struct fw_filter *ht[HTSIZE]; | 52 | struct fw_filter *ht[HTSIZE]; |
53 | u32 mask; | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct fw_filter | 56 | struct fw_filter |
@@ -101,7 +102,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, | |||
101 | struct fw_filter *f; | 102 | struct fw_filter *f; |
102 | int r; | 103 | int r; |
103 | #ifdef CONFIG_NETFILTER | 104 | #ifdef CONFIG_NETFILTER |
104 | u32 id = skb->nfmark; | 105 | u32 id = skb->nfmark & head->mask; |
105 | #else | 106 | #else |
106 | u32 id = 0; | 107 | u32 id = 0; |
107 | #endif | 108 | #endif |
@@ -209,7 +210,9 @@ static int | |||
209 | fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, | 210 | fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, |
210 | struct rtattr **tb, struct rtattr **tca, unsigned long base) | 211 | struct rtattr **tb, struct rtattr **tca, unsigned long base) |
211 | { | 212 | { |
213 | struct fw_head *head = (struct fw_head *)tp->root; | ||
212 | struct tcf_exts e; | 214 | struct tcf_exts e; |
215 | u32 mask; | ||
213 | int err; | 216 | int err; |
214 | 217 | ||
215 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map); | 218 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map); |
@@ -232,6 +235,15 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, | |||
232 | } | 235 | } |
233 | #endif /* CONFIG_NET_CLS_IND */ | 236 | #endif /* CONFIG_NET_CLS_IND */ |
234 | 237 | ||
238 | if (tb[TCA_FW_MASK-1]) { | ||
239 | if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32)) | ||
240 | goto errout; | ||
241 | mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]); | ||
242 | if (mask != head->mask) | ||
243 | goto errout; | ||
244 | } else if (head->mask != 0xFFFFFFFF) | ||
245 | goto errout; | ||
246 | |||
235 | tcf_exts_change(tp, &f->exts, &e); | 247 | tcf_exts_change(tp, &f->exts, &e); |
236 | 248 | ||
237 | return 0; | 249 | return 0; |
@@ -267,9 +279,17 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, | |||
267 | return -EINVAL; | 279 | return -EINVAL; |
268 | 280 | ||
269 | if (head == NULL) { | 281 | if (head == NULL) { |
282 | u32 mask = 0xFFFFFFFF; | ||
283 | if (tb[TCA_FW_MASK-1]) { | ||
284 | if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32)) | ||
285 | return -EINVAL; | ||
286 | mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]); | ||
287 | } | ||
288 | |||
270 | head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); | 289 | head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); |
271 | if (head == NULL) | 290 | if (head == NULL) |
272 | return -ENOBUFS; | 291 | return -ENOBUFS; |
292 | head->mask = mask; | ||
273 | 293 | ||
274 | tcf_tree_lock(tp); | 294 | tcf_tree_lock(tp); |
275 | tp->root = head; | 295 | tp->root = head; |
@@ -330,6 +350,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) | |||
330 | static int fw_dump(struct tcf_proto *tp, unsigned long fh, | 350 | static int fw_dump(struct tcf_proto *tp, unsigned long fh, |
331 | struct sk_buff *skb, struct tcmsg *t) | 351 | struct sk_buff *skb, struct tcmsg *t) |
332 | { | 352 | { |
353 | struct fw_head *head = (struct fw_head *)tp->root; | ||
333 | struct fw_filter *f = (struct fw_filter*)fh; | 354 | struct fw_filter *f = (struct fw_filter*)fh; |
334 | unsigned char *b = skb->tail; | 355 | unsigned char *b = skb->tail; |
335 | struct rtattr *rta; | 356 | struct rtattr *rta; |
@@ -351,6 +372,8 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, | |||
351 | if (strlen(f->indev)) | 372 | if (strlen(f->indev)) |
352 | RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev); | 373 | RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev); |
353 | #endif /* CONFIG_NET_CLS_IND */ | 374 | #endif /* CONFIG_NET_CLS_IND */ |
375 | if (head->mask != 0xFFFFFFFF) | ||
376 | RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask); | ||
354 | 377 | ||
355 | if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) | 378 | if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) |
356 | goto rtattr_failure; | 379 | goto rtattr_failure; |