1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/module.h>
14#include <linux/ip.h>
15#include <linux/etherdevice.h>
16#include <linux/skbuff.h>
17#include <linux/errno.h>
18#include <linux/if_ether.h>
19#include <linux/netlink.h>
20#include <linux/jiffies.h>
21#include <linux/timer.h>
22#include <net/netlink.h>
23
24#include <linux/netfilter/ipset/pfxlen.h>
25#include <linux/netfilter/ipset/ip_set.h>
26#include <linux/netfilter/ipset/ip_set_bitmap.h>
27
28#define REVISION_MIN 0
29#define REVISION_MAX 1
30
31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
33IP_SET_MODULE_DESC("bitmap:ip,mac", REVISION_MIN, REVISION_MAX);
34MODULE_ALIAS("ip_set_bitmap:ip,mac");
35
36#define MTYPE bitmap_ipmac
37#define IP_SET_BITMAP_STORED_TIMEOUT
38
39enum {
40 MAC_UNSET,
41 MAC_FILLED,
42};
43
44
45struct bitmap_ipmac {
46 void *members;
47 void *extensions;
48 u32 first_ip;
49 u32 last_ip;
50 u32 elements;
51 u32 timeout;
52 struct timer_list gc;
53 size_t memsize;
54 size_t dsize;
55 size_t offset[IPSET_OFFSET_MAX];
56};
57
58
59struct bitmap_ipmac_adt_elem {
60 u16 id;
61 unsigned char *ether;
62};
63
64struct bitmap_ipmac_elem {
65 unsigned char ether[ETH_ALEN];
66 unsigned char filled;
67} __attribute__ ((aligned));
68
69static inline u32
70ip_to_id(const struct bitmap_ipmac *m, u32 ip)
71{
72 return ip - m->first_ip;
73}
74
75static inline struct bitmap_ipmac_elem *
76get_elem(void *extensions, u16 id, size_t dsize)
77{
78 return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
79}
80
81
82
83static inline int
84bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
85 const struct bitmap_ipmac *map)
86{
87 const struct bitmap_ipmac_elem *elem;
88
89 if (!test_bit(e->id, map->members))
90 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
96 return -EAGAIN;
97}
98
99static inline int
100bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map)
101{
102 const struct bitmap_ipmac_elem *elem;
103
104 if (!test_bit(id, map->members))
105 return 0;
106 elem = get_elem(map->extensions, id, map->dsize);
107
108 return elem->filled == MAC_FILLED;
109}
110
111static inline int
112bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
113{
114 return elem->filled == MAC_FILLED;
115}
116
117static inline int
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)
122{
123 u32 t = ext->timeout;
124
125 if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
126 if (t == map->timeout)
127
128 t = *timeout;
129 ip_set_timeout_set(timeout, t);
130 } else {
131
132
133
134
135 if (e->ether)
136 ip_set_timeout_set(timeout, t);
137 else
138 *timeout = t;
139 }
140 return 0;
141}
142
143static inline int
144bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
145 struct bitmap_ipmac *map, u32 flags)
146{
147 struct bitmap_ipmac_elem *elem;
148
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
157 return IPSET_ADD_FAILED;
158
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
164 memcpy(elem->ether, e->ether, ETH_ALEN);
165 elem->filled = MAC_FILLED;
166 return 0;
167 } else {
168 elem->filled = MAC_UNSET;
169
170 return IPSET_ADD_STORE_PLAIN_TIMEOUT;
171 }
172}
173
174static inline int
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}
180
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);
186
187 return elem->filled == MAC_FILLED ? ip_set_timeout_get(timeout) :
188 *timeout;
189}
190
191static inline int
192bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
193 u32 id)
194{
195 const struct bitmap_ipmac_elem *elem =
196 get_elem(map->extensions, id, map->dsize);
197
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}
203
204static inline int
205bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
206{
207 return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
208 nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
209}
210
211static int
212bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
213 const struct xt_action_param *par,
214 enum ipset_adt adt, struct ip_set_adt_opt *opt)
215{
216 struct bitmap_ipmac *map = set->data;
217 ipset_adtfn adtfn = set->variant->adt[adt];
218 struct bitmap_ipmac_adt_elem e = {};
219 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
220 u32 ip;
221
222
223 if (!(opt->flags & IPSET_DIM_TWO_SRC))
224 return 0;
225
226 ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
227 if (ip < map->first_ip || ip > map->last_ip)
228 return -IPSET_ERR_BITMAP_RANGE;
229
230
231 if (skb_mac_header(skb) < skb->head ||
232 (skb_mac_header(skb) + ETH_HLEN) > skb->data)
233 return -EINVAL;
234
235 e.id = ip_to_id(map, ip);
236 e.ether = eth_hdr(skb)->h_source;
237
238 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
239}
240
241static int
242bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
243 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
244{
245 const struct bitmap_ipmac *map = set->data;
246 ipset_adtfn adtfn = set->variant->adt[adt];
247 struct bitmap_ipmac_adt_elem e = {};
248 struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
249 u32 ip;
250 int ret = 0;
251
252 if (unlikely(!tb[IPSET_ATTR_IP] ||
253 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
254 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
255 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
256 return -IPSET_ERR_PROTOCOL;
257
258 if (tb[IPSET_ATTR_LINENO])
259 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
260
261 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
262 ip_set_get_extensions(set, tb, &ext);
263 if (ret)
264 return ret;
265
266 if (ip < map->first_ip || ip > map->last_ip)
267 return -IPSET_ERR_BITMAP_RANGE;
268
269 e.id = ip_to_id(map, ip);
270 if (tb[IPSET_ATTR_ETHER])
271 e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
272 else
273 e.ether = NULL;
274
275 ret = adtfn(set, &e, &ext, &ext, flags);
276
277 return ip_set_eexist(ret, flags) ? 0 : ret;
278}
279
280static bool
281bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
282{
283 const struct bitmap_ipmac *x = a->data;
284 const struct bitmap_ipmac *y = b->data;
285
286 return x->first_ip == y->first_ip &&
287 x->last_ip == y->last_ip &&
288 x->timeout == y->timeout &&
289 a->extensions == b->extensions;
290}
291
292
293
294
295
296struct bitmap_ipmact_elem {
297 struct {
298 unsigned char ether[ETH_ALEN];
299 unsigned char filled;
300 } __attribute__ ((aligned));
301 unsigned long timeout;
302};
303
304
305
306struct bitmap_ipmacc_elem {
307 struct {
308 unsigned char ether[ETH_ALEN];
309 unsigned char filled;
310 } __attribute__ ((aligned));
311 struct ip_set_counter counter;
312};
313
314
315
316struct bitmap_ipmacct_elem {
317 struct {
318 unsigned char ether[ETH_ALEN];
319 unsigned char filled;
320 } __attribute__ ((aligned));
321 unsigned long timeout;
322 struct ip_set_counter counter;
323};
324
325#include "ip_set_bitmap_gen.h"
326
327
328
329static bool
330init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
331 u32 first_ip, u32 last_ip, u32 elements)
332{
333 map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
334 if (!map->members)
335 return false;
336 if (map->dsize) {
337 map->extensions = ip_set_alloc(map->dsize * elements);
338 if (!map->extensions) {
339 kfree(map->members);
340 return false;
341 }
342 }
343 map->first_ip = first_ip;
344 map->last_ip = last_ip;
345 map->elements = elements;
346 map->timeout = IPSET_NO_TIMEOUT;
347
348 set->data = map;
349 set->family = NFPROTO_IPV4;
350
351 return true;
352}
353
354static int
355bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
356 u32 flags)
357{
358 u32 first_ip, last_ip, cadt_flags = 0;
359 u64 elements;
360 struct bitmap_ipmac *map;
361 int ret;
362
363 if (unlikely(!tb[IPSET_ATTR_IP] ||
364 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
365 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
366 return -IPSET_ERR_PROTOCOL;
367
368 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
369 if (ret)
370 return ret;
371
372 if (tb[IPSET_ATTR_IP_TO]) {
373 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
374 if (ret)
375 return ret;
376 if (first_ip > last_ip) {
377 u32 tmp = first_ip;
378
379 first_ip = last_ip;
380 last_ip = tmp;
381 }
382 } else if (tb[IPSET_ATTR_CIDR]) {
383 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
384
385 if (cidr >= 32)
386 return -IPSET_ERR_INVALID_CIDR;
387 ip_set_mask_from_to(first_ip, last_ip, cidr);
388 } else
389 return -IPSET_ERR_PROTOCOL;
390
391 elements = (u64)last_ip - first_ip + 1;
392
393 if (elements > IPSET_BITMAP_MAX_RANGE + 1)
394 return -IPSET_ERR_BITMAP_RANGE_SIZE;
395
396 map = kzalloc(sizeof(*map), GFP_KERNEL);
397 if (!map)
398 return -ENOMEM;
399
400 map->memsize = bitmap_bytes(0, elements - 1);
401 set->variant = &bitmap_ipmac;
402 if (tb[IPSET_ATTR_CADT_FLAGS])
403 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
404 if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
405 set->extensions |= IPSET_EXT_COUNTER;
406 if (tb[IPSET_ATTR_TIMEOUT]) {
407 map->dsize = sizeof(struct bitmap_ipmacct_elem);
408 map->offset[IPSET_OFFSET_TIMEOUT] =
409 offsetof(struct bitmap_ipmacct_elem, timeout);
410 map->offset[IPSET_OFFSET_COUNTER] =
411 offsetof(struct bitmap_ipmacct_elem, counter);
412
413 if (!init_map_ipmac(set, map, first_ip, last_ip,
414 elements)) {
415 kfree(map);
416 return -ENOMEM;
417 }
418 map->timeout = ip_set_timeout_uget(
419 tb[IPSET_ATTR_TIMEOUT]);
420 set->extensions |= IPSET_EXT_TIMEOUT;
421 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
422 } else {
423 map->dsize = sizeof(struct bitmap_ipmacc_elem);
424 map->offset[IPSET_OFFSET_COUNTER] =
425 offsetof(struct bitmap_ipmacc_elem, counter);
426
427 if (!init_map_ipmac(set, map, first_ip, last_ip,
428 elements)) {
429 kfree(map);
430 return -ENOMEM;
431 }
432 }
433 } else if (tb[IPSET_ATTR_TIMEOUT]) {
434 map->dsize = sizeof(struct bitmap_ipmact_elem);
435 map->offset[IPSET_OFFSET_TIMEOUT] =
436 offsetof(struct bitmap_ipmact_elem, timeout);
437
438 if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
439 kfree(map);
440 return -ENOMEM;
441 }
442 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
443 set->extensions |= IPSET_EXT_TIMEOUT;
444 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
445 } else {
446 map->dsize = sizeof(struct bitmap_ipmac_elem);
447
448 if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
449 kfree(map);
450 return -ENOMEM;
451 }
452 set->variant = &bitmap_ipmac;
453 }
454 return 0;
455}
456
457static struct ip_set_type bitmap_ipmac_type = {
458 .name = "bitmap:ip,mac",
459 .protocol = IPSET_PROTOCOL,
460 .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
461 .dimension = IPSET_DIM_TWO,
462 .family = NFPROTO_IPV4,
463 .revision_min = REVISION_MIN,
464 .revision_max = REVISION_MAX,
465 .create = bitmap_ipmac_create,
466 .create_policy = {
467 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
468 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
469 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
470 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
471 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
472 },
473 .adt_policy = {
474 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
475 [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
476 .len = ETH_ALEN },
477 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
478 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
479 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
480 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
481 },
482 .me = THIS_MODULE,
483};
484
485static int __init
486bitmap_ipmac_init(void)
487{
488 return ip_set_type_register(&bitmap_ipmac_type);
489}
490
491static void __exit
492bitmap_ipmac_fini(void)
493{
494 ip_set_type_unregister(&bitmap_ipmac_type);
495}
496
497module_init(bitmap_ipmac_init);
498module_exit(bitmap_ipmac_fini);
499