1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d956798dSJozsef Kadlecsik /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
3d956798dSJozsef Kadlecsik * Patrick Schaaf <bof@bof.de>
4d956798dSJozsef Kadlecsik * Martin Josefsson <gandalf@wlug.westbo.se>
5fe03d474SJozsef Kadlecsik * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org>
6d956798dSJozsef Kadlecsik */
7d956798dSJozsef Kadlecsik
8d956798dSJozsef Kadlecsik /* Kernel module which implements the set match and SET target
9ca0f6a5cSJozsef Kadlecsik * for netfilter/iptables.
10ca0f6a5cSJozsef Kadlecsik */
11d956798dSJozsef Kadlecsik
12d956798dSJozsef Kadlecsik #include <linux/module.h>
13d956798dSJozsef Kadlecsik #include <linux/skbuff.h>
14d956798dSJozsef Kadlecsik
15d956798dSJozsef Kadlecsik #include <linux/netfilter/x_tables.h>
16a9756e6fSJozsef Kadlecsik #include <linux/netfilter/ipset/ip_set.h>
17a9756e6fSJozsef Kadlecsik #include <uapi/linux/netfilter/xt_set.h>
18d956798dSJozsef Kadlecsik
19d956798dSJozsef Kadlecsik MODULE_LICENSE("GPL");
20fe03d474SJozsef Kadlecsik MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
21d956798dSJozsef Kadlecsik MODULE_DESCRIPTION("Xtables: IP set match and target module");
22d956798dSJozsef Kadlecsik MODULE_ALIAS("xt_SET");
23d956798dSJozsef Kadlecsik MODULE_ALIAS("ipt_set");
24d956798dSJozsef Kadlecsik MODULE_ALIAS("ip6t_set");
25d956798dSJozsef Kadlecsik MODULE_ALIAS("ipt_SET");
26d956798dSJozsef Kadlecsik MODULE_ALIAS("ip6t_SET");
27d956798dSJozsef Kadlecsik
28d956798dSJozsef Kadlecsik static inline int
match_set(ip_set_id_t index,const struct sk_buff * skb,const struct xt_action_param * par,struct ip_set_adt_opt * opt,int inv)29d956798dSJozsef Kadlecsik match_set(ip_set_id_t index, const struct sk_buff *skb,
30b66554cfSJozsef Kadlecsik const struct xt_action_param *par,
31075e64c0SJozsef Kadlecsik struct ip_set_adt_opt *opt, int inv)
32d956798dSJozsef Kadlecsik {
33b66554cfSJozsef Kadlecsik if (ip_set_test(index, skb, par, opt))
34d956798dSJozsef Kadlecsik inv = !inv;
35d956798dSJozsef Kadlecsik return inv;
36d956798dSJozsef Kadlecsik }
37d956798dSJozsef Kadlecsik
384750005aSJozsef Kadlecsik #define ADT_OPT(n, f, d, fs, cfs, t, p, b, po, bo) \
39127f5591SJozsef Kadlecsik struct ip_set_adt_opt n = { \
40127f5591SJozsef Kadlecsik .family = f, \
41127f5591SJozsef Kadlecsik .dim = d, \
42127f5591SJozsef Kadlecsik .flags = fs, \
43127f5591SJozsef Kadlecsik .cmdflags = cfs, \
44075e64c0SJozsef Kadlecsik .ext.timeout = t, \
454750005aSJozsef Kadlecsik .ext.packets = p, \
464750005aSJozsef Kadlecsik .ext.bytes = b, \
474750005aSJozsef Kadlecsik .ext.packets_op = po, \
484750005aSJozsef Kadlecsik .ext.bytes_op = bo, \
49127f5591SJozsef Kadlecsik }
50ac8cc925SJozsef Kadlecsik
51d956798dSJozsef Kadlecsik /* Revision 0 interface: backward compatible with netfilter/iptables */
52d956798dSJozsef Kadlecsik
53d956798dSJozsef Kadlecsik static bool
set_match_v0(const struct sk_buff * skb,struct xt_action_param * par)54d956798dSJozsef Kadlecsik set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
55d956798dSJozsef Kadlecsik {
56d956798dSJozsef Kadlecsik const struct xt_set_info_match_v0 *info = par->matchinfo;
57ca0f6a5cSJozsef Kadlecsik
58613dbd95SPablo Neira Ayuso ADT_OPT(opt, xt_family(par), info->match_set.u.compat.dim,
594750005aSJozsef Kadlecsik info->match_set.u.compat.flags, 0, UINT_MAX,
604750005aSJozsef Kadlecsik 0, 0, 0, 0);
61d956798dSJozsef Kadlecsik
62b66554cfSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt,
63d956798dSJozsef Kadlecsik info->match_set.u.compat.flags & IPSET_INV_MATCH);
64d956798dSJozsef Kadlecsik }
65d956798dSJozsef Kadlecsik
66d956798dSJozsef Kadlecsik static void
compat_flags(struct xt_set_info_v0 * info)67d956798dSJozsef Kadlecsik compat_flags(struct xt_set_info_v0 *info)
68d956798dSJozsef Kadlecsik {
69d956798dSJozsef Kadlecsik u_int8_t i;
70d956798dSJozsef Kadlecsik
71d956798dSJozsef Kadlecsik /* Fill out compatibility data according to enum ip_set_kopt */
72d956798dSJozsef Kadlecsik info->u.compat.dim = IPSET_DIM_ZERO;
73d956798dSJozsef Kadlecsik if (info->u.flags[0] & IPSET_MATCH_INV)
74d956798dSJozsef Kadlecsik info->u.compat.flags |= IPSET_INV_MATCH;
75d956798dSJozsef Kadlecsik for (i = 0; i < IPSET_DIM_MAX - 1 && info->u.flags[i]; i++) {
76d956798dSJozsef Kadlecsik info->u.compat.dim++;
77d956798dSJozsef Kadlecsik if (info->u.flags[i] & IPSET_SRC)
78d956798dSJozsef Kadlecsik info->u.compat.flags |= (1 << info->u.compat.dim);
79d956798dSJozsef Kadlecsik }
80d956798dSJozsef Kadlecsik }
81d956798dSJozsef Kadlecsik
82d956798dSJozsef Kadlecsik static int
set_match_v0_checkentry(const struct xt_mtchk_param * par)83d956798dSJozsef Kadlecsik set_match_v0_checkentry(const struct xt_mtchk_param *par)
84d956798dSJozsef Kadlecsik {
85d956798dSJozsef Kadlecsik struct xt_set_info_match_v0 *info = par->matchinfo;
86d956798dSJozsef Kadlecsik ip_set_id_t index;
87d956798dSJozsef Kadlecsik
881785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
89d956798dSJozsef Kadlecsik
90d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
91c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find set identified by id %u to match\n",
92d956798dSJozsef Kadlecsik info->match_set.index);
93d956798dSJozsef Kadlecsik return -ENOENT;
94d956798dSJozsef Kadlecsik }
95d956798dSJozsef Kadlecsik if (info->match_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
96c82b31c5SFlorian Westphal pr_info_ratelimited("set match dimension is over the limit!\n");
971785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->match_set.index);
98d956798dSJozsef Kadlecsik return -ERANGE;
99d956798dSJozsef Kadlecsik }
100d956798dSJozsef Kadlecsik
101d956798dSJozsef Kadlecsik /* Fill out compatibility data */
102d956798dSJozsef Kadlecsik compat_flags(&info->match_set);
103d956798dSJozsef Kadlecsik
104d956798dSJozsef Kadlecsik return 0;
105d956798dSJozsef Kadlecsik }
106d956798dSJozsef Kadlecsik
107d956798dSJozsef Kadlecsik static void
set_match_v0_destroy(const struct xt_mtdtor_param * par)108d956798dSJozsef Kadlecsik set_match_v0_destroy(const struct xt_mtdtor_param *par)
109d956798dSJozsef Kadlecsik {
110d956798dSJozsef Kadlecsik struct xt_set_info_match_v0 *info = par->matchinfo;
111d956798dSJozsef Kadlecsik
1121785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->match_set.index);
113d956798dSJozsef Kadlecsik }
114d956798dSJozsef Kadlecsik
115bd3129fcSJozsef Kadlecsik /* Revision 1 match */
116bd3129fcSJozsef Kadlecsik
117bd3129fcSJozsef Kadlecsik static bool
set_match_v1(const struct sk_buff * skb,struct xt_action_param * par)118bd3129fcSJozsef Kadlecsik set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
119bd3129fcSJozsef Kadlecsik {
120bd3129fcSJozsef Kadlecsik const struct xt_set_info_match_v1 *info = par->matchinfo;
121ca0f6a5cSJozsef Kadlecsik
122613dbd95SPablo Neira Ayuso ADT_OPT(opt, xt_family(par), info->match_set.dim,
1234750005aSJozsef Kadlecsik info->match_set.flags, 0, UINT_MAX,
1244750005aSJozsef Kadlecsik 0, 0, 0, 0);
125bd3129fcSJozsef Kadlecsik
126bd3129fcSJozsef Kadlecsik if (opt.flags & IPSET_RETURN_NOMATCH)
127bd3129fcSJozsef Kadlecsik opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;
128bd3129fcSJozsef Kadlecsik
129bd3129fcSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt,
130bd3129fcSJozsef Kadlecsik info->match_set.flags & IPSET_INV_MATCH);
131bd3129fcSJozsef Kadlecsik }
132bd3129fcSJozsef Kadlecsik
133bd3129fcSJozsef Kadlecsik static int
set_match_v1_checkentry(const struct xt_mtchk_param * par)134bd3129fcSJozsef Kadlecsik set_match_v1_checkentry(const struct xt_mtchk_param *par)
135bd3129fcSJozsef Kadlecsik {
136bd3129fcSJozsef Kadlecsik struct xt_set_info_match_v1 *info = par->matchinfo;
137bd3129fcSJozsef Kadlecsik ip_set_id_t index;
138bd3129fcSJozsef Kadlecsik
1391785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->match_set.index);
140bd3129fcSJozsef Kadlecsik
141bd3129fcSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
142c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find set identified by id %u to match\n",
143bd3129fcSJozsef Kadlecsik info->match_set.index);
144bd3129fcSJozsef Kadlecsik return -ENOENT;
145bd3129fcSJozsef Kadlecsik }
146bd3129fcSJozsef Kadlecsik if (info->match_set.dim > IPSET_DIM_MAX) {
147c82b31c5SFlorian Westphal pr_info_ratelimited("set match dimension is over the limit!\n");
1481785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->match_set.index);
149bd3129fcSJozsef Kadlecsik return -ERANGE;
150bd3129fcSJozsef Kadlecsik }
151bd3129fcSJozsef Kadlecsik
152bd3129fcSJozsef Kadlecsik return 0;
153bd3129fcSJozsef Kadlecsik }
154bd3129fcSJozsef Kadlecsik
155bd3129fcSJozsef Kadlecsik static void
set_match_v1_destroy(const struct xt_mtdtor_param * par)156bd3129fcSJozsef Kadlecsik set_match_v1_destroy(const struct xt_mtdtor_param *par)
157bd3129fcSJozsef Kadlecsik {
158bd3129fcSJozsef Kadlecsik struct xt_set_info_match_v1 *info = par->matchinfo;
159bd3129fcSJozsef Kadlecsik
1601785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->match_set.index);
161bd3129fcSJozsef Kadlecsik }
162bd3129fcSJozsef Kadlecsik
163bd3129fcSJozsef Kadlecsik /* Revision 3 match */
164bd3129fcSJozsef Kadlecsik
165bd3129fcSJozsef Kadlecsik static bool
set_match_v3(const struct sk_buff * skb,struct xt_action_param * par)166bd3129fcSJozsef Kadlecsik set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
167bd3129fcSJozsef Kadlecsik {
168bd3129fcSJozsef Kadlecsik const struct xt_set_info_match_v3 *info = par->matchinfo;
169ca0f6a5cSJozsef Kadlecsik
170613dbd95SPablo Neira Ayuso ADT_OPT(opt, xt_family(par), info->match_set.dim,
1714750005aSJozsef Kadlecsik info->match_set.flags, info->flags, UINT_MAX,
1724750005aSJozsef Kadlecsik info->packets.value, info->bytes.value,
1734750005aSJozsef Kadlecsik info->packets.op, info->bytes.op);
174bd3129fcSJozsef Kadlecsik
175bd3129fcSJozsef Kadlecsik if (info->packets.op != IPSET_COUNTER_NONE ||
176bd3129fcSJozsef Kadlecsik info->bytes.op != IPSET_COUNTER_NONE)
177bd3129fcSJozsef Kadlecsik opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
178bd3129fcSJozsef Kadlecsik
1794750005aSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt,
180bd3129fcSJozsef Kadlecsik info->match_set.flags & IPSET_INV_MATCH);
181a51b9199SJozsef Kadlecsik }
182a51b9199SJozsef Kadlecsik
183a51b9199SJozsef Kadlecsik #define set_match_v3_checkentry set_match_v1_checkentry
184a51b9199SJozsef Kadlecsik #define set_match_v3_destroy set_match_v1_destroy
185a51b9199SJozsef Kadlecsik
186a51b9199SJozsef Kadlecsik /* Revision 4 match */
187a51b9199SJozsef Kadlecsik
188a51b9199SJozsef Kadlecsik static bool
set_match_v4(const struct sk_buff * skb,struct xt_action_param * par)189a51b9199SJozsef Kadlecsik set_match_v4(const struct sk_buff *skb, struct xt_action_param *par)
190a51b9199SJozsef Kadlecsik {
191a51b9199SJozsef Kadlecsik const struct xt_set_info_match_v4 *info = par->matchinfo;
192ca0f6a5cSJozsef Kadlecsik
193613dbd95SPablo Neira Ayuso ADT_OPT(opt, xt_family(par), info->match_set.dim,
1944750005aSJozsef Kadlecsik info->match_set.flags, info->flags, UINT_MAX,
1954750005aSJozsef Kadlecsik info->packets.value, info->bytes.value,
1964750005aSJozsef Kadlecsik info->packets.op, info->bytes.op);
197a51b9199SJozsef Kadlecsik
198a51b9199SJozsef Kadlecsik if (info->packets.op != IPSET_COUNTER_NONE ||
199a51b9199SJozsef Kadlecsik info->bytes.op != IPSET_COUNTER_NONE)
200a51b9199SJozsef Kadlecsik opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;
201a51b9199SJozsef Kadlecsik
2024750005aSJozsef Kadlecsik return match_set(info->match_set.index, skb, par, &opt,
203a51b9199SJozsef Kadlecsik info->match_set.flags & IPSET_INV_MATCH);
204bd3129fcSJozsef Kadlecsik }
205bd3129fcSJozsef Kadlecsik
206a51b9199SJozsef Kadlecsik #define set_match_v4_checkentry set_match_v1_checkentry
207a51b9199SJozsef Kadlecsik #define set_match_v4_destroy set_match_v1_destroy
208bd3129fcSJozsef Kadlecsik
209bd3129fcSJozsef Kadlecsik /* Revision 0 interface: backward compatible with netfilter/iptables */
210bd3129fcSJozsef Kadlecsik
211d956798dSJozsef Kadlecsik static unsigned int
set_target_v0(struct sk_buff * skb,const struct xt_action_param * par)212d956798dSJozsef Kadlecsik set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
213d956798dSJozsef Kadlecsik {
214d956798dSJozsef Kadlecsik const struct xt_set_info_target_v0 *info = par->targinfo;
215ca0f6a5cSJozsef Kadlecsik
216613dbd95SPablo Neira Ayuso ADT_OPT(add_opt, xt_family(par), info->add_set.u.compat.dim,
2174750005aSJozsef Kadlecsik info->add_set.u.compat.flags, 0, UINT_MAX,
2184750005aSJozsef Kadlecsik 0, 0, 0, 0);
219613dbd95SPablo Neira Ayuso ADT_OPT(del_opt, xt_family(par), info->del_set.u.compat.dim,
2204750005aSJozsef Kadlecsik info->del_set.u.compat.flags, 0, UINT_MAX,
2214750005aSJozsef Kadlecsik 0, 0, 0, 0);
222d956798dSJozsef Kadlecsik
223d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
224b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt);
225d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
226b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt);
227d956798dSJozsef Kadlecsik
228d956798dSJozsef Kadlecsik return XT_CONTINUE;
229d956798dSJozsef Kadlecsik }
230d956798dSJozsef Kadlecsik
231d956798dSJozsef Kadlecsik static int
set_target_v0_checkentry(const struct xt_tgchk_param * par)232d956798dSJozsef Kadlecsik set_target_v0_checkentry(const struct xt_tgchk_param *par)
233d956798dSJozsef Kadlecsik {
234d956798dSJozsef Kadlecsik struct xt_set_info_target_v0 *info = par->targinfo;
235d956798dSJozsef Kadlecsik ip_set_id_t index;
236d956798dSJozsef Kadlecsik
237d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) {
2381785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
239d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
240c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find add_set index %u as target\n",
241d956798dSJozsef Kadlecsik info->add_set.index);
242d956798dSJozsef Kadlecsik return -ENOENT;
243d956798dSJozsef Kadlecsik }
244d956798dSJozsef Kadlecsik }
245d956798dSJozsef Kadlecsik
246d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) {
2471785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
248d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
249c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find del_set index %u as target\n",
250d956798dSJozsef Kadlecsik info->del_set.index);
251eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
2521785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
253d956798dSJozsef Kadlecsik return -ENOENT;
254d956798dSJozsef Kadlecsik }
255d956798dSJozsef Kadlecsik }
256d956798dSJozsef Kadlecsik if (info->add_set.u.flags[IPSET_DIM_MAX - 1] != 0 ||
257d956798dSJozsef Kadlecsik info->del_set.u.flags[IPSET_DIM_MAX - 1] != 0) {
258c82b31c5SFlorian Westphal pr_info_ratelimited("SET target dimension over the limit!\n");
259eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
2601785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
261eafbd3fdSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
2621785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->del_set.index);
263d956798dSJozsef Kadlecsik return -ERANGE;
264d956798dSJozsef Kadlecsik }
265d956798dSJozsef Kadlecsik
266d956798dSJozsef Kadlecsik /* Fill out compatibility data */
267d956798dSJozsef Kadlecsik compat_flags(&info->add_set);
268d956798dSJozsef Kadlecsik compat_flags(&info->del_set);
269d956798dSJozsef Kadlecsik
270d956798dSJozsef Kadlecsik return 0;
271d956798dSJozsef Kadlecsik }
272d956798dSJozsef Kadlecsik
273d956798dSJozsef Kadlecsik static void
set_target_v0_destroy(const struct xt_tgdtor_param * par)274d956798dSJozsef Kadlecsik set_target_v0_destroy(const struct xt_tgdtor_param *par)
275d956798dSJozsef Kadlecsik {
276d956798dSJozsef Kadlecsik const struct xt_set_info_target_v0 *info = par->targinfo;
277d956798dSJozsef Kadlecsik
278d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
2791785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
280d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
2811785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->del_set.index);
282d956798dSJozsef Kadlecsik }
283d956798dSJozsef Kadlecsik
284bd3129fcSJozsef Kadlecsik /* Revision 1 target */
285d956798dSJozsef Kadlecsik
286d956798dSJozsef Kadlecsik static unsigned int
set_target_v1(struct sk_buff * skb,const struct xt_action_param * par)287ac8cc925SJozsef Kadlecsik set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
288d956798dSJozsef Kadlecsik {
289ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo;
290ca0f6a5cSJozsef Kadlecsik
291613dbd95SPablo Neira Ayuso ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
2924750005aSJozsef Kadlecsik info->add_set.flags, 0, UINT_MAX,
2934750005aSJozsef Kadlecsik 0, 0, 0, 0);
294613dbd95SPablo Neira Ayuso ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
2954750005aSJozsef Kadlecsik info->del_set.flags, 0, UINT_MAX,
2964750005aSJozsef Kadlecsik 0, 0, 0, 0);
297d956798dSJozsef Kadlecsik
298d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
299b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt);
300d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
301b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt);
302d956798dSJozsef Kadlecsik
303d956798dSJozsef Kadlecsik return XT_CONTINUE;
304d956798dSJozsef Kadlecsik }
305d956798dSJozsef Kadlecsik
306d956798dSJozsef Kadlecsik static int
set_target_v1_checkentry(const struct xt_tgchk_param * par)307ac8cc925SJozsef Kadlecsik set_target_v1_checkentry(const struct xt_tgchk_param *par)
308d956798dSJozsef Kadlecsik {
309ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo;
310d956798dSJozsef Kadlecsik ip_set_id_t index;
311d956798dSJozsef Kadlecsik
312d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID) {
3131785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->add_set.index);
314d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
315c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find add_set index %u as target\n",
316d956798dSJozsef Kadlecsik info->add_set.index);
317d956798dSJozsef Kadlecsik return -ENOENT;
318d956798dSJozsef Kadlecsik }
319d956798dSJozsef Kadlecsik }
320d956798dSJozsef Kadlecsik
321d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID) {
3221785e8f4SVitaly Lavrov index = ip_set_nfnl_get_byindex(par->net, info->del_set.index);
323d956798dSJozsef Kadlecsik if (index == IPSET_INVALID_ID) {
324c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find del_set index %u as target\n",
325d956798dSJozsef Kadlecsik info->del_set.index);
326eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
3271785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
328d956798dSJozsef Kadlecsik return -ENOENT;
329d956798dSJozsef Kadlecsik }
330d956798dSJozsef Kadlecsik }
331d956798dSJozsef Kadlecsik if (info->add_set.dim > IPSET_DIM_MAX ||
332eafbd3fdSJozsef Kadlecsik info->del_set.dim > IPSET_DIM_MAX) {
333c82b31c5SFlorian Westphal pr_info_ratelimited("SET target dimension over the limit!\n");
334eafbd3fdSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
3351785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
336eafbd3fdSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
3371785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->del_set.index);
338d956798dSJozsef Kadlecsik return -ERANGE;
339d956798dSJozsef Kadlecsik }
340d956798dSJozsef Kadlecsik
341d956798dSJozsef Kadlecsik return 0;
342d956798dSJozsef Kadlecsik }
343d956798dSJozsef Kadlecsik
344d956798dSJozsef Kadlecsik static void
set_target_v1_destroy(const struct xt_tgdtor_param * par)345ac8cc925SJozsef Kadlecsik set_target_v1_destroy(const struct xt_tgdtor_param *par)
346d956798dSJozsef Kadlecsik {
347ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v1 *info = par->targinfo;
348d956798dSJozsef Kadlecsik
349d956798dSJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
3501785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->add_set.index);
351d956798dSJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
3521785e8f4SVitaly Lavrov ip_set_nfnl_put(par->net, info->del_set.index);
353d956798dSJozsef Kadlecsik }
354d956798dSJozsef Kadlecsik
355ac8cc925SJozsef Kadlecsik /* Revision 2 target */
356ac8cc925SJozsef Kadlecsik
357ac8cc925SJozsef Kadlecsik static unsigned int
set_target_v2(struct sk_buff * skb,const struct xt_action_param * par)358ac8cc925SJozsef Kadlecsik set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
359ac8cc925SJozsef Kadlecsik {
360ac8cc925SJozsef Kadlecsik const struct xt_set_info_target_v2 *info = par->targinfo;
361ca0f6a5cSJozsef Kadlecsik
362613dbd95SPablo Neira Ayuso ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
3634750005aSJozsef Kadlecsik info->add_set.flags, info->flags, info->timeout,
3644750005aSJozsef Kadlecsik 0, 0, 0, 0);
365613dbd95SPablo Neira Ayuso ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
3664750005aSJozsef Kadlecsik info->del_set.flags, 0, UINT_MAX,
3674750005aSJozsef Kadlecsik 0, 0, 0, 0);
368ac8cc925SJozsef Kadlecsik
369127f5591SJozsef Kadlecsik /* Normalize to fit into jiffies */
370075e64c0SJozsef Kadlecsik if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
37130a2e107SJozsef Kadlecsik add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
37230a2e107SJozsef Kadlecsik add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
373ac8cc925SJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
374b66554cfSJozsef Kadlecsik ip_set_add(info->add_set.index, skb, par, &add_opt);
375ac8cc925SJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
376b66554cfSJozsef Kadlecsik ip_set_del(info->del_set.index, skb, par, &del_opt);
377ac8cc925SJozsef Kadlecsik
378ac8cc925SJozsef Kadlecsik return XT_CONTINUE;
379ac8cc925SJozsef Kadlecsik }
380ac8cc925SJozsef Kadlecsik
381ac8cc925SJozsef Kadlecsik #define set_target_v2_checkentry set_target_v1_checkentry
382ac8cc925SJozsef Kadlecsik #define set_target_v2_destroy set_target_v1_destroy
383ac8cc925SJozsef Kadlecsik
38476cea410SAnton Danilov /* Revision 3 target */
38576cea410SAnton Danilov
386bec810d9SJozsef Kadlecsik #define MOPT(opt, member) ((opt).ext.skbinfo.member)
387bec810d9SJozsef Kadlecsik
38876cea410SAnton Danilov static unsigned int
set_target_v3(struct sk_buff * skb,const struct xt_action_param * par)38976cea410SAnton Danilov set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
39076cea410SAnton Danilov {
39176cea410SAnton Danilov const struct xt_set_info_target_v3 *info = par->targinfo;
392ca0f6a5cSJozsef Kadlecsik int ret;
393ca0f6a5cSJozsef Kadlecsik
394613dbd95SPablo Neira Ayuso ADT_OPT(add_opt, xt_family(par), info->add_set.dim,
3954750005aSJozsef Kadlecsik info->add_set.flags, info->flags, info->timeout,
3964750005aSJozsef Kadlecsik 0, 0, 0, 0);
397613dbd95SPablo Neira Ayuso ADT_OPT(del_opt, xt_family(par), info->del_set.dim,
3984750005aSJozsef Kadlecsik info->del_set.flags, 0, UINT_MAX,
3994750005aSJozsef Kadlecsik 0, 0, 0, 0);
400613dbd95SPablo Neira Ayuso ADT_OPT(map_opt, xt_family(par), info->map_set.dim,
4014750005aSJozsef Kadlecsik info->map_set.flags, 0, UINT_MAX,
4024750005aSJozsef Kadlecsik 0, 0, 0, 0);
40376cea410SAnton Danilov
40476cea410SAnton Danilov /* Normalize to fit into jiffies */
40576cea410SAnton Danilov if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
40630a2e107SJozsef Kadlecsik add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
40730a2e107SJozsef Kadlecsik add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
40876cea410SAnton Danilov if (info->add_set.index != IPSET_INVALID_ID)
40976cea410SAnton Danilov ip_set_add(info->add_set.index, skb, par, &add_opt);
41076cea410SAnton Danilov if (info->del_set.index != IPSET_INVALID_ID)
41176cea410SAnton Danilov ip_set_del(info->del_set.index, skb, par, &del_opt);
41276cea410SAnton Danilov if (info->map_set.index != IPSET_INVALID_ID) {
41376cea410SAnton Danilov map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
41476cea410SAnton Danilov IPSET_FLAG_MAP_SKBPRIO |
41576cea410SAnton Danilov IPSET_FLAG_MAP_SKBQUEUE);
41676cea410SAnton Danilov ret = match_set(info->map_set.index, skb, par, &map_opt,
41776cea410SAnton Danilov info->map_set.flags & IPSET_INV_MATCH);
41876cea410SAnton Danilov if (!ret)
41976cea410SAnton Danilov return XT_CONTINUE;
42076cea410SAnton Danilov if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
421bec810d9SJozsef Kadlecsik skb->mark = (skb->mark & ~MOPT(map_opt,skbmarkmask))
422bec810d9SJozsef Kadlecsik ^ MOPT(map_opt, skbmark);
42376cea410SAnton Danilov if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
424bec810d9SJozsef Kadlecsik skb->priority = MOPT(map_opt, skbprio);
42576cea410SAnton Danilov if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
42676cea410SAnton Danilov skb->dev &&
427bec810d9SJozsef Kadlecsik skb->dev->real_num_tx_queues > MOPT(map_opt, skbqueue))
428bec810d9SJozsef Kadlecsik skb_set_queue_mapping(skb, MOPT(map_opt, skbqueue));
42976cea410SAnton Danilov }
43076cea410SAnton Danilov return XT_CONTINUE;
43176cea410SAnton Danilov }
43276cea410SAnton Danilov
43376cea410SAnton Danilov static int
set_target_v3_checkentry(const struct xt_tgchk_param * par)43476cea410SAnton Danilov set_target_v3_checkentry(const struct xt_tgchk_param *par)
43576cea410SAnton Danilov {
43676cea410SAnton Danilov const struct xt_set_info_target_v3 *info = par->targinfo;
43776cea410SAnton Danilov ip_set_id_t index;
438b1732e16SJozsef Kadlecsik int ret = 0;
43976cea410SAnton Danilov
44076cea410SAnton Danilov if (info->add_set.index != IPSET_INVALID_ID) {
44176cea410SAnton Danilov index = ip_set_nfnl_get_byindex(par->net,
44276cea410SAnton Danilov info->add_set.index);
44376cea410SAnton Danilov if (index == IPSET_INVALID_ID) {
444c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find add_set index %u as target\n",
44576cea410SAnton Danilov info->add_set.index);
44676cea410SAnton Danilov return -ENOENT;
44776cea410SAnton Danilov }
44876cea410SAnton Danilov }
44976cea410SAnton Danilov
45076cea410SAnton Danilov if (info->del_set.index != IPSET_INVALID_ID) {
45176cea410SAnton Danilov index = ip_set_nfnl_get_byindex(par->net,
45276cea410SAnton Danilov info->del_set.index);
45376cea410SAnton Danilov if (index == IPSET_INVALID_ID) {
454c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find del_set index %u as target\n",
45576cea410SAnton Danilov info->del_set.index);
456b1732e16SJozsef Kadlecsik ret = -ENOENT;
457b1732e16SJozsef Kadlecsik goto cleanup_add;
45876cea410SAnton Danilov }
45976cea410SAnton Danilov }
46076cea410SAnton Danilov
46176cea410SAnton Danilov if (info->map_set.index != IPSET_INVALID_ID) {
46276cea410SAnton Danilov if (strncmp(par->table, "mangle", 7)) {
463c82b31c5SFlorian Westphal pr_info_ratelimited("--map-set only usable from mangle table\n");
464b1732e16SJozsef Kadlecsik ret = -EINVAL;
465b1732e16SJozsef Kadlecsik goto cleanup_del;
46676cea410SAnton Danilov }
46776cea410SAnton Danilov if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
46876cea410SAnton Danilov (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
4699dcceb13SSerhey Popovych (par->hook_mask & ~(1 << NF_INET_FORWARD |
47076cea410SAnton Danilov 1 << NF_INET_LOCAL_OUT |
47176cea410SAnton Danilov 1 << NF_INET_POST_ROUTING))) {
472c82b31c5SFlorian Westphal pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
473b1732e16SJozsef Kadlecsik ret = -EINVAL;
474b1732e16SJozsef Kadlecsik goto cleanup_del;
47576cea410SAnton Danilov }
47676cea410SAnton Danilov index = ip_set_nfnl_get_byindex(par->net,
47776cea410SAnton Danilov info->map_set.index);
47876cea410SAnton Danilov if (index == IPSET_INVALID_ID) {
479c82b31c5SFlorian Westphal pr_info_ratelimited("Cannot find map_set index %u as target\n",
48076cea410SAnton Danilov info->map_set.index);
481b1732e16SJozsef Kadlecsik ret = -ENOENT;
482b1732e16SJozsef Kadlecsik goto cleanup_del;
48376cea410SAnton Danilov }
48476cea410SAnton Danilov }
48576cea410SAnton Danilov
48676cea410SAnton Danilov if (info->add_set.dim > IPSET_DIM_MAX ||
48776cea410SAnton Danilov info->del_set.dim > IPSET_DIM_MAX ||
48876cea410SAnton Danilov info->map_set.dim > IPSET_DIM_MAX) {
489c82b31c5SFlorian Westphal pr_info_ratelimited("SET target dimension over the limit!\n");
490b1732e16SJozsef Kadlecsik ret = -ERANGE;
491b1732e16SJozsef Kadlecsik goto cleanup_mark;
49276cea410SAnton Danilov }
49376cea410SAnton Danilov
49476cea410SAnton Danilov return 0;
495b1732e16SJozsef Kadlecsik cleanup_mark:
496b1732e16SJozsef Kadlecsik if (info->map_set.index != IPSET_INVALID_ID)
497b1732e16SJozsef Kadlecsik ip_set_nfnl_put(par->net, info->map_set.index);
498b1732e16SJozsef Kadlecsik cleanup_del:
499b1732e16SJozsef Kadlecsik if (info->del_set.index != IPSET_INVALID_ID)
500b1732e16SJozsef Kadlecsik ip_set_nfnl_put(par->net, info->del_set.index);
501b1732e16SJozsef Kadlecsik cleanup_add:
502b1732e16SJozsef Kadlecsik if (info->add_set.index != IPSET_INVALID_ID)
503b1732e16SJozsef Kadlecsik ip_set_nfnl_put(par->net, info->add_set.index);
504b1732e16SJozsef Kadlecsik return ret;
50576cea410SAnton Danilov }
50676cea410SAnton Danilov
50776cea410SAnton Danilov static void
set_target_v3_destroy(const struct xt_tgdtor_param * par)50876cea410SAnton Danilov set_target_v3_destroy(const struct xt_tgdtor_param *par)
50976cea410SAnton Danilov {
51076cea410SAnton Danilov const struct xt_set_info_target_v3 *info = par->targinfo;
51176cea410SAnton Danilov
51276cea410SAnton Danilov if (info->add_set.index != IPSET_INVALID_ID)
51376cea410SAnton Danilov ip_set_nfnl_put(par->net, info->add_set.index);
51476cea410SAnton Danilov if (info->del_set.index != IPSET_INVALID_ID)
51576cea410SAnton Danilov ip_set_nfnl_put(par->net, info->del_set.index);
51676cea410SAnton Danilov if (info->map_set.index != IPSET_INVALID_ID)
51776cea410SAnton Danilov ip_set_nfnl_put(par->net, info->map_set.index);
51876cea410SAnton Danilov }
51976cea410SAnton Danilov
520d956798dSJozsef Kadlecsik static struct xt_match set_matches[] __read_mostly = {
521d956798dSJozsef Kadlecsik {
522d956798dSJozsef Kadlecsik .name = "set",
523d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4,
524d956798dSJozsef Kadlecsik .revision = 0,
525d956798dSJozsef Kadlecsik .match = set_match_v0,
526d956798dSJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v0),
527d956798dSJozsef Kadlecsik .checkentry = set_match_v0_checkentry,
528d956798dSJozsef Kadlecsik .destroy = set_match_v0_destroy,
529d956798dSJozsef Kadlecsik .me = THIS_MODULE
530d956798dSJozsef Kadlecsik },
531d956798dSJozsef Kadlecsik {
532d956798dSJozsef Kadlecsik .name = "set",
533d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4,
534d956798dSJozsef Kadlecsik .revision = 1,
535ac8cc925SJozsef Kadlecsik .match = set_match_v1,
536ac8cc925SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1),
537ac8cc925SJozsef Kadlecsik .checkentry = set_match_v1_checkentry,
538ac8cc925SJozsef Kadlecsik .destroy = set_match_v1_destroy,
539d956798dSJozsef Kadlecsik .me = THIS_MODULE
540d956798dSJozsef Kadlecsik },
541d956798dSJozsef Kadlecsik {
542d956798dSJozsef Kadlecsik .name = "set",
543d956798dSJozsef Kadlecsik .family = NFPROTO_IPV6,
544d956798dSJozsef Kadlecsik .revision = 1,
545ac8cc925SJozsef Kadlecsik .match = set_match_v1,
546ac8cc925SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1),
547ac8cc925SJozsef Kadlecsik .checkentry = set_match_v1_checkentry,
548ac8cc925SJozsef Kadlecsik .destroy = set_match_v1_destroy,
549d956798dSJozsef Kadlecsik .me = THIS_MODULE
550d956798dSJozsef Kadlecsik },
5513e0304a5SJozsef Kadlecsik /* --return-nomatch flag support */
5523e0304a5SJozsef Kadlecsik {
5533e0304a5SJozsef Kadlecsik .name = "set",
5543e0304a5SJozsef Kadlecsik .family = NFPROTO_IPV4,
5553e0304a5SJozsef Kadlecsik .revision = 2,
5563e0304a5SJozsef Kadlecsik .match = set_match_v1,
5573e0304a5SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1),
5583e0304a5SJozsef Kadlecsik .checkentry = set_match_v1_checkentry,
5593e0304a5SJozsef Kadlecsik .destroy = set_match_v1_destroy,
5603e0304a5SJozsef Kadlecsik .me = THIS_MODULE
5613e0304a5SJozsef Kadlecsik },
5623e0304a5SJozsef Kadlecsik {
5633e0304a5SJozsef Kadlecsik .name = "set",
5643e0304a5SJozsef Kadlecsik .family = NFPROTO_IPV6,
5653e0304a5SJozsef Kadlecsik .revision = 2,
5663e0304a5SJozsef Kadlecsik .match = set_match_v1,
5673e0304a5SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v1),
5683e0304a5SJozsef Kadlecsik .checkentry = set_match_v1_checkentry,
5693e0304a5SJozsef Kadlecsik .destroy = set_match_v1_destroy,
5703e0304a5SJozsef Kadlecsik .me = THIS_MODULE
5713e0304a5SJozsef Kadlecsik },
5726e01781dSJozsef Kadlecsik /* counters support: update, match */
5736e01781dSJozsef Kadlecsik {
5746e01781dSJozsef Kadlecsik .name = "set",
5756e01781dSJozsef Kadlecsik .family = NFPROTO_IPV4,
5766e01781dSJozsef Kadlecsik .revision = 3,
5776e01781dSJozsef Kadlecsik .match = set_match_v3,
5786e01781dSJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v3),
5796e01781dSJozsef Kadlecsik .checkentry = set_match_v3_checkentry,
5806e01781dSJozsef Kadlecsik .destroy = set_match_v3_destroy,
5816e01781dSJozsef Kadlecsik .me = THIS_MODULE
5826e01781dSJozsef Kadlecsik },
5836e01781dSJozsef Kadlecsik {
5846e01781dSJozsef Kadlecsik .name = "set",
5856e01781dSJozsef Kadlecsik .family = NFPROTO_IPV6,
5866e01781dSJozsef Kadlecsik .revision = 3,
5876e01781dSJozsef Kadlecsik .match = set_match_v3,
5886e01781dSJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v3),
5896e01781dSJozsef Kadlecsik .checkentry = set_match_v3_checkentry,
5906e01781dSJozsef Kadlecsik .destroy = set_match_v3_destroy,
5916e01781dSJozsef Kadlecsik .me = THIS_MODULE
5926e01781dSJozsef Kadlecsik },
593a51b9199SJozsef Kadlecsik /* new revision for counters support: update, match */
594a51b9199SJozsef Kadlecsik {
595a51b9199SJozsef Kadlecsik .name = "set",
596a51b9199SJozsef Kadlecsik .family = NFPROTO_IPV4,
597a51b9199SJozsef Kadlecsik .revision = 4,
598a51b9199SJozsef Kadlecsik .match = set_match_v4,
599a51b9199SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v4),
600a51b9199SJozsef Kadlecsik .checkentry = set_match_v4_checkentry,
601a51b9199SJozsef Kadlecsik .destroy = set_match_v4_destroy,
602a51b9199SJozsef Kadlecsik .me = THIS_MODULE
603a51b9199SJozsef Kadlecsik },
604a51b9199SJozsef Kadlecsik {
605a51b9199SJozsef Kadlecsik .name = "set",
606a51b9199SJozsef Kadlecsik .family = NFPROTO_IPV6,
607a51b9199SJozsef Kadlecsik .revision = 4,
608a51b9199SJozsef Kadlecsik .match = set_match_v4,
609a51b9199SJozsef Kadlecsik .matchsize = sizeof(struct xt_set_info_match_v4),
610a51b9199SJozsef Kadlecsik .checkentry = set_match_v4_checkentry,
611a51b9199SJozsef Kadlecsik .destroy = set_match_v4_destroy,
612a51b9199SJozsef Kadlecsik .me = THIS_MODULE
613a51b9199SJozsef Kadlecsik },
614d956798dSJozsef Kadlecsik };
615d956798dSJozsef Kadlecsik
616d956798dSJozsef Kadlecsik static struct xt_target set_targets[] __read_mostly = {
617d956798dSJozsef Kadlecsik {
618d956798dSJozsef Kadlecsik .name = "SET",
619d956798dSJozsef Kadlecsik .revision = 0,
620d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4,
621d956798dSJozsef Kadlecsik .target = set_target_v0,
622d956798dSJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v0),
623d956798dSJozsef Kadlecsik .checkentry = set_target_v0_checkentry,
624d956798dSJozsef Kadlecsik .destroy = set_target_v0_destroy,
625d956798dSJozsef Kadlecsik .me = THIS_MODULE
626d956798dSJozsef Kadlecsik },
627d956798dSJozsef Kadlecsik {
628d956798dSJozsef Kadlecsik .name = "SET",
629d956798dSJozsef Kadlecsik .revision = 1,
630d956798dSJozsef Kadlecsik .family = NFPROTO_IPV4,
631ac8cc925SJozsef Kadlecsik .target = set_target_v1,
632ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v1),
633ac8cc925SJozsef Kadlecsik .checkentry = set_target_v1_checkentry,
634ac8cc925SJozsef Kadlecsik .destroy = set_target_v1_destroy,
635d956798dSJozsef Kadlecsik .me = THIS_MODULE
636d956798dSJozsef Kadlecsik },
637d956798dSJozsef Kadlecsik {
638d956798dSJozsef Kadlecsik .name = "SET",
639d956798dSJozsef Kadlecsik .revision = 1,
640d956798dSJozsef Kadlecsik .family = NFPROTO_IPV6,
641ac8cc925SJozsef Kadlecsik .target = set_target_v1,
642ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v1),
643ac8cc925SJozsef Kadlecsik .checkentry = set_target_v1_checkentry,
644ac8cc925SJozsef Kadlecsik .destroy = set_target_v1_destroy,
645ac8cc925SJozsef Kadlecsik .me = THIS_MODULE
646ac8cc925SJozsef Kadlecsik },
6473e0304a5SJozsef Kadlecsik /* --timeout and --exist flags support */
648ac8cc925SJozsef Kadlecsik {
649ac8cc925SJozsef Kadlecsik .name = "SET",
650ac8cc925SJozsef Kadlecsik .revision = 2,
651ac8cc925SJozsef Kadlecsik .family = NFPROTO_IPV4,
652ac8cc925SJozsef Kadlecsik .target = set_target_v2,
653ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v2),
654ac8cc925SJozsef Kadlecsik .checkentry = set_target_v2_checkentry,
655ac8cc925SJozsef Kadlecsik .destroy = set_target_v2_destroy,
656ac8cc925SJozsef Kadlecsik .me = THIS_MODULE
657ac8cc925SJozsef Kadlecsik },
658ac8cc925SJozsef Kadlecsik {
659ac8cc925SJozsef Kadlecsik .name = "SET",
660ac8cc925SJozsef Kadlecsik .revision = 2,
661ac8cc925SJozsef Kadlecsik .family = NFPROTO_IPV6,
662ac8cc925SJozsef Kadlecsik .target = set_target_v2,
663ac8cc925SJozsef Kadlecsik .targetsize = sizeof(struct xt_set_info_target_v2),
664ac8cc925SJozsef Kadlecsik .checkentry = set_target_v2_checkentry,
665ac8cc925SJozsef Kadlecsik .destroy = set_target_v2_destroy,
666d956798dSJozsef Kadlecsik .me = THIS_MODULE
667d956798dSJozsef Kadlecsik },
66876cea410SAnton Danilov /* --map-set support */
66976cea410SAnton Danilov {
67076cea410SAnton Danilov .name = "SET",
67176cea410SAnton Danilov .revision = 3,
67276cea410SAnton Danilov .family = NFPROTO_IPV4,
67376cea410SAnton Danilov .target = set_target_v3,
67476cea410SAnton Danilov .targetsize = sizeof(struct xt_set_info_target_v3),
67576cea410SAnton Danilov .checkentry = set_target_v3_checkentry,
67676cea410SAnton Danilov .destroy = set_target_v3_destroy,
67776cea410SAnton Danilov .me = THIS_MODULE
67876cea410SAnton Danilov },
67976cea410SAnton Danilov {
68076cea410SAnton Danilov .name = "SET",
68176cea410SAnton Danilov .revision = 3,
68276cea410SAnton Danilov .family = NFPROTO_IPV6,
68376cea410SAnton Danilov .target = set_target_v3,
68476cea410SAnton Danilov .targetsize = sizeof(struct xt_set_info_target_v3),
68576cea410SAnton Danilov .checkentry = set_target_v3_checkentry,
68676cea410SAnton Danilov .destroy = set_target_v3_destroy,
68776cea410SAnton Danilov .me = THIS_MODULE
68876cea410SAnton Danilov },
689d956798dSJozsef Kadlecsik };
690d956798dSJozsef Kadlecsik
xt_set_init(void)691d956798dSJozsef Kadlecsik static int __init xt_set_init(void)
692d956798dSJozsef Kadlecsik {
693d956798dSJozsef Kadlecsik int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
694d956798dSJozsef Kadlecsik
695d956798dSJozsef Kadlecsik if (!ret) {
696d956798dSJozsef Kadlecsik ret = xt_register_targets(set_targets,
697d956798dSJozsef Kadlecsik ARRAY_SIZE(set_targets));
698d956798dSJozsef Kadlecsik if (ret)
699d956798dSJozsef Kadlecsik xt_unregister_matches(set_matches,
700d956798dSJozsef Kadlecsik ARRAY_SIZE(set_matches));
701d956798dSJozsef Kadlecsik }
702d956798dSJozsef Kadlecsik return ret;
703d956798dSJozsef Kadlecsik }
704d956798dSJozsef Kadlecsik
xt_set_fini(void)705d956798dSJozsef Kadlecsik static void __exit xt_set_fini(void)
706d956798dSJozsef Kadlecsik {
707d956798dSJozsef Kadlecsik xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
708d956798dSJozsef Kadlecsik xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
709d956798dSJozsef Kadlecsik }
710d956798dSJozsef Kadlecsik
711d956798dSJozsef Kadlecsik module_init(xt_set_init);
712d956798dSJozsef Kadlecsik module_exit(xt_set_fini);
713