]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_list_set.c
rt2x00: rt2800pci: use module_pci_driver macro
[karo-tx-linux.git] / net / netfilter / ipset / ip_set_list_set.c
1 /* Copyright (C) 2008-2013 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 list:set type */
9
10 #include <linux/module.h>
11 #include <linux/ip.h>
12 #include <linux/skbuff.h>
13 #include <linux/errno.h>
14
15 #include <linux/netfilter/ipset/ip_set.h>
16 #include <linux/netfilter/ipset/ip_set_list.h>
17
18 #define REVISION_MIN    0
19 #define REVISION_MAX    1 /* Counters support added */
20
21 MODULE_LICENSE("GPL");
22 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
23 IP_SET_MODULE_DESC("list:set", REVISION_MIN, REVISION_MAX);
24 MODULE_ALIAS("ip_set_list:set");
25
26 /* Member elements  */
27 struct set_elem {
28         ip_set_id_t id;
29 };
30
31 struct sett_elem {
32         struct {
33                 ip_set_id_t id;
34         } __attribute__ ((aligned));
35         unsigned long timeout;
36 };
37
38 struct setc_elem {
39         struct {
40                 ip_set_id_t id;
41         } __attribute__ ((aligned));
42         struct ip_set_counter counter;
43 };
44
45 struct setct_elem {
46         struct {
47                 ip_set_id_t id;
48         } __attribute__ ((aligned));
49         struct ip_set_counter counter;
50         unsigned long timeout;
51 };
52
53 struct set_adt_elem {
54         ip_set_id_t id;
55         ip_set_id_t refid;
56         int before;
57 };
58
59 /* Type structure */
60 struct list_set {
61         size_t dsize;           /* element size */
62         size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
63         u32 size;               /* size of set list array */
64         u32 timeout;            /* timeout value */
65         struct timer_list gc;   /* garbage collection */
66         struct set_elem members[0]; /* the set members */
67 };
68
69 static inline struct set_elem *
70 list_set_elem(const struct list_set *map, u32 id)
71 {
72         return (struct set_elem *)((void *)map->members + id * map->dsize);
73 }
74
75 #define ext_timeout(e, m)       \
76 (unsigned long *)((void *)(e) + (m)->offset[IPSET_OFFSET_TIMEOUT])
77 #define ext_counter(e, m)       \
78 (struct ip_set_counter *)((void *)(e) + (m)->offset[IPSET_OFFSET_COUNTER])
79
80 static int
81 list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
82                const struct xt_action_param *par,
83                struct ip_set_adt_opt *opt, const struct ip_set_ext *ext)
84 {
85         struct list_set *map = set->data;
86         struct set_elem *e;
87         u32 i, cmdflags = opt->cmdflags;
88         int ret;
89
90         /* Don't lookup sub-counters at all */
91         opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS;
92         if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
93                 opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
94         for (i = 0; i < map->size; i++) {
95                 e = list_set_elem(map, i);
96                 if (e->id == IPSET_INVALID_ID)
97                         return 0;
98                 if (SET_WITH_TIMEOUT(set) &&
99                     ip_set_timeout_expired(ext_timeout(e, map)))
100                         continue;
101                 ret = ip_set_test(e->id, skb, par, opt);
102                 if (ret > 0) {
103                         if (SET_WITH_COUNTER(set))
104                                 ip_set_update_counter(ext_counter(e, map),
105                                                       ext, &opt->ext,
106                                                       cmdflags);
107                         return ret;
108                 }
109         }
110         return 0;
111 }
112
113 static int
114 list_set_kadd(struct ip_set *set, const struct sk_buff *skb,
115               const struct xt_action_param *par,
116               struct ip_set_adt_opt *opt, const struct ip_set_ext *ext)
117 {
118         struct list_set *map = set->data;
119         struct set_elem *e;
120         u32 i;
121         int ret;
122
123         for (i = 0; i < map->size; i++) {
124                 e = list_set_elem(map, i);
125                 if (e->id == IPSET_INVALID_ID)
126                         return 0;
127                 if (SET_WITH_TIMEOUT(set) &&
128                     ip_set_timeout_expired(ext_timeout(e, map)))
129                         continue;
130                 ret = ip_set_add(e->id, skb, par, opt);
131                 if (ret == 0)
132                         return ret;
133         }
134         return 0;
135 }
136
137 static int
138 list_set_kdel(struct ip_set *set, const struct sk_buff *skb,
139               const struct xt_action_param *par,
140               struct ip_set_adt_opt *opt, const struct ip_set_ext *ext)
141 {
142         struct list_set *map = set->data;
143         struct set_elem *e;
144         u32 i;
145         int ret;
146
147         for (i = 0; i < map->size; i++) {
148                 e = list_set_elem(map, i);
149                 if (e->id == IPSET_INVALID_ID)
150                         return 0;
151                 if (SET_WITH_TIMEOUT(set) &&
152                     ip_set_timeout_expired(ext_timeout(e, map)))
153                         continue;
154                 ret = ip_set_del(e->id, skb, par, opt);
155                 if (ret == 0)
156                         return ret;
157         }
158         return 0;
159 }
160
161 static int
162 list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
163               const struct xt_action_param *par,
164               enum ipset_adt adt, struct ip_set_adt_opt *opt)
165 {
166         struct list_set *map = set->data;
167         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
168
169         switch (adt) {
170         case IPSET_TEST:
171                 return list_set_ktest(set, skb, par, opt, &ext);
172         case IPSET_ADD:
173                 return list_set_kadd(set, skb, par, opt, &ext);
174         case IPSET_DEL:
175                 return list_set_kdel(set, skb, par, opt, &ext);
176         default:
177                 break;
178         }
179         return -EINVAL;
180 }
181
182 static bool
183 id_eq(const struct ip_set *set, u32 i, ip_set_id_t id)
184 {
185         const struct list_set *map = set->data;
186         const struct set_elem *e;
187
188         if (i >= map->size)
189                 return 0;
190
191         e = list_set_elem(map, i);
192         return !!(e->id == id &&
193                  !(SET_WITH_TIMEOUT(set) &&
194                    ip_set_timeout_expired(ext_timeout(e, map))));
195 }
196
197 static int
198 list_set_add(struct ip_set *set, u32 i, struct set_adt_elem *d,
199              const struct ip_set_ext *ext)
200 {
201         struct list_set *map = set->data;
202         struct set_elem *e = list_set_elem(map, i);
203
204         if (e->id != IPSET_INVALID_ID) {
205                 if (i == map->size - 1)
206                         /* Last element replaced: e.g. add new,before,last */
207                         ip_set_put_byindex(e->id);
208                 else {
209                         struct set_elem *x = list_set_elem(map, map->size - 1);
210
211                         /* Last element pushed off */
212                         if (x->id != IPSET_INVALID_ID)
213                                 ip_set_put_byindex(x->id);
214                         memmove(list_set_elem(map, i + 1), e,
215                                 map->dsize * (map->size - (i + 1)));
216                 }
217         }
218
219         e->id = d->id;
220         if (SET_WITH_TIMEOUT(set))
221                 ip_set_timeout_set(ext_timeout(e, map), ext->timeout);
222         if (SET_WITH_COUNTER(set))
223                 ip_set_init_counter(ext_counter(e, map), ext);
224         return 0;
225 }
226
227 static int
228 list_set_del(struct ip_set *set, u32 i)
229 {
230         struct list_set *map = set->data;
231         struct set_elem *e = list_set_elem(map, i);
232
233         ip_set_put_byindex(e->id);
234
235         if (i < map->size - 1)
236                 memmove(e, list_set_elem(map, i + 1),
237                         map->dsize * (map->size - (i + 1)));
238
239         /* Last element */
240         e = list_set_elem(map, map->size - 1);
241         e->id = IPSET_INVALID_ID;
242         return 0;
243 }
244
245 static void
246 set_cleanup_entries(struct ip_set *set)
247 {
248         struct list_set *map = set->data;
249         struct set_elem *e;
250         u32 i;
251
252         for (i = 0; i < map->size; i++) {
253                 e = list_set_elem(map, i);
254                 if (e->id != IPSET_INVALID_ID &&
255                     ip_set_timeout_expired(ext_timeout(e, map)))
256                         list_set_del(set, i);
257         }
258 }
259
260 static int
261 list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,
262                struct ip_set_ext *mext, u32 flags)
263 {
264         struct list_set *map = set->data;
265         struct set_adt_elem *d = value;
266         struct set_elem *e;
267         u32 i;
268         int ret;
269
270         for (i = 0; i < map->size; i++) {
271                 e = list_set_elem(map, i);
272                 if (e->id == IPSET_INVALID_ID)
273                         return 0;
274                 else if (SET_WITH_TIMEOUT(set) &&
275                          ip_set_timeout_expired(ext_timeout(e, map)))
276                         continue;
277                 else if (e->id != d->id)
278                         continue;
279
280                 if (d->before == 0)
281                         return 1;
282                 else if (d->before > 0)
283                         ret = id_eq(set, i + 1, d->refid);
284                 else
285                         ret = i > 0 && id_eq(set, i - 1, d->refid);
286                 return ret;
287         }
288         return 0;
289 }
290
291
292 static int
293 list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
294               struct ip_set_ext *mext, u32 flags)
295 {
296         struct list_set *map = set->data;
297         struct set_adt_elem *d = value;
298         struct set_elem *e;
299         bool flag_exist = flags & IPSET_FLAG_EXIST;
300         u32 i, ret = 0;
301
302         /* Check already added element */
303         for (i = 0; i < map->size; i++) {
304                 e = list_set_elem(map, i);
305                 if (e->id == IPSET_INVALID_ID)
306                         goto insert;
307                 else if (SET_WITH_TIMEOUT(set) &&
308                          ip_set_timeout_expired(ext_timeout(e, map)))
309                         continue;
310                 else if (e->id != d->id)
311                         continue;
312
313                 if ((d->before > 1 && !id_eq(set, i + 1, d->refid)) ||
314                     (d->before < 0 &&
315                      (i == 0 || !id_eq(set, i - 1, d->refid))))
316                         /* Before/after doesn't match */
317                         return -IPSET_ERR_REF_EXIST;
318                 if (!flag_exist)
319                         /* Can't re-add */
320                         return -IPSET_ERR_EXIST;
321                 /* Update extensions */
322                 if (SET_WITH_TIMEOUT(set))
323                         ip_set_timeout_set(ext_timeout(e, map), ext->timeout);
324                 if (SET_WITH_COUNTER(set))
325                         ip_set_init_counter(ext_counter(e, map), ext);
326                 /* Set is already added to the list */
327                 ip_set_put_byindex(d->id);
328                 return 0;
329         }
330 insert:
331         ret = -IPSET_ERR_LIST_FULL;
332         for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
333                 e = list_set_elem(map, i);
334                 if (e->id == IPSET_INVALID_ID)
335                         ret = d->before != 0 ? -IPSET_ERR_REF_EXIST
336                                 : list_set_add(set, i, d, ext);
337                 else if (e->id != d->refid)
338                         continue;
339                 else if (d->before > 0)
340                         ret = list_set_add(set, i, d, ext);
341                 else if (i + 1 < map->size)
342                         ret = list_set_add(set, i + 1, d, ext);
343         }
344
345         return ret;
346 }
347
348 static int
349 list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext,
350               struct ip_set_ext *mext, u32 flags)
351 {
352         struct list_set *map = set->data;
353         struct set_adt_elem *d = value;
354         struct set_elem *e;
355         u32 i;
356
357         for (i = 0; i < map->size; i++) {
358                 e = list_set_elem(map, i);
359                 if (e->id == IPSET_INVALID_ID)
360                         return d->before != 0 ? -IPSET_ERR_REF_EXIST
361                                               : -IPSET_ERR_EXIST;
362                 else if (SET_WITH_TIMEOUT(set) &&
363                          ip_set_timeout_expired(ext_timeout(e, map)))
364                         continue;
365                 else if (e->id != d->id)
366                         continue;
367
368                 if (d->before == 0)
369                         return list_set_del(set, i);
370                 else if (d->before > 0) {
371                         if (!id_eq(set, i + 1, d->refid))
372                                 return -IPSET_ERR_REF_EXIST;
373                         return list_set_del(set, i);
374                 } else if (i == 0 || !id_eq(set, i - 1, d->refid))
375                         return -IPSET_ERR_REF_EXIST;
376                 else
377                         return list_set_del(set, i);
378         }
379         return -IPSET_ERR_EXIST;
380 }
381
382 static int
383 list_set_uadt(struct ip_set *set, struct nlattr *tb[],
384               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
385 {
386         struct list_set *map = set->data;
387         ipset_adtfn adtfn = set->variant->adt[adt];
388         struct set_adt_elem e = { .refid = IPSET_INVALID_ID };
389         struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
390         struct ip_set *s;
391         int ret = 0;
392
393         if (unlikely(!tb[IPSET_ATTR_NAME] ||
394                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
395                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
396                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
397                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
398                 return -IPSET_ERR_PROTOCOL;
399
400         if (tb[IPSET_ATTR_LINENO])
401                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
402
403         ret = ip_set_get_extensions(set, tb, &ext);
404         if (ret)
405                 return ret;
406         e.id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
407         if (e.id == IPSET_INVALID_ID)
408                 return -IPSET_ERR_NAME;
409         /* "Loop detection" */
410         if (s->type->features & IPSET_TYPE_NAME) {
411                 ret = -IPSET_ERR_LOOP;
412                 goto finish;
413         }
414
415         if (tb[IPSET_ATTR_CADT_FLAGS]) {
416                 u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
417                 e.before = f & IPSET_FLAG_BEFORE;
418         }
419
420         if (e.before && !tb[IPSET_ATTR_NAMEREF]) {
421                 ret = -IPSET_ERR_BEFORE;
422                 goto finish;
423         }
424
425         if (tb[IPSET_ATTR_NAMEREF]) {
426                 e.refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
427                                             &s);
428                 if (e.refid == IPSET_INVALID_ID) {
429                         ret = -IPSET_ERR_NAMEREF;
430                         goto finish;
431                 }
432                 if (!e.before)
433                         e.before = -1;
434         }
435         if (adt != IPSET_TEST && SET_WITH_TIMEOUT(set))
436                 set_cleanup_entries(set);
437
438         ret = adtfn(set, &e, &ext, &ext, flags);
439
440 finish:
441         if (e.refid != IPSET_INVALID_ID)
442                 ip_set_put_byindex(e.refid);
443         if (adt != IPSET_ADD || ret)
444                 ip_set_put_byindex(e.id);
445
446         return ip_set_eexist(ret, flags) ? 0 : ret;
447 }
448
449 static void
450 list_set_flush(struct ip_set *set)
451 {
452         struct list_set *map = set->data;
453         struct set_elem *e;
454         u32 i;
455
456         for (i = 0; i < map->size; i++) {
457                 e = list_set_elem(map, i);
458                 if (e->id != IPSET_INVALID_ID) {
459                         ip_set_put_byindex(e->id);
460                         e->id = IPSET_INVALID_ID;
461                 }
462         }
463 }
464
465 static void
466 list_set_destroy(struct ip_set *set)
467 {
468         struct list_set *map = set->data;
469
470         if (SET_WITH_TIMEOUT(set))
471                 del_timer_sync(&map->gc);
472         list_set_flush(set);
473         kfree(map);
474
475         set->data = NULL;
476 }
477
478 static int
479 list_set_head(struct ip_set *set, struct sk_buff *skb)
480 {
481         const struct list_set *map = set->data;
482         struct nlattr *nested;
483
484         nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
485         if (!nested)
486                 goto nla_put_failure;
487         if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) ||
488             (SET_WITH_TIMEOUT(set) &&
489              nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) ||
490             (SET_WITH_COUNTER(set) &&
491              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
492                            htonl(IPSET_FLAG_WITH_COUNTERS))) ||
493             nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
494             nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
495                           htonl(sizeof(*map) + map->size * map->dsize)))
496                 goto nla_put_failure;
497         ipset_nest_end(skb, nested);
498
499         return 0;
500 nla_put_failure:
501         return -EMSGSIZE;
502 }
503
504 static int
505 list_set_list(const struct ip_set *set,
506               struct sk_buff *skb, struct netlink_callback *cb)
507 {
508         const struct list_set *map = set->data;
509         struct nlattr *atd, *nested;
510         u32 i, first = cb->args[2];
511         const struct set_elem *e;
512
513         atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
514         if (!atd)
515                 return -EMSGSIZE;
516         for (; cb->args[2] < map->size; cb->args[2]++) {
517                 i = cb->args[2];
518                 e = list_set_elem(map, i);
519                 if (e->id == IPSET_INVALID_ID)
520                         goto finish;
521                 if (SET_WITH_TIMEOUT(set) &&
522                     ip_set_timeout_expired(ext_timeout(e, map)))
523                         continue;
524                 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
525                 if (!nested) {
526                         if (i == first) {
527                                 nla_nest_cancel(skb, atd);
528                                 return -EMSGSIZE;
529                         } else
530                                 goto nla_put_failure;
531                 }
532                 if (nla_put_string(skb, IPSET_ATTR_NAME,
533                                    ip_set_name_byindex(e->id)))
534                         goto nla_put_failure;
535                 if (SET_WITH_TIMEOUT(set) &&
536                     nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
537                                   htonl(ip_set_timeout_get(
538                                                 ext_timeout(e, map)))))
539                         goto nla_put_failure;
540                 if (SET_WITH_COUNTER(set) &&
541                     ip_set_put_counter(skb, ext_counter(e, map)))
542                         goto nla_put_failure;
543                 ipset_nest_end(skb, nested);
544         }
545 finish:
546         ipset_nest_end(skb, atd);
547         /* Set listing finished */
548         cb->args[2] = 0;
549         return 0;
550
551 nla_put_failure:
552         nla_nest_cancel(skb, nested);
553         ipset_nest_end(skb, atd);
554         if (unlikely(i == first)) {
555                 cb->args[2] = 0;
556                 return -EMSGSIZE;
557         }
558         return 0;
559 }
560
561 static bool
562 list_set_same_set(const struct ip_set *a, const struct ip_set *b)
563 {
564         const struct list_set *x = a->data;
565         const struct list_set *y = b->data;
566
567         return x->size == y->size &&
568                x->timeout == y->timeout &&
569                a->extensions == b->extensions;
570 }
571
572 static const struct ip_set_type_variant set_variant = {
573         .kadt   = list_set_kadt,
574         .uadt   = list_set_uadt,
575         .adt    = {
576                 [IPSET_ADD] = list_set_uadd,
577                 [IPSET_DEL] = list_set_udel,
578                 [IPSET_TEST] = list_set_utest,
579         },
580         .destroy = list_set_destroy,
581         .flush  = list_set_flush,
582         .head   = list_set_head,
583         .list   = list_set_list,
584         .same_set = list_set_same_set,
585 };
586
587 static void
588 list_set_gc(unsigned long ul_set)
589 {
590         struct ip_set *set = (struct ip_set *) ul_set;
591         struct list_set *map = set->data;
592
593         write_lock_bh(&set->lock);
594         set_cleanup_entries(set);
595         write_unlock_bh(&set->lock);
596
597         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
598         add_timer(&map->gc);
599 }
600
601 static void
602 list_set_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
603 {
604         struct list_set *map = set->data;
605
606         init_timer(&map->gc);
607         map->gc.data = (unsigned long) set;
608         map->gc.function = gc;
609         map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
610         add_timer(&map->gc);
611 }
612
613 /* Create list:set type of sets */
614
615 static struct list_set *
616 init_list_set(struct ip_set *set, u32 size, size_t dsize,
617               unsigned long timeout)
618 {
619         struct list_set *map;
620         struct set_elem *e;
621         u32 i;
622
623         map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
624         if (!map)
625                 return NULL;
626
627         map->size = size;
628         map->dsize = dsize;
629         map->timeout = timeout;
630         set->data = map;
631
632         for (i = 0; i < size; i++) {
633                 e = list_set_elem(map, i);
634                 e->id = IPSET_INVALID_ID;
635         }
636
637         return map;
638 }
639
640 static int
641 list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
642 {
643         struct list_set *map;
644         u32 size = IP_SET_LIST_DEFAULT_SIZE, cadt_flags = 0;
645         unsigned long timeout = 0;
646
647         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
648                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
649                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
650                 return -IPSET_ERR_PROTOCOL;
651
652         if (tb[IPSET_ATTR_SIZE])
653                 size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
654         if (size < IP_SET_LIST_MIN_SIZE)
655                 size = IP_SET_LIST_MIN_SIZE;
656
657         if (tb[IPSET_ATTR_CADT_FLAGS])
658                 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
659         if (tb[IPSET_ATTR_TIMEOUT])
660                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
661         set->variant = &set_variant;
662         if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
663                 set->extensions |= IPSET_EXT_COUNTER;
664                 if (tb[IPSET_ATTR_TIMEOUT]) {
665                         map = init_list_set(set, size,
666                                         sizeof(struct setct_elem), timeout);
667                         if (!map)
668                                 return -ENOMEM;
669                         set->extensions |= IPSET_EXT_TIMEOUT;
670                         map->offset[IPSET_OFFSET_TIMEOUT] =
671                                 offsetof(struct setct_elem, timeout);
672                         map->offset[IPSET_OFFSET_COUNTER] =
673                                 offsetof(struct setct_elem, counter);
674                         list_set_gc_init(set, list_set_gc);
675                 } else {
676                         map = init_list_set(set, size,
677                                             sizeof(struct setc_elem), 0);
678                         if (!map)
679                                 return -ENOMEM;
680                         map->offset[IPSET_OFFSET_COUNTER] =
681                                 offsetof(struct setc_elem, counter);
682                 }
683         } else if (tb[IPSET_ATTR_TIMEOUT]) {
684                 map = init_list_set(set, size,
685                                     sizeof(struct sett_elem), timeout);
686                 if (!map)
687                         return -ENOMEM;
688                 set->extensions |= IPSET_EXT_TIMEOUT;
689                 map->offset[IPSET_OFFSET_TIMEOUT] =
690                         offsetof(struct sett_elem, timeout);
691                 list_set_gc_init(set, list_set_gc);
692         } else {
693                 map = init_list_set(set, size, sizeof(struct set_elem), 0);
694                 if (!map)
695                         return -ENOMEM;
696         }
697         return 0;
698 }
699
700 static struct ip_set_type list_set_type __read_mostly = {
701         .name           = "list:set",
702         .protocol       = IPSET_PROTOCOL,
703         .features       = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
704         .dimension      = IPSET_DIM_ONE,
705         .family         = NFPROTO_UNSPEC,
706         .revision_min   = REVISION_MIN,
707         .revision_max   = REVISION_MAX,
708         .create         = list_set_create,
709         .create_policy  = {
710                 [IPSET_ATTR_SIZE]       = { .type = NLA_U32 },
711                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
712                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
713         },
714         .adt_policy     = {
715                 [IPSET_ATTR_NAME]       = { .type = NLA_STRING,
716                                             .len = IPSET_MAXNAMELEN },
717                 [IPSET_ATTR_NAMEREF]    = { .type = NLA_STRING,
718                                             .len = IPSET_MAXNAMELEN },
719                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
720                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
721                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
722                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
723                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
724         },
725         .me             = THIS_MODULE,
726 };
727
728 static int __init
729 list_set_init(void)
730 {
731         return ip_set_type_register(&list_set_type);
732 }
733
734 static void __exit
735 list_set_fini(void)
736 {
737         ip_set_type_unregister(&list_set_type);
738 }
739
740 module_init(list_set_init);
741 module_exit(list_set_fini);