]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-imq.patch
- update patches for 2.6.32; they apply when using --without grsecurity
[packages/kernel.git] / kernel-imq.patch
1 diff -uNr --exclude='*~' linux-2.6.29.1/drivers/net/imq.c linux-2.6.29.1-imq/drivers/net/imq.c
2 --- linux-2.6.29.1/drivers/net/imq.c    1970-01-01 02:00:00.000000000 +0200
3 +++ linux-2.6.29.1-imq/drivers/net/imq.c        2009-04-20 23:22:18.935017702 +0300
4 @@ -0,0 +1,571 @@
5 +/*
6 + *             Pseudo-driver for the intermediate queue device.
7 + *
8 + *             This program is free software; you can redistribute it and/or
9 + *             modify it under the terms of the GNU General Public License
10 + *             as published by the Free Software Foundation; either version
11 + *             2 of the License, or (at your option) any later version.
12 + *
13 + * Authors:    Patrick McHardy, <kaber@trash.net>
14 + *
15 + *            The first version was written by Martin Devera, <devik@cdi.cz>
16 + *
17 + * Credits:    Jan Rafaj <imq2t@cedric.vabo.cz>
18 + *              - Update patch to 2.4.21
19 + *             Sebastian Strollo <sstrollo@nortelnetworks.com>
20 + *              - Fix "Dead-loop on netdevice imq"-issue
21 + *             Marcel Sebek <sebek64@post.cz>
22 + *              - Update to 2.6.2-rc1
23 + *
24 + *            After some time of inactivity there is a group taking care
25 + *            of IMQ again: http://www.linuximq.net
26 + *
27 + *
28 + *            2004/06/30 - New version of IMQ patch to kernels <=2.6.7
29 + *             including the following changes:
30 + *
31 + *            - Correction of ipv6 support "+"s issue (Hasso Tepper)
32 + *            - Correction of imq_init_devs() issue that resulted in
33 + *            kernel OOPS unloading IMQ as module (Norbert Buchmuller)
34 + *            - Addition of functionality to choose number of IMQ devices
35 + *            during kernel config (Andre Correa)
36 + *            - Addition of functionality to choose how IMQ hooks on
37 + *            PRE and POSTROUTING (after or before NAT) (Andre Correa)
38 + *            - Cosmetic corrections (Norbert Buchmuller) (Andre Correa)
39 + *
40 + *
41 + *             2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were
42 + *             released with almost no problems. 2.6.14-x was released
43 + *             with some important changes: nfcache was removed; After
44 + *             some weeks of trouble we figured out that some IMQ fields
45 + *             in skb were missing in skbuff.c - skb_clone and copy_skb_header.
46 + *             These functions are correctly patched by this new patch version.
47 + *
48 + *             Thanks for all who helped to figure out all the problems with
49 + *             2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX,
50 + *             Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully
51 + *             I didn't forget anybody). I apologize again for my lack of time.
52 + *
53 + *
54 + *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
55 + *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid
56 + *             recursive locking. New initialization routines to fix 'rmmod' not
57 + *             working anymore. Used code from ifb.c. (Jussi Kivilinna)
58 + *
59 + *             2008/08/06 - 2.6.26 - (JK)
60 + *              - Replaced tasklet with 'netif_schedule()'.
61 + *              - Cleaned up and added comments for imq_nf_queue().
62 + *
63 + *             2009/04/12
64 + *              - Add skb_save_cb/skb_restore_cb helper functions for backuping
65 + *                control buffer. This is needed because qdisc-layer on kernels
66 + *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna)
67 + *              - Add better locking for IMQ device. Hopefully this will solve
68 + *                SMP issues. (Jussi Kivilinna)
69 + *              - Port to 2.6.27
70 + *              - Port to 2.6.28
71 + *              - Port to 2.6.29 + fix rmmod not working
72 + *
73 + *             2009/04/20 - (Jussi Kivilinna)
74 + *              - Use netdevice feature flags to avoid extra packet handling
75 + *                by core networking layer and possibly increase performance.
76 + *
77 + *            Also, many thanks to pablo Sebastian Greco for making the initial
78 + *            patch and to those who helped the testing.
79 + *
80 + *             More info at: http://www.linuximq.net/ (Andre Correa)
81 + */
82 +
83 +#include <linux/module.h>
84 +#include <linux/kernel.h>
85 +#include <linux/moduleparam.h>
86 +#include <linux/list.h>
87 +#include <linux/skbuff.h>
88 +#include <linux/netdevice.h>
89 +#include <linux/etherdevice.h>
90 +#include <linux/rtnetlink.h>
91 +#include <linux/if_arp.h>
92 +#include <linux/netfilter.h>
93 +#include <linux/netfilter_ipv4.h>
94 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
95 +       #include <linux/netfilter_ipv6.h>
96 +#endif
97 +#include <linux/imq.h>
98 +#include <net/pkt_sched.h>
99 +#include <net/netfilter/nf_queue.h>
100 +
101 +static nf_hookfn imq_nf_hook;
102 +
103 +static struct nf_hook_ops imq_ingress_ipv4 = {
104 +       .hook           = imq_nf_hook,
105 +       .owner          = THIS_MODULE,
106 +       .pf             = PF_INET,
107 +       .hooknum        = NF_INET_PRE_ROUTING,
108 +#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
109 +       .priority       = NF_IP_PRI_MANGLE + 1
110 +#else
111 +       .priority       = NF_IP_PRI_NAT_DST + 1
112 +#endif
113 +};
114 +
115 +static struct nf_hook_ops imq_egress_ipv4 = {
116 +       .hook           = imq_nf_hook,
117 +       .owner          = THIS_MODULE,
118 +       .pf             = PF_INET,
119 +       .hooknum        = NF_INET_POST_ROUTING,
120 +#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
121 +       .priority       = NF_IP_PRI_LAST
122 +#else
123 +       .priority       = NF_IP_PRI_NAT_SRC - 1
124 +#endif
125 +};
126 +
127 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
128 +static struct nf_hook_ops imq_ingress_ipv6 = {
129 +       .hook           = imq_nf_hook,
130 +       .owner          = THIS_MODULE,
131 +       .pf             = PF_INET6,
132 +       .hooknum        = NF_INET_PRE_ROUTING,
133 +#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
134 +       .priority       = NF_IP6_PRI_MANGLE + 1
135 +#else
136 +       .priority       = NF_IP6_PRI_NAT_DST + 1
137 +#endif
138 +};
139 +
140 +static struct nf_hook_ops imq_egress_ipv6 = {
141 +       .hook           = imq_nf_hook,
142 +       .owner          = THIS_MODULE,
143 +       .pf             = PF_INET6,
144 +       .hooknum        = NF_INET_POST_ROUTING,
145 +#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA)
146 +       .priority       = NF_IP6_PRI_LAST
147 +#else
148 +       .priority       = NF_IP6_PRI_NAT_SRC - 1
149 +#endif
150 +};
151 +#endif
152 +
153 +#if defined(CONFIG_IMQ_NUM_DEVS)
154 +static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS;
155 +#else
156 +static unsigned int numdevs = IMQ_MAX_DEVS;
157 +#endif
158 +
159 +static DEFINE_SPINLOCK(imq_nf_queue_lock);
160 +
161 +static struct net_device *imq_devs_cache[IMQ_MAX_DEVS];
162 +
163 +
164 +static struct net_device_stats *imq_get_stats(struct net_device *dev)
165 +{
166 +       return &dev->stats;
167 +}
168 +
169 +/* called for packets kfree'd in qdiscs at places other than enqueue */
170 +static void imq_skb_destructor(struct sk_buff *skb)
171 +{
172 +       struct nf_queue_entry *entry = skb->nf_queue_entry;
173 +
174 +       if (entry) {
175 +               nf_queue_entry_release_refs(entry);
176 +               kfree(entry);
177 +       }
178 +
179 +       skb_restore_cb(skb); /* kfree backup */
180 +}
181 +
182 +static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
183 +{
184 +       int status;
185 +
186 +       if (!entry->next_outfn) {
187 +               spin_lock_bh(&imq_nf_queue_lock);
188 +               nf_reinject(entry, verdict);
189 +               spin_unlock_bh(&imq_nf_queue_lock);
190 +               return;
191 +       }
192 +
193 +       rcu_read_lock();
194 +       local_bh_disable();
195 +       status = entry->next_outfn(entry, entry->next_queuenum);
196 +       local_bh_enable();
197 +       if (status < 0) {
198 +               nf_queue_entry_release_refs(entry);
199 +               kfree_skb(entry->skb);
200 +               kfree(entry);
201 +       }
202 +
203 +       rcu_read_unlock();
204 +}
205 +
206 +static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev)
207 +{
208 +       dev->stats.tx_bytes += skb->len;
209 +       dev->stats.tx_packets++;
210 +
211 +       skb->imq_flags = 0;
212 +       skb->destructor = NULL;
213 +
214 +       skb_restore_cb(skb); /* restore skb->cb */
215 +
216 +       dev->trans_start = jiffies;
217 +       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT);
218 +       return 0;
219 +}
220 +
221 +static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num)
222 +{
223 +       struct net_device *dev;
224 +       struct sk_buff *skb_orig, *skb, *skb_shared;
225 +       struct Qdisc *q;
226 +       struct netdev_queue *txq;
227 +       int users, index;
228 +       int retval = -EINVAL;
229 +
230 +       index = entry->skb->imq_flags & IMQ_F_IFMASK;
231 +       if (unlikely(index > numdevs - 1)) {
232 +               if (net_ratelimit())
233 +                       printk(KERN_WARNING
234 +                              "IMQ: invalid device specified, highest is %u\n",
235 +                              numdevs - 1);
236 +               retval = -EINVAL;
237 +               goto out;
238 +       }
239 +
240 +       /* check for imq device by index from cache */
241 +       dev = imq_devs_cache[index];
242 +       if (unlikely(!dev)) {
243 +               char buf[8];
244 +
245 +               /* get device by name and cache result */
246 +               snprintf(buf, sizeof(buf), "imq%d", index);
247 +               dev = dev_get_by_name(&init_net, buf);
248 +               if (!dev) {
249 +                       /* not found ?!*/
250 +                       BUG();
251 +                       retval = -ENODEV;
252 +                       goto out;
253 +               }
254 +
255 +               imq_devs_cache[index] = dev;
256 +               dev_put(dev);
257 +       }
258 +
259 +       if (unlikely(!(dev->flags & IFF_UP))) {
260 +               entry->skb->imq_flags = 0;
261 +               imq_nf_reinject(entry, NF_ACCEPT);
262 +               retval = 0;
263 +               goto out;
264 +       }
265 +       dev->last_rx = jiffies;
266 +
267 +       skb = entry->skb;
268 +       skb_orig = NULL;
269 +
270 +       /* skb has owner? => make clone */
271 +       if (unlikely(skb->destructor)) {
272 +               skb_orig = skb;
273 +               skb = skb_clone(skb, GFP_ATOMIC);
274 +               if (!skb) {
275 +                       retval = -ENOMEM;
276 +                       goto out;
277 +               }
278 +               entry->skb = skb;
279 +       }
280 +
281 +       skb->nf_queue_entry = entry;
282 +
283 +       dev->stats.rx_bytes += skb->len;
284 +       dev->stats.rx_packets++;
285 +
286 +       txq = dev_pick_tx(dev, skb);
287 +
288 +       q = rcu_dereference(txq->qdisc);
289 +       if (unlikely(!q->enqueue))
290 +               goto packet_not_eaten_by_imq_dev;
291 +
292 +       spin_lock_bh(qdisc_lock(q));
293 +
294 +       users = atomic_read(&skb->users);
295 +
296 +       skb_shared = skb_get(skb); /* increase reference count by one */
297 +       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will
298 +                                       overwrite it */
299 +       qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */
300 +
301 +       if (likely(atomic_read(&skb_shared->users) == users + 1)) {
302 +               kfree_skb(skb_shared); /* decrease reference count by one */
303 +
304 +               skb->destructor = &imq_skb_destructor;
305 +
306 +               /* cloned? */
307 +               if (skb_orig)
308 +                       kfree_skb(skb_orig); /* free original */
309 +
310 +               spin_unlock_bh(qdisc_lock(q));
311 +
312 +               /* schedule qdisc dequeue */
313 +               __netif_schedule(q);
314 +
315 +               retval = 0;
316 +               goto out;
317 +       } else {
318 +               skb_restore_cb(skb_shared); /* restore skb->cb */
319 +               /* qdisc dropped packet and decreased skb reference count of
320 +                * skb, so we don't really want to and try refree as that would
321 +                * actually destroy the skb. */
322 +               spin_unlock_bh(qdisc_lock(q));
323 +               goto packet_not_eaten_by_imq_dev;
324 +       }
325 +
326 +packet_not_eaten_by_imq_dev:
327 +       /* cloned? restore original */
328 +       if (skb_orig) {
329 +               kfree_skb(skb);
330 +               entry->skb = skb_orig;
331 +       }
332 +       retval = -1;
333 +out:
334 +       return retval;
335 +}
336 +
337 +static struct nf_queue_handler nfqh = {
338 +       .name  = "imq",
339 +       .outfn = imq_nf_queue,
340 +};
341 +
342 +static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb,
343 +                               const struct net_device *indev,
344 +                               const struct net_device *outdev,
345 +                               int (*okfn)(struct sk_buff *))
346 +{
347 +       if (pskb->imq_flags & IMQ_F_ENQUEUE)
348 +               return NF_QUEUE;
349 +
350 +       return NF_ACCEPT;
351 +}
352 +
353 +static int imq_close(struct net_device *dev)
354 +{
355 +       netif_stop_queue(dev);
356 +       return 0;
357 +}
358 +
359 +static int imq_open(struct net_device *dev)
360 +{
361 +       netif_start_queue(dev);
362 +       return 0;
363 +}
364 +
365 +static const struct net_device_ops imq_netdev_ops = {
366 +       .ndo_open               = imq_open,
367 +       .ndo_stop               = imq_close,
368 +       .ndo_start_xmit         = imq_dev_xmit,
369 +       .ndo_get_stats          = imq_get_stats,
370 +};
371 +
372 +static void imq_setup(struct net_device *dev)
373 +{
374 +       dev->netdev_ops         = &imq_netdev_ops;
375 +       dev->type               = ARPHRD_VOID;
376 +       dev->mtu                = 16000;
377 +       dev->tx_queue_len       = 11000;
378 +       dev->flags              = IFF_NOARP;
379 +       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST |
380 +                                 NETIF_F_GSO | NETIF_F_HW_CSUM |
381 +                                 NETIF_F_HIGHDMA;
382 +}
383 +
384 +static int imq_validate(struct nlattr *tb[], struct nlattr *data[])
385 +{
386 +       int ret = 0;
387 +
388 +       if (tb[IFLA_ADDRESS]) {
389 +               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
390 +                       ret = -EINVAL;
391 +                       goto end;
392 +               }
393 +               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
394 +                       ret = -EADDRNOTAVAIL;
395 +                       goto end;
396 +               }
397 +       }
398 +       return 0;
399 +end:
400 +       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret);
401 +       return ret;
402 +}
403 +
404 +static struct rtnl_link_ops imq_link_ops __read_mostly = {
405 +       .kind           = "imq",
406 +       .priv_size      = 0,
407 +       .setup          = imq_setup,
408 +       .validate       = imq_validate,
409 +};
410 +
411 +static int __init imq_init_hooks(void)
412 +{
413 +       int err;
414 +
415 +       nf_register_queue_imq_handler(&nfqh);
416 +
417 +       err = nf_register_hook(&imq_ingress_ipv4);
418 +       if (err)
419 +               goto err1;
420 +
421 +       err = nf_register_hook(&imq_egress_ipv4);
422 +       if (err)
423 +               goto err2;
424 +
425 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
426 +       err = nf_register_hook(&imq_ingress_ipv6);
427 +       if (err)
428 +               goto err3;
429 +
430 +       err = nf_register_hook(&imq_egress_ipv6);
431 +       if (err)
432 +               goto err4;
433 +#endif
434 +
435 +       return 0;
436 +
437 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
438 +err4:
439 +       nf_unregister_hook(&imq_ingress_ipv6);
440 +err3:
441 +       nf_unregister_hook(&imq_egress_ipv4);
442 +#endif
443 +err2:
444 +       nf_unregister_hook(&imq_ingress_ipv4);
445 +err1:
446 +       nf_unregister_queue_imq_handler();
447 +       return err;
448 +}
449 +
450 +static int __init imq_init_one(int index)
451 +{
452 +       struct net_device *dev;
453 +       int ret;
454 +
455 +       dev = alloc_netdev(0, "imq%d", imq_setup);
456 +       if (!dev)
457 +               return -ENOMEM;
458 +
459 +       ret = dev_alloc_name(dev, dev->name);
460 +       if (ret < 0)
461 +               goto fail;
462 +
463 +       dev->rtnl_link_ops = &imq_link_ops;
464 +       ret = register_netdevice(dev);
465 +       if (ret < 0)
466 +               goto fail;
467 +
468 +       return 0;
469 +fail:
470 +       free_netdev(dev);
471 +       return ret;
472 +}
473 +
474 +static int __init imq_init_devs(void)
475 +{
476 +       int err, i;
477 +
478 +       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) {
479 +               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n",
480 +                      IMQ_MAX_DEVS);
481 +               return -EINVAL;
482 +       }
483 +
484 +       rtnl_lock();
485 +       err = __rtnl_link_register(&imq_link_ops);
486 +
487 +       for (i = 0; i < numdevs && !err; i++)
488 +               err = imq_init_one(i);
489 +
490 +       if (err) {
491 +               __rtnl_link_unregister(&imq_link_ops);
492 +               memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
493 +       }
494 +       rtnl_unlock();
495 +
496 +       return err;
497 +}
498 +
499 +static int __init imq_init_module(void)
500 +{
501 +       int err;
502 +
503 +#if defined(CONFIG_IMQ_NUM_DEVS)
504 +       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16);
505 +       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2);
506 +       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK);
507 +#endif
508 +
509 +       err = imq_init_devs();
510 +       if (err) {
511 +               printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n");
512 +               return err;
513 +       }
514 +
515 +       err = imq_init_hooks();
516 +       if (err) {
517 +               printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n");
518 +               rtnl_link_unregister(&imq_link_ops);
519 +               memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
520 +               return err;
521 +       }
522 +
523 +       printk(KERN_INFO "IMQ driver loaded successfully.\n");
524 +
525 +#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB)
526 +       printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n");
527 +#else
528 +       printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n");
529 +#endif
530 +#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB)
531 +       printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n");
532 +#else
533 +       printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n");
534 +#endif
535 +
536 +       return 0;
537 +}
538 +
539 +static void __exit imq_unhook(void)
540 +{
541 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
542 +       nf_unregister_hook(&imq_ingress_ipv6);
543 +       nf_unregister_hook(&imq_egress_ipv6);
544 +#endif
545 +       nf_unregister_hook(&imq_ingress_ipv4);
546 +       nf_unregister_hook(&imq_egress_ipv4);
547 +
548 +       nf_unregister_queue_imq_handler();
549 +}
550 +
551 +static void __exit imq_cleanup_devs(void)
552 +{
553 +       rtnl_link_unregister(&imq_link_ops);
554 +       memset(imq_devs_cache, 0, sizeof(imq_devs_cache));
555 +}
556 +
557 +static void __exit imq_exit_module(void)
558 +{
559 +       imq_unhook();
560 +       imq_cleanup_devs();
561 +       printk(KERN_INFO "IMQ driver unloaded successfully.\n");
562 +}
563 +
564 +module_init(imq_init_module);
565 +module_exit(imq_exit_module);
566 +
567 +module_param(numdevs, int, 0);
568 +MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will "
569 +                       "be created)");
570 +MODULE_AUTHOR("http://www.linuximq.net");
571 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See "
572 +                       "http://www.linuximq.net/ for more information.");
573 +MODULE_LICENSE("GPL");
574 +MODULE_ALIAS_RTNL_LINK("imq");
575 +
576 diff -uNr --exclude='*~' linux-2.6.29.1/drivers/net/Kconfig linux-2.6.29.1-imq/drivers/net/Kconfig
577 --- linux-2.6.29.1/drivers/net/Kconfig  2009-04-02 23:55:27.000000000 +0300
578 +++ linux-2.6.29.1-imq/drivers/net/Kconfig      2009-04-12 22:28:22.372333533 +0300
579 @@ -110,6 +110,129 @@
580           To compile this driver as a module, choose M here: the module
581           will be called eql.  If unsure, say N.
582  
583 +config IMQ
584 +       tristate "IMQ (intermediate queueing device) support"
585 +       depends on NETDEVICES && NETFILTER
586 +       ---help---
587 +         The IMQ device(s) is used as placeholder for QoS queueing
588 +         disciplines. Every packet entering/leaving the IP stack can be
589 +         directed through the IMQ device where it's enqueued/dequeued to the
590 +         attached qdisc. This allows you to treat network devices as classes
591 +         and distribute bandwidth among them. Iptables is used to specify
592 +         through which IMQ device, if any, packets travel.
593 +
594 +         More information at: http://www.linuximq.net/
595 +
596 +         To compile this driver as a module, choose M here: the module
597 +         will be called imq.  If unsure, say N.
598 +
599 +choice
600 +       prompt "IMQ behavior (PRE/POSTROUTING)"
601 +       depends on IMQ
602 +       default IMQ_BEHAVIOR_AB
603 +       help
604 +
605 +               This settings defines how IMQ behaves in respect to its
606 +               hooking in PREROUTING and POSTROUTING.
607 +
608 +               IMQ can work in any of the following ways:
609 +
610 +                   PREROUTING   |      POSTROUTING
611 +               -----------------|-------------------
612 +               #1  After NAT    |      After NAT
613 +               #2  After NAT    |      Before NAT
614 +               #3  Before NAT   |      After NAT
615 +               #4  Before NAT   |      Before NAT
616 +
617 +               The default behavior is to hook before NAT on PREROUTING
618 +               and after NAT on POSTROUTING (#3).
619 +
620 +               This settings are specially usefull when trying to use IMQ
621 +               to shape NATed clients.
622 +
623 +               More information can be found at: www.linuximq.net
624 +
625 +               If not sure leave the default settings alone.
626 +
627 +config IMQ_BEHAVIOR_AA
628 +       bool "IMQ AA"
629 +       help
630 +               This settings defines how IMQ behaves in respect to its
631 +               hooking in PREROUTING and POSTROUTING.
632 +
633 +               Choosing this option will make IMQ hook like this:
634 +
635 +               PREROUTING:   After NAT
636 +               POSTROUTING:  After NAT
637 +
638 +               More information can be found at: www.linuximq.net
639 +
640 +               If not sure leave the default settings alone.
641 +
642 +config IMQ_BEHAVIOR_AB
643 +       bool "IMQ AB"
644 +       help
645 +               This settings defines how IMQ behaves in respect to its
646 +               hooking in PREROUTING and POSTROUTING.
647 +
648 +               Choosing this option will make IMQ hook like this:
649 +
650 +               PREROUTING:   After NAT
651 +               POSTROUTING:  Before NAT
652 +
653 +               More information can be found at: www.linuximq.net
654 +
655 +               If not sure leave the default settings alone.
656 +
657 +config IMQ_BEHAVIOR_BA
658 +       bool "IMQ BA"
659 +       help
660 +               This settings defines how IMQ behaves in respect to its
661 +               hooking in PREROUTING and POSTROUTING.
662 +
663 +               Choosing this option will make IMQ hook like this:
664 +
665 +               PREROUTING:   Before NAT
666 +               POSTROUTING:  After NAT
667 +
668 +               More information can be found at: www.linuximq.net
669 +
670 +               If not sure leave the default settings alone.
671 +
672 +config IMQ_BEHAVIOR_BB
673 +       bool "IMQ BB"
674 +       help
675 +               This settings defines how IMQ behaves in respect to its
676 +               hooking in PREROUTING and POSTROUTING.
677 +
678 +               Choosing this option will make IMQ hook like this:
679 +
680 +               PREROUTING:   Before NAT
681 +               POSTROUTING:  Before NAT
682 +
683 +               More information can be found at: www.linuximq.net
684 +
685 +               If not sure leave the default settings alone.
686 +
687 +endchoice
688 +
689 +config IMQ_NUM_DEVS
690 +
691 +       int "Number of IMQ devices"
692 +       range 2 16
693 +       depends on IMQ
694 +       default "16"
695 +       help
696 +
697 +               This settings defines how many IMQ devices will be
698 +               created.
699 +
700 +               The default value is 16.
701 +
702 +               More information can be found at: www.linuximq.net
703 +
704 +               If not sure leave the default settings alone.
705 +
706  config TUN
707         tristate "Universal TUN/TAP device driver support"
708         select CRC32
709 diff -uNr --exclude='*~' linux-2.6.29.1/drivers/net/Makefile linux-2.6.29.1-imq/drivers/net/Makefile
710 --- linux-2.6.29.1/drivers/net/Makefile 2009-04-02 23:55:27.000000000 +0300
711 +++ linux-2.6.29.1-imq/drivers/net/Makefile     2009-04-12 22:28:22.372333533 +0300
712 @@ -150,6 +150,7 @@
713  obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
714  
715  obj-$(CONFIG_DUMMY) += dummy.o
716 +obj-$(CONFIG_IMQ) += imq.o
717  obj-$(CONFIG_IFB) += ifb.o
718  obj-$(CONFIG_MACVLAN) += macvlan.o
719  obj-$(CONFIG_DE600) += de600.o
720 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/imq.h linux-2.6.29.1-imq/include/linux/imq.h
721 --- linux-2.6.29.1/include/linux/imq.h  1970-01-01 02:00:00.000000000 +0200
722 +++ linux-2.6.29.1-imq/include/linux/imq.h      2009-04-12 22:28:22.372333533 +0300
723 @@ -0,0 +1,13 @@
724 +#ifndef _IMQ_H
725 +#define _IMQ_H
726 +
727 +/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */
728 +#define IMQ_F_BITS     5
729 +
730 +#define IMQ_F_IFMASK   0x0f
731 +#define IMQ_F_ENQUEUE  0x10
732 +
733 +#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1)
734 +
735 +#endif /* _IMQ_H */
736 +
737 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/netdevice.h linux-2.6.29.1-imq/include/linux/netdevice.h
738 --- linux-2.6.29.1/include/linux/netdevice.h    2009-04-02 23:55:27.000000000 +0300
739 +++ linux-2.6.29.1-imq/include/linux/netdevice.h        2009-04-12 22:28:22.373333509 +0300
740 @@ -1071,6 +1071,7 @@
741  extern int             dev_open(struct net_device *dev);
742  extern int             dev_close(struct net_device *dev);
743  extern void            dev_disable_lro(struct net_device *dev);
744 +extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb);
745  extern int             dev_queue_xmit(struct sk_buff *skb);
746  extern int             register_netdevice(struct net_device *dev);
747  extern void            unregister_netdevice(struct net_device *dev);
748 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/netfilter/xt_IMQ.h linux-2.6.29.1-imq/include/linux/netfilter/xt_IMQ.h
749 --- linux-2.6.29.1/include/linux/netfilter/xt_IMQ.h     1970-01-01 02:00:00.000000000 +0200
750 +++ linux-2.6.29.1-imq/include/linux/netfilter/xt_IMQ.h 2009-04-12 22:28:22.373333509 +0300
751 @@ -0,0 +1,9 @@
752 +#ifndef _XT_IMQ_H
753 +#define _XT_IMQ_H
754 +
755 +struct xt_imq_info {
756 +       unsigned int todev;     /* target imq device */
757 +};
758 +
759 +#endif /* _XT_IMQ_H */
760 +
761 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.6.29.1-imq/include/linux/netfilter_ipv4/ipt_IMQ.h
762 --- linux-2.6.29.1/include/linux/netfilter_ipv4/ipt_IMQ.h       1970-01-01 02:00:00.000000000 +0200
763 +++ linux-2.6.29.1-imq/include/linux/netfilter_ipv4/ipt_IMQ.h   2009-04-12 22:28:22.373333509 +0300
764 @@ -0,0 +1,10 @@
765 +#ifndef _IPT_IMQ_H
766 +#define _IPT_IMQ_H
767 +
768 +/* Backwards compatibility for old userspace */
769 +#include <linux/netfilter/xt_IMQ.h>
770 +
771 +#define ipt_imq_info xt_imq_info
772 +
773 +#endif /* _IPT_IMQ_H */
774 +
775 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.6.29.1-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h
776 --- linux-2.6.29.1/include/linux/netfilter_ipv6/ip6t_IMQ.h      1970-01-01 02:00:00.000000000 +0200
777 +++ linux-2.6.29.1-imq/include/linux/netfilter_ipv6/ip6t_IMQ.h  2009-04-12 22:28:22.373333509 +0300
778 @@ -0,0 +1,10 @@
779 +#ifndef _IP6T_IMQ_H
780 +#define _IP6T_IMQ_H
781 +
782 +/* Backwards compatibility for old userspace */
783 +#include <linux/netfilter/xt_IMQ.h>
784 +
785 +#define ip6t_imq_info xt_imq_info
786 +
787 +#endif /* _IP6T_IMQ_H */
788 +
789 diff -uNr --exclude='*~' linux-2.6.29.1/include/linux/skbuff.h linux-2.6.29.1-imq/include/linux/skbuff.h
790 --- linux-2.6.29.1/include/linux/skbuff.h       2009-04-02 23:55:27.000000000 +0300
791 +++ linux-2.6.29.1-imq/include/linux/skbuff.h   2009-04-12 22:28:22.374333398 +0300
792 @@ -28,6 +28,9 @@
793  #include <linux/rcupdate.h>
794  #include <linux/dmaengine.h>
795  #include <linux/hrtimer.h>
796 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
797 +#include <linux/imq.h>
798 +#endif
799  
800  #define HAVE_ALLOC_SKB         /* For the drivers to know */
801  #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */
802 @@ -282,6 +285,9 @@
803          * first. This is owned by whoever has the skb queued ATM.
804          */
805         char                    cb[48];
806 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
807 +       void                    *cb_next;
808 +#endif
809  
810         unsigned int            len,
811                                 data_len;
812 @@ -312,6 +318,9 @@
813         struct nf_conntrack     *nfct;
814         struct sk_buff          *nfct_reasm;
815  #endif
816 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
817 +       struct nf_queue_entry   *nf_queue_entry;
818 +#endif
819  #ifdef CONFIG_BRIDGE_NETFILTER
820         struct nf_bridge_info   *nf_bridge;
821  #endif
822 @@ -332,6 +341,9 @@
823         __u8                    requeue:1;
824  #endif
825         /* 0/14 bit hole */
826 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
827 +       __u8                    imq_flags:IMQ_F_BITS;
828 +#endif
829  
830  #ifdef CONFIG_NET_DMA
831         dma_cookie_t            dma_cookie;
832 @@ -372,6 +384,12 @@
833                           enum dma_data_direction dir);
834  #endif
835  
836 +
837 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
838 +extern int skb_save_cb(struct sk_buff *skb);
839 +extern int skb_restore_cb(struct sk_buff *skb);
840 +#endif
841 +
842  extern void kfree_skb(struct sk_buff *skb);
843  extern void           __kfree_skb(struct sk_buff *skb);
844  extern struct sk_buff *__alloc_skb(unsigned int size,
845 @@ -1844,6 +1862,10 @@
846         dst->nfct_reasm = src->nfct_reasm;
847         nf_conntrack_get_reasm(src->nfct_reasm);
848  #endif
849 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
850 +       dst->imq_flags = src->imq_flags;
851 +       dst->nf_queue_entry = src->nf_queue_entry;
852 +#endif
853  #ifdef CONFIG_BRIDGE_NETFILTER
854         dst->nf_bridge  = src->nf_bridge;
855         nf_bridge_get(src->nf_bridge);
856 diff -uNr --exclude='*~' linux-2.6.29.1/include/net/netfilter/nf_queue.h linux-2.6.29.1-imq/include/net/netfilter/nf_queue.h
857 --- linux-2.6.29.1/include/net/netfilter/nf_queue.h     2009-04-02 23:55:27.000000000 +0300
858 +++ linux-2.6.29.1-imq/include/net/netfilter/nf_queue.h 2009-04-12 22:28:22.374333398 +0300
859 @@ -13,6 +13,12 @@
860         struct net_device       *indev;
861         struct net_device       *outdev;
862         int                     (*okfn)(struct sk_buff *);
863 +
864 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
865 +       int                     (*next_outfn)(struct nf_queue_entry *entry,
866 +                                             unsigned int queuenum);
867 +       unsigned int            next_queuenum;
868 +#endif
869  };
870  
871  #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
872 @@ -30,5 +36,11 @@
873                                        const struct nf_queue_handler *qh);
874  extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
875  extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
876 +extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
877 +
878 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
879 +extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh);
880 +extern void nf_unregister_queue_imq_handler(void);
881 +#endif
882  
883  #endif /* _NF_QUEUE_H */
884 diff -uNr --exclude='*~' linux-2.6.29.1/net/core/dev.c linux-2.6.29.1-imq/net/core/dev.c
885 --- linux-2.6.29.1/net/core/dev.c       2009-04-02 23:55:27.000000000 +0300
886 +++ linux-2.6.29.1-imq/net/core/dev.c   2009-04-12 22:28:22.375333463 +0300
887 @@ -96,6 +96,9 @@
888  #include <net/net_namespace.h>
889  #include <net/sock.h>
890  #include <linux/rtnetlink.h>
891 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
892 +#include <linux/imq.h>
893 +#endif
894  #include <linux/proc_fs.h>
895  #include <linux/seq_file.h>
896  #include <linux/stat.h>
897 @@ -1671,7 +1674,11 @@
898  
899         prefetch(&dev->netdev_ops->ndo_start_xmit);
900         if (likely(!skb->next)) {
901 -               if (!list_empty(&ptype_all))
902 +               if (!list_empty(&ptype_all)
903 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
904 +                   && !(skb->imq_flags & IMQ_F_ENQUEUE)
905 +#endif
906 +                   )
907                         dev_queue_xmit_nit(skb, dev);
908  
909                 if (netif_needs_gso(dev, skb)) {
910 @@ -1762,8 +1769,7 @@
911         return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
912  }
913  
914 -static struct netdev_queue *dev_pick_tx(struct net_device *dev,
915 -                                       struct sk_buff *skb)
916 +struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb)
917  {
918         const struct net_device_ops *ops = dev->netdev_ops;
919         u16 queue_index = 0;
920 @@ -1776,6 +1782,7 @@
921         skb_set_queue_mapping(skb, queue_index);
922         return netdev_get_tx_queue(dev, queue_index);
923  }
924 +EXPORT_SYMBOL(dev_pick_tx);
925  
926  /**
927   *     dev_queue_xmit - transmit a buffer
928 diff -uNr --exclude='*~' linux-2.6.29.1/net/core/skbuff.c linux-2.6.29.1-imq/net/core/skbuff.c
929 --- linux-2.6.29.1/net/core/skbuff.c    2009-04-02 23:55:27.000000000 +0300
930 +++ linux-2.6.29.1-imq/net/core/skbuff.c        2009-04-12 22:28:22.376333314 +0300
931 @@ -69,6 +69,9 @@
932  
933  static struct kmem_cache *skbuff_head_cache __read_mostly;
934  static struct kmem_cache *skbuff_fclone_cache __read_mostly;
935 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
936 +static struct kmem_cache *skbuff_cb_store_cache __read_mostly;
937 +#endif
938  
939  static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
940                                   struct pipe_buffer *buf)
941 @@ -88,6 +91,80 @@
942         return 1;
943  }
944  
945 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
946 +/* Control buffer save/restore for IMQ devices */
947 +struct skb_cb_table {
948 +       void                    *cb_next;
949 +       atomic_t                refcnt;
950 +       char                    cb[48];
951 +};
952 +
953 +static DEFINE_SPINLOCK(skb_cb_store_lock);
954 +
955 +int skb_save_cb(struct sk_buff *skb)
956 +{
957 +       struct skb_cb_table *next;
958 +
959 +       next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC);
960 +       if (!next)
961 +               return -ENOMEM;
962 +
963 +       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
964 +
965 +       memcpy(next->cb, skb->cb, sizeof(skb->cb));
966 +       next->cb_next = skb->cb_next;
967 +
968 +       atomic_set(&next->refcnt, 1);
969 +
970 +       skb->cb_next = next;
971 +       return 0;
972 +}
973 +EXPORT_SYMBOL(skb_save_cb);
974 +
975 +int skb_restore_cb(struct sk_buff *skb)
976 +{
977 +       struct skb_cb_table *next;
978 +
979 +       if (!skb->cb_next)
980 +               return 0;
981 +
982 +       next = skb->cb_next;
983 +
984 +       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb));
985 +
986 +       memcpy(skb->cb, next->cb, sizeof(skb->cb));
987 +       skb->cb_next = next->cb_next;
988 +
989 +       spin_lock(&skb_cb_store_lock);
990 +
991 +       if (atomic_dec_and_test(&next->refcnt)) {
992 +               kmem_cache_free(skbuff_cb_store_cache, next);
993 +       }
994 +
995 +       spin_unlock(&skb_cb_store_lock);
996 +
997 +       return 0;
998 +}
999 +EXPORT_SYMBOL(skb_restore_cb);
1000 +
1001 +static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old)
1002 +{
1003 +       struct skb_cb_table *next;
1004 +
1005 +       if (!old->cb_next) {
1006 +               new->cb_next = 0;
1007 +               return;
1008 +       }
1009 +
1010 +       spin_lock(&skb_cb_store_lock);
1011 +
1012 +       next = old->cb_next;
1013 +       atomic_inc(&next->refcnt);
1014 +       new->cb_next = next;
1015 +
1016 +       spin_unlock(&skb_cb_store_lock);
1017 +}
1018 +#endif
1019  
1020  /* Pipe buffer operations for a socket. */
1021  static struct pipe_buf_operations sock_pipe_buf_ops = {
1022 @@ -381,6 +458,15 @@
1023                 WARN_ON(in_irq());
1024                 skb->destructor(skb);
1025         }
1026 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1027 +       /* This should not happen. When it does, avoid memleak by restoring
1028 +       the chain of cb-backups. */
1029 +       while(skb->cb_next != NULL) {
1030 +               printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n",
1031 +                       skb->cb_next);
1032 +               skb_restore_cb(skb);
1033 +       }
1034 +#endif
1035  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1036         nf_conntrack_put(skb->nfct);
1037         nf_conntrack_put_reasm(skb->nfct_reasm);
1038 @@ -621,6 +621,9 @@
1039         new->sp                 = secpath_get(old->sp);
1040  #endif
1041         memcpy(new->cb, old->cb, sizeof(old->cb));
1042 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1043 +       skb_copy_stored_cb(new, old);
1044 +#endif
1045         new->csum               = old->csum;
1046         new->local_df           = old->local_df;
1047         new->pkt_type           = old->pkt_type;
1048 @@ -2664,6 +2753,13 @@
1049                                                 0,
1050                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1051                                                 NULL);
1052 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1053 +       skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
1054 +                                                 sizeof(struct skb_cb_table),
1055 +                                                 0,
1056 +                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1057 +                                                 NULL);
1058 +#endif
1059  }
1060  
1061  /**
1062 diff -uNr --exclude='*~' linux-2.6.29.1/net/netfilter/Kconfig linux-2.6.29.1-imq/net/netfilter/Kconfig
1063 --- linux-2.6.29.1/net/netfilter/Kconfig        2009-04-02 23:55:27.000000000 +0300
1064 +++ linux-2.6.29.1-imq/net/netfilter/Kconfig    2009-04-12 22:28:22.376333314 +0300
1065 @@ -357,6 +357,18 @@
1066  
1067           To compile it as a module, choose M here.  If unsure, say N.
1068  
1069 +config NETFILTER_XT_TARGET_IMQ
1070 +        tristate '"IMQ" target support'
1071 +       depends on NETFILTER_XTABLES
1072 +       depends on IP_NF_MANGLE || IP6_NF_MANGLE
1073 +       select IMQ
1074 +       default m if NETFILTER_ADVANCED=n
1075 +        help
1076 +          This option adds a `IMQ' target which is used to specify if and
1077 +          to which imq device packets should get enqueued/dequeued.
1078 +
1079 +          To compile it as a module, choose M here.  If unsure, say N.
1080 +
1081  config NETFILTER_XT_TARGET_MARK
1082         tristate '"MARK" target support'
1083         default m if NETFILTER_ADVANCED=n
1084 diff -uNr --exclude='*~' linux-2.6.29.1/net/netfilter/Makefile linux-2.6.29.1-imq/net/netfilter/Makefile
1085 --- linux-2.6.29.1/net/netfilter/Makefile       2009-04-02 23:55:27.000000000 +0300
1086 +++ linux-2.6.29.1-imq/net/netfilter/Makefile   2009-04-12 22:28:22.377333406 +0300
1087 @@ -45,6 +45,7 @@
1088  obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
1089  obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
1090  obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
1091 +obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
1092  obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
1093  obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
1094  obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
1095 diff -uNr --exclude='*~' linux-2.6.29.1/net/netfilter/nf_queue.c linux-2.6.29.1-imq/net/netfilter/nf_queue.c
1096 --- linux-2.6.29.1/net/netfilter/nf_queue.c     2009-04-02 23:55:27.000000000 +0300
1097 +++ linux-2.6.29.1-imq/net/netfilter/nf_queue.c 2009-04-12 22:28:22.377333406 +0300
1098 @@ -20,6 +20,26 @@
1099  
1100  static DEFINE_MUTEX(queue_handler_mutex);
1101  
1102 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1103 +static const struct nf_queue_handler *queue_imq_handler;
1104 +
1105 +void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)
1106 +{
1107 +       mutex_lock(&queue_handler_mutex);
1108 +       rcu_assign_pointer(queue_imq_handler, qh);
1109 +       mutex_unlock(&queue_handler_mutex);
1110 +}
1111 +EXPORT_SYMBOL(nf_register_queue_imq_handler);
1112 +
1113 +void nf_unregister_queue_imq_handler(void)
1114 +{
1115 +       mutex_lock(&queue_handler_mutex);
1116 +       rcu_assign_pointer(queue_imq_handler, NULL);
1117 +       mutex_unlock(&queue_handler_mutex);
1118 +}
1119 +EXPORT_SYMBOL(nf_unregister_queue_imq_handler);
1120 +#endif
1121 +
1122  /* return EBUSY when somebody else is registered, return EEXIST if the
1123   * same handler is registered, return 0 in case of success. */
1124  int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
1125 @@ -80,7 +100,7 @@
1126  }
1127  EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
1128  
1129 -static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
1130 +void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
1131  {
1132         /* Release those devices we held, or Alexey will kill me. */
1133         if (entry->indev)
1134 @@ -100,6 +120,7 @@
1135         /* Drop reference to owner of hook which queued us. */
1136         module_put(entry->elem->owner);
1137  }
1138 +EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);
1139  
1140  /*
1141   * Any packet that leaves via this function must come back
1142 @@ -121,12 +142,26 @@
1143  #endif
1144         const struct nf_afinfo *afinfo;
1145         const struct nf_queue_handler *qh;
1146 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1147 +       const struct nf_queue_handler *qih = NULL;
1148 +#endif
1149  
1150         /* QUEUE == DROP if noone is waiting, to be safe. */
1151         rcu_read_lock();
1152  
1153         qh = rcu_dereference(queue_handler[pf]);
1154 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1155 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1156 +       if (pf == PF_INET || pf == PF_INET6)
1157 +#else
1158 +       if (pf == PF_INET)
1159 +#endif
1160 +               qih = rcu_dereference(queue_imq_handler);
1161 +
1162 +       if (!qh && !qih)
1163 +#else /* !IMQ */
1164         if (!qh)
1165 +#endif
1166                 goto err_unlock;
1167  
1168         afinfo = nf_get_afinfo(pf);
1169 @@ -145,6 +180,10 @@
1170                 .indev  = indev,
1171                 .outdev = outdev,
1172                 .okfn   = okfn,
1173 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1174 +               .next_outfn = qh ? qh->outfn : NULL,
1175 +               .next_queuenum = queuenum,
1176 +#endif
1177         };
1178  
1179         /* If it's going away, ignore hook. */
1180 @@ -170,8 +209,19 @@
1181         }
1182  #endif
1183         afinfo->saveroute(skb, entry);
1184 +
1185 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1186 +       if (qih) {
1187 +               status = qih->outfn(entry, queuenum);
1188 +               goto imq_skip_queue;
1189 +       }
1190 +#endif
1191 +
1192         status = qh->outfn(entry, queuenum);
1193  
1194 +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
1195 +imq_skip_queue:
1196 +#endif
1197         rcu_read_unlock();
1198  
1199         if (status < 0) {
1200 diff -uNr --exclude='*~' linux-2.6.29.1/net/netfilter/xt_IMQ.c linux-2.6.29.1-imq/net/netfilter/xt_IMQ.c
1201 --- linux-2.6.29.1/net/netfilter/xt_IMQ.c       1970-01-01 02:00:00.000000000 +0200
1202 +++ linux-2.6.29.1-imq/net/netfilter/xt_IMQ.c   2009-04-12 23:07:10.900088430 +0300
1203 @@ -0,0 +1,73 @@
1204 +/*
1205 + * This target marks packets to be enqueued to an imq device
1206 + */
1207 +#include <linux/module.h>
1208 +#include <linux/skbuff.h>
1209 +#include <linux/netfilter/x_tables.h>
1210 +#include <linux/netfilter/xt_IMQ.h>
1211 +#include <linux/imq.h>
1212 +
1213 +static unsigned int imq_target(struct sk_buff *pskb,
1214 +                               const struct xt_target_param *par)
1215 +{
1216 +       const struct xt_imq_info *mr = par->targinfo;
1217 +
1218 +       pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE;
1219 +
1220 +       return XT_CONTINUE;
1221 +}
1222 +
1223 +static bool imq_checkentry(const struct xt_tgchk_param *par)
1224 +{
1225 +       struct xt_imq_info *mr = par->targinfo;
1226 +
1227 +       if (mr->todev > IMQ_MAX_DEVS - 1) {
1228 +               printk(KERN_WARNING
1229 +                      "IMQ: invalid device specified, highest is %u\n",
1230 +                      IMQ_MAX_DEVS - 1);
1231 +               return 0;
1232 +       }
1233 +
1234 +       return 1;
1235 +}
1236 +
1237 +static struct xt_target xt_imq_reg[] __read_mostly = {
1238 +       {
1239 +               .name           = "IMQ",
1240 +               .family         = AF_INET,
1241 +               .checkentry     = imq_checkentry,
1242 +               .target         = imq_target,
1243 +               .targetsize     = sizeof(struct xt_imq_info),
1244 +               .table          = "mangle",
1245 +               .me             = THIS_MODULE
1246 +       },
1247 +       {
1248 +               .name           = "IMQ",
1249 +               .family         = AF_INET6,
1250 +               .checkentry     = imq_checkentry,
1251 +               .target         = imq_target,
1252 +               .targetsize     = sizeof(struct xt_imq_info),
1253 +               .table          = "mangle",
1254 +               .me             = THIS_MODULE
1255 +       },
1256 +};
1257 +
1258 +static int __init imq_init(void)
1259 +{
1260 +       return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
1261 +}
1262 +
1263 +static void __exit imq_fini(void)
1264 +{
1265 +       xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg));
1266 +}
1267 +
1268 +module_init(imq_init);
1269 +module_exit(imq_fini);
1270 +
1271 +MODULE_AUTHOR("http://www.linuximq.net");
1272 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information.");
1273 +MODULE_LICENSE("GPL");
1274 +MODULE_ALIAS("ipt_IMQ");
1275 +MODULE_ALIAS("ip6t_IMQ");
1276 +
This page took 0.142752 seconds and 4 git commands to generate.