xref: /openbmc/linux/net/netfilter/xt_CT.c (revision 0838aa7f)
1 /*
2  * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/module.h>
10 #include <linux/gfp.h>
11 #include <linux/skbuff.h>
12 #include <linux/netfilter_ipv4/ip_tables.h>
13 #include <linux/netfilter_ipv6/ip6_tables.h>
14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter/xt_CT.h>
16 #include <net/netfilter/nf_conntrack.h>
17 #include <net/netfilter/nf_conntrack_l4proto.h>
18 #include <net/netfilter/nf_conntrack_helper.h>
19 #include <net/netfilter/nf_conntrack_ecache.h>
20 #include <net/netfilter/nf_conntrack_timeout.h>
21 #include <net/netfilter/nf_conntrack_zones.h>
22 
23 static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
24 {
25 	/* Previously seen (loopback)? Ignore. */
26 	if (skb->nfct != NULL)
27 		return XT_CONTINUE;
28 
29 	/* special case the untracked ct : we want the percpu object */
30 	if (!ct)
31 		ct = nf_ct_untracked_get();
32 	atomic_inc(&ct->ct_general.use);
33 	skb->nfct = &ct->ct_general;
34 	skb->nfctinfo = IP_CT_NEW;
35 
36 	return XT_CONTINUE;
37 }
38 
39 static unsigned int xt_ct_target_v0(struct sk_buff *skb,
40 				    const struct xt_action_param *par)
41 {
42 	const struct xt_ct_target_info *info = par->targinfo;
43 	struct nf_conn *ct = info->ct;
44 
45 	return xt_ct_target(skb, ct);
46 }
47 
48 static unsigned int xt_ct_target_v1(struct sk_buff *skb,
49 				    const struct xt_action_param *par)
50 {
51 	const struct xt_ct_target_info_v1 *info = par->targinfo;
52 	struct nf_conn *ct = info->ct;
53 
54 	return xt_ct_target(skb, ct);
55 }
56 
57 static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
58 {
59 	if (par->family == NFPROTO_IPV4) {
60 		const struct ipt_entry *e = par->entryinfo;
61 
62 		if (e->ip.invflags & IPT_INV_PROTO)
63 			return 0;
64 		return e->ip.proto;
65 	} else if (par->family == NFPROTO_IPV6) {
66 		const struct ip6t_entry *e = par->entryinfo;
67 
68 		if (e->ipv6.invflags & IP6T_INV_PROTO)
69 			return 0;
70 		return e->ipv6.proto;
71 	} else
72 		return 0;
73 }
74 
75 static int
76 xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
77 		 const struct xt_tgchk_param *par)
78 {
79 	struct nf_conntrack_helper *helper;
80 	struct nf_conn_help *help;
81 	u8 proto;
82 
83 	proto = xt_ct_find_proto(par);
84 	if (!proto) {
85 		pr_info("You must specify a L4 protocol, and not use "
86 			"inversions on it.\n");
87 		return -ENOENT;
88 	}
89 
90 	helper = nf_conntrack_helper_try_module_get(helper_name, par->family,
91 						    proto);
92 	if (helper == NULL) {
93 		pr_info("No such helper \"%s\"\n", helper_name);
94 		return -ENOENT;
95 	}
96 
97 	help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
98 	if (help == NULL) {
99 		module_put(helper->me);
100 		return -ENOMEM;
101 	}
102 
103 	help->helper = helper;
104 	return 0;
105 }
106 
107 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
108 static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
109 {
110 	typeof(nf_ct_timeout_put_hook) timeout_put;
111 
112 	timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
113 	if (timeout_put)
114 		timeout_put(timeout);
115 }
116 #endif
117 
118 static int
119 xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
120 		  const char *timeout_name)
121 {
122 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
123 	typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
124 	struct ctnl_timeout *timeout;
125 	struct nf_conn_timeout *timeout_ext;
126 	struct nf_conntrack_l4proto *l4proto;
127 	int ret = 0;
128 	u8 proto;
129 
130 	rcu_read_lock();
131 	timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
132 	if (timeout_find_get == NULL) {
133 		ret = -ENOENT;
134 		pr_info("Timeout policy base is empty\n");
135 		goto out;
136 	}
137 
138 	proto = xt_ct_find_proto(par);
139 	if (!proto) {
140 		ret = -EINVAL;
141 		pr_info("You must specify a L4 protocol, and not use "
142 			"inversions on it.\n");
143 		goto out;
144 	}
145 
146 	timeout = timeout_find_get(timeout_name);
147 	if (timeout == NULL) {
148 		ret = -ENOENT;
149 		pr_info("No such timeout policy \"%s\"\n", timeout_name);
150 		goto out;
151 	}
152 
153 	if (timeout->l3num != par->family) {
154 		ret = -EINVAL;
155 		pr_info("Timeout policy `%s' can only be used by L3 protocol "
156 			"number %d\n", timeout_name, timeout->l3num);
157 		goto err_put_timeout;
158 	}
159 	/* Make sure the timeout policy matches any existing protocol tracker,
160 	 * otherwise default to generic.
161 	 */
162 	l4proto = __nf_ct_l4proto_find(par->family, proto);
163 	if (timeout->l4proto->l4proto != l4proto->l4proto) {
164 		ret = -EINVAL;
165 		pr_info("Timeout policy `%s' can only be used by L4 protocol "
166 			"number %d\n",
167 			timeout_name, timeout->l4proto->l4proto);
168 		goto err_put_timeout;
169 	}
170 	timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
171 	if (timeout_ext == NULL)
172 		ret = -ENOMEM;
173 
174 err_put_timeout:
175 	__xt_ct_tg_timeout_put(timeout);
176 out:
177 	rcu_read_unlock();
178 	return ret;
179 #else
180 	return -EOPNOTSUPP;
181 #endif
182 }
183 
184 static int xt_ct_tg_check(const struct xt_tgchk_param *par,
185 			  struct xt_ct_target_info_v1 *info)
186 {
187 	struct nf_conn *ct;
188 	int ret = -EOPNOTSUPP;
189 
190 	if (info->flags & XT_CT_NOTRACK) {
191 		ct = NULL;
192 		goto out;
193 	}
194 
195 #ifndef CONFIG_NF_CONNTRACK_ZONES
196 	if (info->zone)
197 		goto err1;
198 #endif
199 
200 	ret = nf_ct_l3proto_try_module_get(par->family);
201 	if (ret < 0)
202 		goto err1;
203 
204 	ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL);
205 	ret = PTR_ERR(ct);
206 	if (IS_ERR(ct))
207 		goto err2;
208 
209 	ret = 0;
210 	if ((info->ct_events || info->exp_events) &&
211 	    !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
212 				  GFP_KERNEL)) {
213 		ret = -EINVAL;
214 		goto err3;
215 	}
216 
217 	if (info->helper[0]) {
218 		ret = xt_ct_set_helper(ct, info->helper, par);
219 		if (ret < 0)
220 			goto err3;
221 	}
222 
223 	if (info->timeout[0]) {
224 		ret = xt_ct_set_timeout(ct, par, info->timeout);
225 		if (ret < 0)
226 			goto err3;
227 	}
228 	__set_bit(IPS_CONFIRMED_BIT, &ct->status);
229 	nf_conntrack_get(&ct->ct_general);
230 out:
231 	info->ct = ct;
232 	return 0;
233 
234 err3:
235 	nf_conntrack_free(ct);
236 err2:
237 	nf_ct_l3proto_module_put(par->family);
238 err1:
239 	return ret;
240 }
241 
242 static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
243 {
244 	struct xt_ct_target_info *info = par->targinfo;
245 	struct xt_ct_target_info_v1 info_v1 = {
246 		.flags 		= info->flags,
247 		.zone		= info->zone,
248 		.ct_events	= info->ct_events,
249 		.exp_events	= info->exp_events,
250 	};
251 	int ret;
252 
253 	if (info->flags & ~XT_CT_NOTRACK)
254 		return -EINVAL;
255 
256 	memcpy(info_v1.helper, info->helper, sizeof(info->helper));
257 
258 	ret = xt_ct_tg_check(par, &info_v1);
259 	if (ret < 0)
260 		return ret;
261 
262 	info->ct = info_v1.ct;
263 
264 	return ret;
265 }
266 
267 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
268 {
269 	struct xt_ct_target_info_v1 *info = par->targinfo;
270 
271 	if (info->flags & ~XT_CT_NOTRACK)
272 		return -EINVAL;
273 
274 	return xt_ct_tg_check(par, par->targinfo);
275 }
276 
277 static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par)
278 {
279 	struct xt_ct_target_info_v1 *info = par->targinfo;
280 
281 	if (info->flags & ~XT_CT_MASK)
282 		return -EINVAL;
283 
284 	return xt_ct_tg_check(par, par->targinfo);
285 }
286 
287 static void xt_ct_destroy_timeout(struct nf_conn *ct)
288 {
289 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
290 	struct nf_conn_timeout *timeout_ext;
291 	typeof(nf_ct_timeout_put_hook) timeout_put;
292 
293 	rcu_read_lock();
294 	timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
295 
296 	if (timeout_put) {
297 		timeout_ext = nf_ct_timeout_find(ct);
298 		if (timeout_ext)
299 			timeout_put(timeout_ext->timeout);
300 	}
301 	rcu_read_unlock();
302 #endif
303 }
304 
305 static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
306 			     struct xt_ct_target_info_v1 *info)
307 {
308 	struct nf_conn *ct = info->ct;
309 	struct nf_conn_help *help;
310 
311 	if (ct && !nf_ct_is_untracked(ct)) {
312 		help = nfct_help(ct);
313 		if (help)
314 			module_put(help->helper->me);
315 
316 		nf_ct_l3proto_module_put(par->family);
317 
318 		xt_ct_destroy_timeout(ct);
319 		nf_ct_put(info->ct);
320 	}
321 }
322 
323 static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
324 {
325 	struct xt_ct_target_info *info = par->targinfo;
326 	struct xt_ct_target_info_v1 info_v1 = {
327 		.flags 		= info->flags,
328 		.zone		= info->zone,
329 		.ct_events	= info->ct_events,
330 		.exp_events	= info->exp_events,
331 		.ct		= info->ct,
332 	};
333 	memcpy(info_v1.helper, info->helper, sizeof(info->helper));
334 
335 	xt_ct_tg_destroy(par, &info_v1);
336 }
337 
338 static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
339 {
340 	xt_ct_tg_destroy(par, par->targinfo);
341 }
342 
343 static struct xt_target xt_ct_tg_reg[] __read_mostly = {
344 	{
345 		.name		= "CT",
346 		.family		= NFPROTO_UNSPEC,
347 		.targetsize	= sizeof(struct xt_ct_target_info),
348 		.checkentry	= xt_ct_tg_check_v0,
349 		.destroy	= xt_ct_tg_destroy_v0,
350 		.target		= xt_ct_target_v0,
351 		.table		= "raw",
352 		.me		= THIS_MODULE,
353 	},
354 	{
355 		.name		= "CT",
356 		.family		= NFPROTO_UNSPEC,
357 		.revision	= 1,
358 		.targetsize	= sizeof(struct xt_ct_target_info_v1),
359 		.checkentry	= xt_ct_tg_check_v1,
360 		.destroy	= xt_ct_tg_destroy_v1,
361 		.target		= xt_ct_target_v1,
362 		.table		= "raw",
363 		.me		= THIS_MODULE,
364 	},
365 	{
366 		.name		= "CT",
367 		.family		= NFPROTO_UNSPEC,
368 		.revision	= 2,
369 		.targetsize	= sizeof(struct xt_ct_target_info_v1),
370 		.checkentry	= xt_ct_tg_check_v2,
371 		.destroy	= xt_ct_tg_destroy_v1,
372 		.target		= xt_ct_target_v1,
373 		.table		= "raw",
374 		.me		= THIS_MODULE,
375 	},
376 };
377 
378 static unsigned int
379 notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
380 {
381 	/* Previously seen (loopback)? Ignore. */
382 	if (skb->nfct != NULL)
383 		return XT_CONTINUE;
384 
385 	skb->nfct = &nf_ct_untracked_get()->ct_general;
386 	skb->nfctinfo = IP_CT_NEW;
387 	nf_conntrack_get(skb->nfct);
388 
389 	return XT_CONTINUE;
390 }
391 
392 static int notrack_chk(const struct xt_tgchk_param *par)
393 {
394 	if (!par->net->xt.notrack_deprecated_warning) {
395 		pr_info("netfilter: NOTRACK target is deprecated, "
396 			"use CT instead or upgrade iptables\n");
397 		par->net->xt.notrack_deprecated_warning = true;
398 	}
399 	return 0;
400 }
401 
402 static struct xt_target notrack_tg_reg __read_mostly = {
403 	.name		= "NOTRACK",
404 	.revision	= 0,
405 	.family		= NFPROTO_UNSPEC,
406 	.checkentry	= notrack_chk,
407 	.target		= notrack_tg,
408 	.table		= "raw",
409 	.me		= THIS_MODULE,
410 };
411 
412 static int __init xt_ct_tg_init(void)
413 {
414 	int ret;
415 
416 	ret = xt_register_target(&notrack_tg_reg);
417 	if (ret < 0)
418 		return ret;
419 
420 	ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
421 	if (ret < 0) {
422 		xt_unregister_target(&notrack_tg_reg);
423 		return ret;
424 	}
425 	return 0;
426 }
427 
428 static void __exit xt_ct_tg_exit(void)
429 {
430 	xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
431 	xt_unregister_target(&notrack_tg_reg);
432 }
433 
434 module_init(xt_ct_tg_init);
435 module_exit(xt_ct_tg_exit);
436 
437 MODULE_LICENSE("GPL");
438 MODULE_DESCRIPTION("Xtables: connection tracking target");
439 MODULE_ALIAS("ipt_CT");
440 MODULE_ALIAS("ip6t_CT");
441 MODULE_ALIAS("ipt_NOTRACK");
442 MODULE_ALIAS("ip6t_NOTRACK");
443