Blame view

net/netfilter/nf_conntrack_extend.c 2.79 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
2
3
4
5
  /* Structure dynamic extension infrastructure
   * Copyright (C) 2004 Rusty Russell IBM Corporation
   * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
   * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org>
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
6
7
   */
  #include <linux/kernel.h>
765cca91b   Stephen Rothwell   netfilter: conntr...
8
  #include <linux/kmemleak.h>
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
9
10
11
12
13
14
  #include <linux/module.h>
  #include <linux/mutex.h>
  #include <linux/rcupdate.h>
  #include <linux/slab.h>
  #include <linux/skbuff.h>
  #include <net/netfilter/nf_conntrack_extend.h>
0906a372f   Arnd Bergmann   net/netfilter: __...
15
  static struct nf_ct_ext_type __rcu *nf_ct_ext_types[NF_CT_EXT_NUM];
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
16
  static DEFINE_MUTEX(nf_ct_ext_type_mutex);
54044b1f0   Florian Westphal   netfilter: conntr...
17
  #define NF_CT_EXT_PREALLOC	128u /* conntrack events are on by default */
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
18

8eeef2350   Liping Zhang   netfilter: nf_ct_...
19
  void nf_ct_ext_destroy(struct nf_conn *ct)
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
20
21
22
23
24
  {
  	unsigned int i;
  	struct nf_ct_ext_type *t;
  
  	for (i = 0; i < NF_CT_EXT_NUM; i++) {
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
25
26
27
28
29
30
31
32
33
34
35
  		rcu_read_lock();
  		t = rcu_dereference(nf_ct_ext_types[i]);
  
  		/* Here the nf_ct_ext_type might have been unregisterd.
  		 * I.e., it has responsible to cleanup private
  		 * area in all conntracks when it is unregisterd.
  		 */
  		if (t && t->destroy)
  			t->destroy(ct);
  		rcu_read_unlock();
  	}
2ad9d7747   Florian Westphal   netfilter: conntr...
36
37
  
  	kfree(ct->ext);
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
38
  }
8eeef2350   Liping Zhang   netfilter: nf_ct_...
39
  EXPORT_SYMBOL(nf_ct_ext_destroy);
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
40

faec865db   Florian Westphal   netfilter: remove...
41
  void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
42
  {
22d4536d2   Florian Westphal   netfilter: conntr...
43
  	unsigned int newlen, newoff, oldlen, alloc;
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
44
  	struct nf_ct_ext_type *t;
2ad9d7747   Florian Westphal   netfilter: conntr...
45
  	struct nf_ct_ext *new;
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
46

55871d047   Patrick McHardy   [NETFILTER]: nf_c...
47
  	/* Conntrack must not be confirmed to avoid races on reallocation. */
44d6e2f27   Varsha Rao   net: Replace NF_C...
48
  	WARN_ON(nf_ct_is_confirmed(ct));
55871d047   Patrick McHardy   [NETFILTER]: nf_c...
49

ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
50

2ad9d7747   Florian Westphal   netfilter: conntr...
51
52
  	if (ct->ext) {
  		const struct nf_ct_ext *old = ct->ext;
22d4536d2   Florian Westphal   netfilter: conntr...
53
54
55
56
57
58
  		if (__nf_ct_ext_exist(old, id))
  			return NULL;
  		oldlen = old->len;
  	} else {
  		oldlen = sizeof(*new);
  	}
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
59
60
61
  
  	rcu_read_lock();
  	t = rcu_dereference(nf_ct_ext_types[id]);
9c3f37949   Liping Zhang   netfilter: nf_ct_...
62
63
64
65
  	if (!t) {
  		rcu_read_unlock();
  		return NULL;
  	}
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
66

22d4536d2   Florian Westphal   netfilter: conntr...
67
  	newoff = ALIGN(oldlen, t->align);
faec865db   Florian Westphal   netfilter: remove...
68
  	newlen = newoff + t->len;
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
69
  	rcu_read_unlock();
22d4536d2   Florian Westphal   netfilter: conntr...
70
  	alloc = max(newlen, NF_CT_EXT_PREALLOC);
2ad9d7747   Florian Westphal   netfilter: conntr...
71
  	new = krealloc(ct->ext, alloc, gfp);
31d8519c9   Pekka Enberg   netfilter: nf_con...
72
73
  	if (!new)
  		return NULL;
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
74

2ad9d7747   Florian Westphal   netfilter: conntr...
75
  	if (!ct->ext)
22d4536d2   Florian Westphal   netfilter: conntr...
76
  		memset(new->offset, 0, sizeof(new->offset));
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
77

6c64825bf   Patrick McHardy   netfilter: nf_con...
78
79
80
  	new->offset[id] = newoff;
  	new->len = newlen;
  	memset((void *)new + newoff, 0, newlen - newoff);
2ad9d7747   Florian Westphal   netfilter: conntr...
81
82
  
  	ct->ext = new;
6c64825bf   Patrick McHardy   netfilter: nf_con...
83
  	return (void *)new + newoff;
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
84
  }
faec865db   Florian Westphal   netfilter: remove...
85
  EXPORT_SYMBOL(nf_ct_ext_add);
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
86

ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
87
  /* This MUST be called in process context. */
23f671a1b   Florian Westphal   netfilter: conntr...
88
  int nf_ct_extend_register(const struct nf_ct_ext_type *type)
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
89
90
91
92
93
94
95
96
  {
  	int ret = 0;
  
  	mutex_lock(&nf_ct_ext_type_mutex);
  	if (nf_ct_ext_types[type->id]) {
  		ret = -EBUSY;
  		goto out;
  	}
cf778b00e   Eric Dumazet   net: reintroduce ...
97
  	rcu_assign_pointer(nf_ct_ext_types[type->id], type);
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
98
99
100
101
102
103
104
  out:
  	mutex_unlock(&nf_ct_ext_type_mutex);
  	return ret;
  }
  EXPORT_SYMBOL_GPL(nf_ct_extend_register);
  
  /* This MUST be called in process context. */
23f671a1b   Florian Westphal   netfilter: conntr...
105
  void nf_ct_extend_unregister(const struct nf_ct_ext_type *type)
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
106
107
  {
  	mutex_lock(&nf_ct_ext_type_mutex);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
108
  	RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
109
  	mutex_unlock(&nf_ct_ext_type_mutex);
9c3f37949   Liping Zhang   netfilter: nf_ct_...
110
  	synchronize_rcu();
ecfab2c9f   Yasuyuki Kozakai   [NETFILTER]: nf_c...
111
112
  }
  EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);