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/uaccess.h>
19 #include <linux/bitops.h>
20 #include <linux/spinlock.h>
21 #include <linux/if_ether.h>
22 #include <linux/netlink.h>
23 #include <linux/jiffies.h>
24 #include <linux/timer.h>
25 #include <net/netlink.h>
27 #include <linux/netfilter/ipset/pfxlen.h>
28 #include <linux/netfilter/ipset/ip_set.h>
29 #include <linux/netfilter/ipset/ip_set_timeout.h>
30 #include <linux/netfilter/ipset/ip_set_bitmap.h>
32 MODULE_LICENSE("GPL");
33 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
34 MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
35 MODULE_ALIAS("ip_set_bitmap:ip,mac");
38 MAC_EMPTY
, /* element is not set */
39 MAC_FILLED
, /* element is set with MAC */
40 MAC_UNSET
, /* element is set, without MAC */
45 void *members
; /* the set members */
46 u32 first_ip
; /* host byte order, included in range */
47 u32 last_ip
; /* host byte order, included in range */
48 u32 timeout
; /* timeout value */
49 struct timer_list gc
; /* garbage collector */
50 size_t dsize
; /* size of element */
53 /* ADT structure for generic function args */
55 u32 id
; /* id in array */
56 unsigned char *ether
; /* ethernet address */
59 /* Member element without and with timeout */
62 unsigned char ether
[ETH_ALEN
];
64 } __attribute__ ((aligned
));
67 unsigned char ether
[ETH_ALEN
];
69 unsigned long timeout
;
70 } __attribute__ ((aligned
));
73 bitmap_ipmac_elem(const struct bitmap_ipmac
*map
, u32 id
)
75 return (void *)((char *)map
->members
+ id
* map
->dsize
);
79 bitmap_timeout(const struct bitmap_ipmac
*map
, u32 id
)
81 const struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, id
);
83 return ip_set_timeout_test(elem
->timeout
);
87 bitmap_expired(const struct bitmap_ipmac
*map
, u32 id
)
89 const struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, id
);
91 return ip_set_timeout_expired(elem
->timeout
);
95 bitmap_ipmac_exist(const struct ipmac_telem
*elem
)
97 return elem
->match
== MAC_UNSET
||
98 (elem
->match
== MAC_FILLED
&&
99 !ip_set_timeout_expired(elem
->timeout
));
105 bitmap_ipmac_test(struct ip_set
*set
, void *value
, u32 timeout
)
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
);
111 switch (elem
->match
) {
113 /* Trigger kernel to fill out the ethernet address */
116 return data
->ether
== NULL
||
117 compare_ether_addr(data
->ether
, elem
->ether
) == 0;
123 bitmap_ipmac_add(struct ip_set
*set
, void *value
, u32 timeout
)
125 struct bitmap_ipmac
*map
= set
->data
;
126 const struct ipmac
*data
= value
;
127 struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
129 switch (elem
->match
) {
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
;
139 return -IPSET_ERR_EXIST
;
142 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
143 elem
->match
= MAC_FILLED
;
145 elem
->match
= MAC_UNSET
;
152 bitmap_ipmac_del(struct ip_set
*set
, void *value
, u32 timeout
)
154 struct bitmap_ipmac
*map
= set
->data
;
155 const struct ipmac
*data
= value
;
156 struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
158 if (elem
->match
== MAC_EMPTY
)
159 return -IPSET_ERR_EXIST
;
161 elem
->match
= MAC_EMPTY
;
167 bitmap_ipmac_list(const struct ip_set
*set
,
168 struct sk_buff
*skb
, struct netlink_callback
*cb
)
170 const struct bitmap_ipmac
*map
= set
->data
;
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
;
176 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
179 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
181 elem
= bitmap_ipmac_elem(map
, id
);
182 if (elem
->match
== MAC_EMPTY
)
184 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
187 nla_nest_cancel(skb
, atd
);
190 goto nla_put_failure
;
192 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
,
193 htonl(map
->first_ip
+ id
));
194 if (elem
->match
== MAC_FILLED
)
195 NLA_PUT(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
,
197 ipset_nest_end(skb
, nested
);
199 ipset_nest_end(skb
, atd
);
200 /* Set listing finished */
206 nla_nest_cancel(skb
, nested
);
207 ipset_nest_end(skb
, atd
);
208 if (unlikely(id
== first
)) {
215 /* Timeout variant */
218 bitmap_ipmac_ttest(struct ip_set
*set
, void *value
, u32 timeout
)
220 const struct bitmap_ipmac
*map
= set
->data
;
221 const struct ipmac
*data
= value
;
222 const struct ipmac_elem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
224 switch (elem
->match
) {
226 /* Trigger kernel to fill out the ethernet address */
229 return (data
->ether
== NULL
||
230 compare_ether_addr(data
->ether
, elem
->ether
) == 0) &&
231 !bitmap_expired(map
, data
->id
);
237 bitmap_ipmac_tadd(struct ip_set
*set
, void *value
, u32 timeout
)
239 struct bitmap_ipmac
*map
= set
->data
;
240 const struct ipmac
*data
= value
;
241 struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
243 switch (elem
->match
) {
246 /* Already added without ethernet address */
247 return -IPSET_ERR_EXIST
;
248 /* Fill the MAC address and activate the timer */
249 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
250 elem
->match
= MAC_FILLED
;
251 if (timeout
== map
->timeout
)
252 /* Timeout was not specified, get stored one */
253 timeout
= elem
->timeout
;
254 elem
->timeout
= ip_set_timeout_set(timeout
);
257 if (!bitmap_expired(map
, data
->id
))
258 return -IPSET_ERR_EXIST
;
262 memcpy(elem
->ether
, data
->ether
, ETH_ALEN
);
263 elem
->match
= MAC_FILLED
;
265 elem
->match
= MAC_UNSET
;
266 /* If MAC is unset yet, we store plain timeout value
267 * because the timer is not activated yet
268 * and we can reuse it later when MAC is filled out,
269 * possibly by the kernel */
270 elem
->timeout
= data
->ether
? ip_set_timeout_set(timeout
)
279 bitmap_ipmac_tdel(struct ip_set
*set
, void *value
, u32 timeout
)
281 struct bitmap_ipmac
*map
= set
->data
;
282 const struct ipmac
*data
= value
;
283 struct ipmac_telem
*elem
= bitmap_ipmac_elem(map
, data
->id
);
285 if (elem
->match
== MAC_EMPTY
|| bitmap_expired(map
, data
->id
))
286 return -IPSET_ERR_EXIST
;
288 elem
->match
= MAC_EMPTY
;
294 bitmap_ipmac_tlist(const struct ip_set
*set
,
295 struct sk_buff
*skb
, struct netlink_callback
*cb
)
297 const struct bitmap_ipmac
*map
= set
->data
;
298 const struct ipmac_telem
*elem
;
299 struct nlattr
*atd
, *nested
;
300 u32 id
, first
= cb
->args
[2];
301 u32 timeout
, last
= map
->last_ip
- map
->first_ip
;
303 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
306 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
308 elem
= bitmap_ipmac_elem(map
, id
);
309 if (!bitmap_ipmac_exist(elem
))
311 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
314 nla_nest_cancel(skb
, atd
);
317 goto nla_put_failure
;
319 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
,
320 htonl(map
->first_ip
+ id
));
321 if (elem
->match
== MAC_FILLED
)
322 NLA_PUT(skb
, IPSET_ATTR_ETHER
, ETH_ALEN
,
324 timeout
= elem
->match
== MAC_UNSET
? elem
->timeout
325 : ip_set_timeout_get(elem
->timeout
);
326 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
, htonl(timeout
));
327 ipset_nest_end(skb
, nested
);
329 ipset_nest_end(skb
, atd
);
330 /* Set listing finished */
336 nla_nest_cancel(skb
, nested
);
337 ipset_nest_end(skb
, atd
);
342 bitmap_ipmac_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
343 enum ipset_adt adt
, u8 pf
, u8 dim
, u8 flags
)
345 struct bitmap_ipmac
*map
= set
->data
;
346 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
349 data
.id
= ntohl(ip4addr(skb
, flags
& IPSET_DIM_ONE_SRC
));
350 if (data
.id
< map
->first_ip
|| data
.id
> map
->last_ip
)
351 return -IPSET_ERR_BITMAP_RANGE
;
353 /* Backward compatibility: we don't check the second flag */
354 if (skb_mac_header(skb
) < skb
->head
||
355 (skb_mac_header(skb
) + ETH_HLEN
) > skb
->data
)
358 data
.id
-= map
->first_ip
;
359 data
.ether
= eth_hdr(skb
)->h_source
;
361 return adtfn(set
, &data
, map
->timeout
);
365 bitmap_ipmac_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
366 enum ipset_adt adt
, u32
*lineno
, u32 flags
)
368 const struct bitmap_ipmac
*map
= set
->data
;
369 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
371 u32 timeout
= map
->timeout
;
374 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
375 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
376 return -IPSET_ERR_PROTOCOL
;
378 if (tb
[IPSET_ATTR_LINENO
])
379 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
381 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &data
.id
);
385 if (data
.id
< map
->first_ip
|| data
.id
> map
->last_ip
)
386 return -IPSET_ERR_BITMAP_RANGE
;
388 if (tb
[IPSET_ATTR_ETHER
])
389 data
.ether
= nla_data(tb
[IPSET_ATTR_ETHER
]);
393 if (tb
[IPSET_ATTR_TIMEOUT
]) {
394 if (!with_timeout(map
->timeout
))
395 return -IPSET_ERR_TIMEOUT
;
396 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
399 data
.id
-= map
->first_ip
;
401 ret
= adtfn(set
, &data
, timeout
);
403 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
407 bitmap_ipmac_destroy(struct ip_set
*set
)
409 struct bitmap_ipmac
*map
= set
->data
;
411 if (with_timeout(map
->timeout
))
412 del_timer_sync(&map
->gc
);
414 ip_set_free(map
->members
);
421 bitmap_ipmac_flush(struct ip_set
*set
)
423 struct bitmap_ipmac
*map
= set
->data
;
425 memset(map
->members
, 0,
426 (map
->last_ip
- map
->first_ip
+ 1) * map
->dsize
);
430 bitmap_ipmac_head(struct ip_set
*set
, struct sk_buff
*skb
)
432 const struct bitmap_ipmac
*map
= set
->data
;
433 struct nlattr
*nested
;
435 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
437 goto nla_put_failure
;
438 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
));
439 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
));
440 NLA_PUT_NET32(skb
, IPSET_ATTR_REFERENCES
,
441 htonl(atomic_read(&set
->ref
) - 1));
442 NLA_PUT_NET32(skb
, IPSET_ATTR_MEMSIZE
,
444 + (map
->last_ip
- map
->first_ip
+ 1) * map
->dsize
));
445 if (with_timeout(map
->timeout
))
446 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
, htonl(map
->timeout
));
447 ipset_nest_end(skb
, nested
);
455 bitmap_ipmac_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
457 const struct bitmap_ipmac
*x
= a
->data
;
458 const struct bitmap_ipmac
*y
= b
->data
;
460 return x
->first_ip
== y
->first_ip
&&
461 x
->last_ip
== y
->last_ip
&&
462 x
->timeout
== y
->timeout
;
465 static const struct ip_set_type_variant bitmap_ipmac
= {
466 .kadt
= bitmap_ipmac_kadt
,
467 .uadt
= bitmap_ipmac_uadt
,
469 [IPSET_ADD
] = bitmap_ipmac_add
,
470 [IPSET_DEL
] = bitmap_ipmac_del
,
471 [IPSET_TEST
] = bitmap_ipmac_test
,
473 .destroy
= bitmap_ipmac_destroy
,
474 .flush
= bitmap_ipmac_flush
,
475 .head
= bitmap_ipmac_head
,
476 .list
= bitmap_ipmac_list
,
477 .same_set
= bitmap_ipmac_same_set
,
480 static const struct ip_set_type_variant bitmap_tipmac
= {
481 .kadt
= bitmap_ipmac_kadt
,
482 .uadt
= bitmap_ipmac_uadt
,
484 [IPSET_ADD
] = bitmap_ipmac_tadd
,
485 [IPSET_DEL
] = bitmap_ipmac_tdel
,
486 [IPSET_TEST
] = bitmap_ipmac_ttest
,
488 .destroy
= bitmap_ipmac_destroy
,
489 .flush
= bitmap_ipmac_flush
,
490 .head
= bitmap_ipmac_head
,
491 .list
= bitmap_ipmac_tlist
,
492 .same_set
= bitmap_ipmac_same_set
,
496 bitmap_ipmac_gc(unsigned long ul_set
)
498 struct ip_set
*set
= (struct ip_set
*) ul_set
;
499 struct bitmap_ipmac
*map
= set
->data
;
500 struct ipmac_telem
*elem
;
501 u32 id
, last
= map
->last_ip
- map
->first_ip
;
503 /* We run parallel with other readers (test element)
504 * but adding/deleting new entries is locked out */
505 read_lock_bh(&set
->lock
);
506 for (id
= 0; id
<= last
; id
++) {
507 elem
= bitmap_ipmac_elem(map
, id
);
508 if (elem
->match
== MAC_FILLED
&&
509 ip_set_timeout_expired(elem
->timeout
))
510 elem
->match
= MAC_EMPTY
;
512 read_unlock_bh(&set
->lock
);
514 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
519 bitmap_ipmac_gc_init(struct ip_set
*set
)
521 struct bitmap_ipmac
*map
= set
->data
;
523 init_timer(&map
->gc
);
524 map
->gc
.data
= (unsigned long) set
;
525 map
->gc
.function
= bitmap_ipmac_gc
;
526 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
530 /* Create bitmap:ip,mac type of sets */
533 init_map_ipmac(struct ip_set
*set
, struct bitmap_ipmac
*map
,
534 u32 first_ip
, u32 last_ip
)
536 map
->members
= ip_set_alloc((last_ip
- first_ip
+ 1) * map
->dsize
);
539 map
->first_ip
= first_ip
;
540 map
->last_ip
= last_ip
;
541 map
->timeout
= IPSET_NO_TIMEOUT
;
544 set
->family
= AF_INET
;
550 bitmap_ipmac_create(struct ip_set
*set
, struct nlattr
*tb
[],
553 u32 first_ip
, last_ip
, elements
;
554 struct bitmap_ipmac
*map
;
557 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
558 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
559 return -IPSET_ERR_PROTOCOL
;
561 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
565 if (tb
[IPSET_ATTR_IP_TO
]) {
566 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
569 if (first_ip
> last_ip
) {
575 } else if (tb
[IPSET_ATTR_CIDR
]) {
576 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
579 return -IPSET_ERR_INVALID_CIDR
;
580 last_ip
= first_ip
| ~ip_set_hostmask(cidr
);
582 return -IPSET_ERR_PROTOCOL
;
584 elements
= last_ip
- first_ip
+ 1;
586 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
587 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
589 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
593 if (tb
[IPSET_ATTR_TIMEOUT
]) {
594 map
->dsize
= sizeof(struct ipmac_telem
);
596 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
)) {
601 map
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
603 set
->variant
= &bitmap_tipmac
;
605 bitmap_ipmac_gc_init(set
);
607 map
->dsize
= sizeof(struct ipmac_elem
);
609 if (!init_map_ipmac(set
, map
, first_ip
, last_ip
)) {
613 set
->variant
= &bitmap_ipmac
;
619 static struct ip_set_type bitmap_ipmac_type
= {
620 .name
= "bitmap:ip,mac",
621 .protocol
= IPSET_PROTOCOL
,
622 .features
= IPSET_TYPE_IP
| IPSET_TYPE_MAC
,
623 .dimension
= IPSET_DIM_TWO
,
626 .create
= bitmap_ipmac_create
,
628 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
629 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
630 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
631 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
634 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
635 [IPSET_ATTR_ETHER
] = { .type
= NLA_BINARY
, .len
= ETH_ALEN
},
636 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
637 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
643 bitmap_ipmac_init(void)
645 return ip_set_type_register(&bitmap_ipmac_type
);
649 bitmap_ipmac_fini(void)
651 ip_set_type_unregister(&bitmap_ipmac_type
);
654 module_init(bitmap_ipmac_init
);
655 module_exit(bitmap_ipmac_fini
);