2 * Pseudo-driver for the intermediate queue device.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Patrick McHardy, <kaber@trash.net>
11 * The first version was written by Martin Devera, <devik@cdi.cz>
13 * Credits: Jan Rafaj <imq2t@cedric.vabo.cz>
14 * - Update patch to 2.4.21
15 * Sebastian Strollo <sstrollo@nortelnetworks.com>
16 * - Fix "Dead-loop on netdevice imq"-issue
17 * Marcel Sebek <sebek64@post.cz>
18 * - Update to 2.6.2-rc1
20 * After some time of inactivity there is a group taking care
21 * of IMQ again: http://www.linuximq.net
24 * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 including
25 * the following changes:
27 * - Correction of ipv6 support "+"s issue (Hasso Tepper)
28 * - Correction of imq_init_devs() issue that resulted in
29 * kernel OOPS unloading IMQ as module (Norbert Buchmuller)
30 * - Addition of functionality to choose number of IMQ devices
31 * during kernel config (Andre Correa)
32 * - Addition of functionality to choose how IMQ hooks on
33 * PRE and POSTROUTING (after or before NAT) (Andre Correa)
34 * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
37 * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
38 * released with almost no problems. 2.6.14-x was released
39 * with some important changes: nfcache was removed; After
40 * some weeks of trouble we figured out that some IMQ fields
41 * in skb were missing in skbuff.c - skb_clone and copy_skb_header.
42 * These functions are correctly patched by this new patch version.
44 * Thanks for all who helped to figure out all the problems with
45 * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
46 * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
47 * I didn't forget anybody). I apologize again for my lack of time.
49 * More info at: http://www.linuximq.net/ (Andre Correa)
52 #include <linux/module.h>
53 #include <linux/kernel.h>
54 #include <linux/moduleparam.h>
55 #include <linux/skbuff.h>
56 #include <linux/netdevice.h>
57 #include <linux/rtnetlink.h>
58 #include <linux/if_arp.h>
59 #include <linux/netfilter.h>
60 #include <linux/netfilter_ipv4.h>
61 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
62 #include <linux/netfilter_ipv6.h>
64 #include <linux/imq.h>
65 #include <net/pkt_sched.h>
67 extern int qdisc_restart1(struct net_device
*dev
);
69 static nf_hookfn imq_nf_hook
;
71 static struct nf_hook_ops imq_ingress_ipv4
= {
75 .hooknum
= NF_IP_PRE_ROUTING
,
76 .priority
= NF_IP_PRI_MANGLE
+ 1
79 static struct nf_hook_ops imq_egress_ipv4
= {
83 .hooknum
= NF_IP_POST_ROUTING
,
84 .priority
= NF_IP_PRI_NAT_SRC
- 1
87 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
88 static struct nf_hook_ops imq_ingress_ipv6
= {
92 .hooknum
= NF_IP6_PRE_ROUTING
,
93 .priority
= NF_IP6_PRI_MANGLE
+ 1
96 static struct nf_hook_ops imq_egress_ipv6
= {
100 .hooknum
= NF_IP6_POST_ROUTING
,
101 .priority
= NF_IP6_PRI_NAT_SRC
- 1
105 #if defined(CONFIG_IMQ_NUM_DEVS)
106 static unsigned int numdevs
= CONFIG_IMQ_NUM_DEVS
;
108 static unsigned int numdevs
= IMQ_MAX_DEVS
;
111 static char *behaviour
;
113 #if defined(CONFIG_IMQ_BEHAVIOR_BB)
114 static int imq_behaviour
= 0;
115 #elif defined(CONFIG_IMQ_BEHAVIOR_BA)
116 static int imq_behaviour
= IMQ_BEHAV_EGRESS_AFTER
;
117 #elif defined(CONFIG_IMQ_BEHAVIOR_AB)
118 static int imq_behaviour
= IMQ_BEHAV_INGRESS_AFTER
;
119 #elif defined(CONFIG_IMQ_BEHAVIOR_AA)
120 static int imq_behaviour
= IMQ_BEHAV_INGRESS_AFTER
| IMQ_BEHAV_EGRESS_AFTER
;
122 static int imq_behaviour
= IMQ_BEHAV_EGRESS_AFTER
;
125 static struct net_device
*imq_devs
;
127 static struct net_device_stats
*imq_get_stats(struct net_device
*dev
)
129 return (struct net_device_stats
*)dev
->priv
;
132 /* called for packets kfree'd in qdiscs at places other than enqueue */
133 static void imq_skb_destructor(struct sk_buff
*skb
)
135 struct nf_info
*info
= skb
->nf_info
;
139 dev_put(info
->indev
);
141 dev_put(info
->outdev
);
146 static int imq_dev_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
148 struct net_device_stats
*stats
= (struct net_device_stats
*) dev
->priv
;
150 stats
->tx_bytes
+= skb
->len
;
154 skb
->destructor
= NULL
;
156 dev
->trans_start
= jiffies
;
157 nf_reinject(skb
, skb
->nf_info
, NF_ACCEPT
);
161 static int imq_nf_queue(struct sk_buff
*skb
, struct nf_info
*info
, unsigned queue_num
, void *data
)
163 struct net_device
*dev
;
164 struct net_device_stats
*stats
;
165 struct sk_buff
*skb2
= NULL
;
167 unsigned int index
= skb
->imq_flags
& IMQ_F_IFMASK
;
173 dev
= imq_devs
+ index
;
174 if (!(dev
->flags
& IFF_UP
)) {
176 nf_reinject(skb
, info
, NF_ACCEPT
);
179 dev
->last_rx
= jiffies
;
181 if (skb
->destructor
) {
183 skb
= skb_clone(skb
, GFP_ATOMIC
);
189 stats
= (struct net_device_stats
*)dev
->priv
;
190 stats
->rx_bytes
+= skb
->len
;
193 spin_lock_bh(&dev
->queue_lock
);
196 q
->enqueue(skb_get(skb
), q
);
197 if (skb_shared(skb
)) {
198 skb
->destructor
= imq_skb_destructor
;
203 if (spin_is_locked(&dev
->_xmit_lock
))
206 while (!netif_queue_stopped(dev
) && qdisc_restart1(dev
) < 0)
209 spin_unlock_bh(&dev
->queue_lock
);
212 kfree_skb(ret
? skb
: skb2
);
217 static struct nf_queue_handler nfqh
= {
219 .outfn
= imq_nf_queue
,
222 static unsigned int imq_nf_hook(unsigned int hook
, struct sk_buff
*skb
,
223 const struct net_device
*indev
,
224 const struct net_device
*outdev
,
225 int (*okfn
)(struct sk_buff
*))
227 if (skb
->imq_flags
& IMQ_F_ENQUEUE
)
234 static int __init
imq_init_hooks(void)
239 if (strlen(behaviour
) == 2) {
240 if (behaviour
[0] == 'b')
241 imq_behaviour
&= ~IMQ_BEHAV_INGRESS_AFTER
;
242 else if (behaviour
[0] == 'a')
243 imq_behaviour
|= IMQ_BEHAV_INGRESS_AFTER
;
246 if (behaviour
[1] == 'b')
247 imq_behaviour
&= ~IMQ_BEHAV_EGRESS_AFTER
;
248 else if (behaviour
[1] == 'a')
249 imq_behaviour
|= IMQ_BEHAV_EGRESS_AFTER
;
257 if (imq_behaviour
& IMQ_BEHAV_INGRESS_AFTER
) {
258 imq_ingress_ipv4
.priority
= NF_IP_PRI_NAT_DST
+ 1;
259 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
260 imq_ingress_ipv6
.priority
= NF_IP6_PRI_NAT_DST
+ 1;
263 if (imq_behaviour
& IMQ_BEHAV_EGRESS_AFTER
) {
264 imq_egress_ipv4
.priority
= NF_IP_PRI_LAST
;
265 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
266 imq_egress_ipv6
.priority
= NF_IP6_PRI_LAST
;
270 err
= nf_register_queue_handler(PF_INET
, &nfqh
);
273 if ((err
= nf_register_hook(&imq_ingress_ipv4
)))
275 if ((err
= nf_register_hook(&imq_egress_ipv4
)))
277 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
278 if ((err
= nf_register_queue_handler(PF_INET6
, &nfqh
)))
280 if ((err
= nf_register_hook(&imq_ingress_ipv6
)))
282 if ((err
= nf_register_hook(&imq_egress_ipv6
)))
289 printk(KERN_ERR
"IMQ: behaviour must be one of these: \"bb\", \"ba\", \"ab\", \"aa\".\n");
291 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
293 nf_unregister_hook(&imq_ingress_ipv6
);
295 nf_unregister_queue_handler(PF_INET6
);
297 nf_unregister_hook(&imq_egress_ipv4
);
300 nf_unregister_hook(&imq_ingress_ipv4
);
302 nf_unregister_queue_handler(PF_INET
);
307 static void __exit
imq_unhook(void)
309 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
310 nf_unregister_hook(&imq_ingress_ipv6
);
311 nf_unregister_hook(&imq_egress_ipv6
);
312 nf_unregister_queue_handler(PF_INET6
);
314 nf_unregister_hook(&imq_ingress_ipv4
);
315 nf_unregister_hook(&imq_egress_ipv4
);
316 nf_unregister_queue_handler(PF_INET
);
319 static int __init
imq_dev_init(struct net_device
*dev
)
321 dev
->hard_start_xmit
= imq_dev_xmit
;
322 dev
->type
= ARPHRD_VOID
;
324 dev
->tx_queue_len
= 30;
325 dev
->flags
= IFF_NOARP
;
326 dev
->priv
= kzalloc(sizeof(struct net_device_stats
), GFP_KERNEL
);
327 if (dev
->priv
== NULL
)
329 dev
->get_stats
= imq_get_stats
;
334 static void imq_dev_uninit(struct net_device
*dev
)
339 static int __init
imq_init_devs(void)
341 struct net_device
*dev
;
345 if (numdevs
< 1 || numdevs
> IMQ_MAX_DEVS
) {
346 printk(KERN_ERR
"IMQ: numdevs has to be betweed 1 and %u\n",
351 imq_devs
= kzalloc(sizeof(struct net_device
) * numdevs
, GFP_KERNEL
);
355 /* we start counting at zero */
358 for (i
= 0, dev
= imq_devs
; i
<= numdevs
; i
++, dev
++) {
359 SET_MODULE_OWNER(dev
);
360 strcpy(dev
->name
, "imq%d");
361 dev
->init
= imq_dev_init
;
362 dev
->uninit
= imq_dev_uninit
;
364 if (register_netdev(dev
) < 0)
367 printk(KERN_INFO
"IMQ starting with %u devices...\n", j
);
372 unregister_netdev(--dev
);
377 static void imq_cleanup_devs(void)
380 struct net_device
*dev
= imq_devs
;
382 for (i
= 0; i
<= numdevs
; i
++)
383 unregister_netdev(dev
++);
388 static int __init
imq_init_module(void)
392 if ((err
= imq_init_devs())) {
393 printk(KERN_ERR
"IMQ: Error trying imq_init_devs()\n");
396 if ((err
= imq_init_hooks())) {
397 printk(KERN_ERR
"IMQ: Error trying imq_init_hooks()\n");
402 printk(KERN_INFO
"IMQ driver loaded successfully.\n");
404 if (imq_behaviour
& IMQ_BEHAV_INGRESS_AFTER
)
405 printk(KERN_INFO
"\tHooking IMQ after NAT on PREROUTING.\n");
407 printk(KERN_INFO
"\tHooking IMQ before NAT on PREROUTING.\n");
408 if (imq_behaviour
& IMQ_BEHAV_EGRESS_AFTER
)
409 printk(KERN_INFO
"\tHooking IMQ after NAT on POSTROUTING.\n");
411 printk(KERN_INFO
"\tHooking IMQ before NAT on POSTROUTING.\n");
416 static void __exit
imq_cleanup_module(void)
420 printk(KERN_INFO
"IMQ driver unloaded successfully.\n");
424 module_init(imq_init_module
);
425 module_exit(imq_cleanup_module
);
427 module_param(numdevs
, int, IMQ_MAX_DEVS
);
428 MODULE_PARM_DESC(numdevs
, "number of IMQ devices (how many imq* devices will be created)");
429 module_param(behaviour
, charp
, 0);
430 MODULE_PARM_DESC(behaviour
, "where to hook in PREROUTING and POSTROUTING - before or after NAT (aa,ab,ba,bb)");
431 MODULE_AUTHOR("http://www.linuximq.net");
432 MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
433 MODULE_LICENSE("GPL");