Blame view

net/netfilter/core.c 15.6 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
   * 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.
   *
b3a61254d   Pablo Neira Ayuso   netfilter: remove...
7
   * This code is GPL.
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
8
   */
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
9
10
11
12
13
14
15
16
17
18
  #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...
19
  #include <linux/netfilter_ipv6.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
20
21
  #include <linux/inetdevice.h>
  #include <linux/proc_fs.h>
d486dd1fb   Patrick McHardy   [NETFILTER]: Swit...
22
  #include <linux/mutex.h>
960632ece   Aaron Conole   netfilter: conver...
23
  #include <linux/mm.h>
e3b37f11e   Aaron Conole   netfilter: replac...
24
  #include <linux/rcupdate.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
25
  #include <net/net_namespace.h>
971502d77   Florian Westphal   bridge: netfilter...
26
  #include <net/netfilter/nf_queue.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
27
28
29
  #include <net/sock.h>
  
  #include "nf_internals.h"
2a7851bff   Florian Westphal   netfilter: add nf...
30
31
  const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
  EXPORT_SYMBOL_GPL(nf_ipv6_ops);
bce8032ef   Patrick McHardy   [NETFILTER]: Intr...
32

e7c8899f3   Florian Westphal   netfilter: move t...
33
34
  DEFINE_PER_CPU(bool, nf_skb_duplicated);
  EXPORT_SYMBOL_GPL(nf_skb_duplicated);
e9666d10a   Masahiro Yamada   jump_label: move ...
35
  #ifdef CONFIG_JUMP_LABEL
c5905afb0   Ingo Molnar   static keys: Intr...
36
  struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
a2d7ec58a   Eric Dumazet   netfilter: use ju...
37
38
  EXPORT_SYMBOL(nf_hooks_needed);
  #endif
fd706d695   Patrick McHardy   [NETFILTER]: Swit...
39
  static DEFINE_MUTEX(nf_hook_mutex);
960632ece   Aaron Conole   netfilter: conver...
40
41
42
  
  /* max hooks per family/hooknum */
  #define MAX_HOOK_COUNT		1024
e3b37f11e   Aaron Conole   netfilter: replac...
43
44
  #define nf_entry_dereference(e) \
  	rcu_dereference_protected(e, lockdep_is_held(&nf_hook_mutex))
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
45

960632ece   Aaron Conole   netfilter: conver...
46
47
48
49
50
  static struct nf_hook_entries *allocate_hook_entries_size(u16 num)
  {
  	struct nf_hook_entries *e;
  	size_t alloc = sizeof(*e) +
  		       sizeof(struct nf_hook_entry) * num +
8c873e219   Florian Westphal   netfilter: core: ...
51
52
  		       sizeof(struct nf_hook_ops *) * num +
  		       sizeof(struct nf_hook_entries_rcu_head);
960632ece   Aaron Conole   netfilter: conver...
53
54
55
56
57
58
59
60
61
  
  	if (num == 0)
  		return NULL;
  
  	e = kvzalloc(alloc, GFP_KERNEL);
  	if (e)
  		e->num_hook_entries = num;
  	return e;
  }
8c873e219   Florian Westphal   netfilter: core: ...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  static void __nf_hook_entries_free(struct rcu_head *h)
  {
  	struct nf_hook_entries_rcu_head *head;
  
  	head = container_of(h, struct nf_hook_entries_rcu_head, head);
  	kvfree(head->allocation);
  }
  
  static void nf_hook_entries_free(struct nf_hook_entries *e)
  {
  	struct nf_hook_entries_rcu_head *head;
  	struct nf_hook_ops **ops;
  	unsigned int num;
  
  	if (!e)
  		return;
  
  	num = e->num_hook_entries;
  	ops = nf_hook_entries_get_hook_ops(e);
  	head = (void *)&ops[num];
  	head->allocation = e;
  	call_rcu(&head->head, __nf_hook_entries_free);
  }
960632ece   Aaron Conole   netfilter: conver...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  static unsigned int accept_all(void *priv,
  			       struct sk_buff *skb,
  			       const struct nf_hook_state *state)
  {
  	return NF_ACCEPT; /* ACCEPT makes nf_hook_slow call next hook */
  }
  
  static const struct nf_hook_ops dummy_ops = {
  	.hook = accept_all,
  	.priority = INT_MIN,
  };
  
  static struct nf_hook_entries *
  nf_hook_entries_grow(const struct nf_hook_entries *old,
  		     const struct nf_hook_ops *reg)
  {
  	unsigned int i, alloc_entries, nhooks, old_entries;
  	struct nf_hook_ops **orig_ops = NULL;
  	struct nf_hook_ops **new_ops;
  	struct nf_hook_entries *new;
  	bool inserted = false;
  
  	alloc_entries = 1;
  	old_entries = old ? old->num_hook_entries : 0;
  
  	if (old) {
  		orig_ops = nf_hook_entries_get_hook_ops(old);
  
  		for (i = 0; i < old_entries; i++) {
  			if (orig_ops[i] != &dummy_ops)
  				alloc_entries++;
  		}
  	}
  
  	if (alloc_entries > MAX_HOOK_COUNT)
  		return ERR_PTR(-E2BIG);
  
  	new = allocate_hook_entries_size(alloc_entries);
  	if (!new)
  		return ERR_PTR(-ENOMEM);
  
  	new_ops = nf_hook_entries_get_hook_ops(new);
  
  	i = 0;
  	nhooks = 0;
  	while (i < old_entries) {
  		if (orig_ops[i] == &dummy_ops) {
  			++i;
  			continue;
  		}
f92b40a8b   Florian Westphal   netfilter: core: ...
135

960632ece   Aaron Conole   netfilter: conver...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  		if (inserted || reg->priority > orig_ops[i]->priority) {
  			new_ops[nhooks] = (void *)orig_ops[i];
  			new->hooks[nhooks] = old->hooks[i];
  			i++;
  		} else {
  			new_ops[nhooks] = (void *)reg;
  			new->hooks[nhooks].hook = reg->hook;
  			new->hooks[nhooks].priv = reg->priv;
  			inserted = true;
  		}
  		nhooks++;
  	}
  
  	if (!inserted) {
  		new_ops[nhooks] = (void *)reg;
  		new->hooks[nhooks].hook = reg->hook;
  		new->hooks[nhooks].priv = reg->priv;
  	}
  
  	return new;
  }
2420b79f8   Florian Westphal   netfilter: debug:...
157
158
  static void hooks_validate(const struct nf_hook_entries *hooks)
  {
432d82200   Sinan Kaya   net: replace CONF...
159
  #ifdef CONFIG_DEBUG_MISC
2420b79f8   Florian Westphal   netfilter: debug:...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  	struct nf_hook_ops **orig_ops;
  	int prio = INT_MIN;
  	size_t i = 0;
  
  	orig_ops = nf_hook_entries_get_hook_ops(hooks);
  
  	for (i = 0; i < hooks->num_hook_entries; i++) {
  		if (orig_ops[i] == &dummy_ops)
  			continue;
  
  		WARN_ON(orig_ops[i]->priority < prio);
  
  		if (orig_ops[i]->priority > prio)
  			prio = orig_ops[i]->priority;
  	}
  #endif
  }
06cad3acf   Florian Westphal   netfilter: core: ...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  int nf_hook_entries_insert_raw(struct nf_hook_entries __rcu **pp,
  				const struct nf_hook_ops *reg)
  {
  	struct nf_hook_entries *new_hooks;
  	struct nf_hook_entries *p;
  
  	p = rcu_dereference_raw(*pp);
  	new_hooks = nf_hook_entries_grow(p, reg);
  	if (IS_ERR(new_hooks))
  		return PTR_ERR(new_hooks);
  
  	hooks_validate(new_hooks);
  
  	rcu_assign_pointer(*pp, new_hooks);
  
  	BUG_ON(p == new_hooks);
  	nf_hook_entries_free(p);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(nf_hook_entries_insert_raw);
960632ece   Aaron Conole   netfilter: conver...
197
198
199
  /*
   * __nf_hook_entries_try_shrink - try to shrink hook array
   *
06cad3acf   Florian Westphal   netfilter: core: ...
200
   * @old -- current hook blob at @pp
960632ece   Aaron Conole   netfilter: conver...
201
202
203
204
205
206
207
208
209
210
211
212
   * @pp -- location of hook blob
   *
   * Hook unregistration must always succeed, so to-be-removed hooks
   * are replaced by a dummy one that will just move to next hook.
   *
   * This counts the current dummy hooks, attempts to allocate new blob,
   * copies the live hooks, then replaces and discards old one.
   *
   * return values:
   *
   * Returns address to free, or NULL.
   */
06cad3acf   Florian Westphal   netfilter: core: ...
213
214
  static void *__nf_hook_entries_try_shrink(struct nf_hook_entries *old,
  					  struct nf_hook_entries __rcu **pp)
960632ece   Aaron Conole   netfilter: conver...
215
  {
960632ece   Aaron Conole   netfilter: conver...
216
  	unsigned int i, j, skip = 0, hook_entries;
06cad3acf   Florian Westphal   netfilter: core: ...
217
  	struct nf_hook_entries *new = NULL;
960632ece   Aaron Conole   netfilter: conver...
218
219
  	struct nf_hook_ops **orig_ops;
  	struct nf_hook_ops **new_ops;
960632ece   Aaron Conole   netfilter: conver...
220
221
222
223
224
225
226
227
228
229
230
231
232
  	if (WARN_ON_ONCE(!old))
  		return NULL;
  
  	orig_ops = nf_hook_entries_get_hook_ops(old);
  	for (i = 0; i < old->num_hook_entries; i++) {
  		if (orig_ops[i] == &dummy_ops)
  			skip++;
  	}
  
  	/* if skip == hook_entries all hooks have been removed */
  	hook_entries = old->num_hook_entries;
  	if (skip == hook_entries)
  		goto out_assign;
74585d4f8   Florian Westphal   netfilter: core: ...
233
  	if (skip == 0)
960632ece   Aaron Conole   netfilter: conver...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  		return NULL;
  
  	hook_entries -= skip;
  	new = allocate_hook_entries_size(hook_entries);
  	if (!new)
  		return NULL;
  
  	new_ops = nf_hook_entries_get_hook_ops(new);
  	for (i = 0, j = 0; i < old->num_hook_entries; i++) {
  		if (orig_ops[i] == &dummy_ops)
  			continue;
  		new->hooks[j] = old->hooks[i];
  		new_ops[j] = (void *)orig_ops[i];
  		j++;
  	}
2420b79f8   Florian Westphal   netfilter: debug:...
249
  	hooks_validate(new);
960632ece   Aaron Conole   netfilter: conver...
250
251
252
253
  out_assign:
  	rcu_assign_pointer(*pp, new);
  	return old;
  }
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
254
255
256
  static struct nf_hook_entries __rcu **
  nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,
  		   struct net_device *dev)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
257
  {
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
258
  	switch (pf) {
b0f38338a   Florian Westphal   netfilter: reduce...
259
260
  	case NFPROTO_NETDEV:
  		break;
2a95183a5   Florian Westphal   netfilter: don't ...
261
  #ifdef CONFIG_NETFILTER_FAMILY_ARP
b0f38338a   Florian Westphal   netfilter: reduce...
262
  	case NFPROTO_ARP:
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
263
  		if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= hooknum))
ef57170bb   Florian Westphal   netfilter: reduce...
264
  			return NULL;
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
265
  		return net->nf.hooks_arp + hooknum;
2a95183a5   Florian Westphal   netfilter: don't ...
266
267
  #endif
  #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
b0f38338a   Florian Westphal   netfilter: reduce...
268
  	case NFPROTO_BRIDGE:
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
269
  		if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= hooknum))
ef57170bb   Florian Westphal   netfilter: reduce...
270
  			return NULL;
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
271
  		return net->nf.hooks_bridge + hooknum;
2a95183a5   Florian Westphal   netfilter: don't ...
272
  #endif
b0f38338a   Florian Westphal   netfilter: reduce...
273
  	case NFPROTO_IPV4:
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
274
  		if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= hooknum))
ef57170bb   Florian Westphal   netfilter: reduce...
275
  			return NULL;
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
276
  		return net->nf.hooks_ipv4 + hooknum;
b0f38338a   Florian Westphal   netfilter: reduce...
277
  	case NFPROTO_IPV6:
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
278
  		if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= hooknum))
ef57170bb   Florian Westphal   netfilter: reduce...
279
  			return NULL;
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
280
  		return net->nf.hooks_ipv6 + hooknum;
bb4badf3a   Florian Westphal   netfilter: don't ...
281
  #if IS_ENABLED(CONFIG_DECNET)
b0f38338a   Florian Westphal   netfilter: reduce...
282
  	case NFPROTO_DECNET:
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
283
  		if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= hooknum))
ef57170bb   Florian Westphal   netfilter: reduce...
284
  			return NULL;
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
285
  		return net->nf.hooks_decnet + hooknum;
bb4badf3a   Florian Westphal   netfilter: don't ...
286
  #endif
b0f38338a   Florian Westphal   netfilter: reduce...
287
288
289
290
  	default:
  		WARN_ON_ONCE(1);
  		return NULL;
  	}
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
291

e687ad60a   Pablo Neira   netfilter: add ne...
292
  #ifdef CONFIG_NETFILTER_INGRESS
62a0fe46e   Pablo Neira Ayuso   netfilter: core: ...
293
294
295
  	if (hooknum == NF_NETDEV_INGRESS) {
  		if (dev && dev_net(dev) == net)
  			return &dev->nf_hooks_ingress;
e687ad60a   Pablo Neira   netfilter: add ne...
296
  	}
7816ec564   Aaron Conole   netfilter: accomm...
297
  #endif
960632ece   Aaron Conole   netfilter: conver...
298
  	WARN_ON_ONCE(1);
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
299
  	return NULL;
e3b37f11e   Aaron Conole   netfilter: replac...
300
  }
7181ebafd   Pablo Neira Ayuso   netfilter: fix po...
301

cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
302
303
  static int __nf_register_net_hook(struct net *net, int pf,
  				  const struct nf_hook_ops *reg)
0edcf282b   Eric W. Biederman   netfilter: Factor...
304
  {
960632ece   Aaron Conole   netfilter: conver...
305
306
  	struct nf_hook_entries *p, *new_hooks;
  	struct nf_hook_entries __rcu **pp;
085db2c04   Eric W. Biederman   netfilter: Per ne...
307

cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
308
  	if (pf == NFPROTO_NETDEV) {
7816ec564   Aaron Conole   netfilter: accomm...
309
310
311
312
313
314
315
316
  #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...
317

cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
318
  	pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev);
bd3769bfe   Linus Torvalds   netfilter: Fix sl...
319
320
  	if (!pp)
  		return -EINVAL;
e3b37f11e   Aaron Conole   netfilter: replac...
321
  	mutex_lock(&nf_hook_mutex);
085db2c04   Eric W. Biederman   netfilter: Per ne...
322

960632ece   Aaron Conole   netfilter: conver...
323
324
325
326
327
  	p = nf_entry_dereference(*pp);
  	new_hooks = nf_hook_entries_grow(p, reg);
  
  	if (!IS_ERR(new_hooks))
  		rcu_assign_pointer(*pp, new_hooks);
e3b37f11e   Aaron Conole   netfilter: replac...
328

fd706d695   Patrick McHardy   [NETFILTER]: Swit...
329
  	mutex_unlock(&nf_hook_mutex);
960632ece   Aaron Conole   netfilter: conver...
330
331
  	if (IS_ERR(new_hooks))
  		return PTR_ERR(new_hooks);
2420b79f8   Florian Westphal   netfilter: debug:...
332
  	hooks_validate(new_hooks);
4c0911566   Eric W. Biederman   netfilter: Simply...
333
  #ifdef CONFIG_NETFILTER_INGRESS
cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
334
  	if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
4c0911566   Eric W. Biederman   netfilter: Simply...
335
336
  		net_inc_ingress_queue();
  #endif
e9666d10a   Masahiro Yamada   jump_label: move ...
337
  #ifdef CONFIG_JUMP_LABEL
cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
338
  	static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]);
a2d7ec58a   Eric Dumazet   netfilter: use ju...
339
  #endif
960632ece   Aaron Conole   netfilter: conver...
340
  	BUG_ON(p == new_hooks);
8c873e219   Florian Westphal   netfilter: core: ...
341
  	nf_hook_entries_free(p);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
342
343
  	return 0;
  }
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
344

960632ece   Aaron Conole   netfilter: conver...
345
  /*
3d3cdc38e   Pablo Neira Ayuso   netfilter: core: ...
346
   * nf_remove_net_hook - remove a hook from blob
960632ece   Aaron Conole   netfilter: conver...
347
348
349
350
351
352
353
   *
   * @oldp: current address of hook blob
   * @unreg: hook to unregister
   *
   * This cannot fail, hook unregistration must always succeed.
   * Therefore replace the to-be-removed hook with a dummy hook.
   */
06cad3acf   Florian Westphal   netfilter: core: ...
354
355
  static bool nf_remove_net_hook(struct nf_hook_entries *old,
  			       const struct nf_hook_ops *unreg)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
356
  {
960632ece   Aaron Conole   netfilter: conver...
357
  	struct nf_hook_ops **orig_ops;
960632ece   Aaron Conole   netfilter: conver...
358
  	unsigned int i;
085db2c04   Eric W. Biederman   netfilter: Per ne...
359

960632ece   Aaron Conole   netfilter: conver...
360
361
362
363
364
365
  	orig_ops = nf_hook_entries_get_hook_ops(old);
  	for (i = 0; i < old->num_hook_entries; i++) {
  		if (orig_ops[i] != unreg)
  			continue;
  		WRITE_ONCE(old->hooks[i].hook, accept_all);
  		WRITE_ONCE(orig_ops[i], &dummy_ops);
06cad3acf   Florian Westphal   netfilter: core: ...
366
  		return true;
085db2c04   Eric W. Biederman   netfilter: Per ne...
367
  	}
960632ece   Aaron Conole   netfilter: conver...
368

06cad3acf   Florian Westphal   netfilter: core: ...
369
  	return false;
933bd83ed   Florian Westphal   netfilter: batch ...
370
  }
0ded1785f   Wei Yongjun   netfilter: core: ...
371
372
  static void __nf_unregister_net_hook(struct net *net, int pf,
  				     const struct nf_hook_ops *reg)
933bd83ed   Florian Westphal   netfilter: batch ...
373
  {
960632ece   Aaron Conole   netfilter: conver...
374
375
  	struct nf_hook_entries __rcu **pp;
  	struct nf_hook_entries *p;
933bd83ed   Florian Westphal   netfilter: batch ...
376

cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
377
  	pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev);
960632ece   Aaron Conole   netfilter: conver...
378
379
380
381
382
383
384
385
386
387
  	if (!pp)
  		return;
  
  	mutex_lock(&nf_hook_mutex);
  
  	p = nf_entry_dereference(*pp);
  	if (WARN_ON_ONCE(!p)) {
  		mutex_unlock(&nf_hook_mutex);
  		return;
  	}
06cad3acf   Florian Westphal   netfilter: core: ...
388
389
390
391
392
  	if (nf_remove_net_hook(p, reg)) {
  #ifdef CONFIG_NETFILTER_INGRESS
  		if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
  			net_dec_ingress_queue();
  #endif
e9666d10a   Masahiro Yamada   jump_label: move ...
393
  #ifdef CONFIG_JUMP_LABEL
06cad3acf   Florian Westphal   netfilter: core: ...
394
395
396
397
398
  		static_key_slow_dec(&nf_hooks_needed[pf][reg->hooknum]);
  #endif
  	} else {
  		WARN_ONCE(1, "hook not found, pf %d num %d", pf, reg->hooknum);
  	}
960632ece   Aaron Conole   netfilter: conver...
399

06cad3acf   Florian Westphal   netfilter: core: ...
400
  	p = __nf_hook_entries_try_shrink(p, pp);
960632ece   Aaron Conole   netfilter: conver...
401
  	mutex_unlock(&nf_hook_mutex);
933bd83ed   Florian Westphal   netfilter: batch ...
402
403
  	if (!p)
  		return;
26888dfd7   Florian Westphal   netfilter: core: ...
404
  	nf_queue_nf_hook_drop(net);
8c873e219   Florian Westphal   netfilter: core: ...
405
  	nf_hook_entries_free(p);
085db2c04   Eric W. Biederman   netfilter: Per ne...
406
  }
cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
407
408
409
410
411
412
413
414
415
416
  
  void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
  {
  	if (reg->pf == NFPROTO_INET) {
  		__nf_unregister_net_hook(net, NFPROTO_IPV4, reg);
  		__nf_unregister_net_hook(net, NFPROTO_IPV6, reg);
  	} else {
  		__nf_unregister_net_hook(net, reg->pf, reg);
  	}
  }
085db2c04   Eric W. Biederman   netfilter: Per ne...
417
  EXPORT_SYMBOL(nf_unregister_net_hook);
06cad3acf   Florian Westphal   netfilter: core: ...
418
419
420
421
422
423
424
425
426
427
428
429
  void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp,
  				const struct nf_hook_ops *reg)
  {
  	struct nf_hook_entries *p;
  
  	p = rcu_dereference_raw(*pp);
  	if (nf_remove_net_hook(p, reg)) {
  		p = __nf_hook_entries_try_shrink(p, pp);
  		nf_hook_entries_free(p);
  	}
  }
  EXPORT_SYMBOL_GPL(nf_hook_entries_delete_raw);
cb7ccd835   Pablo Neira Ayuso   netfilter: core: ...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
  {
  	int err;
  
  	if (reg->pf == NFPROTO_INET) {
  		err = __nf_register_net_hook(net, NFPROTO_IPV4, reg);
  		if (err < 0)
  			return err;
  
  		err = __nf_register_net_hook(net, NFPROTO_IPV6, reg);
  		if (err < 0) {
  			__nf_unregister_net_hook(net, NFPROTO_IPV4, reg);
  			return err;
  		}
  	} else {
  		err = __nf_register_net_hook(net, reg->pf, reg);
  		if (err < 0)
  			return err;
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL(nf_register_net_hook);
085db2c04   Eric W. Biederman   netfilter: Per ne...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  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,
933bd83ed   Florian Westphal   netfilter: batch ...
474
  			     unsigned int hookcount)
085db2c04   Eric W. Biederman   netfilter: Per ne...
475
  {
4e645b47c   Florian Westphal   netfilter: core: ...
476
  	unsigned int i;
933bd83ed   Florian Westphal   netfilter: batch ...
477

4e645b47c   Florian Westphal   netfilter: core: ...
478
479
  	for (i = 0; i < hookcount; i++)
  		nf_unregister_net_hook(net, &reg[i]);
085db2c04   Eric W. Biederman   netfilter: Per ne...
480
481
  }
  EXPORT_SYMBOL(nf_unregister_net_hooks);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
482
  /* Returns 1 if okfn() needs to be executed by the caller,
e2361cb90   Aaron Conole   netfilter: Remove...
483
   * -EPERM for NF_DROP, 0 otherwise.  Caller must hold rcu_read_lock. */
01886bd91   Pablo Neira Ayuso   netfilter: remove...
484
  int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state,
960632ece   Aaron Conole   netfilter: conver...
485
  		 const struct nf_hook_entries *e, unsigned int s)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
486
  {
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
487
  	unsigned int verdict;
c63cbc460   Pablo Neira Ayuso   netfilter: use sw...
488
  	int ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
489

960632ece   Aaron Conole   netfilter: conver...
490
491
  	for (; s < e->num_hook_entries; s++) {
  		verdict = nf_hook_entry_hookfn(&e->hooks[s], skb, state);
26dfab721   Pablo Neira Ayuso   netfilter: merge ...
492
493
  		switch (verdict & NF_VERDICT_MASK) {
  		case NF_ACCEPT:
26dfab721   Pablo Neira Ayuso   netfilter: merge ...
494
495
496
497
498
499
500
  			break;
  		case NF_DROP:
  			kfree_skb(skb);
  			ret = NF_DROP_GETERR(verdict);
  			if (ret == 0)
  				ret = -EPERM;
  			return ret;
26dfab721   Pablo Neira Ayuso   netfilter: merge ...
501
  		case NF_QUEUE:
0d9cb300a   Florian Westphal   netfilter: nf_que...
502
  			ret = nf_queue(skb, state, s, verdict);
960632ece   Aaron Conole   netfilter: conver...
503
  			if (ret == 1)
26dfab721   Pablo Neira Ayuso   netfilter: merge ...
504
505
506
507
508
509
510
511
  				continue;
  			return ret;
  		default:
  			/* Implicit handling for NF_STOLEN, as well as any other
  			 * non conventional verdicts.
  			 */
  			return 0;
  		}
960632ece   Aaron Conole   netfilter: conver...
512
  	}
26dfab721   Pablo Neira Ayuso   netfilter: merge ...
513
514
  
  	return 1;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
515
516
  }
  EXPORT_SYMBOL(nf_hook_slow);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
517
518
519
  /* 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...
520
521
  struct nfnl_ct_hook __rcu *nfnl_ct_hook __read_mostly;
  EXPORT_SYMBOL_GPL(nfnl_ct_hook);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
522

1f4b24397   Pablo Neira Ayuso   netfilter: add st...
523
524
  struct nf_ct_hook __rcu *nf_ct_hook __read_mostly;
  EXPORT_SYMBOL_GPL(nf_ct_hook);
c0cd11566   Igor Maravić   net:netfilter: us...
525
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
526
527
528
  /* 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...
529
530
  void (*ip_ct_attach)(struct sk_buff *, const struct sk_buff *)
  		__rcu __read_mostly;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
531
  EXPORT_SYMBOL(ip_ct_attach);
2c205dd39   Pablo Neira Ayuso   netfilter: add st...
532
533
  struct nf_nat_hook __rcu *nf_nat_hook __read_mostly;
  EXPORT_SYMBOL_GPL(nf_nat_hook);
312a0c16c   Patrick McHardy   netfilter: nf_con...
534
  void nf_ct_attach(struct sk_buff *new, const struct sk_buff *skb)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
535
  {
312a0c16c   Patrick McHardy   netfilter: nf_con...
536
  	void (*attach)(struct sk_buff *, const struct sk_buff *);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
537

a9e419dc7   Florian Westphal   netfilter: merge ...
538
  	if (skb->_nfct) {
c3a47ab3e   Patrick McHardy   [NETFILTER]: Prop...
539
540
541
542
543
  		rcu_read_lock();
  		attach = rcu_dereference(ip_ct_attach);
  		if (attach)
  			attach(new, skb);
  		rcu_read_unlock();
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
544
545
546
  	}
  }
  EXPORT_SYMBOL(nf_ct_attach);
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
547

de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
548
549
  void nf_conntrack_destroy(struct nf_conntrack *nfct)
  {
1f4b24397   Pablo Neira Ayuso   netfilter: add st...
550
  	struct nf_ct_hook *ct_hook;
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
551
552
  
  	rcu_read_lock();
1f4b24397   Pablo Neira Ayuso   netfilter: add st...
553
554
555
  	ct_hook = rcu_dereference(nf_ct_hook);
  	BUG_ON(ct_hook == NULL);
  	ct_hook->destroy(nfct);
de6e05c49   Yasuyuki Kozakai   [NETFILTER]: nf_c...
556
557
558
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL(nf_conntrack_destroy);
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
559

b60a60405   Toke Høiland-Jørgensen   netfilter: Add nf...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  bool nf_ct_get_tuple_skb(struct nf_conntrack_tuple *dst_tuple,
  			 const struct sk_buff *skb)
  {
  	struct nf_ct_hook *ct_hook;
  	bool ret = false;
  
  	rcu_read_lock();
  	ct_hook = rcu_dereference(nf_ct_hook);
  	if (ct_hook)
  		ret = ct_hook->get_tuple_skb(dst_tuple, skb);
  	rcu_read_unlock();
  	return ret;
  }
  EXPORT_SYMBOL(nf_ct_get_tuple_skb);
62da98656   Daniel Borkmann   netfilter: nf_con...
574
575
576
577
578
579
  /* 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...
580
  #endif /* CONFIG_NF_CONNTRACK */
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
581

25fd386e0   Florian Westphal   netfilter: core: ...
582
583
  static void __net_init
  __netfilter_net_init(struct nf_hook_entries __rcu **e, int max)
f3c1a44a2   Gao feng   netfilter: make /...
584
  {
b0f38338a   Florian Westphal   netfilter: reduce...
585
  	int h;
085db2c04   Eric W. Biederman   netfilter: Per ne...
586

ef57170bb   Florian Westphal   netfilter: reduce...
587
  	for (h = 0; h < max; h++)
b0f38338a   Florian Westphal   netfilter: reduce...
588
589
590
591
592
  		RCU_INIT_POINTER(e[h], NULL);
  }
  
  static int __net_init netfilter_net_init(struct net *net)
  {
ef57170bb   Florian Westphal   netfilter: reduce...
593
594
  	__netfilter_net_init(net->nf.hooks_ipv4, ARRAY_SIZE(net->nf.hooks_ipv4));
  	__netfilter_net_init(net->nf.hooks_ipv6, ARRAY_SIZE(net->nf.hooks_ipv6));
2a95183a5   Florian Westphal   netfilter: don't ...
595
  #ifdef CONFIG_NETFILTER_FAMILY_ARP
ef57170bb   Florian Westphal   netfilter: reduce...
596
  	__netfilter_net_init(net->nf.hooks_arp, ARRAY_SIZE(net->nf.hooks_arp));
2a95183a5   Florian Westphal   netfilter: don't ...
597
598
  #endif
  #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
ef57170bb   Florian Westphal   netfilter: reduce...
599
  	__netfilter_net_init(net->nf.hooks_bridge, ARRAY_SIZE(net->nf.hooks_bridge));
2a95183a5   Florian Westphal   netfilter: don't ...
600
  #endif
bb4badf3a   Florian Westphal   netfilter: don't ...
601
  #if IS_ENABLED(CONFIG_DECNET)
ef57170bb   Florian Westphal   netfilter: reduce...
602
  	__netfilter_net_init(net->nf.hooks_decnet, ARRAY_SIZE(net->nf.hooks_decnet));
bb4badf3a   Florian Westphal   netfilter: don't ...
603
  #endif
085db2c04   Eric W. Biederman   netfilter: Per ne...
604

f3c1a44a2   Gao feng   netfilter: make /...
605
606
607
  #ifdef CONFIG_PROC_FS
  	net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
  						net->proc_net);
12202fa75   Pablo Neira Ayuso   netfilter: remove...
608
609
610
  	if (!net->nf.proc_netfilter) {
  		if (!net_eq(net, &init_net))
  			pr_err("cannot create netfilter proc entry");
f3c1a44a2   Gao feng   netfilter: make /...
611
612
613
  		return -ENOMEM;
  	}
  #endif
085db2c04   Eric W. Biederman   netfilter: Per ne...
614

073dd5ad3   Dan Carpenter   netfilter: fix ne...
615
  	return 0;
f3c1a44a2   Gao feng   netfilter: make /...
616
617
618
619
620
621
622
623
624
625
626
  }
  
  static void __net_exit netfilter_net_exit(struct net *net)
  {
  	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 ...
627
  int __init netfilter_init(void)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
628
  {
085db2c04   Eric W. Biederman   netfilter: Per ne...
629
  	int ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
630

6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
631
632
633
634
635
636
637
  	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...
638

6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
639
640
641
642
643
  	return 0;
  err_pernet:
  	unregister_pernet_subsys(&netfilter_net_ops);
  err:
  	return ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
644
  }