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