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
, xt_family(par
), 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
, xt_family(par
), 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
, xt_family(par
), 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
, xt_family(par
), 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
, xt_family(par
), info
->add_set
.u
.compat
.dim
,
263 info
->add_set
.u
.compat
.flags
, 0, UINT_MAX
);
264 ADT_OPT(del_opt
, xt_family(par
), 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
, xt_family(par
), info
->add_set
.dim
,
336 info
->add_set
.flags
, 0, UINT_MAX
);
337 ADT_OPT(del_opt
, xt_family(par
), 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
, xt_family(par
), info
->add_set
.dim
,
405 info
->add_set
.flags
, info
->flags
, info
->timeout
);
406 ADT_OPT(del_opt
, xt_family(par
), 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 */
426 #define MOPT(opt, member) ((opt).ext.skbinfo.member)
429 set_target_v3(struct sk_buff
*skb
, const struct xt_action_param
*par
)
431 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
434 ADT_OPT(add_opt
, xt_family(par
), info
->add_set
.dim
,
435 info
->add_set
.flags
, info
->flags
, info
->timeout
);
436 ADT_OPT(del_opt
, xt_family(par
), info
->del_set
.dim
,
437 info
->del_set
.flags
, 0, UINT_MAX
);
438 ADT_OPT(map_opt
, xt_family(par
), info
->map_set
.dim
,
439 info
->map_set
.flags
, 0, UINT_MAX
);
441 /* Normalize to fit into jiffies */
442 if (add_opt
.ext
.timeout
!= IPSET_NO_TIMEOUT
&&
443 add_opt
.ext
.timeout
> UINT_MAX
/ MSEC_PER_SEC
)
444 add_opt
.ext
.timeout
= UINT_MAX
/ MSEC_PER_SEC
;
445 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
446 ip_set_add(info
->add_set
.index
, skb
, par
, &add_opt
);
447 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
448 ip_set_del(info
->del_set
.index
, skb
, par
, &del_opt
);
449 if (info
->map_set
.index
!= IPSET_INVALID_ID
) {
450 map_opt
.cmdflags
|= info
->flags
& (IPSET_FLAG_MAP_SKBMARK
|
451 IPSET_FLAG_MAP_SKBPRIO
|
452 IPSET_FLAG_MAP_SKBQUEUE
);
453 ret
= match_set(info
->map_set
.index
, skb
, par
, &map_opt
,
454 info
->map_set
.flags
& IPSET_INV_MATCH
);
457 if (map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBMARK
)
458 skb
->mark
= (skb
->mark
& ~MOPT(map_opt
,skbmarkmask
))
459 ^ MOPT(map_opt
, skbmark
);
460 if (map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBPRIO
)
461 skb
->priority
= MOPT(map_opt
, skbprio
);
462 if ((map_opt
.cmdflags
& IPSET_FLAG_MAP_SKBQUEUE
) &&
464 skb
->dev
->real_num_tx_queues
> MOPT(map_opt
, skbqueue
))
465 skb_set_queue_mapping(skb
, MOPT(map_opt
, skbqueue
));
471 set_target_v3_checkentry(const struct xt_tgchk_param
*par
)
473 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
476 if (info
->add_set
.index
!= IPSET_INVALID_ID
) {
477 index
= ip_set_nfnl_get_byindex(par
->net
,
478 info
->add_set
.index
);
479 if (index
== IPSET_INVALID_ID
) {
480 pr_warn("Cannot find add_set index %u as target\n",
481 info
->add_set
.index
);
486 if (info
->del_set
.index
!= IPSET_INVALID_ID
) {
487 index
= ip_set_nfnl_get_byindex(par
->net
,
488 info
->del_set
.index
);
489 if (index
== IPSET_INVALID_ID
) {
490 pr_warn("Cannot find del_set index %u as target\n",
491 info
->del_set
.index
);
492 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
493 ip_set_nfnl_put(par
->net
,
494 info
->add_set
.index
);
499 if (info
->map_set
.index
!= IPSET_INVALID_ID
) {
500 if (strncmp(par
->table
, "mangle", 7)) {
501 pr_warn("--map-set only usable from mangle table\n");
504 if (((info
->flags
& IPSET_FLAG_MAP_SKBPRIO
) |
505 (info
->flags
& IPSET_FLAG_MAP_SKBQUEUE
)) &&
506 !(par
->hook_mask
& (1 << NF_INET_FORWARD
|
507 1 << NF_INET_LOCAL_OUT
|
508 1 << NF_INET_POST_ROUTING
))) {
509 pr_warn("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
512 index
= ip_set_nfnl_get_byindex(par
->net
,
513 info
->map_set
.index
);
514 if (index
== IPSET_INVALID_ID
) {
515 pr_warn("Cannot find map_set index %u as target\n",
516 info
->map_set
.index
);
517 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
518 ip_set_nfnl_put(par
->net
,
519 info
->add_set
.index
);
520 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
521 ip_set_nfnl_put(par
->net
,
522 info
->del_set
.index
);
527 if (info
->add_set
.dim
> IPSET_DIM_MAX
||
528 info
->del_set
.dim
> IPSET_DIM_MAX
||
529 info
->map_set
.dim
> IPSET_DIM_MAX
) {
530 pr_warn("Protocol error: SET target dimension is over the limit!\n");
531 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
532 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
533 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
534 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
535 if (info
->map_set
.index
!= IPSET_INVALID_ID
)
536 ip_set_nfnl_put(par
->net
, info
->map_set
.index
);
544 set_target_v3_destroy(const struct xt_tgdtor_param
*par
)
546 const struct xt_set_info_target_v3
*info
= par
->targinfo
;
548 if (info
->add_set
.index
!= IPSET_INVALID_ID
)
549 ip_set_nfnl_put(par
->net
, info
->add_set
.index
);
550 if (info
->del_set
.index
!= IPSET_INVALID_ID
)
551 ip_set_nfnl_put(par
->net
, info
->del_set
.index
);
552 if (info
->map_set
.index
!= IPSET_INVALID_ID
)
553 ip_set_nfnl_put(par
->net
, info
->map_set
.index
);
556 static struct xt_match set_matches
[] __read_mostly
= {
559 .family
= NFPROTO_IPV4
,
561 .match
= set_match_v0
,
562 .matchsize
= sizeof(struct xt_set_info_match_v0
),
563 .checkentry
= set_match_v0_checkentry
,
564 .destroy
= set_match_v0_destroy
,
569 .family
= NFPROTO_IPV4
,
571 .match
= set_match_v1
,
572 .matchsize
= sizeof(struct xt_set_info_match_v1
),
573 .checkentry
= set_match_v1_checkentry
,
574 .destroy
= set_match_v1_destroy
,
579 .family
= NFPROTO_IPV6
,
581 .match
= set_match_v1
,
582 .matchsize
= sizeof(struct xt_set_info_match_v1
),
583 .checkentry
= set_match_v1_checkentry
,
584 .destroy
= set_match_v1_destroy
,
587 /* --return-nomatch flag support */
590 .family
= NFPROTO_IPV4
,
592 .match
= set_match_v1
,
593 .matchsize
= sizeof(struct xt_set_info_match_v1
),
594 .checkentry
= set_match_v1_checkentry
,
595 .destroy
= set_match_v1_destroy
,
600 .family
= NFPROTO_IPV6
,
602 .match
= set_match_v1
,
603 .matchsize
= sizeof(struct xt_set_info_match_v1
),
604 .checkentry
= set_match_v1_checkentry
,
605 .destroy
= set_match_v1_destroy
,
608 /* counters support: update, match */
611 .family
= NFPROTO_IPV4
,
613 .match
= set_match_v3
,
614 .matchsize
= sizeof(struct xt_set_info_match_v3
),
615 .checkentry
= set_match_v3_checkentry
,
616 .destroy
= set_match_v3_destroy
,
621 .family
= NFPROTO_IPV6
,
623 .match
= set_match_v3
,
624 .matchsize
= sizeof(struct xt_set_info_match_v3
),
625 .checkentry
= set_match_v3_checkentry
,
626 .destroy
= set_match_v3_destroy
,
629 /* new revision for counters support: update, match */
632 .family
= NFPROTO_IPV4
,
634 .match
= set_match_v4
,
635 .matchsize
= sizeof(struct xt_set_info_match_v4
),
636 .checkentry
= set_match_v4_checkentry
,
637 .destroy
= set_match_v4_destroy
,
642 .family
= NFPROTO_IPV6
,
644 .match
= set_match_v4
,
645 .matchsize
= sizeof(struct xt_set_info_match_v4
),
646 .checkentry
= set_match_v4_checkentry
,
647 .destroy
= set_match_v4_destroy
,
652 static struct xt_target set_targets
[] __read_mostly
= {
656 .family
= NFPROTO_IPV4
,
657 .target
= set_target_v0
,
658 .targetsize
= sizeof(struct xt_set_info_target_v0
),
659 .checkentry
= set_target_v0_checkentry
,
660 .destroy
= set_target_v0_destroy
,
666 .family
= NFPROTO_IPV4
,
667 .target
= set_target_v1
,
668 .targetsize
= sizeof(struct xt_set_info_target_v1
),
669 .checkentry
= set_target_v1_checkentry
,
670 .destroy
= set_target_v1_destroy
,
676 .family
= NFPROTO_IPV6
,
677 .target
= set_target_v1
,
678 .targetsize
= sizeof(struct xt_set_info_target_v1
),
679 .checkentry
= set_target_v1_checkentry
,
680 .destroy
= set_target_v1_destroy
,
683 /* --timeout and --exist flags support */
687 .family
= NFPROTO_IPV4
,
688 .target
= set_target_v2
,
689 .targetsize
= sizeof(struct xt_set_info_target_v2
),
690 .checkentry
= set_target_v2_checkentry
,
691 .destroy
= set_target_v2_destroy
,
697 .family
= NFPROTO_IPV6
,
698 .target
= set_target_v2
,
699 .targetsize
= sizeof(struct xt_set_info_target_v2
),
700 .checkentry
= set_target_v2_checkentry
,
701 .destroy
= set_target_v2_destroy
,
704 /* --map-set support */
708 .family
= NFPROTO_IPV4
,
709 .target
= set_target_v3
,
710 .targetsize
= sizeof(struct xt_set_info_target_v3
),
711 .checkentry
= set_target_v3_checkentry
,
712 .destroy
= set_target_v3_destroy
,
718 .family
= NFPROTO_IPV6
,
719 .target
= set_target_v3
,
720 .targetsize
= sizeof(struct xt_set_info_target_v3
),
721 .checkentry
= set_target_v3_checkentry
,
722 .destroy
= set_target_v3_destroy
,
727 static int __init
xt_set_init(void)
729 int ret
= xt_register_matches(set_matches
, ARRAY_SIZE(set_matches
));
732 ret
= xt_register_targets(set_targets
,
733 ARRAY_SIZE(set_targets
));
735 xt_unregister_matches(set_matches
,
736 ARRAY_SIZE(set_matches
));
741 static void __exit
xt_set_fini(void)
743 xt_unregister_matches(set_matches
, ARRAY_SIZE(set_matches
));
744 xt_unregister_targets(set_targets
, ARRAY_SIZE(set_targets
));
747 module_init(xt_set_init
);
748 module_exit(xt_set_fini
);