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