]> Pileus Git - ~andy/linux/blob - net/netfilter/ipset/ip_set_bitmap_port.c
Merge tag 'stable/for-linus-3.7-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / net / netfilter / ipset / ip_set_bitmap_port.c
1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation.
6  */
7
8 /* Kernel module implementing an IP set type: the bitmap:port type */
9
10 #include <linux/module.h>
11 #include <linux/ip.h>
12 #include <linux/skbuff.h>
13 #include <linux/errno.h>
14 #include <linux/netlink.h>
15 #include <linux/jiffies.h>
16 #include <linux/timer.h>
17 #include <net/netlink.h>
18
19 #include <linux/netfilter/ipset/ip_set.h>
20 #include <linux/netfilter/ipset/ip_set_bitmap.h>
21 #include <linux/netfilter/ipset/ip_set_getport.h>
22 #define IP_SET_BITMAP_TIMEOUT
23 #include <linux/netfilter/ipset/ip_set_timeout.h>
24
25 #define REVISION_MIN    0
26 #define REVISION_MAX    0
27
28 MODULE_LICENSE("GPL");
29 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30 IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX);
31 MODULE_ALIAS("ip_set_bitmap:port");
32
33 /* Type structure */
34 struct bitmap_port {
35         void *members;          /* the set members */
36         u16 first_port;         /* host byte order, included in range */
37         u16 last_port;          /* host byte order, included in range */
38         size_t memsize;         /* members size */
39         u32 timeout;            /* timeout parameter */
40         struct timer_list gc;   /* garbage collection */
41 };
42
43 /* Base variant */
44
45 static int
46 bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
47 {
48         const struct bitmap_port *map = set->data;
49         u16 id = *(u16 *)value;
50
51         return !!test_bit(id, map->members);
52 }
53
54 static int
55 bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
56 {
57         struct bitmap_port *map = set->data;
58         u16 id = *(u16 *)value;
59
60         if (test_and_set_bit(id, map->members))
61                 return -IPSET_ERR_EXIST;
62
63         return 0;
64 }
65
66 static int
67 bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
68 {
69         struct bitmap_port *map = set->data;
70         u16 id = *(u16 *)value;
71
72         if (!test_and_clear_bit(id, map->members))
73                 return -IPSET_ERR_EXIST;
74
75         return 0;
76 }
77
78 static int
79 bitmap_port_list(const struct ip_set *set,
80                  struct sk_buff *skb, struct netlink_callback *cb)
81 {
82         const struct bitmap_port *map = set->data;
83         struct nlattr *atd, *nested;
84         u16 id, first = cb->args[2];
85         u16 last = map->last_port - map->first_port;
86
87         atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
88         if (!atd)
89                 return -EMSGSIZE;
90         for (; cb->args[2] <= last; cb->args[2]++) {
91                 id = cb->args[2];
92                 if (!test_bit(id, map->members))
93                         continue;
94                 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
95                 if (!nested) {
96                         if (id == first) {
97                                 nla_nest_cancel(skb, atd);
98                                 return -EMSGSIZE;
99                         } else
100                                 goto nla_put_failure;
101                 }
102                 if (nla_put_net16(skb, IPSET_ATTR_PORT,
103                                   htons(map->first_port + id)))
104                         goto nla_put_failure;
105                 ipset_nest_end(skb, nested);
106         }
107         ipset_nest_end(skb, atd);
108         /* Set listing finished */
109         cb->args[2] = 0;
110
111         return 0;
112
113 nla_put_failure:
114         nla_nest_cancel(skb, nested);
115         ipset_nest_end(skb, atd);
116         if (unlikely(id == first)) {
117                 cb->args[2] = 0;
118                 return -EMSGSIZE;
119         }
120         return 0;
121 }
122
123 /* Timeout variant */
124
125 static int
126 bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
127 {
128         const struct bitmap_port *map = set->data;
129         const unsigned long *members = map->members;
130         u16 id = *(u16 *)value;
131
132         return ip_set_timeout_test(members[id]);
133 }
134
135 static int
136 bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
137 {
138         struct bitmap_port *map = set->data;
139         unsigned long *members = map->members;
140         u16 id = *(u16 *)value;
141
142         if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
143                 return -IPSET_ERR_EXIST;
144
145         members[id] = ip_set_timeout_set(timeout);
146
147         return 0;
148 }
149
150 static int
151 bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
152 {
153         struct bitmap_port *map = set->data;
154         unsigned long *members = map->members;
155         u16 id = *(u16 *)value;
156         int ret = -IPSET_ERR_EXIST;
157
158         if (ip_set_timeout_test(members[id]))
159                 ret = 0;
160
161         members[id] = IPSET_ELEM_UNSET;
162         return ret;
163 }
164
165 static int
166 bitmap_port_tlist(const struct ip_set *set,
167                   struct sk_buff *skb, struct netlink_callback *cb)
168 {
169         const struct bitmap_port *map = set->data;
170         struct nlattr *adt, *nested;
171         u16 id, first = cb->args[2];
172         u16 last = map->last_port - map->first_port;
173         const unsigned long *members = map->members;
174
175         adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
176         if (!adt)
177                 return -EMSGSIZE;
178         for (; cb->args[2] <= last; cb->args[2]++) {
179                 id = cb->args[2];
180                 if (!ip_set_timeout_test(members[id]))
181                         continue;
182                 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
183                 if (!nested) {
184                         if (id == first) {
185                                 nla_nest_cancel(skb, adt);
186                                 return -EMSGSIZE;
187                         } else
188                                 goto nla_put_failure;
189                 }
190                 if (nla_put_net16(skb, IPSET_ATTR_PORT,
191                                   htons(map->first_port + id)) ||
192                     nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
193                                   htonl(ip_set_timeout_get(members[id]))))
194                         goto nla_put_failure;
195                 ipset_nest_end(skb, nested);
196         }
197         ipset_nest_end(skb, adt);
198
199         /* Set listing finished */
200         cb->args[2] = 0;
201
202         return 0;
203
204 nla_put_failure:
205         nla_nest_cancel(skb, nested);
206         ipset_nest_end(skb, adt);
207         if (unlikely(id == first)) {
208                 cb->args[2] = 0;
209                 return -EMSGSIZE;
210         }
211         return 0;
212 }
213
214 static int
215 bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
216                  const struct xt_action_param *par,
217                  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
218 {
219         struct bitmap_port *map = set->data;
220         ipset_adtfn adtfn = set->variant->adt[adt];
221         __be16 __port;
222         u16 port = 0;
223
224         if (!ip_set_get_ip_port(skb, opt->family,
225                                 opt->flags & IPSET_DIM_ONE_SRC, &__port))
226                 return -EINVAL;
227
228         port = ntohs(__port);
229
230         if (port < map->first_port || port > map->last_port)
231                 return -IPSET_ERR_BITMAP_RANGE;
232
233         port -= map->first_port;
234
235         return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
236 }
237
238 static int
239 bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
240                  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
241 {
242         struct bitmap_port *map = set->data;
243         ipset_adtfn adtfn = set->variant->adt[adt];
244         u32 timeout = map->timeout;
245         u32 port;       /* wraparound */
246         u16 id, port_to;
247         int ret = 0;
248
249         if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
250                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
251                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
252                 return -IPSET_ERR_PROTOCOL;
253
254         if (tb[IPSET_ATTR_LINENO])
255                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
256
257         port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
258         if (port < map->first_port || port > map->last_port)
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 = port - map->first_port;
269                 return adtfn(set, &id, timeout, flags);
270         }
271
272         if (tb[IPSET_ATTR_PORT_TO]) {
273                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
274                 if (port > port_to) {
275                         swap(port, port_to);
276                         if (port < map->first_port)
277                                 return -IPSET_ERR_BITMAP_RANGE;
278                 }
279         } else
280                 port_to = port;
281
282         if (port_to > map->last_port)
283                 return -IPSET_ERR_BITMAP_RANGE;
284
285         for (; port <= port_to; port++) {
286                 id = port - map->first_port;
287                 ret = adtfn(set, &id, timeout, flags);
288
289                 if (ret && !ip_set_eexist(ret, flags))
290                         return ret;
291                 else
292                         ret = 0;
293         }
294         return ret;
295 }
296
297 static void
298 bitmap_port_destroy(struct ip_set *set)
299 {
300         struct bitmap_port *map = set->data;
301
302         if (with_timeout(map->timeout))
303                 del_timer_sync(&map->gc);
304
305         ip_set_free(map->members);
306         kfree(map);
307
308         set->data = NULL;
309 }
310
311 static void
312 bitmap_port_flush(struct ip_set *set)
313 {
314         struct bitmap_port *map = set->data;
315
316         memset(map->members, 0, map->memsize);
317 }
318
319 static int
320 bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
321 {
322         const struct bitmap_port *map = set->data;
323         struct nlattr *nested;
324
325         nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
326         if (!nested)
327                 goto nla_put_failure;
328         if (nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
329             nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)) ||
330             nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
331             nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
332                           htonl(sizeof(*map) + map->memsize)) ||
333             (with_timeout(map->timeout) &&
334              nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
335                 goto nla_put_failure;
336         ipset_nest_end(skb, nested);
337
338         return 0;
339 nla_put_failure:
340         return -EMSGSIZE;
341 }
342
343 static bool
344 bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
345 {
346         const struct bitmap_port *x = a->data;
347         const struct bitmap_port *y = b->data;
348
349         return x->first_port == y->first_port &&
350                x->last_port == y->last_port &&
351                x->timeout == y->timeout;
352 }
353
354 static const struct ip_set_type_variant bitmap_port = {
355         .kadt   = bitmap_port_kadt,
356         .uadt   = bitmap_port_uadt,
357         .adt    = {
358                 [IPSET_ADD] = bitmap_port_add,
359                 [IPSET_DEL] = bitmap_port_del,
360                 [IPSET_TEST] = bitmap_port_test,
361         },
362         .destroy = bitmap_port_destroy,
363         .flush  = bitmap_port_flush,
364         .head   = bitmap_port_head,
365         .list   = bitmap_port_list,
366         .same_set = bitmap_port_same_set,
367 };
368
369 static const struct ip_set_type_variant bitmap_tport = {
370         .kadt   = bitmap_port_kadt,
371         .uadt   = bitmap_port_uadt,
372         .adt    = {
373                 [IPSET_ADD] = bitmap_port_tadd,
374                 [IPSET_DEL] = bitmap_port_tdel,
375                 [IPSET_TEST] = bitmap_port_ttest,
376         },
377         .destroy = bitmap_port_destroy,
378         .flush  = bitmap_port_flush,
379         .head   = bitmap_port_head,
380         .list   = bitmap_port_tlist,
381         .same_set = bitmap_port_same_set,
382 };
383
384 static void
385 bitmap_port_gc(unsigned long ul_set)
386 {
387         struct ip_set *set = (struct ip_set *) ul_set;
388         struct bitmap_port *map = set->data;
389         unsigned long *table = map->members;
390         u32 id; /* wraparound */
391         u16 last = map->last_port - map->first_port;
392
393         /* We run parallel with other readers (test element)
394          * but adding/deleting new entries is locked out */
395         read_lock_bh(&set->lock);
396         for (id = 0; id <= last; id++)
397                 if (ip_set_timeout_expired(table[id]))
398                         table[id] = IPSET_ELEM_UNSET;
399         read_unlock_bh(&set->lock);
400
401         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
402         add_timer(&map->gc);
403 }
404
405 static void
406 bitmap_port_gc_init(struct ip_set *set)
407 {
408         struct bitmap_port *map = set->data;
409
410         init_timer(&map->gc);
411         map->gc.data = (unsigned long) set;
412         map->gc.function = bitmap_port_gc;
413         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
414         add_timer(&map->gc);
415 }
416
417 /* Create bitmap:ip type of sets */
418
419 static bool
420 init_map_port(struct ip_set *set, struct bitmap_port *map,
421               u16 first_port, u16 last_port)
422 {
423         map->members = ip_set_alloc(map->memsize);
424         if (!map->members)
425                 return false;
426         map->first_port = first_port;
427         map->last_port = last_port;
428         map->timeout = IPSET_NO_TIMEOUT;
429
430         set->data = map;
431         set->family = NFPROTO_UNSPEC;
432
433         return true;
434 }
435
436 static int
437 bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
438                  u32 flags)
439 {
440         struct bitmap_port *map;
441         u16 first_port, last_port;
442
443         if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
444                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
445                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
446                 return -IPSET_ERR_PROTOCOL;
447
448         first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
449         last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
450         if (first_port > last_port) {
451                 u16 tmp = first_port;
452
453                 first_port = last_port;
454                 last_port = tmp;
455         }
456
457         map = kzalloc(sizeof(*map), GFP_KERNEL);
458         if (!map)
459                 return -ENOMEM;
460
461         if (tb[IPSET_ATTR_TIMEOUT]) {
462                 map->memsize = (last_port - first_port + 1)
463                                * sizeof(unsigned long);
464
465                 if (!init_map_port(set, map, first_port, last_port)) {
466                         kfree(map);
467                         return -ENOMEM;
468                 }
469
470                 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
471                 set->variant = &bitmap_tport;
472
473                 bitmap_port_gc_init(set);
474         } else {
475                 map->memsize = bitmap_bytes(0, last_port - first_port);
476                 pr_debug("memsize: %zu\n", map->memsize);
477                 if (!init_map_port(set, map, first_port, last_port)) {
478                         kfree(map);
479                         return -ENOMEM;
480                 }
481
482                 set->variant = &bitmap_port;
483         }
484         return 0;
485 }
486
487 static struct ip_set_type bitmap_port_type = {
488         .name           = "bitmap:port",
489         .protocol       = IPSET_PROTOCOL,
490         .features       = IPSET_TYPE_PORT,
491         .dimension      = IPSET_DIM_ONE,
492         .family         = NFPROTO_UNSPEC,
493         .revision_min   = REVISION_MIN,
494         .revision_max   = REVISION_MAX,
495         .create         = bitmap_port_create,
496         .create_policy  = {
497                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
498                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
499                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
500         },
501         .adt_policy     = {
502                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
503                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
504                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
505                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
506         },
507         .me             = THIS_MODULE,
508 };
509
510 static int __init
511 bitmap_port_init(void)
512 {
513         return ip_set_type_register(&bitmap_port_type);
514 }
515
516 static void __exit
517 bitmap_port_fini(void)
518 {
519         ip_set_type_unregister(&bitmap_port_type);
520 }
521
522 module_init(bitmap_port_init);
523 module_exit(bitmap_port_fini);