at master 17 kB view raw
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_ICMPV6: 465 timeouts = &nf_icmpv6_pernet(info->net)->timeout; 466 break; 467 case IPPROTO_SCTP: 468#ifdef CONFIG_NF_CT_PROTO_SCTP 469 timeouts = nf_sctp_pernet(info->net)->timeouts; 470#endif 471 break; 472 case IPPROTO_GRE: 473#ifdef CONFIG_NF_CT_PROTO_GRE 474 timeouts = nf_gre_pernet(info->net)->timeouts; 475#endif 476 break; 477 case 255: 478 timeouts = &nf_generic_pernet(info->net)->timeout; 479 break; 480 default: 481 WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto); 482 break; 483 } 484 485 if (!timeouts) 486 return -EOPNOTSUPP; 487 488 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 489 if (!skb2) 490 return -ENOMEM; 491 492 ret = cttimeout_default_fill_info(info->net, skb2, 493 NETLINK_CB(skb).portid, 494 info->nlh->nlmsg_seq, 495 NFNL_MSG_TYPE(info->nlh->nlmsg_type), 496 IPCTNL_MSG_TIMEOUT_DEFAULT_SET, 497 l3num, l4proto, timeouts); 498 if (ret <= 0) { 499 kfree_skb(skb2); 500 return -ENOMEM; 501 } 502 503 return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid); 504} 505 506static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net, 507 const char *name) 508{ 509 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 510 struct ctnl_timeout *timeout, *matching = NULL; 511 512 list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) { 513 if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0) 514 continue; 515 516 if (!refcount_inc_not_zero(&timeout->refcnt)) 517 goto err; 518 matching = timeout; 519 break; 520 } 521err: 522 return matching ? &matching->timeout : NULL; 523} 524 525static void ctnl_timeout_put(struct nf_ct_timeout *t) 526{ 527 struct ctnl_timeout *timeout = 528 container_of(t, struct ctnl_timeout, timeout); 529 530 if (refcount_dec_and_test(&timeout->refcnt)) { 531 kfree_rcu(timeout, rcu_head); 532 module_put(THIS_MODULE); 533 } 534} 535 536static const struct nfnl_callback cttimeout_cb[IPCTNL_MSG_TIMEOUT_MAX] = { 537 [IPCTNL_MSG_TIMEOUT_NEW] = { 538 .call = cttimeout_new_timeout, 539 .type = NFNL_CB_MUTEX, 540 .attr_count = CTA_TIMEOUT_MAX, 541 .policy = cttimeout_nla_policy 542 }, 543 [IPCTNL_MSG_TIMEOUT_GET] = { 544 .call = cttimeout_get_timeout, 545 .type = NFNL_CB_MUTEX, 546 .attr_count = CTA_TIMEOUT_MAX, 547 .policy = cttimeout_nla_policy 548 }, 549 [IPCTNL_MSG_TIMEOUT_DELETE] = { 550 .call = cttimeout_del_timeout, 551 .type = NFNL_CB_MUTEX, 552 .attr_count = CTA_TIMEOUT_MAX, 553 .policy = cttimeout_nla_policy 554 }, 555 [IPCTNL_MSG_TIMEOUT_DEFAULT_SET] = { 556 .call = cttimeout_default_set, 557 .type = NFNL_CB_MUTEX, 558 .attr_count = CTA_TIMEOUT_MAX, 559 .policy = cttimeout_nla_policy 560 }, 561 [IPCTNL_MSG_TIMEOUT_DEFAULT_GET] = { 562 .call = cttimeout_default_get, 563 .type = NFNL_CB_MUTEX, 564 .attr_count = CTA_TIMEOUT_MAX, 565 .policy = cttimeout_nla_policy 566 }, 567}; 568 569static const struct nfnetlink_subsystem cttimeout_subsys = { 570 .name = "conntrack_timeout", 571 .subsys_id = NFNL_SUBSYS_CTNETLINK_TIMEOUT, 572 .cb_count = IPCTNL_MSG_TIMEOUT_MAX, 573 .cb = cttimeout_cb, 574}; 575 576MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 577 578static int __net_init cttimeout_net_init(struct net *net) 579{ 580 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 581 582 INIT_LIST_HEAD(&pernet->nfct_timeout_list); 583 INIT_LIST_HEAD(&pernet->nfct_timeout_freelist); 584 585 return 0; 586} 587 588static void __net_exit cttimeout_net_pre_exit(struct net *net) 589{ 590 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 591 struct ctnl_timeout *cur, *tmp; 592 593 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) { 594 list_del_rcu(&cur->head); 595 list_add(&cur->free_head, &pernet->nfct_timeout_freelist); 596 } 597 598 /* core calls synchronize_rcu() after this */ 599} 600 601static void __net_exit cttimeout_net_exit(struct net *net) 602{ 603 struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net); 604 struct ctnl_timeout *cur, *tmp; 605 606 if (list_empty(&pernet->nfct_timeout_freelist)) 607 return; 608 609 nf_ct_untimeout(net, NULL); 610 611 list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, free_head) { 612 list_del(&cur->free_head); 613 614 if (refcount_dec_and_test(&cur->refcnt)) 615 kfree_rcu(cur, rcu_head); 616 } 617} 618 619static struct pernet_operations cttimeout_ops = { 620 .init = cttimeout_net_init, 621 .pre_exit = cttimeout_net_pre_exit, 622 .exit = cttimeout_net_exit, 623 .id = &nfct_timeout_id, 624 .size = sizeof(struct nfct_timeout_pernet), 625}; 626 627static const struct nf_ct_timeout_hooks hooks = { 628 .timeout_find_get = ctnl_timeout_find_get, 629 .timeout_put = ctnl_timeout_put, 630}; 631 632static int __init cttimeout_init(void) 633{ 634 int ret; 635 636 ret = register_pernet_subsys(&cttimeout_ops); 637 if (ret < 0) 638 return ret; 639 640 ret = nfnetlink_subsys_register(&cttimeout_subsys); 641 if (ret < 0) { 642 pr_err("cttimeout_init: cannot register cttimeout with " 643 "nfnetlink.\n"); 644 goto err_out; 645 } 646 RCU_INIT_POINTER(nf_ct_timeout_hook, &hooks); 647 return 0; 648 649err_out: 650 unregister_pernet_subsys(&cttimeout_ops); 651 return ret; 652} 653 654static int untimeout(struct nf_conn *ct, void *timeout) 655{ 656 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct); 657 658 if (timeout_ext) 659 RCU_INIT_POINTER(timeout_ext->timeout, NULL); 660 661 return 0; 662} 663 664static void __exit cttimeout_exit(void) 665{ 666 nfnetlink_subsys_unregister(&cttimeout_subsys); 667 668 unregister_pernet_subsys(&cttimeout_ops); 669 RCU_INIT_POINTER(nf_ct_timeout_hook, NULL); 670 671 nf_ct_iterate_destroy(untimeout, NULL); 672} 673 674module_init(cttimeout_init); 675module_exit(cttimeout_exit);