Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Expectation handling for nf_conntrack. */
0003 
0004 /* (C) 1999-2001 Paul `Rusty' Russell
0005  * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
0006  * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
0007  * (c) 2005-2012 Patrick McHardy <kaber@trash.net>
0008  */
0009 
0010 #include <linux/types.h>
0011 #include <linux/netfilter.h>
0012 #include <linux/skbuff.h>
0013 #include <linux/proc_fs.h>
0014 #include <linux/seq_file.h>
0015 #include <linux/stddef.h>
0016 #include <linux/slab.h>
0017 #include <linux/err.h>
0018 #include <linux/percpu.h>
0019 #include <linux/kernel.h>
0020 #include <linux/siphash.h>
0021 #include <linux/moduleparam.h>
0022 #include <linux/export.h>
0023 #include <net/net_namespace.h>
0024 #include <net/netns/hash.h>
0025 
0026 #include <net/netfilter/nf_conntrack.h>
0027 #include <net/netfilter/nf_conntrack_core.h>
0028 #include <net/netfilter/nf_conntrack_ecache.h>
0029 #include <net/netfilter/nf_conntrack_expect.h>
0030 #include <net/netfilter/nf_conntrack_helper.h>
0031 #include <net/netfilter/nf_conntrack_l4proto.h>
0032 #include <net/netfilter/nf_conntrack_tuple.h>
0033 #include <net/netfilter/nf_conntrack_zones.h>
0034 
0035 unsigned int nf_ct_expect_hsize __read_mostly;
0036 EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
0037 
0038 struct hlist_head *nf_ct_expect_hash __read_mostly;
0039 EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
0040 
0041 unsigned int nf_ct_expect_max __read_mostly;
0042 
0043 static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
0044 static siphash_aligned_key_t nf_ct_expect_hashrnd;
0045 
0046 /* nf_conntrack_expect helper functions */
0047 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
0048                 u32 portid, int report)
0049 {
0050     struct nf_conn_help *master_help = nfct_help(exp->master);
0051     struct net *net = nf_ct_exp_net(exp);
0052     struct nf_conntrack_net *cnet;
0053 
0054     WARN_ON(!master_help);
0055     WARN_ON(timer_pending(&exp->timeout));
0056 
0057     hlist_del_rcu(&exp->hnode);
0058 
0059     cnet = nf_ct_pernet(net);
0060     cnet->expect_count--;
0061 
0062     hlist_del_rcu(&exp->lnode);
0063     master_help->expecting[exp->class]--;
0064 
0065     nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report);
0066     nf_ct_expect_put(exp);
0067 
0068     NF_CT_STAT_INC(net, expect_delete);
0069 }
0070 EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report);
0071 
0072 static void nf_ct_expectation_timed_out(struct timer_list *t)
0073 {
0074     struct nf_conntrack_expect *exp = from_timer(exp, t, timeout);
0075 
0076     spin_lock_bh(&nf_conntrack_expect_lock);
0077     nf_ct_unlink_expect(exp);
0078     spin_unlock_bh(&nf_conntrack_expect_lock);
0079     nf_ct_expect_put(exp);
0080 }
0081 
0082 static unsigned int nf_ct_expect_dst_hash(const struct net *n, const struct nf_conntrack_tuple *tuple)
0083 {
0084     struct {
0085         union nf_inet_addr dst_addr;
0086         u32 net_mix;
0087         u16 dport;
0088         u8 l3num;
0089         u8 protonum;
0090     } __aligned(SIPHASH_ALIGNMENT) combined;
0091     u32 hash;
0092 
0093     get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd));
0094 
0095     memset(&combined, 0, sizeof(combined));
0096 
0097     combined.dst_addr = tuple->dst.u3;
0098     combined.net_mix = net_hash_mix(n);
0099     combined.dport = (__force __u16)tuple->dst.u.all;
0100     combined.l3num = tuple->src.l3num;
0101     combined.protonum = tuple->dst.protonum;
0102 
0103     hash = siphash(&combined, sizeof(combined), &nf_ct_expect_hashrnd);
0104 
0105     return reciprocal_scale(hash, nf_ct_expect_hsize);
0106 }
0107 
0108 static bool
0109 nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple,
0110         const struct nf_conntrack_expect *i,
0111         const struct nf_conntrack_zone *zone,
0112         const struct net *net)
0113 {
0114     return nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
0115            net_eq(net, nf_ct_net(i->master)) &&
0116            nf_ct_zone_equal_any(i->master, zone);
0117 }
0118 
0119 bool nf_ct_remove_expect(struct nf_conntrack_expect *exp)
0120 {
0121     if (del_timer(&exp->timeout)) {
0122         nf_ct_unlink_expect(exp);
0123         nf_ct_expect_put(exp);
0124         return true;
0125     }
0126     return false;
0127 }
0128 EXPORT_SYMBOL_GPL(nf_ct_remove_expect);
0129 
0130 struct nf_conntrack_expect *
0131 __nf_ct_expect_find(struct net *net,
0132             const struct nf_conntrack_zone *zone,
0133             const struct nf_conntrack_tuple *tuple)
0134 {
0135     struct nf_conntrack_net *cnet = nf_ct_pernet(net);
0136     struct nf_conntrack_expect *i;
0137     unsigned int h;
0138 
0139     if (!cnet->expect_count)
0140         return NULL;
0141 
0142     h = nf_ct_expect_dst_hash(net, tuple);
0143     hlist_for_each_entry_rcu(i, &nf_ct_expect_hash[h], hnode) {
0144         if (nf_ct_exp_equal(tuple, i, zone, net))
0145             return i;
0146     }
0147     return NULL;
0148 }
0149 EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
0150 
0151 /* Just find a expectation corresponding to a tuple. */
0152 struct nf_conntrack_expect *
0153 nf_ct_expect_find_get(struct net *net,
0154               const struct nf_conntrack_zone *zone,
0155               const struct nf_conntrack_tuple *tuple)
0156 {
0157     struct nf_conntrack_expect *i;
0158 
0159     rcu_read_lock();
0160     i = __nf_ct_expect_find(net, zone, tuple);
0161     if (i && !refcount_inc_not_zero(&i->use))
0162         i = NULL;
0163     rcu_read_unlock();
0164 
0165     return i;
0166 }
0167 EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
0168 
0169 /* If an expectation for this connection is found, it gets delete from
0170  * global list then returned. */
0171 struct nf_conntrack_expect *
0172 nf_ct_find_expectation(struct net *net,
0173                const struct nf_conntrack_zone *zone,
0174                const struct nf_conntrack_tuple *tuple)
0175 {
0176     struct nf_conntrack_net *cnet = nf_ct_pernet(net);
0177     struct nf_conntrack_expect *i, *exp = NULL;
0178     unsigned int h;
0179 
0180     if (!cnet->expect_count)
0181         return NULL;
0182 
0183     h = nf_ct_expect_dst_hash(net, tuple);
0184     hlist_for_each_entry(i, &nf_ct_expect_hash[h], hnode) {
0185         if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
0186             nf_ct_exp_equal(tuple, i, zone, net)) {
0187             exp = i;
0188             break;
0189         }
0190     }
0191     if (!exp)
0192         return NULL;
0193 
0194     /* If master is not in hash table yet (ie. packet hasn't left
0195        this machine yet), how can other end know about expected?
0196        Hence these are not the droids you are looking for (if
0197        master ct never got confirmed, we'd hold a reference to it
0198        and weird things would happen to future packets). */
0199     if (!nf_ct_is_confirmed(exp->master))
0200         return NULL;
0201 
0202     /* Avoid race with other CPUs, that for exp->master ct, is
0203      * about to invoke ->destroy(), or nf_ct_delete() via timeout
0204      * or early_drop().
0205      *
0206      * The refcount_inc_not_zero() check tells:  If that fails, we
0207      * know that the ct is being destroyed.  If it succeeds, we
0208      * can be sure the ct cannot disappear underneath.
0209      */
0210     if (unlikely(nf_ct_is_dying(exp->master) ||
0211              !refcount_inc_not_zero(&exp->master->ct_general.use)))
0212         return NULL;
0213 
0214     if (exp->flags & NF_CT_EXPECT_PERMANENT) {
0215         refcount_inc(&exp->use);
0216         return exp;
0217     } else if (del_timer(&exp->timeout)) {
0218         nf_ct_unlink_expect(exp);
0219         return exp;
0220     }
0221     /* Undo exp->master refcnt increase, if del_timer() failed */
0222     nf_ct_put(exp->master);
0223 
0224     return NULL;
0225 }
0226 
0227 /* delete all expectations for this conntrack */
0228 void nf_ct_remove_expectations(struct nf_conn *ct)
0229 {
0230     struct nf_conn_help *help = nfct_help(ct);
0231     struct nf_conntrack_expect *exp;
0232     struct hlist_node *next;
0233 
0234     /* Optimization: most connection never expect any others. */
0235     if (!help)
0236         return;
0237 
0238     spin_lock_bh(&nf_conntrack_expect_lock);
0239     hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) {
0240         nf_ct_remove_expect(exp);
0241     }
0242     spin_unlock_bh(&nf_conntrack_expect_lock);
0243 }
0244 EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);
0245 
0246 /* Would two expected things clash? */
0247 static inline int expect_clash(const struct nf_conntrack_expect *a,
0248                    const struct nf_conntrack_expect *b)
0249 {
0250     /* Part covered by intersection of masks must be unequal,
0251        otherwise they clash */
0252     struct nf_conntrack_tuple_mask intersect_mask;
0253     int count;
0254 
0255     intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
0256 
0257     for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
0258         intersect_mask.src.u3.all[count] =
0259             a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
0260     }
0261 
0262     return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) &&
0263            net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
0264            nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
0265 }
0266 
0267 static inline int expect_matches(const struct nf_conntrack_expect *a,
0268                  const struct nf_conntrack_expect *b)
0269 {
0270     return nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
0271            nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
0272            net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
0273            nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
0274 }
0275 
0276 static bool master_matches(const struct nf_conntrack_expect *a,
0277                const struct nf_conntrack_expect *b,
0278                unsigned int flags)
0279 {
0280     if (flags & NF_CT_EXP_F_SKIP_MASTER)
0281         return true;
0282 
0283     return a->master == b->master;
0284 }
0285 
0286 /* Generally a bad idea to call this: could have matched already. */
0287 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
0288 {
0289     spin_lock_bh(&nf_conntrack_expect_lock);
0290     nf_ct_remove_expect(exp);
0291     spin_unlock_bh(&nf_conntrack_expect_lock);
0292 }
0293 EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
0294 
0295 /* We don't increase the master conntrack refcount for non-fulfilled
0296  * conntracks. During the conntrack destruction, the expectations are
0297  * always killed before the conntrack itself */
0298 struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
0299 {
0300     struct nf_conntrack_expect *new;
0301 
0302     new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
0303     if (!new)
0304         return NULL;
0305 
0306     new->master = me;
0307     refcount_set(&new->use, 1);
0308     return new;
0309 }
0310 EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
0311 
0312 void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
0313                u_int8_t family,
0314                const union nf_inet_addr *saddr,
0315                const union nf_inet_addr *daddr,
0316                u_int8_t proto, const __be16 *src, const __be16 *dst)
0317 {
0318     int len;
0319 
0320     if (family == AF_INET)
0321         len = 4;
0322     else
0323         len = 16;
0324 
0325     exp->flags = 0;
0326     exp->class = class;
0327     exp->expectfn = NULL;
0328     exp->helper = NULL;
0329     exp->tuple.src.l3num = family;
0330     exp->tuple.dst.protonum = proto;
0331 
0332     if (saddr) {
0333         memcpy(&exp->tuple.src.u3, saddr, len);
0334         if (sizeof(exp->tuple.src.u3) > len)
0335             /* address needs to be cleared for nf_ct_tuple_equal */
0336             memset((void *)&exp->tuple.src.u3 + len, 0x00,
0337                    sizeof(exp->tuple.src.u3) - len);
0338         memset(&exp->mask.src.u3, 0xFF, len);
0339         if (sizeof(exp->mask.src.u3) > len)
0340             memset((void *)&exp->mask.src.u3 + len, 0x00,
0341                    sizeof(exp->mask.src.u3) - len);
0342     } else {
0343         memset(&exp->tuple.src.u3, 0x00, sizeof(exp->tuple.src.u3));
0344         memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
0345     }
0346 
0347     if (src) {
0348         exp->tuple.src.u.all = *src;
0349         exp->mask.src.u.all = htons(0xFFFF);
0350     } else {
0351         exp->tuple.src.u.all = 0;
0352         exp->mask.src.u.all = 0;
0353     }
0354 
0355     memcpy(&exp->tuple.dst.u3, daddr, len);
0356     if (sizeof(exp->tuple.dst.u3) > len)
0357         /* address needs to be cleared for nf_ct_tuple_equal */
0358         memset((void *)&exp->tuple.dst.u3 + len, 0x00,
0359                sizeof(exp->tuple.dst.u3) - len);
0360 
0361     exp->tuple.dst.u.all = *dst;
0362 
0363 #if IS_ENABLED(CONFIG_NF_NAT)
0364     memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
0365     memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
0366 #endif
0367 }
0368 EXPORT_SYMBOL_GPL(nf_ct_expect_init);
0369 
0370 static void nf_ct_expect_free_rcu(struct rcu_head *head)
0371 {
0372     struct nf_conntrack_expect *exp;
0373 
0374     exp = container_of(head, struct nf_conntrack_expect, rcu);
0375     kmem_cache_free(nf_ct_expect_cachep, exp);
0376 }
0377 
0378 void nf_ct_expect_put(struct nf_conntrack_expect *exp)
0379 {
0380     if (refcount_dec_and_test(&exp->use))
0381         call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
0382 }
0383 EXPORT_SYMBOL_GPL(nf_ct_expect_put);
0384 
0385 static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
0386 {
0387     struct nf_conntrack_net *cnet;
0388     struct nf_conn_help *master_help = nfct_help(exp->master);
0389     struct nf_conntrack_helper *helper;
0390     struct net *net = nf_ct_exp_net(exp);
0391     unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
0392 
0393     /* two references : one for hash insert, one for the timer */
0394     refcount_add(2, &exp->use);
0395 
0396     timer_setup(&exp->timeout, nf_ct_expectation_timed_out, 0);
0397     helper = rcu_dereference_protected(master_help->helper,
0398                        lockdep_is_held(&nf_conntrack_expect_lock));
0399     if (helper) {
0400         exp->timeout.expires = jiffies +
0401             helper->expect_policy[exp->class].timeout * HZ;
0402     }
0403     add_timer(&exp->timeout);
0404 
0405     hlist_add_head_rcu(&exp->lnode, &master_help->expectations);
0406     master_help->expecting[exp->class]++;
0407 
0408     hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
0409     cnet = nf_ct_pernet(net);
0410     cnet->expect_count++;
0411 
0412     NF_CT_STAT_INC(net, expect_create);
0413 }
0414 
0415 /* Race with expectations being used means we could have none to find; OK. */
0416 static void evict_oldest_expect(struct nf_conn *master,
0417                 struct nf_conntrack_expect *new)
0418 {
0419     struct nf_conn_help *master_help = nfct_help(master);
0420     struct nf_conntrack_expect *exp, *last = NULL;
0421 
0422     hlist_for_each_entry(exp, &master_help->expectations, lnode) {
0423         if (exp->class == new->class)
0424             last = exp;
0425     }
0426 
0427     if (last)
0428         nf_ct_remove_expect(last);
0429 }
0430 
0431 static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
0432                        unsigned int flags)
0433 {
0434     const struct nf_conntrack_expect_policy *p;
0435     struct nf_conntrack_expect *i;
0436     struct nf_conntrack_net *cnet;
0437     struct nf_conn *master = expect->master;
0438     struct nf_conn_help *master_help = nfct_help(master);
0439     struct nf_conntrack_helper *helper;
0440     struct net *net = nf_ct_exp_net(expect);
0441     struct hlist_node *next;
0442     unsigned int h;
0443     int ret = 0;
0444 
0445     if (!master_help) {
0446         ret = -ESHUTDOWN;
0447         goto out;
0448     }
0449     h = nf_ct_expect_dst_hash(net, &expect->tuple);
0450     hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
0451         if (master_matches(i, expect, flags) &&
0452             expect_matches(i, expect)) {
0453             if (i->class != expect->class ||
0454                 i->master != expect->master)
0455                 return -EALREADY;
0456 
0457             if (nf_ct_remove_expect(i))
0458                 break;
0459         } else if (expect_clash(i, expect)) {
0460             ret = -EBUSY;
0461             goto out;
0462         }
0463     }
0464     /* Will be over limit? */
0465     helper = rcu_dereference_protected(master_help->helper,
0466                        lockdep_is_held(&nf_conntrack_expect_lock));
0467     if (helper) {
0468         p = &helper->expect_policy[expect->class];
0469         if (p->max_expected &&
0470             master_help->expecting[expect->class] >= p->max_expected) {
0471             evict_oldest_expect(master, expect);
0472             if (master_help->expecting[expect->class]
0473                         >= p->max_expected) {
0474                 ret = -EMFILE;
0475                 goto out;
0476             }
0477         }
0478     }
0479 
0480     cnet = nf_ct_pernet(net);
0481     if (cnet->expect_count >= nf_ct_expect_max) {
0482         net_warn_ratelimited("nf_conntrack: expectation table full\n");
0483         ret = -EMFILE;
0484     }
0485 out:
0486     return ret;
0487 }
0488 
0489 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
0490                 u32 portid, int report, unsigned int flags)
0491 {
0492     int ret;
0493 
0494     spin_lock_bh(&nf_conntrack_expect_lock);
0495     ret = __nf_ct_expect_check(expect, flags);
0496     if (ret < 0)
0497         goto out;
0498 
0499     nf_ct_expect_insert(expect);
0500 
0501     spin_unlock_bh(&nf_conntrack_expect_lock);
0502     nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
0503     return 0;
0504 out:
0505     spin_unlock_bh(&nf_conntrack_expect_lock);
0506     return ret;
0507 }
0508 EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
0509 
0510 void nf_ct_expect_iterate_destroy(bool (*iter)(struct nf_conntrack_expect *e, void *data),
0511                   void *data)
0512 {
0513     struct nf_conntrack_expect *exp;
0514     const struct hlist_node *next;
0515     unsigned int i;
0516 
0517     spin_lock_bh(&nf_conntrack_expect_lock);
0518 
0519     for (i = 0; i < nf_ct_expect_hsize; i++) {
0520         hlist_for_each_entry_safe(exp, next,
0521                       &nf_ct_expect_hash[i],
0522                       hnode) {
0523             if (iter(exp, data) && del_timer(&exp->timeout)) {
0524                 nf_ct_unlink_expect(exp);
0525                 nf_ct_expect_put(exp);
0526             }
0527         }
0528     }
0529 
0530     spin_unlock_bh(&nf_conntrack_expect_lock);
0531 }
0532 EXPORT_SYMBOL_GPL(nf_ct_expect_iterate_destroy);
0533 
0534 void nf_ct_expect_iterate_net(struct net *net,
0535                   bool (*iter)(struct nf_conntrack_expect *e, void *data),
0536                   void *data,
0537                   u32 portid, int report)
0538 {
0539     struct nf_conntrack_expect *exp;
0540     const struct hlist_node *next;
0541     unsigned int i;
0542 
0543     spin_lock_bh(&nf_conntrack_expect_lock);
0544 
0545     for (i = 0; i < nf_ct_expect_hsize; i++) {
0546         hlist_for_each_entry_safe(exp, next,
0547                       &nf_ct_expect_hash[i],
0548                       hnode) {
0549 
0550             if (!net_eq(nf_ct_exp_net(exp), net))
0551                 continue;
0552 
0553             if (iter(exp, data) && del_timer(&exp->timeout)) {
0554                 nf_ct_unlink_expect_report(exp, portid, report);
0555                 nf_ct_expect_put(exp);
0556             }
0557         }
0558     }
0559 
0560     spin_unlock_bh(&nf_conntrack_expect_lock);
0561 }
0562 EXPORT_SYMBOL_GPL(nf_ct_expect_iterate_net);
0563 
0564 #ifdef CONFIG_NF_CONNTRACK_PROCFS
0565 struct ct_expect_iter_state {
0566     struct seq_net_private p;
0567     unsigned int bucket;
0568 };
0569 
0570 static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
0571 {
0572     struct ct_expect_iter_state *st = seq->private;
0573     struct hlist_node *n;
0574 
0575     for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
0576         n = rcu_dereference(hlist_first_rcu(&nf_ct_expect_hash[st->bucket]));
0577         if (n)
0578             return n;
0579     }
0580     return NULL;
0581 }
0582 
0583 static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
0584                          struct hlist_node *head)
0585 {
0586     struct ct_expect_iter_state *st = seq->private;
0587 
0588     head = rcu_dereference(hlist_next_rcu(head));
0589     while (head == NULL) {
0590         if (++st->bucket >= nf_ct_expect_hsize)
0591             return NULL;
0592         head = rcu_dereference(hlist_first_rcu(&nf_ct_expect_hash[st->bucket]));
0593     }
0594     return head;
0595 }
0596 
0597 static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
0598 {
0599     struct hlist_node *head = ct_expect_get_first(seq);
0600 
0601     if (head)
0602         while (pos && (head = ct_expect_get_next(seq, head)))
0603             pos--;
0604     return pos ? NULL : head;
0605 }
0606 
0607 static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
0608     __acquires(RCU)
0609 {
0610     rcu_read_lock();
0611     return ct_expect_get_idx(seq, *pos);
0612 }
0613 
0614 static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0615 {
0616     (*pos)++;
0617     return ct_expect_get_next(seq, v);
0618 }
0619 
0620 static void exp_seq_stop(struct seq_file *seq, void *v)
0621     __releases(RCU)
0622 {
0623     rcu_read_unlock();
0624 }
0625 
0626 static int exp_seq_show(struct seq_file *s, void *v)
0627 {
0628     struct nf_conntrack_expect *expect;
0629     struct nf_conntrack_helper *helper;
0630     struct hlist_node *n = v;
0631     char *delim = "";
0632 
0633     expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
0634 
0635     if (expect->timeout.function)
0636         seq_printf(s, "%ld ", timer_pending(&expect->timeout)
0637                ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
0638     else
0639         seq_puts(s, "- ");
0640     seq_printf(s, "l3proto = %u proto=%u ",
0641            expect->tuple.src.l3num,
0642            expect->tuple.dst.protonum);
0643     print_tuple(s, &expect->tuple,
0644             nf_ct_l4proto_find(expect->tuple.dst.protonum));
0645 
0646     if (expect->flags & NF_CT_EXPECT_PERMANENT) {
0647         seq_puts(s, "PERMANENT");
0648         delim = ",";
0649     }
0650     if (expect->flags & NF_CT_EXPECT_INACTIVE) {
0651         seq_printf(s, "%sINACTIVE", delim);
0652         delim = ",";
0653     }
0654     if (expect->flags & NF_CT_EXPECT_USERSPACE)
0655         seq_printf(s, "%sUSERSPACE", delim);
0656 
0657     helper = rcu_dereference(nfct_help(expect->master)->helper);
0658     if (helper) {
0659         seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name);
0660         if (helper->expect_policy[expect->class].name[0])
0661             seq_printf(s, "/%s",
0662                    helper->expect_policy[expect->class].name);
0663     }
0664 
0665     seq_putc(s, '\n');
0666 
0667     return 0;
0668 }
0669 
0670 static const struct seq_operations exp_seq_ops = {
0671     .start = exp_seq_start,
0672     .next = exp_seq_next,
0673     .stop = exp_seq_stop,
0674     .show = exp_seq_show
0675 };
0676 #endif /* CONFIG_NF_CONNTRACK_PROCFS */
0677 
0678 static int exp_proc_init(struct net *net)
0679 {
0680 #ifdef CONFIG_NF_CONNTRACK_PROCFS
0681     struct proc_dir_entry *proc;
0682     kuid_t root_uid;
0683     kgid_t root_gid;
0684 
0685     proc = proc_create_net("nf_conntrack_expect", 0440, net->proc_net,
0686             &exp_seq_ops, sizeof(struct ct_expect_iter_state));
0687     if (!proc)
0688         return -ENOMEM;
0689 
0690     root_uid = make_kuid(net->user_ns, 0);
0691     root_gid = make_kgid(net->user_ns, 0);
0692     if (uid_valid(root_uid) && gid_valid(root_gid))
0693         proc_set_user(proc, root_uid, root_gid);
0694 #endif /* CONFIG_NF_CONNTRACK_PROCFS */
0695     return 0;
0696 }
0697 
0698 static void exp_proc_remove(struct net *net)
0699 {
0700 #ifdef CONFIG_NF_CONNTRACK_PROCFS
0701     remove_proc_entry("nf_conntrack_expect", net->proc_net);
0702 #endif /* CONFIG_NF_CONNTRACK_PROCFS */
0703 }
0704 
0705 module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
0706 
0707 int nf_conntrack_expect_pernet_init(struct net *net)
0708 {
0709     return exp_proc_init(net);
0710 }
0711 
0712 void nf_conntrack_expect_pernet_fini(struct net *net)
0713 {
0714     exp_proc_remove(net);
0715 }
0716 
0717 int nf_conntrack_expect_init(void)
0718 {
0719     if (!nf_ct_expect_hsize) {
0720         nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
0721         if (!nf_ct_expect_hsize)
0722             nf_ct_expect_hsize = 1;
0723     }
0724     nf_ct_expect_max = nf_ct_expect_hsize * 4;
0725     nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
0726                 sizeof(struct nf_conntrack_expect),
0727                 0, 0, NULL);
0728     if (!nf_ct_expect_cachep)
0729         return -ENOMEM;
0730 
0731     nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 0);
0732     if (!nf_ct_expect_hash) {
0733         kmem_cache_destroy(nf_ct_expect_cachep);
0734         return -ENOMEM;
0735     }
0736 
0737     return 0;
0738 }
0739 
0740 void nf_conntrack_expect_fini(void)
0741 {
0742     rcu_barrier(); /* Wait for call_rcu() before destroy */
0743     kmem_cache_destroy(nf_ct_expect_cachep);
0744     kvfree(nf_ct_expect_hash);
0745 }