1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se>
4 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 /* Kernel module which implements the set match and SET target
12 * for netfilter/iptables.
15 #include <linux/module.h>
16 #include <linux/skbuff.h>
18 #include <linux/netfilter/x_tables.h>
19 #include <linux/netfilter/ipset/ip_set.h>
20 #include <linux/netfilter/ipset/ip_set_timeout.h>
21 #include <uapi/linux/netfilter/xt_set.h>
23 MODULE_LICENSE("GPL");
24 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
25 MODULE_DESCRIPTION("Xtables: IP set match and target module");
26 MODULE_ALIAS("xt_SET");
27 MODULE_ALIAS("ipt_set");
28 MODULE_ALIAS("ip6t_set");
29 MODULE_ALIAS("ipt_SET");
30 MODULE_ALIAS("ip6t_SET");
33 match_set(ip_set_id_t index
, const struct sk_buff
*skb
,
34 const struct xt_action_param
*par
,
35 struct ip_set_adt_opt
*opt
, int inv
)
37 if (ip_set_test(index
, skb
, par
, opt
))
42 #define ADT_OPT(n, f, d, fs, cfs, t) \
43 struct ip_set_adt_opt n = { \
51 /* Revision 0 interface: backward compatible with netfilter/iptables */
54 set_match_v0(const struct sk_buff
*skb
, struct xt_action_param
*par
)
56 const struct xt_set_info_match_v0
*info
= par
->matchinfo
;
58 ADT_OPT(opt
, par
->family
, info
->match_set
.u
.compat
.dim
,
59 info
->match_set
.u
.compat
.flags
, 0, UINT_MAX
);
61 return match_set(info
->match_set
.index
, skb
, par
, &opt
,
62 info
->match_set
.u
.compat
.flags
& IPSET_INV_MATCH
);
66 compat_flags(struct xt_set_info_v0
*info
)
70 /* Fill out compatibility data according to enum ip_set_kopt */
71 info
->u
.compat
.dim
= IPSET_DIM_ZERO
;
72 if (info
->u
.flags
[0] & IPSET_MATCH_INV
)
73 info
->u
.compat
.flags
|= IPSET_INV_MATCH
;
74 for (i
= 0; i
< IPSET_DIM_MAX
- 1 && info
->u
.flags
[i
]; i
++) {
76 if (info
->u
.flags
[i
] & IPSET_SRC
)
77 info
->u
.compat
.flags
|= (1 << info
->u
.compat
.dim
);
82 set_match_v0_checkentry(const struct xt_mtchk_param
*par
)
84 struct xt_set_info_match_v0
*info
= par
->matchinfo
;
87 index
= ip_set_nfnl_get_byindex(par
->net
, info
->match_set
.index
);
89 if (index
== IPSET_INVALID_ID
) {
90 pr_warn("Cannot find set identified by id %u to match\n",
91 info
->match_set
.index
);
94 if (info
->match_set
.u
.flags
[IPSET_DIM_MAX
- 1] != 0) {
95 pr_warn("Protocol error: set match dimension is over the limit!\n");
96 ip_set_nfnl_put(par
->net
, info
->match_set
.index
);
100 /* Fill out compatibility data */
101 compat_flags(&info
->match_set
);
107 set_match_v0_destroy(const struct xt_mtdtor_param
*par
)
109 struct xt_set_info_match_v0
*info
= par
->matchinfo
;
111 ip_set_nfnl_put(par
->net
, info
->match_set
.index
);
114 /* Revision 1 match */
117 set_match_v1(const struct sk_buff
*skb
, struct xt_action_param
*par
)
119 const struct xt_set_info_match_v1
*info
= par
->matchinfo
;
121 ADT_OPT(opt
, par
->family
, info
->match_set
.dim
,
122 info
->match_set
.flags
, 0, UINT_MAX
);
124 if (opt
.flags
& IPSET_RETURN_NOMATCH
)
125 opt
.cmdflags
|= IPSET_FLAG_RETURN_NOMATCH
;
127 return match_set(info
->match_set
.index
, skb
, par
, &opt
,
128 info
->match_set
.flags
& IPSET_INV_MATCH
);
132 set_match_v1_checkentry(const struct xt_mtchk_param
*par
)
134 struct xt_set_info_match_v1
*info
= par
->matchinfo
;
137 index
= ip_set_nfnl_get_byindex(par
->net
, info
->match_set
.index
);
139 if (index
== IPSET_INVALID_ID
) {
140 pr_warn("Cannot find set identified by id %u to match\n",
141 info
->match_set
.index
);
144 if (info
->match_set
.dim
> IPSET_DIM_MAX
) {
145 pr_warn("Protocol error: set match dimension is over the limit!\n");
146 ip_set_nfnl_put(par
->net
, info
->match_set
.index
);
154 set_match_v1_destroy(const struct xt_mtdtor_param
*par
)
156 struct xt_set_info_match_v1
*info
= par
->matchinfo
;
158 ip_set_nfnl_put(par
->net
, info
->match_set
.index
);
161 /* Revision 3 match */
164 match_counter0(u64 counter
, const struct ip_set_counter_match0
*info
)
167 case IPSET_COUNTER_NONE
:
169 case IPSET_COUNTER_EQ
:
170 return counter
== info
->value
;
171 case IPSET_COUNTER_NE
:
172 return counter
!= info
->value
;
173 case IPSET_COUNTER_LT
:
174 return counter
< info
->value
;
175 case IPSET_COUNTER_GT
:
176 return counter
> info
->value
;
182 set_match_v3(const struct sk_buff
*skb
, struct xt_action_param
*par
)
184 const struct xt_set_info_match_v3
*info
= par
->matchinfo
;
187 ADT_OPT(opt
, par
->family
, info
->match_set
.dim
,
188 info
->match_set
.flags
, info
->flags
, UINT_MAX
);
190 if (info
->packets
.op
!= IPSET_COUNTER_NONE
||
191 info
->bytes
.op
!= IPSET_COUNTER_NONE
)
192 opt
.cmdflags
|= IPSET_FLAG_MATCH_COUNTERS
;
194 ret
= match_set(info
->match_set
.index
, skb
, par
, &opt
,
195 info
->match_set
.flags
& IPSET_INV_MATCH
);
197 if (!(ret
&& opt
.cmdflags
& IPSET_FLAG_MATCH_COUNTERS
))
200 if (!match_counter0(opt
.ext
.packets
, &info
->packets
))
202 return match_counter0(opt
.ext
.bytes
, &info
->bytes
);
205 #define set_match_v3_checkentry set_match_v1_checkentry
206 #define set_match_v3_destroy set_match_v1_destroy
208 /* Revision 4 match */
211 match_counter(u64 counter
, const struct ip_set_counter_match
*info
)
214 case IPSET_COUNTER_NONE
:
216 case IPSET_COUNTER_EQ
:
217 return counter
== info
->value
;
218 case IPSET_COUNTER_NE
:
219 return counter
!= info
->value
;
220 case IPSET_COUNTER_LT
:
221 return counter
< info
->value
;
222 case IPSET_COUNTER_GT
:
223 return counter
> info
->value
;
229 set_match_v4(const struct sk_buff
*skb
, struct xt_action_param
*par
)
231 const struct xt_set_info_match_v4
*info
= par
->matchinfo
;
234 ADT_OPT(opt
, par
->family
, info
->match_set
.dim
,
235 info
->match_set
.flags
, info
->flags
, UINT_MAX
);
237 if (info
->packets
.op
!= IPSET_COUNTER_NONE
||
238 info
->bytes
.op
!= IPSET_COUNTER_NONE
)
239 opt
.cmdflags
|= IPSET_FLAG_MATCH_COUNTERS
;
241 ret
= match_set(info
->match_set
.index
, skb
, par
, &opt
,
242 info
->match_set
.flags
& IPSET_INV_MATCH
);
244 if (!(ret
&& opt
.cmdflags
& IPSET_FLAG_MATCH_COUNTERS
))
247 if (!match_counter(opt
.ext
.packets
, &info
->packets
))
249 return match_counter(opt
.ext
.bytes
, &info
->bytes
);
252 #define set_match_v4_checkentry set_match_v1_checkentry
253 #define set_match_v4_destroy set_match_v1_destroy
255 /* Revision 0 interface: backward compatible with netfilter/iptables */
258 set_target_v0(struct sk_buff
*skb
, const struct xt_action_param
*par
)
260 const struct xt_set_info_target_v0
*info
= par
->targinfo
;
262 ADT_OPT(add_opt
, par
->family
, info
->add_set
.u
.compat
.dim
,
263 info
->add_set
.u
.compat
.flags
, 0, UINT_MAX
);
264 ADT_OPT(del_opt
, par
->family
, info
->del_set
.u
.compat
.dim
,
265 info
->del_set
.u
.compat
.flags
, 0, UINT_MAX
);
267 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
268 ip_set_add(info
->add_set
.index
, skb
, par
, &add_opt
);
269 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
270 ip_set_del(info
->del_set
.index
, skb
, par
, &del_opt
);
276 set_target_v0_checkentry(const struct xt_tgchk_param
*par
)
278 struct xt_set_info_target_v0
*info
= par
->targinfo
;
281 if (info
->add_set
.index
!= IPSET_INVALID_ID
) {
282 index
= ip_set_nfnl_get_byindex(par
->net
, info
->add_set
.index
);
283 if (index
== IPSET_INVALID_ID
) {
284 pr_warn("Cannot find add_set index %u as target\n",
285 info
->add_set
.index
);
290 if (info
->del_set
.index
!= IPSET_INVALID_ID
) {
291 index
= ip_set_nfnl_get_byindex(par
->net
, info
->del_set
.index
);
292 if (index
== IPSET_INVALID_ID
) {
293 pr_warn("Cannot find del_set index %u as target\n",
294 info
->del_set
.index
);
295 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
296 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
300 if (info
->add_set
.u
.flags
[IPSET_DIM_MAX
- 1] != 0 ||
301 info
->del_set
.u
.flags
[IPSET_DIM_MAX
- 1] != 0) {
302 pr_warn("Protocol error: SET target dimension is over the limit!\n");
303 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
304 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
305 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
306 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
310 /* Fill out compatibility data */
311 compat_flags(&info
->add_set
);
312 compat_flags(&info
->del_set
);
318 set_target_v0_destroy(const struct xt_tgdtor_param
*par
)
320 const struct xt_set_info_target_v0
*info
= par
->targinfo
;
322 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
323 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
324 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
325 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
328 /* Revision 1 target */
331 set_target_v1(struct sk_buff
*skb
, const struct xt_action_param
*par
)
333 const struct xt_set_info_target_v1
*info
= par
->targinfo
;
335 ADT_OPT(add_opt
, par
->family
, info
->add_set
.dim
,
336 info
->add_set
.flags
, 0, UINT_MAX
);
337 ADT_OPT(del_opt
, par
->family
, info
->del_set
.dim
,
338 info
->del_set
.flags
, 0, UINT_MAX
);
340 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
341 ip_set_add(info
->add_set
.index
, skb
, par
, &add_opt
);
342 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
343 ip_set_del(info
->del_set
.index
, skb
, par
, &del_opt
);
349 set_target_v1_checkentry(const struct xt_tgchk_param
*par
)
351 const struct xt_set_info_target_v1
*info
= par
->targinfo
;
354 if (info
->add_set
.index
!= IPSET_INVALID_ID
) {
355 index
= ip_set_nfnl_get_byindex(par
->net
, info
->add_set
.index
);
356 if (index
== IPSET_INVALID_ID
) {
357 pr_warn("Cannot find add_set index %u as target\n",
358 info
->add_set
.index
);
363 if (info
->del_set
.index
!= IPSET_INVALID_ID
) {
364 index
= ip_set_nfnl_get_byindex(par
->net
, info
->del_set
.index
);
365 if (index
== IPSET_INVALID_ID
) {
366 pr_warn("Cannot find del_set index %u as target\n",
367 info
->del_set
.index
);
368 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
369 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
373 if (info
->add_set
.dim
> IPSET_DIM_MAX
||
374 info
->del_set
.dim
> IPSET_DIM_MAX
) {
375 pr_warn("Protocol error: SET target dimension is over the limit!\n");
376 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
377 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
378 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
379 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
387 set_target_v1_destroy(const struct xt_tgdtor_param
*par
)
389 const struct xt_set_info_target_v1
*info
= par
->targinfo
;
391 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
392 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
393 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
394 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
397 /* Revision 2 target */
400 set_target_v2(struct sk_buff
*skb
, const struct xt_action_param
*par
)
402 const struct xt_set_info_target_v2
*info
= par
->targinfo
;
404 ADT_OPT(add_opt
, par
->family
, info
->add_set
.dim
,
405 info
->add_set
.flags
, info
->flags
, info
->timeout
);
406 ADT_OPT(del_opt
, par
->family
, info
->del_set
.dim
,
407 info
->del_set
.flags
, 0, UINT_MAX
);
409 /* Normalize to fit into jiffies */
410 if (add_opt
.ext
.timeout
!= IPSET_NO_TIMEOUT
&&
411 add_opt
.ext
.timeout
> UINT_MAX
/ MSEC_PER_SEC
)
412 add_opt
.ext
.timeout
= UINT_MAX
/ MSEC_PER_SEC
;
413 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
414 ip_set_add(info
->add_set
.index
, skb
, par
, &add_opt
);
415 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
416 ip_set_del(info
->del_set
.index
, skb
, par
, &del_opt
);
421 #define set_target_v2_checkentry set_target_v1_checkentry
422 #define set_target_v2_destroy set_target_v1_destroy
424 /* Revision 3 target */
427 set_target_v3(struct sk_buff
*skb
, const struct xt_action_param
*par
)
429 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
432 ADT_OPT(add_opt
, par
->family
, info
->add_set
.dim
,
433 info
->add_set
.flags
, info
->flags
, info
->timeout
);
434 ADT_OPT(del_opt
, par
->family
, info
->del_set
.dim
,
435 info
->del_set
.flags
, 0, UINT_MAX
);
436 ADT_OPT(map_opt
, par
->family
, info
->map_set
.dim
,
437 info
->map_set
.flags
, 0, UINT_MAX
);
439 /* Normalize to fit into jiffies */
440 if (add_opt
.ext
.timeout
!= IPSET_NO_TIMEOUT
&&
441 add_opt
.ext
.timeout
> UINT_MAX
/ MSEC_PER_SEC
)
442 add_opt
.ext
.timeout
= UINT_MAX
/ MSEC_PER_SEC
;
443 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
444 ip_set_add(info
->add_set
.index
, skb
, par
, &add_opt
);
445 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
446 ip_set_del(info
->del_set
.index
, skb
, par
, &del_opt
);
447 if (info
->map_set
.index
!= IPSET_INVALID_ID
) {
448 map_opt
.cmdflags
|= info
->flags
& (IPSET_FLAG_MAP_SKBMARK
|
449 IPSET_FLAG_MAP_SKBPRIO
|
450 IPSET_FLAG_MAP_SKBQUEUE
);
451 ret
= match_set(info
->map_set
.index
, skb
, par
, &map_opt
,
452 info
->map_set
.flags
& IPSET_INV_MATCH
);
455 if (map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBMARK
)
456 skb
->mark
= (skb
->mark
& ~(map_opt
.ext
.skbmarkmask
))
457 ^ (map_opt
.ext
.skbmark
);
458 if (map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBPRIO
)
459 skb
->priority
= map_opt
.ext
.skbprio
;
460 if ((map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBQUEUE
) &&
462 skb
->dev
->real_num_tx_queues
> map_opt
.ext
.skbqueue
)
463 skb_set_queue_mapping(skb
, map_opt
.ext
.skbqueue
);
469 set_target_v3_checkentry(const struct xt_tgchk_param
*par
)
471 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
474 if (info
->add_set
.index
!= IPSET_INVALID_ID
) {
475 index
= ip_set_nfnl_get_byindex(par
->net
,
476 info
->add_set
.index
);
477 if (index
== IPSET_INVALID_ID
) {
478 pr_warn("Cannot find add_set index %u as target\n",
479 info
->add_set
.index
);
484 if (info
->del_set
.index
!= IPSET_INVALID_ID
) {
485 index
= ip_set_nfnl_get_byindex(par
->net
,
486 info
->del_set
.index
);
487 if (index
== IPSET_INVALID_ID
) {
488 pr_warn("Cannot find del_set index %u as target\n",
489 info
->del_set
.index
);
490 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
491 ip_set_nfnl_put(par
->net
,
492 info
->add_set
.index
);
497 if (info
->map_set
.index
!= IPSET_INVALID_ID
) {
498 if (strncmp(par
->table
, "mangle", 7)) {
499 pr_warn("--map-set only usable from mangle table\n");
502 if (((info
->flags
& IPSET_FLAG_MAP_SKBPRIO
) |
503 (info
->flags
& IPSET_FLAG_MAP_SKBQUEUE
)) &&
504 !(par
->hook_mask
& (1 << NF_INET_FORWARD
|
505 1 << NF_INET_LOCAL_OUT
|
506 1 << NF_INET_POST_ROUTING
))) {
507 pr_warn("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
510 index
= ip_set_nfnl_get_byindex(par
->net
,
511 info
->map_set
.index
);
512 if (index
== IPSET_INVALID_ID
) {
513 pr_warn("Cannot find map_set index %u as target\n",
514 info
->map_set
.index
);
515 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
516 ip_set_nfnl_put(par
->net
,
517 info
->add_set
.index
);
518 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
519 ip_set_nfnl_put(par
->net
,
520 info
->del_set
.index
);
525 if (info
->add_set
.dim
> IPSET_DIM_MAX
||
526 info
->del_set
.dim
> IPSET_DIM_MAX
||
527 info
->map_set
.dim
> IPSET_DIM_MAX
) {
528 pr_warn("Protocol error: SET target dimension is over the limit!\n");
529 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
530 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
531 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
532 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
533 if (info
->map_set
.index
!= IPSET_INVALID_ID
)
534 ip_set_nfnl_put(par
->net
, info
->map_set
.index
);
542 set_target_v3_destroy(const struct xt_tgdtor_param
*par
)
544 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
546 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
547 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
548 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
549 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
550 if (info
->map_set
.index
!= IPSET_INVALID_ID
)
551 ip_set_nfnl_put(par
->net
, info
->map_set
.index
);
554 static struct xt_match set_matches
[] __read_mostly
= {
557 .family
= NFPROTO_IPV4
,
559 .match
= set_match_v0
,
560 .matchsize
= sizeof(struct xt_set_info_match_v0
),
561 .checkentry
= set_match_v0_checkentry
,
562 .destroy
= set_match_v0_destroy
,
567 .family
= NFPROTO_IPV4
,
569 .match
= set_match_v1
,
570 .matchsize
= sizeof(struct xt_set_info_match_v1
),
571 .checkentry
= set_match_v1_checkentry
,
572 .destroy
= set_match_v1_destroy
,
577 .family
= NFPROTO_IPV6
,
579 .match
= set_match_v1
,
580 .matchsize
= sizeof(struct xt_set_info_match_v1
),
581 .checkentry
= set_match_v1_checkentry
,
582 .destroy
= set_match_v1_destroy
,
585 /* --return-nomatch flag support */
588 .family
= NFPROTO_IPV4
,
590 .match
= set_match_v1
,
591 .matchsize
= sizeof(struct xt_set_info_match_v1
),
592 .checkentry
= set_match_v1_checkentry
,
593 .destroy
= set_match_v1_destroy
,
598 .family
= NFPROTO_IPV6
,
600 .match
= set_match_v1
,
601 .matchsize
= sizeof(struct xt_set_info_match_v1
),
602 .checkentry
= set_match_v1_checkentry
,
603 .destroy
= set_match_v1_destroy
,
606 /* counters support: update, match */
609 .family
= NFPROTO_IPV4
,
611 .match
= set_match_v3
,
612 .matchsize
= sizeof(struct xt_set_info_match_v3
),
613 .checkentry
= set_match_v3_checkentry
,
614 .destroy
= set_match_v3_destroy
,
619 .family
= NFPROTO_IPV6
,
621 .match
= set_match_v3
,
622 .matchsize
= sizeof(struct xt_set_info_match_v3
),
623 .checkentry
= set_match_v3_checkentry
,
624 .destroy
= set_match_v3_destroy
,
627 /* new revision for counters support: update, match */
630 .family
= NFPROTO_IPV4
,
632 .match
= set_match_v4
,
633 .matchsize
= sizeof(struct xt_set_info_match_v4
),
634 .checkentry
= set_match_v4_checkentry
,
635 .destroy
= set_match_v4_destroy
,
640 .family
= NFPROTO_IPV6
,
642 .match
= set_match_v4
,
643 .matchsize
= sizeof(struct xt_set_info_match_v4
),
644 .checkentry
= set_match_v4_checkentry
,
645 .destroy
= set_match_v4_destroy
,
650 static struct xt_target set_targets
[] __read_mostly
= {
654 .family
= NFPROTO_IPV4
,
655 .target
= set_target_v0
,
656 .targetsize
= sizeof(struct xt_set_info_target_v0
),
657 .checkentry
= set_target_v0_checkentry
,
658 .destroy
= set_target_v0_destroy
,
664 .family
= NFPROTO_IPV4
,
665 .target
= set_target_v1
,
666 .targetsize
= sizeof(struct xt_set_info_target_v1
),
667 .checkentry
= set_target_v1_checkentry
,
668 .destroy
= set_target_v1_destroy
,
674 .family
= NFPROTO_IPV6
,
675 .target
= set_target_v1
,
676 .targetsize
= sizeof(struct xt_set_info_target_v1
),
677 .checkentry
= set_target_v1_checkentry
,
678 .destroy
= set_target_v1_destroy
,
681 /* --timeout and --exist flags support */
685 .family
= NFPROTO_IPV4
,
686 .target
= set_target_v2
,
687 .targetsize
= sizeof(struct xt_set_info_target_v2
),
688 .checkentry
= set_target_v2_checkentry
,
689 .destroy
= set_target_v2_destroy
,
695 .family
= NFPROTO_IPV6
,
696 .target
= set_target_v2
,
697 .targetsize
= sizeof(struct xt_set_info_target_v2
),
698 .checkentry
= set_target_v2_checkentry
,
699 .destroy
= set_target_v2_destroy
,
702 /* --map-set support */
706 .family
= NFPROTO_IPV4
,
707 .target
= set_target_v3
,
708 .targetsize
= sizeof(struct xt_set_info_target_v3
),
709 .checkentry
= set_target_v3_checkentry
,
710 .destroy
= set_target_v3_destroy
,
716 .family
= NFPROTO_IPV6
,
717 .target
= set_target_v3
,
718 .targetsize
= sizeof(struct xt_set_info_target_v3
),
719 .checkentry
= set_target_v3_checkentry
,
720 .destroy
= set_target_v3_destroy
,
725 static int __init
xt_set_init(void)
727 int ret
= xt_register_matches(set_matches
, ARRAY_SIZE(set_matches
));
730 ret
= xt_register_targets(set_targets
,
731 ARRAY_SIZE(set_targets
));
733 xt_unregister_matches(set_matches
,
734 ARRAY_SIZE(set_matches
));
739 static void __exit
xt_set_fini(void)
741 xt_unregister_matches(set_matches
, ARRAY_SIZE(set_matches
));
742 xt_unregister_targets(set_targets
, ARRAY_SIZE(set_targets
));
745 module_init(xt_set_init
);
746 module_exit(xt_set_fini
);