Blame view

net/netfilter/nfnetlink_queue.c 38.4 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
2
3
  /*
   * This is a module which is used for queueing packets and communicating with
67137f3cc   Jesper Dangaard Brouer   nfnetlink_queue: ...
4
   * userspace via nfnetlink.
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
5
6
   *
   * (C) 2005 by Harald Welte <laforge@netfilter.org>
4ad9d4fa9   Patrick McHardy   [NETFILTER]: nfne...
7
   * (C) 2007 by Patrick McHardy <kaber@trash.net>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
8
9
10
11
   *
   * Based on the old ipv4-only ip_queue.c:
   * (C) 2000-2002 James Morris <jmorris@intercode.com.au>
   * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
12
   */
5191d70f8   Arushi Singhal   netfilter: Replac...
13
14
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
15
16
17
18
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/init.h>
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
20
21
22
  #include <linux/notifier.h>
  #include <linux/netdevice.h>
  #include <linux/netfilter.h>
838ab6364   Harald Welte   [NETFILTER]: Add ...
23
  #include <linux/proc_fs.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
24
25
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv6.h>
c737b7c45   Florian Westphal   netfilter: bridge...
26
  #include <linux/netfilter_bridge.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
27
28
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_queue.h>
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
29
  #include <linux/netfilter/nf_conntrack_common.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
30
31
  #include <linux/list.h>
  #include <net/sock.h>
83111e7fe   David S. Miller   netfilter: Fix bu...
32
  #include <net/tcp_states.h>
c01cd429f   Patrick McHardy   [NETFILTER]: nf_q...
33
  #include <net/netfilter/nf_queue.h>
e81796104   Gao feng   netfilter: nfnetl...
34
  #include <net/netns/generic.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
35

60063497a   Arun Sharma   atomic: use <linu...
36
  #include <linux/atomic.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
37

1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
38
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
fbcd923c3   Harald Welte   [NETFILTER]: add ...
39
40
  #include "../bridge/br_private.h"
  #endif
5da773a3e   Florian Westphal   netfilter: nfnetl...
41
42
43
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
  #include <net/netfilter/nf_conntrack.h>
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
44
  #define NFQNL_QMAX_DEFAULT 1024
9cefbbc9c   Florian Westphal   netfilter: nfnetl...
45
46
47
48
49
50
51
  /* We're using struct nlattr which has 16bit nla_len. Note that nla_len
   * includes the header length. Thus, the maximum packet length that we
   * support is 65531 bytes. We send truncated packets if the specified length
   * is larger than that.  Userspace can check for presence of NFQA_CAP_LEN
   * attribute to detect truncation.
   */
  #define NFQNL_MAX_COPY_RANGE (0xffff - NLA_HDRLEN)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
52
53
  struct nfqnl_instance {
  	struct hlist_node hlist;		/* global list of queues */
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
54
  	struct rcu_head rcu;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
55

cc6bc4486   Richard Weinberger   netfilter: Fix po...
56
  	u32 peer_portid;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
57
58
  	unsigned int queue_maxlen;
  	unsigned int copy_range;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
59
60
  	unsigned int queue_dropped;
  	unsigned int queue_user_dropped;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
61
62
63
  
  	u_int16_t queue_num;			/* number of this queue */
  	u_int8_t copy_mode;
fdb694a01   Krishna Kumar   netfilter: Add fa...
64
  	u_int32_t flags;			/* Set using NFQA_CFG_FLAGS */
c463ac972   Eric Dumazet   netfilter: nfnetl...
65
66
67
68
  /*
   * Following fields are dirtied for each queued packet,
   * keep them in same cache line if possible.
   */
886bc5034   Florian Westphal   netfilter: nf_que...
69
  	spinlock_t	lock	____cacheline_aligned_in_smp;
c463ac972   Eric Dumazet   netfilter: nfnetl...
70
  	unsigned int	queue_total;
5863702a3   Eric Dumazet   netfilter: nfnetl...
71
  	unsigned int	id_sequence;		/* 'sequence' of pkt ids */
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
72
73
  	struct list_head queue_list;		/* packets in queue */
  };
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
74
  typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
75

c7d03a00b   Alexey Dobriyan   netns: make struc...
76
  static unsigned int nfnl_queue_net_id __read_mostly;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
77

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
78
  #define INSTANCE_BUCKETS	16
e81796104   Gao feng   netfilter: nfnetl...
79
80
81
82
83
84
85
86
87
  struct nfnl_queue_net {
  	spinlock_t instances_lock;
  	struct hlist_head instance_table[INSTANCE_BUCKETS];
  };
  
  static struct nfnl_queue_net *nfnl_queue_pernet(struct net *net)
  {
  	return net_generic(net, nfnl_queue_net_id);
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
88
89
90
  
  static inline u_int8_t instance_hashfn(u_int16_t queue_num)
  {
1cdb09056   Pablo Neira Ayuso   netfilter: nfnetl...
91
  	return ((queue_num >> 8) ^ queue_num) % INSTANCE_BUCKETS;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
92
93
94
  }
  
  static struct nfqnl_instance *
e81796104   Gao feng   netfilter: nfnetl...
95
  instance_lookup(struct nfnl_queue_net *q, u_int16_t queue_num)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
96
97
  {
  	struct hlist_head *head;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
98
  	struct nfqnl_instance *inst;
e81796104   Gao feng   netfilter: nfnetl...
99
  	head = &q->instance_table[instance_hashfn(queue_num)];
b67bfe0d4   Sasha Levin   hlist: drop the n...
100
  	hlist_for_each_entry_rcu(inst, head, hlist) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
101
102
103
104
105
106
107
  		if (inst->queue_num == queue_num)
  			return inst;
  	}
  	return NULL;
  }
  
  static struct nfqnl_instance *
cc6bc4486   Richard Weinberger   netfilter: Fix po...
108
  instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
109
  {
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
110
  	struct nfqnl_instance *inst;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
111
  	unsigned int h;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
112
  	int err;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
113

e81796104   Gao feng   netfilter: nfnetl...
114
115
  	spin_lock(&q->instances_lock);
  	if (instance_lookup(q, queue_num)) {
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
116
  		err = -EEXIST;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
117
  		goto out_unlock;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
118
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
119

10dfdc69e   Harald Welte   [NETFILTER] nfnet...
120
  	inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
121
122
  	if (!inst) {
  		err = -ENOMEM;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
123
  		goto out_unlock;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
124
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
125

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
126
  	inst->queue_num = queue_num;
15e473046   Eric W. Biederman   netlink: Rename p...
127
  	inst->peer_portid = portid;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
128
  	inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
9cefbbc9c   Florian Westphal   netfilter: nfnetl...
129
  	inst->copy_range = NFQNL_MAX_COPY_RANGE;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
130
  	inst->copy_mode = NFQNL_COPY_NONE;
181a46a56   YOSHIFUJI Hideaki   [NETFILTER]: Use ...
131
  	spin_lock_init(&inst->lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
132
  	INIT_LIST_HEAD(&inst->queue_list);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
133
134
  	if (!try_module_get(THIS_MODULE)) {
  		err = -EAGAIN;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
135
  		goto out_free;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
136
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
137

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
138
  	h = instance_hashfn(queue_num);
e81796104   Gao feng   netfilter: nfnetl...
139
  	hlist_add_head_rcu(&inst->hlist, &q->instance_table[h]);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
140

e81796104   Gao feng   netfilter: nfnetl...
141
  	spin_unlock(&q->instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
142

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
143
144
145
146
147
  	return inst;
  
  out_free:
  	kfree(inst);
  out_unlock:
e81796104   Gao feng   netfilter: nfnetl...
148
  	spin_unlock(&q->instances_lock);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
149
  	return ERR_PTR(err);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
150
  }
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
151
152
  static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
  			unsigned long data);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
153
154
  
  static void
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
155
  instance_destroy_rcu(struct rcu_head *head)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
156
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
157
158
  	struct nfqnl_instance *inst = container_of(head, struct nfqnl_instance,
  						   rcu);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
159

b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
160
  	nfqnl_flush(inst, NULL, 0);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
161
  	kfree(inst);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
162
163
  	module_put(THIS_MODULE);
  }
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
164
  static void
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
165
166
  __instance_destroy(struct nfqnl_instance *inst)
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
167
168
  	hlist_del_rcu(&inst->hlist);
  	call_rcu(&inst->rcu, instance_destroy_rcu);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
169
  }
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
170
  static void
e81796104   Gao feng   netfilter: nfnetl...
171
  instance_destroy(struct nfnl_queue_net *q, struct nfqnl_instance *inst)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
172
  {
e81796104   Gao feng   netfilter: nfnetl...
173
  	spin_lock(&q->instances_lock);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
174
  	__instance_destroy(inst);
e81796104   Gao feng   netfilter: nfnetl...
175
  	spin_unlock(&q->instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
176
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
177
  static inline void
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
178
  __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
179
  {
0ac41e814   Patrick McHardy   [NETFILTER]: {nf_...
180
         list_add_tail(&entry->list, &queue->queue_list);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
181
182
         queue->queue_total++;
  }
97d32cf94   Florian Westphal   netfilter: nfnetl...
183
184
185
186
187
188
  static void
  __dequeue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
  {
  	list_del(&entry->list);
  	queue->queue_total--;
  }
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
189
  static struct nf_queue_entry *
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
190
  find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
191
  {
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
192
  	struct nf_queue_entry *entry = NULL, *i;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
193

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
194
  	spin_lock_bh(&queue->lock);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
195
196
197
198
199
200
201
  
  	list_for_each_entry(i, &queue->queue_list, list) {
  		if (i->id == id) {
  			entry = i;
  			break;
  		}
  	}
97d32cf94   Florian Westphal   netfilter: nfnetl...
202
203
  	if (entry)
  		__dequeue_entry(queue, entry);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
204

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
205
206
207
208
  	spin_unlock_bh(&queue->lock);
  
  	return entry;
  }
368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
209
210
211
212
213
214
  static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
  {
  	struct nf_ct_hook *ct_hook;
  	int err;
  
  	if (verdict == NF_ACCEPT ||
ad18d7bf6   Michal 'vorner' Vaner   netfilter: nfnetl...
215
  	    verdict == NF_REPEAT ||
368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
216
217
218
219
220
221
222
223
224
225
226
227
  	    verdict == NF_STOP) {
  		rcu_read_lock();
  		ct_hook = rcu_dereference(nf_ct_hook);
  		if (ct_hook) {
  			err = ct_hook->update(entry->state.net, entry->skb);
  			if (err < 0)
  				verdict = NF_DROP;
  		}
  		rcu_read_unlock();
  	}
  	nf_reinject(entry, verdict);
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
228
  static void
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
229
  nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
230
  {
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
231
  	struct nf_queue_entry *entry, *next;
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
232

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
233
  	spin_lock_bh(&queue->lock);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
234
235
236
237
  	list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
  		if (!cmpfn || cmpfn(entry, data)) {
  			list_del(&entry->list);
  			queue->queue_total--;
368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
238
  			nfqnl_reinject(entry, NF_DROP);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
239
240
  		}
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
241
242
  	spin_unlock_bh(&queue->lock);
  }
496e4ae7d   Florian Westphal   netfilter: nf_que...
243
244
245
  static int
  nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet,
  		      bool csum_verify)
7237190df   Florian Westphal   netfilter: nfnetl...
246
247
248
249
250
  {
  	__u32 flags = 0;
  
  	if (packet->ip_summed == CHECKSUM_PARTIAL)
  		flags = NFQA_SKB_CSUMNOTREADY;
496e4ae7d   Florian Westphal   netfilter: nf_que...
251
252
  	else if (csum_verify)
  		flags = NFQA_SKB_CSUM_NOTVERIFIED;
7237190df   Florian Westphal   netfilter: nfnetl...
253
254
255
256
257
  	if (skb_is_gso(packet))
  		flags |= NFQA_SKB_GSO;
  
  	return flags ? nla_put_be32(nlskb, NFQA_SKB_INFO, htonl(flags)) : 0;
  }
08c0cad69   Valentina Giusti   netfilter: nfnetl...
258
259
260
  static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
  {
  	const struct cred *cred;
a8399231f   Eric Dumazet   netfilter: use sk...
261
  	if (!sk_fullsock(sk))
08c0cad69   Valentina Giusti   netfilter: nfnetl...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  		return 0;
  
  	read_lock_bh(&sk->sk_callback_lock);
  	if (sk->sk_socket && sk->sk_socket->file) {
  		cred = sk->sk_socket->file->f_cred;
  		if (nla_put_be32(skb, NFQA_UID,
  		    htonl(from_kuid_munged(&init_user_ns, cred->fsuid))))
  			goto nla_put_failure;
  		if (nla_put_be32(skb, NFQA_GID,
  		    htonl(from_kgid_munged(&init_user_ns, cred->fsgid))))
  			goto nla_put_failure;
  	}
  	read_unlock_bh(&sk->sk_callback_lock);
  	return 0;
  
  nla_put_failure:
  	read_unlock_bh(&sk->sk_callback_lock);
  	return -1;
  }
ef493bd93   Roman Kubiak   netfilter: nfnetl...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
  {
  	u32 seclen = 0;
  #if IS_ENABLED(CONFIG_NETWORK_SECMARK)
  	if (!skb || !sk_fullsock(skb->sk))
  		return 0;
  
  	read_lock_bh(&skb->sk->sk_callback_lock);
  
  	if (skb->secmark)
  		security_secid_to_secctx(skb->secmark, secdata, &seclen);
  
  	read_unlock_bh(&skb->sk->sk_callback_lock);
  #endif
  	return seclen;
  }
15824ab29   Stephane Bryant   netfilter: bridge...
297
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
  static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry)
  {
  	struct sk_buff *entskb = entry->skb;
  	u32 nlalen = 0;
  
  	if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb))
  		return 0;
  
  	if (skb_vlan_tag_present(entskb))
  		nlalen += nla_total_size(nla_total_size(sizeof(__be16)) +
  					 nla_total_size(sizeof(__be16)));
  
  	if (entskb->network_header > entskb->mac_header)
  		nlalen += nla_total_size((entskb->network_header -
  					  entskb->mac_header));
  
  	return nlalen;
  }
  
  static int nfqnl_put_bridge(struct nf_queue_entry *entry, struct sk_buff *skb)
  {
  	struct sk_buff *entskb = entry->skb;
  
  	if (entry->state.pf != PF_BRIDGE || !skb_mac_header_was_set(entskb))
  		return 0;
  
  	if (skb_vlan_tag_present(entskb)) {
  		struct nlattr *nest;
ae0be8de9   Michal Kubecek   netlink: make nla...
325
  		nest = nla_nest_start(skb, NFQA_VLAN);
15824ab29   Stephane Bryant   netfilter: bridge...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  		if (!nest)
  			goto nla_put_failure;
  
  		if (nla_put_be16(skb, NFQA_VLAN_TCI, htons(entskb->vlan_tci)) ||
  		    nla_put_be16(skb, NFQA_VLAN_PROTO, entskb->vlan_proto))
  			goto nla_put_failure;
  
  		nla_nest_end(skb, nest);
  	}
  
  	if (entskb->mac_header < entskb->network_header) {
  		int len = (int)(entskb->network_header - entskb->mac_header);
  
  		if (nla_put(skb, NFQA_L2HDR, len, skb_mac_header(entskb)))
  			goto nla_put_failure;
  	}
  
  	return 0;
  
  nla_put_failure:
  	return -1;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
348
  static struct sk_buff *
743326878   Gao feng   netfilter: nfnetl...
349
  nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
5863702a3   Eric Dumazet   netfilter: nfnetl...
350
351
  			   struct nf_queue_entry *entry,
  			   __be32 **packet_id_ptr)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
352
  {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
353
  	size_t size;
c5b0db326   Florian Westphal   nfnetlink: Revert...
354
  	size_t data_len = 0, cap_len = 0;
af2806f8f   Thomas Graf   net: Export skb_z...
355
  	unsigned int hlen = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
356
  	struct sk_buff *skb;
5863702a3   Eric Dumazet   netfilter: nfnetl...
357
358
  	struct nlattr *nla;
  	struct nfqnl_msg_packet_hdr *pmsg;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
359
360
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
361
362
363
  	struct sk_buff *entskb = entry->skb;
  	struct net_device *indev;
  	struct net_device *outdev;
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
364
  	struct nf_conn *ct = NULL;
3f649ab72   Kees Cook   treewide: Remove ...
365
  	enum ip_conntrack_info ctinfo;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
366
  	struct nfnl_ct_hook *nfnl_ct;
496e4ae7d   Florian Westphal   netfilter: nf_que...
367
  	bool csum_verify;
ef493bd93   Roman Kubiak   netfilter: nfnetl...
368
369
  	char *secdata = NULL;
  	u32 seclen = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
370

7e59b3fea   yangxingwu   netfilter: remove...
371
  	size = nlmsg_total_size(sizeof(struct nfgenmsg))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
372
373
374
  		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
375
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
376
377
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
fbcd923c3   Harald Welte   [NETFILTER]: add ...
378
  #endif
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
379
380
  		+ nla_total_size(sizeof(u_int32_t))	/* mark */
  		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
7237190df   Florian Westphal   netfilter: nfnetl...
381
  		+ nla_total_size(sizeof(u_int32_t))	/* skbinfo */
ae08ce002   Eric Dumazet   netfilter: nfnetl...
382
  		+ nla_total_size(sizeof(u_int32_t));	/* cap_len */
2456e8553   Thomas Gleixner   ktime: Get rid of...
383
  	if (entskb->tstamp)
ae08ce002   Eric Dumazet   netfilter: nfnetl...
384
  		size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
385

15824ab29   Stephane Bryant   netfilter: bridge...
386
  	size += nfqnl_get_bridge_size(entry);
1d1de89b9   David S. Miller   netfilter: Use nf...
387
388
  	if (entry->state.hook <= NF_INET_FORWARD ||
  	   (entry->state.hook == NF_INET_POST_ROUTING && entskb->sk == NULL))
496e4ae7d   Florian Westphal   netfilter: nf_que...
389
390
391
  		csum_verify = !skb_csum_unnecessary(entskb);
  	else
  		csum_verify = false;
1d1de89b9   David S. Miller   netfilter: Use nf...
392
  	outdev = entry->state.out;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
393

14cd5d4a0   Mark Rutland   locking/atomics, ...
394
  	switch ((enum nfqnl_config_mode)READ_ONCE(queue->copy_mode)) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
395
396
  	case NFQNL_COPY_META:
  	case NFQNL_COPY_NONE:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
397
  		break;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
398

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
399
  	case NFQNL_COPY_PACKET:
00bd1cc24   Florian Westphal   netfilter: nfnetl...
400
401
  		if (!(queue->flags & NFQA_CFG_F_GSO) &&
  		    entskb->ip_summed == CHECKSUM_PARTIAL &&
c463ac972   Eric Dumazet   netfilter: nfnetl...
402
  		    skb_checksum_help(entskb))
e7dfb09a3   Patrick McHardy   [NETFILTER]: Fix ...
403
  			return NULL;
c463ac972   Eric Dumazet   netfilter: nfnetl...
404

14cd5d4a0   Mark Rutland   locking/atomics, ...
405
  		data_len = READ_ONCE(queue->copy_range);
9cefbbc9c   Florian Westphal   netfilter: nfnetl...
406
  		if (data_len > entskb->len)
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
407
  			data_len = entskb->len;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
408

af2806f8f   Thomas Graf   net: Export skb_z...
409
410
  		hlen = skb_zerocopy_headlen(entskb);
  		hlen = min_t(unsigned int, hlen, data_len);
ae08ce002   Eric Dumazet   netfilter: nfnetl...
411
  		size += sizeof(struct nlattr) + hlen;
6ee584be3   Pablo Neira Ayuso   netfilter: nfnetl...
412
  		cap_len = entskb->len;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
413
  		break;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
414
  	}
8e662164a   Arnd Bergmann   netfilter: nfnetl...
415
  	nfnl_ct = rcu_dereference(nfnl_ct_hook);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
416
  	if (queue->flags & NFQA_CFG_F_CONNTRACK) {
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
417
418
  		if (nfnl_ct != NULL) {
  			ct = nfnl_ct->get_ct(entskb, &ctinfo);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
419
  			if (ct != NULL)
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
420
  				size += nfnl_ct->build_size(ct);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
421
422
  		}
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
423

08c0cad69   Valentina Giusti   netfilter: nfnetl...
424
  	if (queue->flags & NFQA_CFG_F_UID_GID) {
7e59b3fea   yangxingwu   netfilter: remove...
425
  		size += (nla_total_size(sizeof(u_int32_t))	/* uid */
08c0cad69   Valentina Giusti   netfilter: nfnetl...
426
427
  			+ nla_total_size(sizeof(u_int32_t)));	/* gid */
  	}
ef493bd93   Roman Kubiak   netfilter: nfnetl...
428
429
430
431
432
  	if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
  		seclen = nfqnl_get_sk_secctx(entskb, &secdata);
  		if (seclen)
  			size += nla_total_size(seclen);
  	}
c5b0db326   Florian Westphal   nfnetlink: Revert...
433
  	skb = alloc_skb(size, GFP_ATOMIC);
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
434
435
  	if (!skb) {
  		skb_tx_error(entskb);
77c1c03c5   Liping Zhang   netfilter: nfnetl...
436
  		goto nlmsg_failure;
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
437
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
438

3da07c0c2   David S. Miller   netfilter: nfnetl...
439
  	nlh = nlmsg_put(skb, 0, 0,
dedb67c4b   Pablo Neira Ayuso   netfilter: Add nf...
440
  			nfnl_msg_type(NFNL_SUBSYS_QUEUE, NFQNL_MSG_PACKET),
3da07c0c2   David S. Miller   netfilter: nfnetl...
441
442
  			sizeof(struct nfgenmsg), 0);
  	if (!nlh) {
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
443
  		skb_tx_error(entskb);
3da07c0c2   David S. Miller   netfilter: nfnetl...
444
  		kfree_skb(skb);
77c1c03c5   Liping Zhang   netfilter: nfnetl...
445
  		goto nlmsg_failure;
3da07c0c2   David S. Miller   netfilter: nfnetl...
446
447
  	}
  	nfmsg = nlmsg_data(nlh);
1d1de89b9   David S. Miller   netfilter: Use nf...
448
  	nfmsg->nfgen_family = entry->state.pf;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
449
450
  	nfmsg->version = NFNETLINK_V0;
  	nfmsg->res_id = htons(queue->queue_num);
5863702a3   Eric Dumazet   netfilter: nfnetl...
451
452
453
  	nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
  	pmsg = nla_data(nla);
  	pmsg->hw_protocol	= entskb->protocol;
1d1de89b9   David S. Miller   netfilter: Use nf...
454
  	pmsg->hook		= entry->state.hook;
5863702a3   Eric Dumazet   netfilter: nfnetl...
455
  	*packet_id_ptr		= &pmsg->packet_id;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
456

1d1de89b9   David S. Miller   netfilter: Use nf...
457
  	indev = entry->state.in;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
458
  	if (indev) {
1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
459
  #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
a447189e0   David S. Miller   nfnetlink_queue: ...
460
461
  		if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex)))
  			goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
462
  #else
1d1de89b9   David S. Miller   netfilter: Use nf...
463
  		if (entry->state.pf == PF_BRIDGE) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
464
  			/* Case 1: indev is physical input device, we need to
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
465
  			 * look for bridge group (when called from
fbcd923c3   Harald Welte   [NETFILTER]: add ...
466
  			 * netfilter_bridge) */
a447189e0   David S. Miller   nfnetlink_queue: ...
467
468
  			if (nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
  					 htonl(indev->ifindex)) ||
fbcd923c3   Harald Welte   [NETFILTER]: add ...
469
  			/* this is the bridge group "brX" */
f350a0a87   Jiri Pirko   bridge: use rx_ha...
470
  			/* rcu_read_lock()ed by __nf_queue */
a447189e0   David S. Miller   nfnetlink_queue: ...
471
472
473
  			    nla_put_be32(skb, NFQA_IFINDEX_INDEV,
  					 htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
  				goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
474
  		} else {
c737b7c45   Florian Westphal   netfilter: bridge...
475
  			int physinif;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
476
477
  			/* Case 2: indev is bridge group, we need to look for
  			 * physical device (when called from ipv4) */
a447189e0   David S. Miller   nfnetlink_queue: ...
478
479
480
  			if (nla_put_be32(skb, NFQA_IFINDEX_INDEV,
  					 htonl(indev->ifindex)))
  				goto nla_put_failure;
c737b7c45   Florian Westphal   netfilter: bridge...
481
482
483
  
  			physinif = nf_bridge_get_physinif(entskb);
  			if (physinif &&
a447189e0   David S. Miller   nfnetlink_queue: ...
484
  			    nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
c737b7c45   Florian Westphal   netfilter: bridge...
485
  					 htonl(physinif)))
a447189e0   David S. Miller   nfnetlink_queue: ...
486
  				goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
487
488
  		}
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
489
  	}
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
490
  	if (outdev) {
1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
491
  #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
a447189e0   David S. Miller   nfnetlink_queue: ...
492
493
  		if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex)))
  			goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
494
  #else
1d1de89b9   David S. Miller   netfilter: Use nf...
495
  		if (entry->state.pf == PF_BRIDGE) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
496
  			/* Case 1: outdev is physical output device, we need to
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
497
  			 * look for bridge group (when called from
fbcd923c3   Harald Welte   [NETFILTER]: add ...
498
  			 * netfilter_bridge) */
a447189e0   David S. Miller   nfnetlink_queue: ...
499
500
  			if (nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
  					 htonl(outdev->ifindex)) ||
fbcd923c3   Harald Welte   [NETFILTER]: add ...
501
  			/* this is the bridge group "brX" */
f350a0a87   Jiri Pirko   bridge: use rx_ha...
502
  			/* rcu_read_lock()ed by __nf_queue */
a447189e0   David S. Miller   nfnetlink_queue: ...
503
504
505
  			    nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
  					 htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
  				goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
506
  		} else {
c737b7c45   Florian Westphal   netfilter: bridge...
507
  			int physoutif;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
508
509
  			/* Case 2: outdev is bridge group, we need to look for
  			 * physical output device (when called from ipv4) */
a447189e0   David S. Miller   nfnetlink_queue: ...
510
511
512
  			if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
  					 htonl(outdev->ifindex)))
  				goto nla_put_failure;
c737b7c45   Florian Westphal   netfilter: bridge...
513
514
515
  
  			physoutif = nf_bridge_get_physoutif(entskb);
  			if (physoutif &&
a447189e0   David S. Miller   nfnetlink_queue: ...
516
  			    nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
c737b7c45   Florian Westphal   netfilter: bridge...
517
  					 htonl(physoutif)))
a447189e0   David S. Miller   nfnetlink_queue: ...
518
  				goto nla_put_failure;
fbcd923c3   Harald Welte   [NETFILTER]: add ...
519
520
  		}
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
521
  	}
a447189e0   David S. Miller   nfnetlink_queue: ...
522
523
524
  	if (entskb->mark &&
  	    nla_put_be32(skb, NFQA_MARK, htonl(entskb->mark)))
  		goto nla_put_failure;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
525

2c38de4c1   Nicolas Cavallari   netfilter: fix lo...
526
527
  	if (indev && entskb->dev &&
  	    entskb->mac_header != entskb->network_header) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
528
  		struct nfqnl_msg_packet_hw phw;
e4d091d7b   Dan Carpenter   netfilter: nfnetl...
529
530
531
532
  		int len;
  
  		memset(&phw, 0, sizeof(phw));
  		len = dev_parse_header(entskb, phw.hw_addr);
b95cce357   Stephen Hemminger   [NET]: Wrap hard_...
533
534
  		if (len) {
  			phw.hw_addrlen = htons(len);
a447189e0   David S. Miller   nfnetlink_queue: ...
535
536
  			if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw))
  				goto nla_put_failure;
b95cce357   Stephen Hemminger   [NET]: Wrap hard_...
537
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
538
  	}
15824ab29   Stephane Bryant   netfilter: bridge...
539
540
  	if (nfqnl_put_bridge(entry, skb) < 0)
  		goto nla_put_failure;
916f6efae   Florian Westphal   netfilter: never ...
541
  	if (entry->state.hook <= NF_INET_FORWARD && entskb->tstamp) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
542
  		struct nfqnl_msg_packet_timestamp ts;
a7f188455   Florian Westphal   netfilter: nfnetl...
543
  		struct timespec64 kts = ktime_to_timespec64(entskb->tstamp);
b28b1e826   Pablo Neira Ayuso   netfilter: nfnetl...
544
545
546
  
  		ts.sec = cpu_to_be64(kts.tv_sec);
  		ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
547

a447189e0   David S. Miller   nfnetlink_queue: ...
548
549
  		if (nla_put(skb, NFQA_TIMESTAMP, sizeof(ts), &ts))
  			goto nla_put_failure;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
550
  	}
08c0cad69   Valentina Giusti   netfilter: nfnetl...
551
552
553
  	if ((queue->flags & NFQA_CFG_F_UID_GID) && entskb->sk &&
  	    nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
  		goto nla_put_failure;
ef493bd93   Roman Kubiak   netfilter: nfnetl...
554
555
  	if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
  		goto nla_put_failure;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
556
  	if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
ae08ce002   Eric Dumazet   netfilter: nfnetl...
557
  		goto nla_put_failure;
7f87712c0   Florian Westphal   netfilter: nfnetl...
558
559
  	if (cap_len > data_len &&
  	    nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
ae08ce002   Eric Dumazet   netfilter: nfnetl...
560
  		goto nla_put_failure;
496e4ae7d   Florian Westphal   netfilter: nf_que...
561
  	if (nfqnl_put_packet_info(skb, entskb, csum_verify))
7237190df   Florian Westphal   netfilter: nfnetl...
562
  		goto nla_put_failure;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
563
  	if (data_len) {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
564
  		struct nlattr *nla;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
565

ae08ce002   Eric Dumazet   netfilter: nfnetl...
566
567
  		if (skb_tailroom(skb) < sizeof(*nla) + hlen)
  			goto nla_put_failure;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
568

4df864c1d   Johannes Berg   networking: make ...
569
  		nla = skb_put(skb, sizeof(*nla));
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
570
  		nla->nla_type = NFQA_PAYLOAD;
ae08ce002   Eric Dumazet   netfilter: nfnetl...
571
  		nla->nla_len = nla_attr_size(data_len);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
572

36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
573
574
  		if (skb_zerocopy(skb, entskb, data_len, hlen))
  			goto nla_put_failure;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
575
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
576

ae08ce002   Eric Dumazet   netfilter: nfnetl...
577
  	nlh->nlmsg_len = skb->len;
77c1c03c5   Liping Zhang   netfilter: nfnetl...
578
579
  	if (seclen)
  		security_release_secctx(secdata, seclen);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
580
  	return skb;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
581
  nla_put_failure:
36d5fe6a0   Zoltan Kiss   core, nfqueue, op...
582
  	skb_tx_error(entskb);
a67299556   Wei Yongjun   netfilter: nfnetl...
583
  	kfree_skb(skb);
e87cc4728   Joe Perches   net: Convert net_...
584
585
  	net_err_ratelimited("nf_queue: error creating packet message
  ");
77c1c03c5   Liping Zhang   netfilter: nfnetl...
586
587
588
  nlmsg_failure:
  	if (seclen)
  		security_release_secctx(secdata, seclen);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
589
590
  	return NULL;
  }
5da773a3e   Florian Westphal   netfilter: nfnetl...
591
592
593
594
595
596
597
598
599
600
601
  static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry)
  {
  #if IS_ENABLED(CONFIG_NF_CONNTRACK)
  	static const unsigned long flags = IPS_CONFIRMED | IPS_DYING;
  	const struct nf_conn *ct = (void *)skb_nfct(entry->skb);
  
  	if (ct && ((ct->status & flags) == IPS_DYING))
  		return true;
  #endif
  	return false;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
602
  static int
a5fedd43d   Florian Westphal   netfilter: move s...
603
604
  __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
  			struct nf_queue_entry *entry)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
605
  {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
606
  	struct sk_buff *nskb;
f15850861   Florian Westphal   netfilter: nfnetl...
607
  	int err = -ENOBUFS;
5863702a3   Eric Dumazet   netfilter: nfnetl...
608
  	__be32 *packet_id_ptr;
fdb694a01   Krishna Kumar   netfilter: Add fa...
609
  	int failopen = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
610

743326878   Gao feng   netfilter: nfnetl...
611
  	nskb = nfqnl_build_packet_message(net, queue, entry, &packet_id_ptr);
f15850861   Florian Westphal   netfilter: nfnetl...
612
613
  	if (nskb == NULL) {
  		err = -ENOMEM;
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
614
  		goto err_out;
f15850861   Florian Westphal   netfilter: nfnetl...
615
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
616
  	spin_lock_bh(&queue->lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
617

5da773a3e   Florian Westphal   netfilter: nfnetl...
618
619
  	if (nf_ct_drop_unconfirmed(entry))
  		goto err_out_free_nskb;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
620
  	if (queue->queue_total >= queue->queue_maxlen) {
fdb694a01   Krishna Kumar   netfilter: Add fa...
621
622
623
624
625
626
627
628
629
  		if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
  			failopen = 1;
  			err = 0;
  		} else {
  			queue->queue_dropped++;
  			net_warn_ratelimited("nf_queue: full at %d entries, dropping packets(s)
  ",
  					     queue->queue_total);
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
630
631
  		goto err_out_free_nskb;
  	}
5863702a3   Eric Dumazet   netfilter: nfnetl...
632
633
  	entry->id = ++queue->id_sequence;
  	*packet_id_ptr = htonl(entry->id);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
634
635
  
  	/* nfnetlink_unicast will either free the nskb or add it to a socket */
ee9211835   Pablo Neira Ayuso   netfilter: nfnetl...
636
  	err = nfnetlink_unicast(nskb, net, queue->peer_portid);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
637
  	if (err < 0) {
931401137   Pablo Neira Ayuso   netfilter: nfnetl...
638
639
640
641
642
643
  		if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
  			failopen = 1;
  			err = 0;
  		} else {
  			queue->queue_user_dropped++;
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
644
645
646
647
648
649
  		goto err_out_unlock;
  	}
  
  	__enqueue_entry(queue, entry);
  
  	spin_unlock_bh(&queue->lock);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
650
  	return 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
651
652
  
  err_out_free_nskb:
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
653
  	kfree_skb(nskb);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
654
655
  err_out_unlock:
  	spin_unlock_bh(&queue->lock);
fdb694a01   Krishna Kumar   netfilter: Add fa...
656
  	if (failopen)
368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
657
  		nfqnl_reinject(entry, NF_ACCEPT);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
658
  err_out:
f15850861   Florian Westphal   netfilter: nfnetl...
659
  	return err;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
660
  }
a5fedd43d   Florian Westphal   netfilter: move s...
661
662
663
664
  static struct nf_queue_entry *
  nf_queue_entry_dup(struct nf_queue_entry *e)
  {
  	struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC);
ed78d09d5   Florian Westphal   netfilter: make n...
665
666
667
  	if (entry)
  		nf_queue_entry_get_refs(entry);
  	return entry;
a5fedd43d   Florian Westphal   netfilter: move s...
668
  }
1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
669
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
a5fedd43d   Florian Westphal   netfilter: move s...
670
671
672
673
674
675
  /* When called from bridge netfilter, skb->data must point to MAC header
   * before calling skb_gso_segment(). Else, original MAC header is lost
   * and segmented skbs will be sent to wrong destination.
   */
  static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
  {
c4b0e771f   Florian Westphal   netfilter: avoid ...
676
  	if (nf_bridge_info_get(skb))
a5fedd43d   Florian Westphal   netfilter: move s...
677
678
679
680
681
  		__skb_push(skb, skb->network_header - skb->mac_header);
  }
  
  static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
  {
c4b0e771f   Florian Westphal   netfilter: avoid ...
682
  	if (nf_bridge_info_get(skb))
a5fedd43d   Florian Westphal   netfilter: move s...
683
684
685
686
687
688
  		__skb_pull(skb, skb->network_header - skb->mac_header);
  }
  #else
  #define nf_bridge_adjust_skb_data(s) do {} while (0)
  #define nf_bridge_adjust_segmented_data(s) do {} while (0)
  #endif
a5fedd43d   Florian Westphal   netfilter: move s...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  static int
  __nfqnl_enqueue_packet_gso(struct net *net, struct nfqnl_instance *queue,
  			   struct sk_buff *skb, struct nf_queue_entry *entry)
  {
  	int ret = -ENOMEM;
  	struct nf_queue_entry *entry_seg;
  
  	nf_bridge_adjust_segmented_data(skb);
  
  	if (skb->next == NULL) { /* last packet, no need to copy entry */
  		struct sk_buff *gso_skb = entry->skb;
  		entry->skb = skb;
  		ret = __nfqnl_enqueue_packet(net, queue, entry);
  		if (ret)
  			entry->skb = gso_skb;
  		return ret;
  	}
a8305bff6   David S. Miller   net: Add and use ...
706
  	skb_mark_not_on_list(skb);
a5fedd43d   Florian Westphal   netfilter: move s...
707
708
709
710
711
712
  
  	entry_seg = nf_queue_entry_dup(entry);
  	if (entry_seg) {
  		entry_seg->skb = skb;
  		ret = __nfqnl_enqueue_packet(net, queue, entry_seg);
  		if (ret)
dd3cc111f   Florian Westphal   netfilter: nf_que...
713
  			nf_queue_entry_free(entry_seg);
a5fedd43d   Florian Westphal   netfilter: move s...
714
715
716
717
718
719
720
721
722
  	}
  	return ret;
  }
  
  static int
  nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
  {
  	unsigned int queued;
  	struct nfqnl_instance *queue;
2670ee77c   Jason A. Donenfeld   net: netfilter: u...
723
  	struct sk_buff *skb, *segs, *nskb;
a5fedd43d   Florian Westphal   netfilter: move s...
724
  	int err = -ENOBUFS;
9dff2c966   Eric W. Biederman   netfilter: Use nf...
725
  	struct net *net = entry->state.net;
a5fedd43d   Florian Westphal   netfilter: move s...
726
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
e2361cb90   Aaron Conole   netfilter: Remove...
727
  	/* rcu_read_lock()ed by nf_hook_thresh */
a5fedd43d   Florian Westphal   netfilter: move s...
728
729
730
731
732
733
  	queue = instance_lookup(q, queuenum);
  	if (!queue)
  		return -ESRCH;
  
  	if (queue->copy_mode == NFQNL_COPY_NONE)
  		return -EINVAL;
a5fedd43d   Florian Westphal   netfilter: move s...
734
  	skb = entry->skb;
1d1de89b9   David S. Miller   netfilter: Use nf...
735
  	switch (entry->state.pf) {
a5fedd43d   Florian Westphal   netfilter: move s...
736
737
738
739
740
741
742
  	case NFPROTO_IPV4:
  		skb->protocol = htons(ETH_P_IP);
  		break;
  	case NFPROTO_IPV6:
  		skb->protocol = htons(ETH_P_IPV6);
  		break;
  	}
7b8dfe289   Pablo Neira Ayuso   netfilter: nfnetl...
743
744
  	if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb))
  		return __nfqnl_enqueue_packet(net, queue, entry);
a5fedd43d   Florian Westphal   netfilter: move s...
745
746
747
  	nf_bridge_adjust_skb_data(skb);
  	segs = skb_gso_segment(skb, 0);
  	/* Does not use PTR_ERR to limit the number of error codes that can be
ed78d09d5   Florian Westphal   netfilter: make n...
748
  	 * returned by nf_queue.  For instance, callers rely on -ESRCH to
a5fedd43d   Florian Westphal   netfilter: move s...
749
750
  	 * mean 'ignore this hook'.
  	 */
330966e50   Florian Westphal   net: make skb_gso...
751
  	if (IS_ERR_OR_NULL(segs))
a5fedd43d   Florian Westphal   netfilter: move s...
752
753
754
  		goto out_err;
  	queued = 0;
  	err = 0;
2670ee77c   Jason A. Donenfeld   net: netfilter: u...
755
  	skb_list_walk_safe(segs, segs, nskb) {
a5fedd43d   Florian Westphal   netfilter: move s...
756
757
758
759
760
761
762
  		if (err == 0)
  			err = __nfqnl_enqueue_packet_gso(net, queue,
  							segs, entry);
  		if (err == 0)
  			queued++;
  		else
  			kfree_skb(segs);
2670ee77c   Jason A. Donenfeld   net: netfilter: u...
763
  	}
a5fedd43d   Florian Westphal   netfilter: move s...
764
765
766
  
  	if (queued) {
  		if (err) /* some segments are already queued */
dd3cc111f   Florian Westphal   netfilter: nf_que...
767
  			nf_queue_entry_free(entry);
a5fedd43d   Florian Westphal   netfilter: move s...
768
769
770
771
772
773
774
  		kfree_skb(skb);
  		return 0;
  	}
   out_err:
  	nf_bridge_adjust_segmented_data(skb);
  	return err;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
775
  static int
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
776
  nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e, int diff)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
777
  {
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
778
  	struct sk_buff *nskb;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
779

d8a585d78   Patrick McHardy   [NETFILTER]: Use ...
780
781
782
783
  	if (diff < 0) {
  		if (pskb_trim(e->skb, data_len))
  			return -ENOMEM;
  	} else if (diff > 0) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
784
785
786
  		if (data_len > 0xFFFF)
  			return -EINVAL;
  		if (diff > skb_tailroom(e->skb)) {
9a732ed6d   Arnaud Ebalard   netfilter: {nfnet...
787
788
  			nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
  					       diff, GFP_ATOMIC);
5191d70f8   Arushi Singhal   netfilter: Replac...
789
  			if (!nskb)
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
790
  				return -ENOMEM;
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
791
792
  			kfree_skb(e->skb);
  			e->skb = nskb;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
793
794
795
  		}
  		skb_put(e->skb, diff);
  	}
2cf6bffc4   Florian Westphal   netfilter: replac...
796
  	if (skb_ensure_writable(e->skb, data_len))
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
797
  		return -ENOMEM;
27d7ff46a   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
798
  	skb_copy_to_linear_data(e->skb, data, data_len);
e7dfb09a3   Patrick McHardy   [NETFILTER]: Fix ...
799
  	e->skb->ip_summed = CHECKSUM_NONE;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
800
801
  	return 0;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
802
803
804
805
  static int
  nfqnl_set_mode(struct nfqnl_instance *queue,
  	       unsigned char mode, unsigned int range)
  {
c5de0dfde   Patrick McHardy   [NETFILTER]: nfne...
806
  	int status = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
807
808
  
  	spin_lock_bh(&queue->lock);
c5de0dfde   Patrick McHardy   [NETFILTER]: nfne...
809
810
811
812
813
814
815
816
817
  	switch (mode) {
  	case NFQNL_COPY_NONE:
  	case NFQNL_COPY_META:
  		queue->copy_mode = mode;
  		queue->copy_range = 0;
  		break;
  
  	case NFQNL_COPY_PACKET:
  		queue->copy_mode = mode;
9cefbbc9c   Florian Westphal   netfilter: nfnetl...
818
819
  		if (range == 0 || range > NFQNL_MAX_COPY_RANGE)
  			queue->copy_range = NFQNL_MAX_COPY_RANGE;
c5de0dfde   Patrick McHardy   [NETFILTER]: nfne...
820
821
822
823
824
825
826
827
  		else
  			queue->copy_range = range;
  		break;
  
  	default:
  		status = -EINVAL;
  
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
828
829
830
831
832
833
  	spin_unlock_bh(&queue->lock);
  
  	return status;
  }
  
  static int
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
834
  dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
835
  {
c4b0e771f   Florian Westphal   netfilter: avoid ...
836
837
838
839
840
841
842
843
844
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
  	int physinif, physoutif;
  
  	physinif = nf_bridge_get_physinif(entry->skb);
  	physoutif = nf_bridge_get_physoutif(entry->skb);
  
  	if (physinif == ifindex || physoutif == ifindex)
  		return 1;
  #endif
1d1de89b9   David S. Miller   netfilter: Use nf...
845
846
  	if (entry->state.in)
  		if (entry->state.in->ifindex == ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
847
  			return 1;
1d1de89b9   David S. Miller   netfilter: Use nf...
848
849
  	if (entry->state.out)
  		if (entry->state.out->ifindex == ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
850
  			return 1;
c737b7c45   Florian Westphal   netfilter: bridge...
851

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
852
853
854
855
856
857
  	return 0;
  }
  
  /* drop all packets with either indev or outdev == ifindex from all queue
   * instances */
  static void
e81796104   Gao feng   netfilter: nfnetl...
858
  nfqnl_dev_drop(struct net *net, int ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
859
860
  {
  	int i;
e81796104   Gao feng   netfilter: nfnetl...
861
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
862

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
863
  	rcu_read_lock();
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
864

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
865
  	for (i = 0; i < INSTANCE_BUCKETS; i++) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
866
  		struct nfqnl_instance *inst;
e81796104   Gao feng   netfilter: nfnetl...
867
  		struct hlist_head *head = &q->instance_table[i];
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
868

b67bfe0d4   Sasha Levin   hlist: drop the n...
869
  		hlist_for_each_entry_rcu(inst, head, hlist)
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
870
  			nfqnl_flush(inst, dev_cmp, ifindex);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
871
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
872
  	rcu_read_unlock();
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
873
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
874
875
876
877
  static int
  nfqnl_rcv_dev_event(struct notifier_block *this,
  		    unsigned long event, void *ptr)
  {
351638e7d   Jiri Pirko   net: pass info st...
878
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
879
880
881
  
  	/* Drop any packets associated with the downed device */
  	if (event == NETDEV_DOWN)
e81796104   Gao feng   netfilter: nfnetl...
882
  		nfqnl_dev_drop(dev_net(dev), dev->ifindex);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
883
884
885
886
887
888
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block nfqnl_dev_notifier = {
  	.notifier_call	= nfqnl_rcv_dev_event,
  };
26888dfd7   Florian Westphal   netfilter: core: ...
889
  static void nfqnl_nf_hook_drop(struct net *net)
8405a8fff   Eric W. Biederman   netfilter: nf_qeu...
890
891
892
  {
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
  	int i;
8405a8fff   Eric W. Biederman   netfilter: nf_qeu...
893
894
895
  	for (i = 0; i < INSTANCE_BUCKETS; i++) {
  		struct nfqnl_instance *inst;
  		struct hlist_head *head = &q->instance_table[i];
26888dfd7   Florian Westphal   netfilter: core: ...
896
  		hlist_for_each_entry_rcu(inst, head, hlist)
039b40ee5   Florian Westphal   netfilter: nf_que...
897
  			nfqnl_flush(inst, NULL, 0);
8405a8fff   Eric W. Biederman   netfilter: nf_qeu...
898
  	}
8405a8fff   Eric W. Biederman   netfilter: nf_qeu...
899
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
900
901
902
903
904
  static int
  nfqnl_rcv_nl_event(struct notifier_block *this,
  		   unsigned long event, void *ptr)
  {
  	struct netlink_notify *n = ptr;
e81796104   Gao feng   netfilter: nfnetl...
905
  	struct nfnl_queue_net *q = nfnl_queue_pernet(n->net);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
906

dee5817e8   Patrick McHardy   netfilter: remove...
907
  	if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
908
  		int i;
15e473046   Eric W. Biederman   netlink: Rename p...
909
  		/* destroy all instances for this portid */
e81796104   Gao feng   netfilter: nfnetl...
910
  		spin_lock(&q->instances_lock);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
911
  		for (i = 0; i < INSTANCE_BUCKETS; i++) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
912
  			struct hlist_node *t2;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
913
  			struct nfqnl_instance *inst;
e81796104   Gao feng   netfilter: nfnetl...
914
  			struct hlist_head *head = &q->instance_table[i];
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
915

b67bfe0d4   Sasha Levin   hlist: drop the n...
916
  			hlist_for_each_entry_safe(inst, t2, head, hlist) {
e81796104   Gao feng   netfilter: nfnetl...
917
  				if (n->portid == inst->peer_portid)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
918
919
920
  					__instance_destroy(inst);
  			}
  		}
e81796104   Gao feng   netfilter: nfnetl...
921
  		spin_unlock(&q->instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
922
923
924
925
926
927
928
  	}
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block nfqnl_rtnl_notifier = {
  	.notifier_call	= nfqnl_rcv_nl_event,
  };
8d45ff22f   Stephane Bryant   netfilter: bridge...
929
930
931
932
  static const struct nla_policy nfqa_vlan_policy[NFQA_VLAN_MAX + 1] = {
  	[NFQA_VLAN_TCI]		= { .type = NLA_U16},
  	[NFQA_VLAN_PROTO]	= { .type = NLA_U16},
  };
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
933
934
935
936
  static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
  	[NFQA_VERDICT_HDR]	= { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
  	[NFQA_MARK]		= { .type = NLA_U32 },
  	[NFQA_PAYLOAD]		= { .type = NLA_UNSPEC },
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
937
  	[NFQA_CT]		= { .type = NLA_UNSPEC },
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
938
  	[NFQA_EXP]		= { .type = NLA_UNSPEC },
8d45ff22f   Stephane Bryant   netfilter: bridge...
939
  	[NFQA_VLAN]		= { .type = NLA_NESTED },
838ab6364   Harald Welte   [NETFILTER]: Add ...
940
  };
97d32cf94   Florian Westphal   netfilter: nfnetl...
941
942
943
944
  static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
  	[NFQA_VERDICT_HDR]	= { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
  	[NFQA_MARK]		= { .type = NLA_U32 },
  };
e81796104   Gao feng   netfilter: nfnetl...
945
  static struct nfqnl_instance *
cc6bc4486   Richard Weinberger   netfilter: Fix po...
946
  verdict_instance_lookup(struct nfnl_queue_net *q, u16 queue_num, u32 nlportid)
97d32cf94   Florian Westphal   netfilter: nfnetl...
947
948
  {
  	struct nfqnl_instance *queue;
e81796104   Gao feng   netfilter: nfnetl...
949
  	queue = instance_lookup(q, queue_num);
97d32cf94   Florian Westphal   netfilter: nfnetl...
950
951
  	if (!queue)
  		return ERR_PTR(-ENODEV);
15e473046   Eric W. Biederman   netlink: Rename p...
952
  	if (queue->peer_portid != nlportid)
97d32cf94   Florian Westphal   netfilter: nfnetl...
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
  		return ERR_PTR(-EPERM);
  
  	return queue;
  }
  
  static struct nfqnl_msg_verdict_hdr*
  verdicthdr_get(const struct nlattr * const nfqa[])
  {
  	struct nfqnl_msg_verdict_hdr *vhdr;
  	unsigned int verdict;
  
  	if (!nfqa[NFQA_VERDICT_HDR])
  		return NULL;
  
  	vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
c6675233f   Florian Westphal   netfilter: nf_que...
968
969
  	verdict = ntohl(vhdr->verdict) & NF_VERDICT_MASK;
  	if (verdict > NF_MAX_VERDICT || verdict == NF_STOLEN)
97d32cf94   Florian Westphal   netfilter: nfnetl...
970
971
972
973
974
975
976
977
  		return NULL;
  	return vhdr;
  }
  
  static int nfq_id_after(unsigned int id, unsigned int max)
  {
  	return (int)(id - max) > 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
978
979
980
  static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl,
  				    struct sk_buff *skb,
  				    const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
981
982
  			            const struct nlattr * const nfqa[],
  				    struct netlink_ext_ack *extack)
97d32cf94   Florian Westphal   netfilter: nfnetl...
983
  {
3da07c0c2   David S. Miller   netfilter: nfnetl...
984
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
97d32cf94   Florian Westphal   netfilter: nfnetl...
985
986
987
988
989
990
  	struct nf_queue_entry *entry, *tmp;
  	unsigned int verdict, maxid;
  	struct nfqnl_msg_verdict_hdr *vhdr;
  	struct nfqnl_instance *queue;
  	LIST_HEAD(batch_list);
  	u16 queue_num = ntohs(nfmsg->res_id);
e81796104   Gao feng   netfilter: nfnetl...
991
992
993
994
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
  
  	queue = verdict_instance_lookup(q, queue_num,
  					NETLINK_CB(skb).portid);
97d32cf94   Florian Westphal   netfilter: nfnetl...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  	if (IS_ERR(queue))
  		return PTR_ERR(queue);
  
  	vhdr = verdicthdr_get(nfqa);
  	if (!vhdr)
  		return -EINVAL;
  
  	verdict = ntohl(vhdr->verdict);
  	maxid = ntohl(vhdr->id);
  
  	spin_lock_bh(&queue->lock);
  
  	list_for_each_entry_safe(entry, tmp, &queue->queue_list, list) {
  		if (nfq_id_after(entry->id, maxid))
  			break;
  		__dequeue_entry(queue, entry);
  		list_add_tail(&entry->list, &batch_list);
  	}
  
  	spin_unlock_bh(&queue->lock);
  
  	if (list_empty(&batch_list))
  		return -ENOENT;
  
  	list_for_each_entry_safe(entry, tmp, &batch_list, list) {
  		if (nfqa[NFQA_MARK])
  			entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
1022
1023
  
  		nfqnl_reinject(entry, verdict);
97d32cf94   Florian Westphal   netfilter: nfnetl...
1024
1025
1026
  	}
  	return 0;
  }
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1027
  static struct nf_conn *nfqnl_ct_parse(struct nfnl_ct_hook *nfnl_ct,
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
1028
1029
1030
1031
1032
1033
  				      const struct nlmsghdr *nlh,
  				      const struct nlattr * const nfqa[],
  				      struct nf_queue_entry *entry,
  				      enum ip_conntrack_info *ctinfo)
  {
  	struct nf_conn *ct;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1034
  	ct = nfnl_ct->get_ct(entry->skb, ctinfo);
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
1035
1036
  	if (ct == NULL)
  		return NULL;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1037
  	if (nfnl_ct->parse(nfqa[NFQA_CT], ct) < 0)
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
1038
1039
1040
  		return NULL;
  
  	if (nfqa[NFQA_EXP])
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1041
  		nfnl_ct->attach_expect(nfqa[NFQA_EXP], ct,
b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
1042
1043
1044
1045
  				      NETLINK_CB(entry->skb).portid,
  				      nlmsg_report(nlh));
  	return ct;
  }
8d45ff22f   Stephane Bryant   netfilter: bridge...
1046
1047
1048
1049
1050
1051
  static int nfqa_parse_bridge(struct nf_queue_entry *entry,
  			     const struct nlattr * const nfqa[])
  {
  	if (nfqa[NFQA_VLAN]) {
  		struct nlattr *tb[NFQA_VLAN_MAX + 1];
  		int err;
8cb081746   Johannes Berg   netlink: make val...
1052
1053
1054
  		err = nla_parse_nested_deprecated(tb, NFQA_VLAN_MAX,
  						  nfqa[NFQA_VLAN],
  						  nfqa_vlan_policy, NULL);
8d45ff22f   Stephane Bryant   netfilter: bridge...
1055
1056
1057
1058
1059
  		if (err < 0)
  			return err;
  
  		if (!tb[NFQA_VLAN_TCI] || !tb[NFQA_VLAN_PROTO])
  			return -EINVAL;
82eea4cfe   MichaÅ‚ MirosÅ‚aw   nfnetlink/queue: ...
1060
1061
1062
  		__vlan_hwaccel_put_tag(entry->skb,
  			nla_get_be16(tb[NFQA_VLAN_PROTO]),
  			ntohs(nla_get_be16(tb[NFQA_VLAN_TCI])));
8d45ff22f   Stephane Bryant   netfilter: bridge...
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  	}
  
  	if (nfqa[NFQA_L2HDR]) {
  		int mac_header_len = entry->skb->network_header -
  			entry->skb->mac_header;
  
  		if (mac_header_len != nla_len(nfqa[NFQA_L2HDR]))
  			return -EINVAL;
  		else if (mac_header_len > 0)
  			memcpy(skb_mac_header(entry->skb),
  			       nla_data(nfqa[NFQA_L2HDR]),
  			       mac_header_len);
  	}
  
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1079
1080
1081
  static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
  			      struct sk_buff *skb,
  			      const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1082
1083
  			      const struct nlattr * const nfqa[],
  			      struct netlink_ext_ack *extack)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1084
  {
3da07c0c2   David S. Miller   netfilter: nfnetl...
1085
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1086
  	u_int16_t queue_num = ntohs(nfmsg->res_id);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1087
1088
1089
  	struct nfqnl_msg_verdict_hdr *vhdr;
  	struct nfqnl_instance *queue;
  	unsigned int verdict;
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
1090
  	struct nf_queue_entry *entry;
3f649ab72   Kees Cook   treewide: Remove ...
1091
  	enum ip_conntrack_info ctinfo;
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1092
  	struct nfnl_ct_hook *nfnl_ct;
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
1093
  	struct nf_conn *ct = NULL;
e81796104   Gao feng   netfilter: nfnetl...
1094
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
8d45ff22f   Stephane Bryant   netfilter: bridge...
1095
  	int err;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1096

00a3101f5   Liping Zhang   netfilter: nfnetl...
1097
1098
  	queue = verdict_instance_lookup(q, queue_num,
  					NETLINK_CB(skb).portid);
97d32cf94   Florian Westphal   netfilter: nfnetl...
1099
1100
  	if (IS_ERR(queue))
  		return PTR_ERR(queue);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1101

97d32cf94   Florian Westphal   netfilter: nfnetl...
1102
1103
  	vhdr = verdicthdr_get(nfqa);
  	if (!vhdr)
84a797dd0   Eric Dumazet   netfilter: nfnetl...
1104
  		return -EINVAL;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1105

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1106
  	verdict = ntohl(vhdr->verdict);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
1107
  	entry = find_dequeue_entry(queue, ntohl(vhdr->id));
84a797dd0   Eric Dumazet   netfilter: nfnetl...
1108
1109
  	if (entry == NULL)
  		return -ENOENT;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1110

8e662164a   Arnd Bergmann   netfilter: nfnetl...
1111
1112
  	/* rcu lock already held from nfnl->call_rcu. */
  	nfnl_ct = rcu_dereference(nfnl_ct_hook);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
1113
  	if (nfqa[NFQA_CT]) {
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1114
1115
  		if (nfnl_ct != NULL)
  			ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo);
bd0779370   Pablo Neira Ayuso   netfilter: nfnetl...
1116
  	}
9cb017665   Pablo Neira Ayuso   netfilter: add gl...
1117

8d45ff22f   Stephane Bryant   netfilter: bridge...
1118
1119
1120
1121
1122
  	if (entry->state.pf == PF_BRIDGE) {
  		err = nfqa_parse_bridge(entry, nfqa);
  		if (err < 0)
  			return err;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1123
  	if (nfqa[NFQA_PAYLOAD]) {
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
1124
1125
  		u16 payload_len = nla_len(nfqa[NFQA_PAYLOAD]);
  		int diff = payload_len - entry->skb->len;
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1126
  		if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
1127
  				 payload_len, entry, diff) < 0)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1128
  			verdict = NF_DROP;
8c88f87cb   Pablo Neira Ayuso   netfilter: nfnetl...
1129

b7bd1809e   Pablo Neira Ayuso   netfilter: nfnetl...
1130
  		if (ct && diff)
a4b4766c3   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1131
  			nfnl_ct->seq_adjust(entry->skb, ct, ctinfo, diff);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1132
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1133
  	if (nfqa[NFQA_MARK])
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
1134
  		entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1135

368982cd7   Pablo Neira Ayuso   netfilter: nfnetl...
1136
  	nfqnl_reinject(entry, verdict);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1137
1138
  	return 0;
  }
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1139
1140
  static int nfqnl_recv_unsupp(struct net *net, struct sock *ctnl,
  			     struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1141
1142
  			     const struct nlattr * const nfqa[],
  			     struct netlink_ext_ack *extack)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1143
1144
1145
  {
  	return -ENOTSUPP;
  }
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
1146
1147
1148
  static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
  	[NFQA_CFG_CMD]		= { .len = sizeof(struct nfqnl_msg_config_cmd) },
  	[NFQA_CFG_PARAMS]	= { .len = sizeof(struct nfqnl_msg_config_params) },
ba062ebb2   Eric Dumazet   netfilter: nf_que...
1149
1150
1151
  	[NFQA_CFG_QUEUE_MAXLEN]	= { .type = NLA_U32 },
  	[NFQA_CFG_MASK]		= { .type = NLA_U32 },
  	[NFQA_CFG_FLAGS]	= { .type = NLA_U32 },
838ab6364   Harald Welte   [NETFILTER]: Add ...
1152
  };
e3ac52981   Patrick McHardy   [NETFILTER]: nf_q...
1153
  static const struct nf_queue_handler nfqh = {
d4ef38354   Arushi Singhal   netfilter: Remove...
1154
1155
  	.outfn		= nfqnl_enqueue_packet,
  	.nf_hook_drop	= nfqnl_nf_hook_drop,
bbd86b9fc   Harald Welte   [NETFILTER]: add ...
1156
  };
7b8002a15   Pablo Neira Ayuso   netfilter: nfnetl...
1157
1158
  static int nfqnl_recv_config(struct net *net, struct sock *ctnl,
  			     struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b6   Pablo Neira Ayuso   netfilter: nfnetl...
1159
1160
  			     const struct nlattr * const nfqa[],
  			     struct netlink_ext_ack *extack)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1161
  {
3da07c0c2   David S. Miller   netfilter: nfnetl...
1162
  	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1163
1164
  	u_int16_t queue_num = ntohs(nfmsg->res_id);
  	struct nfqnl_instance *queue;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1165
  	struct nfqnl_msg_config_cmd *cmd = NULL;
e81796104   Gao feng   netfilter: nfnetl...
1166
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1167
  	__u32 flags = 0, mask = 0;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1168
  	int ret = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1169

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1170
1171
  	if (nfqa[NFQA_CFG_CMD]) {
  		cmd = nla_data(nfqa[NFQA_CFG_CMD]);
0360ae412   Florian Westphal   netfilter: kill s...
1172
  		/* Obsolete commands without queue context */
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1173
  		switch (cmd->command) {
0360ae412   Florian Westphal   netfilter: kill s...
1174
1175
  		case NFQNL_CFG_CMD_PF_BIND: return 0;
  		case NFQNL_CFG_CMD_PF_UNBIND: return 0;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1176
  		}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1177
  	}
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
  	/* Check if we support these flags in first place, dependencies should
  	 * be there too not to break atomicity.
  	 */
  	if (nfqa[NFQA_CFG_FLAGS]) {
  		if (!nfqa[NFQA_CFG_MASK]) {
  			/* A mask is needed to specify which flags are being
  			 * changed.
  			 */
  			return -EINVAL;
  		}
  
  		flags = ntohl(nla_get_be32(nfqa[NFQA_CFG_FLAGS]));
  		mask = ntohl(nla_get_be32(nfqa[NFQA_CFG_MASK]));
  
  		if (flags >= NFQA_CFG_F_MAX)
  			return -EOPNOTSUPP;
  
  #if !IS_ENABLED(CONFIG_NETWORK_SECMARK)
  		if (flags & mask & NFQA_CFG_F_SECCTX)
  			return -EOPNOTSUPP;
  #endif
71b2e5f5c   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
  		if ((flags & mask & NFQA_CFG_F_CONNTRACK) &&
  		    !rcu_access_pointer(nfnl_ct_hook)) {
  #ifdef CONFIG_MODULES
  			nfnl_unlock(NFNL_SUBSYS_QUEUE);
  			request_module("ip_conntrack_netlink");
  			nfnl_lock(NFNL_SUBSYS_QUEUE);
  			if (rcu_access_pointer(nfnl_ct_hook))
  				return -EAGAIN;
  #endif
  			return -EOPNOTSUPP;
  		}
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1210
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1211
  	rcu_read_lock();
e81796104   Gao feng   netfilter: nfnetl...
1212
  	queue = instance_lookup(q, queue_num);
15e473046   Eric W. Biederman   netlink: Rename p...
1213
  	if (queue && queue->peer_portid != NETLINK_CB(skb).portid) {
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
1214
  		ret = -EPERM;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1215
  		goto err_out_unlock;
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
1216
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1217
  	if (cmd != NULL) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1218
1219
  		switch (cmd->command) {
  		case NFQNL_CFG_CMD_BIND:
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1220
1221
1222
1223
  			if (queue) {
  				ret = -EBUSY;
  				goto err_out_unlock;
  			}
e81796104   Gao feng   netfilter: nfnetl...
1224
1225
  			queue = instance_create(q, queue_num,
  						NETLINK_CB(skb).portid);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
1226
1227
  			if (IS_ERR(queue)) {
  				ret = PTR_ERR(queue);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1228
1229
  				goto err_out_unlock;
  			}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1230
1231
  			break;
  		case NFQNL_CFG_CMD_UNBIND:
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1232
1233
1234
1235
  			if (!queue) {
  				ret = -ENODEV;
  				goto err_out_unlock;
  			}
e81796104   Gao feng   netfilter: nfnetl...
1236
  			instance_destroy(q, queue);
17bc6b488   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1237
  			goto err_out_unlock;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1238
  		case NFQNL_CFG_CMD_PF_BIND:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1239
  		case NFQNL_CFG_CMD_PF_UNBIND:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1240
1241
  			break;
  		default:
cd21f0ac4   Patrick McHardy   [NETFILTER]: nfne...
1242
  			ret = -ENOTSUPP;
21c3c971d   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1243
  			goto err_out_unlock;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1244
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1245
  	}
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1246
1247
1248
1249
  	if (!queue) {
  		ret = -ENODEV;
  		goto err_out_unlock;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1250
  	if (nfqa[NFQA_CFG_PARAMS]) {
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1251
1252
  		struct nfqnl_msg_config_params *params =
  			nla_data(nfqa[NFQA_CFG_PARAMS]);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1253
1254
1255
1256
  
  		nfqnl_set_mode(queue, params->copy_mode,
  				ntohl(params->copy_range));
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
1257
  	if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
60d2c7f9a   Ken-ichirou MATSUZAWA   netfilter: nfnetl...
1258
  		__be32 *queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
1259

829e17a1a   Eric Leblond   [NETFILTER]: nfne...
1260
1261
1262
1263
  		spin_lock_bh(&queue->lock);
  		queue->queue_maxlen = ntohl(*queue_maxlen);
  		spin_unlock_bh(&queue->lock);
  	}
fdb694a01   Krishna Kumar   netfilter: Add fa...
1264
  	if (nfqa[NFQA_CFG_FLAGS]) {
fdb694a01   Krishna Kumar   netfilter: Add fa...
1265
1266
1267
1268
1269
  		spin_lock_bh(&queue->lock);
  		queue->flags &= ~mask;
  		queue->flags |= flags & mask;
  		spin_unlock_bh(&queue->lock);
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
1270
1271
  err_out_unlock:
  	rcu_read_unlock();
838ab6364   Harald Welte   [NETFILTER]: Add ...
1272
  	return ret;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1273
  }
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
1274
  static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
84a797dd0   Eric Dumazet   netfilter: nfnetl...
1275
  	[NFQNL_MSG_PACKET]	= { .call_rcu = nfqnl_recv_unsupp,
37d2e7a20   Harald Welte   [NETFILTER] nfnet...
1276
  				    .attr_count = NFQA_MAX, },
84a797dd0   Eric Dumazet   netfilter: nfnetl...
1277
  	[NFQNL_MSG_VERDICT]	= { .call_rcu = nfqnl_recv_verdict,
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
1278
1279
  				    .attr_count = NFQA_MAX,
  				    .policy = nfqa_verdict_policy },
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1280
  	[NFQNL_MSG_CONFIG]	= { .call = nfqnl_recv_config,
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
1281
1282
  				    .attr_count = NFQA_CFG_MAX,
  				    .policy = nfqa_cfg_policy },
97d32cf94   Florian Westphal   netfilter: nfnetl...
1283
1284
1285
  	[NFQNL_MSG_VERDICT_BATCH]={ .call_rcu = nfqnl_recv_verdict_batch,
  				    .attr_count = NFQA_MAX,
  				    .policy = nfqa_verdict_batch_policy },
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1286
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
1287
  static const struct nfnetlink_subsystem nfqnl_subsys = {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1288
1289
1290
  	.name		= "nf_queue",
  	.subsys_id	= NFNL_SUBSYS_QUEUE,
  	.cb_count	= NFQNL_MSG_MAX,
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1291
1292
  	.cb		= nfqnl_cb,
  };
838ab6364   Harald Welte   [NETFILTER]: Add ...
1293
1294
  #ifdef CONFIG_PROC_FS
  struct iter_state {
e81796104   Gao feng   netfilter: nfnetl...
1295
  	struct seq_net_private p;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1296
1297
1298
1299
1300
1301
  	unsigned int bucket;
  };
  
  static struct hlist_node *get_first(struct seq_file *seq)
  {
  	struct iter_state *st = seq->private;
e81796104   Gao feng   netfilter: nfnetl...
1302
1303
  	struct net *net;
  	struct nfnl_queue_net *q;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1304
1305
1306
  
  	if (!st)
  		return NULL;
e81796104   Gao feng   netfilter: nfnetl...
1307
1308
  	net = seq_file_net(seq);
  	q = nfnl_queue_pernet(net);
838ab6364   Harald Welte   [NETFILTER]: Add ...
1309
  	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
e81796104   Gao feng   netfilter: nfnetl...
1310
1311
  		if (!hlist_empty(&q->instance_table[st->bucket]))
  			return q->instance_table[st->bucket].first;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1312
1313
1314
1315
1316
1317
1318
  	}
  	return NULL;
  }
  
  static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
  {
  	struct iter_state *st = seq->private;
e81796104   Gao feng   netfilter: nfnetl...
1319
  	struct net *net = seq_file_net(seq);
838ab6364   Harald Welte   [NETFILTER]: Add ...
1320
1321
1322
  
  	h = h->next;
  	while (!h) {
e81796104   Gao feng   netfilter: nfnetl...
1323
  		struct nfnl_queue_net *q;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1324
1325
  		if (++st->bucket >= INSTANCE_BUCKETS)
  			return NULL;
e81796104   Gao feng   netfilter: nfnetl...
1326
1327
  		q = nfnl_queue_pernet(net);
  		h = q->instance_table[st->bucket].first;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
  	}
  	return h;
  }
  
  static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
  {
  	struct hlist_node *head;
  	head = get_first(seq);
  
  	if (head)
  		while (pos && (head = get_next(seq, head)))
  			pos--;
  	return pos ? NULL : head;
  }
e81796104   Gao feng   netfilter: nfnetl...
1342
1343
  static void *seq_start(struct seq_file *s, loff_t *pos)
  	__acquires(nfnl_queue_pernet(seq_file_net(s))->instances_lock)
838ab6364   Harald Welte   [NETFILTER]: Add ...
1344
  {
e81796104   Gao feng   netfilter: nfnetl...
1345
1346
  	spin_lock(&nfnl_queue_pernet(seq_file_net(s))->instances_lock);
  	return get_idx(s, *pos);
838ab6364   Harald Welte   [NETFILTER]: Add ...
1347
1348
1349
1350
1351
1352
1353
1354
1355
  }
  
  static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
  {
  	(*pos)++;
  	return get_next(s, v);
  }
  
  static void seq_stop(struct seq_file *s, void *v)
e81796104   Gao feng   netfilter: nfnetl...
1356
  	__releases(nfnl_queue_pernet(seq_file_net(s))->instances_lock)
838ab6364   Harald Welte   [NETFILTER]: Add ...
1357
  {
e81796104   Gao feng   netfilter: nfnetl...
1358
  	spin_unlock(&nfnl_queue_pernet(seq_file_net(s))->instances_lock);
838ab6364   Harald Welte   [NETFILTER]: Add ...
1359
1360
1361
1362
1363
  }
  
  static int seq_show(struct seq_file *s, void *v)
  {
  	const struct nfqnl_instance *inst = v;
6b46f7b7e   Richard Weinberger   netfilter: Fix fo...
1364
1365
  	seq_printf(s, "%5u %6u %5u %1u %5u %5u %5u %8u %2d
  ",
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
1366
1367
1368
1369
1370
  		   inst->queue_num,
  		   inst->peer_portid, inst->queue_total,
  		   inst->copy_mode, inst->copy_range,
  		   inst->queue_dropped, inst->queue_user_dropped,
  		   inst->id_sequence, 1);
861fb1078   Joe Perches   netfilter: Use co...
1371
  	return 0;
838ab6364   Harald Welte   [NETFILTER]: Add ...
1372
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
1373
  static const struct seq_operations nfqnl_seq_ops = {
838ab6364   Harald Welte   [NETFILTER]: Add ...
1374
1375
1376
1377
1378
  	.start	= seq_start,
  	.next	= seq_next,
  	.stop	= seq_stop,
  	.show	= seq_show,
  };
838ab6364   Harald Welte   [NETFILTER]: Add ...
1379
  #endif /* PROC_FS */
e81796104   Gao feng   netfilter: nfnetl...
1380
  static int __net_init nfnl_queue_net_init(struct net *net)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1381
  {
e81796104   Gao feng   netfilter: nfnetl...
1382
1383
  	unsigned int i;
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
1384

838ab6364   Harald Welte   [NETFILTER]: Add ...
1385
  	for (i = 0; i < INSTANCE_BUCKETS; i++)
e81796104   Gao feng   netfilter: nfnetl...
1386
1387
1388
1389
1390
  		INIT_HLIST_HEAD(&q->instance_table[i]);
  
  	spin_lock_init(&q->instances_lock);
  
  #ifdef CONFIG_PROC_FS
c35063722   Christoph Hellwig   proc: introduce p...
1391
1392
  	if (!proc_create_net("nfnetlink_queue", 0440, net->nf.proc_netfilter,
  			&nfqnl_seq_ops, sizeof(struct iter_state)))
e81796104   Gao feng   netfilter: nfnetl...
1393
1394
  		return -ENOMEM;
  #endif
dc3ee32e9   Eric W. Biederman   netfilter: nf_que...
1395
  	nf_register_queue_handler(net, &nfqh);
e81796104   Gao feng   netfilter: nfnetl...
1396
1397
1398
1399
1400
  	return 0;
  }
  
  static void __net_exit nfnl_queue_net_exit(struct net *net)
  {
613d0776d   Vasily Averin   netfilter: exit_n...
1401
1402
  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
  	unsigned int i;
dc3ee32e9   Eric W. Biederman   netfilter: nf_que...
1403
  	nf_unregister_queue_handler(net);
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
1404
  #ifdef CONFIG_PROC_FS
e81796104   Gao feng   netfilter: nfnetl...
1405
  	remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
1406
  #endif
613d0776d   Vasily Averin   netfilter: exit_n...
1407
1408
  	for (i = 0; i < INSTANCE_BUCKETS; i++)
  		WARN_ON_ONCE(!hlist_empty(&q->instance_table[i]));
e81796104   Gao feng   netfilter: nfnetl...
1409
  }
dc3ee32e9   Eric W. Biederman   netfilter: nf_que...
1410
1411
1412
1413
  static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list)
  {
  	synchronize_rcu();
  }
e81796104   Gao feng   netfilter: nfnetl...
1414
  static struct pernet_operations nfnl_queue_net_ops = {
dc3ee32e9   Eric W. Biederman   netfilter: nf_que...
1415
1416
1417
1418
1419
  	.init		= nfnl_queue_net_init,
  	.exit		= nfnl_queue_net_exit,
  	.exit_batch	= nfnl_queue_net_exit_batch,
  	.id		= &nfnl_queue_net_id,
  	.size		= sizeof(struct nfnl_queue_net),
e81796104   Gao feng   netfilter: nfnetl...
1420
1421
1422
1423
  };
  
  static int __init nfnetlink_queue_init(void)
  {
3bfe04980   Francesco Ruggeri   netfilter: nfnetl...
1424
1425
1426
1427
  	int status;
  
  	status = register_pernet_subsys(&nfnl_queue_net_ops);
  	if (status < 0) {
5191d70f8   Arushi Singhal   netfilter: Replac...
1428
1429
  		pr_err("failed to register pernet ops
  ");
3bfe04980   Francesco Ruggeri   netfilter: nfnetl...
1430
1431
  		goto out;
  	}
838ab6364   Harald Welte   [NETFILTER]: Add ...
1432

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1433
1434
1435
  	netlink_register_notifier(&nfqnl_rtnl_notifier);
  	status = nfnetlink_subsys_register(&nfqnl_subsys);
  	if (status < 0) {
5191d70f8   Arushi Singhal   netfilter: Replac...
1436
1437
  		pr_err("failed to create netlink socket
  ");
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1438
1439
  		goto cleanup_netlink_notifier;
  	}
4e6577de7   Gao Feng   netfilter: Add th...
1440
1441
  	status = register_netdevice_notifier(&nfqnl_dev_notifier);
  	if (status < 0) {
5191d70f8   Arushi Singhal   netfilter: Replac...
1442
1443
  		pr_err("failed to register netdevice notifier
  ");
4e6577de7   Gao Feng   netfilter: Add th...
1444
1445
  		goto cleanup_netlink_subsys;
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1446
  	return status;
4e6577de7   Gao Feng   netfilter: Add th...
1447
1448
  cleanup_netlink_subsys:
  	nfnetlink_subsys_unregister(&nfqnl_subsys);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1449
1450
  cleanup_netlink_notifier:
  	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
639e077b4   Nikolay Borisov   netfilter: nfnetl...
1451
  	unregister_pernet_subsys(&nfnl_queue_net_ops);
3bfe04980   Francesco Ruggeri   netfilter: nfnetl...
1452
  out:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1453
1454
  	return status;
  }
65b4b4e81   Andrew Morton   [NETFILTER]: Rena...
1455
  static void __exit nfnetlink_queue_fini(void)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1456
  {
32292a7ff   Patrick McHardy   [NETFILTER]: Fix ...
1457
  	unregister_netdevice_notifier(&nfqnl_dev_notifier);
32292a7ff   Patrick McHardy   [NETFILTER]: Fix ...
1458
1459
  	nfnetlink_subsys_unregister(&nfqnl_subsys);
  	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
3bfe04980   Francesco Ruggeri   netfilter: nfnetl...
1460
  	unregister_pernet_subsys(&nfnl_queue_net_ops);
67137f3cc   Jesper Dangaard Brouer   nfnetlink_queue: ...
1461
1462
  
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1463
1464
1465
1466
1467
1468
  }
  
  MODULE_DESCRIPTION("netfilter packet queue handler");
  MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_QUEUE);
65b4b4e81   Andrew Morton   [NETFILTER]: Rena...
1469
1470
  module_init(nfnetlink_queue_init);
  module_exit(nfnetlink_queue_fini);