diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2013-04-27 08:40:50 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-29 14:09:03 -0400 |
commit | 6e01781d1c80e2e8263471252a631e86165b15c5 (patch) | |
tree | 7984310c841a98832be4eaee3f865ce9bf2c355f /net/netfilter | |
parent | de76303c5a30e4754cd566dd4b9f3c26170fcf26 (diff) |
netfilter: ipset: set match: add support to match the counters
The new revision of the set match supports to match the counters
and to suppress updating the counters at matching too.
At the set:list types, the updating of the subcounters can be
suppressed as well.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/ipset/ip_set_core.c | 2 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_list_set.c | 8 | ||||
-rw-r--r-- | net/netfilter/xt_set.c | 70 |
3 files changed, 77 insertions, 3 deletions
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index f6d878a46c43..f77139007983 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -413,7 +413,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, | |||
413 | ret = 1; | 413 | ret = 1; |
414 | } else { | 414 | } else { |
415 | /* --return-nomatch: invert matched element */ | 415 | /* --return-nomatch: invert matched element */ |
416 | if ((opt->flags & IPSET_RETURN_NOMATCH) && | 416 | if ((opt->cmdflags & IPSET_FLAG_RETURN_NOMATCH) && |
417 | (set->type->features & IPSET_TYPE_NOMATCH) && | 417 | (set->type->features & IPSET_TYPE_NOMATCH) && |
418 | (ret > 0 || ret == -ENOTEMPTY)) | 418 | (ret > 0 || ret == -ENOTEMPTY)) |
419 | ret = -ret; | 419 | ret = -ret; |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index c09022e37406..979b8c90e422 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -84,9 +84,13 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, | |||
84 | { | 84 | { |
85 | struct list_set *map = set->data; | 85 | struct list_set *map = set->data; |
86 | struct set_elem *e; | 86 | struct set_elem *e; |
87 | u32 i; | 87 | u32 i, cmdflags = opt->cmdflags; |
88 | int ret; | 88 | int ret; |
89 | 89 | ||
90 | /* Don't lookup sub-counters at all */ | ||
91 | opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS; | ||
92 | if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) | ||
93 | opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; | ||
90 | for (i = 0; i < map->size; i++) { | 94 | for (i = 0; i < map->size; i++) { |
91 | e = list_set_elem(map, i); | 95 | e = list_set_elem(map, i); |
92 | if (e->id == IPSET_INVALID_ID) | 96 | if (e->id == IPSET_INVALID_ID) |
@@ -99,7 +103,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, | |||
99 | if (SET_WITH_COUNTER(set)) | 103 | if (SET_WITH_COUNTER(set)) |
100 | ip_set_update_counter(ext_counter(e, map), | 104 | ip_set_update_counter(ext_counter(e, map), |
101 | ext, &opt->ext, | 105 | ext, &opt->ext, |
102 | opt->cmdflags); | 106 | cmdflags); |
103 | return ret; | 107 | return ret; |
104 | } | 108 | } |
105 | } | 109 | } |
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 636c5199ff35..31790e789e22 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c | |||
@@ -189,6 +189,9 @@ set_match_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
189 | ADT_OPT(opt, par->family, info->match_set.dim, | 189 | ADT_OPT(opt, par->family, info->match_set.dim, |
190 | info->match_set.flags, 0, UINT_MAX); | 190 | info->match_set.flags, 0, UINT_MAX); |
191 | 191 | ||
192 | if (opt.flags & IPSET_RETURN_NOMATCH) | ||
193 | opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH; | ||
194 | |||
192 | return match_set(info->match_set.index, skb, par, &opt, | 195 | return match_set(info->match_set.index, skb, par, &opt, |
193 | info->match_set.flags & IPSET_INV_MATCH); | 196 | info->match_set.flags & IPSET_INV_MATCH); |
194 | } | 197 | } |
@@ -317,6 +320,52 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) | |||
317 | #define set_target_v2_checkentry set_target_v1_checkentry | 320 | #define set_target_v2_checkentry set_target_v1_checkentry |
318 | #define set_target_v2_destroy set_target_v1_destroy | 321 | #define set_target_v2_destroy set_target_v1_destroy |
319 | 322 | ||
323 | /* Revision 3 match */ | ||
324 | |||
325 | static bool | ||
326 | match_counter(u64 counter, const struct ip_set_counter_match *info) | ||
327 | { | ||
328 | switch (info->op) { | ||
329 | case IPSET_COUNTER_NONE: | ||
330 | return true; | ||
331 | case IPSET_COUNTER_EQ: | ||
332 | return counter == info->value; | ||
333 | case IPSET_COUNTER_NE: | ||
334 | return counter != info->value; | ||
335 | case IPSET_COUNTER_LT: | ||
336 | return counter < info->value; | ||
337 | case IPSET_COUNTER_GT: | ||
338 | return counter > info->value; | ||
339 | } | ||
340 | return false; | ||
341 | } | ||
342 | |||
343 | static bool | ||
344 | set_match_v3(const struct sk_buff *skb, struct xt_action_param *par) | ||
345 | { | ||
346 | const struct xt_set_info_match_v3 *info = par->matchinfo; | ||
347 | ADT_OPT(opt, par->family, info->match_set.dim, | ||
348 | info->match_set.flags, info->flags, UINT_MAX); | ||
349 | int ret; | ||
350 | |||
351 | if (info->packets.op != IPSET_COUNTER_NONE || | ||
352 | info->bytes.op != IPSET_COUNTER_NONE) | ||
353 | opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS; | ||
354 | |||
355 | ret = match_set(info->match_set.index, skb, par, &opt, | ||
356 | info->match_set.flags & IPSET_INV_MATCH); | ||
357 | |||
358 | if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS)) | ||
359 | return ret; | ||
360 | |||
361 | if (!match_counter(opt.ext.packets, &info->packets)) | ||
362 | return 0; | ||
363 | return match_counter(opt.ext.bytes, &info->bytes); | ||
364 | } | ||
365 | |||
366 | #define set_match_v3_checkentry set_match_v1_checkentry | ||
367 | #define set_match_v3_destroy set_match_v1_destroy | ||
368 | |||
320 | static struct xt_match set_matches[] __read_mostly = { | 369 | static struct xt_match set_matches[] __read_mostly = { |
321 | { | 370 | { |
322 | .name = "set", | 371 | .name = "set", |
@@ -369,6 +418,27 @@ static struct xt_match set_matches[] __read_mostly = { | |||
369 | .destroy = set_match_v1_destroy, | 418 | .destroy = set_match_v1_destroy, |
370 | .me = THIS_MODULE | 419 | .me = THIS_MODULE |
371 | }, | 420 | }, |
421 | /* counters support: update, match */ | ||
422 | { | ||
423 | .name = "set", | ||
424 | .family = NFPROTO_IPV4, | ||
425 | .revision = 3, | ||
426 | .match = set_match_v3, | ||
427 | .matchsize = sizeof(struct xt_set_info_match_v3), | ||
428 | .checkentry = set_match_v3_checkentry, | ||
429 | .destroy = set_match_v3_destroy, | ||
430 | .me = THIS_MODULE | ||
431 | }, | ||
432 | { | ||
433 | .name = "set", | ||
434 | .family = NFPROTO_IPV6, | ||
435 | .revision = 3, | ||
436 | .match = set_match_v3, | ||
437 | .matchsize = sizeof(struct xt_set_info_match_v3), | ||
438 | .checkentry = set_match_v3_checkentry, | ||
439 | .destroy = set_match_v3_destroy, | ||
440 | .me = THIS_MODULE | ||
441 | }, | ||
372 | }; | 442 | }; |
373 | 443 | ||
374 | static struct xt_target set_targets[] __read_mostly = { | 444 | static struct xt_target set_targets[] __read_mostly = { |