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