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