1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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
7 * published by the Free Software Foundation.
10 /* Kernel module implementing an IP set type: the single bitmap type */
12 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 #include <linux/errno.h>
16 #include <asm/uaccess.h>
17 #include <asm/bitops.h>
18 #include <linux/spinlock.h>
20 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
22 static inline ip_set_ip_t
23 ip_to_id(const struct ip_set_ipmap
*map
, ip_set_ip_t ip
)
25 return ((ip
& map
->netmask
) - map
->first_ip
)/map
->hosts
;
29 ipmap_test(const struct ip_set
*set
, ip_set_ip_t ip
)
31 const struct ip_set_ipmap
*map
= set
->data
;
33 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
36 DP("set: %s, ip:%u.%u.%u.%u", set
->name
, HIPQUAD(ip
));
37 return !!test_bit(ip_to_id(map
, ip
), map
->members
);
40 #define KADT_CONDITION
43 KADT(ipmap
, test
, ipaddr
)
46 ipmap_add(struct ip_set
*set
, ip_set_ip_t ip
)
48 struct ip_set_ipmap
*map
= set
->data
;
50 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
53 DP("set: %s, ip:%u.%u.%u.%u", set
->name
, HIPQUAD(ip
));
54 if (test_and_set_bit(ip_to_id(map
, ip
), map
->members
))
61 KADT(ipmap
, add
, ipaddr
)
64 ipmap_del(struct ip_set
*set
, ip_set_ip_t ip
)
66 struct ip_set_ipmap
*map
= set
->data
;
68 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
71 DP("set: %s, ip:%u.%u.%u.%u", set
->name
, HIPQUAD(ip
));
72 if (!test_and_clear_bit(ip_to_id(map
, ip
), map
->members
))
79 KADT(ipmap
, del
, ipaddr
)
82 __ipmap_create(const struct ip_set_req_ipmap_create
*req
,
83 struct ip_set_ipmap
*map
)
85 map
->netmask
= req
->netmask
;
87 if (req
->netmask
== 0xFFFFFFFF) {
89 map
->sizeid
= map
->last_ip
- map
->first_ip
+ 1;
91 unsigned int mask_bits
, netmask_bits
;
94 map
->first_ip
&= map
->netmask
; /* Should we better bark? */
96 mask
= range_to_mask(map
->first_ip
, map
->last_ip
, &mask_bits
);
97 netmask_bits
= mask_to_bits(map
->netmask
);
99 if ((!mask
&& (map
->first_ip
|| map
->last_ip
!= 0xFFFFFFFF))
100 || netmask_bits
<= mask_bits
)
103 DP("mask_bits %u, netmask_bits %u",
104 mask_bits
, netmask_bits
);
105 map
->hosts
= 2 << (32 - netmask_bits
- 1);
106 map
->sizeid
= 2 << (netmask_bits
- mask_bits
- 1);
108 if (map
->sizeid
> MAX_RANGE
+ 1) {
109 ip_set_printk("range too big, %d elements (max %d)",
110 map
->sizeid
, MAX_RANGE
+1);
113 DP("hosts %u, sizeid %u", map
->hosts
, map
->sizeid
);
114 return bitmap_bytes(0, map
->sizeid
- 1);
118 BITMAP_DESTROY(ipmap
)
122 __ipmap_list_header(const struct ip_set_ipmap
*map
,
123 struct ip_set_req_ipmap_create
*header
)
125 header
->netmask
= map
->netmask
;
128 BITMAP_LIST_HEADER(ipmap
)
129 BITMAP_LIST_MEMBERS_SIZE(ipmap
, ip_set_ip_t
, map
->sizeid
,
130 test_bit(i
, map
->members
))
133 ipmap_list_members(const struct ip_set
*set
, void *data
, char dont_align
)
135 const struct ip_set_ipmap
*map
= set
->data
;
140 memcpy(data
, map
->members
, map
->size
);
144 for (i
= 0; i
< map
->sizeid
; i
++)
145 if (test_bit(i
, map
->members
)) {
146 d
= data
+ n
* IPSET_ALIGN(sizeof(ip_set_ip_t
));
147 *d
= map
->first_ip
+ i
* map
->hosts
;
152 IP_SET_TYPE(ipmap
, IPSET_TYPE_IP
| IPSET_DATA_SINGLE
)
154 MODULE_LICENSE("GPL");
155 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
156 MODULE_DESCRIPTION("ipmap type of IP sets");
158 REGISTER_MODULE(ipmap
)