Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[deliverable/linux.git] / net / netfilter / xt_set.c
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>
5 *
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.
9 */
10
11 /* Kernel module which implements the set match and SET target
12 * for netfilter/iptables. */
13
14 #include <linux/module.h>
15 #include <linux/skbuff.h>
16
17 #include <linux/netfilter/x_tables.h>
18 #include <linux/netfilter/ipset/ip_set.h>
19 #include <linux/netfilter/ipset/ip_set_timeout.h>
20 #include <uapi/linux/netfilter/xt_set.h>
21
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
24 MODULE_DESCRIPTION("Xtables: IP set match and target module");
25 MODULE_ALIAS("xt_SET");
26 MODULE_ALIAS("ipt_set");
27 MODULE_ALIAS("ip6t_set");
28 MODULE_ALIAS("ipt_SET");
29 MODULE_ALIAS("ip6t_SET");
30
31 static inline int
32 match_set(ip_set_id_t index, const struct sk_buff *skb,
33 const struct xt_action_param *par,
34 struct ip_set_adt_opt *opt, int inv)
35 {
36 if (ip_set_test(index, skb, par, opt))
37 inv = !inv;
38 return inv;
39 }
40
41 #define ADT_OPT(n, f, d, fs, cfs, t) \
42 struct ip_set_adt_opt n = { \
43 .family = f, \
44 .dim = d, \
45 .flags = fs, \
46 .cmdflags = cfs, \
47 .ext.timeout = t, \
48 }
49
50 /* Revision 0 interface: backward compatible with netfilter/iptables */
51
52 static bool
53 set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
54 {
55 const struct xt_set_info_match_v0 *info = par->matchinfo;
56 ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
57 info->match_set.u.compat.flags, 0, UINT_MAX);
58
59 return match_set(info->match_set.index, skb, par, &opt,
60 info->match_set.u.compat.flags & IPSET_INV_MATCH);
61 }
62
63 static void
64 compat_flags(struct xt_set_info_v0 *info)
65 {
66 u_int8_t i;
67
68 /* Fill out compatibility data according to enum ip_set_kopt */
69 info->u.compat.dim = IPSET_DIM_ZERO;
70 if (info->u.flags[0] & IPSET_MATCH_INV)
71 info->u.compat.flags |= IPSET_INV_MATCH;
72 for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) {
73 info->u.compat.dim++;
74 if (info->u.flags[i] & IPSET_SRC)
75 info->u.compat.flags |= (1<<info->u.compat.dim);
76 }
77 }
78
79 static int
80 set_match_v0_checkentry(const struct xt_mtchk_param *par)
81 {
82 struct xt_set_info_match_v0 *info = par->matchinfo;
83 ip_set_id_t index;
84
85 index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
86
87 if (index == IPSET_INVALID_ID) {
88 pr_warn("Cannot find set identified by id %u to match\n",
89 info->match_set.index);
90 return -ENOENT;
91 }
92 if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
93 pr_warn("Protocol error: set match dimension is over the limit!\n");
94 ip_set_nfnl_put(par->net, info->match_set.index);
95 return -ERANGE;
96 }
97
98 /* Fill out compatibility data */
99 compat_flags(&info->match_set);
100
101 return 0;
102 }
103
104 static void
105 set_match_v0_destroy(const struct xt_mtdtor_param *par)
106 {
107 struct xt_set_info_match_v0 *info = par->matchinfo;
108
109 ip_set_nfnl_put(par->net, info->match_set.index);
110 }
111
112 /* Revision 1 match */
113
114 static bool
115 set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
116 {
117 const struct xt_set_info_match_v1 *info = par->matchinfo;
118 ADT_OPT(opt, par->family, info->match_set.dim,
119 info->match_set.flags, 0, UINT_MAX);
120
121 if (opt.flags & IPSET_RETURN_NOMATCH)
122 opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
123
124 return match_set(info->match_set.index, skb, par, &opt,
125 info->match_set.flags & IPSET_INV_MATCH);
126 }
127
128 static int
129 set_match_v1_checkentry(const struct xt_mtchk_param *par)
130 {
131 struct xt_set_info_match_v1 *info = par->matchinfo;
132 ip_set_id_t index;
133
134 index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
135
136 if (index == IPSET_INVALID_ID) {
137 pr_warn("Cannot find set identified by id %u to match\n",
138 info->match_set.index);
139 return -ENOENT;
140 }
141 if (info->match_set.dim > IPSET_DIM_MAX) {
142 pr_warn("Protocol error: set match dimension is over the limit!\n");
143 ip_set_nfnl_put(par->net, info->match_set.index);
144 return -ERANGE;
145 }
146
147 return 0;
148 }
149
150 static void
151 set_match_v1_destroy(const struct xt_mtdtor_param *par)
152 {
153 struct xt_set_info_match_v1 *info = par->matchinfo;
154
155 ip_set_nfnl_put(par->net, info->match_set.index);
156 }
157
158 /* Revision 3 match */
159
160 static bool
161 match_counter0(u64 counter, const struct ip_set_counter_match0 *info)
162 {
163 switch (info->op) {
164 case IPSET_COUNTER_NONE:
165 return true;
166 case IPSET_COUNTER_EQ:
167 return counter == info->value;
168 case IPSET_COUNTER_NE:
169 return counter != info->value;
170 case IPSET_COUNTER_LT:
171 return counter < info->value;
172 case IPSET_COUNTER_GT:
173 return counter > info->value;
174 }
175 return false;
176 }
177
178 static bool
179 set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
180 {
181 const struct xt_set_info_match_v3 *info = par->matchinfo;
182 ADT_OPT(opt, par->family, info->match_set.dim,
183 info->match_set.flags, info->flags, UINT_MAX);
184 int ret;
185
186 if (info->packets.op != IPSET_COUNTER_NONE ||
187 info->bytes.op != IPSET_COUNTER_NONE)
188 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
189
190 ret = match_set(info->match_set.index, skb, par, &opt,
191 info->match_set.flags & IPSET_INV_MATCH);
192
193 if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS))
194 return ret;
195
196 if (!match_counter0(opt.ext.packets, &info->packets))
197 return false;
198 return match_counter0(opt.ext.bytes, &info->bytes);
199 }
200
201 #define set_match_v3_checkentry set_match_v1_checkentry
202 #define set_match_v3_destroy set_match_v1_destroy
203
204 /* Revision 4 match */
205
206 static bool
207 match_counter(u64 counter, const struct ip_set_counter_match *info)
208 {
209 switch (info->op) {
210 case IPSET_COUNTER_NONE:
211 return true;
212 case IPSET_COUNTER_EQ:
213 return counter == info->value;
214 case IPSET_COUNTER_NE:
215 return counter != info->value;
216 case IPSET_COUNTER_LT:
217 return counter < info->value;
218 case IPSET_COUNTER_GT:
219 return counter > info->value;
220 }
221 return false;
222 }
223
224 static bool
225 set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
226 {
227 const struct xt_set_info_match_v4 *info = par->matchinfo;
228 ADT_OPT(opt, par->family, info->match_set.dim,
229 info->match_set.flags, info->flags, UINT_MAX);
230 int ret;
231
232 if (info->packets.op != IPSET_COUNTER_NONE ||
233 info->bytes.op != IPSET_COUNTER_NONE)
234 opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
235
236 ret = match_set(info->match_set.index, skb, par, &opt,
237 info->match_set.flags & IPSET_INV_MATCH);
238
239 if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS))
240 return ret;
241
242 if (!match_counter(opt.ext.packets, &info->packets))
243 return false;
244 return match_counter(opt.ext.bytes, &info->bytes);
245 }
246
247 #define set_match_v4_checkentry set_match_v1_checkentry
248 #define set_match_v4_destroy set_match_v1_destroy
249
250 /* Revision 0 interface: backward compatible with netfilter/iptables */
251
252 static unsigned int
253 set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
254 {
255 const struct xt_set_info_target_v0 *info = par->targinfo;
256 ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
257 info->add_set.u.compat.flags, 0, UINT_MAX);
258 ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
259 info->del_set.u.compat.flags, 0, UINT_MAX);
260
261 if (info->add_set.index != IPSET_INVALID_ID)
262 ip_set_add(info->add_set.index, skb, par, &add_opt);
263 if (info->del_set.index != IPSET_INVALID_ID)
264 ip_set_del(info->del_set.index, skb, par, &del_opt);
265
266 return XT_CONTINUE;
267 }
268
269 static int
270 set_target_v0_checkentry(const struct xt_tgchk_param *par)
271 {
272 struct xt_set_info_target_v0 *info = par->targinfo;
273 ip_set_id_t index;
274
275 if (info->add_set.index != IPSET_INVALID_ID) {
276 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
277 if (index == IPSET_INVALID_ID) {
278 pr_warn("Cannot find add_set index %u as target\n",
279 info->add_set.index);
280 return -ENOENT;
281 }
282 }
283
284 if (info->del_set.index != IPSET_INVALID_ID) {
285 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
286 if (index == IPSET_INVALID_ID) {
287 pr_warn("Cannot find del_set index %u as target\n",
288 info->del_set.index);
289 if (info->add_set.index != IPSET_INVALID_ID)
290 ip_set_nfnl_put(par->net, info->add_set.index);
291 return -ENOENT;
292 }
293 }
294 if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
295 info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
296 pr_warn("Protocol error: SET target dimension is over the limit!\n");
297 if (info->add_set.index != IPSET_INVALID_ID)
298 ip_set_nfnl_put(par->net, info->add_set.index);
299 if (info->del_set.index != IPSET_INVALID_ID)
300 ip_set_nfnl_put(par->net, info->del_set.index);
301 return -ERANGE;
302 }
303
304 /* Fill out compatibility data */
305 compat_flags(&info->add_set);
306 compat_flags(&info->del_set);
307
308 return 0;
309 }
310
311 static void
312 set_target_v0_destroy(const struct xt_tgdtor_param *par)
313 {
314 const struct xt_set_info_target_v0 *info = par->targinfo;
315
316 if (info->add_set.index != IPSET_INVALID_ID)
317 ip_set_nfnl_put(par->net, info->add_set.index);
318 if (info->del_set.index != IPSET_INVALID_ID)
319 ip_set_nfnl_put(par->net, info->del_set.index);
320 }
321
322 /* Revision 1 target */
323
324 static unsigned int
325 set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
326 {
327 const struct xt_set_info_target_v1 *info = par->targinfo;
328 ADT_OPT(add_opt, par->family, info->add_set.dim,
329 info->add_set.flags, 0, UINT_MAX);
330 ADT_OPT(del_opt, par->family, info->del_set.dim,
331 info->del_set.flags, 0, UINT_MAX);
332
333 if (info->add_set.index != IPSET_INVALID_ID)
334 ip_set_add(info->add_set.index, skb, par, &add_opt);
335 if (info->del_set.index != IPSET_INVALID_ID)
336 ip_set_del(info->del_set.index, skb, par, &del_opt);
337
338 return XT_CONTINUE;
339 }
340
341 static int
342 set_target_v1_checkentry(const struct xt_tgchk_param *par)
343 {
344 const struct xt_set_info_target_v1 *info = par->targinfo;
345 ip_set_id_t index;
346
347 if (info->add_set.index != IPSET_INVALID_ID) {
348 index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
349 if (index == IPSET_INVALID_ID) {
350 pr_warn("Cannot find add_set index %u as target\n",
351 info->add_set.index);
352 return -ENOENT;
353 }
354 }
355
356 if (info->del_set.index != IPSET_INVALID_ID) {
357 index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
358 if (index == IPSET_INVALID_ID) {
359 pr_warn("Cannot find del_set index %u as target\n",
360 info->del_set.index);
361 if (info->add_set.index != IPSET_INVALID_ID)
362 ip_set_nfnl_put(par->net, info->add_set.index);
363 return -ENOENT;
364 }
365 }
366 if (info->add_set.dim > IPSET_DIM_MAX ||
367 info->del_set.dim > IPSET_DIM_MAX) {
368 pr_warn("Protocol error: SET target dimension is over the limit!\n");
369 if (info->add_set.index != IPSET_INVALID_ID)
370 ip_set_nfnl_put(par->net, info->add_set.index);
371 if (info->del_set.index != IPSET_INVALID_ID)
372 ip_set_nfnl_put(par->net, info->del_set.index);
373 return -ERANGE;
374 }
375
376 return 0;
377 }
378
379 static void
380 set_target_v1_destroy(const struct xt_tgdtor_param *par)
381 {
382 const struct xt_set_info_target_v1 *info = par->targinfo;
383
384 if (info->add_set.index != IPSET_INVALID_ID)
385 ip_set_nfnl_put(par->net, info->add_set.index);
386 if (info->del_set.index != IPSET_INVALID_ID)
387 ip_set_nfnl_put(par->net, info->del_set.index);
388 }
389
390 /* Revision 2 target */
391
392 static unsigned int
393 set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
394 {
395 const struct xt_set_info_target_v2 *info = par->targinfo;
396 ADT_OPT(add_opt, par->family, info->add_set.dim,
397 info->add_set.flags, info->flags, info->timeout);
398 ADT_OPT(del_opt, par->family, info->del_set.dim,
399 info->del_set.flags, 0, UINT_MAX);
400
401 /* Normalize to fit into jiffies */
402 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
403 add_opt.ext.timeout > UINT_MAX/MSEC_PER_SEC)
404 add_opt.ext.timeout = UINT_MAX/MSEC_PER_SEC;
405 if (info->add_set.index != IPSET_INVALID_ID)
406 ip_set_add(info->add_set.index, skb, par, &add_opt);
407 if (info->del_set.index != IPSET_INVALID_ID)
408 ip_set_del(info->del_set.index, skb, par, &del_opt);
409
410 return XT_CONTINUE;
411 }
412
413 #define set_target_v2_checkentry set_target_v1_checkentry
414 #define set_target_v2_destroy set_target_v1_destroy
415
416 /* Revision 3 target */
417
418 static unsigned int
419 set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
420 {
421 const struct xt_set_info_target_v3 *info = par->targinfo;
422 ADT_OPT(add_opt, par->family, info->add_set.dim,
423 info->add_set.flags, info->flags, info->timeout);
424 ADT_OPT(del_opt, par->family, info->del_set.dim,
425 info->del_set.flags, 0, UINT_MAX);
426 ADT_OPT(map_opt, par->family, info->map_set.dim,
427 info->map_set.flags, 0, UINT_MAX);
428
429 int ret;
430
431 /* Normalize to fit into jiffies */
432 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
433 add_opt.ext.timeout > UINT_MAX/MSEC_PER_SEC)
434 add_opt.ext.timeout = UINT_MAX/MSEC_PER_SEC;
435 if (info->add_set.index != IPSET_INVALID_ID)
436 ip_set_add(info->add_set.index, skb, par, &add_opt);
437 if (info->del_set.index != IPSET_INVALID_ID)
438 ip_set_del(info->del_set.index, skb, par, &del_opt);
439 if (info->map_set.index != IPSET_INVALID_ID) {
440 map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
441 IPSET_FLAG_MAP_SKBPRIO |
442 IPSET_FLAG_MAP_SKBQUEUE);
443 ret = match_set(info->map_set.index, skb, par, &map_opt,
444 info->map_set.flags & IPSET_INV_MATCH);
445 if (!ret)
446 return XT_CONTINUE;
447 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
448 skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
449 ^ (map_opt.ext.skbmark);
450 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
451 skb->priority = map_opt.ext.skbprio;
452 if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
453 skb->dev &&
454 skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
455 skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
456 }
457 return XT_CONTINUE;
458 }
459
460
461 static int
462 set_target_v3_checkentry(const struct xt_tgchk_param *par)
463 {
464 const struct xt_set_info_target_v3 *info = par->targinfo;
465 ip_set_id_t index;
466
467 if (info->add_set.index != IPSET_INVALID_ID) {
468 index = ip_set_nfnl_get_byindex(par->net,
469 info->add_set.index);
470 if (index == IPSET_INVALID_ID) {
471 pr_warn("Cannot find add_set index %u as target\n",
472 info->add_set.index);
473 return -ENOENT;
474 }
475 }
476
477 if (info->del_set.index != IPSET_INVALID_ID) {
478 index = ip_set_nfnl_get_byindex(par->net,
479 info->del_set.index);
480 if (index == IPSET_INVALID_ID) {
481 pr_warn("Cannot find del_set index %u as target\n",
482 info->del_set.index);
483 if (info->add_set.index != IPSET_INVALID_ID)
484 ip_set_nfnl_put(par->net,
485 info->add_set.index);
486 return -ENOENT;
487 }
488 }
489
490 if (info->map_set.index != IPSET_INVALID_ID) {
491 if (strncmp(par->table, "mangle", 7)) {
492 pr_warn("--map-set only usable from mangle table\n");
493 return -EINVAL;
494 }
495 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
496 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
497 !(par->hook_mask & (1 << NF_INET_FORWARD |
498 1 << NF_INET_LOCAL_OUT |
499 1 << NF_INET_POST_ROUTING))) {
500 pr_warn("mapping of prio or/and queue is allowed only"
501 "from OUTPUT/FORWARD/POSTROUTING chains\n");
502 return -EINVAL;
503 }
504 index = ip_set_nfnl_get_byindex(par->net,
505 info->map_set.index);
506 if (index == IPSET_INVALID_ID) {
507 pr_warn("Cannot find map_set index %u as target\n",
508 info->map_set.index);
509 if (info->add_set.index != IPSET_INVALID_ID)
510 ip_set_nfnl_put(par->net,
511 info->add_set.index);
512 if (info->del_set.index != IPSET_INVALID_ID)
513 ip_set_nfnl_put(par->net,
514 info->del_set.index);
515 return -ENOENT;
516 }
517 }
518
519 if (info->add_set.dim > IPSET_DIM_MAX ||
520 info->del_set.dim > IPSET_DIM_MAX ||
521 info->map_set.dim > IPSET_DIM_MAX) {
522 pr_warn("Protocol error: SET target dimension "
523 "is over the limit!\n");
524 if (info->add_set.index != IPSET_INVALID_ID)
525 ip_set_nfnl_put(par->net, info->add_set.index);
526 if (info->del_set.index != IPSET_INVALID_ID)
527 ip_set_nfnl_put(par->net, info->del_set.index);
528 if (info->map_set.index != IPSET_INVALID_ID)
529 ip_set_nfnl_put(par->net, info->map_set.index);
530 return -ERANGE;
531 }
532
533 return 0;
534 }
535
536 static void
537 set_target_v3_destroy(const struct xt_tgdtor_param *par)
538 {
539 const struct xt_set_info_target_v3 *info = par->targinfo;
540
541 if (info->add_set.index != IPSET_INVALID_ID)
542 ip_set_nfnl_put(par->net, info->add_set.index);
543 if (info->del_set.index != IPSET_INVALID_ID)
544 ip_set_nfnl_put(par->net, info->del_set.index);
545 if (info->map_set.index != IPSET_INVALID_ID)
546 ip_set_nfnl_put(par->net, info->map_set.index);
547 }
548
549
550 static struct xt_match set_matches[] __read_mostly = {
551 {
552 .name = "set",
553 .family = NFPROTO_IPV4,
554 .revision = 0,
555 .match = set_match_v0,
556 .matchsize = sizeof(struct xt_set_info_match_v0),
557 .checkentry = set_match_v0_checkentry,
558 .destroy = set_match_v0_destroy,
559 .me = THIS_MODULE
560 },
561 {
562 .name = "set",
563 .family = NFPROTO_IPV4,
564 .revision = 1,
565 .match = set_match_v1,
566 .matchsize = sizeof(struct xt_set_info_match_v1),
567 .checkentry = set_match_v1_checkentry,
568 .destroy = set_match_v1_destroy,
569 .me = THIS_MODULE
570 },
571 {
572 .name = "set",
573 .family = NFPROTO_IPV6,
574 .revision = 1,
575 .match = set_match_v1,
576 .matchsize = sizeof(struct xt_set_info_match_v1),
577 .checkentry = set_match_v1_checkentry,
578 .destroy = set_match_v1_destroy,
579 .me = THIS_MODULE
580 },
581 /* --return-nomatch flag support */
582 {
583 .name = "set",
584 .family = NFPROTO_IPV4,
585 .revision = 2,
586 .match = set_match_v1,
587 .matchsize = sizeof(struct xt_set_info_match_v1),
588 .checkentry = set_match_v1_checkentry,
589 .destroy = set_match_v1_destroy,
590 .me = THIS_MODULE
591 },
592 {
593 .name = "set",
594 .family = NFPROTO_IPV6,
595 .revision = 2,
596 .match = set_match_v1,
597 .matchsize = sizeof(struct xt_set_info_match_v1),
598 .checkentry = set_match_v1_checkentry,
599 .destroy = set_match_v1_destroy,
600 .me = THIS_MODULE
601 },
602 /* counters support: update, match */
603 {
604 .name = "set",
605 .family = NFPROTO_IPV4,
606 .revision = 3,
607 .match = set_match_v3,
608 .matchsize = sizeof(struct xt_set_info_match_v3),
609 .checkentry = set_match_v3_checkentry,
610 .destroy = set_match_v3_destroy,
611 .me = THIS_MODULE
612 },
613 {
614 .name = "set",
615 .family = NFPROTO_IPV6,
616 .revision = 3,
617 .match = set_match_v3,
618 .matchsize = sizeof(struct xt_set_info_match_v3),
619 .checkentry = set_match_v3_checkentry,
620 .destroy = set_match_v3_destroy,
621 .me = THIS_MODULE
622 },
623 /* new revision for counters support: update, match */
624 {
625 .name = "set",
626 .family = NFPROTO_IPV4,
627 .revision = 4,
628 .match = set_match_v4,
629 .matchsize = sizeof(struct xt_set_info_match_v4),
630 .checkentry = set_match_v4_checkentry,
631 .destroy = set_match_v4_destroy,
632 .me = THIS_MODULE
633 },
634 {
635 .name = "set",
636 .family = NFPROTO_IPV6,
637 .revision = 4,
638 .match = set_match_v4,
639 .matchsize = sizeof(struct xt_set_info_match_v4),
640 .checkentry = set_match_v4_checkentry,
641 .destroy = set_match_v4_destroy,
642 .me = THIS_MODULE
643 },
644 };
645
646 static struct xt_target set_targets[] __read_mostly = {
647 {
648 .name = "SET",
649 .revision = 0,
650 .family = NFPROTO_IPV4,
651 .target = set_target_v0,
652 .targetsize = sizeof(struct xt_set_info_target_v0),
653 .checkentry = set_target_v0_checkentry,
654 .destroy = set_target_v0_destroy,
655 .me = THIS_MODULE
656 },
657 {
658 .name = "SET",
659 .revision = 1,
660 .family = NFPROTO_IPV4,
661 .target = set_target_v1,
662 .targetsize = sizeof(struct xt_set_info_target_v1),
663 .checkentry = set_target_v1_checkentry,
664 .destroy = set_target_v1_destroy,
665 .me = THIS_MODULE
666 },
667 {
668 .name = "SET",
669 .revision = 1,
670 .family = NFPROTO_IPV6,
671 .target = set_target_v1,
672 .targetsize = sizeof(struct xt_set_info_target_v1),
673 .checkentry = set_target_v1_checkentry,
674 .destroy = set_target_v1_destroy,
675 .me = THIS_MODULE
676 },
677 /* --timeout and --exist flags support */
678 {
679 .name = "SET",
680 .revision = 2,
681 .family = NFPROTO_IPV4,
682 .target = set_target_v2,
683 .targetsize = sizeof(struct xt_set_info_target_v2),
684 .checkentry = set_target_v2_checkentry,
685 .destroy = set_target_v2_destroy,
686 .me = THIS_MODULE
687 },
688 {
689 .name = "SET",
690 .revision = 2,
691 .family = NFPROTO_IPV6,
692 .target = set_target_v2,
693 .targetsize = sizeof(struct xt_set_info_target_v2),
694 .checkentry = set_target_v2_checkentry,
695 .destroy = set_target_v2_destroy,
696 .me = THIS_MODULE
697 },
698 /* --map-set support */
699 {
700 .name = "SET",
701 .revision = 3,
702 .family = NFPROTO_IPV4,
703 .target = set_target_v3,
704 .targetsize = sizeof(struct xt_set_info_target_v3),
705 .checkentry = set_target_v3_checkentry,
706 .destroy = set_target_v3_destroy,
707 .me = THIS_MODULE
708 },
709 {
710 .name = "SET",
711 .revision = 3,
712 .family = NFPROTO_IPV6,
713 .target = set_target_v3,
714 .targetsize = sizeof(struct xt_set_info_target_v3),
715 .checkentry = set_target_v3_checkentry,
716 .destroy = set_target_v3_destroy,
717 .me = THIS_MODULE
718 },
719 };
720
721 static int __init xt_set_init(void)
722 {
723 int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
724
725 if (!ret) {
726 ret = xt_register_targets(set_targets,
727 ARRAY_SIZE(set_targets));
728 if (ret)
729 xt_unregister_matches(set_matches,
730 ARRAY_SIZE(set_matches));
731 }
732 return ret;
733 }
734
735 static void __exit xt_set_fini(void)
736 {
737 xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
738 xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
739 }
740
741 module_init(xt_set_init);
742 module_exit(xt_set_fini);
This page took 0.063104 seconds and 6 git commands to generate.