1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se>
4 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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
8 * published by the Free Software Foundation.
11 /* Kernel module implementing an IP set type: the bitmap:ip,mac type */
13 #include <linux/module.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>
24 #include <linux/netfilter/ipset/pfxlen.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>
29 MODULE_LICENSE("GPL");
30 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
31 MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
32 MODULE_ALIAS("ip_set_bitmap:ip,mac");
35 MAC_EMPTY
, /* element is not set */
36 MAC_FILLED
, /* element is set with MAC */
37 MAC_UNSET
, /* element is set, without MAC */
42 void *members
; /* the set members */
43 u32 first_ip
; /* host byte order, included in range */
44 u32 last_ip
; /* host byte order, included in range */
45 u32 timeout
; /* timeout value */
46 struct timer_list gc
; /* garbage collector */
47 size_t dsize
; /* size of element */
50 /* ADT structure for generic function args */
52 u32 id
; /* id in array */
53 unsigned char *ether
; /* ethernet address */
56 /* Member element without and with timeout */
59 unsigned char ether
[ETH_ALEN
];
61 } __attribute__ ((aligned
));
64 unsigned char ether
[ETH_ALEN
];
66 unsigned long timeout
;
67 } __attribute__ ((aligned
));
70 bitmap_ipmac_elem(const struct bitmap_ipmac
*map
, u32 id
)
72 return (void *)((char *)map
->members
+ id
* map
->dsize
);
76 bitmap_timeout(const struct bitmap_ipmac
*map
, u32 id
)
78 const struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, id
);
80 return ip_set_timeout_test(elem
->timeout
);
84 bitmap_expired(const struct bitmap_ipmac
*map
, u32 id
)
86 const struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, id
);
88 return ip_set_timeout_expired(elem
->timeout
);
92 bitmap_ipmac_exist(const struct ipmac_telem
*elem
)
94 return elem
->match
== MAC_UNSET
||
95 (elem
->match
== MAC_FILLED
&&
96 !ip_set_timeout_expired(elem
->timeout
));
102 bitmap_ipmac_test(struct ip_set
*set
, void *value
, u32 timeout
)
104 const struct bitmap_ipmac
*map
= set
->data
;
105 const struct ipmac
*data
= value
;
106 const struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
108 switch (elem
->match
) {
110 /* Trigger kernel to fill out the ethernet address */
113 return data
->ether
== NULL
||
114 compare_ether_addr(data
->ether
, elem
->ether
) == 0;
120 bitmap_ipmac_add(struct ip_set
*set
, void *value
, u32 timeout
)
122 struct bitmap_ipmac
*map
= set
->data
;
123 const struct ipmac
*data
= value
;
124 struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
126 switch (elem
->match
) {
129 /* Already added without ethernet address */
130 return -IPSET_ERR_EXIST
;
131 /* Fill the MAC address */
132 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
133 elem
->match
= MAC_FILLED
;
136 return -IPSET_ERR_EXIST
;
139 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
140 elem
->match
= MAC_FILLED
;
142 elem
->match
= MAC_UNSET
;
149 bitmap_ipmac_del(struct ip_set
*set
, void *value
, u32 timeout
)
151 struct bitmap_ipmac
*map
= set
->data
;
152 const struct ipmac
*data
= value
;
153 struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
155 if (elem
->match
== MAC_EMPTY
)
156 return -IPSET_ERR_EXIST
;
158 elem
->match
= MAC_EMPTY
;
164 bitmap_ipmac_list(const struct ip_set
*set
,
165 struct sk_buff
*skb
, struct netlink_callback
*cb
)
167 const struct bitmap_ipmac
*map
= set
->data
;
168 const struct ipmac_elem
*elem
;
169 struct nlattr
*atd
, *nested
;
170 u32 id
, first
= cb
->args
[2];
171 u32 last
= map
->last_ip
- map
->first_ip
;
173 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
176 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
178 elem
= bitmap_ipmac_elem(map
, id
);
179 if (elem
->match
== MAC_EMPTY
)
181 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
184 nla_nest_cancel(skb
, atd
);
187 goto nla_put_failure
;
189 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
,
190 htonl(map
->first_ip
+ id
));
191 if (elem
->match
== MAC_FILLED
)
192 NLA_PUT(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
,
194 ipset_nest_end(skb
, nested
);
196 ipset_nest_end(skb
, atd
);
197 /* Set listing finished */
203 nla_nest_cancel(skb
, nested
);
204 ipset_nest_end(skb
, atd
);
205 if (unlikely(id
== first
)) {
212 /* Timeout variant */
215 bitmap_ipmac_ttest(struct ip_set
*set
, void *value
, u32 timeout
)
217 const struct bitmap_ipmac
*map
= set
->data
;
218 const struct ipmac
*data
= value
;
219 const struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
221 switch (elem
->match
) {
223 /* Trigger kernel to fill out the ethernet address */
226 return (data
->ether
== NULL
||
227 compare_ether_addr(data
->ether
, elem
->ether
) == 0) &&
228 !bitmap_expired(map
, data
->id
);
234 bitmap_ipmac_tadd(struct ip_set
*set
, void *value
, u32 timeout
)
236 struct bitmap_ipmac
*map
= set
->data
;
237 const struct ipmac
*data
= value
;
238 struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
240 switch (elem
->match
) {
243 /* Already added without ethernet address */
244 return -IPSET_ERR_EXIST
;
245 /* Fill the MAC address and activate the timer */
246 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
247 elem
->match
= MAC_FILLED
;
248 if (timeout
== map
->timeout
)
249 /* Timeout was not specified, get stored one */
250 timeout
= elem
->timeout
;
251 elem
->timeout
= ip_set_timeout_set(timeout
);
254 if (!bitmap_expired(map
, data
->id
))
255 return -IPSET_ERR_EXIST
;
259 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
260 elem
->match
= MAC_FILLED
;
262 elem
->match
= MAC_UNSET
;
263 /* If MAC is unset yet, we store plain timeout value
264 * because the timer is not activated yet
265 * and we can reuse it later when MAC is filled out,
266 * possibly by the kernel */
267 elem
->timeout
= data
->ether
? ip_set_timeout_set(timeout
)
276 bitmap_ipmac_tdel(struct ip_set
*set
, void *value
, u32 timeout
)
278 struct bitmap_ipmac
*map
= set
->data
;
279 const struct ipmac
*data
= value
;
280 struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
282 if (elem
->match
== MAC_EMPTY
|| bitmap_expired(map
, data
->id
))
283 return -IPSET_ERR_EXIST
;
285 elem
->match
= MAC_EMPTY
;
291 bitmap_ipmac_tlist(const struct ip_set
*set
,
292 struct sk_buff
*skb
, struct netlink_callback
*cb
)
294 const struct bitmap_ipmac
*map
= set
->data
;
295 const struct ipmac_telem
*elem
;
296 struct nlattr
*atd
, *nested
;
297 u32 id
, first
= cb
->args
[2];
298 u32 timeout
, last
= map
->last_ip
- map
->first_ip
;
300 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
303 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
305 elem
= bitmap_ipmac_elem(map
, id
);
306 if (!bitmap_ipmac_exist(elem
))
308 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
311 nla_nest_cancel(skb
, atd
);
314 goto nla_put_failure
;
316 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
,
317 htonl(map
->first_ip
+ id
));
318 if (elem
->match
== MAC_FILLED
)
319 NLA_PUT(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
,
321 timeout
= elem
->match
== MAC_UNSET
? elem
->timeout
322 : ip_set_timeout_get(elem
->timeout
);
323 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
, htonl(timeout
));
324 ipset_nest_end(skb
, nested
);
326 ipset_nest_end(skb
, atd
);
327 /* Set listing finished */
333 nla_nest_cancel(skb
, nested
);
334 ipset_nest_end(skb
, atd
);
339 bitmap_ipmac_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
340 enum ipset_adt adt
, u8 pf
, u8 dim
, u8 flags
)
342 struct bitmap_ipmac
*map
= set
->data
;
343 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
346 data
.id
= ntohl(ip4addr(skb
, flags
& IPSET_DIM_ONE_SRC
));
347 if (data
.id
< map
->first_ip
|| data
.id
> map
->last_ip
)
348 return -IPSET_ERR_BITMAP_RANGE
;
350 /* Backward compatibility: we don't check the second flag */
351 if (skb_mac_header(skb
) < skb
->head
||
352 (skb_mac_header(skb
) + ETH_HLEN
) > skb
->data
)
355 data
.id
-= map
->first_ip
;
356 data
.ether
= eth_hdr(skb
)->h_source
;
358 return adtfn(set
, &data
, map
->timeout
);
362 bitmap_ipmac_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
363 enum ipset_adt adt
, u32
*lineno
, u32 flags
)
365 const struct bitmap_ipmac
*map
= set
->data
;
366 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
368 u32 timeout
= map
->timeout
;
371 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
372 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
373 return -IPSET_ERR_PROTOCOL
;
375 if (tb
[IPSET_ATTR_LINENO
])
376 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
378 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &data
.id
);
382 if (data
.id
< map
->first_ip
|| data
.id
> map
->last_ip
)
383 return -IPSET_ERR_BITMAP_RANGE
;
385 if (tb
[IPSET_ATTR_ETHER
])
386 data
.ether
= nla_data(tb
[IPSET_ATTR_ETHER
]);
390 if (tb
[IPSET_ATTR_TIMEOUT
]) {
391 if (!with_timeout(map
->timeout
))
392 return -IPSET_ERR_TIMEOUT
;
393 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
396 data
.id
-= map
->first_ip
;
398 ret
= adtfn(set
, &data
, timeout
);
400 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
404 bitmap_ipmac_destroy(struct ip_set
*set
)
406 struct bitmap_ipmac
*map
= set
->data
;
408 if (with_timeout(map
->timeout
))
409 del_timer_sync(&map
->gc
);
411 ip_set_free(map
->members
);
418 bitmap_ipmac_flush(struct ip_set
*set
)
420 struct bitmap_ipmac
*map
= set
->data
;
422 memset(map
->members
, 0,
423 (map
->last_ip
- map
->first_ip
+ 1) * map
->dsize
);
427 bitmap_ipmac_head(struct ip_set
*set
, struct sk_buff
*skb
)
429 const struct bitmap_ipmac
*map
= set
->data
;
430 struct nlattr
*nested
;
432 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
434 goto nla_put_failure
;
435 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
));
436 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
));
437 NLA_PUT_NET32(skb
, IPSET_ATTR_REFERENCES
, htonl(set
->ref
- 1));
438 NLA_PUT_NET32(skb
, IPSET_ATTR_MEMSIZE
,
440 + (map
->last_ip
- map
->first_ip
+ 1) * map
->dsize
));
441 if (with_timeout(map
->timeout
))
442 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
, htonl(map
->timeout
));
443 ipset_nest_end(skb
, nested
);
451 bitmap_ipmac_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
453 const struct bitmap_ipmac
*x
= a
->data
;
454 const struct bitmap_ipmac
*y
= b
->data
;
456 return x
->first_ip
== y
->first_ip
&&
457 x
->last_ip
== y
->last_ip
&&
458 x
->timeout
== y
->timeout
;
461 static const struct ip_set_type_variant bitmap_ipmac
= {
462 .kadt
= bitmap_ipmac_kadt
,
463 .uadt
= bitmap_ipmac_uadt
,
465 [IPSET_ADD
] = bitmap_ipmac_add
,
466 [IPSET_DEL
] = bitmap_ipmac_del
,
467 [IPSET_TEST
] = bitmap_ipmac_test
,
469 .destroy
= bitmap_ipmac_destroy
,
470 .flush
= bitmap_ipmac_flush
,
471 .head
= bitmap_ipmac_head
,
472 .list
= bitmap_ipmac_list
,
473 .same_set
= bitmap_ipmac_same_set
,
476 static const struct ip_set_type_variant bitmap_tipmac
= {
477 .kadt
= bitmap_ipmac_kadt
,
478 .uadt
= bitmap_ipmac_uadt
,
480 [IPSET_ADD
] = bitmap_ipmac_tadd
,
481 [IPSET_DEL
] = bitmap_ipmac_tdel
,
482 [IPSET_TEST
] = bitmap_ipmac_ttest
,
484 .destroy
= bitmap_ipmac_destroy
,
485 .flush
= bitmap_ipmac_flush
,
486 .head
= bitmap_ipmac_head
,
487 .list
= bitmap_ipmac_tlist
,
488 .same_set
= bitmap_ipmac_same_set
,
492 bitmap_ipmac_gc(unsigned long ul_set
)
494 struct ip_set
*set
= (struct ip_set
*) ul_set
;
495 struct bitmap_ipmac
*map
= set
->data
;
496 struct ipmac_telem
*elem
;
497 u32 id
, last
= map
->last_ip
- map
->first_ip
;
499 /* We run parallel with other readers (test element)
500 * but adding/deleting new entries is locked out */
501 read_lock_bh(&set
->lock
);
502 for (id
= 0; id
<= last
; id
++) {
503 elem
= bitmap_ipmac_elem(map
, id
);
504 if (elem
->match
== MAC_FILLED
&&
505 ip_set_timeout_expired(elem
->timeout
))
506 elem
->match
= MAC_EMPTY
;
508 read_unlock_bh(&set
->lock
);
510 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
515 bitmap_ipmac_gc_init(struct ip_set
*set
)
517 struct bitmap_ipmac
*map
= set
->data
;
519 init_timer(&map
->gc
);
520 map
->gc
.data
= (unsigned long) set
;
521 map
->gc
.function
= bitmap_ipmac_gc
;
522 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
526 /* Create bitmap:ip,mac type of sets */
529 init_map_ipmac(struct ip_set
*set
, struct bitmap_ipmac
*map
,
530 u32 first_ip
, u32 last_ip
)
532 map
->members
= ip_set_alloc((last_ip
- first_ip
+ 1) * map
->dsize
);
535 map
->first_ip
= first_ip
;
536 map
->last_ip
= last_ip
;
537 map
->timeout
= IPSET_NO_TIMEOUT
;
540 set
->family
= AF_INET
;
546 bitmap_ipmac_create(struct ip_set
*set
, struct nlattr
*tb
[],
549 u32 first_ip
, last_ip
, elements
;
550 struct bitmap_ipmac
*map
;
553 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
554 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
555 return -IPSET_ERR_PROTOCOL
;
557 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
561 if (tb
[IPSET_ATTR_IP_TO
]) {
562 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
565 if (first_ip
> last_ip
) {
571 } else if (tb
[IPSET_ATTR_CIDR
]) {
572 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
575 return -IPSET_ERR_INVALID_CIDR
;
576 last_ip
= first_ip
| ~ip_set_hostmask(cidr
);
578 return -IPSET_ERR_PROTOCOL
;
580 elements
= last_ip
- first_ip
+ 1;
582 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
583 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
585 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
589 if (tb
[IPSET_ATTR_TIMEOUT
]) {
590 map
->dsize
= sizeof(struct ipmac_telem
);
592 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
)) {
597 map
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
599 set
->variant
= &bitmap_tipmac
;
601 bitmap_ipmac_gc_init(set
);
603 map
->dsize
= sizeof(struct ipmac_elem
);
605 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
)) {
609 set
->variant
= &bitmap_ipmac
;
615 static struct ip_set_type bitmap_ipmac_type
= {
616 .name
= "bitmap:ip,mac",
617 .protocol
= IPSET_PROTOCOL
,
618 .features
= IPSET_TYPE_IP
| IPSET_TYPE_MAC
,
619 .dimension
= IPSET_DIM_TWO
,
622 .create
= bitmap_ipmac_create
,
624 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
625 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
626 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
627 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
630 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
631 [IPSET_ATTR_ETHER
] = { .type
= NLA_BINARY
, .len
= ETH_ALEN
},
632 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
633 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
639 bitmap_ipmac_init(void)
641 return ip_set_type_register(&bitmap_ipmac_type
);
645 bitmap_ipmac_fini(void)
647 ip_set_type_unregister(&bitmap_ipmac_type
);
650 module_init(bitmap_ipmac_init
);
651 module_exit(bitmap_ipmac_fini
);