1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2013 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 bitmap:ip type */
12 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 #include <linux/errno.h>
16 #include <linux/bitops.h>
17 #include <linux/spinlock.h>
18 #include <linux/netlink.h>
19 #include <linux/jiffies.h>
20 #include <linux/timer.h>
21 #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_bitmap.h>
28 #define REVISION_MIN 0
29 #define REVISION_MAX 1 /* Counter support added */
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
33 IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN
, REVISION_MAX
);
34 MODULE_ALIAS("ip_set_bitmap:ip");
36 #define MTYPE bitmap_ip
40 void *members
; /* the set members */
41 void *extensions
; /* data extensions */
42 u32 first_ip
; /* host byte order, included in range */
43 u32 last_ip
; /* host byte order, included in range */
44 u32 elements
; /* number of max elements in the set */
45 u32 hosts
; /* number of hosts in a subnet */
46 size_t memsize
; /* members size */
47 size_t dsize
; /* extensions struct size */
48 size_t offset
[IPSET_OFFSET_MAX
]; /* Offsets to extensions */
49 u8 netmask
; /* subnet netmask */
50 u32 timeout
; /* timeout parameter */
51 struct timer_list gc
; /* garbage collection */
54 /* ADT structure for generic function args */
55 struct bitmap_ip_adt_elem
{
60 ip_to_id(const struct bitmap_ip
*m
, u32 ip
)
62 return ((ip
& ip_set_hostmask(m
->netmask
)) - m
->first_ip
)/m
->hosts
;
65 /* Common functions */
68 bitmap_ip_do_test(const struct bitmap_ip_adt_elem
*e
, struct bitmap_ip
*map
)
70 return !!test_bit(e
->id
, map
->members
);
74 bitmap_ip_gc_test(u16 id
, const struct bitmap_ip
*map
)
76 return !!test_bit(id
, map
->members
);
80 bitmap_ip_do_add(const struct bitmap_ip_adt_elem
*e
, struct bitmap_ip
*map
,
83 return !!test_and_set_bit(e
->id
, map
->members
);
87 bitmap_ip_do_del(const struct bitmap_ip_adt_elem
*e
, struct bitmap_ip
*map
)
89 return !test_and_clear_bit(e
->id
, map
->members
);
93 bitmap_ip_do_list(struct sk_buff
*skb
, const struct bitmap_ip
*map
, u32 id
)
95 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
,
96 htonl(map
->first_ip
+ id
* map
->hosts
));
100 bitmap_ip_do_head(struct sk_buff
*skb
, const struct bitmap_ip
*map
)
102 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
)) ||
103 nla_put_ipaddr4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
)) ||
104 (map
->netmask
!= 32 &&
105 nla_put_u8(skb
, IPSET_ATTR_NETMASK
, map
->netmask
));
109 bitmap_ip_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
110 const struct xt_action_param
*par
,
111 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
113 struct bitmap_ip
*map
= set
->data
;
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
);
119 ip
= ntohl(ip4addr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
));
120 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
121 return -IPSET_ERR_BITMAP_RANGE
;
123 e
.id
= ip_to_id(map
, ip
);
125 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
129 bitmap_ip_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
130 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
132 struct bitmap_ip
*map
= set
->data
;
133 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
135 struct bitmap_ip_adt_elem e
= { };
136 struct ip_set_ext ext
= IP_SET_INIT_UEXT(map
);
139 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
140 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
141 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PACKETS
) ||
142 !ip_set_optattr_netorder(tb
, IPSET_ATTR_BYTES
)))
143 return -IPSET_ERR_PROTOCOL
;
145 if (tb
[IPSET_ATTR_LINENO
])
146 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
148 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
) ||
149 ip_set_get_extensions(set
, tb
, &ext
);
153 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
154 return -IPSET_ERR_BITMAP_RANGE
;
156 if (adt
== IPSET_TEST
) {
157 e
.id
= ip_to_id(map
, ip
);
158 return adtfn(set
, &e
, &ext
, &ext
, flags
);
161 if (tb
[IPSET_ATTR_IP_TO
]) {
162 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &ip_to
);
167 if (ip
< map
->first_ip
)
168 return -IPSET_ERR_BITMAP_RANGE
;
170 } else if (tb
[IPSET_ATTR_CIDR
]) {
171 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
173 if (!cidr
|| cidr
> 32)
174 return -IPSET_ERR_INVALID_CIDR
;
175 ip_set_mask_from_to(ip
, ip_to
, cidr
);
179 if (ip_to
> map
->last_ip
)
180 return -IPSET_ERR_BITMAP_RANGE
;
182 for (; !before(ip_to
, ip
); ip
+= map
->hosts
) {
183 e
.id
= ip_to_id(map
, ip
);
184 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
186 if (ret
&& !ip_set_eexist(ret
, flags
))
195 bitmap_ip_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
197 const struct bitmap_ip
*x
= a
->data
;
198 const struct bitmap_ip
*y
= b
->data
;
200 return x
->first_ip
== y
->first_ip
&&
201 x
->last_ip
== y
->last_ip
&&
202 x
->netmask
== y
->netmask
&&
203 x
->timeout
== y
->timeout
&&
204 a
->extensions
== b
->extensions
;
209 struct bitmap_ip_elem
{
212 /* Timeout variant */
214 struct bitmap_ipt_elem
{
215 unsigned long timeout
;
218 /* Plain variant with counter */
220 struct bitmap_ipc_elem
{
221 struct ip_set_counter counter
;
224 /* Timeout variant with counter */
226 struct bitmap_ipct_elem
{
227 unsigned long timeout
;
228 struct ip_set_counter counter
;
231 #include "ip_set_bitmap_gen.h"
233 /* Create bitmap:ip type of sets */
236 init_map_ip(struct ip_set
*set
, struct bitmap_ip
*map
,
237 u32 first_ip
, u32 last_ip
,
238 u32 elements
, u32 hosts
, u8 netmask
)
240 map
->members
= ip_set_alloc(map
->memsize
);
244 map
->extensions
= ip_set_alloc(map
->dsize
* elements
);
245 if (!map
->extensions
) {
250 map
->first_ip
= first_ip
;
251 map
->last_ip
= last_ip
;
252 map
->elements
= elements
;
254 map
->netmask
= netmask
;
255 map
->timeout
= IPSET_NO_TIMEOUT
;
258 set
->family
= NFPROTO_IPV4
;
264 bitmap_ip_create(struct ip_set
*set
, struct nlattr
*tb
[], u32 flags
)
266 struct bitmap_ip
*map
;
267 u32 first_ip
, last_ip
, hosts
, cadt_flags
= 0;
272 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
273 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
274 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
275 return -IPSET_ERR_PROTOCOL
;
277 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
281 if (tb
[IPSET_ATTR_IP_TO
]) {
282 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
285 if (first_ip
> last_ip
) {
291 } else if (tb
[IPSET_ATTR_CIDR
]) {
292 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
295 return -IPSET_ERR_INVALID_CIDR
;
296 ip_set_mask_from_to(first_ip
, last_ip
, cidr
);
298 return -IPSET_ERR_PROTOCOL
;
300 if (tb
[IPSET_ATTR_NETMASK
]) {
301 netmask
= nla_get_u8(tb
[IPSET_ATTR_NETMASK
]);
304 return -IPSET_ERR_INVALID_NETMASK
;
306 first_ip
&= ip_set_hostmask(netmask
);
307 last_ip
|= ~ip_set_hostmask(netmask
);
312 elements
= (u64
)last_ip
- first_ip
+ 1;
317 mask
= range_to_mask(first_ip
, last_ip
, &mask_bits
);
319 if ((!mask
&& (first_ip
|| last_ip
!= 0xFFFFFFFF)) ||
320 netmask
<= mask_bits
)
321 return -IPSET_ERR_BITMAP_RANGE
;
323 pr_debug("mask_bits %u, netmask %u\n", mask_bits
, netmask
);
324 hosts
= 2 << (32 - netmask
- 1);
325 elements
= 2 << (netmask
- mask_bits
- 1);
327 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
328 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
330 pr_debug("hosts %u, elements %llu\n",
331 hosts
, (unsigned long long)elements
);
333 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
337 map
->memsize
= bitmap_bytes(0, elements
- 1);
338 set
->variant
= &bitmap_ip
;
339 if (tb
[IPSET_ATTR_CADT_FLAGS
])
340 cadt_flags
= ip_set_get_h32(tb
[IPSET_ATTR_CADT_FLAGS
]);
341 if (cadt_flags
& IPSET_FLAG_WITH_COUNTERS
) {
342 set
->extensions
|= IPSET_EXT_COUNTER
;
343 if (tb
[IPSET_ATTR_TIMEOUT
]) {
344 map
->dsize
= sizeof(struct bitmap_ipct_elem
);
345 map
->offset
[IPSET_OFFSET_TIMEOUT
] =
346 offsetof(struct bitmap_ipct_elem
, timeout
);
347 map
->offset
[IPSET_OFFSET_COUNTER
] =
348 offsetof(struct bitmap_ipct_elem
, counter
);
350 if (!init_map_ip(set
, map
, first_ip
, last_ip
,
351 elements
, hosts
, netmask
)) {
356 map
->timeout
= ip_set_timeout_uget(
357 tb
[IPSET_ATTR_TIMEOUT
]);
358 set
->extensions
|= IPSET_EXT_TIMEOUT
;
360 bitmap_ip_gc_init(set
, bitmap_ip_gc
);
362 map
->dsize
= sizeof(struct bitmap_ipc_elem
);
363 map
->offset
[IPSET_OFFSET_COUNTER
] =
364 offsetof(struct bitmap_ipc_elem
, counter
);
366 if (!init_map_ip(set
, map
, first_ip
, last_ip
,
367 elements
, hosts
, netmask
)) {
372 } else if (tb
[IPSET_ATTR_TIMEOUT
]) {
373 map
->dsize
= sizeof(struct bitmap_ipt_elem
);
374 map
->offset
[IPSET_OFFSET_TIMEOUT
] =
375 offsetof(struct bitmap_ipt_elem
, timeout
);
377 if (!init_map_ip(set
, map
, first_ip
, last_ip
,
378 elements
, hosts
, netmask
)) {
383 map
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
384 set
->extensions
|= IPSET_EXT_TIMEOUT
;
386 bitmap_ip_gc_init(set
, bitmap_ip_gc
);
389 if (!init_map_ip(set
, map
, first_ip
, last_ip
,
390 elements
, hosts
, netmask
)) {
398 static struct ip_set_type bitmap_ip_type __read_mostly
= {
400 .protocol
= IPSET_PROTOCOL
,
401 .features
= IPSET_TYPE_IP
,
402 .dimension
= IPSET_DIM_ONE
,
403 .family
= NFPROTO_IPV4
,
404 .revision_min
= REVISION_MIN
,
405 .revision_max
= REVISION_MAX
,
406 .create
= bitmap_ip_create
,
408 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
409 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
410 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
411 [IPSET_ATTR_NETMASK
] = { .type
= NLA_U8
},
412 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
413 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
416 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
417 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
418 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
419 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
420 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
421 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
422 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
430 return ip_set_type_register(&bitmap_ip_type
);
436 ip_set_type_unregister(&bitmap_ip_type
);
439 module_init(bitmap_ip_init
);
440 module_exit(bitmap_ip_fini
);