1 /* Copyright (C) 2008-2013 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 list:set type */
10 #include <linux/module.h>
12 #include <linux/rculist.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
16 #include <linux/netfilter/ipset/ip_set.h>
17 #include <linux/netfilter/ipset/ip_set_list.h>
19 #define IPSET_TYPE_REV_MIN 0
20 /* 1 Counters support added */
21 /* 2 Comments support added */
22 #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
24 MODULE_LICENSE("GPL");
25 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
26 IP_SET_MODULE_DESC("list:set", IPSET_TYPE_REV_MIN
, IPSET_TYPE_REV_MAX
);
27 MODULE_ALIAS("ip_set_list:set");
32 struct list_head list
;
33 struct ip_set
*set
; /* Sigh, in order to cleanup reference */
35 } __aligned(__alignof__(u64
));
45 u32 size
; /* size of set list array */
46 struct timer_list gc
; /* garbage collection */
47 struct net
*net
; /* namespace */
48 struct list_head members
; /* the set members */
52 list_set_ktest(struct ip_set
*set
, const struct sk_buff
*skb
,
53 const struct xt_action_param
*par
,
54 struct ip_set_adt_opt
*opt
, const struct ip_set_ext
*ext
)
56 struct list_set
*map
= set
->data
;
58 u32 cmdflags
= opt
->cmdflags
;
61 /* Don't lookup sub-counters at all */
62 opt
->cmdflags
&= ~IPSET_FLAG_MATCH_COUNTERS
;
63 if (opt
->cmdflags
& IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE
)
64 opt
->cmdflags
&= ~IPSET_FLAG_SKIP_COUNTER_UPDATE
;
65 list_for_each_entry_rcu(e
, &map
->members
, list
) {
66 if (SET_WITH_TIMEOUT(set
) &&
67 ip_set_timeout_expired(ext_timeout(e
, set
)))
69 ret
= ip_set_test(e
->id
, skb
, par
, opt
);
71 if (SET_WITH_COUNTER(set
))
72 ip_set_update_counter(ext_counter(e
, set
),
75 if (SET_WITH_SKBINFO(set
))
76 ip_set_get_skbinfo(ext_skbinfo(e
, set
),
86 list_set_kadd(struct ip_set
*set
, const struct sk_buff
*skb
,
87 const struct xt_action_param
*par
,
88 struct ip_set_adt_opt
*opt
, const struct ip_set_ext
*ext
)
90 struct list_set
*map
= set
->data
;
94 list_for_each_entry(e
, &map
->members
, list
) {
95 if (SET_WITH_TIMEOUT(set
) &&
96 ip_set_timeout_expired(ext_timeout(e
, set
)))
98 ret
= ip_set_add(e
->id
, skb
, par
, opt
);
106 list_set_kdel(struct ip_set
*set
, const struct sk_buff
*skb
,
107 const struct xt_action_param
*par
,
108 struct ip_set_adt_opt
*opt
, const struct ip_set_ext
*ext
)
110 struct list_set
*map
= set
->data
;
114 list_for_each_entry(e
, &map
->members
, list
) {
115 if (SET_WITH_TIMEOUT(set
) &&
116 ip_set_timeout_expired(ext_timeout(e
, set
)))
118 ret
= ip_set_del(e
->id
, skb
, par
, opt
);
126 list_set_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
127 const struct xt_action_param
*par
,
128 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
130 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
136 ret
= list_set_ktest(set
, skb
, par
, opt
, &ext
);
139 ret
= list_set_kadd(set
, skb
, par
, opt
, &ext
);
142 ret
= list_set_kdel(set
, skb
, par
, opt
, &ext
);
152 /* Userspace interfaces: we are protected by the nfnl mutex */
155 __list_set_del_rcu(struct rcu_head
* rcu
)
157 struct set_elem
*e
= container_of(rcu
, struct set_elem
, rcu
);
158 struct ip_set
*set
= e
->set
;
159 struct list_set
*map
= set
->data
;
161 ip_set_put_byindex(map
->net
, e
->id
);
162 ip_set_ext_destroy(set
, e
);
167 list_set_del(struct ip_set
*set
, struct set_elem
*e
)
169 list_del_rcu(&e
->list
);
170 call_rcu(&e
->rcu
, __list_set_del_rcu
);
174 list_set_replace(struct set_elem
*e
, struct set_elem
*old
)
176 list_replace_rcu(&old
->list
, &e
->list
);
177 call_rcu(&old
->rcu
, __list_set_del_rcu
);
181 set_cleanup_entries(struct ip_set
*set
)
183 struct list_set
*map
= set
->data
;
184 struct set_elem
*e
, *n
;
186 list_for_each_entry_safe(e
, n
, &map
->members
, list
)
187 if (ip_set_timeout_expired(ext_timeout(e
, set
)))
188 list_set_del(set
, e
);
192 list_set_utest(struct ip_set
*set
, void *value
, const struct ip_set_ext
*ext
,
193 struct ip_set_ext
*mext
, u32 flags
)
195 struct list_set
*map
= set
->data
;
196 struct set_adt_elem
*d
= value
;
197 struct set_elem
*e
, *next
, *prev
= NULL
;
200 list_for_each_entry(e
, &map
->members
, list
) {
201 if (SET_WITH_TIMEOUT(set
) &&
202 ip_set_timeout_expired(ext_timeout(e
, set
)))
204 else if (e
->id
!= d
->id
) {
209 if (d
->before
== 0) {
211 } else if (d
->before
> 0) {
212 next
= list_next_entry(e
, list
);
213 ret
= !list_is_last(&e
->list
, &map
->members
) &&
214 next
->id
== d
->refid
;
216 ret
= prev
&& prev
->id
== d
->refid
;
224 list_set_init_extensions(struct ip_set
*set
, const struct ip_set_ext
*ext
,
227 if (SET_WITH_COUNTER(set
))
228 ip_set_init_counter(ext_counter(e
, set
), ext
);
229 if (SET_WITH_COMMENT(set
))
230 ip_set_init_comment(ext_comment(e
, set
), ext
);
231 if (SET_WITH_SKBINFO(set
))
232 ip_set_init_skbinfo(ext_skbinfo(e
, set
), ext
);
233 /* Update timeout last */
234 if (SET_WITH_TIMEOUT(set
))
235 ip_set_timeout_set(ext_timeout(e
, set
), ext
->timeout
);
239 list_set_uadd(struct ip_set
*set
, void *value
, const struct ip_set_ext
*ext
,
240 struct ip_set_ext
*mext
, u32 flags
)
242 struct list_set
*map
= set
->data
;
243 struct set_adt_elem
*d
= value
;
244 struct set_elem
*e
, *n
, *prev
, *next
;
245 bool flag_exist
= flags
& IPSET_FLAG_EXIST
;
247 /* Find where to add the new entry */
248 n
= prev
= next
= NULL
;
249 list_for_each_entry(e
, &map
->members
, list
) {
250 if (SET_WITH_TIMEOUT(set
) &&
251 ip_set_timeout_expired(ext_timeout(e
, set
)))
253 else if (d
->id
== e
->id
)
255 else if (d
->before
== 0 || e
->id
!= d
->refid
)
257 else if (d
->before
> 0)
262 /* Re-add already existing element */
264 if ((d
->before
> 0 && !next
) ||
265 (d
->before
< 0 && !prev
))
266 return -IPSET_ERR_REF_EXIST
;
268 return -IPSET_ERR_EXIST
;
269 /* Update extensions */
270 ip_set_ext_destroy(set
, n
);
271 list_set_init_extensions(set
, ext
, n
);
273 /* Set is already added to the list */
274 ip_set_put_byindex(map
->net
, d
->id
);
278 if (d
->before
== 0) {
280 n
= list_empty(&map
->members
) ? NULL
:
281 list_last_entry(&map
->members
, struct set_elem
, list
);
282 } else if (d
->before
> 0) {
283 /* Insert after next element */
284 if (!list_is_last(&next
->list
, &map
->members
))
285 n
= list_next_entry(next
, list
);
287 /* Insert before prev element */
288 if (prev
->list
.prev
!= &map
->members
)
289 n
= list_prev_entry(prev
, list
);
291 /* Can we replace a timed out entry? */
293 !(SET_WITH_TIMEOUT(set
) &&
294 ip_set_timeout_expired(ext_timeout(n
, set
))))
297 e
= kzalloc(set
->dsize
, GFP_ATOMIC
);
302 INIT_LIST_HEAD(&e
->list
);
303 list_set_init_extensions(set
, ext
, e
);
305 list_set_replace(e
, n
);
307 list_add_tail_rcu(&e
->list
, &next
->list
);
309 list_add_rcu(&e
->list
, &prev
->list
);
311 list_add_tail_rcu(&e
->list
, &map
->members
);
317 list_set_udel(struct ip_set
*set
, void *value
, const struct ip_set_ext
*ext
,
318 struct ip_set_ext
*mext
, u32 flags
)
320 struct list_set
*map
= set
->data
;
321 struct set_adt_elem
*d
= value
;
322 struct set_elem
*e
, *next
, *prev
= NULL
;
324 list_for_each_entry(e
, &map
->members
, list
) {
325 if (SET_WITH_TIMEOUT(set
) &&
326 ip_set_timeout_expired(ext_timeout(e
, set
)))
328 else if (e
->id
!= d
->id
) {
334 next
= list_next_entry(e
, list
);
335 if (list_is_last(&e
->list
, &map
->members
) ||
336 next
->id
!= d
->refid
)
337 return -IPSET_ERR_REF_EXIST
;
338 } else if (d
->before
< 0) {
339 if (!prev
|| prev
->id
!= d
->refid
)
340 return -IPSET_ERR_REF_EXIST
;
342 list_set_del(set
, e
);
345 return d
->before
!= 0 ? -IPSET_ERR_REF_EXIST
: -IPSET_ERR_EXIST
;
349 list_set_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
350 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
352 struct list_set
*map
= set
->data
;
353 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
354 struct set_adt_elem e
= { .refid
= IPSET_INVALID_ID
};
355 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
359 if (tb
[IPSET_ATTR_LINENO
])
360 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
362 if (unlikely(!tb
[IPSET_ATTR_NAME
] ||
363 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
364 return -IPSET_ERR_PROTOCOL
;
366 ret
= ip_set_get_extensions(set
, tb
, &ext
);
369 e
.id
= ip_set_get_byname(map
->net
, nla_data(tb
[IPSET_ATTR_NAME
]), &s
);
370 if (e
.id
== IPSET_INVALID_ID
)
371 return -IPSET_ERR_NAME
;
372 /* "Loop detection" */
373 if (s
->type
->features
& IPSET_TYPE_NAME
) {
374 ret
= -IPSET_ERR_LOOP
;
378 if (tb
[IPSET_ATTR_CADT_FLAGS
]) {
379 u32 f
= ip_set_get_h32(tb
[IPSET_ATTR_CADT_FLAGS
]);
381 e
.before
= f
& IPSET_FLAG_BEFORE
;
384 if (e
.before
&& !tb
[IPSET_ATTR_NAMEREF
]) {
385 ret
= -IPSET_ERR_BEFORE
;
389 if (tb
[IPSET_ATTR_NAMEREF
]) {
390 e
.refid
= ip_set_get_byname(map
->net
,
391 nla_data(tb
[IPSET_ATTR_NAMEREF
]),
393 if (e
.refid
== IPSET_INVALID_ID
) {
394 ret
= -IPSET_ERR_NAMEREF
;
400 if (adt
!= IPSET_TEST
&& SET_WITH_TIMEOUT(set
))
401 set_cleanup_entries(set
);
403 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
406 if (e
.refid
!= IPSET_INVALID_ID
)
407 ip_set_put_byindex(map
->net
, e
.refid
);
408 if (adt
!= IPSET_ADD
|| ret
)
409 ip_set_put_byindex(map
->net
, e
.id
);
411 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
415 list_set_flush(struct ip_set
*set
)
417 struct list_set
*map
= set
->data
;
418 struct set_elem
*e
, *n
;
420 list_for_each_entry_safe(e
, n
, &map
->members
, list
)
421 list_set_del(set
, e
);
425 list_set_destroy(struct ip_set
*set
)
427 struct list_set
*map
= set
->data
;
428 struct set_elem
*e
, *n
;
430 if (SET_WITH_TIMEOUT(set
))
431 del_timer_sync(&map
->gc
);
433 list_for_each_entry_safe(e
, n
, &map
->members
, list
) {
435 ip_set_put_byindex(map
->net
, e
->id
);
436 ip_set_ext_destroy(set
, e
);
445 list_set_head(struct ip_set
*set
, struct sk_buff
*skb
)
447 const struct list_set
*map
= set
->data
;
448 struct nlattr
*nested
;
453 list_for_each_entry_rcu(e
, &map
->members
, list
)
457 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
459 goto nla_put_failure
;
460 if (nla_put_net32(skb
, IPSET_ATTR_SIZE
, htonl(map
->size
)) ||
461 nla_put_net32(skb
, IPSET_ATTR_REFERENCES
, htonl(set
->ref
)) ||
462 nla_put_net32(skb
, IPSET_ATTR_MEMSIZE
,
463 htonl(sizeof(*map
) + n
* set
->dsize
)))
464 goto nla_put_failure
;
465 if (unlikely(ip_set_put_flags(skb
, set
)))
466 goto nla_put_failure
;
467 ipset_nest_end(skb
, nested
);
475 list_set_list(const struct ip_set
*set
,
476 struct sk_buff
*skb
, struct netlink_callback
*cb
)
478 const struct list_set
*map
= set
->data
;
479 struct nlattr
*atd
, *nested
;
480 u32 i
= 0, first
= cb
->args
[IPSET_CB_ARG0
];
484 atd
= ipset_nest_start(skb
, IPSET_ATTR_ADT
);
489 list_for_each_entry_rcu(e
, &map
->members
, list
) {
491 (SET_WITH_TIMEOUT(set
) &&
492 ip_set_timeout_expired(ext_timeout(e
, set
)))) {
496 nested
= ipset_nest_start(skb
, IPSET_ATTR_DATA
);
498 goto nla_put_failure
;
499 if (nla_put_string(skb
, IPSET_ATTR_NAME
,
500 ip_set_name_byindex(map
->net
, e
->id
)))
501 goto nla_put_failure
;
502 if (ip_set_put_extensions(skb
, set
, e
, true))
503 goto nla_put_failure
;
504 ipset_nest_end(skb
, nested
);
508 ipset_nest_end(skb
, atd
);
509 /* Set listing finished */
510 cb
->args
[IPSET_CB_ARG0
] = 0;
514 nla_nest_cancel(skb
, nested
);
515 if (unlikely(i
== first
)) {
516 nla_nest_cancel(skb
, atd
);
517 cb
->args
[IPSET_CB_ARG0
] = 0;
520 cb
->args
[IPSET_CB_ARG0
] = i
;
522 ipset_nest_end(skb
, atd
);
529 list_set_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
531 const struct list_set
*x
= a
->data
;
532 const struct list_set
*y
= b
->data
;
534 return x
->size
== y
->size
&&
535 a
->timeout
== b
->timeout
&&
536 a
->extensions
== b
->extensions
;
539 static const struct ip_set_type_variant set_variant
= {
540 .kadt
= list_set_kadt
,
541 .uadt
= list_set_uadt
,
543 [IPSET_ADD
] = list_set_uadd
,
544 [IPSET_DEL
] = list_set_udel
,
545 [IPSET_TEST
] = list_set_utest
,
547 .destroy
= list_set_destroy
,
548 .flush
= list_set_flush
,
549 .head
= list_set_head
,
550 .list
= list_set_list
,
551 .same_set
= list_set_same_set
,
555 list_set_gc(unsigned long ul_set
)
557 struct ip_set
*set
= (struct ip_set
*)ul_set
;
558 struct list_set
*map
= set
->data
;
560 spin_lock_bh(&set
->lock
);
561 set_cleanup_entries(set
);
562 spin_unlock_bh(&set
->lock
);
564 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(set
->timeout
) * HZ
;
569 list_set_gc_init(struct ip_set
*set
, void (*gc
)(unsigned long ul_set
))
571 struct list_set
*map
= set
->data
;
573 init_timer(&map
->gc
);
574 map
->gc
.data
= (unsigned long)set
;
575 map
->gc
.function
= gc
;
576 map
->gc
.expires
= jiffies
+ IPSET_GC_PERIOD(set
->timeout
) * HZ
;
580 /* Create list:set type of sets */
583 init_list_set(struct net
*net
, struct ip_set
*set
, u32 size
)
585 struct list_set
*map
;
587 map
= kzalloc(sizeof(*map
), GFP_KERNEL
);
593 INIT_LIST_HEAD(&map
->members
);
600 list_set_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
603 u32 size
= IP_SET_LIST_DEFAULT_SIZE
;
605 if (unlikely(!ip_set_optattr_netorder(tb
, IPSET_ATTR_SIZE
) ||
606 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
607 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
608 return -IPSET_ERR_PROTOCOL
;
610 if (tb
[IPSET_ATTR_SIZE
])
611 size
= ip_set_get_h32(tb
[IPSET_ATTR_SIZE
]);
612 if (size
< IP_SET_LIST_MIN_SIZE
)
613 size
= IP_SET_LIST_MIN_SIZE
;
615 set
->variant
= &set_variant
;
616 set
->dsize
= ip_set_elem_len(set
, tb
, sizeof(struct set_elem
),
617 __alignof__(struct set_elem
));
618 if (!init_list_set(net
, set
, size
))
620 if (tb
[IPSET_ATTR_TIMEOUT
]) {
621 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
622 list_set_gc_init(set
, list_set_gc
);
627 static struct ip_set_type list_set_type __read_mostly
= {
629 .protocol
= IPSET_PROTOCOL
,
630 .features
= IPSET_TYPE_NAME
| IPSET_DUMP_LAST
,
631 .dimension
= IPSET_DIM_ONE
,
632 .family
= NFPROTO_UNSPEC
,
633 .revision_min
= IPSET_TYPE_REV_MIN
,
634 .revision_max
= IPSET_TYPE_REV_MAX
,
635 .create
= list_set_create
,
637 [IPSET_ATTR_SIZE
] = { .type
= NLA_U32
},
638 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
639 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
642 [IPSET_ATTR_NAME
] = { .type
= NLA_STRING
,
643 .len
= IPSET_MAXNAMELEN
},
644 [IPSET_ATTR_NAMEREF
] = { .type
= NLA_STRING
,
645 .len
= IPSET_MAXNAMELEN
},
646 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
647 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
648 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
649 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
650 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
651 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
652 .len
= IPSET_MAX_COMMENT_SIZE
},
653 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
654 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
655 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
663 return ip_set_type_register(&list_set_type
);
670 ip_set_type_unregister(&list_set_type
);
673 module_init(list_set_init
);
674 module_exit(list_set_fini
);