aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-04-08 17:11:32 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-04-29 14:09:02 -0400
commitde76303c5a30e4754cd566dd4b9f3c26170fcf26 (patch)
treeeeb68ce350fa8c72f5aff2e63f8db2cc4e682124 /net
parent00d71b270eedacd7d3d7b20fb93269853470d18e (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.c73
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
21MODULE_LICENSE("GPL"); 21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 22MODULE_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
38struct setc_elem {
39 struct {
40 ip_set_id_t id;
41 } __attribute__ ((aligned));
42 struct ip_set_counter counter;
43};
44
45struct 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
38struct set_adt_elem { 53struct 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
63static int 80static int
64list_set_ktest(struct ip_set *set, const struct sk_buff *skb, 81list_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 }
507finish: 541finish:
@@ -603,11 +637,12 @@ static int
603list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 637list_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};