Root/target/linux/generic-2.4/patches/616-netfilter_imq.patch

1--- a/Documentation/Configure.help
2+++ b/Documentation/Configure.help
3@@ -3160,6 +3160,22 @@ CONFIG_IP_NF_TARGET_TOS
4   If you want to compile it as a module, say M here and read
5   <file:Documentation/modules.txt>. If unsure, say `N'.
6 
7+IMQ target support
8+CONFIG_IP_NF_TARGET_IMQ
9+ This option adds a `IMQ' target which is used to specify if and
10+ to which imq device packets should get enqueued/dequeued.
11+
12+ If you want to compile it as a module, say M here and read
13+ <file:Documentation/modules.txt>. If unsure, say `N'.
14+
15+IMQ target support
16+CONFIG_IP6_NF_TARGET_IMQ
17+ This option adds a `IMQ' target which is used to specify if and
18+ to which imq device packets should get enqueued/dequeued.
19+
20+ If you want to compile it as a module, say M here and read
21+ <file:Documentation/modules.txt>. If unsure, say `N'.
22+
23 MARK target support
24 CONFIG_IP_NF_TARGET_MARK
25   This option adds a `MARK' target, which allows you to create rules
26@@ -9862,6 +9878,20 @@ CONFIG_BONDING
27   say M here and read <file:Documentation/modules.txt>. The module
28   will be called bonding.o.
29 
30+Intermediate queueing device support
31+CONFIG_IMQ
32+ The imq device(s) is used as placeholder for QoS queueing disciplines.
33+ Every packet entering/leaving the ip stack can be directed through
34+ the imq device where it's enqueued/dequeued to the attached qdisc.
35+ This allows you to treat network devices as classes and distribute
36+ bandwidth among them. Iptables is used to specify through which imq
37+ device, if any, packets travel.
38+
39+ If you want to compile this as a module ( = code which ca be
40+ inserted in and removed from the running kernel whenever you want),
41+ say M here and read <file:Documentation/modules.txt>. The module
42+ will be called imq.o
43+
44 SLIP (serial line) support
45 CONFIG_SLIP
46   Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
47--- a/drivers/net/Config.in
48+++ b/drivers/net/Config.in
49@@ -7,6 +7,11 @@ source drivers/net/arcnet/Config.in
50 tristate 'Dummy net driver support' CONFIG_DUMMY
51 tristate 'Bonding driver support' CONFIG_BONDING
52 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
53+if [ "$CONFIG_NETFILTER" = "y" ]; then
54+ tristate 'IMQ (intermediate queueing device) support' CONFIG_IMQ
55+else
56+ comment 'IMQ needs CONFIG_NETFILTER enabled'
57+fi
58 tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
59 bool 'Allow Net Devices to contribute to /dev/random' CONFIG_NET_RANDOM
60 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
61--- a/drivers/net/Makefile
62+++ b/drivers/net/Makefile
63@@ -176,6 +176,7 @@ endif
64 
65 obj-$(CONFIG_STRIP) += strip.o
66 obj-$(CONFIG_DUMMY) += dummy.o
67+obj-$(CONFIG_IMQ) += imq.o
68 obj-$(CONFIG_DE600) += de600.o
69 obj-$(CONFIG_DE620) += de620.o
70 obj-$(CONFIG_AT1500) += lance.o
71--- /dev/null
72+++ b/drivers/net/imq.c
73@@ -0,0 +1,321 @@
74+/*
75+ * Pseudo-driver for the intermediate queue device.
76+ *
77+ * This program is free software; you can redistribute it and/or
78+ * modify it under the terms of the GNU General Public License
79+ * as published by the Free Software Foundation; either version
80+ * 2 of the License, or (at your option) any later version.
81+ *
82+ * Authors: Patrick McHardy, <kaber@trash.net>
83+ *
84+ * The first version was written by Martin Devera, <devik@cdi.cz>
85+ *
86+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
87+ * - Update patch to 2.4.21
88+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
89+ * - Fix "Dead-loop on netdevice imq"-issue
90+ */
91+
92+#include <linux/kernel.h>
93+#include <linux/module.h>
94+#include <linux/config.h>
95+#include <linux/skbuff.h>
96+#include <linux/netdevice.h>
97+#include <linux/rtnetlink.h>
98+#include <linux/if_arp.h>
99+#include <linux/netfilter.h>
100+#include <linux/netfilter_ipv4.h>
101+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
102+#include <linux/netfilter_ipv6.h>
103+#endif
104+#include <linux/imq.h>
105+#include <net/pkt_sched.h>
106+
107+static nf_hookfn imq_nf_hook;
108+
109+static struct nf_hook_ops imq_ingress_ipv4 = {
110+ { NULL, NULL},
111+ imq_nf_hook,
112+ PF_INET,
113+ NF_IP_PRE_ROUTING,
114+ NF_IP_PRI_MANGLE + 1
115+};
116+
117+static struct nf_hook_ops imq_egress_ipv4 = {
118+ { NULL, NULL},
119+ imq_nf_hook,
120+ PF_INET,
121+ NF_IP_POST_ROUTING,
122+ NF_IP_PRI_LAST
123+};
124+
125+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
126+static struct nf_hook_ops imq_ingress_ipv6 = {
127+ { NULL, NULL},
128+ imq_nf_hook,
129+ PF_INET6,
130+ NF_IP6_PRE_ROUTING,
131+ NF_IP6_PRI_MANGLE + 1
132+};
133+
134+static struct nf_hook_ops imq_egress_ipv6 = {
135+ { NULL, NULL},
136+ imq_nf_hook,
137+ PF_INET6,
138+ NF_IP6_POST_ROUTING,
139+ NF_IP6_PRI_LAST
140+};
141+#endif
142+
143+static unsigned int numdevs = 2;
144+
145+MODULE_PARM(numdevs, "i");
146+MODULE_PARM_DESC(numdevs, "number of imq devices");
147+
148+static struct net_device *imq_devs;
149+
150+
151+static struct net_device_stats *imq_get_stats(struct net_device *dev)
152+{
153+ return (struct net_device_stats *)dev->priv;
154+}
155+
156+/* called for packets kfree'd in qdiscs at places other than enqueue */
157+static void imq_skb_destructor(struct sk_buff *skb)
158+{
159+ struct nf_info *info = skb->nf_info;
160+
161+ if (info) {
162+ if (info->indev)
163+ dev_put(info->indev);
164+ if (info->outdev)
165+ dev_put(info->outdev);
166+ kfree(info);
167+ }
168+}
169+
170+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
171+{
172+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
173+
174+ stats->tx_bytes += skb->len;
175+ stats->tx_packets++;
176+
177+ skb->imq_flags = 0;
178+ skb->destructor = NULL;
179+
180+ dev->trans_start = jiffies;
181+ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
182+ return 0;
183+}
184+
185+static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info,
186+ void *data)
187+{
188+ struct net_device *dev;
189+ struct net_device_stats *stats;
190+ struct sk_buff *skb2 = NULL;
191+ struct Qdisc *q;
192+ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
193+ int ret = -1;
194+
195+ if (index > numdevs)
196+ return -1;
197+
198+ dev = imq_devs + index;
199+ if (!(dev->flags & IFF_UP)) {
200+ skb->imq_flags = 0;
201+ nf_reinject(skb, info, NF_ACCEPT);
202+ return 0;
203+ }
204+ dev->last_rx = jiffies;
205+
206+ if (skb->destructor) {
207+ skb2 = skb;
208+ skb = skb_clone(skb, GFP_ATOMIC);
209+ if (!skb)
210+ return -1;
211+ }
212+ skb->nf_info = info;
213+
214+ stats = (struct net_device_stats *)dev->priv;
215+ stats->rx_bytes+= skb->len;
216+ stats->rx_packets++;
217+
218+ spin_lock_bh(&dev->queue_lock);
219+ q = dev->qdisc;
220+ if (q->enqueue) {
221+ q->enqueue(skb_get(skb), q);
222+ if (skb_shared(skb)) {
223+ skb->destructor = imq_skb_destructor;
224+ kfree_skb(skb);
225+ ret = 0;
226+ }
227+ }
228+ if (spin_is_locked(&dev->xmit_lock))
229+ netif_schedule(dev);
230+ else
231+ qdisc_run(dev);
232+ spin_unlock_bh(&dev->queue_lock);
233+
234+ if (skb2)
235+ kfree_skb(ret ? skb : skb2);
236+
237+ return ret;
238+}
239+
240+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
241+ const struct net_device *indev,
242+ const struct net_device *outdev,
243+ int (*okfn)(struct sk_buff *))
244+{
245+ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
246+ return NF_QUEUE;
247+
248+ return NF_ACCEPT;
249+}
250+
251+
252+static int __init imq_init_hooks(void)
253+{
254+ int err;
255+
256+ if ((err = nf_register_queue_handler(PF_INET, imq_nf_queue, NULL)))
257+ goto err1;
258+ if ((err = nf_register_hook(&imq_ingress_ipv4)))
259+ goto err2;
260+ if ((err = nf_register_hook(&imq_egress_ipv4)))
261+ goto err3;
262+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
263+ if ((err = nf_register_queue_handler(PF_INET6, imq_nf_queue, NULL)))
264+ goto err4;
265+ if ((err = nf_register_hook(&imq_ingress_ipv6)))
266+ goto err5;
267+ if ((err = nf_register_hook(&imq_egress_ipv6)))
268+ goto err6;
269+#endif
270+
271+ return 0;
272+
273+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
274+err6:
275+ nf_unregister_hook(&imq_ingress_ipv6);
276+err5:
277+ nf_unregister_queue_handler(PF_INET6);
278+err4:
279+ nf_unregister_hook(&imq_egress_ipv4);
280+#endif
281+err3:
282+ nf_unregister_hook(&imq_ingress_ipv4);
283+err2:
284+ nf_unregister_queue_handler(PF_INET);
285+err1:
286+ return err;
287+}
288+
289+static void __exit imq_unhook(void)
290+{
291+ nf_unregister_hook(&imq_ingress_ipv4);
292+ nf_unregister_hook(&imq_egress_ipv4);
293+ nf_unregister_queue_handler(PF_INET);
294+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
295+ nf_unregister_hook(&imq_ingress_ipv6);
296+ nf_unregister_hook(&imq_egress_ipv6);
297+ nf_unregister_queue_handler(PF_INET6);
298+#endif
299+}
300+
301+static int __init imq_dev_init(struct net_device *dev)
302+{
303+ dev->hard_start_xmit = imq_dev_xmit;
304+ dev->type = ARPHRD_VOID;
305+ dev->mtu = 1500;
306+ dev->tx_queue_len = 30;
307+ dev->flags = IFF_NOARP;
308+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
309+ if (dev->priv == NULL)
310+ return -ENOMEM;
311+ memset(dev->priv, 0, sizeof(struct net_device_stats));
312+ dev->get_stats = imq_get_stats;
313+
314+ return 0;
315+}
316+
317+static void imq_dev_uninit(struct net_device *dev)
318+{
319+ kfree(dev->priv);
320+}
321+
322+static int __init imq_init_devs(void)
323+{
324+ struct net_device *dev;
325+ int i;
326+
327+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
328+ printk(KERN_ERR "numdevs has to be betweed 1 and %u\n",
329+ IMQ_MAX_DEVS);
330+ return -EINVAL;
331+ }
332+
333+ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
334+ if (!imq_devs)
335+ return -ENOMEM;
336+ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
337+
338+ /* we start counting at zero */
339+ numdevs--;
340+
341+ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
342+ SET_MODULE_OWNER(dev);
343+ strcpy(dev->name, "imq%d");
344+ dev->init = imq_dev_init;
345+ dev->uninit = imq_dev_uninit;
346+
347+ if (register_netdev(dev) < 0)
348+ goto err_register;
349+ }
350+ return 0;
351+
352+err_register:
353+ for (; i; i--)
354+ unregister_netdev(--dev);
355+ kfree(imq_devs);
356+ return -EIO;
357+}
358+
359+static void imq_cleanup_devs(void)
360+{
361+ int i;
362+ struct net_device *dev = imq_devs;
363+
364+ for (i = 0; i <= numdevs; i++)
365+ unregister_netdev(dev++);
366+
367+ kfree(imq_devs);
368+}
369+
370+static int __init imq_init_module(void)
371+{
372+ int err;
373+
374+ if ((err = imq_init_devs()))
375+ return err;
376+ if ((err = imq_init_hooks())) {
377+ imq_cleanup_devs();
378+ return err;
379+ }
380+
381+ printk(KERN_INFO "imq driver loaded.\n");
382+
383+ return 0;
384+}
385+
386+static void __exit imq_cleanup_module(void)
387+{
388+ imq_unhook();
389+ imq_cleanup_devs();
390+}
391+
392+module_init(imq_init_module);
393+module_exit(imq_cleanup_module);
394+MODULE_LICENSE("GPL");
395--- /dev/null
396+++ b/include/linux/imq.h
397@@ -0,0 +1,9 @@
398+#ifndef _IMQ_H
399+#define _IMQ_H
400+
401+#define IMQ_MAX_DEVS 16
402+
403+#define IMQ_F_IFMASK 0x7f
404+#define IMQ_F_ENQUEUE 0x80
405+
406+#endif /* _IMQ_H */
407--- /dev/null
408+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h
409@@ -0,0 +1,8 @@
410+#ifndef _IPT_IMQ_H
411+#define _IPT_IMQ_H
412+
413+struct ipt_imq_info {
414+ unsigned int todev; /* target imq device */
415+};
416+
417+#endif /* _IPT_IMQ_H */
418--- /dev/null
419+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h
420@@ -0,0 +1,8 @@
421+#ifndef _IP6T_IMQ_H
422+#define _IP6T_IMQ_H
423+
424+struct ip6t_imq_info {
425+ unsigned int todev; /* target imq device */
426+};
427+
428+#endif /* _IP6T_IMQ_H */
429--- a/include/linux/skbuff.h
430+++ b/include/linux/skbuff.h
431@@ -93,6 +93,9 @@ struct nf_ct_info {
432     struct nf_conntrack *master;
433 };
434 #endif
435+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
436+struct nf_info;
437+#endif
438 
439 struct sk_buff_head {
440     /* These two members must be first. */
441@@ -182,7 +185,7 @@ struct sk_buff {
442     unsigned int len; /* Length of actual data */
443      unsigned int data_len;
444     unsigned int csum; /* Checksum */
445- unsigned char __unused, /* Dead field, may be reused */
446+ unsigned char imq_flags, /* intermediate queueing device */
447             cloned, /* head may be cloned (check refcnt to be sure). */
448               pkt_type, /* Packet class */
449               ip_summed; /* Driver fed us an IP checksum */
450@@ -219,6 +222,9 @@ struct sk_buff {
451 #ifdef CONFIG_NET_SCHED
452        __u32 tc_index; /* traffic control index */
453 #endif
454+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
455+ struct nf_info *nf_info;
456+#endif
457 };
458 
459 #ifdef __KERNEL__
460--- a/net/core/skbuff.c
461+++ b/net/core/skbuff.c
462@@ -202,6 +202,10 @@ struct sk_buff *alloc_skb(unsigned int s
463     /* Set up other state */
464     skb->len = 0;
465     skb->cloned = 0;
466+#if defined(CONFIG_IMQ) || defined (CONFIG_IMQ_MODULE)
467+ skb->imq_flags = 0;
468+ skb->nf_info = NULL;
469+#endif
470     skb->data_len = 0;
471 
472     atomic_set(&skb->users, 1);
473@@ -250,6 +254,10 @@ static inline void skb_headerinit(void *
474 #ifdef CONFIG_NET_SCHED
475     skb->tc_index = 0;
476 #endif
477+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
478+ skb->imq_flags = 0;
479+ skb->nf_info = NULL;
480+#endif
481 }
482 
483 static void skb_drop_fraglist(struct sk_buff *skb)
484@@ -400,6 +408,10 @@ struct sk_buff *skb_clone(struct sk_buff
485 #ifdef CONFIG_NET_SCHED
486     C(tc_index);
487 #endif
488+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
489+ C(imq_flags);
490+ C(nf_info);
491+#endif
492 
493     atomic_inc(&(skb_shinfo(skb)->dataref));
494     skb->cloned = 1;
495@@ -444,6 +456,10 @@ static void copy_skb_header(struct sk_bu
496 #ifdef CONFIG_NET_SCHED
497     new->tc_index = old->tc_index;
498 #endif
499+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
500+ new->imq_flags=old->imq_flags;
501+ new->nf_info=old->nf_info;
502+#endif
503 }
504 
505 /**
506--- a/net/ipv4/netfilter/Config.in
507+++ b/net/ipv4/netfilter/Config.in
508@@ -141,6 +141,7 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ];
509     dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
510  
511     dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
512+ dep_tristate ' IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
513     dep_tristate ' CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_MANGLE
514   fi
515   if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
516--- a/net/ipv4/netfilter/Makefile
517+++ b/net/ipv4/netfilter/Makefile
518@@ -118,6 +118,7 @@ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TO
519 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
520 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
521 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
522+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
523 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
524 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
525 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
526--- /dev/null
527+++ b/net/ipv4/netfilter/ipt_IMQ.c
528@@ -0,0 +1,78 @@
529+/* This target marks packets to be enqueued to an imq device */
530+#include <linux/module.h>
531+#include <linux/skbuff.h>
532+#include <linux/netfilter_ipv4/ip_tables.h>
533+#include <linux/netfilter_ipv4/ipt_IMQ.h>
534+#include <linux/imq.h>
535+
536+static unsigned int imq_target(struct sk_buff **pskb,
537+ unsigned int hooknum,
538+ const struct net_device *in,
539+ const struct net_device *out,
540+ const void *targinfo,
541+ void *userinfo)
542+{
543+ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
544+
545+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
546+ (*pskb)->nfcache |= NFC_ALTERED;
547+
548+ return IPT_CONTINUE;
549+}
550+
551+static int imq_checkentry(const char *tablename,
552+ const struct ipt_entry *e,
553+ void *targinfo,
554+ unsigned int targinfosize,
555+ unsigned int hook_mask)
556+{
557+ struct ipt_imq_info *mr;
558+
559+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
560+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
561+ return 0;
562+ }
563+ mr = (struct ipt_imq_info*)targinfo;
564+
565+ if (strcmp(tablename, "mangle") != 0) {
566+ printk(KERN_WARNING
567+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
568+ tablename);
569+ return 0;
570+ }
571+
572+ if (mr->todev > IMQ_MAX_DEVS) {
573+ printk(KERN_WARNING
574+ "IMQ: invalid device specified, highest is %u\n",
575+ IMQ_MAX_DEVS);
576+ return 0;
577+ }
578+
579+ return 1;
580+}
581+
582+static struct ipt_target ipt_imq_reg = {
583+ { NULL, NULL},
584+ "IMQ",
585+ imq_target,
586+ imq_checkentry,
587+ NULL,
588+ THIS_MODULE
589+};
590+
591+static int __init init(void)
592+{
593+ if (ipt_register_target(&ipt_imq_reg))
594+ return -EINVAL;
595+
596+ return 0;
597+}
598+
599+static void __exit fini(void)
600+{
601+ ipt_unregister_target(&ipt_imq_reg);
602+}
603+
604+module_init(init);
605+module_exit(fini);
606+MODULE_LICENSE("GPL");
607--- a/net/ipv6/netfilter/Config.in
608+++ b/net/ipv6/netfilter/Config.in
609@@ -72,6 +72,7 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ];
610   if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
611 # dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
612     dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
613+ dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
614   fi
615   #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
616 fi
617--- a/net/ipv6/netfilter/Makefile
618+++ b/net/ipv6/netfilter/Makefile
619@@ -29,6 +29,7 @@ obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t
620 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
621 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
622 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
623+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
624 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
625 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
626 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
627--- /dev/null
628+++ b/net/ipv6/netfilter/ip6t_IMQ.c
629@@ -0,0 +1,78 @@
630+/* This target marks packets to be enqueued to an imq device */
631+#include <linux/module.h>
632+#include <linux/skbuff.h>
633+#include <linux/netfilter_ipv6/ip6_tables.h>
634+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
635+#include <linux/imq.h>
636+
637+static unsigned int imq_target(struct sk_buff **pskb,
638+ unsigned int hooknum,
639+ const struct net_device *in,
640+ const struct net_device *out,
641+ const void *targinfo,
642+ void *userinfo)
643+{
644+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
645+
646+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
647+ (*pskb)->nfcache |= NFC_ALTERED;
648+
649+ return IP6T_CONTINUE;
650+}
651+
652+static int imq_checkentry(const char *tablename,
653+ const struct ip6t_entry *e,
654+ void *targinfo,
655+ unsigned int targinfosize,
656+ unsigned int hook_mask)
657+{
658+ struct ip6t_imq_info *mr;
659+
660+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
661+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
662+ return 0;
663+ }
664+ mr = (struct ip6t_imq_info*)targinfo;
665+
666+ if (strcmp(tablename, "mangle") != 0) {
667+ printk(KERN_WARNING
668+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
669+ tablename);
670+ return 0;
671+ }
672+
673+ if (mr->todev > IMQ_MAX_DEVS) {
674+ printk(KERN_WARNING
675+ "IMQ: invalid device specified, highest is %u\n",
676+ IMQ_MAX_DEVS);
677+ return 0;
678+ }
679+
680+ return 1;
681+}
682+
683+static struct ip6t_target ip6t_imq_reg = {
684+ { NULL, NULL},
685+ "IMQ",
686+ imq_target,
687+ imq_checkentry,
688+ NULL,
689+ THIS_MODULE
690+};
691+
692+static int __init init(void)
693+{
694+ if (ip6t_register_target(&ip6t_imq_reg))
695+ return -EINVAL;
696+
697+ return 0;
698+}
699+
700+static void __exit fini(void)
701+{
702+ ip6t_unregister_target(&ip6t_imq_reg);
703+}
704+
705+module_init(init);
706+module_exit(fini);
707+MODULE_LICENSE("GPL");
708--- a/net/sched/sch_generic.c
709+++ b/net/sched/sch_generic.c
710@@ -29,6 +29,9 @@
711 #include <linux/skbuff.h>
712 #include <linux/rtnetlink.h>
713 #include <linux/init.h>
714+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
715+#include <linux/imq.h>
716+#endif
717 #include <linux/list.h>
718 #include <net/sock.h>
719 #include <net/pkt_sched.h>
720@@ -90,7 +93,11 @@ int qdisc_restart(struct net_device *dev
721             spin_unlock(&dev->queue_lock);
722 
723             if (!netif_queue_stopped(dev)) {
724- if (netdev_nit)
725+ if (netdev_nit
726+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
727+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
728+#endif
729+ )
730                     dev_queue_xmit_nit(skb, dev);
731 
732                 if (dev->hard_start_xmit(skb, dev) == 0) {
733

Archive Download this file



interactive