aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-04-27 08:37:01 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-04-29 14:08:55 -0400
commitb0da3905bb1eb0969470f57b18c978f902475c78 (patch)
tree7d8b0e3a06377cd682dda2dcb01c0feaab58b99a /net
parent4d73de38c256623b324474098f7d2bb4e97f7cf0 (diff)
netfilter: ipset: Bitmap types using the unified code base
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_bitmap_ip.c351
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c562
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c361
3 files changed, 316 insertions, 958 deletions
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index 4a92fd47bd4c..f2ab0116d94f 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -1,6 +1,6 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de> 2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 3 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -24,8 +24,6 @@
24#include <linux/netfilter/ipset/pfxlen.h> 24#include <linux/netfilter/ipset/pfxlen.h>
25#include <linux/netfilter/ipset/ip_set.h> 25#include <linux/netfilter/ipset/ip_set.h>
26#include <linux/netfilter/ipset/ip_set_bitmap.h> 26#include <linux/netfilter/ipset/ip_set_bitmap.h>
27#define IP_SET_BITMAP_TIMEOUT
28#include <linux/netfilter/ipset/ip_set_timeout.h>
29 27
30#define REVISION_MIN 0 28#define REVISION_MIN 0
31#define REVISION_MAX 0 29#define REVISION_MAX 0
@@ -35,20 +33,28 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
35IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX); 33IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX);
36MODULE_ALIAS("ip_set_bitmap:ip"); 34MODULE_ALIAS("ip_set_bitmap:ip");
37 35
36#define MTYPE bitmap_ip
37
38/* Type structure */ 38/* Type structure */
39struct bitmap_ip { 39struct bitmap_ip {
40 void *members; /* the set members */ 40 void *members; /* the set members */
41 void *extensions; /* data extensions */
41 u32 first_ip; /* host byte order, included in range */ 42 u32 first_ip; /* host byte order, included in range */
42 u32 last_ip; /* host byte order, included in range */ 43 u32 last_ip; /* host byte order, included in range */
43 u32 elements; /* number of max elements in the set */ 44 u32 elements; /* number of max elements in the set */
44 u32 hosts; /* number of hosts in a subnet */ 45 u32 hosts; /* number of hosts in a subnet */
45 size_t memsize; /* members size */ 46 size_t memsize; /* members size */
47 size_t dsize; /* extensions struct size */
48 size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
46 u8 netmask; /* subnet netmask */ 49 u8 netmask; /* subnet netmask */
47 u32 timeout; /* timeout parameter */ 50 u32 timeout; /* timeout parameter */
48 struct timer_list gc; /* garbage collection */ 51 struct timer_list gc; /* garbage collection */
49}; 52};
50 53
51/* Base variant */ 54/* ADT structure for generic function args */
55struct bitmap_ip_adt_elem {
56 u16 id;
57};
52 58
53static inline u32 59static inline u32
54ip_to_id(const struct bitmap_ip *m, u32 ip) 60ip_to_id(const struct bitmap_ip *m, u32 ip)
@@ -56,188 +62,67 @@ ip_to_id(const struct bitmap_ip *m, u32 ip)
56 return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts; 62 return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
57} 63}
58 64
59static int 65/* Common functions */
60bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
61{
62 const struct bitmap_ip *map = set->data;
63 u16 id = *(u16 *)value;
64
65 return !!test_bit(id, map->members);
66}
67
68static int
69bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
70{
71 struct bitmap_ip *map = set->data;
72 u16 id = *(u16 *)value;
73
74 if (test_and_set_bit(id, map->members))
75 return -IPSET_ERR_EXIST;
76
77 return 0;
78}
79 66
80static int 67static inline int
81bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags) 68bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map)
82{ 69{
83 struct bitmap_ip *map = set->data; 70 return !!test_bit(e->id, map->members);
84 u16 id = *(u16 *)value;
85
86 if (!test_and_clear_bit(id, map->members))
87 return -IPSET_ERR_EXIST;
88
89 return 0;
90} 71}
91 72
92static int 73static inline int
93bitmap_ip_list(const struct ip_set *set, 74bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map)
94 struct sk_buff *skb, struct netlink_callback *cb)
95{ 75{
96 const struct bitmap_ip *map = set->data; 76 return !!test_bit(id, map->members);
97 struct nlattr *atd, *nested;
98 u32 id, first = cb->args[2];
99
100 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
101 if (!atd)
102 return -EMSGSIZE;
103 for (; cb->args[2] < map->elements; cb->args[2]++) {
104 id = cb->args[2];
105 if (!test_bit(id, map->members))
106 continue;
107 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
108 if (!nested) {
109 if (id == first) {
110 nla_nest_cancel(skb, atd);
111 return -EMSGSIZE;
112 } else
113 goto nla_put_failure;
114 }
115 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
116 htonl(map->first_ip + id * map->hosts)))
117 goto nla_put_failure;
118 ipset_nest_end(skb, nested);
119 }
120 ipset_nest_end(skb, atd);
121 /* Set listing finished */
122 cb->args[2] = 0;
123 return 0;
124
125nla_put_failure:
126 nla_nest_cancel(skb, nested);
127 ipset_nest_end(skb, atd);
128 if (unlikely(id == first)) {
129 cb->args[2] = 0;
130 return -EMSGSIZE;
131 }
132 return 0;
133} 77}
134 78
135/* Timeout variant */ 79static inline int
136 80bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map,
137static int 81 u32 flags)
138bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
139{ 82{
140 const struct bitmap_ip *map = set->data; 83 return !!test_and_set_bit(e->id, map->members);
141 const unsigned long *members = map->members;
142 u16 id = *(u16 *)value;
143
144 return ip_set_timeout_test(members[id]);
145} 84}
146 85
147static int 86static inline int
148bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) 87bitmap_ip_do_del(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map)
149{ 88{
150 struct bitmap_ip *map = set->data; 89 return !test_and_clear_bit(e->id, map->members);
151 unsigned long *members = map->members;
152 u16 id = *(u16 *)value;
153
154 if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
155 return -IPSET_ERR_EXIST;
156
157 members[id] = ip_set_timeout_set(timeout);
158
159 return 0;
160} 90}
161 91
162static int 92static inline int
163bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) 93bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id)
164{ 94{
165 struct bitmap_ip *map = set->data; 95 return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
166 unsigned long *members = map->members; 96 htonl(map->first_ip + id * map->hosts));
167 u16 id = *(u16 *)value;
168 int ret = -IPSET_ERR_EXIST;
169
170 if (ip_set_timeout_test(members[id]))
171 ret = 0;
172
173 members[id] = IPSET_ELEM_UNSET;
174 return ret;
175} 97}
176 98
177static int 99static inline int
178bitmap_ip_tlist(const struct ip_set *set, 100bitmap_ip_do_head(struct sk_buff *skb, const struct bitmap_ip *map)
179 struct sk_buff *skb, struct netlink_callback *cb)
180{ 101{
181 const struct bitmap_ip *map = set->data; 102 return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
182 struct nlattr *adt, *nested; 103 nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
183 u32 id, first = cb->args[2]; 104 (map->netmask != 32 &&
184 const unsigned long *members = map->members; 105 nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask));
185
186 adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
187 if (!adt)
188 return -EMSGSIZE;
189 for (; cb->args[2] < map->elements; cb->args[2]++) {
190 id = cb->args[2];
191 if (!ip_set_timeout_test(members[id]))
192 continue;
193 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
194 if (!nested) {
195 if (id == first) {
196 nla_nest_cancel(skb, adt);
197 return -EMSGSIZE;
198 } else
199 goto nla_put_failure;
200 }
201 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
202 htonl(map->first_ip + id * map->hosts)) ||
203 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
204 htonl(ip_set_timeout_get(members[id]))))
205 goto nla_put_failure;
206 ipset_nest_end(skb, nested);
207 }
208 ipset_nest_end(skb, adt);
209
210 /* Set listing finished */
211 cb->args[2] = 0;
212
213 return 0;
214
215nla_put_failure:
216 nla_nest_cancel(skb, nested);
217 ipset_nest_end(skb, adt);
218 if (unlikely(id == first)) {
219 cb->args[2] = 0;
220 return -EMSGSIZE;
221 }
222 return 0;
223} 106}
224 107
225static int 108static int
226bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, 109bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
227 const struct xt_action_param *par, 110 const struct xt_action_param *par,
228 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 111 enum ipset_adt adt, struct ip_set_adt_opt *opt)
229{ 112{
230 struct bitmap_ip *map = set->data; 113 struct bitmap_ip *map = set->data;
231 ipset_adtfn adtfn = set->variant->adt[adt]; 114 ipset_adtfn adtfn = set->variant->adt[adt];
115 struct bitmap_ip_adt_elem e = { };
116 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
232 u32 ip; 117 u32 ip;
233 118
234 ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC)); 119 ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
235 if (ip < map->first_ip || ip > map->last_ip) 120 if (ip < map->first_ip || ip > map->last_ip)
236 return -IPSET_ERR_BITMAP_RANGE; 121 return -IPSET_ERR_BITMAP_RANGE;
237 122
238 ip = ip_to_id(map, ip); 123 e.id = ip_to_id(map, ip);
239 124
240 return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags); 125 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
241} 126}
242 127
243static int 128static int
@@ -246,8 +131,9 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
246{ 131{
247 struct bitmap_ip *map = set->data; 132 struct bitmap_ip *map = set->data;
248 ipset_adtfn adtfn = set->variant->adt[adt]; 133 ipset_adtfn adtfn = set->variant->adt[adt];
249 u32 timeout = map->timeout; 134 u32 ip, ip_to;
250 u32 ip, ip_to, id; 135 struct bitmap_ip_adt_elem e = { };
136 struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
251 int ret = 0; 137 int ret = 0;
252 138
253 if (unlikely(!tb[IPSET_ATTR_IP] || 139 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -257,22 +143,17 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
257 if (tb[IPSET_ATTR_LINENO]) 143 if (tb[IPSET_ATTR_LINENO])
258 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 144 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
259 145
260 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 146 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
147 ip_set_get_extensions(set, tb, &ext);
261 if (ret) 148 if (ret)
262 return ret; 149 return ret;
263 150
264 if (ip < map->first_ip || ip > map->last_ip) 151 if (ip < map->first_ip || ip > map->last_ip)
265 return -IPSET_ERR_BITMAP_RANGE; 152 return -IPSET_ERR_BITMAP_RANGE;
266 153
267 if (tb[IPSET_ATTR_TIMEOUT]) {
268 if (!with_timeout(map->timeout))
269 return -IPSET_ERR_TIMEOUT;
270 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
271 }
272
273 if (adt == IPSET_TEST) { 154 if (adt == IPSET_TEST) {
274 id = ip_to_id(map, ip); 155 e.id = ip_to_id(map, ip);
275 return adtfn(set, &id, timeout, flags); 156 return adtfn(set, &e, &ext, &ext, flags);
276 } 157 }
277 158
278 if (tb[IPSET_ATTR_IP_TO]) { 159 if (tb[IPSET_ATTR_IP_TO]) {
@@ -297,8 +178,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
297 return -IPSET_ERR_BITMAP_RANGE; 178 return -IPSET_ERR_BITMAP_RANGE;
298 179
299 for (; !before(ip_to, ip); ip += map->hosts) { 180 for (; !before(ip_to, ip); ip += map->hosts) {
300 id = ip_to_id(map, ip); 181 e.id = ip_to_id(map, ip);
301 ret = adtfn(set, &id, timeout, flags); 182 ret = adtfn(set, &e, &ext, &ext, flags);
302 183
303 if (ret && !ip_set_eexist(ret, flags)) 184 if (ret && !ip_set_eexist(ret, flags))
304 return ret; 185 return ret;
@@ -308,54 +189,6 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
308 return ret; 189 return ret;
309} 190}
310 191
311static void
312bitmap_ip_destroy(struct ip_set *set)
313{
314 struct bitmap_ip *map = set->data;
315
316 if (with_timeout(map->timeout))
317 del_timer_sync(&map->gc);
318
319 ip_set_free(map->members);
320 kfree(map);
321
322 set->data = NULL;
323}
324
325static void
326bitmap_ip_flush(struct ip_set *set)
327{
328 struct bitmap_ip *map = set->data;
329
330 memset(map->members, 0, map->memsize);
331}
332
333static int
334bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
335{
336 const struct bitmap_ip *map = set->data;
337 struct nlattr *nested;
338
339 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
340 if (!nested)
341 goto nla_put_failure;
342 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
343 nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
344 (map->netmask != 32 &&
345 nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask)) ||
346 nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
347 nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
348 htonl(sizeof(*map) + map->memsize)) ||
349 (with_timeout(map->timeout) &&
350 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
351 goto nla_put_failure;
352 ipset_nest_end(skb, nested);
353
354 return 0;
355nla_put_failure:
356 return -EMSGSIZE;
357}
358
359static bool 192static bool
360bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) 193bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
361{ 194{
@@ -365,70 +198,22 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
365 return x->first_ip == y->first_ip && 198 return x->first_ip == y->first_ip &&
366 x->last_ip == y->last_ip && 199 x->last_ip == y->last_ip &&
367 x->netmask == y->netmask && 200 x->netmask == y->netmask &&
368 x->timeout == y->timeout; 201 x->timeout == y->timeout &&
202 a->extensions == b->extensions;
369} 203}
370 204
371static const struct ip_set_type_variant bitmap_ip = { 205/* Plain variant */
372 .kadt = bitmap_ip_kadt,
373 .uadt = bitmap_ip_uadt,
374 .adt = {
375 [IPSET_ADD] = bitmap_ip_add,
376 [IPSET_DEL] = bitmap_ip_del,
377 [IPSET_TEST] = bitmap_ip_test,
378 },
379 .destroy = bitmap_ip_destroy,
380 .flush = bitmap_ip_flush,
381 .head = bitmap_ip_head,
382 .list = bitmap_ip_list,
383 .same_set = bitmap_ip_same_set,
384};
385 206
386static const struct ip_set_type_variant bitmap_tip = { 207struct bitmap_ip_elem {
387 .kadt = bitmap_ip_kadt,
388 .uadt = bitmap_ip_uadt,
389 .adt = {
390 [IPSET_ADD] = bitmap_ip_tadd,
391 [IPSET_DEL] = bitmap_ip_tdel,
392 [IPSET_TEST] = bitmap_ip_ttest,
393 },
394 .destroy = bitmap_ip_destroy,
395 .flush = bitmap_ip_flush,
396 .head = bitmap_ip_head,
397 .list = bitmap_ip_tlist,
398 .same_set = bitmap_ip_same_set,
399}; 208};
400 209
401static void 210/* Timeout variant */
402bitmap_ip_gc(unsigned long ul_set)
403{
404 struct ip_set *set = (struct ip_set *) ul_set;
405 struct bitmap_ip *map = set->data;
406 unsigned long *table = map->members;
407 u32 id;
408
409 /* We run parallel with other readers (test element)
410 * but adding/deleting new entries is locked out */
411 read_lock_bh(&set->lock);
412 for (id = 0; id < map->elements; id++)
413 if (ip_set_timeout_expired(table[id]))
414 table[id] = IPSET_ELEM_UNSET;
415 read_unlock_bh(&set->lock);
416
417 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
418 add_timer(&map->gc);
419}
420 211
421static void 212struct bitmap_ipt_elem {
422bitmap_ip_gc_init(struct ip_set *set) 213 unsigned long timeout;
423{ 214};
424 struct bitmap_ip *map = set->data;
425 215
426 init_timer(&map->gc); 216#include "ip_set_bitmap_gen.h"
427 map->gc.data = (unsigned long) set;
428 map->gc.function = bitmap_ip_gc;
429 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
430 add_timer(&map->gc);
431}
432 217
433/* Create bitmap:ip type of sets */ 218/* Create bitmap:ip type of sets */
434 219
@@ -440,6 +225,13 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
440 map->members = ip_set_alloc(map->memsize); 225 map->members = ip_set_alloc(map->memsize);
441 if (!map->members) 226 if (!map->members)
442 return false; 227 return false;
228 if (map->dsize) {
229 map->extensions = ip_set_alloc(map->dsize * elements);
230 if (!map->extensions) {
231 kfree(map->members);
232 return false;
233 }
234 }
443 map->first_ip = first_ip; 235 map->first_ip = first_ip;
444 map->last_ip = last_ip; 236 map->last_ip = last_ip;
445 map->elements = elements; 237 map->elements = elements;
@@ -526,8 +318,12 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
526 if (!map) 318 if (!map)
527 return -ENOMEM; 319 return -ENOMEM;
528 320
321 map->memsize = bitmap_bytes(0, elements - 1);
322 set->variant = &bitmap_ip;
529 if (tb[IPSET_ATTR_TIMEOUT]) { 323 if (tb[IPSET_ATTR_TIMEOUT]) {
530 map->memsize = elements * sizeof(unsigned long); 324 map->dsize = sizeof(struct bitmap_ipt_elem);
325 map->offset[IPSET_OFFSET_TIMEOUT] =
326 offsetof(struct bitmap_ipt_elem, timeout);
531 327
532 if (!init_map_ip(set, map, first_ip, last_ip, 328 if (!init_map_ip(set, map, first_ip, last_ip,
533 elements, hosts, netmask)) { 329 elements, hosts, netmask)) {
@@ -536,19 +332,16 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
536 } 332 }
537 333
538 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 334 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
539 set->variant = &bitmap_tip; 335 set->extensions |= IPSET_EXT_TIMEOUT;
540 336
541 bitmap_ip_gc_init(set); 337 bitmap_ip_gc_init(set, bitmap_ip_gc);
542 } else { 338 } else {
543 map->memsize = bitmap_bytes(0, elements - 1); 339 map->dsize = 0;
544
545 if (!init_map_ip(set, map, first_ip, last_ip, 340 if (!init_map_ip(set, map, first_ip, last_ip,
546 elements, hosts, netmask)) { 341 elements, hosts, netmask)) {
547 kfree(map); 342 kfree(map);
548 return -ENOMEM; 343 return -ENOMEM;
549 } 344 }
550
551 set->variant = &bitmap_ip;
552 } 345 }
553 return 0; 346 return 0;
554} 347}
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index d7df6ac2c6f1..960810dfcd81 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -1,7 +1,7 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de> 2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se> 3 * Martin Josefsson <gandalf@wlug.westbo.se>
4 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
@@ -23,7 +23,6 @@
23 23
24#include <linux/netfilter/ipset/pfxlen.h> 24#include <linux/netfilter/ipset/pfxlen.h>
25#include <linux/netfilter/ipset/ip_set.h> 25#include <linux/netfilter/ipset/ip_set.h>
26#include <linux/netfilter/ipset/ip_set_timeout.h>
27#include <linux/netfilter/ipset/ip_set_bitmap.h> 26#include <linux/netfilter/ipset/ip_set_bitmap.h>
28 27
29#define REVISION_MIN 0 28#define REVISION_MIN 0
@@ -34,333 +33,198 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
34IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX); 33IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX);
35MODULE_ALIAS("ip_set_bitmap:ip,mac"); 34MODULE_ALIAS("ip_set_bitmap:ip,mac");
36 35
36#define MTYPE bitmap_ipmac
37#define IP_SET_BITMAP_STORED_TIMEOUT
38
37enum { 39enum {
38 MAC_EMPTY, /* element is not set */
39 MAC_FILLED, /* element is set with MAC */
40 MAC_UNSET, /* element is set, without MAC */ 40 MAC_UNSET, /* element is set, without MAC */
41 MAC_FILLED, /* element is set with MAC */
41}; 42};
42 43
43/* Type structure */ 44/* Type structure */
44struct bitmap_ipmac { 45struct bitmap_ipmac {
45 void *members; /* the set members */ 46 void *members; /* the set members */
47 void *extensions; /* MAC + data extensions */
46 u32 first_ip; /* host byte order, included in range */ 48 u32 first_ip; /* host byte order, included in range */
47 u32 last_ip; /* host byte order, included in range */ 49 u32 last_ip; /* host byte order, included in range */
50 u32 elements; /* number of max elements in the set */
48 u32 timeout; /* timeout value */ 51 u32 timeout; /* timeout value */
49 struct timer_list gc; /* garbage collector */ 52 struct timer_list gc; /* garbage collector */
53 size_t memsize; /* members size */
50 size_t dsize; /* size of element */ 54 size_t dsize; /* size of element */
55 size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
51}; 56};
52 57
53/* ADT structure for generic function args */ 58/* ADT structure for generic function args */
54struct ipmac { 59struct bitmap_ipmac_adt_elem {
55 u32 id; /* id in array */ 60 u16 id;
56 unsigned char *ether; /* ethernet address */ 61 unsigned char *ether;
57}; 62};
58 63
59/* Member element without and with timeout */ 64struct bitmap_ipmac_elem {
60
61struct ipmac_elem {
62 unsigned char ether[ETH_ALEN]; 65 unsigned char ether[ETH_ALEN];
63 unsigned char match; 66 unsigned char filled;
64} __attribute__ ((aligned)); 67} __attribute__ ((aligned));
65 68
66struct ipmac_telem { 69static inline u32
67 unsigned char ether[ETH_ALEN]; 70ip_to_id(const struct bitmap_ipmac *m, u32 ip)
68 unsigned char match;
69 unsigned long timeout;
70} __attribute__ ((aligned));
71
72static inline void *
73bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
74{ 71{
75 return (void *)((char *)map->members + id * map->dsize); 72 return ip - m->first_ip;
76} 73}
77 74
78static inline bool 75static inline struct bitmap_ipmac_elem *
79bitmap_timeout(const struct bitmap_ipmac *map, u32 id) 76get_elem(void *extensions, u16 id, size_t dsize)
80{ 77{
81 const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id); 78 return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
82
83 return ip_set_timeout_test(elem->timeout);
84} 79}
85 80
86static inline bool 81/* Common functions */
87bitmap_expired(const struct bitmap_ipmac *map, u32 id)
88{
89 const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
90
91 return ip_set_timeout_expired(elem->timeout);
92}
93 82
94static inline int 83static inline int
95bitmap_ipmac_exist(const struct ipmac_telem *elem) 84bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
96{ 85 const struct bitmap_ipmac *map)
97 return elem->match == MAC_UNSET ||
98 (elem->match == MAC_FILLED &&
99 !ip_set_timeout_expired(elem->timeout));
100}
101
102/* Base variant */
103
104static int
105bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
106{
107 const struct bitmap_ipmac *map = set->data;
108 const struct ipmac *data = value;
109 const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
110
111 switch (elem->match) {
112 case MAC_UNSET:
113 /* Trigger kernel to fill out the ethernet address */
114 return -EAGAIN;
115 case MAC_FILLED:
116 return data->ether == NULL ||
117 ether_addr_equal(data->ether, elem->ether);
118 }
119 return 0;
120}
121
122static int
123bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
124{
125 struct bitmap_ipmac *map = set->data;
126 const struct ipmac *data = value;
127 struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
128
129 switch (elem->match) {
130 case MAC_UNSET:
131 if (!data->ether)
132 /* Already added without ethernet address */
133 return -IPSET_ERR_EXIST;
134 /* Fill the MAC address */
135 memcpy(elem->ether, data->ether, ETH_ALEN);
136 elem->match = MAC_FILLED;
137 break;
138 case MAC_FILLED:
139 return -IPSET_ERR_EXIST;
140 case MAC_EMPTY:
141 if (data->ether) {
142 memcpy(elem->ether, data->ether, ETH_ALEN);
143 elem->match = MAC_FILLED;
144 } else
145 elem->match = MAC_UNSET;
146 }
147
148 return 0;
149}
150
151static int
152bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
153{ 86{
154 struct bitmap_ipmac *map = set->data; 87 const struct bitmap_ipmac_elem *elem;
155 const struct ipmac *data = value;
156 struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
157
158 if (elem->match == MAC_EMPTY)
159 return -IPSET_ERR_EXIST;
160 88
161 elem->match = MAC_EMPTY; 89 if (!test_bit(e->id, map->members))
162 90 return 0;
163 return 0; 91 elem = get_elem(map->extensions, e->id, map->dsize);
92 if (elem->filled == MAC_FILLED)
93 return e->ether == NULL ||
94 ether_addr_equal(e->ether, elem->ether);
95 /* Trigger kernel to fill out the ethernet address */
96 return -EAGAIN;
164} 97}
165 98
166static int 99static inline int
167bitmap_ipmac_list(const struct ip_set *set, 100bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map)
168 struct sk_buff *skb, struct netlink_callback *cb)
169{ 101{
170 const struct bitmap_ipmac *map = set->data; 102 const struct bitmap_ipmac_elem *elem;
171 const struct ipmac_elem *elem;
172 struct nlattr *atd, *nested;
173 u32 id, first = cb->args[2];
174 u32 last = map->last_ip - map->first_ip;
175
176 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
177 if (!atd)
178 return -EMSGSIZE;
179 for (; cb->args[2] <= last; cb->args[2]++) {
180 id = cb->args[2];
181 elem = bitmap_ipmac_elem(map, id);
182 if (elem->match == MAC_EMPTY)
183 continue;
184 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
185 if (!nested) {
186 if (id == first) {
187 nla_nest_cancel(skb, atd);
188 return -EMSGSIZE;
189 } else
190 goto nla_put_failure;
191 }
192 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
193 htonl(map->first_ip + id)) ||
194 (elem->match == MAC_FILLED &&
195 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN,
196 elem->ether)))
197 goto nla_put_failure;
198 ipset_nest_end(skb, nested);
199 }
200 ipset_nest_end(skb, atd);
201 /* Set listing finished */
202 cb->args[2] = 0;
203
204 return 0;
205 103
206nla_put_failure: 104 if (!test_bit(id, map->members))
207 nla_nest_cancel(skb, nested); 105 return 0;
208 ipset_nest_end(skb, atd); 106 elem = get_elem(map->extensions, id, map->dsize);
209 if (unlikely(id == first)) { 107 /* Timer not started for the incomplete elements */
210 cb->args[2] = 0; 108 return elem->filled == MAC_FILLED;
211 return -EMSGSIZE;
212 }
213 return 0;
214} 109}
215 110
216/* Timeout variant */ 111static inline int
217 112bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
218static int
219bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
220{ 113{
221 const struct bitmap_ipmac *map = set->data; 114 return elem->filled == MAC_FILLED;
222 const struct ipmac *data = value;
223 const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
224
225 switch (elem->match) {
226 case MAC_UNSET:
227 /* Trigger kernel to fill out the ethernet address */
228 return -EAGAIN;
229 case MAC_FILLED:
230 return (data->ether == NULL ||
231 ether_addr_equal(data->ether, elem->ether)) &&
232 !bitmap_expired(map, data->id);
233 }
234 return 0;
235} 115}
236 116
237static int 117static inline int
238bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) 118bitmap_ipmac_add_timeout(unsigned long *timeout,
119 const struct bitmap_ipmac_adt_elem *e,
120 const struct ip_set_ext *ext,
121 struct bitmap_ipmac *map, int mode)
239{ 122{
240 struct bitmap_ipmac *map = set->data; 123 u32 t = ext->timeout;
241 const struct ipmac *data = value;
242 struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
243 bool flag_exist = flags & IPSET_FLAG_EXIST;
244 124
245 switch (elem->match) { 125 if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
246 case MAC_UNSET: 126 if (t == map->timeout)
247 if (!(data->ether || flag_exist))
248 /* Already added without ethernet address */
249 return -IPSET_ERR_EXIST;
250 /* Fill the MAC address and activate the timer */
251 memcpy(elem->ether, data->ether, ETH_ALEN);
252 elem->match = MAC_FILLED;
253 if (timeout == map->timeout)
254 /* Timeout was not specified, get stored one */ 127 /* Timeout was not specified, get stored one */
255 timeout = elem->timeout; 128 t = *timeout;
256 elem->timeout = ip_set_timeout_set(timeout); 129 ip_set_timeout_set(timeout, t);
257 break; 130 } else {
258 case MAC_FILLED:
259 if (!(bitmap_expired(map, data->id) || flag_exist))
260 return -IPSET_ERR_EXIST;
261 /* Fall through */
262 case MAC_EMPTY:
263 if (data->ether) {
264 memcpy(elem->ether, data->ether, ETH_ALEN);
265 elem->match = MAC_FILLED;
266 } else
267 elem->match = MAC_UNSET;
268 /* If MAC is unset yet, we store plain timeout value 131 /* If MAC is unset yet, we store plain timeout value
269 * because the timer is not activated yet 132 * because the timer is not activated yet
270 * and we can reuse it later when MAC is filled out, 133 * and we can reuse it later when MAC is filled out,
271 * possibly by the kernel */ 134 * possibly by the kernel */
272 elem->timeout = data->ether ? ip_set_timeout_set(timeout) 135 if (e->ether)
273 : timeout; 136 ip_set_timeout_set(timeout, t);
274 break; 137 else
138 *timeout = t;
275 } 139 }
276
277 return 0; 140 return 0;
278} 141}
279 142
280static int 143static inline int
281bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) 144bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
145 struct bitmap_ipmac *map, u32 flags)
282{ 146{
283 struct bitmap_ipmac *map = set->data; 147 struct bitmap_ipmac_elem *elem;
284 const struct ipmac *data = value; 148
285 struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); 149 elem = get_elem(map->extensions, e->id, map->dsize);
150 if (test_and_set_bit(e->id, map->members)) {
151 if (elem->filled == MAC_FILLED) {
152 if (e->ether && (flags & IPSET_FLAG_EXIST))
153 memcpy(elem->ether, e->ether, ETH_ALEN);
154 return IPSET_ADD_FAILED;
155 } else if (!e->ether)
156 /* Already added without ethernet address */
157 return IPSET_ADD_FAILED;
158 /* Fill the MAC address and trigger the timer activation */
159 memcpy(elem->ether, e->ether, ETH_ALEN);
160 elem->filled = MAC_FILLED;
161 return IPSET_ADD_START_STORED_TIMEOUT;
162 } else if (e->ether) {
163 /* We can store MAC too */
164 memcpy(elem->ether, e->ether, ETH_ALEN);
165 elem->filled = MAC_FILLED;
166 return 0;
167 } else {
168 elem->filled = MAC_UNSET;
169 /* MAC is not stored yet, don't start timer */
170 return IPSET_ADD_STORE_PLAIN_TIMEOUT;
171 }
172}
286 173
287 if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id)) 174static inline int
288 return -IPSET_ERR_EXIST; 175bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
176 struct bitmap_ipmac *map)
177{
178 return !test_and_clear_bit(e->id, map->members);
179}
289 180
290 elem->match = MAC_EMPTY; 181static inline unsigned long
182ip_set_timeout_stored(struct bitmap_ipmac *map, u32 id, unsigned long *timeout)
183{
184 const struct bitmap_ipmac_elem *elem =
185 get_elem(map->extensions, id, map->dsize);
291 186
292 return 0; 187 return elem->filled == MAC_FILLED ? ip_set_timeout_get(timeout) :
188 *timeout;
293} 189}
294 190
295static int 191static inline int
296bitmap_ipmac_tlist(const struct ip_set *set, 192bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
297 struct sk_buff *skb, struct netlink_callback *cb) 193 u32 id)
298{ 194{
299 const struct bitmap_ipmac *map = set->data; 195 const struct bitmap_ipmac_elem *elem =
300 const struct ipmac_telem *elem; 196 get_elem(map->extensions, id, map->dsize);
301 struct nlattr *atd, *nested;
302 u32 id, first = cb->args[2];
303 u32 timeout, last = map->last_ip - map->first_ip;
304
305 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
306 if (!atd)
307 return -EMSGSIZE;
308 for (; cb->args[2] <= last; cb->args[2]++) {
309 id = cb->args[2];
310 elem = bitmap_ipmac_elem(map, id);
311 if (!bitmap_ipmac_exist(elem))
312 continue;
313 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
314 if (!nested) {
315 if (id == first) {
316 nla_nest_cancel(skb, atd);
317 return -EMSGSIZE;
318 } else
319 goto nla_put_failure;
320 }
321 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
322 htonl(map->first_ip + id)) ||
323 (elem->match == MAC_FILLED &&
324 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN,
325 elem->ether)))
326 goto nla_put_failure;
327 timeout = elem->match == MAC_UNSET ? elem->timeout
328 : ip_set_timeout_get(elem->timeout);
329 if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout)))
330 goto nla_put_failure;
331 ipset_nest_end(skb, nested);
332 }
333 ipset_nest_end(skb, atd);
334 /* Set listing finished */
335 cb->args[2] = 0;
336 197
337 return 0; 198 return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
199 htonl(map->first_ip + id)) ||
200 (elem->filled == MAC_FILLED &&
201 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether));
202}
338 203
339nla_put_failure: 204static inline int
340 nla_nest_cancel(skb, nested); 205bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
341 ipset_nest_end(skb, atd); 206{
342 if (unlikely(id == first)) { 207 return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
343 cb->args[2] = 0; 208 nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
344 return -EMSGSIZE;
345 }
346 return 0;
347} 209}
348 210
349static int 211static int
350bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, 212bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
351 const struct xt_action_param *par, 213 const struct xt_action_param *par,
352 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 214 enum ipset_adt adt, struct ip_set_adt_opt *opt)
353{ 215{
354 struct bitmap_ipmac *map = set->data; 216 struct bitmap_ipmac *map = set->data;
355 ipset_adtfn adtfn = set->variant->adt[adt]; 217 ipset_adtfn adtfn = set->variant->adt[adt];
356 struct ipmac data; 218 struct bitmap_ipmac_adt_elem e = {};
219 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
220 u32 ip;
357 221
358 /* MAC can be src only */ 222 /* MAC can be src only */
359 if (!(opt->flags & IPSET_DIM_TWO_SRC)) 223 if (!(opt->flags & IPSET_DIM_TWO_SRC))
360 return 0; 224 return 0;
361 225
362 data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC)); 226 ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
363 if (data.id < map->first_ip || data.id > map->last_ip) 227 if (ip < map->first_ip || ip > map->last_ip)
364 return -IPSET_ERR_BITMAP_RANGE; 228 return -IPSET_ERR_BITMAP_RANGE;
365 229
366 /* Backward compatibility: we don't check the second flag */ 230 /* Backward compatibility: we don't check the second flag */
@@ -368,10 +232,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
368 (skb_mac_header(skb) + ETH_HLEN) > skb->data) 232 (skb_mac_header(skb) + ETH_HLEN) > skb->data)
369 return -EINVAL; 233 return -EINVAL;
370 234
371 data.id -= map->first_ip; 235 e.id = ip_to_id(map, ip);
372 data.ether = eth_hdr(skb)->h_source; 236 e.ether = eth_hdr(skb)->h_source;
373 237
374 return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags); 238 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
375} 239}
376 240
377static int 241static int
@@ -380,8 +244,9 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
380{ 244{
381 const struct bitmap_ipmac *map = set->data; 245 const struct bitmap_ipmac *map = set->data;
382 ipset_adtfn adtfn = set->variant->adt[adt]; 246 ipset_adtfn adtfn = set->variant->adt[adt];
383 struct ipmac data; 247 struct bitmap_ipmac_adt_elem e = {};
384 u32 timeout = map->timeout; 248 struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
249 u32 ip;
385 int ret = 0; 250 int ret = 0;
386 251
387 if (unlikely(!tb[IPSET_ATTR_IP] || 252 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -391,80 +256,25 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
391 if (tb[IPSET_ATTR_LINENO]) 256 if (tb[IPSET_ATTR_LINENO])
392 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 257 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
393 258
394 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id); 259 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
260 ip_set_get_extensions(set, tb, &ext);
395 if (ret) 261 if (ret)
396 return ret; 262 return ret;
397 263
398 if (data.id < map->first_ip || data.id > map->last_ip) 264 if (ip < map->first_ip || ip > map->last_ip)
399 return -IPSET_ERR_BITMAP_RANGE; 265 return -IPSET_ERR_BITMAP_RANGE;
400 266
267 e.id = ip_to_id(map, ip);
401 if (tb[IPSET_ATTR_ETHER]) 268 if (tb[IPSET_ATTR_ETHER])
402 data.ether = nla_data(tb[IPSET_ATTR_ETHER]); 269 e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
403 else 270 else
404 data.ether = NULL; 271 e.ether = NULL;
405
406 if (tb[IPSET_ATTR_TIMEOUT]) {
407 if (!with_timeout(map->timeout))
408 return -IPSET_ERR_TIMEOUT;
409 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
410 }
411 272
412 data.id -= map->first_ip; 273 ret = adtfn(set, &e, &ext, &ext, flags);
413
414 ret = adtfn(set, &data, timeout, flags);
415 274
416 return ip_set_eexist(ret, flags) ? 0 : ret; 275 return ip_set_eexist(ret, flags) ? 0 : ret;
417} 276}
418 277
419static void
420bitmap_ipmac_destroy(struct ip_set *set)
421{
422 struct bitmap_ipmac *map = set->data;
423
424 if (with_timeout(map->timeout))
425 del_timer_sync(&map->gc);
426
427 ip_set_free(map->members);
428 kfree(map);
429
430 set->data = NULL;
431}
432
433static void
434bitmap_ipmac_flush(struct ip_set *set)
435{
436 struct bitmap_ipmac *map = set->data;
437
438 memset(map->members, 0,
439 (map->last_ip - map->first_ip + 1) * map->dsize);
440}
441
442static int
443bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
444{
445 const struct bitmap_ipmac *map = set->data;
446 struct nlattr *nested;
447
448 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
449 if (!nested)
450 goto nla_put_failure;
451 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
452 nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
453 nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
454 nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
455 htonl(sizeof(*map) +
456 ((map->last_ip - map->first_ip + 1) *
457 map->dsize))) ||
458 (with_timeout(map->timeout) &&
459 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
460 goto nla_put_failure;
461 ipset_nest_end(skb, nested);
462
463 return 0;
464nla_put_failure:
465 return -EMSGSIZE;
466}
467
468static bool 278static bool
469bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b) 279bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
470{ 280{
@@ -473,85 +283,43 @@ bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
473 283
474 return x->first_ip == y->first_ip && 284 return x->first_ip == y->first_ip &&
475 x->last_ip == y->last_ip && 285 x->last_ip == y->last_ip &&
476 x->timeout == y->timeout; 286 x->timeout == y->timeout &&
287 a->extensions == b->extensions;
477} 288}
478 289
479static const struct ip_set_type_variant bitmap_ipmac = { 290/* Plain variant */
480 .kadt = bitmap_ipmac_kadt,
481 .uadt = bitmap_ipmac_uadt,
482 .adt = {
483 [IPSET_ADD] = bitmap_ipmac_add,
484 [IPSET_DEL] = bitmap_ipmac_del,
485 [IPSET_TEST] = bitmap_ipmac_test,
486 },
487 .destroy = bitmap_ipmac_destroy,
488 .flush = bitmap_ipmac_flush,
489 .head = bitmap_ipmac_head,
490 .list = bitmap_ipmac_list,
491 .same_set = bitmap_ipmac_same_set,
492};
493
494static const struct ip_set_type_variant bitmap_tipmac = {
495 .kadt = bitmap_ipmac_kadt,
496 .uadt = bitmap_ipmac_uadt,
497 .adt = {
498 [IPSET_ADD] = bitmap_ipmac_tadd,
499 [IPSET_DEL] = bitmap_ipmac_tdel,
500 [IPSET_TEST] = bitmap_ipmac_ttest,
501 },
502 .destroy = bitmap_ipmac_destroy,
503 .flush = bitmap_ipmac_flush,
504 .head = bitmap_ipmac_head,
505 .list = bitmap_ipmac_tlist,
506 .same_set = bitmap_ipmac_same_set,
507};
508
509static void
510bitmap_ipmac_gc(unsigned long ul_set)
511{
512 struct ip_set *set = (struct ip_set *) ul_set;
513 struct bitmap_ipmac *map = set->data;
514 struct ipmac_telem *elem;
515 u32 id, last = map->last_ip - map->first_ip;
516
517 /* We run parallel with other readers (test element)
518 * but adding/deleting new entries is locked out */
519 read_lock_bh(&set->lock);
520 for (id = 0; id <= last; id++) {
521 elem = bitmap_ipmac_elem(map, id);
522 if (elem->match == MAC_FILLED &&
523 ip_set_timeout_expired(elem->timeout))
524 elem->match = MAC_EMPTY;
525 }
526 read_unlock_bh(&set->lock);
527 291
528 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 292/* Timeout variant */
529 add_timer(&map->gc);
530}
531 293
532static void 294struct bitmap_ipmact_elem {
533bitmap_ipmac_gc_init(struct ip_set *set) 295 struct {
534{ 296 unsigned char ether[ETH_ALEN];
535 struct bitmap_ipmac *map = set->data; 297 unsigned char filled;
298 } __attribute__ ((aligned));
299 unsigned long timeout;
300};
536 301
537 init_timer(&map->gc); 302#include "ip_set_bitmap_gen.h"
538 map->gc.data = (unsigned long) set;
539 map->gc.function = bitmap_ipmac_gc;
540 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
541 add_timer(&map->gc);
542}
543 303
544/* Create bitmap:ip,mac type of sets */ 304/* Create bitmap:ip,mac type of sets */
545 305
546static bool 306static bool
547init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, 307init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
548 u32 first_ip, u32 last_ip) 308 u32 first_ip, u32 last_ip, u32 elements)
549{ 309{
550 map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize); 310 map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
551 if (!map->members) 311 if (!map->members)
552 return false; 312 return false;
313 if (map->dsize) {
314 map->extensions = ip_set_alloc(map->dsize * elements);
315 if (!map->extensions) {
316 kfree(map->members);
317 return false;
318 }
319 }
553 map->first_ip = first_ip; 320 map->first_ip = first_ip;
554 map->last_ip = last_ip; 321 map->last_ip = last_ip;
322 map->elements = elements;
555 map->timeout = IPSET_NO_TIMEOUT; 323 map->timeout = IPSET_NO_TIMEOUT;
556 324
557 set->data = map; 325 set->data = map;
@@ -605,28 +373,28 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
605 if (!map) 373 if (!map)
606 return -ENOMEM; 374 return -ENOMEM;
607 375
376 map->memsize = bitmap_bytes(0, elements - 1);
377 set->variant = &bitmap_ipmac;
608 if (tb[IPSET_ATTR_TIMEOUT]) { 378 if (tb[IPSET_ATTR_TIMEOUT]) {
609 map->dsize = sizeof(struct ipmac_telem); 379 map->dsize = sizeof(struct bitmap_ipmact_elem);
380 map->offset[IPSET_OFFSET_TIMEOUT] =
381 offsetof(struct bitmap_ipmact_elem, timeout);
610 382
611 if (!init_map_ipmac(set, map, first_ip, last_ip)) { 383 if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
612 kfree(map); 384 kfree(map);
613 return -ENOMEM; 385 return -ENOMEM;
614 } 386 }
615
616 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 387 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
617 388 set->extensions |= IPSET_EXT_TIMEOUT;
618 set->variant = &bitmap_tipmac; 389 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
619
620 bitmap_ipmac_gc_init(set);
621 } else { 390 } else {
622 map->dsize = sizeof(struct ipmac_elem); 391 map->dsize = sizeof(struct bitmap_ipmac_elem);
623 392
624 if (!init_map_ipmac(set, map, first_ip, last_ip)) { 393 if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
625 kfree(map); 394 kfree(map);
626 return -ENOMEM; 395 return -ENOMEM;
627 } 396 }
628 set->variant = &bitmap_ipmac; 397 set->variant = &bitmap_ipmac;
629
630 } 398 }
631 return 0; 399 return 0;
632} 400}
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index e6b2db76f4c3..27e2c573adcd 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as 4 * it under the terms of the GNU General Public License version 2 as
@@ -19,8 +19,6 @@
19#include <linux/netfilter/ipset/ip_set.h> 19#include <linux/netfilter/ipset/ip_set.h>
20#include <linux/netfilter/ipset/ip_set_bitmap.h> 20#include <linux/netfilter/ipset/ip_set_bitmap.h>
21#include <linux/netfilter/ipset/ip_set_getport.h> 21#include <linux/netfilter/ipset/ip_set_getport.h>
22#define IP_SET_BITMAP_TIMEOUT
23#include <linux/netfilter/ipset/ip_set_timeout.h>
24 22
25#define REVISION_MIN 0 23#define REVISION_MIN 0
26#define REVISION_MAX 0 24#define REVISION_MAX 0
@@ -30,194 +28,85 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX); 28IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX);
31MODULE_ALIAS("ip_set_bitmap:port"); 29MODULE_ALIAS("ip_set_bitmap:port");
32 30
31#define MTYPE bitmap_port
32
33/* Type structure */ 33/* Type structure */
34struct bitmap_port { 34struct bitmap_port {
35 void *members; /* the set members */ 35 void *members; /* the set members */
36 void *extensions; /* data extensions */
36 u16 first_port; /* host byte order, included in range */ 37 u16 first_port; /* host byte order, included in range */
37 u16 last_port; /* host byte order, included in range */ 38 u16 last_port; /* host byte order, included in range */
39 u32 elements; /* number of max elements in the set */
38 size_t memsize; /* members size */ 40 size_t memsize; /* members size */
41 size_t dsize; /* extensions struct size */
42 size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
39 u32 timeout; /* timeout parameter */ 43 u32 timeout; /* timeout parameter */
40 struct timer_list gc; /* garbage collection */ 44 struct timer_list gc; /* garbage collection */
41}; 45};
42 46
43/* Base variant */ 47/* ADT structure for generic function args */
48struct bitmap_port_adt_elem {
49 u16 id;
50};
44 51
45static int 52static inline u16
46bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags) 53port_to_id(const struct bitmap_port *m, u16 port)
47{ 54{
48 const struct bitmap_port *map = set->data; 55 return port - m->first_port;
49 u16 id = *(u16 *)value;
50
51 return !!test_bit(id, map->members);
52} 56}
53 57
54static int 58/* Common functions */
55bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
56{
57 struct bitmap_port *map = set->data;
58 u16 id = *(u16 *)value;
59
60 if (test_and_set_bit(id, map->members))
61 return -IPSET_ERR_EXIST;
62
63 return 0;
64}
65 59
66static int 60static inline int
67bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags) 61bitmap_port_do_test(const struct bitmap_port_adt_elem *e,
62 const struct bitmap_port *map)
68{ 63{
69 struct bitmap_port *map = set->data; 64 return !!test_bit(e->id, map->members);
70 u16 id = *(u16 *)value;
71
72 if (!test_and_clear_bit(id, map->members))
73 return -IPSET_ERR_EXIST;
74
75 return 0;
76} 65}
77 66
78static int 67static inline int
79bitmap_port_list(const struct ip_set *set, 68bitmap_port_gc_test(u16 id, const struct bitmap_port *map)
80 struct sk_buff *skb, struct netlink_callback *cb)
81{ 69{
82 const struct bitmap_port *map = set->data; 70 return !!test_bit(id, map->members);
83 struct nlattr *atd, *nested;
84 u16 id, first = cb->args[2];
85 u16 last = map->last_port - map->first_port;
86
87 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
88 if (!atd)
89 return -EMSGSIZE;
90 for (; cb->args[2] <= last; cb->args[2]++) {
91 id = cb->args[2];
92 if (!test_bit(id, map->members))
93 continue;
94 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
95 if (!nested) {
96 if (id == first) {
97 nla_nest_cancel(skb, atd);
98 return -EMSGSIZE;
99 } else
100 goto nla_put_failure;
101 }
102 if (nla_put_net16(skb, IPSET_ATTR_PORT,
103 htons(map->first_port + id)))
104 goto nla_put_failure;
105 ipset_nest_end(skb, nested);
106 }
107 ipset_nest_end(skb, atd);
108 /* Set listing finished */
109 cb->args[2] = 0;
110
111 return 0;
112
113nla_put_failure:
114 nla_nest_cancel(skb, nested);
115 ipset_nest_end(skb, atd);
116 if (unlikely(id == first)) {
117 cb->args[2] = 0;
118 return -EMSGSIZE;
119 }
120 return 0;
121} 71}
122 72
123/* Timeout variant */ 73static inline int
124 74bitmap_port_do_add(const struct bitmap_port_adt_elem *e,
125static int 75 struct bitmap_port *map, u32 flags)
126bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
127{ 76{
128 const struct bitmap_port *map = set->data; 77 return !!test_and_set_bit(e->id, map->members);
129 const unsigned long *members = map->members;
130 u16 id = *(u16 *)value;
131
132 return ip_set_timeout_test(members[id]);
133} 78}
134 79
135static int 80static inline int
136bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) 81bitmap_port_do_del(const struct bitmap_port_adt_elem *e,
82 struct bitmap_port *map)
137{ 83{
138 struct bitmap_port *map = set->data; 84 return !test_and_clear_bit(e->id, map->members);
139 unsigned long *members = map->members;
140 u16 id = *(u16 *)value;
141
142 if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
143 return -IPSET_ERR_EXIST;
144
145 members[id] = ip_set_timeout_set(timeout);
146
147 return 0;
148} 85}
149 86
150static int 87static inline int
151bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) 88bitmap_port_do_list(struct sk_buff *skb, const struct bitmap_port *map, u32 id)
152{ 89{
153 struct bitmap_port *map = set->data; 90 return nla_put_net16(skb, IPSET_ATTR_PORT,
154 unsigned long *members = map->members; 91 htons(map->first_port + id));
155 u16 id = *(u16 *)value;
156 int ret = -IPSET_ERR_EXIST;
157
158 if (ip_set_timeout_test(members[id]))
159 ret = 0;
160
161 members[id] = IPSET_ELEM_UNSET;
162 return ret;
163} 92}
164 93
165static int 94static inline int
166bitmap_port_tlist(const struct ip_set *set, 95bitmap_port_do_head(struct sk_buff *skb, const struct bitmap_port *map)
167 struct sk_buff *skb, struct netlink_callback *cb)
168{ 96{
169 const struct bitmap_port *map = set->data; 97 return nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
170 struct nlattr *adt, *nested; 98 nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
171 u16 id, first = cb->args[2];
172 u16 last = map->last_port - map->first_port;
173 const unsigned long *members = map->members;
174
175 adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
176 if (!adt)
177 return -EMSGSIZE;
178 for (; cb->args[2] <= last; cb->args[2]++) {
179 id = cb->args[2];
180 if (!ip_set_timeout_test(members[id]))
181 continue;
182 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
183 if (!nested) {
184 if (id == first) {
185 nla_nest_cancel(skb, adt);
186 return -EMSGSIZE;
187 } else
188 goto nla_put_failure;
189 }
190 if (nla_put_net16(skb, IPSET_ATTR_PORT,
191 htons(map->first_port + id)) ||
192 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
193 htonl(ip_set_timeout_get(members[id]))))
194 goto nla_put_failure;
195 ipset_nest_end(skb, nested);
196 }
197 ipset_nest_end(skb, adt);
198
199 /* Set listing finished */
200 cb->args[2] = 0;
201
202 return 0;
203
204nla_put_failure:
205 nla_nest_cancel(skb, nested);
206 ipset_nest_end(skb, adt);
207 if (unlikely(id == first)) {
208 cb->args[2] = 0;
209 return -EMSGSIZE;
210 }
211 return 0;
212} 99}
213 100
214static int 101static int
215bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, 102bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
216 const struct xt_action_param *par, 103 const struct xt_action_param *par,
217 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 104 enum ipset_adt adt, struct ip_set_adt_opt *opt)
218{ 105{
219 struct bitmap_port *map = set->data; 106 struct bitmap_port *map = set->data;
220 ipset_adtfn adtfn = set->variant->adt[adt]; 107 ipset_adtfn adtfn = set->variant->adt[adt];
108 struct bitmap_port_adt_elem e = {};
109 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
221 __be16 __port; 110 __be16 __port;
222 u16 port = 0; 111 u16 port = 0;
223 112
@@ -230,9 +119,9 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
230 if (port < map->first_port || port > map->last_port) 119 if (port < map->first_port || port > map->last_port)
231 return -IPSET_ERR_BITMAP_RANGE; 120 return -IPSET_ERR_BITMAP_RANGE;
232 121
233 port -= map->first_port; 122 e.id = port_to_id(map, port);
234 123
235 return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags); 124 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
236} 125}
237 126
238static int 127static int
@@ -241,9 +130,10 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
241{ 130{
242 struct bitmap_port *map = set->data; 131 struct bitmap_port *map = set->data;
243 ipset_adtfn adtfn = set->variant->adt[adt]; 132 ipset_adtfn adtfn = set->variant->adt[adt];
244 u32 timeout = map->timeout; 133 struct bitmap_port_adt_elem e = {};
134 struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
245 u32 port; /* wraparound */ 135 u32 port; /* wraparound */
246 u16 id, port_to; 136 u16 port_to;
247 int ret = 0; 137 int ret = 0;
248 138
249 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 139 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
@@ -257,16 +147,13 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
257 port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); 147 port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
258 if (port < map->first_port || port > map->last_port) 148 if (port < map->first_port || port > map->last_port)
259 return -IPSET_ERR_BITMAP_RANGE; 149 return -IPSET_ERR_BITMAP_RANGE;
260 150 ret = ip_set_get_extensions(set, tb, &ext);
261 if (tb[IPSET_ATTR_TIMEOUT]) { 151 if (ret)
262 if (!with_timeout(map->timeout)) 152 return ret;
263 return -IPSET_ERR_TIMEOUT;
264 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
265 }
266 153
267 if (adt == IPSET_TEST) { 154 if (adt == IPSET_TEST) {
268 id = port - map->first_port; 155 e.id = port_to_id(map, port);
269 return adtfn(set, &id, timeout, flags); 156 return adtfn(set, &e, &ext, &ext, flags);
270 } 157 }
271 158
272 if (tb[IPSET_ATTR_PORT_TO]) { 159 if (tb[IPSET_ATTR_PORT_TO]) {
@@ -283,8 +170,8 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
283 return -IPSET_ERR_BITMAP_RANGE; 170 return -IPSET_ERR_BITMAP_RANGE;
284 171
285 for (; port <= port_to; port++) { 172 for (; port <= port_to; port++) {
286 id = port - map->first_port; 173 e.id = port_to_id(map, port);
287 ret = adtfn(set, &id, timeout, flags); 174 ret = adtfn(set, &e, &ext, &ext, flags);
288 175
289 if (ret && !ip_set_eexist(ret, flags)) 176 if (ret && !ip_set_eexist(ret, flags))
290 return ret; 177 return ret;
@@ -294,52 +181,6 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
294 return ret; 181 return ret;
295} 182}
296 183
297static void
298bitmap_port_destroy(struct ip_set *set)
299{
300 struct bitmap_port *map = set->data;
301
302 if (with_timeout(map->timeout))
303 del_timer_sync(&map->gc);
304
305 ip_set_free(map->members);
306 kfree(map);
307
308 set->data = NULL;
309}
310
311static void
312bitmap_port_flush(struct ip_set *set)
313{
314 struct bitmap_port *map = set->data;
315
316 memset(map->members, 0, map->memsize);
317}
318
319static int
320bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
321{
322 const struct bitmap_port *map = set->data;
323 struct nlattr *nested;
324
325 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
326 if (!nested)
327 goto nla_put_failure;
328 if (nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
329 nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)) ||
330 nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
331 nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
332 htonl(sizeof(*map) + map->memsize)) ||
333 (with_timeout(map->timeout) &&
334 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
335 goto nla_put_failure;
336 ipset_nest_end(skb, nested);
337
338 return 0;
339nla_put_failure:
340 return -EMSGSIZE;
341}
342
343static bool 184static bool
344bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b) 185bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
345{ 186{
@@ -348,71 +189,21 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
348 189
349 return x->first_port == y->first_port && 190 return x->first_port == y->first_port &&
350 x->last_port == y->last_port && 191 x->last_port == y->last_port &&
351 x->timeout == y->timeout; 192 x->timeout == y->timeout &&
193 a->extensions == b->extensions;
352} 194}
353 195
354static const struct ip_set_type_variant bitmap_port = { 196/* Plain variant */
355 .kadt = bitmap_port_kadt,
356 .uadt = bitmap_port_uadt,
357 .adt = {
358 [IPSET_ADD] = bitmap_port_add,
359 [IPSET_DEL] = bitmap_port_del,
360 [IPSET_TEST] = bitmap_port_test,
361 },
362 .destroy = bitmap_port_destroy,
363 .flush = bitmap_port_flush,
364 .head = bitmap_port_head,
365 .list = bitmap_port_list,
366 .same_set = bitmap_port_same_set,
367};
368 197
369static const struct ip_set_type_variant bitmap_tport = { 198struct bitmap_port_elem {
370 .kadt = bitmap_port_kadt,
371 .uadt = bitmap_port_uadt,
372 .adt = {
373 [IPSET_ADD] = bitmap_port_tadd,
374 [IPSET_DEL] = bitmap_port_tdel,
375 [IPSET_TEST] = bitmap_port_ttest,
376 },
377 .destroy = bitmap_port_destroy,
378 .flush = bitmap_port_flush,
379 .head = bitmap_port_head,
380 .list = bitmap_port_tlist,
381 .same_set = bitmap_port_same_set,
382}; 199};
383 200
384static void 201/* Timeout variant */
385bitmap_port_gc(unsigned long ul_set) 202struct bitmap_portt_elem {
386{ 203 unsigned long timeout;
387 struct ip_set *set = (struct ip_set *) ul_set; 204};
388 struct bitmap_port *map = set->data;
389 unsigned long *table = map->members;
390 u32 id; /* wraparound */
391 u16 last = map->last_port - map->first_port;
392
393 /* We run parallel with other readers (test element)
394 * but adding/deleting new entries is locked out */
395 read_lock_bh(&set->lock);
396 for (id = 0; id <= last; id++)
397 if (ip_set_timeout_expired(table[id]))
398 table[id] = IPSET_ELEM_UNSET;
399 read_unlock_bh(&set->lock);
400
401 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
402 add_timer(&map->gc);
403}
404
405static void
406bitmap_port_gc_init(struct ip_set *set)
407{
408 struct bitmap_port *map = set->data;
409 205
410 init_timer(&map->gc); 206#include "ip_set_bitmap_gen.h"
411 map->gc.data = (unsigned long) set;
412 map->gc.function = bitmap_port_gc;
413 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
414 add_timer(&map->gc);
415}
416 207
417/* Create bitmap:ip type of sets */ 208/* Create bitmap:ip type of sets */
418 209
@@ -423,6 +214,13 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
423 map->members = ip_set_alloc(map->memsize); 214 map->members = ip_set_alloc(map->memsize);
424 if (!map->members) 215 if (!map->members)
425 return false; 216 return false;
217 if (map->dsize) {
218 map->extensions = ip_set_alloc(map->dsize * map->elements);
219 if (!map->extensions) {
220 kfree(map->members);
221 return false;
222 }
223 }
426 map->first_port = first_port; 224 map->first_port = first_port;
427 map->last_port = last_port; 225 map->last_port = last_port;
428 map->timeout = IPSET_NO_TIMEOUT; 226 map->timeout = IPSET_NO_TIMEOUT;
@@ -434,8 +232,7 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
434} 232}
435 233
436static int 234static int
437bitmap_port_create(struct ip_set *set, struct nlattr *tb[], 235bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
438 u32 flags)
439{ 236{
440 struct bitmap_port *map; 237 struct bitmap_port *map;
441 u16 first_port, last_port; 238 u16 first_port, last_port;
@@ -458,28 +255,28 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
458 if (!map) 255 if (!map)
459 return -ENOMEM; 256 return -ENOMEM;
460 257
258 map->elements = last_port - first_port + 1;
259 map->memsize = map->elements * sizeof(unsigned long);
260 set->variant = &bitmap_port;
461 if (tb[IPSET_ATTR_TIMEOUT]) { 261 if (tb[IPSET_ATTR_TIMEOUT]) {
462 map->memsize = (last_port - first_port + 1) 262 map->dsize = sizeof(struct bitmap_portt_elem);
463 * sizeof(unsigned long); 263 map->offset[IPSET_OFFSET_TIMEOUT] =
464 264 offsetof(struct bitmap_portt_elem, timeout);
465 if (!init_map_port(set, map, first_port, last_port)) { 265 if (!init_map_port(set, map, first_port, last_port)) {
466 kfree(map); 266 kfree(map);
467 return -ENOMEM; 267 return -ENOMEM;
468 } 268 }
469 269
470 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 270 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
471 set->variant = &bitmap_tport; 271 set->extensions |= IPSET_EXT_TIMEOUT;
472 272 bitmap_port_gc_init(set, bitmap_port_gc);
473 bitmap_port_gc_init(set);
474 } else { 273 } else {
475 map->memsize = bitmap_bytes(0, last_port - first_port); 274 map->dsize = 0;
476 pr_debug("memsize: %zu\n", map->memsize);
477 if (!init_map_port(set, map, first_port, last_port)) { 275 if (!init_map_port(set, map, first_port, last_port)) {
478 kfree(map); 276 kfree(map);
479 return -ENOMEM; 277 return -ENOMEM;
480 } 278 }
481 279
482 set->variant = &bitmap_port;
483 } 280 }
484 return 0; 281 return 0;
485} 282}