Blame view

net/netfilter/nfnetlink_queue.c 24.2 KB
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
1
2
  /*
   * This is a module which is used for queueing packets and communicating with
67137f3cc   Jesper Dangaard Brouer   nfnetlink_queue: ...
3
   * userspace via nfnetlink.
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
4
5
   *
   * (C) 2005 by Harald Welte <laforge@netfilter.org>
4ad9d4fa9   Patrick McHardy   [NETFILTER]: nfne...
6
   * (C) 2007 by Patrick McHardy <kaber@trash.net>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   *
   * 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>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   */
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/init.h>
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
22
23
24
  #include <linux/notifier.h>
  #include <linux/netdevice.h>
  #include <linux/netfilter.h>
838ab6364   Harald Welte   [NETFILTER]: Add ...
25
  #include <linux/proc_fs.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
26
27
28
29
30
31
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv6.h>
  #include <linux/netfilter/nfnetlink.h>
  #include <linux/netfilter/nfnetlink_queue.h>
  #include <linux/list.h>
  #include <net/sock.h>
c01cd429f   Patrick McHardy   [NETFILTER]: nf_q...
32
  #include <net/netfilter/nf_queue.h>
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
33

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

fbcd923c3   Harald Welte   [NETFILTER]: add ...
36
37
38
  #ifdef CONFIG_BRIDGE_NETFILTER
  #include "../bridge/br_private.h"
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
39
  #define NFQNL_QMAX_DEFAULT 1024
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
40
41
  struct nfqnl_instance {
  	struct hlist_node hlist;		/* global list of queues */
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
42
  	struct rcu_head rcu;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
43
44
45
46
  
  	int peer_pid;
  	unsigned int queue_maxlen;
  	unsigned int copy_range;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
47
48
  	unsigned int queue_dropped;
  	unsigned int queue_user_dropped;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
49
50
51
  
  	u_int16_t queue_num;			/* number of this queue */
  	u_int8_t copy_mode;
c463ac972   Eric Dumazet   netfilter: nfnetl...
52
53
54
55
56
57
  /*
   * Following fields are dirtied for each queued packet,
   * keep them in same cache line if possible.
   */
  	spinlock_t	lock;
  	unsigned int	queue_total;
5863702a3   Eric Dumazet   netfilter: nfnetl...
58
  	unsigned int	id_sequence;		/* 'sequence' of pkt ids */
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
59
60
  	struct list_head queue_list;		/* packets in queue */
  };
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
61
  typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
62

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
63
  static DEFINE_SPINLOCK(instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
64

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
65
  #define INSTANCE_BUCKETS	16
9d6023ab8   Patrick McHardy   [NETFILTER]: nfne...
66
  static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
67
68
69
70
71
72
73
  
  static inline u_int8_t instance_hashfn(u_int16_t queue_num)
  {
  	return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
  }
  
  static struct nfqnl_instance *
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
74
  instance_lookup(u_int16_t queue_num)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
75
76
77
78
79
80
  {
  	struct hlist_head *head;
  	struct hlist_node *pos;
  	struct nfqnl_instance *inst;
  
  	head = &instance_table[instance_hashfn(queue_num)];
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
81
  	hlist_for_each_entry_rcu(inst, pos, head, hlist) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
82
83
84
85
86
87
88
  		if (inst->queue_num == queue_num)
  			return inst;
  	}
  	return NULL;
  }
  
  static struct nfqnl_instance *
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
89
90
  instance_create(u_int16_t queue_num, int pid)
  {
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
91
  	struct nfqnl_instance *inst;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
92
  	unsigned int h;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
93
  	int err;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
94

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
95
  	spin_lock(&instances_lock);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
96
97
  	if (instance_lookup(queue_num)) {
  		err = -EEXIST;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
98
  		goto out_unlock;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
99
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
100

10dfdc69e   Harald Welte   [NETFILTER] nfnet...
101
  	inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
102
103
  	if (!inst) {
  		err = -ENOMEM;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
104
  		goto out_unlock;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
105
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
106

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
107
108
109
110
111
  	inst->queue_num = queue_num;
  	inst->peer_pid = pid;
  	inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
  	inst->copy_range = 0xfffff;
  	inst->copy_mode = NFQNL_COPY_NONE;
181a46a56   YOSHIFUJI Hideaki   [NETFILTER]: Use ...
112
  	spin_lock_init(&inst->lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
113
  	INIT_LIST_HEAD(&inst->queue_list);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
114
115
  	if (!try_module_get(THIS_MODULE)) {
  		err = -EAGAIN;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
116
  		goto out_free;
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
117
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
118

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
119
120
  	h = instance_hashfn(queue_num);
  	hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
121

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
122
  	spin_unlock(&instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
123

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
124
125
126
127
128
  	return inst;
  
  out_free:
  	kfree(inst);
  out_unlock:
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
129
  	spin_unlock(&instances_lock);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
130
  	return ERR_PTR(err);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
131
  }
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
132
133
  static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
  			unsigned long data);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
134
135
  
  static void
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
136
  instance_destroy_rcu(struct rcu_head *head)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
137
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
138
139
  	struct nfqnl_instance *inst = container_of(head, struct nfqnl_instance,
  						   rcu);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
140

b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
141
  	nfqnl_flush(inst, NULL, 0);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
142
  	kfree(inst);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
143
144
  	module_put(THIS_MODULE);
  }
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
145
  static void
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
146
147
  __instance_destroy(struct nfqnl_instance *inst)
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
148
149
  	hlist_del_rcu(&inst->hlist);
  	call_rcu(&inst->rcu, instance_destroy_rcu);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
150
  }
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
151
  static void
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
152
153
  instance_destroy(struct nfqnl_instance *inst)
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
154
155
156
  	spin_lock(&instances_lock);
  	__instance_destroy(inst);
  	spin_unlock(&instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
157
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
158
  static inline void
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
159
  __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
160
  {
0ac41e814   Patrick McHardy   [NETFILTER]: {nf_...
161
         list_add_tail(&entry->list, &queue->queue_list);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
162
163
         queue->queue_total++;
  }
97d32cf94   Florian Westphal   netfilter: nfnetl...
164
165
166
167
168
169
  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...
170
  static struct nf_queue_entry *
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
171
  find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
172
  {
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
173
  	struct nf_queue_entry *entry = NULL, *i;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
174

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
175
  	spin_lock_bh(&queue->lock);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
176
177
178
179
180
181
182
  
  	list_for_each_entry(i, &queue->queue_list, list) {
  		if (i->id == id) {
  			entry = i;
  			break;
  		}
  	}
97d32cf94   Florian Westphal   netfilter: nfnetl...
183
184
  	if (entry)
  		__dequeue_entry(queue, entry);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
185

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
186
187
188
189
190
191
  	spin_unlock_bh(&queue->lock);
  
  	return entry;
  }
  
  static void
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
192
  nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
193
  {
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
194
  	struct nf_queue_entry *entry, *next;
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
195

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
196
  	spin_lock_bh(&queue->lock);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
197
198
199
200
  	list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
  		if (!cmpfn || cmpfn(entry, data)) {
  			list_del(&entry->list);
  			queue->queue_total--;
4b3d15ef4   Patrick McHardy   [NETFILTER]: {nfn...
201
  			nf_reinject(entry, NF_DROP);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
202
203
  		}
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
204
205
206
207
208
  	spin_unlock_bh(&queue->lock);
  }
  
  static struct sk_buff *
  nfqnl_build_packet_message(struct nfqnl_instance *queue,
5863702a3   Eric Dumazet   netfilter: nfnetl...
209
210
  			   struct nf_queue_entry *entry,
  			   __be32 **packet_id_ptr)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
211
  {
27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
212
  	sk_buff_data_t old_tail;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
213
214
215
  	size_t size;
  	size_t data_len = 0;
  	struct sk_buff *skb;
5863702a3   Eric Dumazet   netfilter: nfnetl...
216
217
  	struct nlattr *nla;
  	struct nfqnl_msg_packet_hdr *pmsg;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
218
219
  	struct nlmsghdr *nlh;
  	struct nfgenmsg *nfmsg;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
220
221
222
  	struct sk_buff *entskb = entry->skb;
  	struct net_device *indev;
  	struct net_device *outdev;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
223

cabaa9bfb   Eric Leblond   [NETFILTER]: nfne...
224
  	size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
225
226
227
  		+ 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 */
fbcd923c3   Harald Welte   [NETFILTER]: add ...
228
  #ifdef CONFIG_BRIDGE_NETFILTER
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
229
230
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
  		+ nla_total_size(sizeof(u_int32_t))	/* ifindex */
fbcd923c3   Harald Welte   [NETFILTER]: add ...
231
  #endif
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
232
233
234
  		+ nla_total_size(sizeof(u_int32_t))	/* mark */
  		+ nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
  		+ nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
235

02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
236
  	outdev = entry->outdev;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
237

c463ac972   Eric Dumazet   netfilter: nfnetl...
238
  	switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
239
240
  	case NFQNL_COPY_META:
  	case NFQNL_COPY_NONE:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
241
  		break;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
242

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
243
  	case NFQNL_COPY_PACKET:
e9f13cab4   Herbert Xu   netfilter: only d...
244
  		if (entskb->ip_summed == CHECKSUM_PARTIAL &&
c463ac972   Eric Dumazet   netfilter: nfnetl...
245
  		    skb_checksum_help(entskb))
e7dfb09a3   Patrick McHardy   [NETFILTER]: Fix ...
246
  			return NULL;
c463ac972   Eric Dumazet   netfilter: nfnetl...
247
248
249
  
  		data_len = ACCESS_ONCE(queue->copy_range);
  		if (data_len == 0 || data_len > entskb->len)
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
250
  			data_len = entskb->len;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
251

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
252
  		size += nla_total_size(data_len);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
253
  		break;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
254
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
255
256
257
258
  
  	skb = alloc_skb(size, GFP_ATOMIC);
  	if (!skb)
  		goto nlmsg_failure;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
259

27a884dc3   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
260
  	old_tail = skb->tail;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
261
  	nlh = NLMSG_PUT(skb, 0, 0,
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
262
263
264
  			NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
  			sizeof(struct nfgenmsg));
  	nfmsg = NLMSG_DATA(nlh);
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
265
  	nfmsg->nfgen_family = entry->pf;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
266
267
  	nfmsg->version = NFNETLINK_V0;
  	nfmsg->res_id = htons(queue->queue_num);
5863702a3   Eric Dumazet   netfilter: nfnetl...
268
269
270
271
272
  	nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
  	pmsg = nla_data(nla);
  	pmsg->hw_protocol	= entskb->protocol;
  	pmsg->hook		= entry->hook;
  	*packet_id_ptr		= &pmsg->packet_id;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
273

02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
274
  	indev = entry->indev;
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
275
  	if (indev) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
276
  #ifndef CONFIG_BRIDGE_NETFILTER
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
277
  		NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
278
  #else
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
279
  		if (entry->pf == PF_BRIDGE) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
280
  			/* Case 1: indev is physical input device, we need to
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
281
  			 * look for bridge group (when called from
fbcd923c3   Harald Welte   [NETFILTER]: add ...
282
  			 * netfilter_bridge) */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
283
284
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
  				     htonl(indev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
285
  			/* this is the bridge group "brX" */
f350a0a87   Jiri Pirko   bridge: use rx_ha...
286
  			/* rcu_read_lock()ed by __nf_queue */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
287
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
f350a0a87   Jiri Pirko   bridge: use rx_ha...
288
  				     htonl(br_port_get_rcu(indev)->br->dev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
289
290
291
  		} else {
  			/* Case 2: indev is bridge group, we need to look for
  			 * physical device (when called from ipv4) */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
292
293
294
295
296
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_INDEV,
  				     htonl(indev->ifindex));
  			if (entskb->nf_bridge && entskb->nf_bridge->physindev)
  				NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSINDEV,
  					     htonl(entskb->nf_bridge->physindev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
297
298
  		}
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
299
  	}
3e4ead4fe   Jesper Juhl   [NETFILTER]: Decr...
300
  	if (outdev) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
301
  #ifndef CONFIG_BRIDGE_NETFILTER
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
302
  		NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
303
  #else
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
304
  		if (entry->pf == PF_BRIDGE) {
fbcd923c3   Harald Welte   [NETFILTER]: add ...
305
  			/* Case 1: outdev is physical output device, we need to
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
306
  			 * look for bridge group (when called from
fbcd923c3   Harald Welte   [NETFILTER]: add ...
307
  			 * netfilter_bridge) */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
308
309
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
  				     htonl(outdev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
310
  			/* this is the bridge group "brX" */
f350a0a87   Jiri Pirko   bridge: use rx_ha...
311
  			/* rcu_read_lock()ed by __nf_queue */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
312
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
f350a0a87   Jiri Pirko   bridge: use rx_ha...
313
  				     htonl(br_port_get_rcu(outdev)->br->dev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
314
315
316
  		} else {
  			/* Case 2: outdev is bridge group, we need to look for
  			 * physical output device (when called from ipv4) */
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
317
318
319
320
321
  			NLA_PUT_BE32(skb, NFQA_IFINDEX_OUTDEV,
  				     htonl(outdev->ifindex));
  			if (entskb->nf_bridge && entskb->nf_bridge->physoutdev)
  				NLA_PUT_BE32(skb, NFQA_IFINDEX_PHYSOUTDEV,
  					     htonl(entskb->nf_bridge->physoutdev->ifindex));
fbcd923c3   Harald Welte   [NETFILTER]: add ...
322
323
  		}
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
324
  	}
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
325
326
  	if (entskb->mark)
  		NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark));
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
327

2c38de4c1   Nicolas Cavallari   netfilter: fix lo...
328
329
  	if (indev && entskb->dev &&
  	    entskb->mac_header != entskb->network_header) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
330
  		struct nfqnl_msg_packet_hw phw;
b95cce357   Stephen Hemminger   [NET]: Wrap hard_...
331
332
333
  		int len = dev_parse_header(entskb, phw.hw_addr);
  		if (len) {
  			phw.hw_addrlen = htons(len);
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
334
  			NLA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
b95cce357   Stephen Hemminger   [NET]: Wrap hard_...
335
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
336
  	}
b7aa0bf70   Eric Dumazet   [NET]: convert ne...
337
  	if (entskb->tstamp.tv64) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
338
  		struct nfqnl_msg_packet_timestamp ts;
b7aa0bf70   Eric Dumazet   [NET]: convert ne...
339
340
341
  		struct timeval tv = ktime_to_timeval(entskb->tstamp);
  		ts.sec = cpu_to_be64(tv.tv_sec);
  		ts.usec = cpu_to_be64(tv.tv_usec);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
342

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
343
  		NLA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
344
345
346
  	}
  
  	if (data_len) {
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
347
  		struct nlattr *nla;
ca7c48ca9   Eric Dumazet   [NETFILTER]: Supr...
348
  		int sz = nla_attr_size(data_len);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
349

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
350
  		if (skb_tailroom(skb) < nla_total_size(data_len)) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
351
352
353
354
  			printk(KERN_WARNING "nf_queue: no tailroom!
  ");
  			goto nlmsg_failure;
  		}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
355
356
  		nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len));
  		nla->nla_type = NFQA_PAYLOAD;
ca7c48ca9   Eric Dumazet   [NETFILTER]: Supr...
357
  		nla->nla_len = sz;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
358

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
359
  		if (skb_copy_bits(entskb, 0, nla_data(nla), data_len))
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
360
361
  			BUG();
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
362

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
363
364
365
366
  	nlh->nlmsg_len = skb->tail - old_tail;
  	return skb;
  
  nlmsg_failure:
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
367
  nla_put_failure:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
368
369
  	if (skb)
  		kfree_skb(skb);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
370
371
372
373
374
375
376
  	if (net_ratelimit())
  		printk(KERN_ERR "nf_queue: error creating packet message
  ");
  	return NULL;
  }
  
  static int
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
377
  nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
378
  {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
379
380
  	struct sk_buff *nskb;
  	struct nfqnl_instance *queue;
f15850861   Florian Westphal   netfilter: nfnetl...
381
  	int err = -ENOBUFS;
5863702a3   Eric Dumazet   netfilter: nfnetl...
382
  	__be32 *packet_id_ptr;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
383

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
384
385
  	/* rcu_read_lock()ed by nf_hook_slow() */
  	queue = instance_lookup(queuenum);
f15850861   Florian Westphal   netfilter: nfnetl...
386
387
  	if (!queue) {
  		err = -ESRCH;
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
388
  		goto err_out;
f15850861   Florian Westphal   netfilter: nfnetl...
389
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
390

f15850861   Florian Westphal   netfilter: nfnetl...
391
392
  	if (queue->copy_mode == NFQNL_COPY_NONE) {
  		err = -EINVAL;
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
393
  		goto err_out;
f15850861   Florian Westphal   netfilter: nfnetl...
394
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
395

5863702a3   Eric Dumazet   netfilter: nfnetl...
396
  	nskb = nfqnl_build_packet_message(queue, entry, &packet_id_ptr);
f15850861   Florian Westphal   netfilter: nfnetl...
397
398
  	if (nskb == NULL) {
  		err = -ENOMEM;
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
399
  		goto err_out;
f15850861   Florian Westphal   netfilter: nfnetl...
400
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
401
  	spin_lock_bh(&queue->lock);
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
402

f15850861   Florian Westphal   netfilter: nfnetl...
403
404
  	if (!queue->peer_pid) {
  		err = -EINVAL;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
405
  		goto err_out_free_nskb;
f15850861   Florian Westphal   netfilter: nfnetl...
406
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
407
  	if (queue->queue_total >= queue->queue_maxlen) {
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
408
  		queue->queue_dropped++;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
409
  		if (net_ratelimit())
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
410
  			  printk(KERN_WARNING "nf_queue: full at %d entries, "
a5d896adf   Eric Leblond   netfilter: nfnetl...
411
412
413
  				 "dropping packets(s).
  ",
  				 queue->queue_total);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
414
415
  		goto err_out_free_nskb;
  	}
5863702a3   Eric Dumazet   netfilter: nfnetl...
416
417
  	entry->id = ++queue->id_sequence;
  	*packet_id_ptr = htonl(entry->id);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
418
419
  
  	/* nfnetlink_unicast will either free the nskb or add it to a socket */
cd8c20b65   Alexey Dobriyan   netfilter: nfnetl...
420
  	err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
421
  	if (err < 0) {
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
422
  		queue->queue_user_dropped++;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
423
424
425
426
427
428
  		goto err_out_unlock;
  	}
  
  	__enqueue_entry(queue, entry);
  
  	spin_unlock_bh(&queue->lock);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
429
  	return 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
430
431
  
  err_out_free_nskb:
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
432
  	kfree_skb(nskb);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
433
434
  err_out_unlock:
  	spin_unlock_bh(&queue->lock);
0ef0f4658   Patrick McHardy   [NETFILTER]: nfne...
435
  err_out:
f15850861   Florian Westphal   netfilter: nfnetl...
436
  	return err;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
437
438
439
  }
  
  static int
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
440
  nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
441
  {
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
442
  	struct sk_buff *nskb;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
443
444
445
  	int diff;
  
  	diff = data_len - e->skb->len;
d8a585d78   Patrick McHardy   [NETFILTER]: Use ...
446
447
448
449
  	if (diff < 0) {
  		if (pskb_trim(e->skb, data_len))
  			return -ENOMEM;
  	} else if (diff > 0) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
450
451
452
  		if (data_len > 0xFFFF)
  			return -EINVAL;
  		if (diff > skb_tailroom(e->skb)) {
9a732ed6d   Arnaud Ebalard   netfilter: {nfnet...
453
454
  			nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
  					       diff, GFP_ATOMIC);
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
455
  			if (!nskb) {
1158ba27b   Patrick McHardy   [NETFILTER]: nfne...
456
  				printk(KERN_WARNING "nf_queue: OOM "
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
457
458
  				      "in mangle, dropping packet
  ");
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
459
  				return -ENOMEM;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
460
  			}
e2b58a67b   Patrick McHardy   [NETFILTER]: {ip,...
461
462
  			kfree_skb(e->skb);
  			e->skb = nskb;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
463
464
465
  		}
  		skb_put(e->skb, diff);
  	}
37d418792   Herbert Xu   [NETFILTER]: Do n...
466
  	if (!skb_make_writable(e->skb, data_len))
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
467
  		return -ENOMEM;
27d7ff46a   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
468
  	skb_copy_to_linear_data(e->skb, data, data_len);
e7dfb09a3   Patrick McHardy   [NETFILTER]: Fix ...
469
  	e->skb->ip_summed = CHECKSUM_NONE;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
470
471
  	return 0;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
472
473
474
475
  static int
  nfqnl_set_mode(struct nfqnl_instance *queue,
  	       unsigned char mode, unsigned int range)
  {
c5de0dfde   Patrick McHardy   [NETFILTER]: nfne...
476
  	int status = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
477
478
  
  	spin_lock_bh(&queue->lock);
c5de0dfde   Patrick McHardy   [NETFILTER]: nfne...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  	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;
  		/* we're using struct nlattr which has 16bit nla_len */
  		if (range > 0xffff)
  			queue->copy_range = 0xffff;
  		else
  			queue->copy_range = range;
  		break;
  
  	default:
  		status = -EINVAL;
  
  	}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
499
500
501
502
503
504
  	spin_unlock_bh(&queue->lock);
  
  	return status;
  }
  
  static int
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
505
  dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
506
  {
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
507
508
  	if (entry->indev)
  		if (entry->indev->ifindex == ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
509
  			return 1;
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
510
511
  	if (entry->outdev)
  		if (entry->outdev->ifindex == ifindex)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
512
  			return 1;
ef47c6a7b   Patrick McHardy   [NETFILTER]: ip_q...
513
514
515
516
517
518
519
520
521
522
  #ifdef CONFIG_BRIDGE_NETFILTER
  	if (entry->skb->nf_bridge) {
  		if (entry->skb->nf_bridge->physindev &&
  		    entry->skb->nf_bridge->physindev->ifindex == ifindex)
  			return 1;
  		if (entry->skb->nf_bridge->physoutdev &&
  		    entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
  			return 1;
  	}
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
523
524
525
526
527
528
529
530
531
  	return 0;
  }
  
  /* drop all packets with either indev or outdev == ifindex from all queue
   * instances */
  static void
  nfqnl_dev_drop(int ifindex)
  {
  	int i;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
532

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

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
535
  	for (i = 0; i < INSTANCE_BUCKETS; i++) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
536
537
538
  		struct hlist_node *tmp;
  		struct nfqnl_instance *inst;
  		struct hlist_head *head = &instance_table[i];
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
539
  		hlist_for_each_entry_rcu(inst, tmp, head, hlist)
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
540
  			nfqnl_flush(inst, dev_cmp, ifindex);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
541
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
542
  	rcu_read_unlock();
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
543
544
545
546
547
548
549
550
551
  }
  
  #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
  
  static int
  nfqnl_rcv_dev_event(struct notifier_block *this,
  		    unsigned long event, void *ptr)
  {
  	struct net_device *dev = ptr;
721499e89   YOSHIFUJI Hideaki   netns: Use net_eq...
552
  	if (!net_eq(dev_net(dev), &init_net))
e9dc86534   Eric W. Biederman   [NET]: Make devic...
553
  		return NOTIFY_DONE;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
  	/* Drop any packets associated with the downed device */
  	if (event == NETDEV_DOWN)
  		nfqnl_dev_drop(dev->ifindex);
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block nfqnl_dev_notifier = {
  	.notifier_call	= nfqnl_rcv_dev_event,
  };
  
  static int
  nfqnl_rcv_nl_event(struct notifier_block *this,
  		   unsigned long event, void *ptr)
  {
  	struct netlink_notify *n = ptr;
dee5817e8   Patrick McHardy   netfilter: remove...
569
  	if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
570
571
572
  		int i;
  
  		/* destroy all instances for this pid */
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
573
574
  		spin_lock(&instances_lock);
  		for (i = 0; i < INSTANCE_BUCKETS; i++) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
575
576
577
578
579
  			struct hlist_node *tmp, *t2;
  			struct nfqnl_instance *inst;
  			struct hlist_head *head = &instance_table[i];
  
  			hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
b4b510290   Eric W. Biederman   [NET]: Support mu...
580
581
  				if ((n->net == &init_net) &&
  				    (n->pid == inst->peer_pid))
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
582
583
584
  					__instance_destroy(inst);
  			}
  		}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
585
  		spin_unlock(&instances_lock);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
586
587
588
589
590
591
592
  	}
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block nfqnl_rtnl_notifier = {
  	.notifier_call	= nfqnl_rcv_nl_event,
  };
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
593
594
595
596
  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 },
838ab6364   Harald Welte   [NETFILTER]: Add ...
597
  };
97d32cf94   Florian Westphal   netfilter: nfnetl...
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  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 },
  };
  
  static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
  {
  	struct nfqnl_instance *queue;
  
  	queue = instance_lookup(queue_num);
  	if (!queue)
  		return ERR_PTR(-ENODEV);
  
  	if (queue->peer_pid != nlpid)
  		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...
627
628
  	verdict = ntohl(vhdr->verdict) & NF_VERDICT_MASK;
  	if (verdict > NF_MAX_VERDICT || verdict == NF_STOLEN)
97d32cf94   Florian Westphal   netfilter: nfnetl...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  		return NULL;
  	return vhdr;
  }
  
  static int nfq_id_after(unsigned int id, unsigned int max)
  {
  	return (int)(id - max) > 0;
  }
  
  static int
  nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
  		   const struct nlmsghdr *nlh,
  		   const struct nlattr * const nfqa[])
  {
  	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
  	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);
  
  	queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
  	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]));
  		nf_reinject(entry, verdict);
  	}
  	return 0;
  }
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
683
684
  static int
  nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
685
686
  		   const struct nlmsghdr *nlh,
  		   const struct nlattr * const nfqa[])
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
687
688
689
690
691
692
693
  {
  	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
  	u_int16_t queue_num = ntohs(nfmsg->res_id);
  
  	struct nfqnl_msg_verdict_hdr *vhdr;
  	struct nfqnl_instance *queue;
  	unsigned int verdict;
02f014d88   Patrick McHardy   [NETFILTER]: nf_q...
694
  	struct nf_queue_entry *entry;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
695

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
696
  	queue = instance_lookup(queue_num);
84a797dd0   Eric Dumazet   netfilter: nfnetl...
697
  	if (!queue)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
698

97d32cf94   Florian Westphal   netfilter: nfnetl...
699
700
701
  	queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
  	if (IS_ERR(queue))
  		return PTR_ERR(queue);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
702

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

7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
707
  	verdict = ntohl(vhdr->verdict);
b43d8d859   Patrick McHardy   [NETFILTER]: nfne...
708
  	entry = find_dequeue_entry(queue, ntohl(vhdr->id));
84a797dd0   Eric Dumazet   netfilter: nfnetl...
709
710
  	if (entry == NULL)
  		return -ENOENT;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
711

df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
712
713
714
  	if (nfqa[NFQA_PAYLOAD]) {
  		if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
  				 nla_len(nfqa[NFQA_PAYLOAD]), entry) < 0)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
715
716
  			verdict = NF_DROP;
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
717
  	if (nfqa[NFQA_MARK])
ea3a66ff5   Patrick McHardy   [NETFILTER]: nfne...
718
  		entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
719

4b3d15ef4   Patrick McHardy   [NETFILTER]: {nfn...
720
  	nf_reinject(entry, verdict);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
721
722
723
724
725
  	return 0;
  }
  
  static int
  nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
726
727
  		  const struct nlmsghdr *nlh,
  		  const struct nlattr * const nfqa[])
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
728
729
730
  {
  	return -ENOTSUPP;
  }
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
731
732
733
  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) },
838ab6364   Harald Welte   [NETFILTER]: Add ...
734
  };
e3ac52981   Patrick McHardy   [NETFILTER]: nf_q...
735
  static const struct nf_queue_handler nfqh = {
bbd86b9fc   Harald Welte   [NETFILTER]: add ...
736
737
738
  	.name 	= "nf_queue",
  	.outfn	= &nfqnl_enqueue_packet,
  };
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
739
740
  static int
  nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
399383246   Patrick McHardy   netfilter: nfnetl...
741
742
  		  const struct nlmsghdr *nlh,
  		  const struct nlattr * const nfqa[])
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
743
744
745
746
  {
  	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
  	u_int16_t queue_num = ntohs(nfmsg->res_id);
  	struct nfqnl_instance *queue;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
747
  	struct nfqnl_msg_config_cmd *cmd = NULL;
838ab6364   Harald Welte   [NETFILTER]: Add ...
748
  	int ret = 0;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
749

9872bec77   Patrick McHardy   [NETFILTER]: nfne...
750
751
752
753
754
755
  	if (nfqa[NFQA_CFG_CMD]) {
  		cmd = nla_data(nfqa[NFQA_CFG_CMD]);
  
  		/* Commands without queue context - might sleep */
  		switch (cmd->command) {
  		case NFQNL_CFG_CMD_PF_BIND:
914afea84   Patrick McHardy   [NETFILTER]: nfne...
756
757
  			return nf_register_queue_handler(ntohs(cmd->pf),
  							 &nfqh);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
758
  		case NFQNL_CFG_CMD_PF_UNBIND:
914afea84   Patrick McHardy   [NETFILTER]: nfne...
759
760
  			return nf_unregister_queue_handler(ntohs(cmd->pf),
  							   &nfqh);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
761
  		}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
762
763
764
765
  	}
  
  	rcu_read_lock();
  	queue = instance_lookup(queue_num);
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
766
767
  	if (queue && queue->peer_pid != NETLINK_CB(skb).pid) {
  		ret = -EPERM;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
768
  		goto err_out_unlock;
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
769
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
770
  	if (cmd != NULL) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
771
772
  		switch (cmd->command) {
  		case NFQNL_CFG_CMD_BIND:
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
773
774
775
776
  			if (queue) {
  				ret = -EBUSY;
  				goto err_out_unlock;
  			}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
777
  			queue = instance_create(queue_num, NETLINK_CB(skb).pid);
baab2ce7d   Patrick McHardy   [NETFILTER]: nfne...
778
779
  			if (IS_ERR(queue)) {
  				ret = PTR_ERR(queue);
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
780
781
  				goto err_out_unlock;
  			}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
782
783
  			break;
  		case NFQNL_CFG_CMD_UNBIND:
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
784
785
786
787
  			if (!queue) {
  				ret = -ENODEV;
  				goto err_out_unlock;
  			}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
788
789
790
  			instance_destroy(queue);
  			break;
  		case NFQNL_CFG_CMD_PF_BIND:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
791
  		case NFQNL_CFG_CMD_PF_UNBIND:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
792
793
  			break;
  		default:
cd21f0ac4   Patrick McHardy   [NETFILTER]: nfne...
794
  			ret = -ENOTSUPP;
838ab6364   Harald Welte   [NETFILTER]: Add ...
795
  			break;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
796
  		}
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
797
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
798
  	if (nfqa[NFQA_CFG_PARAMS]) {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
799
  		struct nfqnl_msg_config_params *params;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
800

406dbfc9a   Patrick McHardy   [NETFILTER]: nfne...
801
  		if (!queue) {
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
802
  			ret = -ENODEV;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
803
  			goto err_out_unlock;
406dbfc9a   Patrick McHardy   [NETFILTER]: nfne...
804
  		}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
805
  		params = nla_data(nfqa[NFQA_CFG_PARAMS]);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
806
807
808
  		nfqnl_set_mode(queue, params->copy_mode,
  				ntohl(params->copy_range));
  	}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
809
  	if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
829e17a1a   Eric Leblond   [NETFILTER]: nfne...
810
  		__be32 *queue_maxlen;
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
811
812
813
  
  		if (!queue) {
  			ret = -ENODEV;
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
814
  			goto err_out_unlock;
a3c8e7fd4   Patrick McHardy   [NETFILTER]: nfne...
815
  		}
df6fb868d   Patrick McHardy   [NETFILTER]: nfne...
816
  		queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
829e17a1a   Eric Leblond   [NETFILTER]: nfne...
817
818
819
820
  		spin_lock_bh(&queue->lock);
  		queue->queue_maxlen = ntohl(*queue_maxlen);
  		spin_unlock_bh(&queue->lock);
  	}
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
821
822
  err_out_unlock:
  	rcu_read_unlock();
838ab6364   Harald Welte   [NETFILTER]: Add ...
823
  	return ret;
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
824
  }
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
825
  static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
84a797dd0   Eric Dumazet   netfilter: nfnetl...
826
  	[NFQNL_MSG_PACKET]	= { .call_rcu = nfqnl_recv_unsupp,
37d2e7a20   Harald Welte   [NETFILTER] nfnet...
827
  				    .attr_count = NFQA_MAX, },
84a797dd0   Eric Dumazet   netfilter: nfnetl...
828
  	[NFQNL_MSG_VERDICT]	= { .call_rcu = nfqnl_recv_verdict,
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
829
830
  				    .attr_count = NFQA_MAX,
  				    .policy = nfqa_verdict_policy },
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
831
  	[NFQNL_MSG_CONFIG]	= { .call = nfqnl_recv_config,
5bf758539   Patrick McHardy   [NETFILTER]: nfne...
832
833
  				    .attr_count = NFQA_CFG_MAX,
  				    .policy = nfqa_cfg_policy },
97d32cf94   Florian Westphal   netfilter: nfnetl...
834
835
836
  	[NFQNL_MSG_VERDICT_BATCH]={ .call_rcu = nfqnl_recv_verdict_batch,
  				    .attr_count = NFQA_MAX,
  				    .policy = nfqa_verdict_batch_policy },
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
837
  };
7c8d4cb41   Patrick McHardy   [NETFILTER]: nfne...
838
  static const struct nfnetlink_subsystem nfqnl_subsys = {
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
839
840
841
  	.name		= "nf_queue",
  	.subsys_id	= NFNL_SUBSYS_QUEUE,
  	.cb_count	= NFQNL_MSG_MAX,
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
842
843
  	.cb		= nfqnl_cb,
  };
838ab6364   Harald Welte   [NETFILTER]: Add ...
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  #ifdef CONFIG_PROC_FS
  struct iter_state {
  	unsigned int bucket;
  };
  
  static struct hlist_node *get_first(struct seq_file *seq)
  {
  	struct iter_state *st = seq->private;
  
  	if (!st)
  		return NULL;
  
  	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
  		if (!hlist_empty(&instance_table[st->bucket]))
  			return instance_table[st->bucket].first;
  	}
  	return NULL;
  }
  
  static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
  {
  	struct iter_state *st = seq->private;
  
  	h = h->next;
  	while (!h) {
  		if (++st->bucket >= INSTANCE_BUCKETS)
  			return NULL;
  
  		h = instance_table[st->bucket].first;
  	}
  	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;
  }
  
  static void *seq_start(struct seq_file *seq, loff_t *pos)
ca7c48ca9   Eric Dumazet   [NETFILTER]: Supr...
889
  	__acquires(instances_lock)
838ab6364   Harald Welte   [NETFILTER]: Add ...
890
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
891
  	spin_lock(&instances_lock);
838ab6364   Harald Welte   [NETFILTER]: Add ...
892
893
894
895
896
897
898
899
900
901
  	return get_idx(seq, *pos);
  }
  
  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)
ca7c48ca9   Eric Dumazet   [NETFILTER]: Supr...
902
  	__releases(instances_lock)
838ab6364   Harald Welte   [NETFILTER]: Add ...
903
  {
9872bec77   Patrick McHardy   [NETFILTER]: nfne...
904
  	spin_unlock(&instances_lock);
838ab6364   Harald Welte   [NETFILTER]: Add ...
905
906
907
908
909
910
911
912
913
914
915
916
  }
  
  static int seq_show(struct seq_file *s, void *v)
  {
  	const struct nfqnl_instance *inst = v;
  
  	return seq_printf(s, "%5d %6d %5d %1d %5d %5d %5d %8d %2d
  ",
  			  inst->queue_num,
  			  inst->peer_pid, inst->queue_total,
  			  inst->copy_mode, inst->copy_range,
  			  inst->queue_dropped, inst->queue_user_dropped,
5863702a3   Eric Dumazet   netfilter: nfnetl...
917
  			  inst->id_sequence, 1);
838ab6364   Harald Welte   [NETFILTER]: Add ...
918
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
919
  static const struct seq_operations nfqnl_seq_ops = {
838ab6364   Harald Welte   [NETFILTER]: Add ...
920
921
922
923
924
925
926
927
  	.start	= seq_start,
  	.next	= seq_next,
  	.stop	= seq_stop,
  	.show	= seq_show,
  };
  
  static int nfqnl_open(struct inode *inode, struct file *file)
  {
e2da59133   Pavel Emelyanov   [NETFILTER]: Make...
928
929
  	return seq_open_private(file, &nfqnl_seq_ops,
  			sizeof(struct iter_state));
838ab6364   Harald Welte   [NETFILTER]: Add ...
930
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
931
  static const struct file_operations nfqnl_file_ops = {
838ab6364   Harald Welte   [NETFILTER]: Add ...
932
933
934
935
936
937
938
939
  	.owner	 = THIS_MODULE,
  	.open	 = nfqnl_open,
  	.read	 = seq_read,
  	.llseek	 = seq_lseek,
  	.release = seq_release_private,
  };
  
  #endif /* PROC_FS */
32292a7ff   Patrick McHardy   [NETFILTER]: Fix ...
940
  static int __init nfnetlink_queue_init(void)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
941
  {
838ab6364   Harald Welte   [NETFILTER]: Add ...
942
  	int i, status = -ENOMEM;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
943

838ab6364   Harald Welte   [NETFILTER]: Add ...
944
945
  	for (i = 0; i < INSTANCE_BUCKETS; i++)
  		INIT_HLIST_HEAD(&instance_table[i]);
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
946
947
948
949
950
951
952
  	netlink_register_notifier(&nfqnl_rtnl_notifier);
  	status = nfnetlink_subsys_register(&nfqnl_subsys);
  	if (status < 0) {
  		printk(KERN_ERR "nf_queue: failed to create netlink socket
  ");
  		goto cleanup_netlink_notifier;
  	}
838ab6364   Harald Welte   [NETFILTER]: Add ...
953
  #ifdef CONFIG_PROC_FS
8eeee8b15   Denis V. Lunev   [NETFILTER]: Repl...
954
955
  	if (!proc_create("nfnetlink_queue", 0440,
  			 proc_net_netfilter, &nfqnl_file_ops))
838ab6364   Harald Welte   [NETFILTER]: Add ...
956
  		goto cleanup_subsys;
838ab6364   Harald Welte   [NETFILTER]: Add ...
957
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
958
959
  	register_netdevice_notifier(&nfqnl_dev_notifier);
  	return status;
838ab6364   Harald Welte   [NETFILTER]: Add ...
960
961
  #ifdef CONFIG_PROC_FS
  cleanup_subsys:
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
962
  	nfnetlink_subsys_unregister(&nfqnl_subsys);
32292a7ff   Patrick McHardy   [NETFILTER]: Fix ...
963
  #endif
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
964
965
966
967
  cleanup_netlink_notifier:
  	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
  	return status;
  }
65b4b4e81   Andrew Morton   [NETFILTER]: Rena...
968
  static void __exit nfnetlink_queue_fini(void)
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
969
  {
32292a7ff   Patrick McHardy   [NETFILTER]: Fix ...
970
971
972
973
974
975
976
  	nf_unregister_queue_handlers(&nfqh);
  	unregister_netdevice_notifier(&nfqnl_dev_notifier);
  #ifdef CONFIG_PROC_FS
  	remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
  #endif
  	nfnetlink_subsys_unregister(&nfqnl_subsys);
  	netlink_unregister_notifier(&nfqnl_rtnl_notifier);
67137f3cc   Jesper Dangaard Brouer   nfnetlink_queue: ...
977
978
  
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
7af4cc3fa   Harald Welte   [NETFILTER]: Add ...
979
980
981
982
983
984
  }
  
  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...
985
986
  module_init(nfnetlink_queue_init);
  module_exit(nfnetlink_queue_fini);