linux/net/netfilter/nf_conntrack_expect.c
<<
>>
Prefs
   1/* Expectation handling for nf_conntrack. */
   2
   3/* (C) 1999-2001 Paul `Rusty' Russell
   4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
   5 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
   6 * (c) 2005-2012 Patrick McHardy <kaber@trash.net>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/types.h>
  14#include <linux/netfilter.h>
  15#include <linux/skbuff.h>
  16#include <linux/proc_fs.h>
  17#include <linux/seq_file.h>
  18#include <linux/stddef.h>
  19#include <linux/slab.h>
  20#include <linux/err.h>
  21#include <linux/percpu.h>
  22#include <linux/kernel.h>
  23#include <linux/jhash.h>
  24#include <linux/moduleparam.h>
  25#include <linux/export.h>
  26#include <net/net_namespace.h>
  27
  28#include <net/netfilter/nf_conntrack.h>
  29#include <net/netfilter/nf_conntrack_core.h>
  30#include <net/netfilter/nf_conntrack_expect.h>
  31#include <net/netfilter/nf_conntrack_helper.h>
  32#include <net/netfilter/nf_conntrack_tuple.h>
  33#include <net/netfilter/nf_conntrack_zones.h>
  34
  35unsigned int nf_ct_expect_hsize __read_mostly;
  36EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
  37
  38unsigned int nf_ct_expect_max __read_mostly;
  39
  40static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
  41
  42/* nf_conntrack_expect helper functions */
  43void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
  44                                u32 portid, int report)
  45{
  46        struct nf_conn_help *master_help = nfct_help(exp->master);
  47        struct net *net = nf_ct_exp_net(exp);
  48
  49        NF_CT_ASSERT(master_help);
  50        NF_CT_ASSERT(!timer_pending(&exp->timeout));
  51
  52        hlist_del_rcu(&exp->hnode);
  53        net->ct.expect_count--;
  54
  55        hlist_del(&exp->lnode);
  56        master_help->expecting[exp->class]--;
  57
  58        nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report);
  59        nf_ct_expect_put(exp);
  60
  61        NF_CT_STAT_INC(net, expect_delete);
  62}
  63EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report);
  64
  65static void nf_ct_expectation_timed_out(unsigned long ul_expect)
  66{
  67        struct nf_conntrack_expect *exp = (void *)ul_expect;
  68
  69        spin_lock_bh(&nf_conntrack_expect_lock);
  70        nf_ct_unlink_expect(exp);
  71        spin_unlock_bh(&nf_conntrack_expect_lock);
  72        nf_ct_expect_put(exp);
  73}
  74
  75static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple)
  76{
  77        unsigned int hash;
  78
  79        if (unlikely(!nf_conntrack_hash_rnd)) {
  80                init_nf_conntrack_hash_rnd();
  81        }
  82
  83        hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
  84                      (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
  85                       (__force __u16)tuple->dst.u.all) ^ nf_conntrack_hash_rnd);
  86
  87        return reciprocal_scale(hash, nf_ct_expect_hsize);
  88}
  89
  90struct nf_conntrack_expect *
  91__nf_ct_expect_find(struct net *net,
  92                    const struct nf_conntrack_zone *zone,
  93                    const struct nf_conntrack_tuple *tuple)
  94{
  95        struct nf_conntrack_expect *i;
  96        unsigned int h;
  97
  98        if (!net->ct.expect_count)
  99                return NULL;
 100
 101        h = nf_ct_expect_dst_hash(tuple);
 102        hlist_for_each_entry_rcu(i, &net->ct.expect_hash[h], hnode) {
 103                if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
 104                    nf_ct_zone_equal_any(i->master, zone))
 105                        return i;
 106        }
 107        return NULL;
 108}
 109EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
 110
 111/* Just find a expectation corresponding to a tuple. */
 112struct nf_conntrack_expect *
 113nf_ct_expect_find_get(struct net *net,
 114                      const struct nf_conntrack_zone *zone,
 115                      const struct nf_conntrack_tuple *tuple)
 116{
 117        struct nf_conntrack_expect *i;
 118
 119        rcu_read_lock();
 120        i = __nf_ct_expect_find(net, zone, tuple);
 121        if (i && !atomic_inc_not_zero(&i->use))
 122                i = NULL;
 123        rcu_read_unlock();
 124
 125        return i;
 126}
 127EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 128
 129/* If an expectation for this connection is found, it gets delete from
 130 * global list then returned. */
 131struct nf_conntrack_expect *
 132nf_ct_find_expectation(struct net *net,
 133                       const struct nf_conntrack_zone *zone,
 134                       const struct nf_conntrack_tuple *tuple)
 135{
 136        struct nf_conntrack_expect *i, *exp = NULL;
 137        unsigned int h;
 138
 139        if (!net->ct.expect_count)
 140                return NULL;
 141
 142        h = nf_ct_expect_dst_hash(tuple);
 143        hlist_for_each_entry(i, &net->ct.expect_hash[h], hnode) {
 144                if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
 145                    nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
 146                    nf_ct_zone_equal_any(i->master, zone)) {
 147                        exp = i;
 148                        break;
 149                }
 150        }
 151        if (!exp)
 152                return NULL;
 153
 154        /* If master is not in hash table yet (ie. packet hasn't left
 155           this machine yet), how can other end know about expected?
 156           Hence these are not the droids you are looking for (if
 157           master ct never got confirmed, we'd hold a reference to it
 158           and weird things would happen to future packets). */
 159        if (!nf_ct_is_confirmed(exp->master))
 160                return NULL;
 161
 162        /* Avoid race with other CPUs, that for exp->master ct, is
 163         * about to invoke ->destroy(), or nf_ct_delete() via timeout
 164         * or early_drop().
 165         *
 166         * The atomic_inc_not_zero() check tells:  If that fails, we
 167         * know that the ct is being destroyed.  If it succeeds, we
 168         * can be sure the ct cannot disappear underneath.
 169         */
 170        if (unlikely(nf_ct_is_dying(exp->master) ||
 171                     !atomic_inc_not_zero(&exp->master->ct_general.use)))
 172                return NULL;
 173
 174        if (exp->flags & NF_CT_EXPECT_PERMANENT) {
 175                atomic_inc(&exp->use);
 176                return exp;
 177        } else if (del_timer(&exp->timeout)) {
 178                nf_ct_unlink_expect(exp);
 179                return exp;
 180        }
 181        /* Undo exp->master refcnt increase, if del_timer() failed */
 182        nf_ct_put(exp->master);
 183
 184        return NULL;
 185}
 186
 187/* delete all expectations for this conntrack */
 188void nf_ct_remove_expectations(struct nf_conn *ct)
 189{
 190        struct nf_conn_help *help = nfct_help(ct);
 191        struct nf_conntrack_expect *exp;
 192        struct hlist_node *next;
 193
 194        /* Optimization: most connection never expect any others. */
 195        if (!help)
 196                return;
 197
 198        spin_lock_bh(&nf_conntrack_expect_lock);
 199        hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) {
 200                if (del_timer(&exp->timeout)) {
 201                        nf_ct_unlink_expect(exp);
 202                        nf_ct_expect_put(exp);
 203                }
 204        }
 205        spin_unlock_bh(&nf_conntrack_expect_lock);
 206}
 207EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);
 208
 209/* Would two expected things clash? */
 210static inline int expect_clash(const struct nf_conntrack_expect *a,
 211                               const struct nf_conntrack_expect *b)
 212{
 213        /* Part covered by intersection of masks must be unequal,
 214           otherwise they clash */
 215        struct nf_conntrack_tuple_mask intersect_mask;
 216        int count;
 217
 218        intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
 219
 220        for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
 221                intersect_mask.src.u3.all[count] =
 222                        a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
 223        }
 224
 225        return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) &&
 226               nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
 227}
 228
 229static inline int expect_matches(const struct nf_conntrack_expect *a,
 230                                 const struct nf_conntrack_expect *b)
 231{
 232        return a->master == b->master && a->class == b->class &&
 233               nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
 234               nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
 235               nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
 236}
 237
 238/* Generally a bad idea to call this: could have matched already. */
 239void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
 240{
 241        spin_lock_bh(&nf_conntrack_expect_lock);
 242        if (del_timer(&exp->timeout)) {
 243                nf_ct_unlink_expect(exp);
 244                nf_ct_expect_put(exp);
 245        }
 246        spin_unlock_bh(&nf_conntrack_expect_lock);
 247}
 248EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
 249
 250/* We don't increase the master conntrack refcount for non-fulfilled
 251 * conntracks. During the conntrack destruction, the expectations are
 252 * always killed before the conntrack itself */
 253struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 254{
 255        struct nf_conntrack_expect *new;
 256
 257        new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
 258        if (!new)
 259                return NULL;
 260
 261        new->master = me;
 262        atomic_set(&new->use, 1);
 263        return new;
 264}
 265EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
 266
 267void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
 268                       u_int8_t family,
 269                       const union nf_inet_addr *saddr,
 270                       const union nf_inet_addr *daddr,
 271                       u_int8_t proto, const __be16 *src, const __be16 *dst)
 272{
 273        int len;
 274
 275        if (family == AF_INET)
 276                len = 4;
 277        else
 278                len = 16;
 279
 280        exp->flags = 0;
 281        exp->class = class;
 282        exp->expectfn = NULL;
 283        exp->helper = NULL;
 284        exp->tuple.src.l3num = family;
 285        exp->tuple.dst.protonum = proto;
 286
 287        if (saddr) {
 288                memcpy(&exp->tuple.src.u3, saddr, len);
 289                if (sizeof(exp->tuple.src.u3) > len)
 290                        /* address needs to be cleared for nf_ct_tuple_equal */
 291                        memset((void *)&exp->tuple.src.u3 + len, 0x00,
 292                               sizeof(exp->tuple.src.u3) - len);
 293                memset(&exp->mask.src.u3, 0xFF, len);
 294                if (sizeof(exp->mask.src.u3) > len)
 295                        memset((void *)&exp->mask.src.u3 + len, 0x00,
 296                               sizeof(exp->mask.src.u3) - len);
 297        } else {
 298                memset(&exp->tuple.src.u3, 0x00, sizeof(exp->tuple.src.u3));
 299                memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
 300        }
 301
 302        if (src) {
 303                exp->tuple.src.u.all = *src;
 304                exp->mask.src.u.all = htons(0xFFFF);
 305        } else {
 306                exp->tuple.src.u.all = 0;
 307                exp->mask.src.u.all = 0;
 308        }
 309
 310        memcpy(&exp->tuple.dst.u3, daddr, len);
 311        if (sizeof(exp->tuple.dst.u3) > len)
 312                /* address needs to be cleared for nf_ct_tuple_equal */
 313                memset((void *)&exp->tuple.dst.u3 + len, 0x00,
 314                       sizeof(exp->tuple.dst.u3) - len);
 315
 316        exp->tuple.dst.u.all = *dst;
 317
 318#ifdef CONFIG_NF_NAT_NEEDED
 319        memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
 320        memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
 321#endif
 322}
 323EXPORT_SYMBOL_GPL(nf_ct_expect_init);
 324
 325static void nf_ct_expect_free_rcu(struct rcu_head *head)
 326{
 327        struct nf_conntrack_expect *exp;
 328
 329        exp = container_of(head, struct nf_conntrack_expect, rcu);
 330        kmem_cache_free(nf_ct_expect_cachep, exp);
 331}
 332
 333void nf_ct_expect_put(struct nf_conntrack_expect *exp)
 334{
 335        if (atomic_dec_and_test(&exp->use))
 336                call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
 337}
 338EXPORT_SYMBOL_GPL(nf_ct_expect_put);
 339
 340static int nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 341{
 342        struct nf_conn_help *master_help = nfct_help(exp->master);
 343        struct nf_conntrack_helper *helper;
 344        struct net *net = nf_ct_exp_net(exp);
 345        unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
 346
 347        /* two references : one for hash insert, one for the timer */
 348        atomic_add(2, &exp->use);
 349
 350        hlist_add_head(&exp->lnode, &master_help->expectations);
 351        master_help->expecting[exp->class]++;
 352
 353        hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]);
 354        net->ct.expect_count++;
 355
 356        setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
 357                    (unsigned long)exp);
 358        helper = rcu_dereference_protected(master_help->helper,
 359                                           lockdep_is_held(&nf_conntrack_expect_lock));
 360        if (helper) {
 361                exp->timeout.expires = jiffies +
 362                        helper->expect_policy[exp->class].timeout * HZ;
 363        }
 364        add_timer(&exp->timeout);
 365
 366        NF_CT_STAT_INC(net, expect_create);
 367        return 0;
 368}
 369
 370/* Race with expectations being used means we could have none to find; OK. */
 371static void evict_oldest_expect(struct nf_conn *master,
 372                                struct nf_conntrack_expect *new)
 373{
 374        struct nf_conn_help *master_help = nfct_help(master);
 375        struct nf_conntrack_expect *exp, *last = NULL;
 376
 377        hlist_for_each_entry(exp, &master_help->expectations, lnode) {
 378                if (exp->class == new->class)
 379                        last = exp;
 380        }
 381
 382        if (last && del_timer(&last->timeout)) {
 383                nf_ct_unlink_expect(last);
 384                nf_ct_expect_put(last);
 385        }
 386}
 387
 388static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
 389{
 390        const struct nf_conntrack_expect_policy *p;
 391        struct nf_conntrack_expect *i;
 392        struct nf_conn *master = expect->master;
 393        struct nf_conn_help *master_help = nfct_help(master);
 394        struct nf_conntrack_helper *helper;
 395        struct net *net = nf_ct_exp_net(expect);
 396        struct hlist_node *next;
 397        unsigned int h;
 398        int ret = 1;
 399
 400        if (!master_help) {
 401                ret = -ESHUTDOWN;
 402                goto out;
 403        }
 404        h = nf_ct_expect_dst_hash(&expect->tuple);
 405        hlist_for_each_entry_safe(i, next, &net->ct.expect_hash[h], hnode) {
 406                if (expect_matches(i, expect)) {
 407                        if (del_timer(&i->timeout)) {
 408                                nf_ct_unlink_expect(i);
 409                                nf_ct_expect_put(i);
 410                                break;
 411                        }
 412                } else if (expect_clash(i, expect)) {
 413                        ret = -EBUSY;
 414                        goto out;
 415                }
 416        }
 417        /* Will be over limit? */
 418        helper = rcu_dereference_protected(master_help->helper,
 419                                           lockdep_is_held(&nf_conntrack_expect_lock));
 420        if (helper) {
 421                p = &helper->expect_policy[expect->class];
 422                if (p->max_expected &&
 423                    master_help->expecting[expect->class] >= p->max_expected) {
 424                        evict_oldest_expect(master, expect);
 425                        if (master_help->expecting[expect->class]
 426                                                >= p->max_expected) {
 427                                ret = -EMFILE;
 428                                goto out;
 429                        }
 430                }
 431        }
 432
 433        if (net->ct.expect_count >= nf_ct_expect_max) {
 434                net_warn_ratelimited("nf_conntrack: expectation table full\n");
 435                ret = -EMFILE;
 436        }
 437out:
 438        return ret;
 439}
 440
 441int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
 442                                u32 portid, int report)
 443{
 444        int ret;
 445
 446        spin_lock_bh(&nf_conntrack_expect_lock);
 447        ret = __nf_ct_expect_check(expect);
 448        if (ret <= 0)
 449                goto out;
 450
 451        ret = nf_ct_expect_insert(expect);
 452        if (ret < 0)
 453                goto out;
 454        spin_unlock_bh(&nf_conntrack_expect_lock);
 455        nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
 456        return ret;
 457out:
 458        spin_unlock_bh(&nf_conntrack_expect_lock);
 459        return ret;
 460}
 461EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
 462
 463#ifdef CONFIG_NF_CONNTRACK_PROCFS
 464struct ct_expect_iter_state {
 465        struct seq_net_private p;
 466        unsigned int bucket;
 467};
 468
 469static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 470{
 471        struct net *net = seq_file_net(seq);
 472        struct ct_expect_iter_state *st = seq->private;
 473        struct hlist_node *n;
 474
 475        for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
 476                n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 477                if (n)
 478                        return n;
 479        }
 480        return NULL;
 481}
 482
 483static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
 484                                             struct hlist_node *head)
 485{
 486        struct net *net = seq_file_net(seq);
 487        struct ct_expect_iter_state *st = seq->private;
 488
 489        head = rcu_dereference(hlist_next_rcu(head));
 490        while (head == NULL) {
 491                if (++st->bucket >= nf_ct_expect_hsize)
 492                        return NULL;
 493                head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 494        }
 495        return head;
 496}
 497
 498static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
 499{
 500        struct hlist_node *head = ct_expect_get_first(seq);
 501
 502        if (head)
 503                while (pos && (head = ct_expect_get_next(seq, head)))
 504                        pos--;
 505        return pos ? NULL : head;
 506}
 507
 508static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
 509        __acquires(RCU)
 510{
 511        rcu_read_lock();
 512        return ct_expect_get_idx(seq, *pos);
 513}
 514
 515static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 516{
 517        (*pos)++;
 518        return ct_expect_get_next(seq, v);
 519}
 520
 521static void exp_seq_stop(struct seq_file *seq, void *v)
 522        __releases(RCU)
 523{
 524        rcu_read_unlock();
 525}
 526
 527static int exp_seq_show(struct seq_file *s, void *v)
 528{
 529        struct nf_conntrack_expect *expect;
 530        struct nf_conntrack_helper *helper;
 531        struct hlist_node *n = v;
 532        char *delim = "";
 533
 534        expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
 535
 536        if (expect->timeout.function)
 537                seq_printf(s, "%ld ", timer_pending(&expect->timeout)
 538                           ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
 539        else
 540                seq_printf(s, "- ");
 541        seq_printf(s, "l3proto = %u proto=%u ",
 542                   expect->tuple.src.l3num,
 543                   expect->tuple.dst.protonum);
 544        print_tuple(s, &expect->tuple,
 545                    __nf_ct_l3proto_find(expect->tuple.src.l3num),
 546                    __nf_ct_l4proto_find(expect->tuple.src.l3num,
 547                                       expect->tuple.dst.protonum));
 548
 549        if (expect->flags & NF_CT_EXPECT_PERMANENT) {
 550                seq_printf(s, "PERMANENT");
 551                delim = ",";
 552        }
 553        if (expect->flags & NF_CT_EXPECT_INACTIVE) {
 554                seq_printf(s, "%sINACTIVE", delim);
 555                delim = ",";
 556        }
 557        if (expect->flags & NF_CT_EXPECT_USERSPACE)
 558                seq_printf(s, "%sUSERSPACE", delim);
 559
 560        helper = rcu_dereference(nfct_help(expect->master)->helper);
 561        if (helper) {
 562                seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name);
 563                if (helper->expect_policy[expect->class].name)
 564                        seq_printf(s, "/%s",
 565                                   helper->expect_policy[expect->class].name);
 566        }
 567
 568        return seq_putc(s, '\n');
 569}
 570
 571static const struct seq_operations exp_seq_ops = {
 572        .start = exp_seq_start,
 573        .next = exp_seq_next,
 574        .stop = exp_seq_stop,
 575        .show = exp_seq_show
 576};
 577
 578static int exp_open(struct inode *inode, struct file *file)
 579{
 580        return seq_open_net(inode, file, &exp_seq_ops,
 581                        sizeof(struct ct_expect_iter_state));
 582}
 583
 584static const struct file_operations exp_file_ops = {
 585        .owner   = THIS_MODULE,
 586        .open    = exp_open,
 587        .read    = seq_read,
 588        .llseek  = seq_lseek,
 589        .release = seq_release_net,
 590};
 591#endif /* CONFIG_NF_CONNTRACK_PROCFS */
 592
 593static int exp_proc_init(struct net *net)
 594{
 595#ifdef CONFIG_NF_CONNTRACK_PROCFS
 596        struct proc_dir_entry *proc;
 597
 598        proc = proc_create("nf_conntrack_expect", 0440, net->proc_net,
 599                           &exp_file_ops);
 600        if (!proc)
 601                return -ENOMEM;
 602#endif /* CONFIG_NF_CONNTRACK_PROCFS */
 603        return 0;
 604}
 605
 606static void exp_proc_remove(struct net *net)
 607{
 608#ifdef CONFIG_NF_CONNTRACK_PROCFS
 609        remove_proc_entry("nf_conntrack_expect", net->proc_net);
 610#endif /* CONFIG_NF_CONNTRACK_PROCFS */
 611}
 612
 613module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
 614
 615int nf_conntrack_expect_pernet_init(struct net *net)
 616{
 617        int err = -ENOMEM;
 618
 619        net->ct.expect_count = 0;
 620        net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 0);
 621        if (net->ct.expect_hash == NULL)
 622                goto err1;
 623
 624        err = exp_proc_init(net);
 625        if (err < 0)
 626                goto err2;
 627
 628        return 0;
 629err2:
 630        nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
 631err1:
 632        return err;
 633}
 634
 635void nf_conntrack_expect_pernet_fini(struct net *net)
 636{
 637        exp_proc_remove(net);
 638        nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
 639}
 640
 641int nf_conntrack_expect_init(void)
 642{
 643        if (!nf_ct_expect_hsize) {
 644                nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
 645                if (!nf_ct_expect_hsize)
 646                        nf_ct_expect_hsize = 1;
 647        }
 648        nf_ct_expect_max = nf_ct_expect_hsize * 4;
 649        nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
 650                                sizeof(struct nf_conntrack_expect),
 651                                0, 0, NULL);
 652        if (!nf_ct_expect_cachep)
 653                return -ENOMEM;
 654        return 0;
 655}
 656
 657void nf_conntrack_expect_fini(void)
 658{
 659        rcu_barrier(); /* Wait for call_rcu() before destroy */
 660        kmem_cache_destroy(nf_ct_expect_cachep);
 661}
 662