Blame view

net/netfilter/core.c 11.2 KB
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1
  /* netfilter.c: look after the filters for various protocols.
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
2
3
4
5
6
7
   * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
   *
   * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
   * way.
   *
   * Rusty Russell (C)2000 -- This code is GPL.
f229f6ce4   Patrick McHardy   netfilter: add my...
8
   * Patrick McHardy (c) 2006-2012
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
9
   */
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
10
11
12
13
14
15
16
17
18
19
  #include <linux/kernel.h>
  #include <linux/netfilter.h>
  #include <net/protocol.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
  #include <linux/wait.h>
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/if.h>
  #include <linux/netdevice.h>
567686443   Florian Westphal   netfilter: fix va...
20
  #include <linux/netfilter_ipv6.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
21
22
  #include <linux/inetdevice.h>
  #include <linux/proc_fs.h>
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
23
  #include <linux/mutex.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
e3b37f11e   Aaron Conole   netfilter: replac...
25
  #include <linux/rcupdate.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
26
  #include <net/net_namespace.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
27
28
29
  #include <net/sock.h>
  
  #include "nf_internals.h"
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
30
  static DEFINE_MUTEX(afinfo_mutex);
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
31

0906a372f   Arnd Bergmann   net/netfilter: __...
32
  const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
33
  EXPORT_SYMBOL(nf_afinfo);
2a7851bff   Florian Westphal   netfilter: add nf...
34
35
  const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
  EXPORT_SYMBOL_GPL(nf_ipv6_ops);
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
36

e7c8899f3   Florian Westphal   netfilter: move t...
37
38
  DEFINE_PER_CPU(bool, nf_skb_duplicated);
  EXPORT_SYMBOL_GPL(nf_skb_duplicated);
1e796fda0   Patrick McHardy   [NETFILTER]: cons...
39
  int nf_register_afinfo(const struct nf_afinfo *afinfo)
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
40
  {
7926dbfa4   Pablo Neira Ayuso   netfilter: don't ...
41
  	mutex_lock(&afinfo_mutex);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
42
  	RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
43
  	mutex_unlock(&afinfo_mutex);
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
44
45
46
  	return 0;
  }
  EXPORT_SYMBOL_GPL(nf_register_afinfo);
1e796fda0   Patrick McHardy   [NETFILTER]: cons...
47
  void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
48
  {
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
49
  	mutex_lock(&afinfo_mutex);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
50
  	RCU_INIT_POINTER(nf_afinfo[afinfo->family], NULL);
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
51
  	mutex_unlock(&afinfo_mutex);
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
52
53
54
  	synchronize_rcu();
  }
  EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
d1c85c2eb   Zhouyi Zhou   netfilter: HAVE_J...
55
  #ifdef HAVE_JUMP_LABEL
c5905afb0   Ingo Molnar   static keys: Intr...
56
  struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
a2d7ec58a   Eric Dumazet   netfilter: use ju...
57
58
  EXPORT_SYMBOL(nf_hooks_needed);
  #endif
fd706d695   Patrick McHardy   [NETFILTER]: Swit...
59
  static DEFINE_MUTEX(nf_hook_mutex);
e3b37f11e   Aaron Conole   netfilter: replac...
60
61
  #define nf_entry_dereference(e) \
  	rcu_dereference_protected(e, lockdep_is_held(&nf_hook_mutex))
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
62

bd3769bfe   Linus Torvalds   netfilter: Fix sl...
63
  static struct nf_hook_entry __rcu **nf_hook_entry_head(struct net *net, const struct nf_hook_ops *reg)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
64
  {
0edcf282b   Eric W. Biederman   netfilter: Factor...
65
  	if (reg->pf != NFPROTO_NETDEV)
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
66
  		return net->nf.hooks[reg->pf]+reg->hooknum;
e687ad60a   Pablo Neira   netfilter: add ne...
67
  #ifdef CONFIG_NETFILTER_INGRESS
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
68
  	if (reg->hooknum == NF_NETDEV_INGRESS) {
085db2c04   Eric W. Biederman   netfilter: Per ne...
69
  		if (reg->dev && dev_net(reg->dev) == net)
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
70
  			return &reg->dev->nf_hooks_ingress;
e687ad60a   Pablo Neira   netfilter: add ne...
71
  	}
7816ec564   Aaron Conole   netfilter: accomm...
72
  #endif
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
73
  	return NULL;
e3b37f11e   Aaron Conole   netfilter: replac...
74
  }
7181ebafd   Pablo Neira Ayuso   netfilter: fix po...
75

085db2c04   Eric W. Biederman   netfilter: Per ne...
76
  int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
0edcf282b   Eric W. Biederman   netfilter: Factor...
77
  {
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
78
79
  	struct nf_hook_entry __rcu **pp;
  	struct nf_hook_entry *entry, *p;
085db2c04   Eric W. Biederman   netfilter: Per ne...
80

7816ec564   Aaron Conole   netfilter: accomm...
81
82
83
84
85
86
87
88
89
  	if (reg->pf == NFPROTO_NETDEV) {
  #ifndef CONFIG_NETFILTER_INGRESS
  		if (reg->hooknum == NF_NETDEV_INGRESS)
  			return -EOPNOTSUPP;
  #endif
  		if (reg->hooknum != NF_NETDEV_INGRESS ||
  		    !reg->dev || dev_net(reg->dev) != net)
  			return -EINVAL;
  	}
d4bb5caa9   Aaron Conole   netfilter: Only a...
90

bd3769bfe   Linus Torvalds   netfilter: Fix sl...
91
92
93
  	pp = nf_hook_entry_head(net, reg);
  	if (!pp)
  		return -EINVAL;
7181ebafd   Pablo Neira Ayuso   netfilter: fix po...
94
95
  	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
  	if (!entry)
085db2c04   Eric W. Biederman   netfilter: Per ne...
96
  		return -ENOMEM;
0edcf282b   Eric W. Biederman   netfilter: Factor...
97

7181ebafd   Pablo Neira Ayuso   netfilter: fix po...
98
99
  	entry->orig_ops	= reg;
  	entry->ops	= *reg;
e3b37f11e   Aaron Conole   netfilter: replac...
100
101
102
  	entry->next	= NULL;
  
  	mutex_lock(&nf_hook_mutex);
085db2c04   Eric W. Biederman   netfilter: Per ne...
103

bd3769bfe   Linus Torvalds   netfilter: Fix sl...
104
105
106
107
108
  	/* Find the spot in the list */
  	while ((p = nf_entry_dereference(*pp)) != NULL) {
  		if (reg->priority < p->orig_ops->priority)
  			break;
  		pp = &p->next;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
109
  	}
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
110
111
  	rcu_assign_pointer(entry->next, p);
  	rcu_assign_pointer(*pp, entry);
e3b37f11e   Aaron Conole   netfilter: replac...
112

fd706d695   Patrick McHardy   [NETFILTER]: Swit...
113
  	mutex_unlock(&nf_hook_mutex);
4c0911566   Eric W. Biederman   netfilter: Simply...
114
115
116
117
  #ifdef CONFIG_NETFILTER_INGRESS
  	if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
  		net_inc_ingress_queue();
  #endif
d1c85c2eb   Zhouyi Zhou   netfilter: HAVE_J...
118
  #ifdef HAVE_JUMP_LABEL
c5905afb0   Ingo Molnar   static keys: Intr...
119
  	static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
a2d7ec58a   Eric Dumazet   netfilter: use ju...
120
  #endif
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
121
122
  	return 0;
  }
085db2c04   Eric W. Biederman   netfilter: Per ne...
123
  EXPORT_SYMBOL(nf_register_net_hook);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
124

085db2c04   Eric W. Biederman   netfilter: Per ne...
125
  void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
126
  {
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
127
128
129
130
131
132
  	struct nf_hook_entry __rcu **pp;
  	struct nf_hook_entry *p;
  
  	pp = nf_hook_entry_head(net, reg);
  	if (WARN_ON_ONCE(!pp))
  		return;
085db2c04   Eric W. Biederman   netfilter: Per ne...
133

fd706d695   Patrick McHardy   [NETFILTER]: Swit...
134
  	mutex_lock(&nf_hook_mutex);
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
135
136
137
138
  	while ((p = nf_entry_dereference(*pp)) != NULL) {
  		if (p->orig_ops == reg) {
  			rcu_assign_pointer(*pp, p->next);
  			break;
085db2c04   Eric W. Biederman   netfilter: Per ne...
139
  		}
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
140
  		pp = &p->next;
085db2c04   Eric W. Biederman   netfilter: Per ne...
141
  	}
fd706d695   Patrick McHardy   [NETFILTER]: Swit...
142
  	mutex_unlock(&nf_hook_mutex);
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
143
  	if (!p) {
085db2c04   Eric W. Biederman   netfilter: Per ne...
144
145
146
147
  		WARN(1, "nf_unregister_net_hook: hook not found!
  ");
  		return;
  	}
e687ad60a   Pablo Neira   netfilter: add ne...
148
  #ifdef CONFIG_NETFILTER_INGRESS
4c0911566   Eric W. Biederman   netfilter: Simply...
149
150
  	if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
  		net_dec_ingress_queue();
e687ad60a   Pablo Neira   netfilter: add ne...
151
  #endif
d1c85c2eb   Zhouyi Zhou   netfilter: HAVE_J...
152
  #ifdef HAVE_JUMP_LABEL
c5905afb0   Ingo Molnar   static keys: Intr...
153
  	static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]);
a2d7ec58a   Eric Dumazet   netfilter: use ju...
154
  #endif
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
155
  	synchronize_net();
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
156
  	nf_queue_nf_hook_drop(net, p);
514ed62ed   Florian Westphal   netfilter: sync w...
157
158
  	/* other cpu might still process nfqueue verdict that used reg */
  	synchronize_net();
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
159
  	kfree(p);
085db2c04   Eric W. Biederman   netfilter: Per ne...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  }
  EXPORT_SYMBOL(nf_unregister_net_hook);
  
  int nf_register_net_hooks(struct net *net, const struct nf_hook_ops *reg,
  			  unsigned int n)
  {
  	unsigned int i;
  	int err = 0;
  
  	for (i = 0; i < n; i++) {
  		err = nf_register_net_hook(net, &reg[i]);
  		if (err)
  			goto err;
  	}
  	return err;
  
  err:
  	if (i > 0)
  		nf_unregister_net_hooks(net, reg, i);
  	return err;
  }
  EXPORT_SYMBOL(nf_register_net_hooks);
  
  void nf_unregister_net_hooks(struct net *net, const struct nf_hook_ops *reg,
  			     unsigned int n)
  {
  	while (n-- > 0)
  		nf_unregister_net_hook(net, &reg[n]);
  }
  EXPORT_SYMBOL(nf_unregister_net_hooks);
  
  static LIST_HEAD(nf_hook_list);
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
192
  static int _nf_register_hook(struct nf_hook_ops *reg)
085db2c04   Eric W. Biederman   netfilter: Per ne...
193
194
195
  {
  	struct net *net, *last;
  	int ret;
085db2c04   Eric W. Biederman   netfilter: Per ne...
196
197
198
199
200
201
  	for_each_net(net) {
  		ret = nf_register_net_hook(net, reg);
  		if (ret && ret != -ENOENT)
  			goto rollback;
  	}
  	list_add_tail(&reg->list, &nf_hook_list);
085db2c04   Eric W. Biederman   netfilter: Per ne...
202
203
204
205
206
207
208
209
210
  
  	return 0;
  rollback:
  	last = net;
  	for_each_net(net) {
  		if (net == last)
  			break;
  		nf_unregister_net_hook(net, reg);
  	}
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
211
212
213
214
215
216
217
218
219
  	return ret;
  }
  
  int nf_register_hook(struct nf_hook_ops *reg)
  {
  	int ret;
  
  	rtnl_lock();
  	ret = _nf_register_hook(reg);
085db2c04   Eric W. Biederman   netfilter: Per ne...
220
  	rtnl_unlock();
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
221

085db2c04   Eric W. Biederman   netfilter: Per ne...
222
223
224
  	return ret;
  }
  EXPORT_SYMBOL(nf_register_hook);
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
225
  static void _nf_unregister_hook(struct nf_hook_ops *reg)
085db2c04   Eric W. Biederman   netfilter: Per ne...
226
227
  {
  	struct net *net;
085db2c04   Eric W. Biederman   netfilter: Per ne...
228
229
230
  	list_del(&reg->list);
  	for_each_net(net)
  		nf_unregister_net_hook(net, reg);
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
231
232
233
234
235
236
  }
  
  void nf_unregister_hook(struct nf_hook_ops *reg)
  {
  	rtnl_lock();
  	_nf_unregister_hook(reg);
085db2c04   Eric W. Biederman   netfilter: Per ne...
237
  	rtnl_unlock();
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
238
239
  }
  EXPORT_SYMBOL(nf_unregister_hook);
972d1cb14   Patrick McHardy   [NETFILTER]: Add ...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
  {
  	unsigned int i;
  	int err = 0;
  
  	for (i = 0; i < n; i++) {
  		err = nf_register_hook(&reg[i]);
  		if (err)
  			goto err;
  	}
  	return err;
  
  err:
  	if (i > 0)
  		nf_unregister_hooks(reg, i);
  	return err;
  }
  EXPORT_SYMBOL(nf_register_hooks);
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  /* Caller MUST take rtnl_lock() */
  int _nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
  {
  	unsigned int i;
  	int err = 0;
  
  	for (i = 0; i < n; i++) {
  		err = _nf_register_hook(&reg[i]);
  		if (err)
  			goto err;
  	}
  	return err;
  
  err:
  	if (i > 0)
  		_nf_unregister_hooks(reg, i);
  	return err;
  }
  EXPORT_SYMBOL(_nf_register_hooks);
972d1cb14   Patrick McHardy   [NETFILTER]: Add ...
277
278
  void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
  {
f68c53015   Changli Gao   netfilter: unregi...
279
280
  	while (n-- > 0)
  		nf_unregister_hook(&reg[n]);
972d1cb14   Patrick McHardy   [NETFILTER]: Add ...
281
282
  }
  EXPORT_SYMBOL(nf_unregister_hooks);
e8bffe0cf   Mahesh Bandewar   net: Add _nf_(un)...
283
284
285
286
287
288
289
  /* Caller MUST take rtnl_lock */
  void _nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n)
  {
  	while (n-- > 0)
  		_nf_unregister_hook(&reg[n]);
  }
  EXPORT_SYMBOL(_nf_unregister_hooks);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
290
  /* Returns 1 if okfn() needs to be executed by the caller,
e2361cb90   Aaron Conole   netfilter: Remove...
291
   * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
01886bd91   Pablo Neira Ayuso   netfilter: remove...
292
293
  int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
  		 struct nf_hook_entry *entry)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
294
  {
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
295
  	unsigned int verdict;
c63cbc460   Pablo Neira Ayuso   netfilter: use sw...
296
  	int ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
297

26dfab721   Pablo Neira Ayuso   netfilter: merge ...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  	do {
  		verdict = entry->ops.hook(entry->ops.priv, skb, state);
  		switch (verdict & NF_VERDICT_MASK) {
  		case NF_ACCEPT:
  			entry = rcu_dereference(entry->next);
  			break;
  		case NF_DROP:
  			kfree_skb(skb);
  			ret = NF_DROP_GETERR(verdict);
  			if (ret == 0)
  				ret = -EPERM;
  			return ret;
  		case NF_REPEAT:
  			continue;
  		case NF_QUEUE:
  			ret = nf_queue(skb, state, &entry, verdict);
  			if (ret == 1 && entry)
  				continue;
  			return ret;
  		default:
  			/* Implicit handling for NF_STOLEN, as well as any other
  			 * non conventional verdicts.
  			 */
  			return 0;
  		}
  	} while (entry);
  
  	return 1;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
326
327
  }
  EXPORT_SYMBOL(nf_hook_slow);
37d418792   Herbert Xu   [NETFILTER]: Do n...
328
  int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
329
  {
37d418792   Herbert Xu   [NETFILTER]: Do n...
330
  	if (writable_len > skb->len)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
331
332
333
  		return 0;
  
  	/* Not exclusive use of packet?  Must copy. */
37d418792   Herbert Xu   [NETFILTER]: Do n...
334
335
336
337
338
339
340
341
342
343
344
345
  	if (!skb_cloned(skb)) {
  		if (writable_len <= skb_headlen(skb))
  			return 1;
  	} else if (skb_clone_writable(skb, writable_len))
  		return 1;
  
  	if (writable_len <= skb_headlen(skb))
  		writable_len = 0;
  	else
  		writable_len -= skb_headlen(skb);
  
  	return !!__pskb_pull_tail(skb, writable_len);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
346
347
  }
  EXPORT_SYMBOL(skb_make_writable);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
348
349
350
  /* This needs to be compiled in any case to avoid dependencies between the
   * nfnetlink_queue code and nf_conntrack.
   */
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
351
352
  struct nfnl_ct_hook __rcu *nfnl_ct_hook __read_mostly;
  EXPORT_SYMBOL_GPL(nfnl_ct_hook);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
353

c0cd11566   Igor Maravić   net:netfilter: us...
354
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
355
356
357
  /* This does not belong here, but locally generated errors need it if connection
     tracking in use: without this, connection may not be in hash table, and hence
     manufactured ICMP or RST packets will not be associated with it. */
312a0c16c   Patrick McHardy   netfilter: nf_con...
358
359
  void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *)
  		__rcu __read_mostly;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
360
  EXPORT_SYMBOL(ip_ct_attach);
312a0c16c   Patrick McHardy   netfilter: nf_con...
361
  void nf_ct_attach(struct sk_buff *new, const struct sk_buff *skb)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
362
  {
312a0c16c   Patrick McHardy   netfilter: nf_con...
363
  	void (*attach)(struct sk_buff *, const struct sk_buff *);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
364

c3a47ab3e   Patrick McHardy   [NETFILTER]: Prop...
365
366
367
368
369
370
  	if (skb->nfct) {
  		rcu_read_lock();
  		attach = rcu_dereference(ip_ct_attach);
  		if (attach)
  			attach(new, skb);
  		rcu_read_unlock();
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
371
372
373
  	}
  }
  EXPORT_SYMBOL(nf_ct_attach);
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
374

0e60ebe04   Eric Dumazet   netfilter: add __...
375
  void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
376
377
378
379
380
381
382
383
384
385
386
387
388
  EXPORT_SYMBOL(nf_ct_destroy);
  
  void nf_conntrack_destroy(struct nf_conntrack *nfct)
  {
  	void (*destroy)(struct nf_conntrack *);
  
  	rcu_read_lock();
  	destroy = rcu_dereference(nf_ct_destroy);
  	BUG_ON(destroy == NULL);
  	destroy(nfct);
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL(nf_conntrack_destroy);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
389

62da98656   Daniel Borkmann   netfilter: nf_con...
390
391
392
393
394
395
  /* Built-in default zone used e.g. by modules. */
  const struct nf_conntrack_zone nf_ct_zone_dflt = {
  	.id	= NF_CT_DEFAULT_ZONE_ID,
  	.dir	= NF_CT_DEFAULT_ZONE_DIR,
  };
  EXPORT_SYMBOL_GPL(nf_ct_zone_dflt);
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
396
  #endif /* CONFIG_NF_CONNTRACK */
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
397

c7232c997   Patrick McHardy   netfilter: add pr...
398
399
400
401
  #ifdef CONFIG_NF_NAT_NEEDED
  void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
  EXPORT_SYMBOL(nf_nat_decode_session_hook);
  #endif
085db2c04   Eric W. Biederman   netfilter: Per ne...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  static int nf_register_hook_list(struct net *net)
  {
  	struct nf_hook_ops *elem;
  	int ret;
  
  	rtnl_lock();
  	list_for_each_entry(elem, &nf_hook_list, list) {
  		ret = nf_register_net_hook(net, elem);
  		if (ret && ret != -ENOENT)
  			goto out_undo;
  	}
  	rtnl_unlock();
  	return 0;
  
  out_undo:
  	list_for_each_entry_continue_reverse(elem, &nf_hook_list, list)
  		nf_unregister_net_hook(net, elem);
  	rtnl_unlock();
  	return ret;
  }
  
  static void nf_unregister_hook_list(struct net *net)
  {
  	struct nf_hook_ops *elem;
  
  	rtnl_lock();
  	list_for_each_entry(elem, &nf_hook_list, list)
  		nf_unregister_net_hook(net, elem);
  	rtnl_unlock();
  }
f3c1a44a2   Gao feng   netfilter: make /...
432
433
  static int __net_init netfilter_net_init(struct net *net)
  {
085db2c04   Eric W. Biederman   netfilter: Per ne...
434
435
436
437
  	int i, h, ret;
  
  	for (i = 0; i < ARRAY_SIZE(net->nf.hooks); i++) {
  		for (h = 0; h < NF_MAX_HOOKS; h++)
e3b37f11e   Aaron Conole   netfilter: replac...
438
  			RCU_INIT_POINTER(net->nf.hooks[i][h], NULL);
085db2c04   Eric W. Biederman   netfilter: Per ne...
439
  	}
f3c1a44a2   Gao feng   netfilter: make /...
440
441
442
  #ifdef CONFIG_PROC_FS
  	net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
  						net->proc_net);
12202fa75   Pablo Neira Ayuso   netfilter: remove...
443
444
445
  	if (!net->nf.proc_netfilter) {
  		if (!net_eq(net, &init_net))
  			pr_err("cannot create netfilter proc entry");
f3c1a44a2   Gao feng   netfilter: make /...
446
447
448
  		return -ENOMEM;
  	}
  #endif
085db2c04   Eric W. Biederman   netfilter: Per ne...
449
450
451
452
453
  	ret = nf_register_hook_list(net);
  	if (ret)
  		remove_proc_entry("netfilter", net->proc_net);
  
  	return ret;
f3c1a44a2   Gao feng   netfilter: make /...
454
455
456
457
  }
  
  static void __net_exit netfilter_net_exit(struct net *net)
  {
085db2c04   Eric W. Biederman   netfilter: Per ne...
458
  	nf_unregister_hook_list(net);
f3c1a44a2   Gao feng   netfilter: make /...
459
460
461
462
463
464
465
  	remove_proc_entry("netfilter", net->proc_net);
  }
  
  static struct pernet_operations netfilter_net_ops = {
  	.init = netfilter_net_init,
  	.exit = netfilter_net_exit,
  };
6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
466
  int __init netfilter_init(void)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
467
  {
085db2c04   Eric W. Biederman   netfilter: Per ne...
468
  	int ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
469

6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
470
471
472
473
474
475
476
  	ret = register_pernet_subsys(&netfilter_net_ops);
  	if (ret < 0)
  		goto err;
  
  	ret = netfilter_log_init();
  	if (ret < 0)
  		goto err_pernet;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
477

6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
478
479
480
481
482
  	return 0;
  err_pernet:
  	unregister_pernet_subsys(&netfilter_net_ops);
  err:
  	return ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
483
  }