aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-05-08 13:45:28 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2012-05-08 14:25:42 -0400
commitd16cf20e2f2f13411eece7f7fb72c17d141c4a84 (patch)
tree8154b3db8cdbb4b8d9f35d4c407cfe961253f0b4
parent6714cf5465d2803a21c6a46c1ea747795a8889fa (diff)
netfilter: remove ip_queue support
This patch removes ip_queue support which was marked as obsolete years ago. The nfnetlink_queue modules provides more advanced user-space packet queueing mechanism. This patch also removes capability code included in SELinux that refers to ip_queue. Otherwise, we break compilation. Several warning has been sent regarding this to the mailing list in the past month without anyone rising the hand to stop this with some strong argument. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--Documentation/ABI/removed/ip_queue9
-rw-r--r--include/linux/netfilter_ipv4/Kbuild1
-rw-r--r--include/linux/netfilter_ipv4/ip_queue.h72
-rw-r--r--include/linux/netlink.h2
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/ip_queue.c639
-rw-r--r--net/ipv6/netfilter/Kconfig22
-rw-r--r--net/ipv6/netfilter/Makefile1
-rw-r--r--net/ipv6/netfilter/ip6_queue.c641
-rw-r--r--security/selinux/nlmsgtab.c13
10 files changed, 10 insertions, 1393 deletions
diff --git a/Documentation/ABI/removed/ip_queue b/Documentation/ABI/removed/ip_queue
new file mode 100644
index 000000000000..3243613bc2d2
--- /dev/null
+++ b/Documentation/ABI/removed/ip_queue
@@ -0,0 +1,9 @@
1What: ip_queue
2Date: finally removed in kernel v3.5.0
3Contact: Pablo Neira Ayuso <pablo@netfilter.org>
4Description:
5 ip_queue has been replaced by nfnetlink_queue which provides
6 more advanced queueing mechanism to user-space. The ip_queue
7 module was already announced to become obsolete years ago.
8
9Users:
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index 31f8bec95650..c61b8fb1a9ef 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -1,4 +1,3 @@
1header-y += ip_queue.h
2header-y += ip_tables.h 1header-y += ip_tables.h
3header-y += ipt_CLUSTERIP.h 2header-y += ipt_CLUSTERIP.h
4header-y += ipt_ECN.h 3header-y += ipt_ECN.h
diff --git a/include/linux/netfilter_ipv4/ip_queue.h b/include/linux/netfilter_ipv4/ip_queue.h
deleted file mode 100644
index a03507f465f8..000000000000
--- a/include/linux/netfilter_ipv4/ip_queue.h
+++ /dev/null
@@ -1,72 +0,0 @@
1/*
2 * This is a module which is used for queueing IPv4 packets and
3 * communicating with userspace via netlink.
4 *
5 * (C) 2000 James Morris, this code is GPL.
6 */
7#ifndef _IP_QUEUE_H
8#define _IP_QUEUE_H
9
10#ifdef __KERNEL__
11#ifdef DEBUG_IPQ
12#define QDEBUG(x...) printk(KERN_DEBUG ## x)
13#else
14#define QDEBUG(x...)
15#endif /* DEBUG_IPQ */
16#else
17#include <net/if.h>
18#endif /* ! __KERNEL__ */
19
20/* Messages sent from kernel */
21typedef struct ipq_packet_msg {
22 unsigned long packet_id; /* ID of queued packet */
23 unsigned long mark; /* Netfilter mark value */
24 long timestamp_sec; /* Packet arrival time (seconds) */
25 long timestamp_usec; /* Packet arrvial time (+useconds) */
26 unsigned int hook; /* Netfilter hook we rode in on */
27 char indev_name[IFNAMSIZ]; /* Name of incoming interface */
28 char outdev_name[IFNAMSIZ]; /* Name of outgoing interface */
29 __be16 hw_protocol; /* Hardware protocol (network order) */
30 unsigned short hw_type; /* Hardware type */
31 unsigned char hw_addrlen; /* Hardware address length */
32 unsigned char hw_addr[8]; /* Hardware address */
33 size_t data_len; /* Length of packet data */
34 unsigned char payload[0]; /* Optional packet data */
35} ipq_packet_msg_t;
36
37/* Messages sent from userspace */
38typedef struct ipq_mode_msg {
39 unsigned char value; /* Requested mode */
40 size_t range; /* Optional range of packet requested */
41} ipq_mode_msg_t;
42
43typedef struct ipq_verdict_msg {
44 unsigned int value; /* Verdict to hand to netfilter */
45 unsigned long id; /* Packet ID for this verdict */
46 size_t data_len; /* Length of replacement data */
47 unsigned char payload[0]; /* Optional replacement packet */
48} ipq_verdict_msg_t;
49
50typedef struct ipq_peer_msg {
51 union {
52 ipq_verdict_msg_t verdict;
53 ipq_mode_msg_t mode;
54 } msg;
55} ipq_peer_msg_t;
56
57/* Packet delivery modes */
58enum {
59 IPQ_COPY_NONE, /* Initial mode, packets are dropped */
60 IPQ_COPY_META, /* Copy metadata */
61 IPQ_COPY_PACKET /* Copy metadata + packet (range) */
62};
63#define IPQ_COPY_MAX IPQ_COPY_PACKET
64
65/* Types of messages */
66#define IPQM_BASE 0x10 /* standard netlink messages below this */
67#define IPQM_MODE (IPQM_BASE + 1) /* Mode request from peer */
68#define IPQM_VERDICT (IPQM_BASE + 2) /* Verdict from peer */
69#define IPQM_PACKET (IPQM_BASE + 3) /* Packet from kernel */
70#define IPQM_MAX (IPQM_BASE + 4)
71
72#endif /*_IP_QUEUE_H*/
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index a2092f582a78..0f628ffa420c 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -7,7 +7,7 @@
7#define NETLINK_ROUTE 0 /* Routing/device hook */ 7#define NETLINK_ROUTE 0 /* Routing/device hook */
8#define NETLINK_UNUSED 1 /* Unused number */ 8#define NETLINK_UNUSED 1 /* Unused number */
9#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ 9#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
10#define NETLINK_FIREWALL 3 /* Firewalling hook */ 10#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
11#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ 11#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
12#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ 12#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
13#define NETLINK_XFRM 6 /* ipsec */ 13#define NETLINK_XFRM 6 /* ipsec */
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 240b68469a7a..c20674dc9452 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -66,6 +66,3 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
66 66
67# just filtering instance of ARP tables for now 67# just filtering instance of ARP tables for now
68obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o 68obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
69
70obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
71
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
deleted file mode 100644
index 09775a1e1348..000000000000
--- a/net/ipv4/netfilter/ip_queue.c
+++ /dev/null
@@ -1,639 +0,0 @@
1/*
2 * This is a module which is used for queueing IPv4 packets and
3 * communicating with userspace via netlink.
4 *
5 * (C) 2000-2002 James Morris <jmorris@intercode.com.au>
6 * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/init.h>
15#include <linux/ip.h>
16#include <linux/notifier.h>
17#include <linux/netdevice.h>
18#include <linux/netfilter.h>
19#include <linux/netfilter_ipv4/ip_queue.h>
20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <linux/netlink.h>
22#include <linux/spinlock.h>
23#include <linux/sysctl.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26#include <linux/security.h>
27#include <linux/net.h>
28#include <linux/mutex.h>
29#include <linux/slab.h>
30#include <net/net_namespace.h>
31#include <net/sock.h>
32#include <net/route.h>
33#include <net/netfilter/nf_queue.h>
34#include <net/ip.h>
35
36#define IPQ_QMAX_DEFAULT 1024
37#define IPQ_PROC_FS_NAME "ip_queue"
38#define NET_IPQ_QMAX 2088
39#define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
40
41typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
42
43static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
44static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
45static DEFINE_SPINLOCK(queue_lock);
46static int peer_pid __read_mostly;
47static unsigned int copy_range __read_mostly;
48static unsigned int queue_total;
49static unsigned int queue_dropped = 0;
50static unsigned int queue_user_dropped = 0;
51static struct sock *ipqnl __read_mostly;
52static LIST_HEAD(queue_list);
53static DEFINE_MUTEX(ipqnl_mutex);
54
55static inline void
56__ipq_enqueue_entry(struct nf_queue_entry *entry)
57{
58 list_add_tail(&entry->list, &queue_list);
59 queue_total++;
60}
61
62static inline int
63__ipq_set_mode(unsigned char mode, unsigned int range)
64{
65 int status = 0;
66
67 switch(mode) {
68 case IPQ_COPY_NONE:
69 case IPQ_COPY_META:
70 copy_mode = mode;
71 copy_range = 0;
72 break;
73
74 case IPQ_COPY_PACKET:
75 if (range > 0xFFFF)
76 range = 0xFFFF;
77 copy_range = range;
78 copy_mode = mode;
79 break;
80
81 default:
82 status = -EINVAL;
83
84 }
85 return status;
86}
87
88static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data);
89
90static inline void
91__ipq_reset(void)
92{
93 peer_pid = 0;
94 net_disable_timestamp();
95 __ipq_set_mode(IPQ_COPY_NONE, 0);
96 __ipq_flush(NULL, 0);
97}
98
99static struct nf_queue_entry *
100ipq_find_dequeue_entry(unsigned long id)
101{
102 struct nf_queue_entry *entry = NULL, *i;
103
104 spin_lock_bh(&queue_lock);
105
106 list_for_each_entry(i, &queue_list, list) {
107 if ((unsigned long)i == id) {
108 entry = i;
109 break;
110 }
111 }
112
113 if (entry) {
114 list_del(&entry->list);
115 queue_total--;
116 }
117
118 spin_unlock_bh(&queue_lock);
119 return entry;
120}
121
122static void
123__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
124{
125 struct nf_queue_entry *entry, *next;
126
127 list_for_each_entry_safe(entry, next, &queue_list, list) {
128 if (!cmpfn || cmpfn(entry, data)) {
129 list_del(&entry->list);
130 queue_total--;
131 nf_reinject(entry, NF_DROP);
132 }
133 }
134}
135
136static void
137ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
138{
139 spin_lock_bh(&queue_lock);
140 __ipq_flush(cmpfn, data);
141 spin_unlock_bh(&queue_lock);
142}
143
144static struct sk_buff *
145ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
146{
147 sk_buff_data_t old_tail;
148 size_t size = 0;
149 size_t data_len = 0;
150 struct sk_buff *skb;
151 struct ipq_packet_msg *pmsg;
152 struct nlmsghdr *nlh;
153 struct timeval tv;
154
155 switch (ACCESS_ONCE(copy_mode)) {
156 case IPQ_COPY_META:
157 case IPQ_COPY_NONE:
158 size = NLMSG_SPACE(sizeof(*pmsg));
159 break;
160
161 case IPQ_COPY_PACKET:
162 if (entry->skb->ip_summed == CHECKSUM_PARTIAL &&
163 (*errp = skb_checksum_help(entry->skb)))
164 return NULL;
165
166 data_len = ACCESS_ONCE(copy_range);
167 if (data_len == 0 || data_len > entry->skb->len)
168 data_len = entry->skb->len;
169
170 size = NLMSG_SPACE(sizeof(*pmsg) + data_len);
171 break;
172
173 default:
174 *errp = -EINVAL;
175 return NULL;
176 }
177
178 skb = alloc_skb(size, GFP_ATOMIC);
179 if (!skb)
180 goto nlmsg_failure;
181
182 old_tail = skb->tail;
183 nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
184 pmsg = NLMSG_DATA(nlh);
185 memset(pmsg, 0, sizeof(*pmsg));
186
187 pmsg->packet_id = (unsigned long )entry;
188 pmsg->data_len = data_len;
189 tv = ktime_to_timeval(entry->skb->tstamp);
190 pmsg->timestamp_sec = tv.tv_sec;
191 pmsg->timestamp_usec = tv.tv_usec;
192 pmsg->mark = entry->skb->mark;
193 pmsg->hook = entry->hook;
194 pmsg->hw_protocol = entry->skb->protocol;
195
196 if (entry->indev)
197 strcpy(pmsg->indev_name, entry->indev->name);
198 else
199 pmsg->indev_name[0] = '\0';
200
201 if (entry->outdev)
202 strcpy(pmsg->outdev_name, entry->outdev->name);
203 else
204 pmsg->outdev_name[0] = '\0';
205
206 if (entry->indev && entry->skb->dev &&
207 entry->skb->mac_header != entry->skb->network_header) {
208 pmsg->hw_type = entry->skb->dev->type;
209 pmsg->hw_addrlen = dev_parse_header(entry->skb,
210 pmsg->hw_addr);
211 }
212
213 if (data_len)
214 if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
215 BUG();
216
217 nlh->nlmsg_len = skb->tail - old_tail;
218 return skb;
219
220nlmsg_failure:
221 kfree_skb(skb);
222 *errp = -EINVAL;
223 printk(KERN_ERR "ip_queue: error creating packet message\n");
224 return NULL;
225}
226
227static int
228ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
229{
230 int status = -EINVAL;
231 struct sk_buff *nskb;
232
233 if (copy_mode == IPQ_COPY_NONE)
234 return -EAGAIN;
235
236 nskb = ipq_build_packet_message(entry, &status);
237 if (nskb == NULL)
238 return status;
239
240 spin_lock_bh(&queue_lock);
241
242 if (!peer_pid)
243 goto err_out_free_nskb;
244
245 if (queue_total >= queue_maxlen) {
246 queue_dropped++;
247 status = -ENOSPC;
248 if (net_ratelimit())
249 printk (KERN_WARNING "ip_queue: full at %d entries, "
250 "dropping packets(s). Dropped: %d\n", queue_total,
251 queue_dropped);
252 goto err_out_free_nskb;
253 }
254
255 /* netlink_unicast will either free the nskb or attach it to a socket */
256 status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
257 if (status < 0) {
258 queue_user_dropped++;
259 goto err_out_unlock;
260 }
261
262 __ipq_enqueue_entry(entry);
263
264 spin_unlock_bh(&queue_lock);
265 return status;
266
267err_out_free_nskb:
268 kfree_skb(nskb);
269
270err_out_unlock:
271 spin_unlock_bh(&queue_lock);
272 return status;
273}
274
275static int
276ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
277{
278 int diff;
279 struct iphdr *user_iph = (struct iphdr *)v->payload;
280 struct sk_buff *nskb;
281
282 if (v->data_len < sizeof(*user_iph))
283 return 0;
284 diff = v->data_len - e->skb->len;
285 if (diff < 0) {
286 if (pskb_trim(e->skb, v->data_len))
287 return -ENOMEM;
288 } else if (diff > 0) {
289 if (v->data_len > 0xFFFF)
290 return -EINVAL;
291 if (diff > skb_tailroom(e->skb)) {
292 nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
293 diff, GFP_ATOMIC);
294 if (!nskb) {
295 printk(KERN_WARNING "ip_queue: error "
296 "in mangle, dropping packet\n");
297 return -ENOMEM;
298 }
299 kfree_skb(e->skb);
300 e->skb = nskb;
301 }
302 skb_put(e->skb, diff);
303 }
304 if (!skb_make_writable(e->skb, v->data_len))
305 return -ENOMEM;
306 skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
307 e->skb->ip_summed = CHECKSUM_NONE;
308
309 return 0;
310}
311
312static int
313ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
314{
315 struct nf_queue_entry *entry;
316
317 if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN)
318 return -EINVAL;
319
320 entry = ipq_find_dequeue_entry(vmsg->id);
321 if (entry == NULL)
322 return -ENOENT;
323 else {
324 int verdict = vmsg->value;
325
326 if (vmsg->data_len && vmsg->data_len == len)
327 if (ipq_mangle_ipv4(vmsg, entry) < 0)
328 verdict = NF_DROP;
329
330 nf_reinject(entry, verdict);
331 return 0;
332 }
333}
334
335static int
336ipq_set_mode(unsigned char mode, unsigned int range)
337{
338 int status;
339
340 spin_lock_bh(&queue_lock);
341 status = __ipq_set_mode(mode, range);
342 spin_unlock_bh(&queue_lock);
343 return status;
344}
345
346static int
347ipq_receive_peer(struct ipq_peer_msg *pmsg,
348 unsigned char type, unsigned int len)
349{
350 int status = 0;
351
352 if (len < sizeof(*pmsg))
353 return -EINVAL;
354
355 switch (type) {
356 case IPQM_MODE:
357 status = ipq_set_mode(pmsg->msg.mode.value,
358 pmsg->msg.mode.range);
359 break;
360
361 case IPQM_VERDICT:
362 status = ipq_set_verdict(&pmsg->msg.verdict,
363 len - sizeof(*pmsg));
364 break;
365 default:
366 status = -EINVAL;
367 }
368 return status;
369}
370
371static int
372dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
373{
374 if (entry->indev)
375 if (entry->indev->ifindex == ifindex)
376 return 1;
377 if (entry->outdev)
378 if (entry->outdev->ifindex == ifindex)
379 return 1;
380#ifdef CONFIG_BRIDGE_NETFILTER
381 if (entry->skb->nf_bridge) {
382 if (entry->skb->nf_bridge->physindev &&
383 entry->skb->nf_bridge->physindev->ifindex == ifindex)
384 return 1;
385 if (entry->skb->nf_bridge->physoutdev &&
386 entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
387 return 1;
388 }
389#endif
390 return 0;
391}
392
393static void
394ipq_dev_drop(int ifindex)
395{
396 ipq_flush(dev_cmp, ifindex);
397}
398
399#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
400
401static inline void
402__ipq_rcv_skb(struct sk_buff *skb)
403{
404 int status, type, pid, flags;
405 unsigned int nlmsglen, skblen;
406 struct nlmsghdr *nlh;
407 bool enable_timestamp = false;
408
409 skblen = skb->len;
410 if (skblen < sizeof(*nlh))
411 return;
412
413 nlh = nlmsg_hdr(skb);
414 nlmsglen = nlh->nlmsg_len;
415 if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
416 return;
417
418 pid = nlh->nlmsg_pid;
419 flags = nlh->nlmsg_flags;
420
421 if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
422 RCV_SKB_FAIL(-EINVAL);
423
424 if (flags & MSG_TRUNC)
425 RCV_SKB_FAIL(-ECOMM);
426
427 type = nlh->nlmsg_type;
428 if (type < NLMSG_NOOP || type >= IPQM_MAX)
429 RCV_SKB_FAIL(-EINVAL);
430
431 if (type <= IPQM_BASE)
432 return;
433
434 if (!capable(CAP_NET_ADMIN))
435 RCV_SKB_FAIL(-EPERM);
436
437 spin_lock_bh(&queue_lock);
438
439 if (peer_pid) {
440 if (peer_pid != pid) {
441 spin_unlock_bh(&queue_lock);
442 RCV_SKB_FAIL(-EBUSY);
443 }
444 } else {
445 enable_timestamp = true;
446 peer_pid = pid;
447 }
448
449 spin_unlock_bh(&queue_lock);
450 if (enable_timestamp)
451 net_enable_timestamp();
452 status = ipq_receive_peer(NLMSG_DATA(nlh), type,
453 nlmsglen - NLMSG_LENGTH(0));
454 if (status < 0)
455 RCV_SKB_FAIL(status);
456
457 if (flags & NLM_F_ACK)
458 netlink_ack(skb, nlh, 0);
459}
460
461static void
462ipq_rcv_skb(struct sk_buff *skb)
463{
464 mutex_lock(&ipqnl_mutex);
465 __ipq_rcv_skb(skb);
466 mutex_unlock(&ipqnl_mutex);
467}
468
469static int
470ipq_rcv_dev_event(struct notifier_block *this,
471 unsigned long event, void *ptr)
472{
473 struct net_device *dev = ptr;
474
475 if (!net_eq(dev_net(dev), &init_net))
476 return NOTIFY_DONE;
477
478 /* Drop any packets associated with the downed device */
479 if (event == NETDEV_DOWN)
480 ipq_dev_drop(dev->ifindex);
481 return NOTIFY_DONE;
482}
483
484static struct notifier_block ipq_dev_notifier = {
485 .notifier_call = ipq_rcv_dev_event,
486};
487
488static int
489ipq_rcv_nl_event(struct notifier_block *this,
490 unsigned long event, void *ptr)
491{
492 struct netlink_notify *n = ptr;
493
494 if (event == NETLINK_URELEASE && n->protocol == NETLINK_FIREWALL) {
495 spin_lock_bh(&queue_lock);
496 if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid))
497 __ipq_reset();
498 spin_unlock_bh(&queue_lock);
499 }
500 return NOTIFY_DONE;
501}
502
503static struct notifier_block ipq_nl_notifier = {
504 .notifier_call = ipq_rcv_nl_event,
505};
506
507#ifdef CONFIG_SYSCTL
508static struct ctl_table_header *ipq_sysctl_header;
509
510static ctl_table ipq_table[] = {
511 {
512 .procname = NET_IPQ_QMAX_NAME,
513 .data = &queue_maxlen,
514 .maxlen = sizeof(queue_maxlen),
515 .mode = 0644,
516 .proc_handler = proc_dointvec
517 },
518 { }
519};
520#endif
521
522#ifdef CONFIG_PROC_FS
523static int ip_queue_show(struct seq_file *m, void *v)
524{
525 spin_lock_bh(&queue_lock);
526
527 seq_printf(m,
528 "Peer PID : %d\n"
529 "Copy mode : %hu\n"
530 "Copy range : %u\n"
531 "Queue length : %u\n"
532 "Queue max. length : %u\n"
533 "Queue dropped : %u\n"
534 "Netlink dropped : %u\n",
535 peer_pid,
536 copy_mode,
537 copy_range,
538 queue_total,
539 queue_maxlen,
540 queue_dropped,
541 queue_user_dropped);
542
543 spin_unlock_bh(&queue_lock);
544 return 0;
545}
546
547static int ip_queue_open(struct inode *inode, struct file *file)
548{
549 return single_open(file, ip_queue_show, NULL);
550}
551
552static const struct file_operations ip_queue_proc_fops = {
553 .open = ip_queue_open,
554 .read = seq_read,
555 .llseek = seq_lseek,
556 .release = single_release,
557 .owner = THIS_MODULE,
558};
559#endif
560
561static const struct nf_queue_handler nfqh = {
562 .name = "ip_queue",
563 .outfn = &ipq_enqueue_packet,
564};
565
566static int __init ip_queue_init(void)
567{
568 int status = -ENOMEM;
569 struct proc_dir_entry *proc __maybe_unused;
570
571 netlink_register_notifier(&ipq_nl_notifier);
572 ipqnl = netlink_kernel_create(&init_net, NETLINK_FIREWALL, 0,
573 ipq_rcv_skb, NULL, THIS_MODULE);
574 if (ipqnl == NULL) {
575 printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
576 goto cleanup_netlink_notifier;
577 }
578
579#ifdef CONFIG_PROC_FS
580 proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net,
581 &ip_queue_proc_fops);
582 if (!proc) {
583 printk(KERN_ERR "ip_queue: failed to create proc entry\n");
584 goto cleanup_ipqnl;
585 }
586#endif
587 register_netdevice_notifier(&ipq_dev_notifier);
588#ifdef CONFIG_SYSCTL
589 ipq_sysctl_header = register_net_sysctl(&init_net, "net/ipv4", ipq_table);
590#endif
591 status = nf_register_queue_handler(NFPROTO_IPV4, &nfqh);
592 if (status < 0) {
593 printk(KERN_ERR "ip_queue: failed to register queue handler\n");
594 goto cleanup_sysctl;
595 }
596 return status;
597
598cleanup_sysctl:
599#ifdef CONFIG_SYSCTL
600 unregister_net_sysctl_table(ipq_sysctl_header);
601#endif
602 unregister_netdevice_notifier(&ipq_dev_notifier);
603 proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
604cleanup_ipqnl: __maybe_unused
605 netlink_kernel_release(ipqnl);
606 mutex_lock(&ipqnl_mutex);
607 mutex_unlock(&ipqnl_mutex);
608
609cleanup_netlink_notifier:
610 netlink_unregister_notifier(&ipq_nl_notifier);
611 return status;
612}
613
614static void __exit ip_queue_fini(void)
615{
616 nf_unregister_queue_handlers(&nfqh);
617
618 ipq_flush(NULL, 0);
619
620#ifdef CONFIG_SYSCTL
621 unregister_net_sysctl_table(ipq_sysctl_header);
622#endif
623 unregister_netdevice_notifier(&ipq_dev_notifier);
624 proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
625
626 netlink_kernel_release(ipqnl);
627 mutex_lock(&ipqnl_mutex);
628 mutex_unlock(&ipqnl_mutex);
629
630 netlink_unregister_notifier(&ipq_nl_notifier);
631}
632
633MODULE_DESCRIPTION("IPv4 packet queue handler");
634MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
635MODULE_LICENSE("GPL");
636MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_FIREWALL);
637
638module_init(ip_queue_init);
639module_exit(ip_queue_fini);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index d33cddd16fbb..10135342799e 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -25,28 +25,6 @@ config NF_CONNTRACK_IPV6
25 25
26 To compile it as a module, choose M here. If unsure, say N. 26 To compile it as a module, choose M here. If unsure, say N.
27 27
28config IP6_NF_QUEUE
29 tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)"
30 depends on INET && IPV6 && NETFILTER
31 depends on NETFILTER_ADVANCED
32 ---help---
33
34 This option adds a queue handler to the kernel for IPv6
35 packets which enables users to receive the filtered packets
36 with QUEUE target using libipq.
37
38 This option enables the old IPv6-only "ip6_queue" implementation
39 which has been obsoleted by the new "nfnetlink_queue" code (see
40 CONFIG_NETFILTER_NETLINK_QUEUE).
41
42 (C) Fernando Anton 2001
43 IPv64 Project - Work based in IPv64 draft by Arturo Azcorra.
44 Universidad Carlos III de Madrid
45 Universidad Politecnica de Alcala de Henares
46 email: <fanton@it.uc3m.es>.
47
48 To compile it as a module, choose M here. If unsure, say N.
49
50config IP6_NF_IPTABLES 28config IP6_NF_IPTABLES
51 tristate "IP6 tables support (required for filtering)" 29 tristate "IP6 tables support (required for filtering)"
52 depends on INET && IPV6 30 depends on INET && IPV6
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index d4dfd0a21097..534d3f216f7b 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -6,7 +6,6 @@
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 7obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
8obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 8obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
9obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
10obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 9obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
11obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 10obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
12 11
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
deleted file mode 100644
index 3ca9303b3a19..000000000000
--- a/net/ipv6/netfilter/ip6_queue.c
+++ /dev/null
@@ -1,641 +0,0 @@
1/*
2 * This is a module which is used for queueing IPv6 packets and
3 * communicating with userspace via netlink.
4 *
5 * (C) 2001 Fernando Anton, this code is GPL.
6 * IPv64 Project - Work based in IPv64 draft by Arturo Azcorra.
7 * Universidad Carlos III de Madrid - Leganes (Madrid) - Spain
8 * Universidad Politecnica de Alcala de Henares - Alcala de H. (Madrid) - Spain
9 * email: fanton@it.uc3m.es
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15#include <linux/module.h>
16#include <linux/skbuff.h>
17#include <linux/init.h>
18#include <linux/ipv6.h>
19#include <linux/notifier.h>
20#include <linux/netdevice.h>
21#include <linux/netfilter.h>
22#include <linux/netlink.h>
23#include <linux/spinlock.h>
24#include <linux/sysctl.h>
25#include <linux/proc_fs.h>
26#include <linux/seq_file.h>
27#include <linux/mutex.h>
28#include <linux/slab.h>
29#include <net/net_namespace.h>
30#include <net/sock.h>
31#include <net/ipv6.h>
32#include <net/ip6_route.h>
33#include <net/netfilter/nf_queue.h>
34#include <linux/netfilter_ipv4/ip_queue.h>
35#include <linux/netfilter_ipv4/ip_tables.h>
36#include <linux/netfilter_ipv6/ip6_tables.h>
37
38#define IPQ_QMAX_DEFAULT 1024
39#define IPQ_PROC_FS_NAME "ip6_queue"
40#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
41
42typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
43
44static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
45static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
46static DEFINE_SPINLOCK(queue_lock);
47static int peer_pid __read_mostly;
48static unsigned int copy_range __read_mostly;
49static unsigned int queue_total;
50static unsigned int queue_dropped = 0;
51static unsigned int queue_user_dropped = 0;
52static struct sock *ipqnl __read_mostly;
53static LIST_HEAD(queue_list);
54static DEFINE_MUTEX(ipqnl_mutex);
55
56static inline void
57__ipq_enqueue_entry(struct nf_queue_entry *entry)
58{
59 list_add_tail(&entry->list, &queue_list);
60 queue_total++;
61}
62
63static inline int
64__ipq_set_mode(unsigned char mode, unsigned int range)
65{
66 int status = 0;
67
68 switch(mode) {
69 case IPQ_COPY_NONE:
70 case IPQ_COPY_META:
71 copy_mode = mode;
72 copy_range = 0;
73 break;
74
75 case IPQ_COPY_PACKET:
76 if (range > 0xFFFF)
77 range = 0xFFFF;
78 copy_range = range;
79 copy_mode = mode;
80 break;
81
82 default:
83 status = -EINVAL;
84
85 }
86 return status;
87}
88
89static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data);
90
91static inline void
92__ipq_reset(void)
93{
94 peer_pid = 0;
95 net_disable_timestamp();
96 __ipq_set_mode(IPQ_COPY_NONE, 0);
97 __ipq_flush(NULL, 0);
98}
99
100static struct nf_queue_entry *
101ipq_find_dequeue_entry(unsigned long id)
102{
103 struct nf_queue_entry *entry = NULL, *i;
104
105 spin_lock_bh(&queue_lock);
106
107 list_for_each_entry(i, &queue_list, list) {
108 if ((unsigned long)i == id) {
109 entry = i;
110 break;
111 }
112 }
113
114 if (entry) {
115 list_del(&entry->list);
116 queue_total--;
117 }
118
119 spin_unlock_bh(&queue_lock);
120 return entry;
121}
122
123static void
124__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
125{
126 struct nf_queue_entry *entry, *next;
127
128 list_for_each_entry_safe(entry, next, &queue_list, list) {
129 if (!cmpfn || cmpfn(entry, data)) {
130 list_del(&entry->list);
131 queue_total--;
132 nf_reinject(entry, NF_DROP);
133 }
134 }
135}
136
137static void
138ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
139{
140 spin_lock_bh(&queue_lock);
141 __ipq_flush(cmpfn, data);
142 spin_unlock_bh(&queue_lock);
143}
144
145static struct sk_buff *
146ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
147{
148 sk_buff_data_t old_tail;
149 size_t size = 0;
150 size_t data_len = 0;
151 struct sk_buff *skb;
152 struct ipq_packet_msg *pmsg;
153 struct nlmsghdr *nlh;
154 struct timeval tv;
155
156 switch (ACCESS_ONCE(copy_mode)) {
157 case IPQ_COPY_META:
158 case IPQ_COPY_NONE:
159 size = NLMSG_SPACE(sizeof(*pmsg));
160 break;
161
162 case IPQ_COPY_PACKET:
163 if (entry->skb->ip_summed == CHECKSUM_PARTIAL &&
164 (*errp = skb_checksum_help(entry->skb)))
165 return NULL;
166
167 data_len = ACCESS_ONCE(copy_range);
168 if (data_len == 0 || data_len > entry->skb->len)
169 data_len = entry->skb->len;
170
171 size = NLMSG_SPACE(sizeof(*pmsg) + data_len);
172 break;
173
174 default:
175 *errp = -EINVAL;
176 return NULL;
177 }
178
179 skb = alloc_skb(size, GFP_ATOMIC);
180 if (!skb)
181 goto nlmsg_failure;
182
183 old_tail = skb->tail;
184 nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
185 pmsg = NLMSG_DATA(nlh);
186 memset(pmsg, 0, sizeof(*pmsg));
187
188 pmsg->packet_id = (unsigned long )entry;
189 pmsg->data_len = data_len;
190 tv = ktime_to_timeval(entry->skb->tstamp);
191 pmsg->timestamp_sec = tv.tv_sec;
192 pmsg->timestamp_usec = tv.tv_usec;
193 pmsg->mark = entry->skb->mark;
194 pmsg->hook = entry->hook;
195 pmsg->hw_protocol = entry->skb->protocol;
196
197 if (entry->indev)
198 strcpy(pmsg->indev_name, entry->indev->name);
199 else
200 pmsg->indev_name[0] = '\0';
201
202 if (entry->outdev)
203 strcpy(pmsg->outdev_name, entry->outdev->name);
204 else
205 pmsg->outdev_name[0] = '\0';
206
207 if (entry->indev && entry->skb->dev &&
208 entry->skb->mac_header != entry->skb->network_header) {
209 pmsg->hw_type = entry->skb->dev->type;
210 pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr);
211 }
212
213 if (data_len)
214 if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len))
215 BUG();
216
217 nlh->nlmsg_len = skb->tail - old_tail;
218 return skb;
219
220nlmsg_failure:
221 kfree_skb(skb);
222 *errp = -EINVAL;
223 printk(KERN_ERR "ip6_queue: error creating packet message\n");
224 return NULL;
225}
226
227static int
228ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
229{
230 int status = -EINVAL;
231 struct sk_buff *nskb;
232
233 if (copy_mode == IPQ_COPY_NONE)
234 return -EAGAIN;
235
236 nskb = ipq_build_packet_message(entry, &status);
237 if (nskb == NULL)
238 return status;
239
240 spin_lock_bh(&queue_lock);
241
242 if (!peer_pid)
243 goto err_out_free_nskb;
244
245 if (queue_total >= queue_maxlen) {
246 queue_dropped++;
247 status = -ENOSPC;
248 if (net_ratelimit())
249 printk (KERN_WARNING "ip6_queue: fill at %d entries, "
250 "dropping packet(s). Dropped: %d\n", queue_total,
251 queue_dropped);
252 goto err_out_free_nskb;
253 }
254
255 /* netlink_unicast will either free the nskb or attach it to a socket */
256 status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
257 if (status < 0) {
258 queue_user_dropped++;
259 goto err_out_unlock;
260 }
261
262 __ipq_enqueue_entry(entry);
263
264 spin_unlock_bh(&queue_lock);
265 return status;
266
267err_out_free_nskb:
268 kfree_skb(nskb);
269
270err_out_unlock:
271 spin_unlock_bh(&queue_lock);
272 return status;
273}
274
275static int
276ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
277{
278 int diff;
279 struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
280 struct sk_buff *nskb;
281
282 if (v->data_len < sizeof(*user_iph))
283 return 0;
284 diff = v->data_len - e->skb->len;
285 if (diff < 0) {
286 if (pskb_trim(e->skb, v->data_len))
287 return -ENOMEM;
288 } else if (diff > 0) {
289 if (v->data_len > 0xFFFF)
290 return -EINVAL;
291 if (diff > skb_tailroom(e->skb)) {
292 nskb = skb_copy_expand(e->skb, skb_headroom(e->skb),
293 diff, GFP_ATOMIC);
294 if (!nskb) {
295 printk(KERN_WARNING "ip6_queue: OOM "
296 "in mangle, dropping packet\n");
297 return -ENOMEM;
298 }
299 kfree_skb(e->skb);
300 e->skb = nskb;
301 }
302 skb_put(e->skb, diff);
303 }
304 if (!skb_make_writable(e->skb, v->data_len))
305 return -ENOMEM;
306 skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
307 e->skb->ip_summed = CHECKSUM_NONE;
308
309 return 0;
310}
311
312static int
313ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
314{
315 struct nf_queue_entry *entry;
316
317 if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN)
318 return -EINVAL;
319
320 entry = ipq_find_dequeue_entry(vmsg->id);
321 if (entry == NULL)
322 return -ENOENT;
323 else {
324 int verdict = vmsg->value;
325
326 if (vmsg->data_len && vmsg->data_len == len)
327 if (ipq_mangle_ipv6(vmsg, entry) < 0)
328 verdict = NF_DROP;
329
330 nf_reinject(entry, verdict);
331 return 0;
332 }
333}
334
335static int
336ipq_set_mode(unsigned char mode, unsigned int range)
337{
338 int status;
339
340 spin_lock_bh(&queue_lock);
341 status = __ipq_set_mode(mode, range);
342 spin_unlock_bh(&queue_lock);
343 return status;
344}
345
346static int
347ipq_receive_peer(struct ipq_peer_msg *pmsg,
348 unsigned char type, unsigned int len)
349{
350 int status = 0;
351
352 if (len < sizeof(*pmsg))
353 return -EINVAL;
354
355 switch (type) {
356 case IPQM_MODE:
357 status = ipq_set_mode(pmsg->msg.mode.value,
358 pmsg->msg.mode.range);
359 break;
360
361 case IPQM_VERDICT:
362 status = ipq_set_verdict(&pmsg->msg.verdict,
363 len - sizeof(*pmsg));
364 break;
365 default:
366 status = -EINVAL;
367 }
368 return status;
369}
370
371static int
372dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
373{
374 if (entry->indev)
375 if (entry->indev->ifindex == ifindex)
376 return 1;
377
378 if (entry->outdev)
379 if (entry->outdev->ifindex == ifindex)
380 return 1;
381#ifdef CONFIG_BRIDGE_NETFILTER
382 if (entry->skb->nf_bridge) {
383 if (entry->skb->nf_bridge->physindev &&
384 entry->skb->nf_bridge->physindev->ifindex == ifindex)
385 return 1;
386 if (entry->skb->nf_bridge->physoutdev &&
387 entry->skb->nf_bridge->physoutdev->ifindex == ifindex)
388 return 1;
389 }
390#endif
391 return 0;
392}
393
394static void
395ipq_dev_drop(int ifindex)
396{
397 ipq_flush(dev_cmp, ifindex);
398}
399
400#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
401
402static inline void
403__ipq_rcv_skb(struct sk_buff *skb)
404{
405 int status, type, pid, flags;
406 unsigned int nlmsglen, skblen;
407 struct nlmsghdr *nlh;
408 bool enable_timestamp = false;
409
410 skblen = skb->len;
411 if (skblen < sizeof(*nlh))
412 return;
413
414 nlh = nlmsg_hdr(skb);
415 nlmsglen = nlh->nlmsg_len;
416 if (nlmsglen < sizeof(*nlh) || skblen < nlmsglen)
417 return;
418
419 pid = nlh->nlmsg_pid;
420 flags = nlh->nlmsg_flags;
421
422 if(pid <= 0 || !(flags & NLM_F_REQUEST) || flags & NLM_F_MULTI)
423 RCV_SKB_FAIL(-EINVAL);
424
425 if (flags & MSG_TRUNC)
426 RCV_SKB_FAIL(-ECOMM);
427
428 type = nlh->nlmsg_type;
429 if (type < NLMSG_NOOP || type >= IPQM_MAX)
430 RCV_SKB_FAIL(-EINVAL);
431
432 if (type <= IPQM_BASE)
433 return;
434
435 if (!capable(CAP_NET_ADMIN))
436 RCV_SKB_FAIL(-EPERM);
437
438 spin_lock_bh(&queue_lock);
439
440 if (peer_pid) {
441 if (peer_pid != pid) {
442 spin_unlock_bh(&queue_lock);
443 RCV_SKB_FAIL(-EBUSY);
444 }
445 } else {
446 enable_timestamp = true;
447 peer_pid = pid;
448 }
449
450 spin_unlock_bh(&queue_lock);
451 if (enable_timestamp)
452 net_enable_timestamp();
453
454 status = ipq_receive_peer(NLMSG_DATA(nlh), type,
455 nlmsglen - NLMSG_LENGTH(0));
456 if (status < 0)
457 RCV_SKB_FAIL(status);
458
459 if (flags & NLM_F_ACK)
460 netlink_ack(skb, nlh, 0);
461}
462
463static void
464ipq_rcv_skb(struct sk_buff *skb)
465{
466 mutex_lock(&ipqnl_mutex);
467 __ipq_rcv_skb(skb);
468 mutex_unlock(&ipqnl_mutex);
469}
470
471static int
472ipq_rcv_dev_event(struct notifier_block *this,
473 unsigned long event, void *ptr)
474{
475 struct net_device *dev = ptr;
476
477 if (!net_eq(dev_net(dev), &init_net))
478 return NOTIFY_DONE;
479
480 /* Drop any packets associated with the downed device */
481 if (event == NETDEV_DOWN)
482 ipq_dev_drop(dev->ifindex);
483 return NOTIFY_DONE;
484}
485
486static struct notifier_block ipq_dev_notifier = {
487 .notifier_call = ipq_rcv_dev_event,
488};
489
490static int
491ipq_rcv_nl_event(struct notifier_block *this,
492 unsigned long event, void *ptr)
493{
494 struct netlink_notify *n = ptr;
495
496 if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) {
497 spin_lock_bh(&queue_lock);
498 if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid))
499 __ipq_reset();
500 spin_unlock_bh(&queue_lock);
501 }
502 return NOTIFY_DONE;
503}
504
505static struct notifier_block ipq_nl_notifier = {
506 .notifier_call = ipq_rcv_nl_event,
507};
508
509#ifdef CONFIG_SYSCTL
510static struct ctl_table_header *ipq_sysctl_header;
511
512static ctl_table ipq_table[] = {
513 {
514 .procname = NET_IPQ_QMAX_NAME,
515 .data = &queue_maxlen,
516 .maxlen = sizeof(queue_maxlen),
517 .mode = 0644,
518 .proc_handler = proc_dointvec
519 },
520 { }
521};
522#endif
523
524#ifdef CONFIG_PROC_FS
525static int ip6_queue_show(struct seq_file *m, void *v)
526{
527 spin_lock_bh(&queue_lock);
528
529 seq_printf(m,
530 "Peer PID : %d\n"
531 "Copy mode : %hu\n"
532 "Copy range : %u\n"
533 "Queue length : %u\n"
534 "Queue max. length : %u\n"
535 "Queue dropped : %u\n"
536 "Netfilter dropped : %u\n",
537 peer_pid,
538 copy_mode,
539 copy_range,
540 queue_total,
541 queue_maxlen,
542 queue_dropped,
543 queue_user_dropped);
544
545 spin_unlock_bh(&queue_lock);
546 return 0;
547}
548
549static int ip6_queue_open(struct inode *inode, struct file *file)
550{
551 return single_open(file, ip6_queue_show, NULL);
552}
553
554static const struct file_operations ip6_queue_proc_fops = {
555 .open = ip6_queue_open,
556 .read = seq_read,
557 .llseek = seq_lseek,
558 .release = single_release,
559 .owner = THIS_MODULE,
560};
561#endif
562
563static const struct nf_queue_handler nfqh = {
564 .name = "ip6_queue",
565 .outfn = &ipq_enqueue_packet,
566};
567
568static int __init ip6_queue_init(void)
569{
570 int status = -ENOMEM;
571 struct proc_dir_entry *proc __maybe_unused;
572
573 netlink_register_notifier(&ipq_nl_notifier);
574 ipqnl = netlink_kernel_create(&init_net, NETLINK_IP6_FW, 0,
575 ipq_rcv_skb, NULL, THIS_MODULE);
576 if (ipqnl == NULL) {
577 printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
578 goto cleanup_netlink_notifier;
579 }
580
581#ifdef CONFIG_PROC_FS
582 proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net,
583 &ip6_queue_proc_fops);
584 if (!proc) {
585 printk(KERN_ERR "ip6_queue: failed to create proc entry\n");
586 goto cleanup_ipqnl;
587 }
588#endif
589 register_netdevice_notifier(&ipq_dev_notifier);
590#ifdef CONFIG_SYSCTL
591 ipq_sysctl_header = register_net_sysctl(&init_net, "net/ipv6", ipq_table);
592#endif
593 status = nf_register_queue_handler(NFPROTO_IPV6, &nfqh);
594 if (status < 0) {
595 printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
596 goto cleanup_sysctl;
597 }
598 return status;
599
600cleanup_sysctl:
601#ifdef CONFIG_SYSCTL
602 unregister_net_sysctl_table(ipq_sysctl_header);
603#endif
604 unregister_netdevice_notifier(&ipq_dev_notifier);
605 proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
606
607cleanup_ipqnl: __maybe_unused
608 netlink_kernel_release(ipqnl);
609 mutex_lock(&ipqnl_mutex);
610 mutex_unlock(&ipqnl_mutex);
611
612cleanup_netlink_notifier:
613 netlink_unregister_notifier(&ipq_nl_notifier);
614 return status;
615}
616
617static void __exit ip6_queue_fini(void)
618{
619 nf_unregister_queue_handlers(&nfqh);
620
621 ipq_flush(NULL, 0);
622
623#ifdef CONFIG_SYSCTL
624 unregister_net_sysctl_table(ipq_sysctl_header);
625#endif
626 unregister_netdevice_notifier(&ipq_dev_notifier);
627 proc_net_remove(&init_net, IPQ_PROC_FS_NAME);
628
629 netlink_kernel_release(ipqnl);
630 mutex_lock(&ipqnl_mutex);
631 mutex_unlock(&ipqnl_mutex);
632
633 netlink_unregister_notifier(&ipq_nl_notifier);
634}
635
636MODULE_DESCRIPTION("IPv6 packet queue handler");
637MODULE_LICENSE("GPL");
638MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_IP6_FW);
639
640module_init(ip6_queue_init);
641module_exit(ip6_queue_fini);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 0920ea3bf599..d309e7f472d8 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -14,7 +14,6 @@
14#include <linux/netlink.h> 14#include <linux/netlink.h>
15#include <linux/rtnetlink.h> 15#include <linux/rtnetlink.h>
16#include <linux/if.h> 16#include <linux/if.h>
17#include <linux/netfilter_ipv4/ip_queue.h>
18#include <linux/inet_diag.h> 17#include <linux/inet_diag.h>
19#include <linux/xfrm.h> 18#include <linux/xfrm.h>
20#include <linux/audit.h> 19#include <linux/audit.h>
@@ -70,12 +69,6 @@ static struct nlmsg_perm nlmsg_route_perms[] =
70 { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, 69 { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
71}; 70};
72 71
73static struct nlmsg_perm nlmsg_firewall_perms[] =
74{
75 { IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
76 { IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
77};
78
79static struct nlmsg_perm nlmsg_tcpdiag_perms[] = 72static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
80{ 73{
81 { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, 74 { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
@@ -145,12 +138,6 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
145 sizeof(nlmsg_route_perms)); 138 sizeof(nlmsg_route_perms));
146 break; 139 break;
147 140
148 case SECCLASS_NETLINK_FIREWALL_SOCKET:
149 case SECCLASS_NETLINK_IP6FW_SOCKET:
150 err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms,
151 sizeof(nlmsg_firewall_perms));
152 break;
153
154 case SECCLASS_NETLINK_TCPDIAG_SOCKET: 141 case SECCLASS_NETLINK_TCPDIAG_SOCKET:
155 err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, 142 err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms,
156 sizeof(nlmsg_tcpdiag_perms)); 143 sizeof(nlmsg_tcpdiag_perms));