nfnetlink_cttimeout.c (16780B)
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_L3PROTO] || 370 !cda[CTA_TIMEOUT_L4PROTO] || 371 !cda[CTA_TIMEOUT_DATA]) 372 return -EINVAL; 373 374 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 375 l4proto = nf_ct_l4proto_find(l4num); 376 377 /* This protocol is not supported, skip. */ 378 if (l4proto->l4proto != l4num) { 379 ret = -EOPNOTSUPP; 380 goto err; 381 } 382 383 ret = ctnl_timeout_parse_policy(NULL, l4proto, info->net, 384 cda[CTA_TIMEOUT_DATA]); 385 if (ret < 0) 386 goto err; 387 388 return 0; 389err: 390 return ret; 391} 392 393static int 394cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, 395 u32 seq, u32 type, int event, u16 l3num, 396 const struct nf_conntrack_l4proto *l4proto, 397 const unsigned int *timeouts) 398{ 399 struct nlmsghdr *nlh; 400 unsigned int flags = portid ? NLM_F_MULTI : 0; 401 struct nlattr *nest_parms; 402 int ret; 403 404 event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event); 405 nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC, 406 NFNETLINK_V0, 0); 407 if (!nlh) 408 goto nlmsg_failure; 409 410 if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) || 411 nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) 412 goto nla_put_failure; 413 414 nest_parms = nla_nest_start(skb, CTA_TIMEOUT_DATA); 415 if (!nest_parms) 416 goto nla_put_failure; 417 418 ret = l4proto->ctnl_timeout.obj_to_nlattr(skb, timeouts); 419 if (ret < 0) 420 goto nla_put_failure; 421 422 nla_nest_end(skb, nest_parms); 423 424 nlmsg_end(skb, nlh); 425 return skb->len; 426 427nlmsg_failure: 428nla_put_failure: 429 nlmsg_cancel(skb, nlh); 430 return -1; 431} 432 433static int cttimeout_default_get(struct sk_buff *skb, 434 const struct nfnl_info *info, 435 const struct nlattr * const cda[]) 436{ 437 const struct nf_conntrack_l4proto *l4proto; 438 unsigned int *timeouts = NULL; 439 struct sk_buff *skb2; 440 __u16 l3num; 441 __u8 l4num; 442 int ret; 443 444 if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO]) 445 return -EINVAL; 446 447 l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); 448 l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); 449 l4proto = nf_ct_l4proto_find(l4num); 450 451 if (l4proto->l4proto != l4num) 452 return -EOPNOTSUPP; 453 454 switch (l4proto->l4proto) { 455 case IPPROTO_ICMP: 456 timeouts = &nf_icmp_pernet(info->net)->timeout; 457 break; 458 case IPPROTO_TCP: 459 timeouts = nf_tcp_pernet(info->net)->timeouts; 460 break; 461 case IPPROTO_UDP: 462 case IPPROTO_UDPLITE: 463 timeouts = nf_udp_pernet(info->net)->timeouts; 464 break; 465 case IPPROTO_DCCP: 466#ifdef CONFIG_NF_CT_PROTO_DCCP 467 timeouts = nf_dccp_pernet(info->net)->dccp_timeout; 468#endif 469 break; 470 case IPPROTO_ICMPV6: 471 timeouts = &nf_icmpv6_pernet(info->net)->timeout; 472 break; 473 case IPPROTO_SCTP: 474#ifdef CONFIG_NF_CT_PROTO_SCTP 475 timeouts = nf_sctp_pernet(info->net)->timeouts; 476#endif 477 break; 478 case IPPROTO_GRE: 479#ifdef CONFIG_NF_CT_PROTO_GRE 480 timeouts = nf_gre_pernet(info->net)->timeouts; 481#endif 482 break; 483 case 255: 484 timeouts = &nf_generic_pernet(info->net)->timeout; 485 break; 486 default: 487 WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto); 488 break; 489 } 490 491 if (!timeouts) 492 return -EOPNOTSUPP; 493 494 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 495 if (!skb2) 496 return -ENOMEM; 497 498 ret = cttimeout_default_fill_info(info->net, skb2, 499 NETLINK_CB(skb).portid, 500 info->nlh->nlmsg_seq, 501 NFNL_MSG_TYPE(info->nlh->nlmsg_type), 502 IPCTNL_MSG_TIMEOUT_DEFAULT_SET, 503 l3num, l4proto, timeouts); 504 if (ret <= 0) { 505 kfree_skb(skb2); 506 return -ENOMEM; 507 } 508 509 return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid); 510} 511 512static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net, 513 const char *name) 514{ 515 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 516 struct ctnl_timeout *timeout, *matching = NULL; 517 518 list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) { 519 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 520 continue; 521 522 if (!refcount_inc_not_zero(&timeout->refcnt)) 523 goto err; 524 matching = timeout; 525 break; 526 } 527err: 528 return matching ? &matching->timeout : NULL; 529} 530 531static void ctnl_timeout_put(struct nf_ct_timeout *t) 532{ 533 struct ctnl_timeout *timeout = 534 container_of(t, struct ctnl_timeout, timeout); 535 536 if (refcount_dec_and_test(&timeout->refcnt)) { 537 kfree_rcu(timeout, rcu_head); 538 module_put(THIS_MODULE); 539 } 540} 541 542static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 543 [IPCTNL_MSG_TIMEOUT_NEW] = { 544 .call = cttimeout_new_timeout, 545 .type = NFNL_CB_MUTEX, 546 .attr_count = CTA_TIMEOUT_MAX, 547 .policy = cttimeout_nla_policy 548 }, 549 [IPCTNL_MSG_TIMEOUT_GET] = { 550 .call = cttimeout_get_timeout, 551 .type = NFNL_CB_MUTEX, 552 .attr_count = CTA_TIMEOUT_MAX, 553 .policy = cttimeout_nla_policy 554 }, 555 [IPCTNL_MSG_TIMEOUT_DELETE] = { 556 .call = cttimeout_del_timeout, 557 .type = NFNL_CB_MUTEX, 558 .attr_count = CTA_TIMEOUT_MAX, 559 .policy = cttimeout_nla_policy 560 }, 561 [IPCTNL_MSG_TIMEOUT_DEFAULT_SET] = { 562 .call = cttimeout_default_set, 563 .type = NFNL_CB_MUTEX, 564 .attr_count = CTA_TIMEOUT_MAX, 565 .policy = cttimeout_nla_policy 566 }, 567 [IPCTNL_MSG_TIMEOUT_DEFAULT_GET] = { 568 .call = cttimeout_default_get, 569 .type = NFNL_CB_MUTEX, 570 .attr_count = CTA_TIMEOUT_MAX, 571 .policy = cttimeout_nla_policy 572 }, 573}; 574 575static const struct nfnetlink_subsystem cttimeout_subsys = { 576 .name = "conntrack_timeout", 577 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT, 578 .cb_count = IPCTNL_MSG_TIMEOUT_MAX, 579 .cb = cttimeout_cb, 580}; 581 582MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 583 584static int __net_init cttimeout_net_init(struct net *net) 585{ 586 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 587 588 INIT_LIST_HEAD(&pernet->nfct_timeout_list); 589 INIT_LIST_HEAD(&pernet->nfct_timeout_freelist); 590 591 return 0; 592} 593 594static void __net_exit cttimeout_net_pre_exit(struct net *net) 595{ 596 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 597 struct ctnl_timeout *cur, *tmp; 598 599 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) { 600 list_del_rcu(&cur->head); 601 list_add(&cur->free_head, &pernet->nfct_timeout_freelist); 602 } 603 604 /* core calls synchronize_rcu() after this */ 605} 606 607static void __net_exit cttimeout_net_exit(struct net *net) 608{ 609 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 610 struct ctnl_timeout *cur, *tmp; 611 612 if (list_empty(&pernet->nfct_timeout_freelist)) 613 return; 614 615 nf_ct_untimeout(net, NULL); 616 617 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, free_head) { 618 list_del(&cur->free_head); 619 620 if (refcount_dec_and_test(&cur->refcnt)) 621 kfree_rcu(cur, rcu_head); 622 } 623} 624 625static struct pernet_operations cttimeout_ops = { 626 .init = cttimeout_net_init, 627 .pre_exit = cttimeout_net_pre_exit, 628 .exit = cttimeout_net_exit, 629 .id = &nfct_timeout_id, 630 .size = sizeof(struct nfct_timeout_pernet), 631}; 632 633static const struct nf_ct_timeout_hooks hooks = { 634 .timeout_find_get = ctnl_timeout_find_get, 635 .timeout_put = ctnl_timeout_put, 636}; 637 638static int __init cttimeout_init(void) 639{ 640 int ret; 641 642 ret = register_pernet_subsys(&cttimeout_ops); 643 if (ret < 0) 644 return ret; 645 646 ret = nfnetlink_subsys_register(&cttimeout_subsys); 647 if (ret < 0) { 648 pr_err("cttimeout_init: cannot register cttimeout with " 649 "nfnetlink.\n"); 650 goto err_out; 651 } 652 RCU_INIT_POINTER(nf_ct_timeout_hook, &hooks); 653 return 0; 654 655err_out: 656 unregister_pernet_subsys(&cttimeout_ops); 657 return ret; 658} 659 660static int untimeout(struct nf_conn *ct, void *timeout) 661{ 662 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct); 663 664 if (timeout_ext) 665 RCU_INIT_POINTER(timeout_ext->timeout, NULL); 666 667 return 0; 668} 669 670static void __exit cttimeout_exit(void) 671{ 672 nfnetlink_subsys_unregister(&cttimeout_subsys); 673 674 unregister_pernet_subsys(&cttimeout_ops); 675 RCU_INIT_POINTER(nf_ct_timeout_hook, NULL); 676 677 nf_ct_iterate_destroy(untimeout, NULL); 678} 679 680module_init(cttimeout_init); 681module_exit(cttimeout_exit);