Linux Audio

Check our new training course

Embedded Linux training

Mar 10-20, 2025, special US time zones
Register
Loading...
v4.10.11
 
  1/*
  2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
  3 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation (or any later at your option).
  8 */
  9#include <linux/init.h>
 10#include <linux/module.h>
 11#include <linux/kernel.h>
 12#include <linux/rculist.h>
 13#include <linux/rculist_nulls.h>
 14#include <linux/types.h>
 15#include <linux/timer.h>
 16#include <linux/security.h>
 17#include <linux/skbuff.h>
 18#include <linux/errno.h>
 19#include <linux/netlink.h>
 20#include <linux/spinlock.h>
 21#include <linux/interrupt.h>
 22#include <linux/slab.h>
 23
 24#include <linux/netfilter.h>
 25#include <net/netlink.h>
 
 26#include <net/sock.h>
 27#include <net/netfilter/nf_conntrack.h>
 28#include <net/netfilter/nf_conntrack_core.h>
 29#include <net/netfilter/nf_conntrack_l3proto.h>
 30#include <net/netfilter/nf_conntrack_l4proto.h>
 31#include <net/netfilter/nf_conntrack_tuple.h>
 32#include <net/netfilter/nf_conntrack_timeout.h>
 33
 34#include <linux/netfilter/nfnetlink.h>
 35#include <linux/netfilter/nfnetlink_cttimeout.h>
 36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 37MODULE_LICENSE("GPL");
 38MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 39MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
 40
 41static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
 42	[CTA_TIMEOUT_NAME]	= { .type = NLA_NUL_STRING,
 43				    .len  = CTNL_TIMEOUT_NAME_MAX - 1},
 44	[CTA_TIMEOUT_L3PROTO]	= { .type = NLA_U16 },
 45	[CTA_TIMEOUT_L4PROTO]	= { .type = NLA_U8 },
 46	[CTA_TIMEOUT_DATA]	= { .type = NLA_NESTED },
 47};
 48
 
 
 
 
 
 49static int
 50ctnl_timeout_parse_policy(void *timeouts, struct nf_conntrack_l4proto *l4proto,
 
 51			  struct net *net, const struct nlattr *attr)
 52{
 
 53	int ret = 0;
 54
 55	if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
 56		struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
 57
 58		ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max,
 59				       attr, l4proto->ctnl_timeout.nla_policy);
 60		if (ret < 0)
 61			return ret;
 62
 63		ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
 64	}
 
 
 
 
 
 
 
 
 
 
 65	return ret;
 66}
 67
 68static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
 69				 struct sk_buff *skb,
 70				 const struct nlmsghdr *nlh,
 71				 const struct nlattr * const cda[])
 72{
 
 73	__u16 l3num;
 74	__u8 l4num;
 75	struct nf_conntrack_l4proto *l4proto;
 76	struct ctnl_timeout *timeout, *matching = NULL;
 77	char *name;
 78	int ret;
 79
 80	if (!cda[CTA_TIMEOUT_NAME] ||
 81	    !cda[CTA_TIMEOUT_L3PROTO] ||
 82	    !cda[CTA_TIMEOUT_L4PROTO] ||
 83	    !cda[CTA_TIMEOUT_DATA])
 84		return -EINVAL;
 85
 86	name = nla_data(cda[CTA_TIMEOUT_NAME]);
 87	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
 88	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
 89
 90	list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
 91		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
 92			continue;
 93
 94		if (nlh->nlmsg_flags & NLM_F_EXCL)
 95			return -EEXIST;
 96
 97		matching = timeout;
 98		break;
 99	}
100
101	if (matching) {
102		if (nlh->nlmsg_flags & NLM_F_REPLACE) {
103			/* You cannot replace one timeout policy by another of
104			 * different kind, sorry.
105			 */
106			if (matching->l3num != l3num ||
107			    matching->l4proto->l4proto != l4num)
108				return -EINVAL;
109
110			return ctnl_timeout_parse_policy(&matching->data,
111							 matching->l4proto, net,
 
112							 cda[CTA_TIMEOUT_DATA]);
113		}
114
115		return -EBUSY;
116	}
117
118	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
119
120	/* This protocol is not supportted, skip. */
121	if (l4proto->l4proto != l4num) {
122		ret = -EOPNOTSUPP;
123		goto err_proto_put;
124	}
125
126	timeout = kzalloc(sizeof(struct ctnl_timeout) +
127			  l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
128	if (timeout == NULL) {
129		ret = -ENOMEM;
130		goto err_proto_put;
131	}
132
133	ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, net,
134					cda[CTA_TIMEOUT_DATA]);
135	if (ret < 0)
136		goto err;
137
138	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
139	timeout->l3num = l3num;
140	timeout->l4proto = l4proto;
141	atomic_set(&timeout->refcnt, 1);
142	list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
 
143
144	return 0;
145err:
146	kfree(timeout);
147err_proto_put:
148	nf_ct_l4proto_put(l4proto);
149	return ret;
150}
151
152static int
153ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
154		       int event, struct ctnl_timeout *timeout)
155{
156	struct nlmsghdr *nlh;
157	struct nfgenmsg *nfmsg;
158	unsigned int flags = portid ? NLM_F_MULTI : 0;
159	struct nf_conntrack_l4proto *l4proto = timeout->l4proto;
 
 
160
161	event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
162	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
163	if (nlh == NULL)
 
164		goto nlmsg_failure;
165
166	nfmsg = nlmsg_data(nlh);
167	nfmsg->nfgen_family = AF_UNSPEC;
168	nfmsg->version = NFNETLINK_V0;
169	nfmsg->res_id = 0;
170
171	if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
172	    nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
173	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
 
174	    nla_put_be32(skb, CTA_TIMEOUT_USE,
175			 htonl(atomic_read(&timeout->refcnt))))
176		goto nla_put_failure;
177
178	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
179		struct nlattr *nest_parms;
180		int ret;
181
182		nest_parms = nla_nest_start(skb,
183					    CTA_TIMEOUT_DATA | NLA_F_NESTED);
184		if (!nest_parms)
185			goto nla_put_failure;
186
187		ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
188		if (ret < 0)
189			goto nla_put_failure;
190
191		nla_nest_end(skb, nest_parms);
192	}
193
194	nlmsg_end(skb, nlh);
195	return skb->len;
196
197nlmsg_failure:
198nla_put_failure:
199	nlmsg_cancel(skb, nlh);
200	return -1;
201}
202
203static int
204ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
205{
 
206	struct net *net = sock_net(skb->sk);
207	struct ctnl_timeout *cur, *last;
208
209	if (cb->args[2])
210		return 0;
211
212	last = (struct ctnl_timeout *)cb->args[1];
213	if (cb->args[1])
214		cb->args[1] = 0;
215
216	rcu_read_lock();
217	list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
 
218		if (last) {
219			if (cur != last)
220				continue;
221
222			last = NULL;
223		}
224		if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
225					   cb->nlh->nlmsg_seq,
226					   NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
227					   IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
228			cb->args[1] = (unsigned long)cur;
229			break;
230		}
231	}
232	if (!cb->args[1])
233		cb->args[2] = 1;
234	rcu_read_unlock();
235	return skb->len;
236}
237
238static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
239				 struct sk_buff *skb,
240				 const struct nlmsghdr *nlh,
241				 const struct nlattr * const cda[])
242{
 
243	int ret = -ENOENT;
244	char *name;
245	struct ctnl_timeout *cur;
246
247	if (nlh->nlmsg_flags & NLM_F_DUMP) {
248		struct netlink_dump_control c = {
249			.dump = ctnl_timeout_dump,
250		};
251		return netlink_dump_start(ctnl, skb, nlh, &c);
252	}
253
254	if (!cda[CTA_TIMEOUT_NAME])
255		return -EINVAL;
256	name = nla_data(cda[CTA_TIMEOUT_NAME]);
257
258	list_for_each_entry(cur, &net->nfct_timeout_list, head) {
259		struct sk_buff *skb2;
260
261		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
262			continue;
263
264		skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
265		if (skb2 == NULL) {
266			ret = -ENOMEM;
267			break;
268		}
269
270		ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
271					     nlh->nlmsg_seq,
272					     NFNL_MSG_TYPE(nlh->nlmsg_type),
273					     IPCTNL_MSG_TIMEOUT_NEW, cur);
274		if (ret <= 0) {
275			kfree_skb(skb2);
276			break;
277		}
278		ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
279					MSG_DONTWAIT);
280		if (ret > 0)
281			ret = 0;
282
283		/* this avoids a loop in nfnetlink. */
284		return ret == -EAGAIN ? -ENOBUFS : ret;
285	}
286	return ret;
287}
288
289static void untimeout(struct nf_conntrack_tuple_hash *i,
290		      struct ctnl_timeout *timeout)
291{
292	struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
293	struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
294
295	if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
296		RCU_INIT_POINTER(timeout_ext->timeout, NULL);
297}
298
299static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
300{
301	struct nf_conntrack_tuple_hash *h;
302	const struct hlist_nulls_node *nn;
303	unsigned int last_hsize;
304	spinlock_t *lock;
305	int i, cpu;
306
307	for_each_possible_cpu(cpu) {
308		struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
309
310		spin_lock_bh(&pcpu->lock);
311		hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode)
312			untimeout(h, timeout);
313		spin_unlock_bh(&pcpu->lock);
314	}
315
316	local_bh_disable();
317restart:
318	last_hsize = nf_conntrack_htable_size;
319	for (i = 0; i < last_hsize; i++) {
320		lock = &nf_conntrack_locks[i % CONNTRACK_LOCKS];
321		nf_conntrack_lock(lock);
322		if (last_hsize != nf_conntrack_htable_size) {
323			spin_unlock(lock);
324			goto restart;
325		}
326
327		hlist_nulls_for_each_entry(h, nn, &nf_conntrack_hash[i], hnnode)
328			untimeout(h, timeout);
329		spin_unlock(lock);
330	}
331	local_bh_enable();
332}
333
334/* try to delete object, fail if it is still in use. */
335static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
336{
337	int ret = 0;
338
339	/* We want to avoid races with ctnl_timeout_put. So only when the
340	 * current refcnt is 1, we decrease it to 0.
341	 */
342	if (atomic_cmpxchg(&timeout->refcnt, 1, 0) == 1) {
343		/* We are protected by nfnl mutex. */
344		list_del_rcu(&timeout->head);
345		nf_ct_l4proto_put(timeout->l4proto);
346		ctnl_untimeout(net, timeout);
347		kfree_rcu(timeout, rcu_head);
348	} else {
349		ret = -EBUSY;
350	}
351	return ret;
352}
353
354static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
355				 struct sk_buff *skb,
356				 const struct nlmsghdr *nlh,
357				 const struct nlattr * const cda[])
358{
 
359	struct ctnl_timeout *cur, *tmp;
360	int ret = -ENOENT;
361	char *name;
362
363	if (!cda[CTA_TIMEOUT_NAME]) {
364		list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
365					 head)
366			ctnl_timeout_try_del(net, cur);
367
368		return 0;
369	}
370	name = nla_data(cda[CTA_TIMEOUT_NAME]);
371
372	list_for_each_entry(cur, &net->nfct_timeout_list, head) {
373		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
374			continue;
375
376		ret = ctnl_timeout_try_del(net, cur);
377		if (ret < 0)
378			return ret;
379
380		break;
381	}
382	return ret;
383}
384
385static int cttimeout_default_set(struct net *net, struct sock *ctnl,
386				 struct sk_buff *skb,
387				 const struct nlmsghdr *nlh,
388				 const struct nlattr * const cda[])
389{
390	__u16 l3num;
391	__u8 l4num;
392	struct nf_conntrack_l4proto *l4proto;
393	unsigned int *timeouts;
394	int ret;
395
396	if (!cda[CTA_TIMEOUT_L3PROTO] ||
397	    !cda[CTA_TIMEOUT_L4PROTO] ||
398	    !cda[CTA_TIMEOUT_DATA])
399		return -EINVAL;
400
401	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
402	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
403	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
404
405	/* This protocol is not supported, skip. */
406	if (l4proto->l4proto != l4num) {
407		ret = -EOPNOTSUPP;
408		goto err;
409	}
410
411	timeouts = l4proto->get_timeouts(net);
412
413	ret = ctnl_timeout_parse_policy(timeouts, l4proto, net,
414					cda[CTA_TIMEOUT_DATA]);
415	if (ret < 0)
416		goto err;
417
418	nf_ct_l4proto_put(l4proto);
419	return 0;
420err:
421	nf_ct_l4proto_put(l4proto);
422	return ret;
423}
424
425static int
426cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
427			    u32 seq, u32 type, int event,
428			    struct nf_conntrack_l4proto *l4proto)
 
429{
430	struct nlmsghdr *nlh;
431	struct nfgenmsg *nfmsg;
432	unsigned int flags = portid ? NLM_F_MULTI : 0;
 
 
433
434	event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
435	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
436	if (nlh == NULL)
 
437		goto nlmsg_failure;
438
439	nfmsg = nlmsg_data(nlh);
440	nfmsg->nfgen_family = AF_UNSPEC;
441	nfmsg->version = NFNETLINK_V0;
442	nfmsg->res_id = 0;
443
444	if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l4proto->l3proto)) ||
445	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
446		goto nla_put_failure;
447
448	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
449		struct nlattr *nest_parms;
450		unsigned int *timeouts = l4proto->get_timeouts(net);
451		int ret;
452
453		nest_parms = nla_nest_start(skb,
454					    CTA_TIMEOUT_DATA | NLA_F_NESTED);
455		if (!nest_parms)
456			goto nla_put_failure;
457
458		ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
459		if (ret < 0)
460			goto nla_put_failure;
461
462		nla_nest_end(skb, nest_parms);
463	}
464
465	nlmsg_end(skb, nlh);
466	return skb->len;
467
468nlmsg_failure:
469nla_put_failure:
470	nlmsg_cancel(skb, nlh);
471	return -1;
472}
473
474static int cttimeout_default_get(struct net *net, struct sock *ctnl,
475				 struct sk_buff *skb,
476				 const struct nlmsghdr *nlh,
477				 const struct nlattr * const cda[])
478{
 
 
 
479	__u16 l3num;
480	__u8 l4num;
481	struct nf_conntrack_l4proto *l4proto;
482	struct sk_buff *skb2;
483	int ret, err;
484
485	if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
486		return -EINVAL;
487
488	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
489	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
490	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
491
492	/* This protocol is not supported, skip. */
493	if (l4proto->l4proto != l4num) {
494		err = -EOPNOTSUPP;
495		goto err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496	}
497
 
 
 
498	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
499	if (skb2 == NULL) {
500		err = -ENOMEM;
501		goto err;
502	}
503
504	ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid,
505					  nlh->nlmsg_seq,
506					  NFNL_MSG_TYPE(nlh->nlmsg_type),
 
507					  IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
508					  l4proto);
509	if (ret <= 0) {
510		kfree_skb(skb2);
511		err = -ENOMEM;
512		goto err;
513	}
514	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
515	if (ret > 0)
516		ret = 0;
517
518	/* this avoids a loop in nfnetlink. */
519	return ret == -EAGAIN ? -ENOBUFS : ret;
520err:
521	nf_ct_l4proto_put(l4proto);
522	return err;
523}
524
525#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
526static struct ctnl_timeout *
527ctnl_timeout_find_get(struct net *net, const char *name)
528{
 
529	struct ctnl_timeout *timeout, *matching = NULL;
530
531	rcu_read_lock();
532	list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
533		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
534			continue;
535
536		if (!try_module_get(THIS_MODULE))
537			goto err;
538
539		if (!atomic_inc_not_zero(&timeout->refcnt)) {
540			module_put(THIS_MODULE);
541			goto err;
542		}
543		matching = timeout;
544		break;
545	}
546err:
547	rcu_read_unlock();
548	return matching;
549}
550
551static void ctnl_timeout_put(struct ctnl_timeout *timeout)
552{
553	if (atomic_dec_and_test(&timeout->refcnt))
554		kfree_rcu(timeout, rcu_head);
555
556	module_put(THIS_MODULE);
 
 
 
557}
558#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
559
560static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
561	[IPCTNL_MSG_TIMEOUT_NEW]	= { .call = cttimeout_new_timeout,
562					    .attr_count = CTA_TIMEOUT_MAX,
563					    .policy = cttimeout_nla_policy },
564	[IPCTNL_MSG_TIMEOUT_GET]	= { .call = cttimeout_get_timeout,
565					    .attr_count = CTA_TIMEOUT_MAX,
566					    .policy = cttimeout_nla_policy },
567	[IPCTNL_MSG_TIMEOUT_DELETE]	= { .call = cttimeout_del_timeout,
568					    .attr_count = CTA_TIMEOUT_MAX,
569					    .policy = cttimeout_nla_policy },
570	[IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set,
571					    .attr_count = CTA_TIMEOUT_MAX,
572					    .policy = cttimeout_nla_policy },
573	[IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get,
574					    .attr_count = CTA_TIMEOUT_MAX,
575					    .policy = cttimeout_nla_policy },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576};
577
578static const struct nfnetlink_subsystem cttimeout_subsys = {
579	.name				= "conntrack_timeout",
580	.subsys_id			= NFNL_SUBSYS_CTNETLINK_TIMEOUT,
581	.cb_count			= IPCTNL_MSG_TIMEOUT_MAX,
582	.cb				= cttimeout_cb,
583};
584
585MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
586
587static int __net_init cttimeout_net_init(struct net *net)
588{
589	INIT_LIST_HEAD(&net->nfct_timeout_list);
 
 
 
590
591	return 0;
592}
593
 
 
 
 
 
 
 
 
 
 
 
 
 
594static void __net_exit cttimeout_net_exit(struct net *net)
595{
 
596	struct ctnl_timeout *cur, *tmp;
597
598	ctnl_untimeout(net, NULL);
 
599
600	list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
601		list_del_rcu(&cur->head);
602		nf_ct_l4proto_put(cur->l4proto);
 
603
604		if (atomic_dec_and_test(&cur->refcnt))
605			kfree_rcu(cur, rcu_head);
606	}
607}
608
609static struct pernet_operations cttimeout_ops = {
610	.init	= cttimeout_net_init,
 
611	.exit	= cttimeout_net_exit,
 
 
 
 
 
 
 
612};
613
614static int __init cttimeout_init(void)
615{
616	int ret;
617
618	ret = register_pernet_subsys(&cttimeout_ops);
619	if (ret < 0)
620		return ret;
621
622	ret = nfnetlink_subsys_register(&cttimeout_subsys);
623	if (ret < 0) {
624		pr_err("cttimeout_init: cannot register cttimeout with "
625			"nfnetlink.\n");
626		goto err_out;
627	}
628#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
629	RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
630	RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
631#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
632	return 0;
633
634err_out:
635	unregister_pernet_subsys(&cttimeout_ops);
636	return ret;
637}
638
639static void __exit cttimeout_exit(void)
640{
641	pr_info("cttimeout: unregistering from nfnetlink.\n");
 
 
 
642
 
 
 
 
 
643	nfnetlink_subsys_unregister(&cttimeout_subsys);
644
645	unregister_pernet_subsys(&cttimeout_ops);
646#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
647	RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
648	RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
649#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
650	rcu_barrier();
651}
652
653module_init(cttimeout_init);
654module_exit(cttimeout_exit);
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
  4 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
 
 
 
 
  5 */
  6#include <linux/init.h>
  7#include <linux/module.h>
  8#include <linux/kernel.h>
  9#include <linux/rculist.h>
 10#include <linux/rculist_nulls.h>
 11#include <linux/types.h>
 12#include <linux/timer.h>
 13#include <linux/security.h>
 14#include <linux/skbuff.h>
 15#include <linux/errno.h>
 16#include <linux/netlink.h>
 17#include <linux/spinlock.h>
 18#include <linux/interrupt.h>
 19#include <linux/slab.h>
 20
 21#include <linux/netfilter.h>
 22#include <net/netlink.h>
 23#include <net/netns/generic.h>
 24#include <net/sock.h>
 25#include <net/netfilter/nf_conntrack.h>
 26#include <net/netfilter/nf_conntrack_core.h>
 
 27#include <net/netfilter/nf_conntrack_l4proto.h>
 28#include <net/netfilter/nf_conntrack_tuple.h>
 29#include <net/netfilter/nf_conntrack_timeout.h>
 30
 31#include <linux/netfilter/nfnetlink.h>
 32#include <linux/netfilter/nfnetlink_cttimeout.h>
 33
 34static unsigned int nfct_timeout_id __read_mostly;
 35
 36struct ctnl_timeout {
 37	struct list_head	head;
 38	struct list_head	free_head;
 39	struct rcu_head		rcu_head;
 40	refcount_t		refcnt;
 41	char			name[CTNL_TIMEOUT_NAME_MAX];
 42
 43	/* must be at the end */
 44	struct nf_ct_timeout	timeout;
 45};
 46
 47struct nfct_timeout_pernet {
 48	struct list_head	nfct_timeout_list;
 49	struct list_head	nfct_timeout_freelist;
 50};
 51
 52MODULE_LICENSE("GPL");
 53MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 54MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
 55
 56static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
 57	[CTA_TIMEOUT_NAME]	= { .type = NLA_NUL_STRING,
 58				    .len  = CTNL_TIMEOUT_NAME_MAX - 1},
 59	[CTA_TIMEOUT_L3PROTO]	= { .type = NLA_U16 },
 60	[CTA_TIMEOUT_L4PROTO]	= { .type = NLA_U8 },
 61	[CTA_TIMEOUT_DATA]	= { .type = NLA_NESTED },
 62};
 63
 64static struct nfct_timeout_pernet *nfct_timeout_pernet(struct net *net)
 65{
 66	return net_generic(net, nfct_timeout_id);
 67}
 68
 69static int
 70ctnl_timeout_parse_policy(void *timeout,
 71			  const struct nf_conntrack_l4proto *l4proto,
 72			  struct net *net, const struct nlattr *attr)
 73{
 74	struct nlattr **tb;
 75	int ret = 0;
 76
 77	tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb),
 78		     GFP_KERNEL);
 79
 80	if (!tb)
 81		return -ENOMEM;
 
 
 82
 83	ret = nla_parse_nested_deprecated(tb,
 84					  l4proto->ctnl_timeout.nlattr_max,
 85					  attr,
 86					  l4proto->ctnl_timeout.nla_policy,
 87					  NULL);
 88	if (ret < 0)
 89		goto err;
 90
 91	ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeout);
 92
 93err:
 94	kfree(tb);
 95	return ret;
 96}
 97
 98static int cttimeout_new_timeout(struct sk_buff *skb,
 99				 const struct nfnl_info *info,
 
100				 const struct nlattr * const cda[])
101{
102	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
103	__u16 l3num;
104	__u8 l4num;
105	const struct nf_conntrack_l4proto *l4proto;
106	struct ctnl_timeout *timeout, *matching = NULL;
107	char *name;
108	int ret;
109
110	if (!cda[CTA_TIMEOUT_NAME] ||
111	    !cda[CTA_TIMEOUT_L3PROTO] ||
112	    !cda[CTA_TIMEOUT_L4PROTO] ||
113	    !cda[CTA_TIMEOUT_DATA])
114		return -EINVAL;
115
116	name = nla_data(cda[CTA_TIMEOUT_NAME]);
117	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
118	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
119
120	list_for_each_entry(timeout, &pernet->nfct_timeout_list, head) {
121		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
122			continue;
123
124		if (info->nlh->nlmsg_flags & NLM_F_EXCL)
125			return -EEXIST;
126
127		matching = timeout;
128		break;
129	}
130
131	if (matching) {
132		if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
133			/* You cannot replace one timeout policy by another of
134			 * different kind, sorry.
135			 */
136			if (matching->timeout.l3num != l3num ||
137			    matching->timeout.l4proto->l4proto != l4num)
138				return -EINVAL;
139
140			return ctnl_timeout_parse_policy(&matching->timeout.data,
141							 matching->timeout.l4proto,
142							 info->net,
143							 cda[CTA_TIMEOUT_DATA]);
144		}
145
146		return -EBUSY;
147	}
148
149	l4proto = nf_ct_l4proto_find(l4num);
150
151	/* This protocol is not supportted, skip. */
152	if (l4proto->l4proto != l4num) {
153		ret = -EOPNOTSUPP;
154		goto err_proto_put;
155	}
156
157	timeout = kzalloc(sizeof(struct ctnl_timeout) +
158			  l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
159	if (timeout == NULL) {
160		ret = -ENOMEM;
161		goto err_proto_put;
162	}
163
164	ret = ctnl_timeout_parse_policy(&timeout->timeout.data, l4proto,
165					info->net, cda[CTA_TIMEOUT_DATA]);
166	if (ret < 0)
167		goto err;
168
169	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
170	timeout->timeout.l3num = l3num;
171	timeout->timeout.l4proto = l4proto;
172	refcount_set(&timeout->refcnt, 1);
173	__module_get(THIS_MODULE);
174	list_add_tail_rcu(&timeout->head, &pernet->nfct_timeout_list);
175
176	return 0;
177err:
178	kfree(timeout);
179err_proto_put:
 
180	return ret;
181}
182
183static int
184ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
185		       int event, struct ctnl_timeout *timeout)
186{
187	struct nlmsghdr *nlh;
 
188	unsigned int flags = portid ? NLM_F_MULTI : 0;
189	const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto;
190	struct nlattr *nest_parms;
191	int ret;
192
193	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
194	nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
195			   NFNETLINK_V0, 0);
196	if (!nlh)
197		goto nlmsg_failure;
198
 
 
 
 
 
199	if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
200	    nla_put_be16(skb, CTA_TIMEOUT_L3PROTO,
201			 htons(timeout->timeout.l3num)) ||
202	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto) ||
203	    nla_put_be32(skb, CTA_TIMEOUT_USE,
204			 htonl(refcount_read(&timeout->refcnt))))
205		goto nla_put_failure;
206
207	nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA);
208	if (!nest_parms)
209		goto nla_put_failure;
 
 
 
 
 
210
211	ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->timeout.data);
212	if (ret < 0)
213		goto nla_put_failure;
214
215	nla_nest_end(skb, nest_parms);
 
216
217	nlmsg_end(skb, nlh);
218	return skb->len;
219
220nlmsg_failure:
221nla_put_failure:
222	nlmsg_cancel(skb, nlh);
223	return -1;
224}
225
226static int
227ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
228{
229	struct nfct_timeout_pernet *pernet;
230	struct net *net = sock_net(skb->sk);
231	struct ctnl_timeout *cur, *last;
232
233	if (cb->args[2])
234		return 0;
235
236	last = (struct ctnl_timeout *)cb->args[1];
237	if (cb->args[1])
238		cb->args[1] = 0;
239
240	rcu_read_lock();
241	pernet = nfct_timeout_pernet(net);
242	list_for_each_entry_rcu(cur, &pernet->nfct_timeout_list, head) {
243		if (last) {
244			if (cur != last)
245				continue;
246
247			last = NULL;
248		}
249		if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
250					   cb->nlh->nlmsg_seq,
251					   NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
252					   IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
253			cb->args[1] = (unsigned long)cur;
254			break;
255		}
256	}
257	if (!cb->args[1])
258		cb->args[2] = 1;
259	rcu_read_unlock();
260	return skb->len;
261}
262
263static int cttimeout_get_timeout(struct sk_buff *skb,
264				 const struct nfnl_info *info,
 
265				 const struct nlattr * const cda[])
266{
267	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
268	int ret = -ENOENT;
269	char *name;
270	struct ctnl_timeout *cur;
271
272	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
273		struct netlink_dump_control c = {
274			.dump = ctnl_timeout_dump,
275		};
276		return netlink_dump_start(info->sk, skb, info->nlh, &c);
277	}
278
279	if (!cda[CTA_TIMEOUT_NAME])
280		return -EINVAL;
281	name = nla_data(cda[CTA_TIMEOUT_NAME]);
282
283	list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
284		struct sk_buff *skb2;
285
286		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
287			continue;
288
289		skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
290		if (skb2 == NULL) {
291			ret = -ENOMEM;
292			break;
293		}
294
295		ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
296					     info->nlh->nlmsg_seq,
297					     NFNL_MSG_TYPE(info->nlh->nlmsg_type),
298					     IPCTNL_MSG_TIMEOUT_NEW, cur);
299		if (ret <= 0) {
300			kfree_skb(skb2);
301			break;
302		}
 
 
 
 
303
304		ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
305		break;
306	}
 
 
307
308	return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309}
310
311/* try to delete object, fail if it is still in use. */
312static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
313{
314	int ret = 0;
315
316	/* We want to avoid races with ctnl_timeout_put. So only when the
317	 * current refcnt is 1, we decrease it to 0.
318	 */
319	if (refcount_dec_if_one(&timeout->refcnt)) {
320		/* We are protected by nfnl mutex. */
321		list_del_rcu(&timeout->head);
322		nf_ct_untimeout(net, &timeout->timeout);
 
323		kfree_rcu(timeout, rcu_head);
324	} else {
325		ret = -EBUSY;
326	}
327	return ret;
328}
329
330static int cttimeout_del_timeout(struct sk_buff *skb,
331				 const struct nfnl_info *info,
 
332				 const struct nlattr * const cda[])
333{
334	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(info->net);
335	struct ctnl_timeout *cur, *tmp;
336	int ret = -ENOENT;
337	char *name;
338
339	if (!cda[CTA_TIMEOUT_NAME]) {
340		list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list,
341					 head)
342			ctnl_timeout_try_del(info->net, cur);
343
344		return 0;
345	}
346	name = nla_data(cda[CTA_TIMEOUT_NAME]);
347
348	list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
349		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
350			continue;
351
352		ret = ctnl_timeout_try_del(info->net, cur);
353		if (ret < 0)
354			return ret;
355
356		break;
357	}
358	return ret;
359}
360
361static int cttimeout_default_set(struct sk_buff *skb,
362				 const struct nfnl_info *info,
 
363				 const struct nlattr * const cda[])
364{
365	const struct nf_conntrack_l4proto *l4proto;
366	__u8 l4num;
 
 
367	int ret;
368
369	if (!cda[CTA_TIMEOUT_L4PROTO] ||
 
370	    !cda[CTA_TIMEOUT_DATA])
371		return -EINVAL;
372
 
373	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
374	l4proto = nf_ct_l4proto_find(l4num);
375
376	/* This protocol is not supported, skip. */
377	if (l4proto->l4proto != l4num) {
378		ret = -EOPNOTSUPP;
379		goto err;
380	}
381
382	ret = ctnl_timeout_parse_policy(NULL, l4proto, info->net,
 
 
383					cda[CTA_TIMEOUT_DATA]);
384	if (ret < 0)
385		goto err;
386
 
387	return 0;
388err:
 
389	return ret;
390}
391
392static int
393cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
394			    u32 seq, u32 type, int event, u16 l3num,
395			    const struct nf_conntrack_l4proto *l4proto,
396			    const unsigned int *timeouts)
397{
398	struct nlmsghdr *nlh;
 
399	unsigned int flags = portid ? NLM_F_MULTI : 0;
400	struct nlattr *nest_parms;
401	int ret;
402
403	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
404	nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
405			   NFNETLINK_V0, 0);
406	if (!nlh)
407		goto nlmsg_failure;
408
409	if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) ||
 
 
 
 
 
410	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
411		goto nla_put_failure;
412
413	nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA);
414	if (!nest_parms)
415		goto nla_put_failure;
 
 
 
 
 
 
416
417	ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
418	if (ret < 0)
419		goto nla_put_failure;
420
421	nla_nest_end(skb, nest_parms);
 
422
423	nlmsg_end(skb, nlh);
424	return skb->len;
425
426nlmsg_failure:
427nla_put_failure:
428	nlmsg_cancel(skb, nlh);
429	return -1;
430}
431
432static int cttimeout_default_get(struct sk_buff *skb,
433				 const struct nfnl_info *info,
 
434				 const struct nlattr * const cda[])
435{
436	const struct nf_conntrack_l4proto *l4proto;
437	unsigned int *timeouts = NULL;
438	struct sk_buff *skb2;
439	__u16 l3num;
440	__u8 l4num;
441	int ret;
 
 
442
443	if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
444		return -EINVAL;
445
446	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
447	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
448	l4proto = nf_ct_l4proto_find(l4num);
449
450	if (l4proto->l4proto != l4num)
451		return -EOPNOTSUPP;
452
453	switch (l4proto->l4proto) {
454	case IPPROTO_ICMP:
455		timeouts = &nf_icmp_pernet(info->net)->timeout;
456		break;
457	case IPPROTO_TCP:
458		timeouts = nf_tcp_pernet(info->net)->timeouts;
459		break;
460	case IPPROTO_UDP:
461	case IPPROTO_UDPLITE:
462		timeouts = nf_udp_pernet(info->net)->timeouts;
463		break;
464	case IPPROTO_DCCP:
465#ifdef CONFIG_NF_CT_PROTO_DCCP
466		timeouts = nf_dccp_pernet(info->net)->dccp_timeout;
467#endif
468		break;
469	case IPPROTO_ICMPV6:
470		timeouts = &nf_icmpv6_pernet(info->net)->timeout;
471		break;
472	case IPPROTO_SCTP:
473#ifdef CONFIG_NF_CT_PROTO_SCTP
474		timeouts = nf_sctp_pernet(info->net)->timeouts;
475#endif
476		break;
477	case IPPROTO_GRE:
478#ifdef CONFIG_NF_CT_PROTO_GRE
479		timeouts = nf_gre_pernet(info->net)->timeouts;
480#endif
481		break;
482	case 255:
483		timeouts = &nf_generic_pernet(info->net)->timeout;
484		break;
485	default:
486		WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto);
487		break;
488	}
489
490	if (!timeouts)
491		return -EOPNOTSUPP;
492
493	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
494	if (!skb2)
495		return -ENOMEM;
 
 
496
497	ret = cttimeout_default_fill_info(info->net, skb2,
498					  NETLINK_CB(skb).portid,
499					  info->nlh->nlmsg_seq,
500					  NFNL_MSG_TYPE(info->nlh->nlmsg_type),
501					  IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
502					  l3num, l4proto, timeouts);
503	if (ret <= 0) {
504		kfree_skb(skb2);
505		return -ENOMEM;
 
506	}
 
 
 
507
508	return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
 
 
 
 
509}
510
511static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
512						   const char *name)
 
513{
514	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
515	struct ctnl_timeout *timeout, *matching = NULL;
516
517	list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) {
 
518		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
519			continue;
520
521		if (!refcount_inc_not_zero(&timeout->refcnt))
 
 
 
 
522			goto err;
 
523		matching = timeout;
524		break;
525	}
526err:
527	return matching ? &matching->timeout : NULL;
 
528}
529
530static void ctnl_timeout_put(struct nf_ct_timeout *t)
531{
532	struct ctnl_timeout *timeout =
533		container_of(t, struct ctnl_timeout, timeout);
534
535	if (refcount_dec_and_test(&timeout->refcnt)) {
536		kfree_rcu(timeout, rcu_head);
537		module_put(THIS_MODULE);
538	}
539}
 
540
541static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
542	[IPCTNL_MSG_TIMEOUT_NEW] = {
543		.call		= cttimeout_new_timeout,
544		.type		= NFNL_CB_MUTEX,
545		.attr_count	= CTA_TIMEOUT_MAX,
546		.policy		= cttimeout_nla_policy
547	},
548	[IPCTNL_MSG_TIMEOUT_GET] = {
549		.call		= cttimeout_get_timeout,
550		.type		= NFNL_CB_MUTEX,
551		.attr_count	= CTA_TIMEOUT_MAX,
552		.policy		= cttimeout_nla_policy
553	},
554	[IPCTNL_MSG_TIMEOUT_DELETE] = {
555		.call		= cttimeout_del_timeout,
556		.type		= NFNL_CB_MUTEX,
557		.attr_count	= CTA_TIMEOUT_MAX,
558		.policy		= cttimeout_nla_policy
559	},
560	[IPCTNL_MSG_TIMEOUT_DEFAULT_SET] = {
561		.call		= cttimeout_default_set,
562		.type		= NFNL_CB_MUTEX,
563		.attr_count	= CTA_TIMEOUT_MAX,
564		.policy		= cttimeout_nla_policy
565	},
566	[IPCTNL_MSG_TIMEOUT_DEFAULT_GET] = {
567		.call		= cttimeout_default_get,
568		.type		= NFNL_CB_MUTEX,
569		.attr_count	= CTA_TIMEOUT_MAX,
570		.policy		= cttimeout_nla_policy
571	},
572};
573
574static const struct nfnetlink_subsystem cttimeout_subsys = {
575	.name				= "conntrack_timeout",
576	.subsys_id			= NFNL_SUBSYS_CTNETLINK_TIMEOUT,
577	.cb_count			= IPCTNL_MSG_TIMEOUT_MAX,
578	.cb				= cttimeout_cb,
579};
580
581MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
582
583static int __net_init cttimeout_net_init(struct net *net)
584{
585	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
586
587	INIT_LIST_HEAD(&pernet->nfct_timeout_list);
588	INIT_LIST_HEAD(&pernet->nfct_timeout_freelist);
589
590	return 0;
591}
592
593static void __net_exit cttimeout_net_pre_exit(struct net *net)
594{
595	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
596	struct ctnl_timeout *cur, *tmp;
597
598	list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
599		list_del_rcu(&cur->head);
600		list_add(&cur->free_head, &pernet->nfct_timeout_freelist);
601	}
602
603	/* core calls synchronize_rcu() after this */
604}
605
606static void __net_exit cttimeout_net_exit(struct net *net)
607{
608	struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
609	struct ctnl_timeout *cur, *tmp;
610
611	if (list_empty(&pernet->nfct_timeout_freelist))
612		return;
613
614	nf_ct_untimeout(net, NULL);
615
616	list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, free_head) {
617		list_del(&cur->free_head);
618
619		if (refcount_dec_and_test(&cur->refcnt))
620			kfree_rcu(cur, rcu_head);
621	}
622}
623
624static struct pernet_operations cttimeout_ops = {
625	.init	= cttimeout_net_init,
626	.pre_exit = cttimeout_net_pre_exit,
627	.exit	= cttimeout_net_exit,
628	.id     = &nfct_timeout_id,
629	.size   = sizeof(struct nfct_timeout_pernet),
630};
631
632static const struct nf_ct_timeout_hooks hooks = {
633	.timeout_find_get = ctnl_timeout_find_get,
634	.timeout_put = ctnl_timeout_put,
635};
636
637static int __init cttimeout_init(void)
638{
639	int ret;
640
641	ret = register_pernet_subsys(&cttimeout_ops);
642	if (ret < 0)
643		return ret;
644
645	ret = nfnetlink_subsys_register(&cttimeout_subsys);
646	if (ret < 0) {
647		pr_err("cttimeout_init: cannot register cttimeout with "
648			"nfnetlink.\n");
649		goto err_out;
650	}
651	RCU_INIT_POINTER(nf_ct_timeout_hook, &hooks);
 
 
 
652	return 0;
653
654err_out:
655	unregister_pernet_subsys(&cttimeout_ops);
656	return ret;
657}
658
659static int untimeout(struct nf_conn *ct, void *timeout)
660{
661	struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
662
663	if (timeout_ext)
664		RCU_INIT_POINTER(timeout_ext->timeout, NULL);
665
666	return 0;
667}
668
669static void __exit cttimeout_exit(void)
670{
671	nfnetlink_subsys_unregister(&cttimeout_subsys);
672
673	unregister_pernet_subsys(&cttimeout_ops);
674	RCU_INIT_POINTER(nf_ct_timeout_hook, NULL);
675
676	nf_ct_iterate_destroy(untimeout, NULL);
 
 
677}
678
679module_init(cttimeout_init);
680module_exit(cttimeout_exit);