]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/linux-2.6.16-imq2.diff
Pakfire laedt die Listen jetzt besser und hat eine veraenderte Oberflaeche bekommen.
[ipfire-2.x.git] / src / patches / linux-2.6.16-imq2.diff
CommitLineData
3185932e
MT
1diff -Nru linux-2.6.16/drivers/net/Kconfig linux-2.6.16-imq/drivers/net/Kconfig
2--- linux-2.6.16/drivers/net/Kconfig 2006-03-20 05:53:29.000000000 +0000
3+++ linux-2.6.16-imq/drivers/net/Kconfig 2006-03-25 20:57:14.000000000 +0000
4@@ -93,6 +93,129 @@
5 To compile this driver as a module, choose M here: the module
6 will be called eql. If unsure, say N.
7
8+config IMQ
9+ tristate "IMQ (intermediate queueing device) support"
10+ depends on NETDEVICES && NETFILTER
11+ ---help---
12+ The IMQ device(s) is used as placeholder for QoS queueing disciplines.
13+ Every packet entering/leaving the IP stack can be directed through
14+ the IMQ device where it's enqueued/dequeued to the attached qdisc.
15+ This allows you to treat network devices as classes and distribute
16+ bandwidth among them. Iptables is used to specify through which IMQ
17+ device, if any, packets travel.
18+
19+ More information at: http://www.linuximq.net/
20+
21+ To compile this driver as a module, choose M here: the module
22+ will be called imq. If unsure, say N.
23+
24+choice
25+ prompt "IMQ behavior (PRE/POSTROUTING)"
26+ depends on IMQ
27+ default IMQ_BEHAVIOR_BA
28+ help
29+
30+ This settings defines how IMQ behaves in respect to its
31+ hooking in PREROUTING and POSTROUTING.
32+
33+ IMQ can work in any of the following ways:
34+
35+ PREROUTING | POSTROUTING
36+ -----------------|-------------------
37+ #1 After NAT | After NAT
38+ #2 After NAT | Before NAT
39+ #3 Before NAT | After NAT
40+ #4 Before NAT | Before NAT
41+
42+ The default behavior is to hook before NAT on PREROUTING
43+ and after NAT on POSTROUTING (#3).
44+
45+ This settings are specially usefull when trying to use IMQ
46+ to shape NATed clients.
47+
48+ More information can be found at: www.linuximq.net
49+
50+ If not sure leave the default settings alone.
51+
52+config IMQ_BEHAVIOR_AA
53+ bool "IMQ AA"
54+ help
55+ This settings defines how IMQ behaves in respect to its
56+ hooking in PREROUTING and POSTROUTING.
57+
58+ Choosing this option will make IMQ hook like this:
59+
60+ PREROUTING: After NAT
61+ POSTROUTING: After NAT
62+
63+ More information can be found at: www.linuximq.net
64+
65+ If not sure leave the default settings alone.
66+
67+config IMQ_BEHAVIOR_AB
68+ bool "IMQ AB"
69+ help
70+ This settings defines how IMQ behaves in respect to its
71+ hooking in PREROUTING and POSTROUTING.
72+
73+ Choosing this option will make IMQ hook like this:
74+
75+ PREROUTING: After NAT
76+ POSTROUTING: Before NAT
77+
78+ More information can be found at: www.linuximq.net
79+
80+ If not sure leave the default settings alone.
81+
82+config IMQ_BEHAVIOR_BA
83+ bool "IMQ BA"
84+ help
85+ This settings defines how IMQ behaves in respect to its
86+ hooking in PREROUTING and POSTROUTING.
87+
88+ Choosing this option will make IMQ hook like this:
89+
90+ PREROUTING: Before NAT
91+ POSTROUTING: After NAT
92+
93+ More information can be found at: www.linuximq.net
94+
95+ If not sure leave the default settings alone.
96+
97+config IMQ_BEHAVIOR_BB
98+ bool "IMQ BB"
99+ help
100+ This settings defines how IMQ behaves in respect to its
101+ hooking in PREROUTING and POSTROUTING.
102+
103+ Choosing this option will make IMQ hook like this:
104+
105+ PREROUTING: Before NAT
106+ POSTROUTING: Before NAT
107+
108+ More information can be found at: www.linuximq.net
109+
110+ If not sure leave the default settings alone.
111+
112+endchoice
113+
114+config IMQ_NUM_DEVS
115+
116+ int "Number of IMQ devices"
117+ range 2 8
118+ depends on IMQ
119+ default "2"
120+ help
121+
122+ This settings defines how many IMQ devices will be
123+ created.
124+
125+ The default value is 2.
126+
127+ More information can be found at: www.linuximq.net
128+
129+ If not sure leave the default settings alone.
130+
131 config TUN
132 tristate "Universal TUN/TAP device driver support"
133 select CRC32
134diff -Nru linux-2.6.16/drivers/net/Makefile linux-2.6.16-imq/drivers/net/Makefile
135--- linux-2.6.16/drivers/net/Makefile 2006-03-20 05:53:29.000000000 +0000
136+++ linux-2.6.16-imq/drivers/net/Makefile 2006-03-25 21:04:53.000000000 +0000
137@@ -125,6 +125,7 @@
138 endif
139
140 obj-$(CONFIG_DUMMY) += dummy.o
141+obj-$(CONFIG_IMQ) += imq.o
142 obj-$(CONFIG_IFB) += ifb.o
143 obj-$(CONFIG_DE600) += de600.o
144 obj-$(CONFIG_DE620) += de620.o
145diff -Nru linux-2.6.16/drivers/net/imq.c linux-2.6.16-imq/drivers/net/imq.c
146--- linux-2.6.16/drivers/net/imq.c 1970-01-01 00:00:00.000000000 +0000
147+++ linux-2.6.16-imq/drivers/net/imq.c 2006-03-25 20:57:14.000000000 +0000
148@@ -0,0 +1,403 @@
149+/*
150+ * Pseudo-driver for the intermediate queue device.
151+ *
152+ * This program is free software; you can redistribute it and/or
153+ * modify it under the terms of the GNU General Public License
154+ * as published by the Free Software Foundation; either version
155+ * 2 of the License, or (at your option) any later version.
156+ *
157+ * Authors: Patrick McHardy, <kaber@trash.net>
158+ *
159+ * The first version was written by Martin Devera, <devik@cdi.cz>
160+ *
161+ * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
162+ * - Update patch to 2.4.21
163+ * Sebastian Strollo <sstrollo@nortelnetworks.com>
164+ * - Fix "Dead-loop on netdevice imq"-issue
165+ * Marcel Sebek <sebek64@post.cz>
166+ * - Update to 2.6.2-rc1
167+ *
168+ * After some time of inactivity there is a group taking care
169+ * of IMQ again: http://www.linuximq.net
170+ *
171+ *
172+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including
173+ * the following changes:
174+ *
175+ * - Correction of ipv6 support "+"s issue (Hasso Tepper)
176+ * - Correction of imq_init_devs() issue that resulted in
177+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
178+ * - Addition of functionality to choose number of IMQ devices
179+ * during kernel config (Andre Correa)
180+ * - Addition of functionality to choose how IMQ hooks on
181+ * PRE and POSTROUTING (after or before NAT) (Andre Correa)
182+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
183+ *
184+ *
185+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
186+ * released with almost no problems. 2.6.14-x was released
187+ * with some important changes: nfcache was removed; After
188+ * some weeks of trouble we figured out that some IMQ fields
189+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
190+ * These functions are correctly patched by this new patch version.
191+ *
192+ * Thanks for all who helped to figure out all the problems with
193+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
194+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
195+ * I didn't forget anybody). I apologize again for my lack of time.
196+ *
197+ * More info at: http://www.linuximq.net/ (Andre Correa)
198+ */
199+
200+#include <linux/config.h>
201+#include <linux/module.h>
202+#include <linux/kernel.h>
203+#include <linux/moduleparam.h>
204+#include <linux/skbuff.h>
205+#include <linux/netdevice.h>
206+#include <linux/rtnetlink.h>
207+#include <linux/if_arp.h>
208+#include <linux/netfilter.h>
209+#include <linux/netfilter_ipv4.h>
210+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
211+ #include <linux/netfilter_ipv6.h>
212+#endif
213+#include <linux/imq.h>
214+#include <net/pkt_sched.h>
215+
216+static nf_hookfn imq_nf_hook;
217+
218+static struct nf_hook_ops imq_ingress_ipv4 = {
219+ .hook = imq_nf_hook,
220+ .owner = THIS_MODULE,
221+ .pf = PF_INET,
222+ .hooknum = NF_IP_PRE_ROUTING,
223+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
224+ .priority = NF_IP_PRI_MANGLE + 1
225+#else
226+ .priority = NF_IP_PRI_NAT_DST + 1
227+#endif
228+};
229+
230+static struct nf_hook_ops imq_egress_ipv4 = {
231+ .hook = imq_nf_hook,
232+ .owner = THIS_MODULE,
233+ .pf = PF_INET,
234+ .hooknum = NF_IP_POST_ROUTING,
235+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
236+ .priority = NF_IP_PRI_LAST
237+#else
238+ .priority = NF_IP_PRI_NAT_SRC - 1
239+#endif
240+};
241+
242+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
243+static struct nf_hook_ops imq_ingress_ipv6 = {
244+ .hook = imq_nf_hook,
245+ .owner = THIS_MODULE,
246+ .pf = PF_INET6,
247+ .hooknum = NF_IP6_PRE_ROUTING,
248+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
249+ .priority = NF_IP6_PRI_MANGLE + 1
250+#else
251+ .priority = NF_IP6_PRI_NAT_DST + 1
252+#endif
253+};
254+
255+static struct nf_hook_ops imq_egress_ipv6 = {
256+ .hook = imq_nf_hook,
257+ .owner = THIS_MODULE,
258+ .pf = PF_INET6,
259+ .hooknum = NF_IP6_POST_ROUTING,
260+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
261+ .priority = NF_IP6_PRI_LAST
262+#else
263+ .priority = NF_IP6_PRI_NAT_SRC - 1
264+#endif
265+};
266+#endif
267+
268+#if defined(CONFIG_IMQ_NUM_DEVS)
269+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
270+#else
271+static unsigned int numdevs = 2;
272+#endif
273+
274+static struct net_device *imq_devs;
275+
276+static struct net_device_stats *imq_get_stats(struct net_device *dev)
277+{
278+ return (struct net_device_stats *)dev->priv;
279+}
280+
281+/* called for packets kfree'd in qdiscs at places other than enqueue */
282+static void imq_skb_destructor(struct sk_buff *skb)
283+{
284+ struct nf_info *info = skb->nf_info;
285+
286+ if (info) {
287+ if (info->indev)
288+ dev_put(info->indev);
289+ if (info->outdev)
290+ dev_put(info->outdev);
291+ kfree(info);
292+ }
293+}
294+
295+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
296+{
297+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
298+
299+ stats->tx_bytes += skb->len;
300+ stats->tx_packets++;
301+
302+ skb->imq_flags = 0;
303+ skb->destructor = NULL;
304+
305+ dev->trans_start = jiffies;
306+ nf_reinject(skb, skb->nf_info, NF_ACCEPT);
307+ return 0;
308+}
309+
310+static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)
311+{
312+ struct net_device *dev;
313+ struct net_device_stats *stats;
314+ struct sk_buff *skb2 = NULL;
315+ struct Qdisc *q;
316+ unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
317+ int ret = -1;
318+
319+ if (index > numdevs)
320+ return -1;
321+
322+ dev = imq_devs + index;
323+ if (!(dev->flags & IFF_UP)) {
324+ skb->imq_flags = 0;
325+ nf_reinject(skb, info, NF_ACCEPT);
326+ return 0;
327+ }
328+ dev->last_rx = jiffies;
329+
330+ if (skb->destructor) {
331+ skb2 = skb;
332+ skb = skb_clone(skb, GFP_ATOMIC);
333+ if (!skb)
334+ return -1;
335+ }
336+ skb->nf_info = info;
337+
338+ stats = (struct net_device_stats *)dev->priv;
339+ stats->rx_bytes+= skb->len;
340+ stats->rx_packets++;
341+
342+ spin_lock_bh(&dev->queue_lock);
343+ q = dev->qdisc;
344+ if (q->enqueue) {
345+ q->enqueue(skb_get(skb), q);
346+ if (skb_shared(skb)) {
347+ skb->destructor = imq_skb_destructor;
348+ kfree_skb(skb);
349+ ret = 0;
350+ }
351+ }
352+ if (spin_is_locked(&dev->xmit_lock))
353+ netif_schedule(dev);
354+ else
355+
356+ while (!netif_queue_stopped(dev) &&
357+ qdisc_restart(dev)<0)
358+ /* NOTHING */;
359+
360+ spin_unlock_bh(&dev->queue_lock);
361+
362+ if (skb2)
363+ kfree_skb(ret ? skb : skb2);
364+
365+ return ret;
366+}
367+
368+static struct nf_queue_handler nfqh = {
369+ .name = "imq",
370+ .outfn = imq_nf_queue,
371+};
372+
373+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff **pskb,
374+ const struct net_device *indev,
375+ const struct net_device *outdev,
376+ int (*okfn)(struct sk_buff *))
377+{
378+ if ((*pskb)->imq_flags & IMQ_F_ENQUEUE)
379+ return NF_QUEUE;
380+
381+ return NF_ACCEPT;
382+}
383+
384+
385+static int __init imq_init_hooks(void)
386+{
387+ int err;
388+
389+ err = nf_register_queue_handler(PF_INET, &nfqh);
390+ if (err > 0)
391+ goto err1;
392+ if ((err = nf_register_hook(&imq_ingress_ipv4)))
393+ goto err2;
394+ if ((err = nf_register_hook(&imq_egress_ipv4)))
395+ goto err3;
396+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
397+ if ((err = nf_register_queue_handler(PF_INET6, &nfqh)))
398+ goto err4;
399+ if ((err = nf_register_hook(&imq_ingress_ipv6)))
400+ goto err5;
401+ if ((err = nf_register_hook(&imq_egress_ipv6)))
402+ goto err6;
403+#endif
404+
405+ return 0;
406+
407+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
408+err6:
409+ nf_unregister_hook(&imq_ingress_ipv6);
410+err5:
411+ nf_unregister_queue_handler(PF_INET6);
412+err4:
413+ nf_unregister_hook(&imq_egress_ipv6);
414+#endif
415+err3:
416+ nf_unregister_hook(&imq_ingress_ipv4);
417+err2:
418+ nf_unregister_queue_handler(PF_INET);
419+err1:
420+ return err;
421+}
422+
423+static void __exit imq_unhook(void)
424+{
425+ nf_unregister_hook(&imq_ingress_ipv4);
426+ nf_unregister_hook(&imq_egress_ipv4);
427+ nf_unregister_queue_handler(PF_INET);
428+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
429+ nf_unregister_hook(&imq_ingress_ipv6);
430+ nf_unregister_hook(&imq_egress_ipv6);
431+ nf_unregister_queue_handler(PF_INET6);
432+#endif
433+}
434+
435+static int __init imq_dev_init(struct net_device *dev)
436+{
437+ dev->hard_start_xmit = imq_dev_xmit;
438+ dev->type = ARPHRD_VOID;
439+ dev->mtu = 1500;
440+ dev->tx_queue_len = 30;
441+ dev->flags = IFF_NOARP;
442+ dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
443+ if (dev->priv == NULL)
444+ return -ENOMEM;
445+ memset(dev->priv, 0, sizeof(struct net_device_stats));
446+ dev->get_stats = imq_get_stats;
447+
448+ return 0;
449+}
450+
451+static void imq_dev_uninit(struct net_device *dev)
452+{
453+ kfree(dev->priv);
454+}
455+
456+static int __init imq_init_devs(void)
457+{
458+ struct net_device *dev;
459+ int i,j;
460+ j = numdevs;
461+
462+ if (!numdevs || numdevs > IMQ_MAX_DEVS) {
463+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
464+ IMQ_MAX_DEVS);
465+ return -EINVAL;
466+ }
467+
468+ imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL);
469+ if (!imq_devs)
470+ return -ENOMEM;
471+ memset(imq_devs, 0, sizeof(struct net_device) * numdevs);
472+
473+ /* we start counting at zero */
474+ numdevs--;
475+
476+ for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) {
477+ SET_MODULE_OWNER(dev);
478+ strcpy(dev->name, "imq%d");
479+ dev->init = imq_dev_init;
480+ dev->uninit = imq_dev_uninit;
481+
482+ if (register_netdev(dev) < 0)
483+ goto err_register;
484+ }
485+ printk(KERN_INFO "IMQ starting with %u devices...\n", j);
486+ return 0;
487+
488+err_register:
489+ for (; i; i--)
490+ unregister_netdev(--dev);
491+ kfree(imq_devs);
492+ return -EIO;
493+}
494+
495+static void imq_cleanup_devs(void)
496+{
497+ int i;
498+ struct net_device *dev = imq_devs;
499+
500+ for (i = 0; i <= numdevs; i++)
501+ unregister_netdev(dev++);
502+
503+ kfree(imq_devs);
504+}
505+
506+static int __init imq_init_module(void)
507+{
508+ int err;
509+
510+ if ((err = imq_init_devs())) {
511+ printk(KERN_ERR "IMQ: Error trying imq_init_devs()\n");
512+ return err;
513+ }
514+ if ((err = imq_init_hooks())) {
515+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
516+ imq_cleanup_devs();
517+ return err;
518+ }
519+
520+ printk(KERN_INFO "IMQ driver loaded successfully.\n");
521+
522+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
523+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
524+#else
525+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
526+#endif
527+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
528+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
529+#else
530+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
531+#endif
532+
533+ return 0;
534+}
535+
536+static void __exit imq_cleanup_module(void)
537+{
538+ imq_unhook();
539+ imq_cleanup_devs();
540+ printk(KERN_INFO "IMQ driver unloaded successfully.\n");
541+}
542+
543+
544+module_init(imq_init_module);
545+module_exit(imq_cleanup_module);
546+
547+module_param(numdevs, int, 0);
548+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will be created)");
549+MODULE_AUTHOR("http://www.linuximq.net");
550+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
551+MODULE_LICENSE("GPL");
552diff -Nru linux-2.6.16/include/linux/imq.h linux-2.6.16-imq/include/linux/imq.h
553--- linux-2.6.16/include/linux/imq.h 1970-01-01 00:00:00.000000000 +0000
554+++ linux-2.6.16-imq/include/linux/imq.h 2006-03-25 20:57:14.000000000 +0000
555@@ -0,0 +1,9 @@
556+#ifndef _IMQ_H
557+#define _IMQ_H
558+
559+#define IMQ_MAX_DEVS 16
560+
561+#define IMQ_F_IFMASK 0x7f
562+#define IMQ_F_ENQUEUE 0x80
563+
564+#endif /* _IMQ_H */
565diff -Nru linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.16-imq/include/linux/netfilter_ipv4/ipt_IMQ.h
566--- linux-2.6.16/include/linux/netfilter_ipv4/ipt_IMQ.h 1970-01-01 00:00:00.000000000 +0000
567+++ linux-2.6.16-imq/include/linux/netfilter_ipv4/ipt_IMQ.h 2006-03-25 20:57:14.000000000 +0000
568@@ -0,0 +1,8 @@
569+#ifndef _IPT_IMQ_H
570+#define _IPT_IMQ_H
571+
572+struct ipt_imq_info {
573+ unsigned int todev; /* target imq device */
574+};
575+
576+#endif /* _IPT_IMQ_H */
577diff -Nru linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.16-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h
578--- linux-2.6.16/include/linux/netfilter_ipv6/ip6t_IMQ.h 1970-01-01 00:00:00.000000000 +0000
579+++ linux-2.6.16-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h 2006-03-25 20:57:14.000000000 +0000
580@@ -0,0 +1,8 @@
581+#ifndef _IP6T_IMQ_H
582+#define _IP6T_IMQ_H
583+
584+struct ip6t_imq_info {
585+ unsigned int todev; /* target imq device */
586+};
587+
588+#endif /* _IP6T_IMQ_H */
589diff -Nru linux-2.6.16/include/linux/skbuff.h linux-2.6.16-imq/include/linux/skbuff.h
590--- linux-2.6.16/include/linux/skbuff.h 2006-03-20 05:53:29.000000000 +0000
591+++ linux-2.6.16-imq/include/linux/skbuff.h 2006-03-25 20:57:14.000000000 +0000
592@@ -275,6 +275,10 @@
593 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
594 struct sk_buff *nfct_reasm;
595 #endif
596+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
597+ unsigned char imq_flags;
598+ struct nf_info *nf_info;
599+#endif
600 #ifdef CONFIG_BRIDGE_NETFILTER
601 struct nf_bridge_info *nf_bridge;
602 #endif
603diff -Nru linux-2.6.16/net/core/skbuff.c linux-2.6.16-imq/net/core/skbuff.c
604--- linux-2.6.16/net/core/skbuff.c 2006-03-20 05:53:29.000000000 +0000
605+++ linux-2.6.16-imq/net/core/skbuff.c 2006-03-25 20:57:14.000000000 +0000
606@@ -425,6 +425,10 @@
607 C(nfct_reasm);
608 nf_conntrack_get_reasm(skb->nfct_reasm);
609 #endif
610+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
611+ C(imq_flags);
612+ C(nf_info);
613+#endif /*CONFIG_IMQ*/
614 #ifdef CONFIG_BRIDGE_NETFILTER
615 C(nf_bridge);
616 nf_bridge_get(skb->nf_bridge);
617@@ -489,6 +493,10 @@
618 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
619 new->ipvs_property = old->ipvs_property;
620 #endif
621+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
622+ new->imq_flags = old->imq_flags;
623+ new->nf_info = old->nf_info;
624+#endif /*CONFIG_IMQ*/
625 #ifdef CONFIG_BRIDGE_NETFILTER
626 new->nf_bridge = old->nf_bridge;
627 nf_bridge_get(old->nf_bridge);
628diff -Nru linux-2.6.16/net/ipv4/netfilter/Kconfig linux-2.6.16-imq/net/ipv4/netfilter/Kconfig
629--- linux-2.6.16/net/ipv4/netfilter/Kconfig 2006-03-20 05:53:29.000000000 +0000
630+++ linux-2.6.16-imq/net/ipv4/netfilter/Kconfig 2006-03-25 21:54:10.000000000 +0000
631@@ -505,6 +505,17 @@
632
633 To compile it as a module, choose M here. If unsure, say N.
634
635+config IP_NF_TARGET_IMQ
636+ tristate "IMQ target support"
637+ depends on IP_NF_MANGLE
638+ help
639+ This option adds a `IMQ' target which is used to specify if and
640+ to which IMQ device packets should get enqueued/dequeued.
641+
642+ For more information visit: http://www.linuximq.net/
643+
644+ To compile it as a module, choose M here. If unsure, say N.
645+
646 config IP_NF_TARGET_TOS
647 tristate "TOS target support"
648 depends on IP_NF_MANGLE
649diff -Nru linux-2.6.16/net/ipv4/netfilter/Makefile linux-2.6.16-imq/net/ipv4/netfilter/Makefile
650--- linux-2.6.16/net/ipv4/netfilter/Makefile 2006-03-20 05:53:29.000000000 +0000
651+++ linux-2.6.16-imq/net/ipv4/netfilter/Makefile 2006-03-25 21:06:00.000000000 +0000
652@@ -64,6 +64,7 @@
653 obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
654 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
655 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
656+obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
657 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
658 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
659 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
660diff -Nru linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c linux-2.6.16-imq/net/ipv4/netfilter/ipt_IMQ.c
661--- linux-2.6.16/net/ipv4/netfilter/ipt_IMQ.c 1970-01-01 00:00:00.000000000 +0000
662+++ linux-2.6.16-imq/net/ipv4/netfilter/ipt_IMQ.c 2006-03-25 20:57:14.000000000 +0000
663@@ -0,0 +1,80 @@
664+/*
665+ * This target marks packets to be enqueued to an imq device
666+ */
667+#include <linux/module.h>
668+#include <linux/skbuff.h>
669+#include <linux/netfilter_ipv4/ip_tables.h>
670+#include <linux/netfilter_ipv4/ipt_IMQ.h>
671+#include <linux/imq.h>
672+
673+static unsigned int imq_target(struct sk_buff **pskb,
674+ const struct net_device *in,
675+ const struct net_device *out,
676+ unsigned int hooknum,
677+ const void *targinfo,
678+ void *userdata)
679+{
680+ struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
681+
682+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
683+
684+ return IPT_CONTINUE;
685+}
686+
687+static int imq_checkentry(const char *tablename,
688+ const struct ipt_entry *e,
689+ void *targinfo,
690+ unsigned int targinfosize,
691+ unsigned int hook_mask)
692+{
693+ struct ipt_imq_info *mr;
694+
695+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
696+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
697+ return 0;
698+ }
699+ mr = (struct ipt_imq_info*)targinfo;
700+
701+ if (strcmp(tablename, "mangle") != 0) {
702+ printk(KERN_WARNING
703+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
704+ tablename);
705+ return 0;
706+ }
707+
708+ if (mr->todev > IMQ_MAX_DEVS) {
709+ printk(KERN_WARNING
710+ "IMQ: invalid device specified, highest is %u\n",
711+ IMQ_MAX_DEVS);
712+ return 0;
713+ }
714+
715+ return 1;
716+}
717+
718+static struct ipt_target ipt_imq_reg = {
719+ .name = "IMQ",
720+ .target = imq_target,
721+ .checkentry = imq_checkentry,
722+ .me = THIS_MODULE
723+};
724+
725+static int __init init(void)
726+{
727+ if (ipt_register_target(&ipt_imq_reg))
728+ return -EINVAL;
729+
730+ return 0;
731+}
732+
733+static void __exit fini(void)
734+{
735+ ipt_unregister_target(&ipt_imq_reg);
736+}
737+
738+module_init(init);
739+module_exit(fini);
740+
741+MODULE_AUTHOR("http://www.linuximq.net");
742+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
743+MODULE_LICENSE("GPL");
744diff -Nru linux-2.6.16/net/ipv6/netfilter/Kconfig linux-2.6.16-imq/net/ipv6/netfilter/Kconfig
745--- linux-2.6.16/net/ipv6/netfilter/Kconfig 2006-03-20 05:53:29.000000000 +0000
746+++ linux-2.6.16-imq/net/ipv6/netfilter/Kconfig 2006-03-25 21:54:48.000000000 +0000
747@@ -183,6 +183,15 @@
748
749 To compile it as a module, choose M here. If unsure, say N.
750
751+config IP6_NF_TARGET_IMQ
752+ tristate "IMQ target support"
753+ depends on IP6_NF_MANGLE
754+ help
755+ This option adds a `IMQ' target which is used to specify if and
756+ to which imq device packets should get enqueued/dequeued.
757+
758+ To compile it as a module, choose M here. If unsure, say N.
759+
760 config IP6_NF_TARGET_HL
761 tristate 'HL (hoplimit) target support'
762 depends on IP6_NF_MANGLE
763diff -Nru linux-2.6.16/net/ipv6/netfilter/Makefile linux-2.6.16-imq/net/ipv6/netfilter/Makefile
764--- linux-2.6.16/net/ipv6/netfilter/Makefile 2006-03-20 05:53:29.000000000 +0000
765+++ linux-2.6.16-imq/net/ipv6/netfilter/Makefile 2006-03-25 21:07:08.000000000 +0000
766@@ -15,6 +15,7 @@
767 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
768 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
769 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
770+obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
771 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
772 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
773 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
774diff -Nru linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c linux-2.6.16-imq/net/ipv6/netfilter/ip6t_IMQ.c
775--- linux-2.6.16/net/ipv6/netfilter/ip6t_IMQ.c 1970-01-01 00:00:00.000000000 +0000
776+++ linux-2.6.16-imq/net/ipv6/netfilter/ip6t_IMQ.c 2006-03-25 20:57:14.000000000 +0000
777@@ -0,0 +1,80 @@
778+/*
779+ * This target marks packets to be enqueued to an imq device
780+ */
781+#include <linux/module.h>
782+#include <linux/skbuff.h>
783+#include <linux/netfilter_ipv6/ip6_tables.h>
784+#include <linux/netfilter_ipv6/ip6t_IMQ.h>
785+#include <linux/imq.h>
786+
787+static unsigned int imq_target(struct sk_buff **pskb,
788+ unsigned int hooknum,
789+ const struct net_device *in,
790+ const struct net_device *out,
791+ const void *targinfo,
792+ void *userdata)
793+{
794+ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
795+
796+ (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
797+
798+ return IP6T_CONTINUE;
799+}
800+
801+static int imq_checkentry(const char *tablename,
802+ const struct ip6t_entry *e,
803+ void *targinfo,
804+ unsigned int targinfosize,
805+ unsigned int hook_mask)
806+{
807+ struct ip6t_imq_info *mr;
808+
809+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
810+ printk(KERN_WARNING "IMQ: invalid targinfosize\n");
811+ return 0;
812+ }
813+ mr = (struct ip6t_imq_info*)targinfo;
814+
815+ if (strcmp(tablename, "mangle") != 0) {
816+ printk(KERN_WARNING
817+ "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
818+ tablename);
819+ return 0;
820+ }
821+
822+ if (mr->todev > IMQ_MAX_DEVS) {
823+ printk(KERN_WARNING
824+ "IMQ: invalid device specified, highest is %u\n",
825+ IMQ_MAX_DEVS);
826+ return 0;
827+ }
828+
829+ return 1;
830+}
831+
832+static struct ip6t_target ip6t_imq_reg = {
833+ .name = "IMQ",
834+ .target = imq_target,
835+ .checkentry = imq_checkentry,
836+ .me = THIS_MODULE
837+};
838+
839+static int __init init(void)
840+{
841+ if (ip6t_register_target(&ip6t_imq_reg))
842+ return -EINVAL;
843+
844+ return 0;
845+}
846+
847+static void __exit fini(void)
848+{
849+ ip6t_unregister_target(&ip6t_imq_reg);
850+}
851+
852+module_init(init);
853+module_exit(fini);
854+
855+MODULE_AUTHOR("http://www.linuximq.net");
856+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
857+MODULE_LICENSE("GPL");
858diff -Nru linux-2.6.16/net/sched/sch_generic.c linux-2.6.16-imq/net/sched/sch_generic.c
859--- linux-2.6.16/net/sched/sch_generic.c 2006-03-20 05:53:29.000000000 +0000
860+++ linux-2.6.16-imq/net/sched/sch_generic.c 2006-03-25 20:57:14.000000000 +0000
861@@ -29,6 +29,9 @@
862 #include <linux/netdevice.h>
863 #include <linux/skbuff.h>
864 #include <linux/rtnetlink.h>
865+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
866+#include <linux/imq.h>
867+#endif
868 #include <linux/init.h>
869 #include <linux/rcupdate.h>
870 #include <linux/list.h>
871@@ -136,7 +139,13 @@
872
873 if (!netif_queue_stopped(dev)) {
874 int ret;
875- if (netdev_nit)
876+
877+ if (netdev_nit
878+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
879+ && !(skb->imq_flags & IMQ_F_ENQUEUE)
880+#endif
881+ )
882+
883 dev_queue_xmit_nit(skb, dev);
884
885 ret = dev->hard_start_xmit(skb, dev);