1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
8 /* Kernel module implementing an IP set type: the bitmap:port type */
10 #include <linux/module.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>
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>
25 MODULE_LICENSE("GPL");
26 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
27 MODULE_DESCRIPTION("bitmap:port type of IP sets");
28 MODULE_ALIAS("ip_set_bitmap:port");
32 void *members
; /* the set members */
33 u16 first_port
; /* host byte order, included in range */
34 u16 last_port
; /* host byte order, included in range */
35 size_t memsize
; /* members size */
36 u32 timeout
; /* timeout parameter */
37 struct timer_list gc
; /* garbage collection */
43 bitmap_port_test(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
45 const struct bitmap_port
*map
= set
->data
;
46 u16 id
= *(u16
*)value
;
48 return !!test_bit(id
, map
->members
);
52 bitmap_port_add(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
54 struct bitmap_port
*map
= set
->data
;
55 u16 id
= *(u16
*)value
;
57 if (test_and_set_bit(id
, map
->members
))
58 return -IPSET_ERR_EXIST
;
64 bitmap_port_del(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
66 struct bitmap_port
*map
= set
->data
;
67 u16 id
= *(u16
*)value
;
69 if (!test_and_clear_bit(id
, map
->members
))
70 return -IPSET_ERR_EXIST
;
76 bitmap_port_list(const struct ip_set
*set
,
77 struct sk_buff
*skb
, struct netlink_callback
*cb
)
79 const struct bitmap_port
*map
= set
->data
;
80 struct nlattr
*atd
, *nested
;
81 u16 id
, first
= cb
->args
[2];
82 u16 last
= map
->last_port
- map
->first_port
;
84 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
87 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
89 if (!test_bit(id
, map
->members
))
91 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
94 nla_nest_cancel(skb
, atd
);
99 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
,
100 htons(map
->first_port
+ id
));
101 ipset_nest_end(skb
, nested
);
103 ipset_nest_end(skb
, atd
);
104 /* Set listing finished */
110 nla_nest_cancel(skb
, nested
);
111 ipset_nest_end(skb
, atd
);
112 if (unlikely(id
== first
)) {
119 /* Timeout variant */
122 bitmap_port_ttest(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
124 const struct bitmap_port
*map
= set
->data
;
125 const unsigned long *members
= map
->members
;
126 u16 id
= *(u16
*)value
;
128 return ip_set_timeout_test(members
[id
]);
132 bitmap_port_tadd(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
134 struct bitmap_port
*map
= set
->data
;
135 unsigned long *members
= map
->members
;
136 u16 id
= *(u16
*)value
;
138 if (ip_set_timeout_test(members
[id
]) && !(flags
& IPSET_FLAG_EXIST
))
139 return -IPSET_ERR_EXIST
;
141 members
[id
] = ip_set_timeout_set(timeout
);
147 bitmap_port_tdel(struct ip_set
*set
, void *value
, u32 timeout
, u32 flags
)
149 struct bitmap_port
*map
= set
->data
;
150 unsigned long *members
= map
->members
;
151 u16 id
= *(u16
*)value
;
152 int ret
= -IPSET_ERR_EXIST
;
154 if (ip_set_timeout_test(members
[id
]))
157 members
[id
] = IPSET_ELEM_UNSET
;
162 bitmap_port_tlist(const struct ip_set
*set
,
163 struct sk_buff
*skb
, struct netlink_callback
*cb
)
165 const struct bitmap_port
*map
= set
->data
;
166 struct nlattr
*adt
, *nested
;
167 u16 id
, first
= cb
->args
[2];
168 u16 last
= map
->last_port
- map
->first_port
;
169 const unsigned long *members
= map
->members
;
171 adt
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
174 for (; cb
->args
[2] <= last
; cb
->args
[2]++) {
176 if (!ip_set_timeout_test(members
[id
]))
178 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
181 nla_nest_cancel(skb
, adt
);
184 goto nla_put_failure
;
186 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
,
187 htons(map
->first_port
+ id
));
188 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
,
189 htonl(ip_set_timeout_get(members
[id
])));
190 ipset_nest_end(skb
, nested
);
192 ipset_nest_end(skb
, adt
);
194 /* Set listing finished */
200 nla_nest_cancel(skb
, nested
);
201 ipset_nest_end(skb
, adt
);
202 if (unlikely(id
== first
)) {
210 bitmap_port_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
211 enum ipset_adt adt
, u8 pf
, u8 dim
, u8 flags
)
213 struct bitmap_port
*map
= set
->data
;
214 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
218 if (!ip_set_get_ip_port(skb
, pf
, flags
& IPSET_DIM_ONE_SRC
, &__port
))
221 port
= ntohs(__port
);
223 if (port
< map
->first_port
|| port
> map
->last_port
)
224 return -IPSET_ERR_BITMAP_RANGE
;
226 port
-= map
->first_port
;
228 return adtfn(set
, &port
, map
->timeout
, flags
);
232 bitmap_port_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
233 enum ipset_adt adt
, u32
*lineno
, u32 flags
)
235 struct bitmap_port
*map
= set
->data
;
236 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
237 u32 timeout
= map
->timeout
;
238 u32 port
; /* wraparound */
242 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
243 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
244 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
245 return -IPSET_ERR_PROTOCOL
;
247 if (tb
[IPSET_ATTR_LINENO
])
248 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
250 port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
251 if (port
< map
->first_port
|| port
> map
->last_port
)
252 return -IPSET_ERR_BITMAP_RANGE
;
254 if (tb
[IPSET_ATTR_TIMEOUT
]) {
255 if (!with_timeout(map
->timeout
))
256 return -IPSET_ERR_TIMEOUT
;
257 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
260 if (adt
== IPSET_TEST
) {
261 id
= port
- map
->first_port
;
262 return adtfn(set
, &id
, timeout
, flags
);
265 if (tb
[IPSET_ATTR_PORT_TO
]) {
266 port_to
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
267 if (port
> port_to
) {
269 if (port
< map
->first_port
)
270 return -IPSET_ERR_BITMAP_RANGE
;
275 if (port_to
> map
->last_port
)
276 return -IPSET_ERR_BITMAP_RANGE
;
278 for (; port
<= port_to
; port
++) {
279 id
= port
- map
->first_port
;
280 ret
= adtfn(set
, &id
, timeout
, flags
);
282 if (ret
&& !ip_set_eexist(ret
, flags
))
291 bitmap_port_destroy(struct ip_set
*set
)
293 struct bitmap_port
*map
= set
->data
;
295 if (with_timeout(map
->timeout
))
296 del_timer_sync(&map
->gc
);
298 ip_set_free(map
->members
);
305 bitmap_port_flush(struct ip_set
*set
)
307 struct bitmap_port
*map
= set
->data
;
309 memset(map
->members
, 0, map
->memsize
);
313 bitmap_port_head(struct ip_set
*set
, struct sk_buff
*skb
)
315 const struct bitmap_port
*map
= set
->data
;
316 struct nlattr
*nested
;
318 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
320 goto nla_put_failure
;
321 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
, htons(map
->first_port
));
322 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT_TO
, htons(map
->last_port
));
323 NLA_PUT_NET32(skb
, IPSET_ATTR_REFERENCES
, htonl(set
->ref
- 1));
324 NLA_PUT_NET32(skb
, IPSET_ATTR_MEMSIZE
,
325 htonl(sizeof(*map
) + map
->memsize
));
326 if (with_timeout(map
->timeout
))
327 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
, htonl(map
->timeout
));
328 ipset_nest_end(skb
, nested
);
336 bitmap_port_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
338 const struct bitmap_port
*x
= a
->data
;
339 const struct bitmap_port
*y
= b
->data
;
341 return x
->first_port
== y
->first_port
&&
342 x
->last_port
== y
->last_port
&&
343 x
->timeout
== y
->timeout
;
346 static const struct ip_set_type_variant bitmap_port
= {
347 .kadt
= bitmap_port_kadt
,
348 .uadt
= bitmap_port_uadt
,
350 [IPSET_ADD
] = bitmap_port_add
,
351 [IPSET_DEL
] = bitmap_port_del
,
352 [IPSET_TEST
] = bitmap_port_test
,
354 .destroy
= bitmap_port_destroy
,
355 .flush
= bitmap_port_flush
,
356 .head
= bitmap_port_head
,
357 .list
= bitmap_port_list
,
358 .same_set
= bitmap_port_same_set
,
361 static const struct ip_set_type_variant bitmap_tport
= {
362 .kadt
= bitmap_port_kadt
,
363 .uadt
= bitmap_port_uadt
,
365 [IPSET_ADD
] = bitmap_port_tadd
,
366 [IPSET_DEL
] = bitmap_port_tdel
,
367 [IPSET_TEST
] = bitmap_port_ttest
,
369 .destroy
= bitmap_port_destroy
,
370 .flush
= bitmap_port_flush
,
371 .head
= bitmap_port_head
,
372 .list
= bitmap_port_tlist
,
373 .same_set
= bitmap_port_same_set
,
377 bitmap_port_gc(unsigned long ul_set
)
379 struct ip_set
*set
= (struct ip_set
*) ul_set
;
380 struct bitmap_port
*map
= set
->data
;
381 unsigned long *table
= map
->members
;
382 u32 id
; /* wraparound */
383 u16 last
= map
->last_port
- map
->first_port
;
385 /* We run parallel with other readers (test element)
386 * but adding/deleting new entries is locked out */
387 read_lock_bh(&set
->lock
);
388 for (id
= 0; id
<= last
; id
++)
389 if (ip_set_timeout_expired(table
[id
]))
390 table
[id
] = IPSET_ELEM_UNSET
;
391 read_unlock_bh(&set
->lock
);
393 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
398 bitmap_port_gc_init(struct ip_set
*set
)
400 struct bitmap_port
*map
= set
->data
;
402 init_timer(&map
->gc
);
403 map
->gc
.data
= (unsigned long) set
;
404 map
->gc
.function
= bitmap_port_gc
;
405 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(map
->timeout
) * HZ
;
409 /* Create bitmap:ip type of sets */
412 init_map_port(struct ip_set
*set
, struct bitmap_port
*map
,
413 u16 first_port
, u16 last_port
)
415 map
->members
= ip_set_alloc(map
->memsize
);
418 map
->first_port
= first_port
;
419 map
->last_port
= last_port
;
420 map
->timeout
= IPSET_NO_TIMEOUT
;
423 set
->family
= AF_UNSPEC
;
429 bitmap_port_create(struct ip_set
*set
, struct nlattr
*tb
[],
432 struct bitmap_port
*map
;
433 u16 first_port
, last_port
;
435 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
436 !ip_set_attr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
437 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
438 return -IPSET_ERR_PROTOCOL
;
440 first_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
441 last_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
442 if (first_port
> last_port
) {
443 u16 tmp
= first_port
;
445 first_port
= last_port
;
449 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
453 if (tb
[IPSET_ATTR_TIMEOUT
]) {
454 map
->memsize
= (last_port
- first_port
+ 1)
455 * sizeof(unsigned long);
457 if (!init_map_port(set
, map
, first_port
, last_port
)) {
462 map
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
463 set
->variant
= &bitmap_tport
;
465 bitmap_port_gc_init(set
);
467 map
->memsize
= bitmap_bytes(0, last_port
- first_port
);
468 pr_debug("memsize: %zu\n", map
->memsize
);
469 if (!init_map_port(set
, map
, first_port
, last_port
)) {
474 set
->variant
= &bitmap_port
;
479 static struct ip_set_type bitmap_port_type
= {
480 .name
= "bitmap:port",
481 .protocol
= IPSET_PROTOCOL
,
482 .features
= IPSET_TYPE_PORT
,
483 .dimension
= IPSET_DIM_ONE
,
486 .create
= bitmap_port_create
,
488 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
489 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
490 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
493 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
494 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
495 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
496 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
502 bitmap_port_init(void)
504 return ip_set_type_register(&bitmap_port_type
);
508 bitmap_port_fini(void)
510 ip_set_type_unregister(&bitmap_port_type
);
513 module_init(bitmap_port_init
);
514 module_exit(bitmap_port_fini
);