diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2013-04-08 17:11:32 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-29 14:09:02 -0400 |
commit | de76303c5a30e4754cd566dd4b9f3c26170fcf26 (patch) | |
tree | eeb68ce350fa8c72f5aff2e63f8db2cc4e682124 /net | |
parent | 00d71b270eedacd7d3d7b20fb93269853470d18e (diff) |
netfilter: ipset: The list:set type with counter support
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/ipset/ip_set_list_set.c | 73 |
1 files changed, 67 insertions, 6 deletions
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index 919eefe713d5..c09022e37406 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/netfilter/ipset/ip_set_list.h> | 16 | #include <linux/netfilter/ipset/ip_set_list.h> |
17 | 17 | ||
18 | #define REVISION_MIN 0 | 18 | #define REVISION_MIN 0 |
19 | #define REVISION_MAX 0 | 19 | #define REVISION_MAX 1 /* Counters support added */ |
20 | 20 | ||
21 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
22 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 22 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
@@ -35,6 +35,21 @@ struct sett_elem { | |||
35 | unsigned long timeout; | 35 | unsigned long timeout; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct setc_elem { | ||
39 | struct { | ||
40 | ip_set_id_t id; | ||
41 | } __attribute__ ((aligned)); | ||
42 | struct ip_set_counter counter; | ||
43 | }; | ||
44 | |||
45 | struct setct_elem { | ||
46 | struct { | ||
47 | ip_set_id_t id; | ||
48 | } __attribute__ ((aligned)); | ||
49 | struct ip_set_counter counter; | ||
50 | unsigned long timeout; | ||
51 | }; | ||
52 | |||
38 | struct set_adt_elem { | 53 | struct set_adt_elem { |
39 | ip_set_id_t id; | 54 | ip_set_id_t id; |
40 | ip_set_id_t refid; | 55 | ip_set_id_t refid; |
@@ -59,6 +74,8 @@ list_set_elem(const struct list_set *map, u32 id) | |||
59 | 74 | ||
60 | #define ext_timeout(e, m) \ | 75 | #define ext_timeout(e, m) \ |
61 | (unsigned long *)((void *)(e) + (m)->offset[IPSET_OFFSET_TIMEOUT]) | 76 | (unsigned long *)((void *)(e) + (m)->offset[IPSET_OFFSET_TIMEOUT]) |
77 | #define ext_counter(e, m) \ | ||
78 | (struct ip_set_counter *)((void *)(e) + (m)->offset[IPSET_OFFSET_COUNTER]) | ||
62 | 79 | ||
63 | static int | 80 | static int |
64 | list_set_ktest(struct ip_set *set, const struct sk_buff *skb, | 81 | list_set_ktest(struct ip_set *set, const struct sk_buff *skb, |
@@ -78,8 +95,13 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb, | |||
78 | ip_set_timeout_expired(ext_timeout(e, map))) | 95 | ip_set_timeout_expired(ext_timeout(e, map))) |
79 | continue; | 96 | continue; |
80 | ret = ip_set_test(e->id, skb, par, opt); | 97 | ret = ip_set_test(e->id, skb, par, opt); |
81 | if (ret > 0) | 98 | if (ret > 0) { |
99 | if (SET_WITH_COUNTER(set)) | ||
100 | ip_set_update_counter(ext_counter(e, map), | ||
101 | ext, &opt->ext, | ||
102 | opt->cmdflags); | ||
82 | return ret; | 103 | return ret; |
104 | } | ||
83 | } | 105 | } |
84 | return 0; | 106 | return 0; |
85 | } | 107 | } |
@@ -193,6 +215,8 @@ list_set_add(struct ip_set *set, u32 i, struct set_adt_elem *d, | |||
193 | e->id = d->id; | 215 | e->id = d->id; |
194 | if (SET_WITH_TIMEOUT(set)) | 216 | if (SET_WITH_TIMEOUT(set)) |
195 | ip_set_timeout_set(ext_timeout(e, map), ext->timeout); | 217 | ip_set_timeout_set(ext_timeout(e, map), ext->timeout); |
218 | if (SET_WITH_COUNTER(set)) | ||
219 | ip_set_init_counter(ext_counter(e, map), ext); | ||
196 | return 0; | 220 | return 0; |
197 | } | 221 | } |
198 | 222 | ||
@@ -293,6 +317,8 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
293 | /* Update extensions */ | 317 | /* Update extensions */ |
294 | if (SET_WITH_TIMEOUT(set)) | 318 | if (SET_WITH_TIMEOUT(set)) |
295 | ip_set_timeout_set(ext_timeout(e, map), ext->timeout); | 319 | ip_set_timeout_set(ext_timeout(e, map), ext->timeout); |
320 | if (SET_WITH_COUNTER(set)) | ||
321 | ip_set_init_counter(ext_counter(e, map), ext); | ||
296 | /* Set is already added to the list */ | 322 | /* Set is already added to the list */ |
297 | ip_set_put_byindex(d->id); | 323 | ip_set_put_byindex(d->id); |
298 | return 0; | 324 | return 0; |
@@ -362,7 +388,9 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
362 | 388 | ||
363 | if (unlikely(!tb[IPSET_ATTR_NAME] || | 389 | if (unlikely(!tb[IPSET_ATTR_NAME] || |
364 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || | 390 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || |
365 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) | 391 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || |
392 | !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || | ||
393 | !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) | ||
366 | return -IPSET_ERR_PROTOCOL; | 394 | return -IPSET_ERR_PROTOCOL; |
367 | 395 | ||
368 | if (tb[IPSET_ATTR_LINENO]) | 396 | if (tb[IPSET_ATTR_LINENO]) |
@@ -455,6 +483,9 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) | |||
455 | if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) || | 483 | if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) || |
456 | (SET_WITH_TIMEOUT(set) && | 484 | (SET_WITH_TIMEOUT(set) && |
457 | nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || | 485 | nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || |
486 | (SET_WITH_COUNTER(set) && | ||
487 | nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, | ||
488 | htonl(IPSET_FLAG_WITH_COUNTERS))) || | ||
458 | nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || | 489 | nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || |
459 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, | 490 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, |
460 | htonl(sizeof(*map) + map->size * map->dsize))) | 491 | htonl(sizeof(*map) + map->size * map->dsize))) |
@@ -502,6 +533,9 @@ list_set_list(const struct ip_set *set, | |||
502 | htonl(ip_set_timeout_get( | 533 | htonl(ip_set_timeout_get( |
503 | ext_timeout(e, map))))) | 534 | ext_timeout(e, map))))) |
504 | goto nla_put_failure; | 535 | goto nla_put_failure; |
536 | if (SET_WITH_COUNTER(set) && | ||
537 | ip_set_put_counter(skb, ext_counter(e, map))) | ||
538 | goto nla_put_failure; | ||
505 | ipset_nest_end(skb, nested); | 539 | ipset_nest_end(skb, nested); |
506 | } | 540 | } |
507 | finish: | 541 | finish: |
@@ -603,11 +637,12 @@ static int | |||
603 | list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | 637 | list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) |
604 | { | 638 | { |
605 | struct list_set *map; | 639 | struct list_set *map; |
606 | u32 size = IP_SET_LIST_DEFAULT_SIZE; | 640 | u32 size = IP_SET_LIST_DEFAULT_SIZE, cadt_flags = 0; |
607 | unsigned long timeout = 0; | 641 | unsigned long timeout = 0; |
608 | 642 | ||
609 | if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || | 643 | if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || |
610 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) | 644 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || |
645 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) | ||
611 | return -IPSET_ERR_PROTOCOL; | 646 | return -IPSET_ERR_PROTOCOL; |
612 | 647 | ||
613 | if (tb[IPSET_ATTR_SIZE]) | 648 | if (tb[IPSET_ATTR_SIZE]) |
@@ -615,10 +650,33 @@ list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) | |||
615 | if (size < IP_SET_LIST_MIN_SIZE) | 650 | if (size < IP_SET_LIST_MIN_SIZE) |
616 | size = IP_SET_LIST_MIN_SIZE; | 651 | size = IP_SET_LIST_MIN_SIZE; |
617 | 652 | ||
653 | if (tb[IPSET_ATTR_CADT_FLAGS]) | ||
654 | cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); | ||
618 | if (tb[IPSET_ATTR_TIMEOUT]) | 655 | if (tb[IPSET_ATTR_TIMEOUT]) |
619 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 656 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
620 | set->variant = &set_variant; | 657 | set->variant = &set_variant; |
621 | if (tb[IPSET_ATTR_TIMEOUT]) { | 658 | if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { |
659 | set->extensions |= IPSET_EXT_COUNTER; | ||
660 | if (tb[IPSET_ATTR_TIMEOUT]) { | ||
661 | map = init_list_set(set, size, | ||
662 | sizeof(struct setct_elem), timeout); | ||
663 | if (!map) | ||
664 | return -ENOMEM; | ||
665 | set->extensions |= IPSET_EXT_TIMEOUT; | ||
666 | map->offset[IPSET_OFFSET_TIMEOUT] = | ||
667 | offsetof(struct setct_elem, timeout); | ||
668 | map->offset[IPSET_OFFSET_COUNTER] = | ||
669 | offsetof(struct setct_elem, counter); | ||
670 | list_set_gc_init(set, list_set_gc); | ||
671 | } else { | ||
672 | map = init_list_set(set, size, | ||
673 | sizeof(struct setc_elem), 0); | ||
674 | if (!map) | ||
675 | return -ENOMEM; | ||
676 | map->offset[IPSET_OFFSET_COUNTER] = | ||
677 | offsetof(struct setc_elem, counter); | ||
678 | } | ||
679 | } else if (tb[IPSET_ATTR_TIMEOUT]) { | ||
622 | map = init_list_set(set, size, | 680 | map = init_list_set(set, size, |
623 | sizeof(struct sett_elem), timeout); | 681 | sizeof(struct sett_elem), timeout); |
624 | if (!map) | 682 | if (!map) |
@@ -647,6 +705,7 @@ static struct ip_set_type list_set_type __read_mostly = { | |||
647 | .create_policy = { | 705 | .create_policy = { |
648 | [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, | 706 | [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, |
649 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, | 707 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, |
708 | [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, | ||
650 | }, | 709 | }, |
651 | .adt_policy = { | 710 | .adt_policy = { |
652 | [IPSET_ATTR_NAME] = { .type = NLA_STRING, | 711 | [IPSET_ATTR_NAME] = { .type = NLA_STRING, |
@@ -656,6 +715,8 @@ static struct ip_set_type list_set_type __read_mostly = { | |||
656 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, | 715 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, |
657 | [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, | 716 | [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, |
658 | [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, | 717 | [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, |
718 | [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, | ||
719 | [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, | ||
659 | }, | 720 | }, |
660 | .me = THIS_MODULE, | 721 | .me = THIS_MODULE, |
661 | }; | 722 | }; |