Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ip_set_bitmap_port.c
Go to the documentation of this file.
1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <[email protected]>
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>
22 #define IP_SET_BITMAP_TIMEOUT
24 
25 #define REVISION_MIN 0
26 #define REVISION_MAX 0
27 
28 MODULE_LICENSE("GPL");
29 MODULE_AUTHOR("Jozsef Kadlecsik <[email protected]>");
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);
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,
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;
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);