xref: /openbmc/linux/net/netfilter/xt_set.c (revision bd96b4c7)
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