1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> |
3 | * Patrick Schaaf <bof@bof.de> |
4 | * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org> |
5 | */ |
6 | |
7 | /* Kernel module implementing an IP set type: the bitmap:ip type */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/ip.h> |
11 | #include <linux/skbuff.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/bitops.h> |
14 | #include <linux/spinlock.h> |
15 | #include <linux/netlink.h> |
16 | #include <linux/jiffies.h> |
17 | #include <linux/timer.h> |
18 | #include <net/netlink.h> |
19 | #include <net/tcp.h> |
20 | |
21 | #include <linux/netfilter/ipset/pfxlen.h> |
22 | #include <linux/netfilter/ipset/ip_set.h> |
23 | #include <linux/netfilter/ipset/ip_set_bitmap.h> |
24 | |
25 | #define IPSET_TYPE_REV_MIN 0 |
26 | /* 1 Counter support added */ |
27 | /* 2 Comment support added */ |
28 | #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */ |
29 | |
30 | MODULE_LICENSE("GPL" ); |
31 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>" ); |
32 | IP_SET_MODULE_DESC("bitmap:ip" , IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); |
33 | MODULE_ALIAS("ip_set_bitmap:ip" ); |
34 | |
35 | #define MTYPE bitmap_ip |
36 | #define HOST_MASK 32 |
37 | |
38 | /* Type structure */ |
39 | struct bitmap_ip { |
40 | unsigned long *members; /* the set members */ |
41 | u32 first_ip; /* host byte order, included in range */ |
42 | u32 last_ip; /* host byte order, included in range */ |
43 | u32 elements; /* number of max elements in the set */ |
44 | u32 hosts; /* number of hosts in a subnet */ |
45 | size_t memsize; /* members size */ |
46 | u8 netmask; /* subnet netmask */ |
47 | struct timer_list gc; /* garbage collection */ |
48 | struct ip_set *set; /* attached to this ip_set */ |
49 | unsigned char extensions[] /* data extensions */ |
50 | __aligned(__alignof__(u64)); |
51 | }; |
52 | |
53 | /* ADT structure for generic function args */ |
54 | struct bitmap_ip_adt_elem { |
55 | u16 id; |
56 | }; |
57 | |
58 | static u32 |
59 | ip_to_id(const struct bitmap_ip *m, u32 ip) |
60 | { |
61 | return ((ip & ip_set_hostmask(pfxlen: m->netmask)) - m->first_ip) / m->hosts; |
62 | } |
63 | |
64 | /* Common functions */ |
65 | |
66 | static int |
67 | bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e, |
68 | struct bitmap_ip *map, size_t dsize) |
69 | { |
70 | return !!test_bit(e->id, map->members); |
71 | } |
72 | |
73 | static int |
74 | bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map, size_t dsize) |
75 | { |
76 | return !!test_bit(id, map->members); |
77 | } |
78 | |
79 | static int |
80 | bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map, |
81 | u32 flags, size_t dsize) |
82 | { |
83 | return !!test_bit(e->id, map->members); |
84 | } |
85 | |
86 | static int |
87 | bitmap_ip_do_del(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map) |
88 | { |
89 | return !test_and_clear_bit(nr: e->id, addr: map->members); |
90 | } |
91 | |
92 | static int |
93 | bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id, |
94 | size_t dsize) |
95 | { |
96 | return nla_put_ipaddr4(skb, type: IPSET_ATTR_IP, |
97 | htonl(map->first_ip + id * map->hosts)); |
98 | } |
99 | |
100 | static int |
101 | bitmap_ip_do_head(struct sk_buff *skb, const struct bitmap_ip *map) |
102 | { |
103 | return nla_put_ipaddr4(skb, type: IPSET_ATTR_IP, htonl(map->first_ip)) || |
104 | nla_put_ipaddr4(skb, type: IPSET_ATTR_IP_TO, htonl(map->last_ip)) || |
105 | (map->netmask != 32 && |
106 | nla_put_u8(skb, attrtype: IPSET_ATTR_NETMASK, value: map->netmask)); |
107 | } |
108 | |
109 | static int |
110 | bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, |
111 | const struct xt_action_param *par, |
112 | enum ipset_adt adt, struct ip_set_adt_opt *opt) |
113 | { |
114 | struct bitmap_ip *map = set->data; |
115 | ipset_adtfn adtfn = set->variant->adt[adt]; |
116 | struct bitmap_ip_adt_elem e = { .id = 0 }; |
117 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); |
118 | u32 ip; |
119 | |
120 | ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC)); |
121 | if (ip < map->first_ip || ip > map->last_ip) |
122 | return -IPSET_ERR_BITMAP_RANGE; |
123 | |
124 | e.id = ip_to_id(m: map, ip); |
125 | |
126 | return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); |
127 | } |
128 | |
129 | static int |
130 | bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], |
131 | enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) |
132 | { |
133 | struct bitmap_ip *map = set->data; |
134 | ipset_adtfn adtfn = set->variant->adt[adt]; |
135 | u32 ip = 0, ip_to = 0; |
136 | struct bitmap_ip_adt_elem e = { .id = 0 }; |
137 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); |
138 | int ret = 0; |
139 | |
140 | if (tb[IPSET_ATTR_LINENO]) |
141 | *lineno = nla_get_u32(nla: tb[IPSET_ATTR_LINENO]); |
142 | |
143 | if (unlikely(!tb[IPSET_ATTR_IP])) |
144 | return -IPSET_ERR_PROTOCOL; |
145 | |
146 | ret = ip_set_get_hostipaddr4(nla: tb[IPSET_ATTR_IP], ipaddr: &ip); |
147 | if (ret) |
148 | return ret; |
149 | |
150 | ret = ip_set_get_extensions(set, tb, ext: &ext); |
151 | if (ret) |
152 | return ret; |
153 | |
154 | if (ip < map->first_ip || ip > map->last_ip) |
155 | return -IPSET_ERR_BITMAP_RANGE; |
156 | |
157 | if (adt == IPSET_TEST) { |
158 | e.id = ip_to_id(m: map, ip); |
159 | return adtfn(set, &e, &ext, &ext, flags); |
160 | } |
161 | |
162 | if (tb[IPSET_ATTR_IP_TO]) { |
163 | ret = ip_set_get_hostipaddr4(nla: tb[IPSET_ATTR_IP_TO], ipaddr: &ip_to); |
164 | if (ret) |
165 | return ret; |
166 | if (ip > ip_to) { |
167 | swap(ip, ip_to); |
168 | if (ip < map->first_ip) |
169 | return -IPSET_ERR_BITMAP_RANGE; |
170 | } |
171 | } else if (tb[IPSET_ATTR_CIDR]) { |
172 | u8 cidr = nla_get_u8(nla: tb[IPSET_ATTR_CIDR]); |
173 | |
174 | if (!cidr || cidr > HOST_MASK) |
175 | return -IPSET_ERR_INVALID_CIDR; |
176 | ip_set_mask_from_to(ip, ip_to, cidr); |
177 | } else { |
178 | ip_to = ip; |
179 | } |
180 | |
181 | if (ip_to > map->last_ip) |
182 | return -IPSET_ERR_BITMAP_RANGE; |
183 | |
184 | for (; !before(seq1: ip_to, seq2: ip); ip += map->hosts) { |
185 | e.id = ip_to_id(m: map, ip); |
186 | ret = adtfn(set, &e, &ext, &ext, flags); |
187 | |
188 | if (ret && !ip_set_eexist(ret, flags)) |
189 | return ret; |
190 | |
191 | ret = 0; |
192 | } |
193 | return ret; |
194 | } |
195 | |
196 | static bool |
197 | bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) |
198 | { |
199 | const struct bitmap_ip *x = a->data; |
200 | const struct bitmap_ip *y = b->data; |
201 | |
202 | return x->first_ip == y->first_ip && |
203 | x->last_ip == y->last_ip && |
204 | x->netmask == y->netmask && |
205 | a->timeout == b->timeout && |
206 | a->extensions == b->extensions; |
207 | } |
208 | |
209 | /* Plain variant */ |
210 | |
211 | struct bitmap_ip_elem { |
212 | }; |
213 | |
214 | #include "ip_set_bitmap_gen.h" |
215 | |
216 | /* Create bitmap:ip type of sets */ |
217 | |
218 | static bool |
219 | init_map_ip(struct ip_set *set, struct bitmap_ip *map, |
220 | u32 first_ip, u32 last_ip, |
221 | u32 elements, u32 hosts, u8 netmask) |
222 | { |
223 | map->members = bitmap_zalloc(nbits: elements, GFP_KERNEL | __GFP_NOWARN); |
224 | if (!map->members) |
225 | return false; |
226 | map->first_ip = first_ip; |
227 | map->last_ip = last_ip; |
228 | map->elements = elements; |
229 | map->hosts = hosts; |
230 | map->netmask = netmask; |
231 | set->timeout = IPSET_NO_TIMEOUT; |
232 | |
233 | map->set = set; |
234 | set->data = map; |
235 | set->family = NFPROTO_IPV4; |
236 | |
237 | return true; |
238 | } |
239 | |
240 | static u32 |
241 | range_to_mask(u32 from, u32 to, u8 *bits) |
242 | { |
243 | u32 mask = 0xFFFFFFFE; |
244 | |
245 | *bits = 32; |
246 | while (--(*bits) > 0 && mask && (to & mask) != from) |
247 | mask <<= 1; |
248 | |
249 | return mask; |
250 | } |
251 | |
252 | static int |
253 | bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], |
254 | u32 flags) |
255 | { |
256 | struct bitmap_ip *map; |
257 | u32 first_ip = 0, last_ip = 0, hosts; |
258 | u64 elements; |
259 | u8 netmask = 32; |
260 | int ret; |
261 | |
262 | if (unlikely(!tb[IPSET_ATTR_IP] || |
263 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || |
264 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) |
265 | return -IPSET_ERR_PROTOCOL; |
266 | |
267 | ret = ip_set_get_hostipaddr4(nla: tb[IPSET_ATTR_IP], ipaddr: &first_ip); |
268 | if (ret) |
269 | return ret; |
270 | |
271 | if (tb[IPSET_ATTR_IP_TO]) { |
272 | ret = ip_set_get_hostipaddr4(nla: tb[IPSET_ATTR_IP_TO], ipaddr: &last_ip); |
273 | if (ret) |
274 | return ret; |
275 | if (first_ip > last_ip) |
276 | swap(first_ip, last_ip); |
277 | } else if (tb[IPSET_ATTR_CIDR]) { |
278 | u8 cidr = nla_get_u8(nla: tb[IPSET_ATTR_CIDR]); |
279 | |
280 | if (cidr >= HOST_MASK) |
281 | return -IPSET_ERR_INVALID_CIDR; |
282 | ip_set_mask_from_to(first_ip, last_ip, cidr); |
283 | } else { |
284 | return -IPSET_ERR_PROTOCOL; |
285 | } |
286 | |
287 | if (tb[IPSET_ATTR_NETMASK]) { |
288 | netmask = nla_get_u8(nla: tb[IPSET_ATTR_NETMASK]); |
289 | |
290 | if (netmask > HOST_MASK) |
291 | return -IPSET_ERR_INVALID_NETMASK; |
292 | |
293 | first_ip &= ip_set_hostmask(pfxlen: netmask); |
294 | last_ip |= ~ip_set_hostmask(pfxlen: netmask); |
295 | } |
296 | |
297 | if (netmask == 32) { |
298 | hosts = 1; |
299 | elements = (u64)last_ip - first_ip + 1; |
300 | } else { |
301 | u8 mask_bits; |
302 | u32 mask; |
303 | |
304 | mask = range_to_mask(from: first_ip, to: last_ip, bits: &mask_bits); |
305 | |
306 | if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) || |
307 | netmask <= mask_bits) |
308 | return -IPSET_ERR_BITMAP_RANGE; |
309 | |
310 | pr_debug("mask_bits %u, netmask %u\n" , mask_bits, netmask); |
311 | hosts = 2U << (32 - netmask - 1); |
312 | elements = 2UL << (netmask - mask_bits - 1); |
313 | } |
314 | if (elements > IPSET_BITMAP_MAX_RANGE + 1) |
315 | return -IPSET_ERR_BITMAP_RANGE_SIZE; |
316 | |
317 | pr_debug("hosts %u, elements %llu\n" , |
318 | hosts, (unsigned long long)elements); |
319 | |
320 | set->dsize = ip_set_elem_len(set, tb, len: 0, align: 0); |
321 | map = ip_set_alloc(size: sizeof(*map) + elements * set->dsize); |
322 | if (!map) |
323 | return -ENOMEM; |
324 | |
325 | map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); |
326 | set->variant = &bitmap_ip; |
327 | if (!init_map_ip(set, map, first_ip, last_ip, |
328 | elements, hosts, netmask)) { |
329 | ip_set_free(members: map); |
330 | return -ENOMEM; |
331 | } |
332 | if (tb[IPSET_ATTR_TIMEOUT]) { |
333 | set->timeout = ip_set_timeout_uget(tb: tb[IPSET_ATTR_TIMEOUT]); |
334 | bitmap_ip_gc_init(set, gc: bitmap_ip_gc); |
335 | } |
336 | return 0; |
337 | } |
338 | |
339 | static struct ip_set_type bitmap_ip_type __read_mostly = { |
340 | .name = "bitmap:ip" , |
341 | .protocol = IPSET_PROTOCOL, |
342 | .features = IPSET_TYPE_IP, |
343 | .dimension = IPSET_DIM_ONE, |
344 | .family = NFPROTO_IPV4, |
345 | .revision_min = IPSET_TYPE_REV_MIN, |
346 | .revision_max = IPSET_TYPE_REV_MAX, |
347 | .create = bitmap_ip_create, |
348 | .create_policy = { |
349 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, |
350 | [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, |
351 | [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, |
352 | [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, |
353 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, |
354 | [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, |
355 | }, |
356 | .adt_policy = { |
357 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, |
358 | [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, |
359 | [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, |
360 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, |
361 | [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, |
362 | [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, |
363 | [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, |
364 | [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, |
365 | .len = IPSET_MAX_COMMENT_SIZE }, |
366 | [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, |
367 | [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, |
368 | [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, |
369 | }, |
370 | .me = THIS_MODULE, |
371 | }; |
372 | |
373 | static int __init |
374 | bitmap_ip_init(void) |
375 | { |
376 | return ip_set_type_register(set_type: &bitmap_ip_type); |
377 | } |
378 | |
379 | static void __exit |
380 | bitmap_ip_fini(void) |
381 | { |
382 | rcu_barrier(); |
383 | ip_set_type_unregister(set_type: &bitmap_ip_type); |
384 | } |
385 | |
386 | module_init(bitmap_ip_init); |
387 | module_exit(bitmap_ip_fini); |
388 | |