dm-crypt: use __bio_add_page to add single page to clone bio
[linux-block.git] / net / netfilter / nf_conntrack_expect.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
77ab9cff
MJ
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>
f229f6ce 7 * (c) 2005-2012 Patrick McHardy <kaber@trash.net>
77ab9cff
MJ
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>
dd6d2910 20#include <linux/siphash.h>
d9b93842 21#include <linux/moduleparam.h>
bc3b2d7f 22#include <linux/export.h>
457c4cbc 23#include <net/net_namespace.h>
a9a083c3 24#include <net/netns/hash.h>
77ab9cff
MJ
25
26#include <net/netfilter/nf_conntrack.h>
27#include <net/netfilter/nf_conntrack_core.h>
40d102cd 28#include <net/netfilter/nf_conntrack_ecache.h>
77ab9cff
MJ
29#include <net/netfilter/nf_conntrack_expect.h>
30#include <net/netfilter/nf_conntrack_helper.h>
40d102cd 31#include <net/netfilter/nf_conntrack_l4proto.h>
77ab9cff 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
0a93aaed
FW
38struct hlist_head *nf_ct_expect_hash __read_mostly;
39EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
40
f264a7df 41unsigned int nf_ct_expect_max __read_mostly;
a71c0855 42
e9c1b084 43static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
49ecc2e9 44static siphash_aligned_key_t nf_ct_expect_hashrnd;
77ab9cff
MJ
45
46/* nf_conntrack_expect helper functions */
ebbf41df 47void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
ec464e5d 48 u32 portid, int report)
77ab9cff
MJ
49{
50 struct nf_conn_help *master_help = nfct_help(exp->master);
9b03f38d 51 struct net *net = nf_ct_exp_net(exp);
f6f2e580 52 struct nf_conntrack_net *cnet;
77ab9cff 53
44d6e2f2
VR
54 WARN_ON(!master_help);
55 WARN_ON(timer_pending(&exp->timeout));
77ab9cff 56
7d0742da 57 hlist_del_rcu(&exp->hnode);
f6f2e580 58
0418b989 59 cnet = nf_ct_pernet(net);
f6f2e580 60 cnet->expect_count--;
a71c0855 61
7cddd967 62 hlist_del_rcu(&exp->lnode);
3d058d7b 63 master_help->expecting[exp->class]--;
bc01befd 64
ec464e5d 65 nf_ct_expect_event_report(IPEXP_DESTROY, exp, portid, report);
6823645d 66 nf_ct_expect_put(exp);
b560580a 67
0d55af87 68 NF_CT_STAT_INC(net, expect_delete);
77ab9cff 69}
ebbf41df 70EXPORT_SYMBOL_GPL(nf_ct_unlink_expect_report);
77ab9cff 71
e99e88a9 72static void nf_ct_expectation_timed_out(struct timer_list *t)
77ab9cff 73{
e99e88a9 74 struct nf_conntrack_expect *exp = from_timer(exp, t, timeout);
77ab9cff 75
ca7433df 76 spin_lock_bh(&nf_conntrack_expect_lock);
77ab9cff 77 nf_ct_unlink_expect(exp);
ca7433df 78 spin_unlock_bh(&nf_conntrack_expect_lock);
6823645d 79 nf_ct_expect_put(exp);
77ab9cff
MJ
80}
81
a9a083c3 82static unsigned int nf_ct_expect_dst_hash(const struct net *n, const struct nf_conntrack_tuple *tuple)
a71c0855 83{
dd6d2910
FW
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;
34498825 92
7001c6d1 93 get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd));
a71c0855 94
dd6d2910 95 memset(&combined, 0, sizeof(combined));
a9a083c3 96
dd6d2910
FW
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);
8fc54f68
DB
104
105 return reciprocal_scale(hash, nf_ct_expect_hsize);
a71c0855
PM
106}
107
03d7dc5c
FW
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
ec0e3f01
GF
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
77ab9cff 130struct nf_conntrack_expect *
308ac914
DB
131__nf_ct_expect_find(struct net *net,
132 const struct nf_conntrack_zone *zone,
5d0aa2cc 133 const struct nf_conntrack_tuple *tuple)
77ab9cff 134{
0418b989 135 struct nf_conntrack_net *cnet = nf_ct_pernet(net);
77ab9cff 136 struct nf_conntrack_expect *i;
a71c0855
PM
137 unsigned int h;
138
f6f2e580 139 if (!cnet->expect_count)
a71c0855 140 return NULL;
77ab9cff 141
a9a083c3 142 h = nf_ct_expect_dst_hash(net, tuple);
0a93aaed 143 hlist_for_each_entry_rcu(i, &nf_ct_expect_hash[h], hnode) {
03d7dc5c 144 if (nf_ct_exp_equal(tuple, i, zone, net))
77ab9cff
MJ
145 return i;
146 }
147 return NULL;
148}
6823645d 149EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
77ab9cff
MJ
150
151/* Just find a expectation corresponding to a tuple. */
152struct nf_conntrack_expect *
308ac914
DB
153nf_ct_expect_find_get(struct net *net,
154 const struct nf_conntrack_zone *zone,
5d0aa2cc 155 const struct nf_conntrack_tuple *tuple)
77ab9cff
MJ
156{
157 struct nf_conntrack_expect *i;
158
7d0742da 159 rcu_read_lock();
5d0aa2cc 160 i = __nf_ct_expect_find(net, zone, tuple);
b54ab92b 161 if (i && !refcount_inc_not_zero(&i->use))
7d0742da
PM
162 i = NULL;
163 rcu_read_unlock();
77ab9cff
MJ
164
165 return i;
166}
6823645d 167EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
77ab9cff
MJ
168
169/* If an expectation for this connection is found, it gets delete from
170 * global list then returned. */
171struct nf_conntrack_expect *
308ac914
DB
172nf_ct_find_expectation(struct net *net,
173 const struct nf_conntrack_zone *zone,
5d0aa2cc 174 const struct nf_conntrack_tuple *tuple)
77ab9cff 175{
0418b989 176 struct nf_conntrack_net *cnet = nf_ct_pernet(net);
359b9ab6 177 struct nf_conntrack_expect *i, *exp = NULL;
359b9ab6
PM
178 unsigned int h;
179
f6f2e580 180 if (!cnet->expect_count)
359b9ab6 181 return NULL;
ece00641 182
a9a083c3 183 h = nf_ct_expect_dst_hash(net, tuple);
0a93aaed 184 hlist_for_each_entry(i, &nf_ct_expect_hash[h], hnode) {
359b9ab6 185 if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
03d7dc5c 186 nf_ct_exp_equal(tuple, i, zone, net)) {
359b9ab6
PM
187 exp = i;
188 break;
189 }
190 }
ece00641
YK
191 if (!exp)
192 return NULL;
77ab9cff 193
77ab9cff
MJ
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). */
ece00641
YK
199 if (!nf_ct_is_confirmed(exp->master))
200 return NULL;
201
e1b207da
JDB
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 *
71977437 206 * The refcount_inc_not_zero() check tells: If that fails, we
e1b207da
JDB
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) ||
71977437 211 !refcount_inc_not_zero(&exp->master->ct_general.use)))
e1b207da
JDB
212 return NULL;
213
ece00641 214 if (exp->flags & NF_CT_EXPECT_PERMANENT) {
b54ab92b 215 refcount_inc(&exp->use);
ece00641
YK
216 return exp;
217 } else if (del_timer(&exp->timeout)) {
218 nf_ct_unlink_expect(exp);
219 return exp;
77ab9cff 220 }
e1b207da
JDB
221 /* Undo exp->master refcnt increase, if del_timer() failed */
222 nf_ct_put(exp->master);
ece00641 223
77ab9cff
MJ
224 return NULL;
225}
226
227/* delete all expectations for this conntrack */
228void nf_ct_remove_expectations(struct nf_conn *ct)
229{
77ab9cff 230 struct nf_conn_help *help = nfct_help(ct);
b560580a 231 struct nf_conntrack_expect *exp;
b67bfe0d 232 struct hlist_node *next;
77ab9cff
MJ
233
234 /* Optimization: most connection never expect any others. */
6002f266 235 if (!help)
77ab9cff
MJ
236 return;
237
ca7433df 238 spin_lock_bh(&nf_conntrack_expect_lock);
b67bfe0d 239 hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) {
ec0e3f01 240 nf_ct_remove_expect(exp);
77ab9cff 241 }
ca7433df 242 spin_unlock_bh(&nf_conntrack_expect_lock);
77ab9cff 243}
13b18339 244EXPORT_SYMBOL_GPL(nf_ct_remove_expectations);
77ab9cff
MJ
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 */
d4156e8c 252 struct nf_conntrack_tuple_mask intersect_mask;
77ab9cff
MJ
253 int count;
254
77ab9cff 255 intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
77ab9cff
MJ
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
4b31814d 262 return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) &&
03d7dc5c 263 net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
deedb590 264 nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
77ab9cff
MJ
265}
266
267static inline int expect_matches(const struct nf_conntrack_expect *a,
268 const struct nf_conntrack_expect *b)
269{
3c00fb0b 270 return nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
308ac914 271 nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
03d7dc5c 272 net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
deedb590 273 nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
77ab9cff
MJ
274}
275
3c00fb0b 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
77ab9cff 286/* Generally a bad idea to call this: could have matched already. */
6823645d 287void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
77ab9cff 288{
ca7433df 289 spin_lock_bh(&nf_conntrack_expect_lock);
ec0e3f01 290 nf_ct_remove_expect(exp);
ca7433df 291 spin_unlock_bh(&nf_conntrack_expect_lock);
77ab9cff 292}
6823645d 293EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
77ab9cff
MJ
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 */
6823645d 298struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
77ab9cff
MJ
299{
300 struct nf_conntrack_expect *new;
301
6823645d 302 new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
77ab9cff
MJ
303 if (!new)
304 return NULL;
305
306 new->master = me;
b54ab92b 307 refcount_set(&new->use, 1);
77ab9cff
MJ
308 return new;
309}
6823645d 310EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
77ab9cff 311
6002f266 312void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
76108cea 313 u_int8_t family,
1d9d7522
PM
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)
d6a9b650
PM
317{
318 int len;
319
320 if (family == AF_INET)
321 len = 4;
322 else
323 len = 16;
324
325 exp->flags = 0;
6002f266 326 exp->class = class;
d6a9b650
PM
327 exp->expectfn = NULL;
328 exp->helper = NULL;
329 exp->tuple.src.l3num = family;
330 exp->tuple.dst.protonum = proto;
d6a9b650
PM
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
d6a9b650 347 if (src) {
a34c4589
AV
348 exp->tuple.src.u.all = *src;
349 exp->mask.src.u.all = htons(0xFFFF);
d6a9b650
PM
350 } else {
351 exp->tuple.src.u.all = 0;
352 exp->mask.src.u.all = 0;
353 }
354
d4156e8c
PM
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
a34c4589 361 exp->tuple.dst.u.all = *dst;
f09eca8d 362
4806e975 363#if IS_ENABLED(CONFIG_NF_NAT)
f09eca8d
PNA
364 memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
365 memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
366#endif
d6a9b650 367}
6823645d 368EXPORT_SYMBOL_GPL(nf_ct_expect_init);
d6a9b650 369
7d0742da
PM
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
6823645d 378void nf_ct_expect_put(struct nf_conntrack_expect *exp)
77ab9cff 379{
b54ab92b 380 if (refcount_dec_and_test(&exp->use))
7d0742da 381 call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
77ab9cff 382}
6823645d 383EXPORT_SYMBOL_GPL(nf_ct_expect_put);
77ab9cff 384
4dee62b1 385static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
77ab9cff 386{
f6f2e580 387 struct nf_conntrack_net *cnet;
77ab9cff 388 struct nf_conn_help *master_help = nfct_help(exp->master);
3d058d7b 389 struct nf_conntrack_helper *helper;
9b03f38d 390 struct net *net = nf_ct_exp_net(exp);
a9a083c3 391 unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
77ab9cff 392
3bfd45f9 393 /* two references : one for hash insert, one for the timer */
b54ab92b 394 refcount_add(2, &exp->use);
b560580a 395
e99e88a9 396 timer_setup(&exp->timeout, nf_ct_expectation_timed_out, 0);
3d058d7b 397 helper = rcu_dereference_protected(master_help->helper,
ca7433df 398 lockdep_is_held(&nf_conntrack_expect_lock));
3d058d7b
PNA
399 if (helper) {
400 exp->timeout.expires = jiffies +
401 helper->expect_policy[exp->class].timeout * HZ;
bc01befd 402 }
77ab9cff
MJ
403 add_timer(&exp->timeout);
404
56a97e70
FW
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]);
0418b989 409 cnet = nf_ct_pernet(net);
f6f2e580 410 cnet->expect_count++;
56a97e70 411
0d55af87 412 NF_CT_STAT_INC(net, expect_create);
77ab9cff
MJ
413}
414
415/* Race with expectations being used means we could have none to find; OK. */
6002f266
PM
416static void evict_oldest_expect(struct nf_conn *master,
417 struct nf_conntrack_expect *new)
77ab9cff 418{
b560580a 419 struct nf_conn_help *master_help = nfct_help(master);
6002f266 420 struct nf_conntrack_expect *exp, *last = NULL;
77ab9cff 421
b67bfe0d 422 hlist_for_each_entry(exp, &master_help->expectations, lnode) {
6002f266
PM
423 if (exp->class == new->class)
424 last = exp;
425 }
b560580a 426
ec0e3f01
GF
427 if (last)
428 nf_ct_remove_expect(last);
77ab9cff
MJ
429}
430
3c00fb0b 431static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
432 unsigned int flags)
77ab9cff 433{
6002f266 434 const struct nf_conntrack_expect_policy *p;
77ab9cff 435 struct nf_conntrack_expect *i;
f6f2e580 436 struct nf_conntrack_net *cnet;
77ab9cff
MJ
437 struct nf_conn *master = expect->master;
438 struct nf_conn_help *master_help = nfct_help(master);
3d058d7b 439 struct nf_conntrack_helper *helper;
9b03f38d 440 struct net *net = nf_ct_exp_net(expect);
b67bfe0d 441 struct hlist_node *next;
a71c0855 442 unsigned int h;
4b86c459 443 int ret = 0;
77ab9cff 444
3d058d7b 445 if (!master_help) {
3c158f7f
PM
446 ret = -ESHUTDOWN;
447 goto out;
448 }
a9a083c3 449 h = nf_ct_expect_dst_hash(net, &expect->tuple);
0a93aaed 450 hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
3c00fb0b 451 if (master_matches(i, expect, flags) &&
452 expect_matches(i, expect)) {
453 if (i->class != expect->class ||
454 i->master != expect->master)
876c2731
FW
455 return -EALREADY;
456
36ac344e 457 if (nf_ct_remove_expect(i))
2614f864 458 break;
77ab9cff
MJ
459 } else if (expect_clash(i, expect)) {
460 ret = -EBUSY;
461 goto out;
462 }
463 }
464 /* Will be over limit? */
3d058d7b 465 helper = rcu_dereference_protected(master_help->helper,
ca7433df 466 lockdep_is_held(&nf_conntrack_expect_lock));
3d058d7b
PNA
467 if (helper) {
468 p = &helper->expect_policy[expect->class];
bc01befd
PNA
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 }
6002f266
PM
477 }
478 }
77ab9cff 479
0418b989 480 cnet = nf_ct_pernet(net);
f6f2e580 481 if (cnet->expect_count >= nf_ct_expect_max) {
e87cc472 482 net_warn_ratelimited("nf_conntrack: expectation table full\n");
f264a7df 483 ret = -EMFILE;
f264a7df 484 }
19abb7b0
PNA
485out:
486 return ret;
487}
488
b476b72a 489int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
3c00fb0b 490 u32 portid, int report, unsigned int flags)
19abb7b0
PNA
491{
492 int ret;
493
ca7433df 494 spin_lock_bh(&nf_conntrack_expect_lock);
3c00fb0b 495 ret = __nf_ct_expect_check(expect, flags);
4b86c459 496 if (ret < 0)
19abb7b0 497 goto out;
f264a7df 498
4dee62b1
GF
499 nf_ct_expect_insert(expect);
500
ca7433df 501 spin_unlock_bh(&nf_conntrack_expect_lock);
ec464e5d 502 nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report);
7fb668ac 503 return 0;
19abb7b0 504out:
ca7433df 505 spin_unlock_bh(&nf_conntrack_expect_lock);
19abb7b0
PNA
506 return ret;
507}
508EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
509
ac7b8483
FW
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
54b07dca 564#ifdef CONFIG_NF_CONNTRACK_PROCFS
5d08ad44 565struct ct_expect_iter_state {
dc5129f8 566 struct seq_net_private p;
5d08ad44
PM
567 unsigned int bucket;
568};
569
570static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
77ab9cff 571{
5d08ad44 572 struct ct_expect_iter_state *st = seq->private;
7d0742da 573 struct hlist_node *n;
77ab9cff 574
5d08ad44 575 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
0a93aaed 576 n = rcu_dereference(hlist_first_rcu(&nf_ct_expect_hash[st->bucket]));
7d0742da
PM
577 if (n)
578 return n;
5d08ad44
PM
579 }
580 return NULL;
581}
77ab9cff 582
5d08ad44
PM
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;
77ab9cff 587
0e60ebe0 588 head = rcu_dereference(hlist_next_rcu(head));
5d08ad44
PM
589 while (head == NULL) {
590 if (++st->bucket >= nf_ct_expect_hsize)
77ab9cff 591 return NULL;
0a93aaed 592 head = rcu_dereference(hlist_first_rcu(&nf_ct_expect_hash[st->bucket]));
77ab9cff 593 }
5d08ad44 594 return head;
77ab9cff
MJ
595}
596
5d08ad44 597static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
77ab9cff 598{
5d08ad44 599 struct hlist_node *head = ct_expect_get_first(seq);
77ab9cff 600
5d08ad44
PM
601 if (head)
602 while (pos && (head = ct_expect_get_next(seq, head)))
603 pos--;
604 return pos ? NULL : head;
605}
77ab9cff 606
5d08ad44 607static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
7d0742da 608 __acquires(RCU)
5d08ad44 609{
7d0742da 610 rcu_read_lock();
5d08ad44
PM
611 return ct_expect_get_idx(seq, *pos);
612}
77ab9cff 613
5d08ad44
PM
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);
77ab9cff
MJ
618}
619
5d08ad44 620static void exp_seq_stop(struct seq_file *seq, void *v)
7d0742da 621 __releases(RCU)
77ab9cff 622{
7d0742da 623 rcu_read_unlock();
77ab9cff
MJ
624}
625
626static int exp_seq_show(struct seq_file *s, void *v)
627{
5d08ad44 628 struct nf_conntrack_expect *expect;
b87921bd 629 struct nf_conntrack_helper *helper;
5d08ad44 630 struct hlist_node *n = v;
359b9ab6 631 char *delim = "";
5d08ad44
PM
632
633 expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
77ab9cff
MJ
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
cdec2685 639 seq_puts(s, "- ");
77ab9cff
MJ
640 seq_printf(s, "l3proto = %u proto=%u ",
641 expect->tuple.src.l3num,
642 expect->tuple.dst.protonum);
643 print_tuple(s, &expect->tuple,
4a60dc74 644 nf_ct_l4proto_find(expect->tuple.dst.protonum));
4bb119ea 645
359b9ab6 646 if (expect->flags & NF_CT_EXPECT_PERMANENT) {
cdec2685 647 seq_puts(s, "PERMANENT");
359b9ab6
PM
648 delim = ",";
649 }
bc01befd 650 if (expect->flags & NF_CT_EXPECT_INACTIVE) {
359b9ab6 651 seq_printf(s, "%sINACTIVE", delim);
bc01befd
PNA
652 delim = ",";
653 }
654 if (expect->flags & NF_CT_EXPECT_USERSPACE)
655 seq_printf(s, "%sUSERSPACE", delim);
4bb119ea 656
b87921bd
PM
657 helper = rcu_dereference(nfct_help(expect->master)->helper);
658 if (helper) {
659 seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name);
b173a28f 660 if (helper->expect_policy[expect->class].name[0])
b87921bd
PM
661 seq_printf(s, "/%s",
662 helper->expect_policy[expect->class].name);
663 }
664
1ca9e417
JP
665 seq_putc(s, '\n');
666
667 return 0;
77ab9cff
MJ
668}
669
56b3d975 670static const struct seq_operations exp_seq_ops = {
77ab9cff
MJ
671 .start = exp_seq_start,
672 .next = exp_seq_next,
673 .stop = exp_seq_stop,
674 .show = exp_seq_show
675};
54b07dca 676#endif /* CONFIG_NF_CONNTRACK_PROCFS */
e9c1b084 677
dc5129f8 678static int exp_proc_init(struct net *net)
e9c1b084 679{
54b07dca 680#ifdef CONFIG_NF_CONNTRACK_PROCFS
e9c1b084 681 struct proc_dir_entry *proc;
f13f2aee
PW
682 kuid_t root_uid;
683 kgid_t root_gid;
e9c1b084 684
c3506372
CH
685 proc = proc_create_net("nf_conntrack_expect", 0440, net->proc_net,
686 &exp_seq_ops, sizeof(struct ct_expect_iter_state));
e9c1b084
PM
687 if (!proc)
688 return -ENOMEM;
f13f2aee
PW
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);
54b07dca 694#endif /* CONFIG_NF_CONNTRACK_PROCFS */
e9c1b084
PM
695 return 0;
696}
697
dc5129f8 698static void exp_proc_remove(struct net *net)
e9c1b084 699{
54b07dca 700#ifdef CONFIG_NF_CONNTRACK_PROCFS
ece31ffd 701 remove_proc_entry("nf_conntrack_expect", net->proc_net);
54b07dca 702#endif /* CONFIG_NF_CONNTRACK_PROCFS */
e9c1b084
PM
703}
704
13ccdfc2 705module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
a71c0855 706
83b4dbe1 707int nf_conntrack_expect_pernet_init(struct net *net)
e9c1b084 708{
0a93aaed 709 return exp_proc_init(net);
e9c1b084
PM
710}
711
83b4dbe1 712void nf_conntrack_expect_pernet_fini(struct net *net)
e9c1b084 713{
dc5129f8 714 exp_proc_remove(net);
e9c1b084 715}
83b4dbe1
G
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;
0a93aaed
FW
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
83b4dbe1
G
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);
285189c7 744 kvfree(nf_ct_expect_hash);
83b4dbe1 745}