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