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