]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_bitmap_ip.c
c46e3440159780a2fb809c4a7d3eab139362f9e8
[karo-tx-linux.git] / net / netfilter / ipset / ip_set_bitmap_ip.c
1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2  *                         Patrick Schaaf <bof@bof.de>
3  * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4  *
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.
8  */
9
10 /* Kernel module implementing an IP set type: the bitmap:ip type */
11
12 #include <linux/module.h>
13 #include <linux/ip.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>
22 #include <net/tcp.h>
23
24 #include <linux/netfilter/ipset/pfxlen.h>
25 #include <linux/netfilter/ipset/ip_set.h>
26 #include <linux/netfilter/ipset/ip_set_bitmap.h>
27 #define IP_SET_BITMAP_TIMEOUT
28 #include <linux/netfilter/ipset/ip_set_timeout.h>
29
30 MODULE_LICENSE("GPL");
31 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
32 MODULE_DESCRIPTION("bitmap:ip type of IP sets");
33 MODULE_ALIAS("ip_set_bitmap:ip");
34
35 /* Type structure */
36 struct bitmap_ip {
37         void *members;          /* the set members */
38         u32 first_ip;           /* host byte order, included in range */
39         u32 last_ip;            /* host byte order, included in range */
40         u32 elements;           /* number of max elements in the set */
41         u32 hosts;              /* number of hosts in a subnet */
42         size_t memsize;         /* members size */
43         u8 netmask;             /* subnet netmask */
44         u32 timeout;            /* timeout parameter */
45         struct timer_list gc;   /* garbage collection */
46 };
47
48 /* Base variant */
49
50 static inline u32
51 ip_to_id(const struct bitmap_ip *m, u32 ip)
52 {
53         return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
54 }
55
56 static int
57 bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
58 {
59         const struct bitmap_ip *map = set->data;
60         u16 id = *(u16 *)value;
61
62         return !!test_bit(id, map->members);
63 }
64
65 static int
66 bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
67 {
68         struct bitmap_ip *map = set->data;
69         u16 id = *(u16 *)value;
70
71         if (test_and_set_bit(id, map->members))
72                 return -IPSET_ERR_EXIST;
73
74         return 0;
75 }
76
77 static int
78 bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
79 {
80         struct bitmap_ip *map = set->data;
81         u16 id = *(u16 *)value;
82
83         if (!test_and_clear_bit(id, map->members))
84                 return -IPSET_ERR_EXIST;
85
86         return 0;
87 }
88
89 static int
90 bitmap_ip_list(const struct ip_set *set,
91                struct sk_buff *skb, struct netlink_callback *cb)
92 {
93         const struct bitmap_ip *map = set->data;
94         struct nlattr *atd, *nested;
95         u32 id, first = cb->args[2];
96
97         atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
98         if (!atd)
99                 return -EMSGSIZE;
100         for (; cb->args[2] < map->elements; cb->args[2]++) {
101                 id = cb->args[2];
102                 if (!test_bit(id, map->members))
103                         continue;
104                 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
105                 if (!nested) {
106                         if (id == first) {
107                                 nla_nest_cancel(skb, atd);
108                                 return -EMSGSIZE;
109                         } else
110                                 goto nla_put_failure;
111                 }
112                 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
113                                 htonl(map->first_ip + id * map->hosts));
114                 ipset_nest_end(skb, nested);
115         }
116         ipset_nest_end(skb, atd);
117         /* Set listing finished */
118         cb->args[2] = 0;
119         return 0;
120
121 nla_put_failure:
122         nla_nest_cancel(skb, nested);
123         ipset_nest_end(skb, atd);
124         if (unlikely(id == first)) {
125                 cb->args[2] = 0;
126                 return -EMSGSIZE;
127         }
128         return 0;
129 }
130
131 /* Timeout variant */
132
133 static int
134 bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
135 {
136         const struct bitmap_ip *map = set->data;
137         const unsigned long *members = map->members;
138         u16 id = *(u16 *)value;
139
140         return ip_set_timeout_test(members[id]);
141 }
142
143 static int
144 bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
145 {
146         struct bitmap_ip *map = set->data;
147         unsigned long *members = map->members;
148         u16 id = *(u16 *)value;
149
150         if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
151                 return -IPSET_ERR_EXIST;
152
153         members[id] = ip_set_timeout_set(timeout);
154
155         return 0;
156 }
157
158 static int
159 bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
160 {
161         struct bitmap_ip *map = set->data;
162         unsigned long *members = map->members;
163         u16 id = *(u16 *)value;
164         int ret = -IPSET_ERR_EXIST;
165
166         if (ip_set_timeout_test(members[id]))
167                 ret = 0;
168
169         members[id] = IPSET_ELEM_UNSET;
170         return ret;
171 }
172
173 static int
174 bitmap_ip_tlist(const struct ip_set *set,
175                 struct sk_buff *skb, struct netlink_callback *cb)
176 {
177         const struct bitmap_ip *map = set->data;
178         struct nlattr *adt, *nested;
179         u32 id, first = cb->args[2];
180         const unsigned long *members = map->members;
181
182         adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
183         if (!adt)
184                 return -EMSGSIZE;
185         for (; cb->args[2] < map->elements; cb->args[2]++) {
186                 id = cb->args[2];
187                 if (!ip_set_timeout_test(members[id]))
188                         continue;
189                 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
190                 if (!nested) {
191                         if (id == first) {
192                                 nla_nest_cancel(skb, adt);
193                                 return -EMSGSIZE;
194                         } else
195                                 goto nla_put_failure;
196                 }
197                 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
198                                 htonl(map->first_ip + id * map->hosts));
199                 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
200                               htonl(ip_set_timeout_get(members[id])));
201                 ipset_nest_end(skb, nested);
202         }
203         ipset_nest_end(skb, adt);
204
205         /* Set listing finished */
206         cb->args[2] = 0;
207
208         return 0;
209
210 nla_put_failure:
211         nla_nest_cancel(skb, nested);
212         ipset_nest_end(skb, adt);
213         if (unlikely(id == first)) {
214                 cb->args[2] = 0;
215                 return -EMSGSIZE;
216         }
217         return 0;
218 }
219
220 static int
221 bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
222                enum ipset_adt adt, const struct ip_set_adt_opt *opt)
223 {
224         struct bitmap_ip *map = set->data;
225         ipset_adtfn adtfn = set->variant->adt[adt];
226         u32 ip;
227
228         ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
229         if (ip < map->first_ip || ip > map->last_ip)
230                 return -IPSET_ERR_BITMAP_RANGE;
231
232         ip = ip_to_id(map, ip);
233
234         return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
235 }
236
237 static int
238 bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
239                enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
240 {
241         struct bitmap_ip *map = set->data;
242         ipset_adtfn adtfn = set->variant->adt[adt];
243         u32 timeout = map->timeout;
244         u32 ip, ip_to, id;
245         int ret = 0;
246
247         if (unlikely(!tb[IPSET_ATTR_IP] ||
248                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
249                 return -IPSET_ERR_PROTOCOL;
250
251         if (tb[IPSET_ATTR_LINENO])
252                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
253
254         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
255         if (ret)
256                 return ret;
257
258         if (ip < map->first_ip || ip > map->last_ip)
259                 return -IPSET_ERR_BITMAP_RANGE;
260
261         if (tb[IPSET_ATTR_TIMEOUT]) {
262                 if (!with_timeout(map->timeout))
263                         return -IPSET_ERR_TIMEOUT;
264                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
265         }
266
267         if (adt == IPSET_TEST) {
268                 id = ip_to_id(map, ip);
269                 return adtfn(set, &id, timeout, flags);
270         }
271
272         if (tb[IPSET_ATTR_IP_TO]) {
273                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
274                 if (ret)
275                         return ret;
276                 if (ip > ip_to) {
277                         swap(ip, ip_to);
278                         if (ip < map->first_ip)
279                                 return -IPSET_ERR_BITMAP_RANGE;
280                 }
281         } else if (tb[IPSET_ATTR_CIDR]) {
282                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
283
284                 if (cidr > 32)
285                         return -IPSET_ERR_INVALID_CIDR;
286                 ip_set_mask_from_to(ip, ip_to, cidr);
287         } else
288                 ip_to = ip;
289
290         if (ip_to > map->last_ip)
291                 return -IPSET_ERR_BITMAP_RANGE;
292
293         for (; !before(ip_to, ip); ip += map->hosts) {
294                 id = ip_to_id(map, ip);
295                 ret = adtfn(set, &id, timeout, flags);
296
297                 if (ret && !ip_set_eexist(ret, flags))
298                         return ret;
299                 else
300                         ret = 0;
301         }
302         return ret;
303 }
304
305 static void
306 bitmap_ip_destroy(struct ip_set *set)
307 {
308         struct bitmap_ip *map = set->data;
309
310         if (with_timeout(map->timeout))
311                 del_timer_sync(&map->gc);
312
313         ip_set_free(map->members);
314         kfree(map);
315
316         set->data = NULL;
317 }
318
319 static void
320 bitmap_ip_flush(struct ip_set *set)
321 {
322         struct bitmap_ip *map = set->data;
323
324         memset(map->members, 0, map->memsize);
325 }
326
327 static int
328 bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
329 {
330         const struct bitmap_ip *map = set->data;
331         struct nlattr *nested;
332
333         nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
334         if (!nested)
335                 goto nla_put_failure;
336         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
337         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
338         if (map->netmask != 32)
339                 NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
340         NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
341         NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
342                       htonl(sizeof(*map) + map->memsize));
343         if (with_timeout(map->timeout))
344                 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
345         ipset_nest_end(skb, nested);
346
347         return 0;
348 nla_put_failure:
349         return -EMSGSIZE;
350 }
351
352 static bool
353 bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
354 {
355         const struct bitmap_ip *x = a->data;
356         const struct bitmap_ip *y = b->data;
357
358         return x->first_ip == y->first_ip &&
359                x->last_ip == y->last_ip &&
360                x->netmask == y->netmask &&
361                x->timeout == y->timeout;
362 }
363
364 static const struct ip_set_type_variant bitmap_ip = {
365         .kadt   = bitmap_ip_kadt,
366         .uadt   = bitmap_ip_uadt,
367         .adt    = {
368                 [IPSET_ADD] = bitmap_ip_add,
369                 [IPSET_DEL] = bitmap_ip_del,
370                 [IPSET_TEST] = bitmap_ip_test,
371         },
372         .destroy = bitmap_ip_destroy,
373         .flush  = bitmap_ip_flush,
374         .head   = bitmap_ip_head,
375         .list   = bitmap_ip_list,
376         .same_set = bitmap_ip_same_set,
377 };
378
379 static const struct ip_set_type_variant bitmap_tip = {
380         .kadt   = bitmap_ip_kadt,
381         .uadt   = bitmap_ip_uadt,
382         .adt    = {
383                 [IPSET_ADD] = bitmap_ip_tadd,
384                 [IPSET_DEL] = bitmap_ip_tdel,
385                 [IPSET_TEST] = bitmap_ip_ttest,
386         },
387         .destroy = bitmap_ip_destroy,
388         .flush  = bitmap_ip_flush,
389         .head   = bitmap_ip_head,
390         .list   = bitmap_ip_tlist,
391         .same_set = bitmap_ip_same_set,
392 };
393
394 static void
395 bitmap_ip_gc(unsigned long ul_set)
396 {
397         struct ip_set *set = (struct ip_set *) ul_set;
398         struct bitmap_ip *map = set->data;
399         unsigned long *table = map->members;
400         u32 id;
401
402         /* We run parallel with other readers (test element)
403          * but adding/deleting new entries is locked out */
404         read_lock_bh(&set->lock);
405         for (id = 0; id < map->elements; id++)
406                 if (ip_set_timeout_expired(table[id]))
407                         table[id] = IPSET_ELEM_UNSET;
408         read_unlock_bh(&set->lock);
409
410         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
411         add_timer(&map->gc);
412 }
413
414 static void
415 bitmap_ip_gc_init(struct ip_set *set)
416 {
417         struct bitmap_ip *map = set->data;
418
419         init_timer(&map->gc);
420         map->gc.data = (unsigned long) set;
421         map->gc.function = bitmap_ip_gc;
422         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
423         add_timer(&map->gc);
424 }
425
426 /* Create bitmap:ip type of sets */
427
428 static bool
429 init_map_ip(struct ip_set *set, struct bitmap_ip *map,
430             u32 first_ip, u32 last_ip,
431             u32 elements, u32 hosts, u8 netmask)
432 {
433         map->members = ip_set_alloc(map->memsize);
434         if (!map->members)
435                 return false;
436         map->first_ip = first_ip;
437         map->last_ip = last_ip;
438         map->elements = elements;
439         map->hosts = hosts;
440         map->netmask = netmask;
441         map->timeout = IPSET_NO_TIMEOUT;
442
443         set->data = map;
444         set->family = AF_INET;
445
446         return true;
447 }
448
449 static int
450 bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
451 {
452         struct bitmap_ip *map;
453         u32 first_ip, last_ip, hosts, elements;
454         u8 netmask = 32;
455         int ret;
456
457         if (unlikely(!tb[IPSET_ATTR_IP] ||
458                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
459                 return -IPSET_ERR_PROTOCOL;
460
461         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
462         if (ret)
463                 return ret;
464
465         if (tb[IPSET_ATTR_IP_TO]) {
466                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
467                 if (ret)
468                         return ret;
469                 if (first_ip > last_ip) {
470                         u32 tmp = first_ip;
471
472                         first_ip = last_ip;
473                         last_ip = tmp;
474                 }
475         } else if (tb[IPSET_ATTR_CIDR]) {
476                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
477
478                 if (cidr >= 32)
479                         return -IPSET_ERR_INVALID_CIDR;
480                 ip_set_mask_from_to(first_ip, last_ip, cidr);
481         } else
482                 return -IPSET_ERR_PROTOCOL;
483
484         if (tb[IPSET_ATTR_NETMASK]) {
485                 netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
486
487                 if (netmask > 32)
488                         return -IPSET_ERR_INVALID_NETMASK;
489
490                 first_ip &= ip_set_hostmask(netmask);
491                 last_ip |= ~ip_set_hostmask(netmask);
492         }
493
494         if (netmask == 32) {
495                 hosts = 1;
496                 elements = last_ip - first_ip + 1;
497         } else {
498                 u8 mask_bits;
499                 u32 mask;
500
501                 mask = range_to_mask(first_ip, last_ip, &mask_bits);
502
503                 if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
504                     netmask <= mask_bits)
505                         return -IPSET_ERR_BITMAP_RANGE;
506
507                 pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
508                 hosts = 2 << (32 - netmask - 1);
509                 elements = 2 << (netmask - mask_bits - 1);
510         }
511         if (elements > IPSET_BITMAP_MAX_RANGE + 1)
512                 return -IPSET_ERR_BITMAP_RANGE_SIZE;
513
514         pr_debug("hosts %u, elements %u\n", hosts, elements);
515
516         map = kzalloc(sizeof(*map), GFP_KERNEL);
517         if (!map)
518                 return -ENOMEM;
519
520         if (tb[IPSET_ATTR_TIMEOUT]) {
521                 map->memsize = elements * sizeof(unsigned long);
522
523                 if (!init_map_ip(set, map, first_ip, last_ip,
524                                  elements, hosts, netmask)) {
525                         kfree(map);
526                         return -ENOMEM;
527                 }
528
529                 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
530                 set->variant = &bitmap_tip;
531
532                 bitmap_ip_gc_init(set);
533         } else {
534                 map->memsize = bitmap_bytes(0, elements - 1);
535
536                 if (!init_map_ip(set, map, first_ip, last_ip,
537                                  elements, hosts, netmask)) {
538                         kfree(map);
539                         return -ENOMEM;
540                 }
541
542                 set->variant = &bitmap_ip;
543         }
544         return 0;
545 }
546
547 static struct ip_set_type bitmap_ip_type __read_mostly = {
548         .name           = "bitmap:ip",
549         .protocol       = IPSET_PROTOCOL,
550         .features       = IPSET_TYPE_IP,
551         .dimension      = IPSET_DIM_ONE,
552         .family         = AF_INET,
553         .revision_min   = 0,
554         .revision_max   = 0,
555         .create         = bitmap_ip_create,
556         .create_policy  = {
557                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
558                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
559                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
560                 [IPSET_ATTR_NETMASK]    = { .type = NLA_U8  },
561                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
562         },
563         .adt_policy     = {
564                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
565                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
566                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
567                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
568                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
569         },
570         .me             = THIS_MODULE,
571 };
572
573 static int __init
574 bitmap_ip_init(void)
575 {
576         return ip_set_type_register(&bitmap_ip_type);
577 }
578
579 static void __exit
580 bitmap_ip_fini(void)
581 {
582         ip_set_type_unregister(&bitmap_ip_type);
583 }
584
585 module_init(bitmap_ip_init);
586 module_exit(bitmap_ip_fini);