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 34 static unsigned int nfct_timeout_id __read_mostly; 35 36 struct 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 47 struct nfct_timeout_pernet { 48 struct list_head nfct_timeout_list; 49 struct list_head nfct_timeout_freelist; 50 }; 51 52 MODULE_LICENSE("GPL"); 53 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 54 MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning"); 55 56 static 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 64 static struct nfct_timeout_pernet *nfct_timeout_pernet(struct net *net) 65 { 66 return net_generic(net, nfct_timeout_id); 67 } 68 69 static int 70 ctnl_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 93 err: 94 kfree(tb); 95 return ret; 96 } 97 98 static 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; 177 err: 178 kfree(timeout); 179 err_proto_put: 180 return ret; 181 } 182 183 static int 184 ctnl_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 220 nlmsg_failure: 221 nla_put_failure: 222 nlmsg_cancel(skb, nlh); 223 return -1; 224 } 225 226 static int 227 ctnl_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 263 static 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. */ 312 static 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 330 static 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 361 static 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; 388 err: 389 return ret; 390 } 391 392 static int 393 cttimeout_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 426 nlmsg_failure: 427 nla_put_failure: 428 nlmsg_cancel(skb, nlh); 429 return -1; 430 } 431 432 static 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 511 static 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 } 526 err: 527 return matching ? &matching->timeout : NULL; 528 } 529 530 static 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 541 static 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 574 static 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 581 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT); 582 583 static 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 593 static 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 606 static 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 624 static 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 632 static const struct nf_ct_timeout_hooks hooks = { 633 .timeout_find_get = ctnl_timeout_find_get, 634 .timeout_put = ctnl_timeout_put, 635 }; 636 637 static 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 654 err_out: 655 unregister_pernet_subsys(&cttimeout_ops); 656 return ret; 657 } 658 659 static 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 669 static 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 679 module_init(cttimeout_init); 680 module_exit(cttimeout_exit); 681