diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2013-04-27 08:37:01 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-29 14:08:55 -0400 |
commit | b0da3905bb1eb0969470f57b18c978f902475c78 (patch) | |
tree | 7d8b0e3a06377cd682dda2dcb01c0feaab58b99a /net | |
parent | 4d73de38c256623b324474098f7d2bb4e97f7cf0 (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.c | 351 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_bitmap_ipmac.c | 562 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_bitmap_port.c | 361 |
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>"); | |||
35 | IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX); | 33 | IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX); |
36 | MODULE_ALIAS("ip_set_bitmap:ip"); | 34 | MODULE_ALIAS("ip_set_bitmap:ip"); |
37 | 35 | ||
36 | #define MTYPE bitmap_ip | ||
37 | |||
38 | /* Type structure */ | 38 | /* Type structure */ |
39 | struct bitmap_ip { | 39 | struct 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 */ |
55 | struct bitmap_ip_adt_elem { | ||
56 | u16 id; | ||
57 | }; | ||
52 | 58 | ||
53 | static inline u32 | 59 | static inline u32 |
54 | ip_to_id(const struct bitmap_ip *m, u32 ip) | 60 | ip_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 | ||
59 | static int | 65 | /* Common functions */ |
60 | bitmap_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 | |||
68 | static int | ||
69 | bitmap_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 | ||
80 | static int | 67 | static inline int |
81 | bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags) | 68 | bitmap_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 | ||
92 | static int | 73 | static inline int |
93 | bitmap_ip_list(const struct ip_set *set, | 74 | bitmap_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 | |||
125 | nla_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 */ | 79 | static inline int |
136 | 80 | bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map, | |
137 | static int | 81 | u32 flags) |
138 | bitmap_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 | ||
147 | static int | 86 | static inline int |
148 | bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | 87 | bitmap_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 | ||
162 | static int | 92 | static inline int |
163 | bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) | 93 | bitmap_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 | ||
177 | static int | 99 | static inline int |
178 | bitmap_ip_tlist(const struct ip_set *set, | 100 | bitmap_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 | |||
215 | nla_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 | ||
225 | static int | 108 | static int |
226 | bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, | 109 | bitmap_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 | ||
243 | static int | 128 | static 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 | ||
311 | static void | ||
312 | bitmap_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 | |||
325 | static void | ||
326 | bitmap_ip_flush(struct ip_set *set) | ||
327 | { | ||
328 | struct bitmap_ip *map = set->data; | ||
329 | |||
330 | memset(map->members, 0, map->memsize); | ||
331 | } | ||
332 | |||
333 | static int | ||
334 | bitmap_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; | ||
355 | nla_put_failure: | ||
356 | return -EMSGSIZE; | ||
357 | } | ||
358 | |||
359 | static bool | 192 | static bool |
360 | bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) | 193 | bitmap_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 | ||
371 | static 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 | ||
386 | static const struct ip_set_type_variant bitmap_tip = { | 207 | struct 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 | ||
401 | static void | 210 | /* Timeout variant */ |
402 | bitmap_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 | ||
421 | static void | 212 | struct bitmap_ipt_elem { |
422 | bitmap_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>"); | |||
34 | IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX); | 33 | IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX); |
35 | MODULE_ALIAS("ip_set_bitmap:ip,mac"); | 34 | MODULE_ALIAS("ip_set_bitmap:ip,mac"); |
36 | 35 | ||
36 | #define MTYPE bitmap_ipmac | ||
37 | #define IP_SET_BITMAP_STORED_TIMEOUT | ||
38 | |||
37 | enum { | 39 | enum { |
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 */ |
44 | struct bitmap_ipmac { | 45 | struct 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 */ |
54 | struct ipmac { | 59 | struct 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 */ | 64 | struct bitmap_ipmac_elem { |
60 | |||
61 | struct 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 | ||
66 | struct ipmac_telem { | 69 | static inline u32 |
67 | unsigned char ether[ETH_ALEN]; | 70 | ip_to_id(const struct bitmap_ipmac *m, u32 ip) |
68 | unsigned char match; | ||
69 | unsigned long timeout; | ||
70 | } __attribute__ ((aligned)); | ||
71 | |||
72 | static inline void * | ||
73 | bitmap_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 | ||
78 | static inline bool | 75 | static inline struct bitmap_ipmac_elem * |
79 | bitmap_timeout(const struct bitmap_ipmac *map, u32 id) | 76 | get_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 | ||
86 | static inline bool | 81 | /* Common functions */ |
87 | bitmap_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 | ||
94 | static inline int | 83 | static inline int |
95 | bitmap_ipmac_exist(const struct ipmac_telem *elem) | 84 | bitmap_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 | |||
104 | static int | ||
105 | bitmap_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 | |||
122 | static int | ||
123 | bitmap_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 | |||
151 | static int | ||
152 | bitmap_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 | ||
166 | static int | 99 | static inline int |
167 | bitmap_ipmac_list(const struct ip_set *set, | 100 | bitmap_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 | ||
206 | nla_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 */ | 111 | static inline int |
217 | 112 | bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem) | |
218 | static int | ||
219 | bitmap_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 | ||
237 | static int | 117 | static inline int |
238 | bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | 118 | bitmap_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 | ||
280 | static int | 143 | static inline int |
281 | bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) | 144 | bitmap_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)) | 174 | static inline int |
288 | return -IPSET_ERR_EXIST; | 175 | bitmap_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; | 181 | static inline unsigned long |
182 | ip_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 | ||
295 | static int | 191 | static inline int |
296 | bitmap_ipmac_tlist(const struct ip_set *set, | 192 | bitmap_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 | ||
339 | nla_put_failure: | 204 | static inline int |
340 | nla_nest_cancel(skb, nested); | 205 | bitmap_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 | ||
349 | static int | 211 | static int |
350 | bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, | 212 | bitmap_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 | ||
377 | static int | 241 | static 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 | ||
419 | static void | ||
420 | bitmap_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 | |||
433 | static void | ||
434 | bitmap_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 | |||
442 | static int | ||
443 | bitmap_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; | ||
464 | nla_put_failure: | ||
465 | return -EMSGSIZE; | ||
466 | } | ||
467 | |||
468 | static bool | 278 | static bool |
469 | bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b) | 279 | bitmap_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 | ||
479 | static 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 | |||
494 | static 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 | |||
509 | static void | ||
510 | bitmap_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 | ||
532 | static void | 294 | struct bitmap_ipmact_elem { |
533 | bitmap_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 | ||
546 | static bool | 306 | static bool |
547 | init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, | 307 | init_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>"); | |||
30 | IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX); | 28 | IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX); |
31 | MODULE_ALIAS("ip_set_bitmap:port"); | 29 | MODULE_ALIAS("ip_set_bitmap:port"); |
32 | 30 | ||
31 | #define MTYPE bitmap_port | ||
32 | |||
33 | /* Type structure */ | 33 | /* Type structure */ |
34 | struct bitmap_port { | 34 | struct 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 */ |
48 | struct bitmap_port_adt_elem { | ||
49 | u16 id; | ||
50 | }; | ||
44 | 51 | ||
45 | static int | 52 | static inline u16 |
46 | bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags) | 53 | port_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 | ||
54 | static int | 58 | /* Common functions */ |
55 | bitmap_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 | ||
66 | static int | 60 | static inline int |
67 | bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags) | 61 | bitmap_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 | ||
78 | static int | 67 | static inline int |
79 | bitmap_port_list(const struct ip_set *set, | 68 | bitmap_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 | |||
113 | nla_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 */ | 73 | static inline int |
124 | 74 | bitmap_port_do_add(const struct bitmap_port_adt_elem *e, | |
125 | static int | 75 | struct bitmap_port *map, u32 flags) |
126 | bitmap_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 | ||
135 | static int | 80 | static inline int |
136 | bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) | 81 | bitmap_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 | ||
150 | static int | 87 | static inline int |
151 | bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) | 88 | bitmap_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 | ||
165 | static int | 94 | static inline int |
166 | bitmap_port_tlist(const struct ip_set *set, | 95 | bitmap_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 | |||
204 | nla_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 | ||
214 | static int | 101 | static int |
215 | bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, | 102 | bitmap_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 | ||
238 | static int | 127 | static 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 | ||
297 | static void | ||
298 | bitmap_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 | |||
311 | static void | ||
312 | bitmap_port_flush(struct ip_set *set) | ||
313 | { | ||
314 | struct bitmap_port *map = set->data; | ||
315 | |||
316 | memset(map->members, 0, map->memsize); | ||
317 | } | ||
318 | |||
319 | static int | ||
320 | bitmap_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; | ||
339 | nla_put_failure: | ||
340 | return -EMSGSIZE; | ||
341 | } | ||
342 | |||
343 | static bool | 184 | static bool |
344 | bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b) | 185 | bitmap_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 | ||
354 | static 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 | ||
369 | static const struct ip_set_type_variant bitmap_tport = { | 198 | struct 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 | ||
384 | static void | 201 | /* Timeout variant */ |
385 | bitmap_port_gc(unsigned long ul_set) | 202 | struct 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 | |||
405 | static void | ||
406 | bitmap_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 | ||
436 | static int | 234 | static int |
437 | bitmap_port_create(struct ip_set *set, struct nlattr *tb[], | 235 | bitmap_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 | } |