1 /*
2  * (C) 2012 by Pablo Neira Ayuso <[email protected]>
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 
37 MODULE_LICENSE("GPL");
38 MODULE_AUTHOR("Pablo Neira Ayuso <[email protected]>");
39 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
40 
41 static 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 
49 static int
50 ctnl_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 				       NULL);
61 		if (ret < 0)
62 			return ret;
63 
64 		ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
65 	}
66 	return ret;
67 }
68 
69 static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
70 				 struct sk_buff *skb,
71 				 const struct nlmsghdr *nlh,
72 				 const struct nlattr * const cda[],
73 				 struct netlink_ext_ack *extack)
74 {
75 	__u16 l3num;
76 	__u8 l4num;
77 	struct nf_conntrack_l4proto *l4proto;
78 	struct ctnl_timeout *timeout, *matching = NULL;
79 	char *name;
80 	int ret;
81 
82 	if (!cda[CTA_TIMEOUT_NAME] ||
83 	    !cda[CTA_TIMEOUT_L3PROTO] ||
84 	    !cda[CTA_TIMEOUT_L4PROTO] ||
85 	    !cda[CTA_TIMEOUT_DATA])
86 		return -EINVAL;
87 
88 	name = nla_data(cda[CTA_TIMEOUT_NAME]);
89 	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
90 	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
91 
92 	list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
93 		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
94 			continue;
95 
96 		if (nlh->nlmsg_flags & NLM_F_EXCL)
97 			return -EEXIST;
98 
99 		matching = timeout;
100 		break;
101 	}
102 
103 	if (matching) {
104 		if (nlh->nlmsg_flags & NLM_F_REPLACE) {
105 			/* You cannot replace one timeout policy by another of
106 			 * different kind, sorry.
107 			 */
108 			if (matching->l3num != l3num ||
109 			    matching->l4proto->l4proto != l4num)
110 				return -EINVAL;
111 
112 			return ctnl_timeout_parse_policy(&matching->data,
113 							 matching->l4proto, net,
114 							 cda[CTA_TIMEOUT_DATA]);
115 		}
116 
117 		return -EBUSY;
118 	}
119 
120 	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
121 
122 	/* This protocol is not supportted, skip. */
123 	if (l4proto->l4proto != l4num) {
124 		ret = -EOPNOTSUPP;
125 		goto err_proto_put;
126 	}
127 
128 	timeout = kzalloc(sizeof(struct ctnl_timeout) +
129 			  l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
130 	if (timeout == NULL) {
131 		ret = -ENOMEM;
132 		goto err_proto_put;
133 	}
134 
135 	ret = ctnl_timeout_parse_policy(&timeout->data, l4proto, net,
136 					cda[CTA_TIMEOUT_DATA]);
137 	if (ret < 0)
138 		goto err;
139 
140 	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
141 	timeout->l3num = l3num;
142 	timeout->l4proto = l4proto;
143 	refcount_set(&timeout->refcnt, 1);
144 	list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
145 
146 	return 0;
147 err:
148 	kfree(timeout);
149 err_proto_put:
150 	nf_ct_l4proto_put(l4proto);
151 	return ret;
152 }
153 
154 static int
155 ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
156 		       int event, struct ctnl_timeout *timeout)
157 {
158 	struct nlmsghdr *nlh;
159 	struct nfgenmsg *nfmsg;
160 	unsigned int flags = portid ? NLM_F_MULTI : 0;
161 	struct nf_conntrack_l4proto *l4proto = timeout->l4proto;
162 
163 	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
164 	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
165 	if (nlh == NULL)
166 		goto nlmsg_failure;
167 
168 	nfmsg = nlmsg_data(nlh);
169 	nfmsg->nfgen_family = AF_UNSPEC;
170 	nfmsg->version = NFNETLINK_V0;
171 	nfmsg->res_id = 0;
172 
173 	if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
174 	    nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
175 	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
176 	    nla_put_be32(skb, CTA_TIMEOUT_USE,
177 			 htonl(refcount_read(&timeout->refcnt))))
178 		goto nla_put_failure;
179 
180 	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
181 		struct nlattr *nest_parms;
182 		int ret;
183 
184 		nest_parms = nla_nest_start(skb,
185 					    CTA_TIMEOUT_DATA | NLA_F_NESTED);
186 		if (!nest_parms)
187 			goto nla_put_failure;
188 
189 		ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
190 		if (ret < 0)
191 			goto nla_put_failure;
192 
193 		nla_nest_end(skb, nest_parms);
194 	}
195 
196 	nlmsg_end(skb, nlh);
197 	return skb->len;
198 
199 nlmsg_failure:
200 nla_put_failure:
201 	nlmsg_cancel(skb, nlh);
202 	return -1;
203 }
204 
205 static int
206 ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
207 {
208 	struct net *net = sock_net(skb->sk);
209 	struct ctnl_timeout *cur, *last;
210 
211 	if (cb->args[2])
212 		return 0;
213 
214 	last = (struct ctnl_timeout *)cb->args[1];
215 	if (cb->args[1])
216 		cb->args[1] = 0;
217 
218 	rcu_read_lock();
219 	list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
220 		if (last) {
221 			if (cur != last)
222 				continue;
223 
224 			last = NULL;
225 		}
226 		if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
227 					   cb->nlh->nlmsg_seq,
228 					   NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
229 					   IPCTNL_MSG_TIMEOUT_NEW, cur) < 0) {
230 			cb->args[1] = (unsigned long)cur;
231 			break;
232 		}
233 	}
234 	if (!cb->args[1])
235 		cb->args[2] = 1;
236 	rcu_read_unlock();
237 	return skb->len;
238 }
239 
240 static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
241 				 struct sk_buff *skb,
242 				 const struct nlmsghdr *nlh,
243 				 const struct nlattr * const cda[],
244 				 struct netlink_ext_ack *extack)
245 {
246 	int ret = -ENOENT;
247 	char *name;
248 	struct ctnl_timeout *cur;
249 
250 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
251 		struct netlink_dump_control c = {
252 			.dump = ctnl_timeout_dump,
253 		};
254 		return netlink_dump_start(ctnl, skb, nlh, &c);
255 	}
256 
257 	if (!cda[CTA_TIMEOUT_NAME])
258 		return -EINVAL;
259 	name = nla_data(cda[CTA_TIMEOUT_NAME]);
260 
261 	list_for_each_entry(cur, &net->nfct_timeout_list, head) {
262 		struct sk_buff *skb2;
263 
264 		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
265 			continue;
266 
267 		skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
268 		if (skb2 == NULL) {
269 			ret = -ENOMEM;
270 			break;
271 		}
272 
273 		ret = ctnl_timeout_fill_info(skb2, NETLINK_CB(skb).portid,
274 					     nlh->nlmsg_seq,
275 					     NFNL_MSG_TYPE(nlh->nlmsg_type),
276 					     IPCTNL_MSG_TIMEOUT_NEW, cur);
277 		if (ret <= 0) {
278 			kfree_skb(skb2);
279 			break;
280 		}
281 		ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
282 					MSG_DONTWAIT);
283 		if (ret > 0)
284 			ret = 0;
285 
286 		/* this avoids a loop in nfnetlink. */
287 		return ret == -EAGAIN ? -ENOBUFS : ret;
288 	}
289 	return ret;
290 }
291 
292 static int untimeout(struct nf_conn *ct, void *timeout)
293 {
294 	struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
295 
296 	if (timeout_ext && (!timeout || timeout_ext->timeout == timeout))
297 		RCU_INIT_POINTER(timeout_ext->timeout, NULL);
298 
299 	/* We are not intended to delete this conntrack. */
300 	return 0;
301 }
302 
303 static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout)
304 {
305 	nf_ct_iterate_cleanup_net(net, untimeout, timeout, 0, 0);
306 }
307 
308 /* try to delete object, fail if it is still in use. */
309 static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
310 {
311 	int ret = 0;
312 
313 	/* We want to avoid races with ctnl_timeout_put. So only when the
314 	 * current refcnt is 1, we decrease it to 0.
315 	 */
316 	if (refcount_dec_if_one(&timeout->refcnt)) {
317 		/* We are protected by nfnl mutex. */
318 		list_del_rcu(&timeout->head);
319 		nf_ct_l4proto_put(timeout->l4proto);
320 		ctnl_untimeout(net, timeout);
321 		kfree_rcu(timeout, rcu_head);
322 	} else {
323 		ret = -EBUSY;
324 	}
325 	return ret;
326 }
327 
328 static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
329 				 struct sk_buff *skb,
330 				 const struct nlmsghdr *nlh,
331 				 const struct nlattr * const cda[],
332 				 struct netlink_ext_ack *extack)
333 {
334 	struct ctnl_timeout *cur, *tmp;
335 	int ret = -ENOENT;
336 	char *name;
337 
338 	if (!cda[CTA_TIMEOUT_NAME]) {
339 		list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
340 					 head)
341 			ctnl_timeout_try_del(net, cur);
342 
343 		return 0;
344 	}
345 	name = nla_data(cda[CTA_TIMEOUT_NAME]);
346 
347 	list_for_each_entry(cur, &net->nfct_timeout_list, head) {
348 		if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
349 			continue;
350 
351 		ret = ctnl_timeout_try_del(net, cur);
352 		if (ret < 0)
353 			return ret;
354 
355 		break;
356 	}
357 	return ret;
358 }
359 
360 static int cttimeout_default_set(struct net *net, struct sock *ctnl,
361 				 struct sk_buff *skb,
362 				 const struct nlmsghdr *nlh,
363 				 const struct nlattr * const cda[],
364 				 struct netlink_ext_ack *extack)
365 {
366 	__u16 l3num;
367 	__u8 l4num;
368 	struct nf_conntrack_l4proto *l4proto;
369 	unsigned int *timeouts;
370 	int ret;
371 
372 	if (!cda[CTA_TIMEOUT_L3PROTO] ||
373 	    !cda[CTA_TIMEOUT_L4PROTO] ||
374 	    !cda[CTA_TIMEOUT_DATA])
375 		return -EINVAL;
376 
377 	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
378 	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
379 	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
380 
381 	/* This protocol is not supported, skip. */
382 	if (l4proto->l4proto != l4num) {
383 		ret = -EOPNOTSUPP;
384 		goto err;
385 	}
386 
387 	timeouts = l4proto->get_timeouts(net);
388 
389 	ret = ctnl_timeout_parse_policy(timeouts, l4proto, net,
390 					cda[CTA_TIMEOUT_DATA]);
391 	if (ret < 0)
392 		goto err;
393 
394 	nf_ct_l4proto_put(l4proto);
395 	return 0;
396 err:
397 	nf_ct_l4proto_put(l4proto);
398 	return ret;
399 }
400 
401 static int
402 cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
403 			    u32 seq, u32 type, int event,
404 			    struct nf_conntrack_l4proto *l4proto)
405 {
406 	struct nlmsghdr *nlh;
407 	struct nfgenmsg *nfmsg;
408 	unsigned int flags = portid ? NLM_F_MULTI : 0;
409 
410 	event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
411 	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
412 	if (nlh == NULL)
413 		goto nlmsg_failure;
414 
415 	nfmsg = nlmsg_data(nlh);
416 	nfmsg->nfgen_family = AF_UNSPEC;
417 	nfmsg->version = NFNETLINK_V0;
418 	nfmsg->res_id = 0;
419 
420 	if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l4proto->l3proto)) ||
421 	    nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
422 		goto nla_put_failure;
423 
424 	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
425 		struct nlattr *nest_parms;
426 		unsigned int *timeouts = l4proto->get_timeouts(net);
427 		int ret;
428 
429 		nest_parms = nla_nest_start(skb,
430 					    CTA_TIMEOUT_DATA | NLA_F_NESTED);
431 		if (!nest_parms)
432 			goto nla_put_failure;
433 
434 		ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts);
435 		if (ret < 0)
436 			goto nla_put_failure;
437 
438 		nla_nest_end(skb, nest_parms);
439 	}
440 
441 	nlmsg_end(skb, nlh);
442 	return skb->len;
443 
444 nlmsg_failure:
445 nla_put_failure:
446 	nlmsg_cancel(skb, nlh);
447 	return -1;
448 }
449 
450 static int cttimeout_default_get(struct net *net, struct sock *ctnl,
451 				 struct sk_buff *skb,
452 				 const struct nlmsghdr *nlh,
453 				 const struct nlattr * const cda[],
454 				 struct netlink_ext_ack *extack)
455 {
456 	__u16 l3num;
457 	__u8 l4num;
458 	struct nf_conntrack_l4proto *l4proto;
459 	struct sk_buff *skb2;
460 	int ret, err;
461 
462 	if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
463 		return -EINVAL;
464 
465 	l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
466 	l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
467 	l4proto = nf_ct_l4proto_find_get(l3num, l4num);
468 
469 	/* This protocol is not supported, skip. */
470 	if (l4proto->l4proto != l4num) {
471 		err = -EOPNOTSUPP;
472 		goto err;
473 	}
474 
475 	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
476 	if (skb2 == NULL) {
477 		err = -ENOMEM;
478 		goto err;
479 	}
480 
481 	ret = cttimeout_default_fill_info(net, skb2, NETLINK_CB(skb).portid,
482 					  nlh->nlmsg_seq,
483 					  NFNL_MSG_TYPE(nlh->nlmsg_type),
484 					  IPCTNL_MSG_TIMEOUT_DEFAULT_SET,
485 					  l4proto);
486 	if (ret <= 0) {
487 		kfree_skb(skb2);
488 		err = -ENOMEM;
489 		goto err;
490 	}
491 	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
492 	if (ret > 0)
493 		ret = 0;
494 
495 	/* this avoids a loop in nfnetlink. */
496 	return ret == -EAGAIN ? -ENOBUFS : ret;
497 err:
498 	nf_ct_l4proto_put(l4proto);
499 	return err;
500 }
501 
502 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
503 static struct ctnl_timeout *
504 ctnl_timeout_find_get(struct net *net, const char *name)
505 {
506 	struct ctnl_timeout *timeout, *matching = NULL;
507 
508 	rcu_read_lock();
509 	list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
510 		if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
511 			continue;
512 
513 		if (!try_module_get(THIS_MODULE))
514 			goto err;
515 
516 		if (!refcount_inc_not_zero(&timeout->refcnt)) {
517 			module_put(THIS_MODULE);
518 			goto err;
519 		}
520 		matching = timeout;
521 		break;
522 	}
523 err:
524 	rcu_read_unlock();
525 	return matching;
526 }
527 
528 static void ctnl_timeout_put(struct ctnl_timeout *timeout)
529 {
530 	if (refcount_dec_and_test(&timeout->refcnt))
531 		kfree_rcu(timeout, rcu_head);
532 
533 	module_put(THIS_MODULE);
534 }
535 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
536 
537 static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = {
538 	[IPCTNL_MSG_TIMEOUT_NEW]	= { .call = cttimeout_new_timeout,
539 					    .attr_count = CTA_TIMEOUT_MAX,
540 					    .policy = cttimeout_nla_policy },
541 	[IPCTNL_MSG_TIMEOUT_GET]	= { .call = cttimeout_get_timeout,
542 					    .attr_count = CTA_TIMEOUT_MAX,
543 					    .policy = cttimeout_nla_policy },
544 	[IPCTNL_MSG_TIMEOUT_DELETE]	= { .call = cttimeout_del_timeout,
545 					    .attr_count = CTA_TIMEOUT_MAX,
546 					    .policy = cttimeout_nla_policy },
547 	[IPCTNL_MSG_TIMEOUT_DEFAULT_SET]= { .call = cttimeout_default_set,
548 					    .attr_count = CTA_TIMEOUT_MAX,
549 					    .policy = cttimeout_nla_policy },
550 	[IPCTNL_MSG_TIMEOUT_DEFAULT_GET]= { .call = cttimeout_default_get,
551 					    .attr_count = CTA_TIMEOUT_MAX,
552 					    .policy = cttimeout_nla_policy },
553 };
554 
555 static const struct nfnetlink_subsystem cttimeout_subsys = {
556 	.name				= "conntrack_timeout",
557 	.subsys_id			= NFNL_SUBSYS_CTNETLINK_TIMEOUT,
558 	.cb_count			= IPCTNL_MSG_TIMEOUT_MAX,
559 	.cb				= cttimeout_cb,
560 };
561 
562 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
563 
564 static int __net_init cttimeout_net_init(struct net *net)
565 {
566 	INIT_LIST_HEAD(&net->nfct_timeout_list);
567 
568 	return 0;
569 }
570 
571 static void __net_exit cttimeout_net_exit(struct net *net)
572 {
573 	struct ctnl_timeout *cur, *tmp;
574 
575 	ctnl_untimeout(net, NULL);
576 
577 	list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
578 		list_del_rcu(&cur->head);
579 		nf_ct_l4proto_put(cur->l4proto);
580 
581 		if (refcount_dec_and_test(&cur->refcnt))
582 			kfree_rcu(cur, rcu_head);
583 	}
584 }
585 
586 static struct pernet_operations cttimeout_ops = {
587 	.init	= cttimeout_net_init,
588 	.exit	= cttimeout_net_exit,
589 };
590 
591 static int __init cttimeout_init(void)
592 {
593 	int ret;
594 
595 	ret = register_pernet_subsys(&cttimeout_ops);
596 	if (ret < 0)
597 		return ret;
598 
599 	ret = nfnetlink_subsys_register(&cttimeout_subsys);
600 	if (ret < 0) {
601 		pr_err("cttimeout_init: cannot register cttimeout with "
602 			"nfnetlink.\n");
603 		goto err_out;
604 	}
605 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
606 	RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, ctnl_timeout_find_get);
607 	RCU_INIT_POINTER(nf_ct_timeout_put_hook, ctnl_timeout_put);
608 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
609 	return 0;
610 
611 err_out:
612 	unregister_pernet_subsys(&cttimeout_ops);
613 	return ret;
614 }
615 
616 static void __exit cttimeout_exit(void)
617 {
618 	pr_info("cttimeout: unregistering from nfnetlink.\n");
619 
620 	nfnetlink_subsys_unregister(&cttimeout_subsys);
621 
622 	unregister_pernet_subsys(&cttimeout_ops);
623 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
624 	RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL);
625 	RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL);
626 	synchronize_rcu();
627 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
628 }
629 
630 module_init(cttimeout_init);
631 module_exit(cttimeout_exit);
632