aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-04-08 17:10:22 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-04-29 14:09:00 -0400
commitf48d19db12e1cde296ce7a13c38303618e38e304 (patch)
tree521b8f49dab3469b938e8694752eaf598019e946 /net/netfilter
parent34d666d489cf70c246ca99b2387741915c34b88c (diff)
netfilter: ipset: The bitmap types 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/netfilter')
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_gen.h14
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c62
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c68
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c57
4 files changed, 186 insertions, 15 deletions
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
index b9931591cbe9..25243379b887 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -37,6 +37,8 @@
37 37
38#define ext_timeout(e, m) \ 38#define ext_timeout(e, m) \
39 (unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT]) 39 (unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT])
40#define ext_counter(e, m) \
41 (struct ip_set_counter *)((e) + (m)->offset[IPSET_OFFSET_COUNTER])
40#define get_ext(map, id) ((map)->extensions + (map)->dsize * (id)) 42#define get_ext(map, id) ((map)->extensions + (map)->dsize * (id))
41 43
42static void 44static void
@@ -91,7 +93,10 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
91 map->memsize + 93 map->memsize +
92 map->dsize * map->elements)) || 94 map->dsize * map->elements)) ||
93 (SET_WITH_TIMEOUT(set) && 95 (SET_WITH_TIMEOUT(set) &&
94 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) 96 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) ||
97 (SET_WITH_COUNTER(set) &&
98 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
99 htonl(IPSET_FLAG_WITH_COUNTERS))))
95 goto nla_put_failure; 100 goto nla_put_failure;
96 ipset_nest_end(skb, nested); 101 ipset_nest_end(skb, nested);
97 102
@@ -114,6 +119,8 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
114 if (SET_WITH_TIMEOUT(set) && 119 if (SET_WITH_TIMEOUT(set) &&
115 ip_set_timeout_expired(ext_timeout(x, map))) 120 ip_set_timeout_expired(ext_timeout(x, map)))
116 return 0; 121 return 0;
122 if (SET_WITH_COUNTER(set))
123 ip_set_update_counter(ext_counter(x, map), ext, mext, flags);
117 return 1; 124 return 1;
118} 125}
119 126
@@ -141,6 +148,8 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
141 ip_set_timeout_set(ext_timeout(x, map), ext->timeout); 148 ip_set_timeout_set(ext_timeout(x, map), ext->timeout);
142#endif 149#endif
143 150
151 if (SET_WITH_COUNTER(set))
152 ip_set_init_counter(ext_counter(x, map), ext);
144 return 0; 153 return 0;
145} 154}
146 155
@@ -205,6 +214,9 @@ mtype_list(const struct ip_set *set,
205 goto nla_put_failure; 214 goto nla_put_failure;
206#endif 215#endif
207 } 216 }
217 if (SET_WITH_COUNTER(set) &&
218 ip_set_put_counter(skb, ext_counter(x, map)))
219 goto nla_put_failure;
208 ipset_nest_end(skb, nested); 220 ipset_nest_end(skb, nested);
209 } 221 }
210 ipset_nest_end(skb, adt); 222 ipset_nest_end(skb, adt);
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index f2ab0116d94f..f1a8128bef01 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -26,7 +26,7 @@
26#include <linux/netfilter/ipset/ip_set_bitmap.h> 26#include <linux/netfilter/ipset/ip_set_bitmap.h>
27 27
28#define REVISION_MIN 0 28#define REVISION_MIN 0
29#define REVISION_MAX 0 29#define REVISION_MAX 1 /* Counter support added */
30 30
31MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -137,7 +137,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
137 int ret = 0; 137 int ret = 0;
138 138
139 if (unlikely(!tb[IPSET_ATTR_IP] || 139 if (unlikely(!tb[IPSET_ATTR_IP] ||
140 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 140 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
141 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
142 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
141 return -IPSET_ERR_PROTOCOL; 143 return -IPSET_ERR_PROTOCOL;
142 144
143 if (tb[IPSET_ATTR_LINENO]) 145 if (tb[IPSET_ATTR_LINENO])
@@ -213,6 +215,19 @@ struct bitmap_ipt_elem {
213 unsigned long timeout; 215 unsigned long timeout;
214}; 216};
215 217
218/* Plain variant with counter */
219
220struct bitmap_ipc_elem {
221 struct ip_set_counter counter;
222};
223
224/* Timeout variant with counter */
225
226struct bitmap_ipct_elem {
227 unsigned long timeout;
228 struct ip_set_counter counter;
229};
230
216#include "ip_set_bitmap_gen.h" 231#include "ip_set_bitmap_gen.h"
217 232
218/* Create bitmap:ip type of sets */ 233/* Create bitmap:ip type of sets */
@@ -249,13 +264,14 @@ static int
249bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 264bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
250{ 265{
251 struct bitmap_ip *map; 266 struct bitmap_ip *map;
252 u32 first_ip, last_ip, hosts; 267 u32 first_ip, last_ip, hosts, cadt_flags = 0;
253 u64 elements; 268 u64 elements;
254 u8 netmask = 32; 269 u8 netmask = 32;
255 int ret; 270 int ret;
256 271
257 if (unlikely(!tb[IPSET_ATTR_IP] || 272 if (unlikely(!tb[IPSET_ATTR_IP] ||
258 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 273 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
274 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
259 return -IPSET_ERR_PROTOCOL; 275 return -IPSET_ERR_PROTOCOL;
260 276
261 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); 277 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
@@ -320,7 +336,40 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
320 336
321 map->memsize = bitmap_bytes(0, elements - 1); 337 map->memsize = bitmap_bytes(0, elements - 1);
322 set->variant = &bitmap_ip; 338 set->variant = &bitmap_ip;
323 if (tb[IPSET_ATTR_TIMEOUT]) { 339 if (tb[IPSET_ATTR_CADT_FLAGS])
340 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
341 if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
342 set->extensions |= IPSET_EXT_COUNTER;
343 if (tb[IPSET_ATTR_TIMEOUT]) {
344 map->dsize = sizeof(struct bitmap_ipct_elem);
345 map->offset[IPSET_OFFSET_TIMEOUT] =
346 offsetof(struct bitmap_ipct_elem, timeout);
347 map->offset[IPSET_OFFSET_COUNTER] =
348 offsetof(struct bitmap_ipct_elem, counter);
349
350 if (!init_map_ip(set, map, first_ip, last_ip,
351 elements, hosts, netmask)) {
352 kfree(map);
353 return -ENOMEM;
354 }
355
356 map->timeout = ip_set_timeout_uget(
357 tb[IPSET_ATTR_TIMEOUT]);
358 set->extensions |= IPSET_EXT_TIMEOUT;
359
360 bitmap_ip_gc_init(set, bitmap_ip_gc);
361 } else {
362 map->dsize = sizeof(struct bitmap_ipc_elem);
363 map->offset[IPSET_OFFSET_COUNTER] =
364 offsetof(struct bitmap_ipc_elem, counter);
365
366 if (!init_map_ip(set, map, first_ip, last_ip,
367 elements, hosts, netmask)) {
368 kfree(map);
369 return -ENOMEM;
370 }
371 }
372 } else if (tb[IPSET_ATTR_TIMEOUT]) {
324 map->dsize = sizeof(struct bitmap_ipt_elem); 373 map->dsize = sizeof(struct bitmap_ipt_elem);
325 map->offset[IPSET_OFFSET_TIMEOUT] = 374 map->offset[IPSET_OFFSET_TIMEOUT] =
326 offsetof(struct bitmap_ipt_elem, timeout); 375 offsetof(struct bitmap_ipt_elem, timeout);
@@ -361,6 +410,7 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
361 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 410 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
362 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, 411 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
363 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 412 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
413 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
364 }, 414 },
365 .adt_policy = { 415 .adt_policy = {
366 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 416 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
@@ -368,6 +418,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
368 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 418 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
369 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 419 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
370 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 420 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
421 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
422 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
371 }, 423 },
372 .me = THIS_MODULE, 424 .me = THIS_MODULE,
373}; 425};
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index 960810dfcd81..3b30e0bef890 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -26,7 +26,7 @@
26#include <linux/netfilter/ipset/ip_set_bitmap.h> 26#include <linux/netfilter/ipset/ip_set_bitmap.h>
27 27
28#define REVISION_MIN 0 28#define REVISION_MIN 0
29#define REVISION_MAX 0 29#define REVISION_MAX 1 /* Counter support added */
30 30
31MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -250,7 +250,9 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
250 int ret = 0; 250 int ret = 0;
251 251
252 if (unlikely(!tb[IPSET_ATTR_IP] || 252 if (unlikely(!tb[IPSET_ATTR_IP] ||
253 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 253 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
254 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
255 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
254 return -IPSET_ERR_PROTOCOL; 256 return -IPSET_ERR_PROTOCOL;
255 257
256 if (tb[IPSET_ATTR_LINENO]) 258 if (tb[IPSET_ATTR_LINENO])
@@ -299,6 +301,27 @@ struct bitmap_ipmact_elem {
299 unsigned long timeout; 301 unsigned long timeout;
300}; 302};
301 303
304/* Plain variant with counter */
305
306struct bitmap_ipmacc_elem {
307 struct {
308 unsigned char ether[ETH_ALEN];
309 unsigned char filled;
310 } __attribute__ ((aligned));
311 struct ip_set_counter counter;
312};
313
314/* Timeout variant with counter */
315
316struct bitmap_ipmacct_elem {
317 struct {
318 unsigned char ether[ETH_ALEN];
319 unsigned char filled;
320 } __attribute__ ((aligned));
321 unsigned long timeout;
322 struct ip_set_counter counter;
323};
324
302#include "ip_set_bitmap_gen.h" 325#include "ip_set_bitmap_gen.h"
303 326
304/* Create bitmap:ip,mac type of sets */ 327/* Create bitmap:ip,mac type of sets */
@@ -332,13 +355,14 @@ static int
332bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], 355bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
333 u32 flags) 356 u32 flags)
334{ 357{
335 u32 first_ip, last_ip; 358 u32 first_ip, last_ip, cadt_flags = 0;
336 u64 elements; 359 u64 elements;
337 struct bitmap_ipmac *map; 360 struct bitmap_ipmac *map;
338 int ret; 361 int ret;
339 362
340 if (unlikely(!tb[IPSET_ATTR_IP] || 363 if (unlikely(!tb[IPSET_ATTR_IP] ||
341 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 364 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
365 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
342 return -IPSET_ERR_PROTOCOL; 366 return -IPSET_ERR_PROTOCOL;
343 367
344 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); 368 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
@@ -375,7 +399,38 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
375 399
376 map->memsize = bitmap_bytes(0, elements - 1); 400 map->memsize = bitmap_bytes(0, elements - 1);
377 set->variant = &bitmap_ipmac; 401 set->variant = &bitmap_ipmac;
378 if (tb[IPSET_ATTR_TIMEOUT]) { 402 if (tb[IPSET_ATTR_CADT_FLAGS])
403 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
404 if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
405 set->extensions |= IPSET_EXT_COUNTER;
406 if (tb[IPSET_ATTR_TIMEOUT]) {
407 map->dsize = sizeof(struct bitmap_ipmacct_elem);
408 map->offset[IPSET_OFFSET_TIMEOUT] =
409 offsetof(struct bitmap_ipmacct_elem, timeout);
410 map->offset[IPSET_OFFSET_COUNTER] =
411 offsetof(struct bitmap_ipmacct_elem, counter);
412
413 if (!init_map_ipmac(set, map, first_ip, last_ip,
414 elements)) {
415 kfree(map);
416 return -ENOMEM;
417 }
418 map->timeout = ip_set_timeout_uget(
419 tb[IPSET_ATTR_TIMEOUT]);
420 set->extensions |= IPSET_EXT_TIMEOUT;
421 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
422 } else {
423 map->dsize = sizeof(struct bitmap_ipmacc_elem);
424 map->offset[IPSET_OFFSET_COUNTER] =
425 offsetof(struct bitmap_ipmacc_elem, counter);
426
427 if (!init_map_ipmac(set, map, first_ip, last_ip,
428 elements)) {
429 kfree(map);
430 return -ENOMEM;
431 }
432 }
433 } else if (tb[IPSET_ATTR_TIMEOUT]) {
379 map->dsize = sizeof(struct bitmap_ipmact_elem); 434 map->dsize = sizeof(struct bitmap_ipmact_elem);
380 map->offset[IPSET_OFFSET_TIMEOUT] = 435 map->offset[IPSET_OFFSET_TIMEOUT] =
381 offsetof(struct bitmap_ipmact_elem, timeout); 436 offsetof(struct bitmap_ipmact_elem, timeout);
@@ -413,6 +468,7 @@ static struct ip_set_type bitmap_ipmac_type = {
413 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 468 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
414 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 469 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
415 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 470 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
471 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
416 }, 472 },
417 .adt_policy = { 473 .adt_policy = {
418 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 474 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
@@ -420,6 +476,8 @@ static struct ip_set_type bitmap_ipmac_type = {
420 .len = ETH_ALEN }, 476 .len = ETH_ALEN },
421 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 477 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
422 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 478 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
479 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
480 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
423 }, 481 },
424 .me = THIS_MODULE, 482 .me = THIS_MODULE,
425}; 483};
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index 27e2c573adcd..8207d1fda528 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -21,7 +21,7 @@
21#include <linux/netfilter/ipset/ip_set_getport.h> 21#include <linux/netfilter/ipset/ip_set_getport.h>
22 22
23#define REVISION_MIN 0 23#define REVISION_MIN 0
24#define REVISION_MAX 0 24#define REVISION_MAX 1 /* Counter support added */
25 25
26MODULE_LICENSE("GPL"); 26MODULE_LICENSE("GPL");
27MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 27MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -138,7 +138,9 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
138 138
139 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 139 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
140 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 140 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
141 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 141 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
142 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
143 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
142 return -IPSET_ERR_PROTOCOL; 144 return -IPSET_ERR_PROTOCOL;
143 145
144 if (tb[IPSET_ATTR_LINENO]) 146 if (tb[IPSET_ATTR_LINENO])
@@ -199,10 +201,24 @@ struct bitmap_port_elem {
199}; 201};
200 202
201/* Timeout variant */ 203/* Timeout variant */
204
202struct bitmap_portt_elem { 205struct bitmap_portt_elem {
203 unsigned long timeout; 206 unsigned long timeout;
204}; 207};
205 208
209/* Plain variant with counter */
210
211struct bitmap_portc_elem {
212 struct ip_set_counter counter;
213};
214
215/* Timeout variant with counter */
216
217struct bitmap_portct_elem {
218 unsigned long timeout;
219 struct ip_set_counter counter;
220};
221
206#include "ip_set_bitmap_gen.h" 222#include "ip_set_bitmap_gen.h"
207 223
208/* Create bitmap:ip type of sets */ 224/* Create bitmap:ip type of sets */
@@ -236,10 +252,12 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
236{ 252{
237 struct bitmap_port *map; 253 struct bitmap_port *map;
238 u16 first_port, last_port; 254 u16 first_port, last_port;
255 u32 cadt_flags = 0;
239 256
240 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 257 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
241 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || 258 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
242 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 259 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
260 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
243 return -IPSET_ERR_PROTOCOL; 261 return -IPSET_ERR_PROTOCOL;
244 262
245 first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); 263 first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
@@ -258,7 +276,35 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
258 map->elements = last_port - first_port + 1; 276 map->elements = last_port - first_port + 1;
259 map->memsize = map->elements * sizeof(unsigned long); 277 map->memsize = map->elements * sizeof(unsigned long);
260 set->variant = &bitmap_port; 278 set->variant = &bitmap_port;
261 if (tb[IPSET_ATTR_TIMEOUT]) { 279 if (tb[IPSET_ATTR_CADT_FLAGS])
280 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
281 if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
282 set->extensions |= IPSET_EXT_COUNTER;
283 if (tb[IPSET_ATTR_TIMEOUT]) {
284 map->dsize = sizeof(struct bitmap_portct_elem);
285 map->offset[IPSET_OFFSET_TIMEOUT] =
286 offsetof(struct bitmap_portct_elem, timeout);
287 map->offset[IPSET_OFFSET_COUNTER] =
288 offsetof(struct bitmap_portct_elem, counter);
289 if (!init_map_port(set, map, first_port, last_port)) {
290 kfree(map);
291 return -ENOMEM;
292 }
293
294 map->timeout =
295 ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
296 set->extensions |= IPSET_EXT_TIMEOUT;
297 bitmap_port_gc_init(set, bitmap_port_gc);
298 } else {
299 map->dsize = sizeof(struct bitmap_portc_elem);
300 map->offset[IPSET_OFFSET_COUNTER] =
301 offsetof(struct bitmap_portc_elem, counter);
302 if (!init_map_port(set, map, first_port, last_port)) {
303 kfree(map);
304 return -ENOMEM;
305 }
306 }
307 } else if (tb[IPSET_ATTR_TIMEOUT]) {
262 map->dsize = sizeof(struct bitmap_portt_elem); 308 map->dsize = sizeof(struct bitmap_portt_elem);
263 map->offset[IPSET_OFFSET_TIMEOUT] = 309 map->offset[IPSET_OFFSET_TIMEOUT] =
264 offsetof(struct bitmap_portt_elem, timeout); 310 offsetof(struct bitmap_portt_elem, timeout);
@@ -294,12 +340,15 @@ static struct ip_set_type bitmap_port_type = {
294 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 340 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
295 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 341 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
296 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 342 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
343 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
297 }, 344 },
298 .adt_policy = { 345 .adt_policy = {
299 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 346 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
300 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 347 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
301 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 348 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
302 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 349 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
350 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
351 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
303 }, 352 },
304 .me = THIS_MODULE, 353 .me = THIS_MODULE,
305}; 354};