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 IPSET_TYPE_REV_MIN 0
29 /* 1 Counter support added */
30 /* 2 Comment support added */
31 #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
35 IP_SET_MODULE_DESC("bitmap:ip", IPSET_TYPE_REV_MIN
, IPSET_TYPE_REV_MAX
);
36 MODULE_ALIAS("ip_set_bitmap:ip");
38 #define MTYPE bitmap_ip
43 void *members
; /* the set members */
44 u32 first_ip
; /* host byte order, included in range */
45 u32 last_ip
; /* host byte order, included in range */
46 u32 elements
; /* number of max elements in the set */
47 u32 hosts
; /* number of hosts in a subnet */
48 size_t memsize
; /* members size */
49 u8 netmask
; /* subnet netmask */
50 struct timer_list gc
; /* garbage collection */
51 unsigned char extensions
[0] /* data extensions */
52 __aligned(__alignof__(u64
));
55 /* ADT structure for generic function args */
56 struct bitmap_ip_adt_elem
{
61 ip_to_id(const struct bitmap_ip
*m
, u32 ip
)
63 return ((ip
& ip_set_hostmask(m
->netmask
)) - m
->first_ip
) / m
->hosts
;
66 /* Common functions */
69 bitmap_ip_do_test(const struct bitmap_ip_adt_elem
*e
,
70 struct bitmap_ip
*map
, size_t dsize
)
72 return !!test_bit(e
->id
, map
->members
);
76 bitmap_ip_gc_test(u16 id
, const struct bitmap_ip
*map
, size_t dsize
)
78 return !!test_bit(id
, map
->members
);
82 bitmap_ip_do_add(const struct bitmap_ip_adt_elem
*e
, struct bitmap_ip
*map
,
83 u32 flags
, size_t dsize
)
85 return !!test_bit(e
->id
, map
->members
);
89 bitmap_ip_do_del(const struct bitmap_ip_adt_elem
*e
, struct bitmap_ip
*map
)
91 return !test_and_clear_bit(e
->id
, map
->members
);
95 bitmap_ip_do_list(struct sk_buff
*skb
, const struct bitmap_ip
*map
, u32 id
,
98 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
,
99 htonl(map
->first_ip
+ id
* map
->hosts
));
103 bitmap_ip_do_head(struct sk_buff
*skb
, const struct bitmap_ip
*map
)
105 return nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, htonl(map
->first_ip
)) ||
106 nla_put_ipaddr4(skb
, IPSET_ATTR_IP_TO
, htonl(map
->last_ip
)) ||
107 (map
->netmask
!= 32 &&
108 nla_put_u8(skb
, IPSET_ATTR_NETMASK
, map
->netmask
));
112 bitmap_ip_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
113 const struct xt_action_param
*par
,
114 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
116 struct bitmap_ip
*map
= set
->data
;
117 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
118 struct bitmap_ip_adt_elem e
= { .id
= 0 };
119 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
122 ip
= ntohl(ip4addr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
));
123 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
124 return -IPSET_ERR_BITMAP_RANGE
;
126 e
.id
= ip_to_id(map
, ip
);
128 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
132 bitmap_ip_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
133 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
135 struct bitmap_ip
*map
= set
->data
;
136 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
137 u32 ip
= 0, ip_to
= 0;
138 struct bitmap_ip_adt_elem e
= { .id
= 0 };
139 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
142 if (tb
[IPSET_ATTR_LINENO
])
143 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
145 if (unlikely(!tb
[IPSET_ATTR_IP
]))
146 return -IPSET_ERR_PROTOCOL
;
148 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
);
152 ret
= ip_set_get_extensions(set
, tb
, &ext
);
156 if (ip
< map
->first_ip
|| ip
> map
->last_ip
)
157 return -IPSET_ERR_BITMAP_RANGE
;
159 if (adt
== IPSET_TEST
) {
160 e
.id
= ip_to_id(map
, ip
);
161 return adtfn(set
, &e
, &ext
, &ext
, flags
);
164 if (tb
[IPSET_ATTR_IP_TO
]) {
165 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &ip_to
);
170 if (ip
< map
->first_ip
)
171 return -IPSET_ERR_BITMAP_RANGE
;
173 } else if (tb
[IPSET_ATTR_CIDR
]) {
174 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
176 if (!cidr
|| cidr
> HOST_MASK
)
177 return -IPSET_ERR_INVALID_CIDR
;
178 ip_set_mask_from_to(ip
, ip_to
, cidr
);
183 if (ip_to
> map
->last_ip
)
184 return -IPSET_ERR_BITMAP_RANGE
;
186 for (; !before(ip_to
, ip
); ip
+= map
->hosts
) {
187 e
.id
= ip_to_id(map
, ip
);
188 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
190 if (ret
&& !ip_set_eexist(ret
, flags
))
199 bitmap_ip_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
201 const struct bitmap_ip
*x
= a
->data
;
202 const struct bitmap_ip
*y
= b
->data
;
204 return x
->first_ip
== y
->first_ip
&&
205 x
->last_ip
== y
->last_ip
&&
206 x
->netmask
== y
->netmask
&&
207 a
->timeout
== b
->timeout
&&
208 a
->extensions
== b
->extensions
;
213 struct bitmap_ip_elem
{
216 #include "ip_set_bitmap_gen.h"
218 /* Create bitmap:ip type of sets */
221 init_map_ip(struct ip_set
*set
, struct bitmap_ip
*map
,
222 u32 first_ip
, u32 last_ip
,
223 u32 elements
, u32 hosts
, u8 netmask
)
225 map
->members
= ip_set_alloc(map
->memsize
);
228 map
->first_ip
= first_ip
;
229 map
->last_ip
= last_ip
;
230 map
->elements
= elements
;
232 map
->netmask
= netmask
;
233 set
->timeout
= IPSET_NO_TIMEOUT
;
236 set
->family
= NFPROTO_IPV4
;
242 bitmap_ip_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
245 struct bitmap_ip
*map
;
246 u32 first_ip
= 0, last_ip
= 0, hosts
;
251 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
252 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
253 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
254 return -IPSET_ERR_PROTOCOL
;
256 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &first_ip
);
260 if (tb
[IPSET_ATTR_IP_TO
]) {
261 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &last_ip
);
264 if (first_ip
> last_ip
) {
270 } else if (tb
[IPSET_ATTR_CIDR
]) {
271 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
273 if (cidr
>= HOST_MASK
)
274 return -IPSET_ERR_INVALID_CIDR
;
275 ip_set_mask_from_to(first_ip
, last_ip
, cidr
);
277 return -IPSET_ERR_PROTOCOL
;
280 if (tb
[IPSET_ATTR_NETMASK
]) {
281 netmask
= nla_get_u8(tb
[IPSET_ATTR_NETMASK
]);
283 if (netmask
> HOST_MASK
)
284 return -IPSET_ERR_INVALID_NETMASK
;
286 first_ip
&= ip_set_hostmask(netmask
);
287 last_ip
|= ~ip_set_hostmask(netmask
);
292 elements
= (u64
)last_ip
- first_ip
+ 1;
297 mask
= range_to_mask(first_ip
, last_ip
, &mask_bits
);
299 if ((!mask
&& (first_ip
|| last_ip
!= 0xFFFFFFFF)) ||
300 netmask
<= mask_bits
)
301 return -IPSET_ERR_BITMAP_RANGE
;
303 pr_debug("mask_bits %u, netmask %u\n", mask_bits
, netmask
);
304 hosts
= 2 << (32 - netmask
- 1);
305 elements
= 2 << (netmask
- mask_bits
- 1);
307 if (elements
> IPSET_BITMAP_MAX_RANGE
+ 1)
308 return -IPSET_ERR_BITMAP_RANGE_SIZE
;
310 pr_debug("hosts %u, elements %llu\n",
311 hosts
, (unsigned long long)elements
);
313 set
->dsize
= ip_set_elem_len(set
, tb
, 0, 0);
314 map
= ip_set_alloc(sizeof(*map
) + elements
* set
->dsize
);
318 map
->memsize
= bitmap_bytes(0, elements
- 1);
319 set
->variant
= &bitmap_ip
;
320 if (!init_map_ip(set
, map
, first_ip
, last_ip
,
321 elements
, hosts
, netmask
)) {
325 if (tb
[IPSET_ATTR_TIMEOUT
]) {
326 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
327 bitmap_ip_gc_init(set
, bitmap_ip_gc
);
332 static struct ip_set_type bitmap_ip_type __read_mostly
= {
334 .protocol
= IPSET_PROTOCOL
,
335 .features
= IPSET_TYPE_IP
,
336 .dimension
= IPSET_DIM_ONE
,
337 .family
= NFPROTO_IPV4
,
338 .revision_min
= IPSET_TYPE_REV_MIN
,
339 .revision_max
= IPSET_TYPE_REV_MAX
,
340 .create
= bitmap_ip_create
,
342 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
343 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
344 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
345 [IPSET_ATTR_NETMASK
] = { .type
= NLA_U8
},
346 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
347 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
350 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
351 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
352 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
353 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
354 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
355 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
356 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
357 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
358 .len
= IPSET_MAX_COMMENT_SIZE
},
359 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
360 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
361 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
369 return ip_set_type_register(&bitmap_ip_type
);
376 ip_set_type_unregister(&bitmap_ip_type
);
379 module_init(bitmap_ip_init
);
380 module_exit(bitmap_ip_fini
);