Changeset 15655


Ignore:
Timestamp:
2009-05-07T05:09:04+02:00 (9 years ago)
Author:
jow
Message:

[kernel] update imq patches for 2.6.26, 2.6.27, 2.6.28, 2.6.29 and 2.6.30

Location:
trunk/target/linux/generic-2.6
Files:
4 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic-2.6/patches-2.6.26/150-netfilter_imq.patch

    r14600 r15655  
    11--- /dev/null 
    22+++ b/drivers/net/imq.c 
    3 @@ -0,0 +1,474 @@ 
     3@@ -0,0 +1,565 @@ 
    44+/* 
    55+ *             Pseudo-driver for the intermediate queue device. 
     
    5252+ * 
    5353+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
    54 + *            of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
     54+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
    5555+ *             recursive locking. New initialization routines to fix 'rmmod' not 
    5656+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna) 
     57+ * 
     58+ *             2008/08/06 - 2.6.26 - (JK) 
     59+ *              - Replaced tasklet with 'netif_schedule()'. 
     60+ *              - Cleaned up and added comments for imq_nf_queue(). 
     61+ * 
     62+ *             2009/05/02 - Backported 2.6.27 fixes to 2.6.26 (Jussi Kivilinna) 
     63+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping 
     64+ *                control buffer. This is needed because some networking layers 
     65+ *                on kernels before 2.6.27 overwrite control buffer when they 
     66+ *                should not. These errornous uses (wireless for example) of cb 
     67+ *                were found when qdisc-layer started using cb in 2.6.27. As we 
     68+ *                don't want to break up any code, even if it's buggy, use 
     69+ *                same backup-cb trick as used with 2.6.27-patch. 
     70+ *              - Add better locking for IMQ device by using spin_lock_bh 
     71+ *                instead of spin_lock. There was problem where NIC-interrupt 
     72+ *                would happen while IMQ-spin_lock was held which could lead to 
     73+ *                deadlock. Hopefully this will solve the SMP issues. 
     74+ *              - Fix rmmod not working. 
     75+ *              - Use netdevice feature flags to avoid extra packet handling 
     76+ *                by core networking layer and possibly increase performance. 
    5777+ * 
    5878+ *            Also, many thanks to pablo Sebastian Greco for making the initial 
     
    6585+#include <linux/kernel.h> 
    6686+#include <linux/moduleparam.h> 
     87+#include <linux/list.h> 
    6788+#include <linux/skbuff.h> 
    6889+#include <linux/netdevice.h> 
     90+#include <linux/etherdevice.h> 
    6991+#include <linux/rtnetlink.h> 
    7092+#include <linux/if_arp.h> 
     
    7799+#include <net/pkt_sched.h> 
    78100+#include <net/netfilter/nf_queue.h> 
    79 + 
    80 +struct imq_private { 
    81 +       struct tasklet_struct tasklet; 
    82 +       unsigned long tasklet_pending; 
    83 +}; 
    84101+ 
    85102+static nf_hookfn imq_nf_hook; 
     
    141158+#endif 
    142159+ 
     160+static DEFINE_SPINLOCK(imq_nf_queue_lock); 
     161+ 
    143162+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; 
    144163+ 
     
    154173+ 
    155174+       if (entry) { 
    156 +               if (entry->indev) 
    157 +                       dev_put(entry->indev); 
    158 +               if (entry->outdev) 
    159 +                       dev_put(entry->outdev); 
     175+               nf_queue_entry_release_refs(entry); 
    160176+               kfree(entry); 
    161177+       } 
     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(); 
    162204+} 
    163205+ 
     
    170212+       skb->destructor = NULL; 
    171213+ 
     214+       skb_restore_cb(skb); /* restore skb->cb */ 
     215+ 
    172216+       dev->trans_start = jiffies; 
    173 +       nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
     217+       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
    174218+       return 0; 
    175219+} 
     
    178222+{ 
    179223+       struct net_device *dev; 
    180 +       struct imq_private *priv; 
    181 +       struct sk_buff *skb2 = NULL; 
     224+       struct sk_buff *skb_orig, *skb, *skb_shared; 
    182225+       struct Qdisc *q; 
    183 +       unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; 
    184 +       int ret = -1; 
    185 + 
    186 +       if (index > numdevs) 
    187 +               return -1; 
     226+       /*spinlock_t *root_lock;*/ 
     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+       } 
    188239+ 
    189240+       /* check for imq device by index from cache */ 
    190241+       dev = imq_devs_cache[index]; 
    191 +       if (!dev) { 
     242+       if (unlikely(!dev)) { 
    192243+               char buf[8]; 
    193244+ 
     
    198249+                       /* not found ?!*/ 
    199250+                       BUG(); 
    200 +                       return -1; 
     251+                       retval = -ENODEV; 
     252+                       goto out; 
    201253+               } 
    202254+ 
    203255+               imq_devs_cache[index] = dev; 
    204 +       } 
    205 + 
    206 +       priv = netdev_priv(dev); 
    207 +       if (!(dev->flags & IFF_UP)) { 
     256+               dev_put(dev); 
     257+       } 
     258+ 
     259+       if (unlikely(!(dev->flags & IFF_UP))) { 
    208260+               entry->skb->imq_flags = 0; 
    209 +               nf_reinject(entry, NF_ACCEPT); 
    210 +               return 0; 
     261+               imq_nf_reinject(entry, NF_ACCEPT); 
     262+               retval = 0; 
     263+               goto out; 
    211264+       } 
    212265+       dev->last_rx = jiffies; 
    213266+ 
    214 +       if (entry->skb->destructor) { 
    215 +               skb2 = entry->skb; 
    216 +               entry->skb = skb_clone(entry->skb, GFP_ATOMIC); 
    217 +               if (!entry->skb) 
    218 +                       return -1; 
    219 +       } 
    220 +       entry->skb->nf_queue_entry = entry; 
    221 + 
    222 +       dev->stats.rx_bytes += entry->skb->len; 
     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; 
    223284+       dev->stats.rx_packets++; 
    224285+ 
     286+       q = rcu_dereference(dev->qdisc); 
     287+       if (unlikely(!q->enqueue)) 
     288+               goto packet_not_eaten_by_imq_dev; 
     289+ 
    225290+       spin_lock_bh(&dev->queue_lock); 
    226 +       q = dev->qdisc; 
    227 +       if (q->enqueue) { 
    228 +               q->enqueue(skb_get(entry->skb), q); 
    229 +               if (skb_shared(entry->skb)) { 
    230 +                       entry->skb->destructor = imq_skb_destructor; 
    231 +                       kfree_skb(entry->skb); 
    232 +                       ret = 0; 
    233 +               } 
    234 +       } 
    235 +       if (!test_and_set_bit(1, &priv->tasklet_pending)) 
    236 +               tasklet_schedule(&priv->tasklet); 
    237 +       spin_unlock_bh(&dev->queue_lock); 
    238 + 
    239 +       if (skb2) 
    240 +               kfree_skb(ret ? entry->skb : skb2); 
    241 + 
    242 +       return ret; 
     291+ 
     292+       users = atomic_read(&skb->users); 
     293+ 
     294+       skb_shared = skb_get(skb); /* increase reference count by one */ 
     295+       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will 
     296+                                       overwrite it */ 
     297+       q->enqueue(skb_shared, q); /* might kfree_skb */ 
     298+ 
     299+       if (likely(atomic_read(&skb_shared->users) == users + 1)) { 
     300+               kfree_skb(skb_shared); /* decrease reference count by one */ 
     301+ 
     302+               skb->destructor = &imq_skb_destructor; 
     303+ 
     304+               /* cloned? */ 
     305+               if (skb_orig) 
     306+                       kfree_skb(skb_orig); /* free original */ 
     307+ 
     308+               /* schedule qdisc dequeue */ 
     309+               netif_schedule(dev); 
     310+ 
     311+               spin_unlock_bh(&dev->queue_lock); 
     312+               retval = 0; 
     313+               goto out; 
     314+       } else { 
     315+               skb_restore_cb(skb_shared); /* restore skb->cb */ 
     316+               /* qdisc dropped packet and decreased skb reference count of 
     317+                * skb, so we don't really want to and try refree as that would 
     318+                * actually destroy the skb. */ 
     319+               spin_unlock_bh(&dev->queue_lock); 
     320+               goto packet_not_eaten_by_imq_dev; 
     321+       } 
     322+ 
     323+packet_not_eaten_by_imq_dev: 
     324+       /* cloned? restore original */ 
     325+       if (skb_orig) { 
     326+               kfree_skb(skb); 
     327+               entry->skb = skb_orig; 
     328+       } 
     329+       retval = -1; 
     330+out: 
     331+       return retval; 
    243332+} 
    244333+ 
     
    248337+}; 
    249338+ 
    250 +static void qdisc_run_tasklet(unsigned long arg) 
    251 +{ 
    252 +       struct net_device *dev = (struct net_device *)arg; 
    253 +       struct imq_private *priv = netdev_priv(dev); 
    254 + 
    255 +       spin_lock(&dev->queue_lock); 
    256 +       qdisc_run(dev); 
    257 +       clear_bit(1, &priv->tasklet_pending); 
    258 +       spin_unlock(&dev->queue_lock); 
    259 +} 
    260 + 
    261339+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, 
    262340+                               const struct net_device *indev, 
     
    272350+static int imq_close(struct net_device *dev) 
    273351+{ 
    274 +       struct imq_private *priv = netdev_priv(dev); 
    275 + 
    276 +       tasklet_kill(&priv->tasklet); 
    277352+       netif_stop_queue(dev); 
    278 + 
    279353+       return 0; 
    280354+} 
     
    282356+static int imq_open(struct net_device *dev) 
    283357+{ 
    284 +       struct imq_private *priv = netdev_priv(dev); 
    285 + 
    286 +       tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev); 
    287358+       netif_start_queue(dev); 
    288 + 
    289359+       return 0; 
    290360+} 
     
    300370+       dev->tx_queue_len       = 11000; 
    301371+       dev->flags              = IFF_NOARP; 
     372+       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST | 
     373+                                 NETIF_F_GSO | NETIF_F_HW_CSUM | 
     374+                                 NETIF_F_HIGHDMA; 
     375+} 
     376+ 
     377+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) 
     378+{ 
     379+       int ret = 0; 
     380+ 
     381+       if (tb[IFLA_ADDRESS]) { 
     382+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 
     383+                       ret = -EINVAL; 
     384+                       goto end; 
     385+               } 
     386+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { 
     387+                       ret = -EADDRNOTAVAIL; 
     388+                       goto end; 
     389+               } 
     390+       } 
     391+       return 0; 
     392+end: 
     393+       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); 
     394+       return ret; 
    302395+} 
    303396+ 
    304397+static struct rtnl_link_ops imq_link_ops __read_mostly = { 
    305398+       .kind           = "imq", 
    306 +       .priv_size      = sizeof(struct imq_private), 
     399+       .priv_size      = 0, 
    307400+       .setup          = imq_setup, 
     401+       .validate       = imq_validate, 
    308402+}; 
    309403+ 
     
    312406+       int err; 
    313407+ 
    314 +       err = nf_register_queue_handler(PF_INET, &nfqh); 
     408+       nf_register_queue_imq_handler(&nfqh); 
     409+ 
     410+       err = nf_register_hook(&imq_ingress_ipv4); 
    315411+       if (err) 
    316412+               goto err1; 
    317413+ 
    318 +       err = nf_register_hook(&imq_ingress_ipv4); 
     414+       err = nf_register_hook(&imq_egress_ipv4); 
    319415+       if (err) 
    320416+               goto err2; 
    321417+ 
    322 +       err = nf_register_hook(&imq_egress_ipv4); 
     418+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     419+       err = nf_register_hook(&imq_ingress_ipv6); 
    323420+       if (err) 
    324421+               goto err3; 
    325422+ 
    326 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    327 +       err = nf_register_queue_handler(PF_INET6, &nfqh); 
     423+       err = nf_register_hook(&imq_egress_ipv6); 
    328424+       if (err) 
    329425+               goto err4; 
    330 + 
    331 +       err = nf_register_hook(&imq_ingress_ipv6); 
    332 +       if (err) 
    333 +               goto err5; 
    334 + 
    335 +       err = nf_register_hook(&imq_egress_ipv6); 
    336 +       if (err) 
    337 +               goto err6; 
    338426+#endif 
    339427+ 
     
    341429+ 
    342430+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    343 +err6: 
     431+err4: 
    344432+       nf_unregister_hook(&imq_ingress_ipv6); 
    345 +err5: 
    346 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    347 +err4: 
     433+err3: 
    348434+       nf_unregister_hook(&imq_egress_ipv4); 
    349435+#endif 
    350 +err3: 
     436+err2: 
    351437+       nf_unregister_hook(&imq_ingress_ipv4); 
    352 +err2: 
    353 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
    354438+err1: 
     439+       nf_unregister_queue_imq_handler(); 
    355440+       return err; 
    356441+} 
     
    361446+       int ret; 
    362447+ 
    363 +       dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup); 
     448+       dev = alloc_netdev(0, "imq%d", imq_setup); 
    364449+       if (!dev) 
    365450+               return -ENOMEM; 
     
    384469+       int err, i; 
    385470+ 
    386 +       if (!numdevs || numdevs > IMQ_MAX_DEVS) { 
     471+       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { 
    387472+               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", 
    388473+                      IMQ_MAX_DEVS); 
     
    408493+{ 
    409494+       int err; 
     495+ 
     496+#if defined(CONFIG_IMQ_NUM_DEVS) 
     497+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); 
     498+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); 
     499+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); 
     500+#endif 
    410501+ 
    411502+       err = imq_init_devs(); 
     
    444535+       nf_unregister_hook(&imq_ingress_ipv6); 
    445536+       nf_unregister_hook(&imq_egress_ipv6); 
    446 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    447537+#endif 
    448538+       nf_unregister_hook(&imq_ingress_ipv4); 
    449539+       nf_unregister_hook(&imq_egress_ipv4); 
    450 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
     540+ 
     541+       nf_unregister_queue_imq_handler(); 
    451542+} 
    452543+ 
     
    478569--- a/drivers/net/Kconfig 
    479570+++ b/drivers/net/Kconfig 
    480 @@ -117,6 +117,129 @@ config EQUALIZER 
     571@@ -117,6 +117,129 @@ 
    481572          To compile this driver as a module, choose M here: the module 
    482573          will be called eql.  If unsure, say N. 
     
    610701--- a/drivers/net/Makefile 
    611702+++ b/drivers/net/Makefile 
    612 @@ -142,6 +142,7 @@ obj-$(CONFIG_SLHC) += slhc.o 
     703@@ -142,6 +142,7 @@ 
    613704 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o 
    614705  
     
    620711--- /dev/null 
    621712+++ b/include/linux/imq.h 
    622 @@ -0,0 +1,9 @@ 
     713@@ -0,0 +1,13 @@ 
    623714+#ifndef _IMQ_H 
    624715+#define _IMQ_H 
    625716+ 
    626 +#define IMQ_MAX_DEVS   16 
    627 + 
    628 +#define IMQ_F_IFMASK   0x7f 
    629 +#define IMQ_F_ENQUEUE  0x80 
     717+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ 
     718+#define IMQ_F_BITS     5 
     719+ 
     720+#define IMQ_F_IFMASK   0x0f 
     721+#define IMQ_F_ENQUEUE  0x10 
     722+ 
     723+#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1) 
    630724+ 
    631725+#endif /* _IMQ_H */ 
     726+ 
    632727--- /dev/null 
    633728+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 
    634 @@ -0,0 +1,8 @@ 
     729@@ -0,0 +1,10 @@ 
    635730+#ifndef _IPT_IMQ_H 
    636731+#define _IPT_IMQ_H 
    637732+ 
    638 +struct ipt_imq_info { 
    639 +       unsigned int todev;     /* target imq device */ 
    640 +}; 
     733+/* Backwards compatibility for old userspace */ 
     734+#include <linux/netfilter/xt_IMQ.h> 
     735+ 
     736+#define ipt_imq_info xt_imq_info 
    641737+ 
    642738+#endif /* _IPT_IMQ_H */ 
     739+ 
    643740--- /dev/null 
    644741+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 
    645 @@ -0,0 +1,8 @@ 
     742@@ -0,0 +1,10 @@ 
    646743+#ifndef _IP6T_IMQ_H 
    647744+#define _IP6T_IMQ_H 
    648745+ 
    649 +struct ip6t_imq_info { 
    650 +       unsigned int todev;     /* target imq device */ 
    651 +}; 
     746+/* Backwards compatibility for old userspace */ 
     747+#include <linux/netfilter/xt_IMQ.h> 
     748+ 
     749+#define ip6t_imq_info xt_imq_info 
    652750+ 
    653751+#endif /* _IP6T_IMQ_H */ 
     752+ 
    654753--- a/include/linux/skbuff.h 
    655754+++ b/include/linux/skbuff.h 
    656 @@ -300,6 +300,10 @@ struct sk_buff { 
     755@@ -28,6 +28,9 @@ 
     756 #include <linux/rcupdate.h> 
     757 #include <linux/dmaengine.h> 
     758 #include <linux/hrtimer.h> 
     759+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     760+#include <linux/imq.h> 
     761+#endif 
     762  
     763 #define HAVE_ALLOC_SKB         /* For the drivers to know */ 
     764 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */ 
     765@@ -270,6 +273,9 @@ 
     766         * first. This is owned by whoever has the skb queued ATM. 
     767         */ 
     768        char                    cb[48]; 
     769+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     770+       void                    *cb_next; 
     771+#endif 
     772  
     773        unsigned int            len, 
     774                                data_len; 
     775@@ -300,6 +306,9 @@ 
    657776        struct nf_conntrack     *nfct; 
    658777        struct sk_buff          *nfct_reasm; 
    659778 #endif 
    660779+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
    661 +       unsigned char                   imq_flags; 
    662780+       struct nf_queue_entry   *nf_queue_entry; 
    663781+#endif 
     
    665783        struct nf_bridge_info   *nf_bridge; 
    666784 #endif 
    667 @@ -1633,6 +1637,10 @@ static inline void __nf_copy(struct sk_b 
     785@@ -318,6 +327,9 @@ 
     786        __u8                    ndisc_nodetype:2; 
     787 #endif 
     788        /* 14 bit hole */ 
     789+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     790+       __u8                    imq_flags:IMQ_F_BITS; 
     791+#endif 
     792  
     793 #ifdef CONFIG_NET_DMA 
     794        dma_cookie_t            dma_cookie; 
     795@@ -348,6 +360,12 @@ 
     796  
     797 #include <asm/system.h> 
     798  
     799+ 
     800+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     801+extern int skb_save_cb(struct sk_buff *skb); 
     802+extern int skb_restore_cb(struct sk_buff *skb); 
     803+#endif 
     804+ 
     805 extern void kfree_skb(struct sk_buff *skb); 
     806 extern void           __kfree_skb(struct sk_buff *skb); 
     807 extern struct sk_buff *__alloc_skb(unsigned int size, 
     808@@ -1633,6 +1651,10 @@ 
    668809        dst->nfct_reasm = src->nfct_reasm; 
    669810        nf_conntrack_get_reasm(src->nfct_reasm); 
     
    688829 #include <linux/seq_file.h> 
    689830 #include <linux/stat.h> 
    690 @@ -1569,7 +1572,11 @@ static int dev_gso_segment(struct sk_buf 
     831@@ -1569,7 +1572,11 @@ 
    691832 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) 
    692833 { 
     
    702843                if (netif_needs_gso(dev, skb)) { 
    703844--- /dev/null 
    704 +++ b/net/ipv4/netfilter/ipt_IMQ.c 
    705 @@ -0,0 +1,69 @@ 
     845+++ b/include/linux/netfilter/xt_IMQ.h 
     846@@ -0,0 +1,9 @@ 
     847+#ifndef _XT_IMQ_H 
     848+#define _XT_IMQ_H 
     849+ 
     850+struct xt_imq_info { 
     851+       unsigned int todev;     /* target imq device */ 
     852+}; 
     853+ 
     854+#endif /* _XT_IMQ_H */ 
     855+ 
     856--- a/include/net/netfilter/nf_queue.h 
     857+++ b/include/net/netfilter/nf_queue.h 
     858@@ -13,6 +13,12 @@ 
     859        struct net_device       *indev; 
     860        struct net_device       *outdev; 
     861        int                     (*okfn)(struct sk_buff *); 
     862+ 
     863+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     864+       int                     (*next_outfn)(struct nf_queue_entry *entry, 
     865+                                             unsigned int queuenum); 
     866+       unsigned int            next_queuenum; 
     867+#endif 
     868 }; 
     869  
     870 #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) 
     871@@ -30,5 +36,11 @@ 
     872                                       const struct nf_queue_handler *qh); 
     873 extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); 
     874 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); 
     875+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry); 
     876+ 
     877+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     878+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh); 
     879+extern void nf_unregister_queue_imq_handler(void); 
     880+#endif 
     881  
     882 #endif /* _NF_QUEUE_H */ 
     883--- a/net/core/skbuff.c 
     884+++ b/net/core/skbuff.c 
     885@@ -71,6 +71,9 @@ 
     886  
     887 static struct kmem_cache *skbuff_head_cache __read_mostly; 
     888 static struct kmem_cache *skbuff_fclone_cache __read_mostly; 
     889+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     890+static struct kmem_cache *skbuff_cb_store_cache __read_mostly; 
     891+#endif 
     892  
     893 static void sock_pipe_buf_release(struct pipe_inode_info *pipe, 
     894                                  struct pipe_buffer *buf) 
     895@@ -94,6 +97,81 @@ 
     896        return 1; 
     897 } 
     898  
     899+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     900+/* Control buffer save/restore for IMQ devices */ 
     901+struct skb_cb_table { 
     902+       void                    *cb_next; 
     903+       atomic_t                refcnt; 
     904+       char                    cb[48]; 
     905+}; 
     906+ 
     907+static DEFINE_SPINLOCK(skb_cb_store_lock); 
     908+ 
     909+int skb_save_cb(struct sk_buff *skb) 
     910+{ 
     911+       struct skb_cb_table *next; 
     912+ 
     913+       next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC); 
     914+       if (!next) 
     915+               return -ENOMEM; 
     916+ 
     917+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     918+ 
     919+       memcpy(next->cb, skb->cb, sizeof(skb->cb)); 
     920+       next->cb_next = skb->cb_next; 
     921+ 
     922+       atomic_set(&next->refcnt, 1); 
     923+ 
     924+got_next: 
     925+       skb->cb_next = next; 
     926+       return 0; 
     927+} 
     928+EXPORT_SYMBOL(skb_save_cb); 
     929+ 
     930+int skb_restore_cb(struct sk_buff *skb) 
     931+{ 
     932+       struct skb_cb_table *next; 
     933+ 
     934+       if (!skb->cb_next) 
     935+               return 0; 
     936+ 
     937+       next = skb->cb_next; 
     938+ 
     939+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     940+ 
     941+       memcpy(skb->cb, next->cb, sizeof(skb->cb)); 
     942+       skb->cb_next = next->cb_next; 
     943+ 
     944+       spin_lock(&skb_cb_store_lock); 
     945+ 
     946+       if (atomic_dec_and_test(&next->refcnt)) { 
     947+               kmem_cache_free(skbuff_cb_store_cache, next); 
     948+       } 
     949+ 
     950+       spin_unlock(&skb_cb_store_lock); 
     951+ 
     952+       return 0; 
     953+} 
     954+EXPORT_SYMBOL(skb_restore_cb); 
     955+ 
     956+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old) 
     957+{ 
     958+       struct skb_cb_table *next; 
     959+ 
     960+       if (!old->cb_next) { 
     961+               new->cb_next = 0; 
     962+               return; 
     963+       } 
     964+ 
     965+       spin_lock(&skb_cb_store_lock); 
     966+ 
     967+       next = old->cb_next; 
     968+       atomic_inc(&next->refcnt); 
     969+       new->cb_next = next; 
     970+ 
     971+       spin_unlock(&skb_cb_store_lock); 
     972+} 
     973+#endif 
     974  
     975 /* Pipe buffer operations for a socket. */ 
     976 static struct pipe_buf_operations sock_pipe_buf_ops = { 
     977@@ -376,6 +454,15 @@ 
     978                WARN_ON(in_irq()); 
     979                skb->destructor(skb); 
     980        } 
     981+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     982+       /* This should not happen. When it does, avoid memleak by restoring 
     983+       the chain of cb-backups. */ 
     984+       while(skb->cb_next != NULL) { 
     985+               printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n", 
     986+                       skb->cb_next); 
     987+               skb_restore_cb(skb); 
     988+       } 
     989+#endif 
     990 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 
     991        nf_conntrack_put(skb->nfct); 
     992        nf_conntrack_put_reasm(skb->nfct_reasm); 
     993@@ -438,6 +525,9 @@ 
     994        new->sp                 = secpath_get(old->sp); 
     995 #endif 
     996        memcpy(new->cb, old->cb, sizeof(old->cb)); 
     997+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     998+       skb_copy_stored_cb(new, old); 
     999+#endif 
     1000        new->csum_start         = old->csum_start; 
     1001        new->csum_offset        = old->csum_offset; 
     1002        new->local_df           = old->local_df; 
     1003@@ -2290,6 +2380,7 @@ 
     1004                nskb->protocol = skb->protocol; 
     1005                nskb->dst = dst_clone(skb->dst); 
     1006                memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); 
     1007+               skb_copy_stored_cb(nskb, skb); 
     1008                nskb->pkt_type = skb->pkt_type; 
     1009                nskb->mac_len = skb->mac_len; 
     1010  
     1011@@ -2371,6 +2462,13 @@ 
     1012                                                0, 
     1013                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1014                                                NULL); 
     1015+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1016+       skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache", 
     1017+                                                 sizeof(struct skb_cb_table), 
     1018+                                                 0, 
     1019+                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1020+                                                 NULL); 
     1021+#endif 
     1022 } 
     1023  
     1024 /** 
     1025--- a/net/netfilter/Kconfig 
     1026+++ b/net/netfilter/Kconfig 
     1027@@ -334,6 +334,18 @@ 
     1028  
     1029          To compile it as a module, choose M here.  If unsure, say N. 
     1030  
     1031+config NETFILTER_XT_TARGET_IMQ 
     1032+        tristate '"IMQ" target support' 
     1033+       depends on NETFILTER_XTABLES 
     1034+       depends on IP_NF_MANGLE || IP6_NF_MANGLE 
     1035+       select IMQ 
     1036+       default m if NETFILTER_ADVANCED=n 
     1037+        help 
     1038+          This option adds a `IMQ' target which is used to specify if and 
     1039+          to which imq device packets should get enqueued/dequeued. 
     1040+ 
     1041+          To compile it as a module, choose M here.  If unsure, say N. 
     1042+ 
     1043 config NETFILTER_XT_TARGET_MARK 
     1044        tristate '"MARK" target support' 
     1045        depends on NETFILTER_XTABLES 
     1046--- a/net/netfilter/Makefile 
     1047+++ b/net/netfilter/Makefile 
     1048@@ -42,6 +42,7 @@ 
     1049 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 
     1050 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 
     1051 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 
     1052+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o 
     1053 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o 
     1054 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 
     1055 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 
     1056--- a/net/netfilter/nf_queue.c 
     1057+++ b/net/netfilter/nf_queue.c 
     1058@@ -20,6 +20,26 @@ 
     1059  
     1060 static DEFINE_MUTEX(queue_handler_mutex); 
     1061  
     1062+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1063+static const struct nf_queue_handler *queue_imq_handler; 
     1064+ 
     1065+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh) 
     1066+{ 
     1067+       mutex_lock(&queue_handler_mutex); 
     1068+       rcu_assign_pointer(queue_imq_handler, qh); 
     1069+       mutex_unlock(&queue_handler_mutex); 
     1070+} 
     1071+EXPORT_SYMBOL(nf_register_queue_imq_handler); 
     1072+ 
     1073+void nf_unregister_queue_imq_handler(void) 
     1074+{ 
     1075+       mutex_lock(&queue_handler_mutex); 
     1076+       rcu_assign_pointer(queue_imq_handler, NULL); 
     1077+       mutex_unlock(&queue_handler_mutex); 
     1078+} 
     1079+EXPORT_SYMBOL(nf_unregister_queue_imq_handler); 
     1080+#endif 
     1081+ 
     1082 /* return EBUSY when somebody else is registered, return EEXIST if the 
     1083  * same handler is registered, return 0 in case of success. */ 
     1084 int nf_register_queue_handler(int pf, const struct nf_queue_handler *qh) 
     1085@@ -80,7 +100,7 @@ 
     1086 } 
     1087 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 
     1088  
     1089-static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1090+void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1091 { 
     1092        /* Release those devices we held, or Alexey will kill me. */ 
     1093        if (entry->indev) 
     1094@@ -100,6 +120,7 @@ 
     1095        /* Drop reference to owner of hook which queued us. */ 
     1096        module_put(entry->elem->owner); 
     1097 } 
     1098+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); 
     1099  
     1100 /* 
     1101  * Any packet that leaves via this function must come back 
     1102@@ -121,12 +142,26 @@ 
     1103 #endif 
     1104        const struct nf_afinfo *afinfo; 
     1105        const struct nf_queue_handler *qh; 
     1106+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1107+       const struct nf_queue_handler *qih = NULL; 
     1108+#endif 
     1109  
     1110        /* QUEUE == DROP if noone is waiting, to be safe. */ 
     1111        rcu_read_lock(); 
     1112  
     1113        qh = rcu_dereference(queue_handler[pf]); 
     1114+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1115+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     1116+       if (pf == PF_INET || pf == PF_INET6) 
     1117+#else 
     1118+       if (pf == PF_INET) 
     1119+#endif 
     1120+               qih = rcu_dereference(queue_imq_handler); 
     1121+ 
     1122+       if (!qh && !qih) 
     1123+#else /* !IMQ */ 
     1124        if (!qh) 
     1125+#endif 
     1126                goto err_unlock; 
     1127  
     1128        afinfo = nf_get_afinfo(pf); 
     1129@@ -145,6 +180,10 @@ 
     1130                .indev  = indev, 
     1131                .outdev = outdev, 
     1132                .okfn   = okfn, 
     1133+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1134+               .next_outfn = qh ? qh->outfn : NULL, 
     1135+               .next_queuenum = queuenum, 
     1136+#endif 
     1137        }; 
     1138  
     1139        /* If it's going away, ignore hook. */ 
     1140@@ -170,8 +209,19 @@ 
     1141        } 
     1142 #endif 
     1143        afinfo->saveroute(skb, entry); 
     1144+ 
     1145+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1146+       if (qih) { 
     1147+               status = qih->outfn(entry, queuenum); 
     1148+               goto imq_skip_queue; 
     1149+       } 
     1150+#endif 
     1151+ 
     1152        status = qh->outfn(entry, queuenum); 
     1153  
     1154+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1155+imq_skip_queue: 
     1156+#endif 
     1157        rcu_read_unlock(); 
     1158  
     1159        if (status < 0) { 
     1160--- /dev/null 
     1161+++ b/net/netfilter/xt_IMQ.c 
     1162@@ -0,0 +1,81 @@ 
    7061163+/* 
    7071164+ * This target marks packets to be enqueued to an imq device 
     
    7091166+#include <linux/module.h> 
    7101167+#include <linux/skbuff.h> 
    711 +#include <linux/netfilter_ipv4/ip_tables.h> 
    712 +#include <linux/netfilter_ipv4/ipt_IMQ.h> 
     1168+#include <linux/netfilter/x_tables.h> 
     1169+#include <linux/netfilter/xt_IMQ.h> 
    7131170+#include <linux/imq.h> 
    7141171+ 
     
    7201177+                              const void *targinfo) 
    7211178+{ 
    722 +       struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo; 
    723 + 
    724 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
    725 + 
    726 +       return XT_CONTINUE; 
    727 +} 
    728 + 
    729 +static bool imq_checkentry(const char *tablename, 
    730 +                         const void *e, 
    731 +                         const struct xt_target *target, 
    732 +                         void *targinfo, 
    733 +                         unsigned int hook_mask) 
    734 +{ 
    735 +       struct ipt_imq_info *mr; 
    736 + 
    737 +       mr = (struct ipt_imq_info *)targinfo; 
    738 + 
    739 +       if (mr->todev > IMQ_MAX_DEVS) { 
    740 +               printk(KERN_WARNING 
    741 +                      "IMQ: invalid device specified, highest is %u\n", 
    742 +                      IMQ_MAX_DEVS); 
    743 +               return 0; 
    744 +       } 
    745 + 
    746 +       return 1; 
    747 +} 
    748 + 
    749 +static struct xt_target ipt_imq_reg = { 
    750 +       .name           = "IMQ", 
    751 +       .family         = AF_INET, 
    752 +       .target         = imq_target, 
    753 +       .targetsize     = sizeof(struct ipt_imq_info), 
    754 +       .checkentry     = imq_checkentry, 
    755 +       .me             = THIS_MODULE, 
    756 +       .table          = "mangle" 
    757 +}; 
    758 + 
    759 +static int __init init(void) 
    760 +{ 
    761 +       return xt_register_target(&ipt_imq_reg); 
    762 +} 
    763 + 
    764 +static void __exit fini(void) 
    765 +{ 
    766 +       xt_unregister_target(&ipt_imq_reg); 
    767 +} 
    768 + 
    769 +module_init(init); 
    770 +module_exit(fini); 
    771 + 
    772 +MODULE_AUTHOR("http://www.linuximq.net"); 
    773 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    774 +MODULE_LICENSE("GPL"); 
    775 --- a/net/ipv4/netfilter/Kconfig 
    776 +++ b/net/ipv4/netfilter/Kconfig 
    777 @@ -123,6 +123,17 @@ config IP_NF_FILTER 
    778   
    779           To compile it as a module, choose M here.  If unsure, say N. 
    780   
    781 +config IP_NF_TARGET_IMQ 
    782 +       tristate "IMQ target support" 
    783 +       depends on IP_NF_MANGLE && IMQ 
    784 +       help 
    785 +         This option adds a `IMQ' target which is used to specify if and 
    786 +         to which IMQ device packets should get enqueued/dequeued. 
    787 + 
    788 +        For more information visit: http://www.linuximq.net/ 
    789 + 
    790 +         To compile it as a module, choose M here.  If unsure, say N. 
    791 + 
    792  config IP_NF_TARGET_REJECT 
    793         tristate "REJECT target support" 
    794         depends on IP_NF_FILTER 
    795 --- a/net/ipv4/netfilter/Makefile 
    796 +++ b/net/ipv4/netfilter/Makefile 
    797 @@ -55,6 +55,7 @@ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set 
    798  obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 
    799  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 
    800  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 
    801 +obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o 
    802  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 
    803  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 
    804  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 
    805 --- /dev/null 
    806 +++ b/net/ipv6/netfilter/ip6t_IMQ.c 
    807 @@ -0,0 +1,69 @@ 
    808 +/* 
    809 + * This target marks packets to be enqueued to an imq device 
    810 + */ 
    811 +#include <linux/module.h> 
    812 +#include <linux/skbuff.h> 
    813 +#include <linux/netfilter_ipv6/ip6_tables.h> 
    814 +#include <linux/netfilter_ipv6/ip6t_IMQ.h> 
    815 +#include <linux/imq.h> 
    816 + 
    817 +static unsigned int imq_target(struct sk_buff *pskb, 
    818 +                              const struct net_device *in, 
    819 +                              const struct net_device *out, 
    820 +                              unsigned int hooknum, 
    821 +                              const struct xt_target *target, 
    822 +                              const void *targinfo) 
    823 +{ 
    824 +       struct ip6t_imq_info *mr = (struct ip6t_imq_info *)targinfo; 
    825 + 
    826 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
     1179+       const struct xt_imq_info *mr = targinfo; 
     1180+ 
     1181+       pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE; 
    8271182+ 
    8281183+       return XT_CONTINUE; 
     
    8351190+                         unsigned int hook_mask) 
    8361191+{ 
    837 +       struct ip6t_imq_info *mr; 
    838 + 
    839 +       mr = (struct ip6t_imq_info *)targinfo; 
    840 + 
    841 +       if (mr->todev > IMQ_MAX_DEVS) { 
     1192+       struct xt_imq_info *mr = targinfo; 
     1193+ 
     1194+       if (mr->todev > IMQ_MAX_DEVS - 1) { 
    8421195+               printk(KERN_WARNING 
    8431196+                      "IMQ: invalid device specified, highest is %u\n", 
    844 +                      IMQ_MAX_DEVS); 
     1197+                      IMQ_MAX_DEVS - 1); 
    8451198+               return 0; 
    8461199+       } 
     
    8491202+} 
    8501203+ 
    851 +static struct xt_target ip6t_imq_reg = { 
    852 +       .name           = "IMQ", 
    853 +       .family         = AF_INET6, 
    854 +       .target         = imq_target, 
    855 +       .targetsize     = sizeof(struct ip6t_imq_info), 
    856 +       .table          = "mangle", 
    857 +       .checkentry     = imq_checkentry, 
    858 +       .me             = THIS_MODULE 
     1204+static struct xt_target xt_imq_reg[] __read_mostly = { 
     1205+       { 
     1206+               .name           = "IMQ", 
     1207+               .family         = AF_INET, 
     1208+               .target         = imq_target, 
     1209+               .targetsize     = sizeof(struct xt_imq_info), 
     1210+               .table          = "mangle", 
     1211+               .checkentry     = imq_checkentry, 
     1212+               .me             = THIS_MODULE 
     1213+       }, 
     1214+       { 
     1215+               .name           = "IMQ", 
     1216+               .family         = AF_INET6, 
     1217+               .target         = imq_target, 
     1218+               .targetsize     = sizeof(struct xt_imq_info), 
     1219+               .table          = "mangle", 
     1220+               .checkentry     = imq_checkentry, 
     1221+               .me             = THIS_MODULE 
     1222+       }, 
    8591223+}; 
    8601224+ 
    861 +static int __init init(void) 
    862 +{ 
    863 +       return xt_register_target(&ip6t_imq_reg); 
    864 +} 
    865 + 
    866 +static void __exit fini(void) 
    867 +{ 
    868 +       xt_unregister_target(&ip6t_imq_reg); 
    869 +} 
    870 + 
    871 +module_init(init); 
    872 +module_exit(fini); 
     1225+static int __init imq_init(void) 
     1226+{ 
     1227+       return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1228+} 
     1229+ 
     1230+static void __exit imq_fini(void) 
     1231+{ 
     1232+       xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1233+} 
     1234+ 
     1235+module_init(imq_init); 
     1236+module_exit(imq_fini); 
    8731237+ 
    8741238+MODULE_AUTHOR("http://www.linuximq.net"); 
    8751239+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    8761240+MODULE_LICENSE("GPL"); 
    877 --- a/net/ipv6/netfilter/Kconfig 
    878 +++ b/net/ipv6/netfilter/Kconfig 
    879 @@ -179,6 +179,15 @@ config IP6_NF_MANGLE 
    880   
    881           To compile it as a module, choose M here.  If unsure, say N. 
    882   
    883 +config IP6_NF_TARGET_IMQ 
    884 +       tristate "IMQ target support" 
    885 +       depends on IP6_NF_MANGLE && IMQ 
    886 +       help 
    887 +          This option adds a `IMQ' target which is used to specify if and 
    888 +          to which imq device packets should get enqueued/dequeued. 
    889 + 
    890 +          To compile it as a module, choose M here.  If unsure, say N. 
    891 + 
    892  config IP6_NF_TARGET_HL 
    893         tristate  'HL (hoplimit) target support' 
    894         depends on IP6_NF_MANGLE 
    895 --- a/net/ipv6/netfilter/Makefile 
    896 +++ b/net/ipv6/netfilter/Makefile 
    897 @@ -6,6 +6,7 @@ 
    898  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 
    899  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 
    900  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 
    901 +obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o 
    902  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 
    903  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 
    904   
    905 --- a/net/sched/sch_generic.c 
    906 +++ b/net/sched/sch_generic.c 
    907 @@ -203,6 +203,7 @@ void __qdisc_run(struct net_device *dev) 
    908   
    909         clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); 
    910  } 
    911 +EXPORT_SYMBOL(__qdisc_run); 
    912   
    913  static void dev_watchdog(unsigned long arg) 
    914  { 
     1241+MODULE_ALIAS("ipt_IMQ"); 
     1242+MODULE_ALIAS("ip6t_IMQ"); 
     1243+ 
  • trunk/target/linux/generic-2.6/patches-2.6.26/180-netfilter_depends.patch

    r14456 r15655  
    11--- a/net/netfilter/Kconfig 
    22+++ b/net/netfilter/Kconfig 
    3 @@ -157,7 +157,7 @@ config NF_CONNTRACK_FTP 
     3@@ -157,7 +157,7 @@ 
    44  
    55 config NF_CONNTRACK_H323 
     
    1010        help 
    1111          H.323 is a VoIP signalling protocol from ITU-T. As one of the most 
    12 @@ -435,7 +435,7 @@ config NETFILTER_XT_TARGET_CONNSECMARK 
     12@@ -447,7 +447,7 @@ 
    1313  
    1414 config NETFILTER_XT_TARGET_TCPMSS 
  • trunk/target/linux/generic-2.6/patches-2.6.26/190-netfilter_rtsp.patch

    r14600 r15655  
    295295--- a/net/ipv4/netfilter/Makefile 
    296296+++ b/net/ipv4/netfilter/Makefile 
    297 @@ -23,6 +23,7 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_am 
     297@@ -23,6 +23,7 @@ 
    298298 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 
    299299 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 
     
    305305--- a/net/netfilter/Kconfig 
    306306+++ b/net/netfilter/Kconfig 
    307 @@ -270,6 +270,16 @@ config NF_CONNTRACK_TFTP 
     307@@ -270,6 +270,16 @@ 
    308308  
    309309          To compile it as a module, choose M here.  If unsure, say N. 
     
    324324--- a/net/netfilter/Makefile 
    325325+++ b/net/netfilter/Makefile 
    326 @@ -33,6 +33,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co 
     326@@ -33,6 +33,7 @@ 
    327327 obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o 
    328328 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o 
     
    334334--- a/net/ipv4/netfilter/Kconfig 
    335335+++ b/net/ipv4/netfilter/Kconfig 
    336 @@ -282,6 +282,11 @@ config NF_NAT_IRC 
     336@@ -271,6 +271,11 @@ 
    337337        depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 
    338338        default NF_NAT && NF_CONNTRACK_IRC 
  • trunk/target/linux/generic-2.6/patches-2.6.27/150-netfilter_imq.patch

    r15018 r15655  
    11--- /dev/null 
    22+++ b/drivers/net/imq.c 
    3 @@ -0,0 +1,474 @@ 
     3@@ -0,0 +1,566 @@ 
    44+/* 
    55+ *             Pseudo-driver for the intermediate queue device. 
     
    5252+ * 
    5353+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
    54 + *            of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
     54+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
    5555+ *             recursive locking. New initialization routines to fix 'rmmod' not 
    5656+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna) 
     57+ * 
     58+ *             2008/08/06 - 2.6.26 - (JK) 
     59+ *              - Replaced tasklet with 'netif_schedule()'. 
     60+ *              - Cleaned up and added comments for imq_nf_queue(). 
     61+ * 
     62+ *             2009/04/12 
     63+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping 
     64+ *                control buffer. This is needed because qdisc-layer on kernels 
     65+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna) 
     66+ *              - Add better locking for IMQ device. Hopefully this will solve 
     67+ *                SMP issues. (Jussi Kivilinna) 
     68+ *              - Port to 2.6.27 
     69+ * 
     70+ *             2009/04/20 - (Jussi Kivilinna) 
     71+ *              - Fix rmmod not working 
     72+ *              - Use netdevice feature flags to avoid extra packet handling 
     73+ *                by core networking layer and possibly increase performance. 
    5774+ * 
    5875+ *            Also, many thanks to pablo Sebastian Greco for making the initial 
     
    6582+#include <linux/kernel.h> 
    6683+#include <linux/moduleparam.h> 
     84+#include <linux/list.h> 
    6785+#include <linux/skbuff.h> 
    6886+#include <linux/netdevice.h> 
     87+#include <linux/etherdevice.h> 
    6988+#include <linux/rtnetlink.h> 
    7089+#include <linux/if_arp.h> 
     
    7796+#include <net/pkt_sched.h> 
    7897+#include <net/netfilter/nf_queue.h> 
    79 + 
    80 +struct imq_private { 
    81 +       struct tasklet_struct tasklet; 
    82 +       unsigned long tasklet_pending; 
    83 +}; 
    8498+ 
    8599+static nf_hookfn imq_nf_hook; 
     
    141155+#endif 
    142156+ 
     157+static DEFINE_SPINLOCK(imq_nf_queue_lock); 
     158+ 
    143159+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; 
     160+ 
    144161+ 
    145162+static struct net_device_stats *imq_get_stats(struct net_device *dev) 
     
    154171+ 
    155172+       if (entry) { 
    156 +               if (entry->indev) 
    157 +                       dev_put(entry->indev); 
    158 +               if (entry->outdev) 
    159 +                       dev_put(entry->outdev); 
     173+               nf_queue_entry_release_refs(entry); 
    160174+               kfree(entry); 
    161175+       } 
     176+ 
     177+       skb_restore_cb(skb); /* kfree backup */ 
     178+} 
     179+ 
     180+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 
     181+{ 
     182+       int status; 
     183+ 
     184+       if (!entry->next_outfn) { 
     185+               spin_lock_bh(&imq_nf_queue_lock); 
     186+               nf_reinject(entry, verdict); 
     187+               spin_unlock_bh(&imq_nf_queue_lock); 
     188+               return; 
     189+       } 
     190+ 
     191+       rcu_read_lock(); 
     192+       local_bh_disable(); 
     193+       status = entry->next_outfn(entry, entry->next_queuenum); 
     194+       local_bh_enable(); 
     195+       if (status < 0) { 
     196+               nf_queue_entry_release_refs(entry); 
     197+               kfree_skb(entry->skb); 
     198+               kfree(entry); 
     199+       } 
     200+ 
     201+       rcu_read_unlock(); 
    162202+} 
    163203+ 
     
    170210+       skb->destructor = NULL; 
    171211+ 
     212+       skb_restore_cb(skb); /* restore skb->cb */ 
     213+ 
    172214+       dev->trans_start = jiffies; 
    173 +       nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
     215+       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
    174216+       return 0; 
    175217+} 
     
    178220+{ 
    179221+       struct net_device *dev; 
    180 +       struct imq_private *priv; 
    181 +       struct sk_buff *skb2 = NULL; 
     222+       struct sk_buff *skb_orig, *skb, *skb_shared; 
    182223+       struct Qdisc *q; 
    183 +       unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; 
    184 +       int ret = -1; 
    185 + 
    186 +       if (index > numdevs) 
    187 +               return -1; 
     224+       struct netdev_queue *txq; 
     225+       int users, index; 
     226+       int retval = -EINVAL; 
     227+ 
     228+       index = entry->skb->imq_flags & IMQ_F_IFMASK; 
     229+       if (unlikely(index > numdevs - 1)) { 
     230+               if (net_ratelimit()) 
     231+                       printk(KERN_WARNING 
     232+                              "IMQ: invalid device specified, highest is %u\n", 
     233+                              numdevs - 1); 
     234+               retval = -EINVAL; 
     235+               goto out; 
     236+       } 
    188237+ 
    189238+       /* check for imq device by index from cache */ 
    190239+       dev = imq_devs_cache[index]; 
    191 +       if (!dev) { 
     240+       if (unlikely(!dev)) { 
    192241+               char buf[8]; 
    193242+ 
     
    198247+                       /* not found ?!*/ 
    199248+                       BUG(); 
    200 +                       return -1; 
     249+                       retval = -ENODEV; 
     250+                       goto out; 
    201251+               } 
    202252+ 
    203253+               imq_devs_cache[index] = dev; 
    204 +       } 
    205 + 
    206 +       priv = netdev_priv(dev); 
    207 +       if (!(dev->flags & IFF_UP)) { 
     254+               dev_put(dev); 
     255+       } 
     256+ 
     257+       if (unlikely(!(dev->flags & IFF_UP))) { 
    208258+               entry->skb->imq_flags = 0; 
    209 +               nf_reinject(entry, NF_ACCEPT); 
    210 +               return 0; 
     259+               imq_nf_reinject(entry, NF_ACCEPT); 
     260+               retval = 0; 
     261+               goto out; 
    211262+       } 
    212263+       dev->last_rx = jiffies; 
    213264+ 
    214 +       if (entry->skb->destructor) { 
    215 +               skb2 = entry->skb; 
    216 +               entry->skb = skb_clone(entry->skb, GFP_ATOMIC); 
    217 +               if (!entry->skb) 
    218 +                       return -1; 
    219 +       } 
    220 +       entry->skb->nf_queue_entry = entry; 
    221 + 
    222 +       dev->stats.rx_bytes += entry->skb->len; 
     265+       skb = entry->skb; 
     266+       skb_orig = NULL; 
     267+ 
     268+       /* skb has owner? => make clone */ 
     269+       if (unlikely(skb->destructor)) { 
     270+               skb_orig = skb; 
     271+               skb = skb_clone(skb, GFP_ATOMIC); 
     272+               if (!skb) { 
     273+                       retval = -ENOMEM; 
     274+                       goto out; 
     275+               } 
     276+               entry->skb = skb; 
     277+       } 
     278+ 
     279+       skb->nf_queue_entry = entry; 
     280+ 
     281+       dev->stats.rx_bytes += skb->len; 
    223282+       dev->stats.rx_packets++; 
    224283+ 
    225 +       spin_lock_bh(&dev->queue_lock); 
    226 +       q = dev->qdisc; 
    227 +       if (q->enqueue) { 
    228 +               q->enqueue(skb_get(entry->skb), q); 
    229 +               if (skb_shared(entry->skb)) { 
    230 +                       entry->skb->destructor = imq_skb_destructor; 
    231 +                       kfree_skb(entry->skb); 
    232 +                       ret = 0; 
    233 +               } 
    234 +       } 
    235 +       if (!test_and_set_bit(1, &priv->tasklet_pending)) 
    236 +               tasklet_schedule(&priv->tasklet); 
    237 +       spin_unlock_bh(&dev->queue_lock); 
    238 + 
    239 +       if (skb2) 
    240 +               kfree_skb(ret ? entry->skb : skb2); 
    241 + 
    242 +       return ret; 
     284+       txq = dev_pick_tx(dev, skb); 
     285+ 
     286+       q = rcu_dereference(txq->qdisc); 
     287+       if (unlikely(!q->enqueue)) 
     288+               goto packet_not_eaten_by_imq_dev; 
     289+ 
     290+       spin_lock_bh(qdisc_lock(q)); 
     291+ 
     292+       users = atomic_read(&skb->users); 
     293+ 
     294+       skb_shared = skb_get(skb); /* increase reference count by one */ 
     295+       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will 
     296+                                       overwrite it */ 
     297+       qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ 
     298+ 
     299+       if (likely(atomic_read(&skb_shared->users) == users + 1)) { 
     300+               kfree_skb(skb_shared); /* decrease reference count by one */ 
     301+ 
     302+               skb->destructor = &imq_skb_destructor; 
     303+ 
     304+               /* cloned? */ 
     305+               if (skb_orig) 
     306+                       kfree_skb(skb_orig); /* free original */ 
     307+ 
     308+               spin_unlock_bh(qdisc_lock(q)); 
     309+ 
     310+               /* schedule qdisc dequeue */ 
     311+               __netif_schedule(q); 
     312+ 
     313+               retval = 0; 
     314+               goto out; 
     315+       } else { 
     316+               skb_restore_cb(skb_shared); /* restore skb->cb */ 
     317+               /* qdisc dropped packet and decreased skb reference count of 
     318+                * skb, so we don't really want to and try refree as that would 
     319+                * actually destroy the skb. */ 
     320+               spin_unlock_bh(qdisc_lock(q)); 
     321+               goto packet_not_eaten_by_imq_dev; 
     322+       } 
     323+ 
     324+packet_not_eaten_by_imq_dev: 
     325+       /* cloned? restore original */ 
     326+       if (skb_orig) { 
     327+               kfree_skb(skb); 
     328+               entry->skb = skb_orig; 
     329+       } 
     330+       retval = -1; 
     331+out: 
     332+       return retval; 
    243333+} 
    244334+ 
     
    248338+}; 
    249339+ 
    250 +static void qdisc_run_tasklet(unsigned long arg) 
    251 +{ 
    252 +       struct net_device *dev = (struct net_device *)arg; 
    253 +       struct imq_private *priv = netdev_priv(dev); 
    254 + 
    255 +       spin_lock(&dev->queue_lock); 
    256 +       qdisc_run(dev); 
    257 +       clear_bit(1, &priv->tasklet_pending); 
    258 +       spin_unlock(&dev->queue_lock); 
    259 +} 
    260 + 
    261340+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, 
    262341+                               const struct net_device *indev, 
     
    272351+static int imq_close(struct net_device *dev) 
    273352+{ 
    274 +       struct imq_private *priv = netdev_priv(dev); 
    275 + 
    276 +       tasklet_kill(&priv->tasklet); 
    277353+       netif_stop_queue(dev); 
    278 + 
    279354+       return 0; 
    280355+} 
     
    282357+static int imq_open(struct net_device *dev) 
    283358+{ 
    284 +       struct imq_private *priv = netdev_priv(dev); 
    285 + 
    286 +       tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev); 
    287359+       netif_start_queue(dev); 
    288 + 
    289360+       return 0; 
    290361+} 
     
    300371+       dev->tx_queue_len       = 11000; 
    301372+       dev->flags              = IFF_NOARP; 
     373+       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST | 
     374+                                 NETIF_F_GSO | NETIF_F_HW_CSUM | 
     375+                                 NETIF_F_HIGHDMA; 
     376+} 
     377+ 
     378+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) 
     379+{ 
     380+       int ret = 0; 
     381+ 
     382+       if (tb[IFLA_ADDRESS]) { 
     383+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 
     384+                       ret = -EINVAL; 
     385+                       goto end; 
     386+               } 
     387+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { 
     388+                       ret = -EADDRNOTAVAIL; 
     389+                       goto end; 
     390+               } 
     391+       } 
     392+       return 0; 
     393+end: 
     394+       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); 
     395+       return ret; 
    302396+} 
    303397+ 
    304398+static struct rtnl_link_ops imq_link_ops __read_mostly = { 
    305399+       .kind           = "imq", 
    306 +       .priv_size      = sizeof(struct imq_private), 
     400+       .priv_size      = 0, 
    307401+       .setup          = imq_setup, 
     402+       .validate       = imq_validate, 
    308403+}; 
    309404+ 
     
    312407+       int err; 
    313408+ 
    314 +       err = nf_register_queue_handler(PF_INET, &nfqh); 
     409+       nf_register_queue_imq_handler(&nfqh); 
     410+ 
     411+       err = nf_register_hook(&imq_ingress_ipv4); 
    315412+       if (err) 
    316413+               goto err1; 
    317414+ 
    318 +       err = nf_register_hook(&imq_ingress_ipv4); 
     415+       err = nf_register_hook(&imq_egress_ipv4); 
    319416+       if (err) 
    320417+               goto err2; 
    321418+ 
    322 +       err = nf_register_hook(&imq_egress_ipv4); 
     419+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     420+       err = nf_register_hook(&imq_ingress_ipv6); 
    323421+       if (err) 
    324422+               goto err3; 
    325423+ 
    326 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    327 +       err = nf_register_queue_handler(PF_INET6, &nfqh); 
     424+       err = nf_register_hook(&imq_egress_ipv6); 
    328425+       if (err) 
    329426+               goto err4; 
    330 + 
    331 +       err = nf_register_hook(&imq_ingress_ipv6); 
    332 +       if (err) 
    333 +               goto err5; 
    334 + 
    335 +       err = nf_register_hook(&imq_egress_ipv6); 
    336 +       if (err) 
    337 +               goto err6; 
    338427+#endif 
    339428+ 
     
    341430+ 
    342431+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    343 +err6: 
     432+err4: 
    344433+       nf_unregister_hook(&imq_ingress_ipv6); 
    345 +err5: 
    346 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    347 +err4: 
     434+err3: 
    348435+       nf_unregister_hook(&imq_egress_ipv4); 
    349436+#endif 
    350 +err3: 
     437+err2: 
    351438+       nf_unregister_hook(&imq_ingress_ipv4); 
    352 +err2: 
    353 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
    354439+err1: 
     440+       nf_unregister_queue_imq_handler(); 
    355441+       return err; 
    356442+} 
     
    361447+       int ret; 
    362448+ 
    363 +       dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup); 
     449+       dev = alloc_netdev(0, "imq%d", imq_setup); 
    364450+       if (!dev) 
    365451+               return -ENOMEM; 
     
    384470+       int err, i; 
    385471+ 
    386 +       if (!numdevs || numdevs > IMQ_MAX_DEVS) { 
     472+       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { 
    387473+               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", 
    388474+                      IMQ_MAX_DEVS); 
     
    408494+{ 
    409495+       int err; 
     496+ 
     497+#if defined(CONFIG_IMQ_NUM_DEVS) 
     498+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); 
     499+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); 
     500+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); 
     501+#endif 
    410502+ 
    411503+       err = imq_init_devs(); 
     
    444536+       nf_unregister_hook(&imq_ingress_ipv6); 
    445537+       nf_unregister_hook(&imq_egress_ipv6); 
    446 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    447538+#endif 
    448539+       nf_unregister_hook(&imq_ingress_ipv4); 
    449540+       nf_unregister_hook(&imq_egress_ipv4); 
    450 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
     541+ 
     542+       nf_unregister_queue_imq_handler(); 
    451543+} 
    452544+ 
     
    478570--- a/drivers/net/Kconfig 
    479571+++ b/drivers/net/Kconfig 
    480 @@ -109,6 +109,129 @@ config EQUALIZER 
     572@@ -109,6 +109,129 @@ 
    481573          To compile this driver as a module, choose M here: the module 
    482574          will be called eql.  If unsure, say N. 
     
    610702--- a/drivers/net/Makefile 
    611703+++ b/drivers/net/Makefile 
    612 @@ -144,6 +144,7 @@ obj-$(CONFIG_SLHC) += slhc.o 
     704@@ -144,6 +144,7 @@ 
    613705 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o 
    614706  
     
    620712--- /dev/null 
    621713+++ b/include/linux/imq.h 
    622 @@ -0,0 +1,9 @@ 
     714@@ -0,0 +1,13 @@ 
    623715+#ifndef _IMQ_H 
    624716+#define _IMQ_H 
    625717+ 
    626 +#define IMQ_MAX_DEVS   16 
    627 + 
    628 +#define IMQ_F_IFMASK   0x7f 
    629 +#define IMQ_F_ENQUEUE  0x80 
     718+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ 
     719+#define IMQ_F_BITS     5 
     720+ 
     721+#define IMQ_F_IFMASK   0x0f 
     722+#define IMQ_F_ENQUEUE  0x10 
     723+ 
     724+#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1) 
    630725+ 
    631726+#endif /* _IMQ_H */ 
     727+ 
    632728--- /dev/null 
    633729+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 
    634 @@ -0,0 +1,8 @@ 
     730@@ -0,0 +1,10 @@ 
    635731+#ifndef _IPT_IMQ_H 
    636732+#define _IPT_IMQ_H 
    637733+ 
    638 +struct ipt_imq_info { 
    639 +       unsigned int todev;     /* target imq device */ 
    640 +}; 
     734+/* Backwards compatibility for old userspace */ 
     735+#include <linux/netfilter/xt_IMQ.h> 
     736+ 
     737+#define ipt_imq_info xt_imq_info 
    641738+ 
    642739+#endif /* _IPT_IMQ_H */ 
     740+ 
    643741--- /dev/null 
    644742+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 
    645 @@ -0,0 +1,8 @@ 
     743@@ -0,0 +1,10 @@ 
    646744+#ifndef _IP6T_IMQ_H 
    647745+#define _IP6T_IMQ_H 
    648746+ 
    649 +struct ip6t_imq_info { 
    650 +       unsigned int todev;     /* target imq device */ 
    651 +}; 
     747+/* Backwards compatibility for old userspace */ 
     748+#include <linux/netfilter/xt_IMQ.h> 
     749+ 
     750+#define ip6t_imq_info xt_imq_info 
    652751+ 
    653752+#endif /* _IP6T_IMQ_H */ 
     753+ 
    654754--- a/include/linux/skbuff.h 
    655755+++ b/include/linux/skbuff.h 
    656 @@ -302,6 +302,10 @@ struct sk_buff { 
     756@@ -28,6 +28,9 @@ 
     757 #include <linux/rcupdate.h> 
     758 #include <linux/dmaengine.h> 
     759 #include <linux/hrtimer.h> 
     760+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     761+#include <linux/imq.h> 
     762+#endif 
     763  
     764 #define HAVE_ALLOC_SKB         /* For the drivers to know */ 
     765 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */ 
     766@@ -272,6 +275,9 @@ 
     767         * first. This is owned by whoever has the skb queued ATM. 
     768         */ 
     769        char                    cb[48]; 
     770+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     771+       void                    *cb_next; 
     772+#endif 
     773  
     774        unsigned int            len, 
     775                                data_len; 
     776@@ -302,6 +308,9 @@ 
    657777        struct nf_conntrack     *nfct; 
    658778        struct sk_buff          *nfct_reasm; 
    659779 #endif 
    660780+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
    661 +       unsigned char                   imq_flags; 
    662781+       struct nf_queue_entry   *nf_queue_entry; 
    663782+#endif 
     
    665784        struct nf_bridge_info   *nf_bridge; 
    666785 #endif 
    667 @@ -1633,6 +1637,10 @@ static inline void __nf_copy(struct sk_b 
     786@@ -321,6 +330,9 @@ 
     787        __u8                    do_not_encrypt:1; 
     788 #endif 
     789        /* 0/13/14 bit hole */ 
     790+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     791+       __u8                    imq_flags:IMQ_F_BITS; 
     792+#endif 
     793  
     794 #ifdef CONFIG_NET_DMA 
     795        dma_cookie_t            dma_cookie; 
     796@@ -353,6 +365,12 @@ 
     797  
     798 #include <asm/system.h> 
     799  
     800+ 
     801+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     802+extern int skb_save_cb(struct sk_buff *skb); 
     803+extern int skb_restore_cb(struct sk_buff *skb); 
     804+#endif 
     805+ 
     806 extern void kfree_skb(struct sk_buff *skb); 
     807 extern void           __kfree_skb(struct sk_buff *skb); 
     808 extern struct sk_buff *__alloc_skb(unsigned int size, 
     809@@ -1633,6 +1651,10 @@ 
    668810        dst->nfct_reasm = src->nfct_reasm; 
    669811        nf_conntrack_get_reasm(src->nfct_reasm); 
     
    688830 #include <linux/seq_file.h> 
    689831 #include <linux/stat.h> 
    690 @@ -1624,7 +1627,11 @@ int dev_hard_start_xmit(struct sk_buff * 
     832@@ -1624,7 +1627,11 @@ 
    691833                        struct netdev_queue *txq) 
    692834 { 
     
    701843  
    702844                if (netif_needs_gso(dev, skb)) { 
     845@@ -1715,8 +1722,7 @@ 
     846        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); 
     847 } 
     848  
     849-static struct netdev_queue *dev_pick_tx(struct net_device *dev, 
     850-                                       struct sk_buff *skb) 
     851+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) 
     852 { 
     853        u16 queue_index = 0; 
     854  
     855@@ -1728,6 +1734,7 @@ 
     856        skb_set_queue_mapping(skb, queue_index); 
     857        return netdev_get_tx_queue(dev, queue_index); 
     858 } 
     859+EXPORT_SYMBOL(dev_pick_tx); 
     860  
     861 /** 
     862  *     dev_queue_xmit - transmit a buffer 
     863--- a/include/linux/netdevice.h 
     864+++ b/include/linux/netdevice.h 
     865@@ -915,6 +915,7 @@ 
     866 extern int             dev_open(struct net_device *dev); 
     867 extern int             dev_close(struct net_device *dev); 
     868 extern void            dev_disable_lro(struct net_device *dev); 
     869+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb); 
     870 extern int             dev_queue_xmit(struct sk_buff *skb); 
     871 extern int             register_netdevice(struct net_device *dev); 
     872 extern void            unregister_netdevice(struct net_device *dev); 
    703873--- /dev/null 
    704 +++ b/net/ipv4/netfilter/ipt_IMQ.c 
    705 @@ -0,0 +1,69 @@ 
     874+++ b/include/linux/netfilter/xt_IMQ.h 
     875@@ -0,0 +1,9 @@ 
     876+#ifndef _XT_IMQ_H 
     877+#define _XT_IMQ_H 
     878+ 
     879+struct xt_imq_info { 
     880+       unsigned int todev;     /* target imq device */ 
     881+}; 
     882+ 
     883+#endif /* _XT_IMQ_H */ 
     884+ 
     885--- a/include/net/netfilter/nf_queue.h 
     886+++ b/include/net/netfilter/nf_queue.h 
     887@@ -13,6 +13,12 @@ 
     888        struct net_device       *indev; 
     889        struct net_device       *outdev; 
     890        int                     (*okfn)(struct sk_buff *); 
     891+ 
     892+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     893+       int                     (*next_outfn)(struct nf_queue_entry *entry, 
     894+                                             unsigned int queuenum); 
     895+       unsigned int            next_queuenum; 
     896+#endif 
     897 }; 
     898  
     899 #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) 
     900@@ -30,5 +36,11 @@ 
     901                                       const struct nf_queue_handler *qh); 
     902 extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); 
     903 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); 
     904+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry); 
     905+ 
     906+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     907+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh); 
     908+extern void nf_unregister_queue_imq_handler(void); 
     909+#endif 
     910  
     911 #endif /* _NF_QUEUE_H */ 
     912--- a/net/core/skbuff.c 
     913+++ b/net/core/skbuff.c 
     914@@ -69,6 +69,9 @@ 
     915  
     916 static struct kmem_cache *skbuff_head_cache __read_mostly; 
     917 static struct kmem_cache *skbuff_fclone_cache __read_mostly; 
     918+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     919+static struct kmem_cache *skbuff_cb_store_cache __read_mostly; 
     920+#endif 
     921  
     922 static void sock_pipe_buf_release(struct pipe_inode_info *pipe, 
     923                                  struct pipe_buffer *buf) 
     924@@ -88,6 +91,80 @@ 
     925        return 1; 
     926 } 
     927  
     928+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     929+/* Control buffer save/restore for IMQ devices */ 
     930+struct skb_cb_table { 
     931+       void                    *cb_next; 
     932+       atomic_t                refcnt; 
     933+       char                    cb[48]; 
     934+}; 
     935+ 
     936+static DEFINE_SPINLOCK(skb_cb_store_lock); 
     937+ 
     938+int skb_save_cb(struct sk_buff *skb) 
     939+{ 
     940+       struct skb_cb_table *next; 
     941+ 
     942+       next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC); 
     943+       if (!next) 
     944+               return -ENOMEM; 
     945+ 
     946+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     947+ 
     948+       memcpy(next->cb, skb->cb, sizeof(skb->cb)); 
     949+       next->cb_next = skb->cb_next; 
     950+ 
     951+       atomic_set(&next->refcnt, 1); 
     952+ 
     953+       skb->cb_next = next; 
     954+       return 0; 
     955+} 
     956+EXPORT_SYMBOL(skb_save_cb); 
     957+ 
     958+int skb_restore_cb(struct sk_buff *skb) 
     959+{ 
     960+       struct skb_cb_table *next; 
     961+ 
     962+       if (!skb->cb_next) 
     963+               return 0; 
     964+ 
     965+       next = skb->cb_next; 
     966+ 
     967+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     968+ 
     969+       memcpy(skb->cb, next->cb, sizeof(skb->cb)); 
     970+       skb->cb_next = next->cb_next; 
     971+ 
     972+       spin_lock(&skb_cb_store_lock); 
     973+ 
     974+       if (atomic_dec_and_test(&next->refcnt)) { 
     975+               kmem_cache_free(skbuff_cb_store_cache, next); 
     976+       } 
     977+ 
     978+       spin_unlock(&skb_cb_store_lock); 
     979+ 
     980+       return 0; 
     981+} 
     982+EXPORT_SYMBOL(skb_restore_cb); 
     983+ 
     984+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old) 
     985+{ 
     986+       struct skb_cb_table *next; 
     987+ 
     988+       if (!old->cb_next) { 
     989+               new->cb_next = 0; 
     990+               return; 
     991+       } 
     992+ 
     993+       spin_lock(&skb_cb_store_lock); 
     994+ 
     995+       next = old->cb_next; 
     996+       atomic_inc(&next->refcnt); 
     997+       new->cb_next = next; 
     998+ 
     999+       spin_unlock(&skb_cb_store_lock); 
     1000+} 
     1001+#endif 
     1002  
     1003 /* Pipe buffer operations for a socket. */ 
     1004 static struct pipe_buf_operations sock_pipe_buf_ops = { 
     1005@@ -362,6 +439,15 @@ 
     1006                WARN_ON(in_irq()); 
     1007                skb->destructor(skb); 
     1008        } 
     1009+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1010+       /* This should not happen. When it does, avoid memleak by restoring 
     1011+       the chain of cb-backups. */ 
     1012+       while(skb->cb_next != NULL) { 
     1013+               printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n", 
     1014+                       skb->cb_next); 
     1015+               skb_restore_cb(skb); 
     1016+       } 
     1017+#endif 
     1018 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 
     1019        nf_conntrack_put(skb->nfct); 
     1020        nf_conntrack_put_reasm(skb->nfct_reasm); 
     1021@@ -424,6 +510,9 @@ 
     1022        new->sp                 = secpath_get(old->sp); 
     1023 #endif 
     1024        memcpy(new->cb, old->cb, sizeof(old->cb)); 
     1025+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1026+       skb_copy_stored_cb(new, old); 
     1027+#endif 
     1028        new->csum_start         = old->csum_start; 
     1029        new->csum_offset        = old->csum_offset; 
     1030        new->local_df           = old->local_df; 
     1031@@ -2326,6 +2415,13 @@ 
     1032                                                0, 
     1033                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1034                                                NULL); 
     1035+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1036+       skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache", 
     1037+                                                 sizeof(struct skb_cb_table), 
     1038+                                                 0, 
     1039+                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1040+                                                 NULL); 
     1041+#endif 
     1042 } 
     1043  
     1044 /** 
     1045--- a/net/netfilter/Kconfig 
     1046+++ b/net/netfilter/Kconfig 
     1047@@ -342,6 +342,18 @@ 
     1048  
     1049          To compile it as a module, choose M here.  If unsure, say N. 
     1050  
     1051+config NETFILTER_XT_TARGET_IMQ 
     1052+        tristate '"IMQ" target support' 
     1053+       depends on NETFILTER_XTABLES 
     1054+       depends on IP_NF_MANGLE || IP6_NF_MANGLE 
     1055+       select IMQ 
     1056+       default m if NETFILTER_ADVANCED=n 
     1057+        help 
     1058+          This option adds a `IMQ' target which is used to specify if and 
     1059+          to which imq device packets should get enqueued/dequeued. 
     1060+ 
     1061+          To compile it as a module, choose M here.  If unsure, say N. 
     1062+ 
     1063 config NETFILTER_XT_TARGET_MARK 
     1064        tristate '"MARK" target support' 
     1065        depends on NETFILTER_XTABLES 
     1066--- a/net/netfilter/Makefile 
     1067+++ b/net/netfilter/Makefile 
     1068@@ -42,6 +42,7 @@ 
     1069 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 
     1070 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 
     1071 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 
     1072+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o 
     1073 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o 
     1074 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 
     1075 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 
     1076--- a/net/netfilter/nf_queue.c 
     1077+++ b/net/netfilter/nf_queue.c 
     1078@@ -20,6 +20,26 @@ 
     1079  
     1080 static DEFINE_MUTEX(queue_handler_mutex); 
     1081  
     1082+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1083+static const struct nf_queue_handler *queue_imq_handler; 
     1084+ 
     1085+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh) 
     1086+{ 
     1087+       mutex_lock(&queue_handler_mutex); 
     1088+       rcu_assign_pointer(queue_imq_handler, qh); 
     1089+       mutex_unlock(&queue_handler_mutex); 
     1090+} 
     1091+EXPORT_SYMBOL(nf_register_queue_imq_handler); 
     1092+ 
     1093+void nf_unregister_queue_imq_handler(void) 
     1094+{ 
     1095+       mutex_lock(&queue_handler_mutex); 
     1096+       rcu_assign_pointer(queue_imq_handler, NULL); 
     1097+       mutex_unlock(&queue_handler_mutex); 
     1098+} 
     1099+EXPORT_SYMBOL(nf_unregister_queue_imq_handler); 
     1100+#endif 
     1101+ 
     1102 /* return EBUSY when somebody else is registered, return EEXIST if the 
     1103  * same handler is registered, return 0 in case of success. */ 
     1104 int nf_register_queue_handler(int pf, const struct nf_queue_handler *qh) 
     1105@@ -80,7 +100,7 @@ 
     1106 } 
     1107 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 
     1108  
     1109-static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1110+void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1111 { 
     1112        /* Release those devices we held, or Alexey will kill me. */ 
     1113        if (entry->indev) 
     1114@@ -100,6 +120,7 @@ 
     1115        /* Drop reference to owner of hook which queued us. */ 
     1116        module_put(entry->elem->owner); 
     1117 } 
     1118+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); 
     1119  
     1120 /* 
     1121  * Any packet that leaves via this function must come back 
     1122@@ -121,12 +142,26 @@ 
     1123 #endif 
     1124        const struct nf_afinfo *afinfo; 
     1125        const struct nf_queue_handler *qh; 
     1126+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1127+       const struct nf_queue_handler *qih = NULL; 
     1128+#endif 
     1129  
     1130        /* QUEUE == DROP if noone is waiting, to be safe. */ 
     1131        rcu_read_lock(); 
     1132  
     1133        qh = rcu_dereference(queue_handler[pf]); 
     1134+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1135+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     1136+       if (pf == PF_INET || pf == PF_INET6) 
     1137+#else 
     1138+       if (pf == PF_INET) 
     1139+#endif 
     1140+               qih = rcu_dereference(queue_imq_handler); 
     1141+ 
     1142+       if (!qh && !qih) 
     1143+#else /* !IMQ */ 
     1144        if (!qh) 
     1145+#endif 
     1146                goto err_unlock; 
     1147  
     1148        afinfo = nf_get_afinfo(pf); 
     1149@@ -145,6 +180,10 @@ 
     1150                .indev  = indev, 
     1151                .outdev = outdev, 
     1152                .okfn   = okfn, 
     1153+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1154+               .next_outfn = qh ? qh->outfn : NULL, 
     1155+               .next_queuenum = queuenum, 
     1156+#endif 
     1157        }; 
     1158  
     1159        /* If it's going away, ignore hook. */ 
     1160@@ -170,8 +209,19 @@ 
     1161        } 
     1162 #endif 
     1163        afinfo->saveroute(skb, entry); 
     1164+ 
     1165+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1166+       if (qih) { 
     1167+               status = qih->outfn(entry, queuenum); 
     1168+               goto imq_skip_queue; 
     1169+       } 
     1170+#endif 
     1171+ 
     1172        status = qh->outfn(entry, queuenum); 
     1173  
     1174+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1175+imq_skip_queue: 
     1176+#endif 
     1177        rcu_read_unlock(); 
     1178  
     1179        if (status < 0) { 
     1180--- /dev/null 
     1181+++ b/net/netfilter/xt_IMQ.c 
     1182@@ -0,0 +1,81 @@ 
    7061183+/* 
    7071184+ * This target marks packets to be enqueued to an imq device 
     
    7091186+#include <linux/module.h> 
    7101187+#include <linux/skbuff.h> 
    711 +#include <linux/netfilter_ipv4/ip_tables.h> 
    712 +#include <linux/netfilter_ipv4/ipt_IMQ.h> 
     1188+#include <linux/netfilter/x_tables.h> 
     1189+#include <linux/netfilter/xt_IMQ.h> 
    7131190+#include <linux/imq.h> 
    7141191+ 
     
    7201197+                              const void *targinfo) 
    7211198+{ 
    722 +       struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo; 
    723 + 
    724 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
    725 + 
    726 +       return XT_CONTINUE; 
    727 +} 
    728 + 
    729 +static bool imq_checkentry(const char *tablename, 
    730 +                         const void *e, 
    731 +                         const struct xt_target *target, 
    732 +                         void *targinfo, 
    733 +                         unsigned int hook_mask) 
    734 +{ 
    735 +       struct ipt_imq_info *mr; 
    736 + 
    737 +       mr = (struct ipt_imq_info *)targinfo; 
    738 + 
    739 +       if (mr->todev > IMQ_MAX_DEVS) { 
    740 +               printk(KERN_WARNING 
    741 +                      "IMQ: invalid device specified, highest is %u\n", 
    742 +                      IMQ_MAX_DEVS); 
    743 +               return 0; 
    744 +       } 
    745 + 
    746 +       return 1; 
    747 +} 
    748 + 
    749 +static struct xt_target ipt_imq_reg = { 
    750 +       .name           = "IMQ", 
    751 +       .family         = AF_INET, 
    752 +       .target         = imq_target, 
    753 +       .targetsize     = sizeof(struct ipt_imq_info), 
    754 +       .checkentry     = imq_checkentry, 
    755 +       .me             = THIS_MODULE, 
    756 +       .table          = "mangle" 
    757 +}; 
    758 + 
    759 +static int __init init(void) 
    760 +{ 
    761 +       return xt_register_target(&ipt_imq_reg); 
    762 +} 
    763 + 
    764 +static void __exit fini(void) 
    765 +{ 
    766 +       xt_unregister_target(&ipt_imq_reg); 
    767 +} 
    768 + 
    769 +module_init(init); 
    770 +module_exit(fini); 
    771 + 
    772 +MODULE_AUTHOR("http://www.linuximq.net"); 
    773 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    774 +MODULE_LICENSE("GPL"); 
    775 --- a/net/ipv4/netfilter/Kconfig 
    776 +++ b/net/ipv4/netfilter/Kconfig 
    777 @@ -123,6 +123,17 @@ config IP_NF_FILTER 
    778   
    779           To compile it as a module, choose M here.  If unsure, say N. 
    780   
    781 +config IP_NF_TARGET_IMQ 
    782 +       tristate "IMQ target support" 
    783 +       depends on IP_NF_MANGLE && IMQ 
    784 +       help 
    785 +         This option adds a `IMQ' target which is used to specify if and 
    786 +         to which IMQ device packets should get enqueued/dequeued. 
    787 + 
    788 +        For more information visit: http://www.linuximq.net/ 
    789 + 
    790 +         To compile it as a module, choose M here.  If unsure, say N. 
    791 + 
    792  config IP_NF_TARGET_REJECT 
    793         tristate "REJECT target support" 
    794         depends on IP_NF_FILTER 
    795 --- a/net/ipv4/netfilter/Makefile 
    796 +++ b/net/ipv4/netfilter/Makefile 
    797 @@ -56,6 +56,7 @@ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set 
    798  obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 
    799  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 
    800  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 
    801 +obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o 
    802  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 
    803  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 
    804  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 
    805 --- /dev/null 
    806 +++ b/net/ipv6/netfilter/ip6t_IMQ.c 
    807 @@ -0,0 +1,69 @@ 
    808 +/* 
    809 + * This target marks packets to be enqueued to an imq device 
    810 + */ 
    811 +#include <linux/module.h> 
    812 +#include <linux/skbuff.h> 
    813 +#include <linux/netfilter_ipv6/ip6_tables.h> 
    814 +#include <linux/netfilter_ipv6/ip6t_IMQ.h> 
    815 +#include <linux/imq.h> 
    816 + 
    817 +static unsigned int imq_target(struct sk_buff *pskb, 
    818 +                              const struct net_device *in, 
    819 +                              const struct net_device *out, 
    820 +                              unsigned int hooknum, 
    821 +                              const struct xt_target *target, 
    822 +                              const void *targinfo) 
    823 +{ 
    824 +       struct ip6t_imq_info *mr = (struct ip6t_imq_info *)targinfo; 
    825 + 
    826 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
     1199+       const struct xt_imq_info *mr = targinfo; 
     1200+ 
     1201+       pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE; 
    8271202+ 
    8281203+       return XT_CONTINUE; 
     
    8351210+                         unsigned int hook_mask) 
    8361211+{ 
    837 +       struct ip6t_imq_info *mr; 
    838 + 
    839 +       mr = (struct ip6t_imq_info *)targinfo; 
    840 + 
    841 +       if (mr->todev > IMQ_MAX_DEVS) { 
     1212+       struct xt_imq_info *mr = targinfo; 
     1213+ 
     1214+       if (mr->todev > IMQ_MAX_DEVS - 1) { 
    8421215+               printk(KERN_WARNING 
    8431216+                      "IMQ: invalid device specified, highest is %u\n", 
    844 +                      IMQ_MAX_DEVS); 
     1217+                      IMQ_MAX_DEVS - 1); 
    8451218+               return 0; 
    8461219+       } 
     
    8491222+} 
    8501223+ 
    851 +static struct xt_target ip6t_imq_reg = { 
    852 +       .name           = "IMQ", 
    853 +       .family         = AF_INET6, 
    854 +       .target         = imq_target, 
    855 +       .targetsize     = sizeof(struct ip6t_imq_info), 
    856 +       .table          = "mangle", 
    857 +       .checkentry     = imq_checkentry, 
    858 +       .me             = THIS_MODULE 
     1224+static struct xt_target xt_imq_reg[] __read_mostly = { 
     1225+       { 
     1226+               .name           = "IMQ", 
     1227+               .family         = AF_INET, 
     1228+               .target         = imq_target, 
     1229+               .targetsize     = sizeof(struct xt_imq_info), 
     1230+               .table          = "mangle", 
     1231+               .checkentry     = imq_checkentry, 
     1232+               .me             = THIS_MODULE 
     1233+       }, 
     1234+       { 
     1235+               .name           = "IMQ", 
     1236+               .family         = AF_INET6, 
     1237+               .target         = imq_target, 
     1238+               .targetsize     = sizeof(struct xt_imq_info), 
     1239+               .table          = "mangle", 
     1240+               .checkentry     = imq_checkentry, 
     1241+               .me             = THIS_MODULE 
     1242+       }, 
    8591243+}; 
    8601244+ 
    861 +static int __init init(void) 
    862 +{ 
    863 +       return xt_register_target(&ip6t_imq_reg); 
    864 +} 
    865 + 
    866 +static void __exit fini(void) 
    867 +{ 
    868 +       xt_unregister_target(&ip6t_imq_reg); 
    869 +} 
    870 + 
    871 +module_init(init); 
    872 +module_exit(fini); 
     1245+static int __init imq_init(void) 
     1246+{ 
     1247+       return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1248+} 
     1249+ 
     1250+static void __exit imq_fini(void) 
     1251+{ 
     1252+       xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1253+} 
     1254+ 
     1255+module_init(imq_init); 
     1256+module_exit(imq_fini); 
    8731257+ 
    8741258+MODULE_AUTHOR("http://www.linuximq.net"); 
    8751259+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    8761260+MODULE_LICENSE("GPL"); 
    877 --- a/net/ipv6/netfilter/Kconfig 
    878 +++ b/net/ipv6/netfilter/Kconfig 
    879 @@ -179,6 +179,15 @@ config IP6_NF_MANGLE 
    880   
    881           To compile it as a module, choose M here.  If unsure, say N. 
    882   
    883 +config IP6_NF_TARGET_IMQ 
    884 +       tristate "IMQ target support" 
    885 +       depends on IP6_NF_MANGLE && IMQ 
    886 +       help 
    887 +          This option adds a `IMQ' target which is used to specify if and 
    888 +          to which imq device packets should get enqueued/dequeued. 
    889 + 
    890 +          To compile it as a module, choose M here.  If unsure, say N. 
    891 + 
    892  config IP6_NF_TARGET_HL 
    893         tristate  'HL (hoplimit) target support' 
    894         depends on IP6_NF_MANGLE 
    895 --- a/net/ipv6/netfilter/Makefile 
    896 +++ b/net/ipv6/netfilter/Makefile 
    897 @@ -6,6 +6,7 @@ 
    898  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 
    899  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 
    900  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 
    901 +obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o 
    902  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 
    903  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 
    904  obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 
    905 --- a/net/sched/sch_generic.c 
    906 +++ b/net/sched/sch_generic.c 
    907 @@ -188,6 +188,7 @@ void __qdisc_run(struct Qdisc *q) 
    908   
    909         clear_bit(__QDISC_STATE_RUNNING, &q->state); 
    910  } 
    911 +EXPORT_SYMBOL(__qdisc_run); 
    912   
    913  static void dev_watchdog(unsigned long arg) 
    914  { 
     1261+MODULE_ALIAS("ipt_IMQ"); 
     1262+MODULE_ALIAS("ip6t_IMQ"); 
     1263+ 
  • trunk/target/linux/generic-2.6/patches-2.6.27/180-netfilter_depends.patch

    r14456 r15655  
    11--- a/net/netfilter/Kconfig 
    22+++ b/net/netfilter/Kconfig 
    3 @@ -165,7 +165,7 @@ config NF_CONNTRACK_FTP 
     3@@ -165,7 +165,7 @@ 
    44  
    55 config NF_CONNTRACK_H323 
     
    1010        help 
    1111          H.323 is a VoIP signalling protocol from ITU-T. As one of the most 
    12 @@ -443,7 +443,7 @@ config NETFILTER_XT_TARGET_CONNSECMARK 
     12@@ -455,7 +455,7 @@ 
    1313  
    1414 config NETFILTER_XT_TARGET_TCPMSS 
  • trunk/target/linux/generic-2.6/patches-2.6.27/190-netfilter_rtsp.patch

    r14598 r15655  
    295295--- a/net/ipv4/netfilter/Makefile 
    296296+++ b/net/ipv4/netfilter/Makefile 
    297 @@ -23,6 +23,7 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_am 
     297@@ -23,6 +23,7 @@ 
    298298 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 
    299299 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 
     
    305305--- a/net/netfilter/Kconfig 
    306306+++ b/net/netfilter/Kconfig 
    307 @@ -278,6 +278,16 @@ config NF_CONNTRACK_TFTP 
     307@@ -278,6 +278,16 @@ 
    308308  
    309309          To compile it as a module, choose M here.  If unsure, say N. 
     
    324324--- a/net/netfilter/Makefile 
    325325+++ b/net/netfilter/Makefile 
    326 @@ -33,6 +33,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co 
     326@@ -33,6 +33,7 @@ 
    327327 obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o 
    328328 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o 
     
    334334--- a/net/ipv4/netfilter/Kconfig 
    335335+++ b/net/ipv4/netfilter/Kconfig 
    336 @@ -281,6 +281,11 @@ config NF_NAT_IRC 
     336@@ -270,6 +270,11 @@ 
    337337        depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 
    338338        default NF_NAT && NF_CONNTRACK_IRC 
  • trunk/target/linux/generic-2.6/patches-2.6.28/150-netfilter_imq.patch

    r14949 r15655  
    11--- /dev/null 
    22+++ b/drivers/net/imq.c 
    3 @@ -0,0 +1,474 @@ 
     3@@ -0,0 +1,567 @@ 
    44+/* 
    55+ *             Pseudo-driver for the intermediate queue device. 
     
    5252+ * 
    5353+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
    54 + *            of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
     54+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
    5555+ *             recursive locking. New initialization routines to fix 'rmmod' not 
    5656+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna) 
     57+ * 
     58+ *             2008/08/06 - 2.6.26 - (JK) 
     59+ *              - Replaced tasklet with 'netif_schedule()'. 
     60+ *              - Cleaned up and added comments for imq_nf_queue(). 
     61+ * 
     62+ *             2009/04/12 
     63+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping 
     64+ *                control buffer. This is needed because qdisc-layer on kernels 
     65+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna) 
     66+ *              - Add better locking for IMQ device. Hopefully this will solve 
     67+ *                SMP issues. (Jussi Kivilinna) 
     68+ *              - Port to 2.6.27 
     69+ *              - Port to 2.6.28 
     70+ * 
     71+ *             2009/04/20 - (Jussi Kivilinna) 
     72+ *              - Fix rmmod not working 
     73+ *              - Use netdevice feature flags to avoid extra packet handling 
     74+ *                by core networking layer and possibly increase performance. 
    5775+ * 
    5876+ *            Also, many thanks to pablo Sebastian Greco for making the initial 
     
    6583+#include <linux/kernel.h> 
    6684+#include <linux/moduleparam.h> 
     85+#include <linux/list.h> 
    6786+#include <linux/skbuff.h> 
    6887+#include <linux/netdevice.h> 
     88+#include <linux/etherdevice.h> 
    6989+#include <linux/rtnetlink.h> 
    7090+#include <linux/if_arp.h> 
     
    7797+#include <net/pkt_sched.h> 
    7898+#include <net/netfilter/nf_queue.h> 
    79 + 
    80 +struct imq_private { 
    81 +       struct tasklet_struct tasklet; 
    82 +       unsigned long tasklet_pending; 
    83 +}; 
    8499+ 
    85100+static nf_hookfn imq_nf_hook; 
     
    141156+#endif 
    142157+ 
     158+static DEFINE_SPINLOCK(imq_nf_queue_lock); 
     159+ 
    143160+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; 
     161+ 
    144162+ 
    145163+static struct net_device_stats *imq_get_stats(struct net_device *dev) 
     
    154172+ 
    155173+       if (entry) { 
    156 +               if (entry->indev) 
    157 +                       dev_put(entry->indev); 
    158 +               if (entry->outdev) 
    159 +                       dev_put(entry->outdev); 
     174+               nf_queue_entry_release_refs(entry); 
    160175+               kfree(entry); 
    161176+       } 
     177+ 
     178+       skb_restore_cb(skb); /* kfree backup */ 
     179+} 
     180+ 
     181+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 
     182+{ 
     183+       int status; 
     184+ 
     185+       if (!entry->next_outfn) { 
     186+               spin_lock_bh(&imq_nf_queue_lock); 
     187+               nf_reinject(entry, verdict); 
     188+               spin_unlock_bh(&imq_nf_queue_lock); 
     189+               return; 
     190+       } 
     191+ 
     192+       rcu_read_lock(); 
     193+       local_bh_disable(); 
     194+       status = entry->next_outfn(entry, entry->next_queuenum); 
     195+       local_bh_enable(); 
     196+       if (status < 0) { 
     197+               nf_queue_entry_release_refs(entry); 
     198+               kfree_skb(entry->skb); 
     199+               kfree(entry); 
     200+       } 
     201+ 
     202+       rcu_read_unlock(); 
    162203+} 
    163204+ 
     
    170211+       skb->destructor = NULL; 
    171212+ 
     213+       skb_restore_cb(skb); /* restore skb->cb */ 
     214+ 
    172215+       dev->trans_start = jiffies; 
    173 +       nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
     216+       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
    174217+       return 0; 
    175218+} 
     
    178221+{ 
    179222+       struct net_device *dev; 
    180 +       struct imq_private *priv; 
    181 +       struct sk_buff *skb2 = NULL; 
     223+       struct sk_buff *skb_orig, *skb, *skb_shared; 
    182224+       struct Qdisc *q; 
    183 +       unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; 
    184 +       int ret = -1; 
    185 + 
    186 +       if (index > numdevs) 
    187 +               return -1; 
     225+       struct netdev_queue *txq; 
     226+       int users, index; 
     227+       int retval = -EINVAL; 
     228+ 
     229+       index = entry->skb->imq_flags & IMQ_F_IFMASK; 
     230+       if (unlikely(index > numdevs - 1)) { 
     231+               if (net_ratelimit()) 
     232+                       printk(KERN_WARNING 
     233+                              "IMQ: invalid device specified, highest is %u\n", 
     234+                              numdevs - 1); 
     235+               retval = -EINVAL; 
     236+               goto out; 
     237+       } 
    188238+ 
    189239+       /* check for imq device by index from cache */ 
    190240+       dev = imq_devs_cache[index]; 
    191 +       if (!dev) { 
     241+       if (unlikely(!dev)) { 
    192242+               char buf[8]; 
    193243+ 
     
    198248+                       /* not found ?!*/ 
    199249+                       BUG(); 
    200 +                       return -1; 
     250+                       retval = -ENODEV; 
     251+                       goto out; 
    201252+               } 
    202253+ 
    203254+               imq_devs_cache[index] = dev; 
    204 +       } 
    205 + 
    206 +       priv = netdev_priv(dev); 
    207 +       if (!(dev->flags & IFF_UP)) { 
     255+               dev_put(dev); 
     256+       } 
     257+ 
     258+       if (unlikely(!(dev->flags & IFF_UP))) { 
    208259+               entry->skb->imq_flags = 0; 
    209 +               nf_reinject(entry, NF_ACCEPT); 
    210 +               return 0; 
     260+               imq_nf_reinject(entry, NF_ACCEPT); 
     261+               retval = 0; 
     262+               goto out; 
    211263+       } 
    212264+       dev->last_rx = jiffies; 
    213265+ 
    214 +       if (entry->skb->destructor) { 
    215 +               skb2 = entry->skb; 
    216 +               entry->skb = skb_clone(entry->skb, GFP_ATOMIC); 
    217 +               if (!entry->skb) 
    218 +                       return -1; 
    219 +       } 
    220 +       entry->skb->nf_queue_entry = entry; 
    221 + 
    222 +       dev->stats.rx_bytes += entry->skb->len; 
     266+       skb = entry->skb; 
     267+       skb_orig = NULL; 
     268+ 
     269+       /* skb has owner? => make clone */ 
     270+       if (unlikely(skb->destructor)) { 
     271+               skb_orig = skb; 
     272+               skb = skb_clone(skb, GFP_ATOMIC); 
     273+               if (!skb) { 
     274+                       retval = -ENOMEM; 
     275+                       goto out; 
     276+               } 
     277+               entry->skb = skb; 
     278+       } 
     279+ 
     280+       skb->nf_queue_entry = entry; 
     281+ 
     282+       dev->stats.rx_bytes += skb->len; 
    223283+       dev->stats.rx_packets++; 
    224284+ 
    225 +       spin_lock_bh(&dev->queue_lock); 
    226 +       q = dev->qdisc; 
    227 +       if (q->enqueue) { 
    228 +               q->enqueue(skb_get(entry->skb), q); 
    229 +               if (skb_shared(entry->skb)) { 
    230 +                       entry->skb->destructor = imq_skb_destructor; 
    231 +                       kfree_skb(entry->skb); 
    232 +                       ret = 0; 
    233 +               } 
    234 +       } 
    235 +       if (!test_and_set_bit(1, &priv->tasklet_pending)) 
    236 +               tasklet_schedule(&priv->tasklet); 
    237 +       spin_unlock_bh(&dev->queue_lock); 
    238 + 
    239 +       if (skb2) 
    240 +               kfree_skb(ret ? entry->skb : skb2); 
    241 + 
    242 +       return ret; 
     285+       txq = dev_pick_tx(dev, skb); 
     286+ 
     287+       q = rcu_dereference(txq->qdisc); 
     288+       if (unlikely(!q->enqueue)) 
     289+               goto packet_not_eaten_by_imq_dev; 
     290+ 
     291+       spin_lock_bh(qdisc_lock(q)); 
     292+ 
     293+       users = atomic_read(&skb->users); 
     294+ 
     295+       skb_shared = skb_get(skb); /* increase reference count by one */ 
     296+       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will 
     297+                                       overwrite it */ 
     298+       qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ 
     299+ 
     300+       if (likely(atomic_read(&skb_shared->users) == users + 1)) { 
     301+               kfree_skb(skb_shared); /* decrease reference count by one */ 
     302+ 
     303+               skb->destructor = &imq_skb_destructor; 
     304+ 
     305+               /* cloned? */ 
     306+               if (skb_orig) 
     307+                       kfree_skb(skb_orig); /* free original */ 
     308+ 
     309+               spin_unlock_bh(qdisc_lock(q)); 
     310+ 
     311+               /* schedule qdisc dequeue */ 
     312+               __netif_schedule(q); 
     313+ 
     314+               retval = 0; 
     315+               goto out; 
     316+       } else { 
     317+               skb_restore_cb(skb_shared); /* restore skb->cb */ 
     318+               /* qdisc dropped packet and decreased skb reference count of 
     319+                * skb, so we don't really want to and try refree as that would 
     320+                * actually destroy the skb. */ 
     321+               spin_unlock_bh(qdisc_lock(q)); 
     322+               goto packet_not_eaten_by_imq_dev; 
     323+       } 
     324+ 
     325+packet_not_eaten_by_imq_dev: 
     326+       /* cloned? restore original */ 
     327+       if (skb_orig) { 
     328+               kfree_skb(skb); 
     329+               entry->skb = skb_orig; 
     330+       } 
     331+       retval = -1; 
     332+out: 
     333+       return retval; 
    243334+} 
    244335+ 
     
    248339+}; 
    249340+ 
    250 +static void qdisc_run_tasklet(unsigned long arg) 
    251 +{ 
    252 +       struct net_device *dev = (struct net_device *)arg; 
    253 +       struct imq_private *priv = netdev_priv(dev); 
    254 + 
    255 +       spin_lock(&dev->queue_lock); 
    256 +       qdisc_run(dev); 
    257 +       clear_bit(1, &priv->tasklet_pending); 
    258 +       spin_unlock(&dev->queue_lock); 
    259 +} 
    260 + 
    261341+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, 
    262342+                               const struct net_device *indev, 
     
    272352+static int imq_close(struct net_device *dev) 
    273353+{ 
    274 +       struct imq_private *priv = netdev_priv(dev); 
    275 + 
    276 +       tasklet_kill(&priv->tasklet); 
    277354+       netif_stop_queue(dev); 
    278 + 
    279355+       return 0; 
    280356+} 
     
    282358+static int imq_open(struct net_device *dev) 
    283359+{ 
    284 +       struct imq_private *priv = netdev_priv(dev); 
    285 + 
    286 +       tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev); 
    287360+       netif_start_queue(dev); 
    288 + 
    289361+       return 0; 
    290362+} 
     
    300372+       dev->tx_queue_len       = 11000; 
    301373+       dev->flags              = IFF_NOARP; 
     374+       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST | 
     375+                                 NETIF_F_GSO | NETIF_F_HW_CSUM | 
     376+                                 NETIF_F_HIGHDMA; 
     377+} 
     378+ 
     379+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) 
     380+{ 
     381+       int ret = 0; 
     382+ 
     383+       if (tb[IFLA_ADDRESS]) { 
     384+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 
     385+                       ret = -EINVAL; 
     386+                       goto end; 
     387+               } 
     388+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { 
     389+                       ret = -EADDRNOTAVAIL; 
     390+                       goto end; 
     391+               } 
     392+       } 
     393+       return 0; 
     394+end: 
     395+       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); 
     396+       return ret; 
    302397+} 
    303398+ 
    304399+static struct rtnl_link_ops imq_link_ops __read_mostly = { 
    305400+       .kind           = "imq", 
    306 +       .priv_size      = sizeof(struct imq_private), 
     401+       .priv_size      = 0, 
    307402+       .setup          = imq_setup, 
     403+       .validate       = imq_validate, 
    308404+}; 
    309405+ 
     
    312408+       int err; 
    313409+ 
    314 +       err = nf_register_queue_handler(PF_INET, &nfqh); 
     410+       nf_register_queue_imq_handler(&nfqh); 
     411+ 
     412+       err = nf_register_hook(&imq_ingress_ipv4); 
    315413+       if (err) 
    316414+               goto err1; 
    317415+ 
    318 +       err = nf_register_hook(&imq_ingress_ipv4); 
     416+       err = nf_register_hook(&imq_egress_ipv4); 
    319417+       if (err) 
    320418+               goto err2; 
    321419+ 
    322 +       err = nf_register_hook(&imq_egress_ipv4); 
     420+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     421+       err = nf_register_hook(&imq_ingress_ipv6); 
    323422+       if (err) 
    324423+               goto err3; 
    325424+ 
    326 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    327 +       err = nf_register_queue_handler(PF_INET6, &nfqh); 
     425+       err = nf_register_hook(&imq_egress_ipv6); 
    328426+       if (err) 
    329427+               goto err4; 
    330 + 
    331 +       err = nf_register_hook(&imq_ingress_ipv6); 
    332 +       if (err) 
    333 +               goto err5; 
    334 + 
    335 +       err = nf_register_hook(&imq_egress_ipv6); 
    336 +       if (err) 
    337 +               goto err6; 
    338428+#endif 
    339429+ 
     
    341431+ 
    342432+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    343 +err6: 
     433+err4: 
    344434+       nf_unregister_hook(&imq_ingress_ipv6); 
    345 +err5: 
    346 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    347 +err4: 
     435+err3: 
    348436+       nf_unregister_hook(&imq_egress_ipv4); 
    349437+#endif 
    350 +err3: 
     438+err2: 
    351439+       nf_unregister_hook(&imq_ingress_ipv4); 
    352 +err2: 
    353 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
    354440+err1: 
     441+       nf_unregister_queue_imq_handler(); 
    355442+       return err; 
    356443+} 
     
    361448+       int ret; 
    362449+ 
    363 +       dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup); 
     450+       dev = alloc_netdev(0, "imq%d", imq_setup); 
    364451+       if (!dev) 
    365452+               return -ENOMEM; 
     
    384471+       int err, i; 
    385472+ 
    386 +       if (!numdevs || numdevs > IMQ_MAX_DEVS) { 
     473+       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { 
    387474+               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", 
    388475+                      IMQ_MAX_DEVS); 
     
    408495+{ 
    409496+       int err; 
     497+ 
     498+#if defined(CONFIG_IMQ_NUM_DEVS) 
     499+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); 
     500+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); 
     501+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); 
     502+#endif 
    410503+ 
    411504+       err = imq_init_devs(); 
     
    444537+       nf_unregister_hook(&imq_ingress_ipv6); 
    445538+       nf_unregister_hook(&imq_egress_ipv6); 
    446 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    447539+#endif 
    448540+       nf_unregister_hook(&imq_ingress_ipv4); 
    449541+       nf_unregister_hook(&imq_egress_ipv4); 
    450 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
     542+ 
     543+       nf_unregister_queue_imq_handler(); 
    451544+} 
    452545+ 
     
    478571--- a/drivers/net/Kconfig 
    479572+++ b/drivers/net/Kconfig 
    480 @@ -109,6 +109,129 @@ config EQUALIZER 
     573@@ -109,6 +109,129 @@ 
    481574          To compile this driver as a module, choose M here: the module 
    482575          will be called eql.  If unsure, say N. 
     
    610703--- a/drivers/net/Makefile 
    611704+++ b/drivers/net/Makefile 
    612 @@ -148,6 +148,7 @@ obj-$(CONFIG_SLHC) += slhc.o 
     705@@ -148,6 +148,7 @@ 
    613706 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o 
    614707  
     
    620713--- /dev/null 
    621714+++ b/include/linux/imq.h 
    622 @@ -0,0 +1,9 @@ 
     715@@ -0,0 +1,13 @@ 
    623716+#ifndef _IMQ_H 
    624717+#define _IMQ_H 
    625718+ 
    626 +#define IMQ_MAX_DEVS   16 
    627 + 
    628 +#define IMQ_F_IFMASK   0x7f 
    629 +#define IMQ_F_ENQUEUE  0x80 
     719+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ 
     720+#define IMQ_F_BITS     5 
     721+ 
     722+#define IMQ_F_IFMASK   0x0f 
     723+#define IMQ_F_ENQUEUE  0x10 
     724+ 
     725+#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1) 
    630726+ 
    631727+#endif /* _IMQ_H */ 
     728+ 
    632729--- /dev/null 
    633730+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 
    634 @@ -0,0 +1,8 @@ 
     731@@ -0,0 +1,10 @@ 
    635732+#ifndef _IPT_IMQ_H 
    636733+#define _IPT_IMQ_H 
    637734+ 
    638 +struct ipt_imq_info { 
    639 +       unsigned int todev;     /* target imq device */ 
    640 +}; 
     735+/* Backwards compatibility for old userspace */ 
     736+#include <linux/netfilter/xt_IMQ.h> 
     737+ 
     738+#define ipt_imq_info xt_imq_info 
    641739+ 
    642740+#endif /* _IPT_IMQ_H */ 
     741+ 
    643742--- /dev/null 
    644743+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 
    645 @@ -0,0 +1,8 @@ 
     744@@ -0,0 +1,10 @@ 
    646745+#ifndef _IP6T_IMQ_H 
    647746+#define _IP6T_IMQ_H 
    648747+ 
    649 +struct ip6t_imq_info { 
    650 +       unsigned int todev;     /* target imq device */ 
    651 +}; 
     748+/* Backwards compatibility for old userspace */ 
     749+#include <linux/netfilter/xt_IMQ.h> 
     750+ 
     751+#define ip6t_imq_info xt_imq_info 
    652752+ 
    653753+#endif /* _IP6T_IMQ_H */ 
     754+ 
    654755--- a/include/linux/skbuff.h 
    655756+++ b/include/linux/skbuff.h 
    656 @@ -308,6 +308,10 @@ struct sk_buff { 
     757@@ -28,6 +28,9 @@ 
     758 #include <linux/rcupdate.h> 
     759 #include <linux/dmaengine.h> 
     760 #include <linux/hrtimer.h> 
     761+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     762+#include <linux/imq.h> 
     763+#endif 
     764  
     765 #define HAVE_ALLOC_SKB         /* For the drivers to know */ 
     766 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */ 
     767@@ -278,6 +281,9 @@ 
     768         * first. This is owned by whoever has the skb queued ATM. 
     769         */ 
     770        char                    cb[48]; 
     771+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     772+       void                    *cb_next; 
     773+#endif 
     774  
     775        unsigned int            len, 
     776                                data_len; 
     777@@ -308,6 +314,9 @@ 
    657778        struct nf_conntrack     *nfct; 
    658779        struct sk_buff          *nfct_reasm; 
    659780 #endif 
    660781+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
    661 +       unsigned char                   imq_flags; 
    662782+       struct nf_queue_entry   *nf_queue_entry; 
    663783+#endif 
     
    665785        struct nf_bridge_info   *nf_bridge; 
    666786 #endif 
    667 @@ -1804,6 +1808,10 @@ static inline void __nf_copy(struct sk_b 
     787@@ -327,6 +336,9 @@ 
     788        __u8                    do_not_encrypt:1; 
     789 #endif 
     790        /* 0/13/14 bit hole */ 
     791+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     792+       __u8                    imq_flags:IMQ_F_BITS; 
     793+#endif 
     794  
     795 #ifdef CONFIG_NET_DMA 
     796        dma_cookie_t            dma_cookie; 
     797@@ -367,6 +379,12 @@ 
     798                          enum dma_data_direction dir); 
     799 #endif 
     800  
     801+ 
     802+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     803+extern int skb_save_cb(struct sk_buff *skb); 
     804+extern int skb_restore_cb(struct sk_buff *skb); 
     805+#endif 
     806+ 
     807 extern void kfree_skb(struct sk_buff *skb); 
     808 extern void           __kfree_skb(struct sk_buff *skb); 
     809 extern struct sk_buff *__alloc_skb(unsigned int size, 
     810@@ -1804,6 +1822,10 @@ 
    668811        dst->nfct_reasm = src->nfct_reasm; 
    669812        nf_conntrack_get_reasm(src->nfct_reasm); 
     
    688831 #include <linux/seq_file.h> 
    689832 #include <linux/stat.h> 
    690 @@ -1655,7 +1658,11 @@ int dev_hard_start_xmit(struct sk_buff * 
     833@@ -1655,7 +1658,11 @@ 
    691834                        struct netdev_queue *txq) 
    692835 { 
     
    701844  
    702845                if (netif_needs_gso(dev, skb)) { 
     846@@ -1746,8 +1753,7 @@ 
     847        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); 
     848 } 
     849  
     850-static struct netdev_queue *dev_pick_tx(struct net_device *dev, 
     851-                                       struct sk_buff *skb) 
     852+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) 
     853 { 
     854        u16 queue_index = 0; 
     855  
     856@@ -1759,6 +1765,7 @@ 
     857        skb_set_queue_mapping(skb, queue_index); 
     858        return netdev_get_tx_queue(dev, queue_index); 
     859 } 
     860+EXPORT_SYMBOL(dev_pick_tx); 
     861  
     862 /** 
     863  *     dev_queue_xmit - transmit a buffer 
     864--- a/include/linux/netdevice.h 
     865+++ b/include/linux/netdevice.h 
     866@@ -950,6 +950,7 @@ 
     867 extern int             dev_open(struct net_device *dev); 
     868 extern int             dev_close(struct net_device *dev); 
     869 extern void            dev_disable_lro(struct net_device *dev); 
     870+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb); 
     871 extern int             dev_queue_xmit(struct sk_buff *skb); 
     872 extern int             register_netdevice(struct net_device *dev); 
     873 extern void            unregister_netdevice(struct net_device *dev); 
    703874--- /dev/null 
    704 +++ b/net/ipv4/netfilter/ipt_IMQ.c 
    705 @@ -0,0 +1,69 @@ 
     875+++ b/include/linux/netfilter/xt_IMQ.h 
     876@@ -0,0 +1,9 @@ 
     877+#ifndef _XT_IMQ_H 
     878+#define _XT_IMQ_H 
     879+ 
     880+struct xt_imq_info { 
     881+       unsigned int todev;     /* target imq device */ 
     882+}; 
     883+ 
     884+#endif /* _XT_IMQ_H */ 
     885+ 
     886--- a/include/net/netfilter/nf_queue.h 
     887+++ b/include/net/netfilter/nf_queue.h 
     888@@ -13,6 +13,12 @@ 
     889        struct net_device       *indev; 
     890        struct net_device       *outdev; 
     891        int                     (*okfn)(struct sk_buff *); 
     892+ 
     893+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     894+       int                     (*next_outfn)(struct nf_queue_entry *entry, 
     895+                                             unsigned int queuenum); 
     896+       unsigned int            next_queuenum; 
     897+#endif 
     898 }; 
     899  
     900 #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) 
     901@@ -30,5 +36,11 @@ 
     902                                       const struct nf_queue_handler *qh); 
     903 extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); 
     904 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); 
     905+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry); 
     906+ 
     907+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     908+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh); 
     909+extern void nf_unregister_queue_imq_handler(void); 
     910+#endif 
     911  
     912 #endif /* _NF_QUEUE_H */ 
     913--- a/net/core/skbuff.c 
     914+++ b/net/core/skbuff.c 
     915@@ -69,6 +69,9 @@ 
     916  
     917 static struct kmem_cache *skbuff_head_cache __read_mostly; 
     918 static struct kmem_cache *skbuff_fclone_cache __read_mostly; 
     919+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     920+static struct kmem_cache *skbuff_cb_store_cache __read_mostly; 
     921+#endif 
     922  
     923 static void sock_pipe_buf_release(struct pipe_inode_info *pipe, 
     924                                  struct pipe_buffer *buf) 
     925@@ -88,6 +91,80 @@ 
     926        return 1; 
     927 } 
     928  
     929+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     930+/* Control buffer save/restore for IMQ devices */ 
     931+struct skb_cb_table { 
     932+       void                    *cb_next; 
     933+       atomic_t                refcnt; 
     934+       char                    cb[48]; 
     935+}; 
     936+ 
     937+static DEFINE_SPINLOCK(skb_cb_store_lock); 
     938+ 
     939+int skb_save_cb(struct sk_buff *skb) 
     940+{ 
     941+       struct skb_cb_table *next; 
     942+ 
     943+       next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC); 
     944+       if (!next) 
     945+               return -ENOMEM; 
     946+ 
     947+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     948+ 
     949+       memcpy(next->cb, skb->cb, sizeof(skb->cb)); 
     950+       next->cb_next = skb->cb_next; 
     951+ 
     952+       atomic_set(&next->refcnt, 1); 
     953+ 
     954+       skb->cb_next = next; 
     955+       return 0; 
     956+} 
     957+EXPORT_SYMBOL(skb_save_cb); 
     958+ 
     959+int skb_restore_cb(struct sk_buff *skb) 
     960+{ 
     961+       struct skb_cb_table *next; 
     962+ 
     963+       if (!skb->cb_next) 
     964+               return 0; 
     965+ 
     966+       next = skb->cb_next; 
     967+ 
     968+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     969+ 
     970+       memcpy(skb->cb, next->cb, sizeof(skb->cb)); 
     971+       skb->cb_next = next->cb_next; 
     972+ 
     973+       spin_lock(&skb_cb_store_lock); 
     974+ 
     975+       if (atomic_dec_and_test(&next->refcnt)) { 
     976+               kmem_cache_free(skbuff_cb_store_cache, next); 
     977+       } 
     978+ 
     979+       spin_unlock(&skb_cb_store_lock); 
     980+ 
     981+       return 0; 
     982+} 
     983+EXPORT_SYMBOL(skb_restore_cb); 
     984+ 
     985+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old) 
     986+{ 
     987+       struct skb_cb_table *next; 
     988+ 
     989+       if (!old->cb_next) { 
     990+               new->cb_next = 0; 
     991+               return; 
     992+       } 
     993+ 
     994+       spin_lock(&skb_cb_store_lock); 
     995+ 
     996+       next = old->cb_next; 
     997+       atomic_inc(&next->refcnt); 
     998+       new->cb_next = next; 
     999+ 
     1000+       spin_unlock(&skb_cb_store_lock); 
     1001+} 
     1002+#endif 
     1003  
     1004 /* Pipe buffer operations for a socket. */ 
     1005 static struct pipe_buf_operations sock_pipe_buf_ops = { 
     1006@@ -381,6 +458,15 @@ 
     1007                WARN_ON(in_irq()); 
     1008                skb->destructor(skb); 
     1009        } 
     1010+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1011+       /* This should not happen. When it does, avoid memleak by restoring 
     1012+       the chain of cb-backups. */ 
     1013+       while(skb->cb_next != NULL) { 
     1014+               printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n", 
     1015+                       skb->cb_next); 
     1016+               skb_restore_cb(skb); 
     1017+       } 
     1018+#endif 
     1019 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 
     1020        nf_conntrack_put(skb->nfct); 
     1021        nf_conntrack_put_reasm(skb->nfct_reasm); 
     1022@@ -493,6 +579,9 @@ 
     1023        new->sp                 = secpath_get(old->sp); 
     1024 #endif 
     1025        memcpy(new->cb, old->cb, sizeof(old->cb)); 
     1026+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1027+       skb_copy_stored_cb(new, old); 
     1028+#endif 
     1029        new->csum_start         = old->csum_start; 
     1030        new->csum_offset        = old->csum_offset; 
     1031        new->local_df           = old->local_df; 
     1032@@ -2397,6 +2486,13 @@ 
     1033                                                0, 
     1034                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1035                                                NULL); 
     1036+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1037+       skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache", 
     1038+                                                 sizeof(struct skb_cb_table), 
     1039+                                                 0, 
     1040+                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1041+                                                 NULL); 
     1042+#endif 
     1043 } 
     1044  
     1045 /** 
     1046--- a/net/netfilter/Kconfig 
     1047+++ b/net/netfilter/Kconfig 
     1048@@ -357,6 +357,18 @@ 
     1049  
     1050          To compile it as a module, choose M here.  If unsure, say N. 
     1051  
     1052+config NETFILTER_XT_TARGET_IMQ 
     1053+        tristate '"IMQ" target support' 
     1054+       depends on NETFILTER_XTABLES 
     1055+       depends on IP_NF_MANGLE || IP6_NF_MANGLE 
     1056+       select IMQ 
     1057+       default m if NETFILTER_ADVANCED=n 
     1058+        help 
     1059+          This option adds a `IMQ' target which is used to specify if and 
     1060+          to which imq device packets should get enqueued/dequeued. 
     1061+ 
     1062+          To compile it as a module, choose M here.  If unsure, say N. 
     1063+ 
     1064 config NETFILTER_XT_TARGET_MARK 
     1065        tristate '"MARK" target support' 
     1066        default m if NETFILTER_ADVANCED=n 
     1067--- a/net/netfilter/Makefile 
     1068+++ b/net/netfilter/Makefile 
     1069@@ -45,6 +45,7 @@ 
     1070 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 
     1071 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 
     1072 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 
     1073+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o 
     1074 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o 
     1075 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 
     1076 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 
     1077--- a/net/netfilter/nf_queue.c 
     1078+++ b/net/netfilter/nf_queue.c 
     1079@@ -20,6 +20,26 @@ 
     1080  
     1081 static DEFINE_MUTEX(queue_handler_mutex); 
     1082  
     1083+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1084+static const struct nf_queue_handler *queue_imq_handler; 
     1085+ 
     1086+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh) 
     1087+{ 
     1088+       mutex_lock(&queue_handler_mutex); 
     1089+       rcu_assign_pointer(queue_imq_handler, qh); 
     1090+       mutex_unlock(&queue_handler_mutex); 
     1091+} 
     1092+EXPORT_SYMBOL(nf_register_queue_imq_handler); 
     1093+ 
     1094+void nf_unregister_queue_imq_handler(void) 
     1095+{ 
     1096+       mutex_lock(&queue_handler_mutex); 
     1097+       rcu_assign_pointer(queue_imq_handler, NULL); 
     1098+       mutex_unlock(&queue_handler_mutex); 
     1099+} 
     1100+EXPORT_SYMBOL(nf_unregister_queue_imq_handler); 
     1101+#endif 
     1102+ 
     1103 /* return EBUSY when somebody else is registered, return EEXIST if the 
     1104  * same handler is registered, return 0 in case of success. */ 
     1105 int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 
     1106@@ -80,7 +100,7 @@ 
     1107 } 
     1108 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 
     1109  
     1110-static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1111+void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1112 { 
     1113        /* Release those devices we held, or Alexey will kill me. */ 
     1114        if (entry->indev) 
     1115@@ -100,6 +120,7 @@ 
     1116        /* Drop reference to owner of hook which queued us. */ 
     1117        module_put(entry->elem->owner); 
     1118 } 
     1119+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); 
     1120  
     1121 /* 
     1122  * Any packet that leaves via this function must come back 
     1123@@ -121,12 +142,26 @@ 
     1124 #endif 
     1125        const struct nf_afinfo *afinfo; 
     1126        const struct nf_queue_handler *qh; 
     1127+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1128+       const struct nf_queue_handler *qih = NULL; 
     1129+#endif 
     1130  
     1131        /* QUEUE == DROP if noone is waiting, to be safe. */ 
     1132        rcu_read_lock(); 
     1133  
     1134        qh = rcu_dereference(queue_handler[pf]); 
     1135+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1136+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     1137+       if (pf == PF_INET || pf == PF_INET6) 
     1138+#else 
     1139+       if (pf == PF_INET) 
     1140+#endif 
     1141+               qih = rcu_dereference(queue_imq_handler); 
     1142+ 
     1143+       if (!qh && !qih) 
     1144+#else /* !IMQ */ 
     1145        if (!qh) 
     1146+#endif 
     1147                goto err_unlock; 
     1148  
     1149        afinfo = nf_get_afinfo(pf); 
     1150@@ -145,6 +180,10 @@ 
     1151                .indev  = indev, 
     1152                .outdev = outdev, 
     1153                .okfn   = okfn, 
     1154+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1155+               .next_outfn = qh ? qh->outfn : NULL, 
     1156+               .next_queuenum = queuenum, 
     1157+#endif 
     1158        }; 
     1159  
     1160        /* If it's going away, ignore hook. */ 
     1161@@ -170,8 +209,19 @@ 
     1162        } 
     1163 #endif 
     1164        afinfo->saveroute(skb, entry); 
     1165+ 
     1166+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1167+       if (qih) { 
     1168+               status = qih->outfn(entry, queuenum); 
     1169+               goto imq_skip_queue; 
     1170+       } 
     1171+#endif 
     1172+ 
     1173        status = qh->outfn(entry, queuenum); 
     1174  
     1175+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1176+imq_skip_queue: 
     1177+#endif 
     1178        rcu_read_unlock(); 
     1179  
     1180        if (status < 0) { 
     1181--- /dev/null 
     1182+++ b/net/netfilter/xt_IMQ.c 
     1183@@ -0,0 +1,73 @@ 
    7061184+/* 
    7071185+ * This target marks packets to be enqueued to an imq device 
     
    7091187+#include <linux/module.h> 
    7101188+#include <linux/skbuff.h> 
    711 +#include <linux/netfilter_ipv4/ip_tables.h> 
    712 +#include <linux/netfilter_ipv4/ipt_IMQ.h> 
     1189+#include <linux/netfilter/x_tables.h> 
     1190+#include <linux/netfilter/xt_IMQ.h> 
    7131191+#include <linux/imq.h> 
    7141192+ 
    7151193+static unsigned int imq_target(struct sk_buff *pskb, 
    716 +                              const struct net_device *in, 
    717 +                              const struct net_device *out, 
    718 +                              unsigned int hooknum, 
    719 +                              const struct xt_target *target, 
    720 +                              const void *targinfo) 
    721 +{ 
    722 +       struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo; 
    723 + 
    724 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
     1194+                               const struct xt_target_param *par) 
     1195+{ 
     1196+       const struct xt_imq_info *mr = par->targinfo; 
     1197+ 
     1198+       pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE; 
    7251199+ 
    7261200+       return XT_CONTINUE; 
    7271201+} 
    7281202+ 
    729 +static bool imq_checkentry(const char *tablename, 
    730 +                         const void *e, 
    731 +                         const struct xt_target *target, 
    732 +                         void *targinfo, 
    733 +                         unsigned int hook_mask) 
    734 +{ 
    735 +       struct ipt_imq_info *mr; 
    736 + 
    737 +       mr = (struct ipt_imq_info *)targinfo; 
    738 + 
    739 +       if (mr->todev > IMQ_MAX_DEVS) { 
     1203+static bool imq_checkentry(const struct xt_tgchk_param *par) 
     1204+{ 
     1205+       struct xt_imq_info *mr = par->targinfo; 
     1206+ 
     1207+       if (mr->todev > IMQ_MAX_DEVS - 1) { 
    7401208+               printk(KERN_WARNING 
    7411209+                      "IMQ: invalid device specified, highest is %u\n", 
    742 +                      IMQ_MAX_DEVS); 
     1210+                      IMQ_MAX_DEVS - 1); 
    7431211+               return 0; 
    7441212+       } 
     
    7471215+} 
    7481216+ 
    749 +static struct xt_target ipt_imq_reg = { 
    750 +       .name           = "IMQ", 
    751 +       .family         = AF_INET, 
    752 +       .target         = imq_target, 
    753 +       .targetsize     = sizeof(struct ipt_imq_info), 
    754 +       .checkentry     = imq_checkentry, 
    755 +       .me             = THIS_MODULE, 
    756 +       .table          = "mangle" 
     1217+static struct xt_target xt_imq_reg[] __read_mostly = { 
     1218+       { 
     1219+               .name           = "IMQ", 
     1220+               .family         = AF_INET, 
     1221+               .checkentry     = imq_checkentry, 
     1222+               .target         = imq_target, 
     1223+               .targetsize     = sizeof(struct xt_imq_info), 
     1224+               .table          = "mangle", 
     1225+               .me             = THIS_MODULE 
     1226+       }, 
     1227+       { 
     1228+               .name           = "IMQ", 
     1229+               .family         = AF_INET6, 
     1230+               .checkentry     = imq_checkentry, 
     1231+               .target         = imq_target, 
     1232+               .targetsize     = sizeof(struct xt_imq_info), 
     1233+               .table          = "mangle", 
     1234+               .me             = THIS_MODULE 
     1235+       }, 
    7571236+}; 
    7581237+ 
    759 +static int __init init(void) 
    760 +{ 
    761 +       return xt_register_target(&ipt_imq_reg); 
    762 +} 
    763 + 
    764 +static void __exit fini(void) 
    765 +{ 
    766 +       xt_unregister_target(&ipt_imq_reg); 
    767 +} 
    768 + 
    769 +module_init(init); 
    770 +module_exit(fini); 
     1238+static int __init imq_init(void) 
     1239+{ 
     1240+       return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1241+} 
     1242+ 
     1243+static void __exit imq_fini(void) 
     1244+{ 
     1245+       xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1246+} 
     1247+ 
     1248+module_init(imq_init); 
     1249+module_exit(imq_fini); 
    7711250+ 
    7721251+MODULE_AUTHOR("http://www.linuximq.net"); 
    7731252+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    7741253+MODULE_LICENSE("GPL"); 
    775 --- a/net/ipv4/netfilter/Kconfig 
    776 +++ b/net/ipv4/netfilter/Kconfig 
    777 @@ -112,6 +112,17 @@ config IP_NF_FILTER 
    778   
    779           To compile it as a module, choose M here.  If unsure, say N. 
    780   
    781 +config IP_NF_TARGET_IMQ 
    782 +       tristate "IMQ target support" 
    783 +       depends on IP_NF_MANGLE && IMQ 
    784 +       help 
    785 +         This option adds a `IMQ' target which is used to specify if and 
    786 +         to which IMQ device packets should get enqueued/dequeued. 
    787 + 
    788 +        For more information visit: http://www.linuximq.net/ 
    789 + 
    790 +         To compile it as a module, choose M here.  If unsure, say N. 
    791 + 
    792  config IP_NF_TARGET_REJECT 
    793         tristate "REJECT target support" 
    794         depends on IP_NF_FILTER 
    795 --- a/net/ipv4/netfilter/Makefile 
    796 +++ b/net/ipv4/netfilter/Makefile 
    797 @@ -58,6 +58,7 @@ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set 
    798  obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 
    799  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 
    800  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 
    801 +obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o 
    802  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 
    803  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 
    804  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 
    805 --- /dev/null 
    806 +++ b/net/ipv6/netfilter/ip6t_IMQ.c 
    807 @@ -0,0 +1,69 @@ 
    808 +/* 
    809 + * This target marks packets to be enqueued to an imq device 
    810 + */ 
    811 +#include <linux/module.h> 
    812 +#include <linux/skbuff.h> 
    813 +#include <linux/netfilter_ipv6/ip6_tables.h> 
    814 +#include <linux/netfilter_ipv6/ip6t_IMQ.h> 
    815 +#include <linux/imq.h> 
    816 + 
    817 +static unsigned int imq_target(struct sk_buff *pskb, 
    818 +                              const struct net_device *in, 
    819 +                              const struct net_device *out, 
    820 +                              unsigned int hooknum, 
    821 +                              const struct xt_target *target, 
    822 +                              const void *targinfo) 
    823 +{ 
    824 +       struct ip6t_imq_info *mr = (struct ip6t_imq_info *)targinfo; 
    825 + 
    826 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
    827 + 
    828 +       return XT_CONTINUE; 
    829 +} 
    830 + 
    831 +static bool imq_checkentry(const char *tablename, 
    832 +                         const void *entry, 
    833 +                         const struct xt_target *target, 
    834 +                         void *targinfo, 
    835 +                         unsigned int hook_mask) 
    836 +{ 
    837 +       struct ip6t_imq_info *mr; 
    838 + 
    839 +       mr = (struct ip6t_imq_info *)targinfo; 
    840 + 
    841 +       if (mr->todev > IMQ_MAX_DEVS) { 
    842 +               printk(KERN_WARNING 
    843 +                      "IMQ: invalid device specified, highest is %u\n", 
    844 +                      IMQ_MAX_DEVS); 
    845 +               return 0; 
    846 +       } 
    847 + 
    848 +       return 1; 
    849 +} 
    850 + 
    851 +static struct xt_target ip6t_imq_reg = { 
    852 +       .name           = "IMQ", 
    853 +       .family         = AF_INET6, 
    854 +       .target         = imq_target, 
    855 +       .targetsize     = sizeof(struct ip6t_imq_info), 
    856 +       .table          = "mangle", 
    857 +       .checkentry     = imq_checkentry, 
    858 +       .me             = THIS_MODULE 
    859 +}; 
    860 + 
    861 +static int __init init(void) 
    862 +{ 
    863 +       return xt_register_target(&ip6t_imq_reg); 
    864 +} 
    865 + 
    866 +static void __exit fini(void) 
    867 +{ 
    868 +       xt_unregister_target(&ip6t_imq_reg); 
    869 +} 
    870 + 
    871 +module_init(init); 
    872 +module_exit(fini); 
    873 + 
    874 +MODULE_AUTHOR("http://www.linuximq.net"); 
    875 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    876 +MODULE_LICENSE("GPL"); 
    877 --- a/net/ipv6/netfilter/Kconfig 
    878 +++ b/net/ipv6/netfilter/Kconfig 
    879 @@ -170,6 +170,15 @@ config IP6_NF_MANGLE 
    880   
    881           To compile it as a module, choose M here.  If unsure, say N. 
    882   
    883 +config IP6_NF_TARGET_IMQ 
    884 +       tristate "IMQ target support" 
    885 +       depends on IP6_NF_MANGLE && IMQ 
    886 +       help 
    887 +          This option adds a `IMQ' target which is used to specify if and 
    888 +          to which imq device packets should get enqueued/dequeued. 
    889 + 
    890 +          To compile it as a module, choose M here.  If unsure, say N. 
    891 + 
    892  config IP6_NF_TARGET_HL 
    893         tristate  'HL (hoplimit) target support' 
    894         depends on IP6_NF_MANGLE 
    895 --- a/net/ipv6/netfilter/Makefile 
    896 +++ b/net/ipv6/netfilter/Makefile 
    897 @@ -6,6 +6,7 @@ 
    898  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 
    899  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 
    900  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 
    901 +obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o 
    902  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 
    903  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 
    904  obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 
    905 --- a/net/sched/sch_generic.c 
    906 +++ b/net/sched/sch_generic.c 
    907 @@ -195,6 +195,7 @@ void __qdisc_run(struct Qdisc *q) 
    908   
    909         clear_bit(__QDISC_STATE_RUNNING, &q->state); 
    910  } 
    911 +EXPORT_SYMBOL(__qdisc_run); 
    912   
    913  static void dev_watchdog(unsigned long arg) 
    914  { 
     1254+MODULE_ALIAS("ipt_IMQ"); 
     1255+MODULE_ALIAS("ip6t_IMQ"); 
     1256+ 
  • trunk/target/linux/generic-2.6/patches-2.6.28/180-netfilter_depends.patch

    r14441 r15655  
    11--- a/net/netfilter/Kconfig 
    22+++ b/net/netfilter/Kconfig 
    3 @@ -160,7 +160,6 @@ config NF_CONNTRACK_FTP 
     3@@ -160,7 +160,6 @@ 
    44  
    55 config NF_CONNTRACK_H323 
     
    99        help 
    1010          H.323 is a VoIP signalling protocol from ITU-T. As one of the most 
    11 @@ -455,7 +454,6 @@ config NETFILTER_XT_TARGET_SECMARK 
     11@@ -467,7 +466,6 @@ 
    1212  
    1313 config NETFILTER_XT_TARGET_TCPMSS 
  • trunk/target/linux/generic-2.6/patches-2.6.28/190-netfilter_rtsp.patch

    r14597 r15655  
    295295--- a/net/ipv4/netfilter/Makefile 
    296296+++ b/net/ipv4/netfilter/Makefile 
    297 @@ -26,6 +26,7 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_am 
     297@@ -26,6 +26,7 @@ 
    298298 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 
    299299 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 
     
    305305--- a/net/netfilter/Kconfig 
    306306+++ b/net/netfilter/Kconfig 
    307 @@ -267,6 +267,16 @@ config NF_CONNTRACK_TFTP 
     307@@ -267,6 +267,16 @@ 
    308308  
    309309          To compile it as a module, choose M here.  If unsure, say N. 
     
    324324--- a/net/netfilter/Makefile 
    325325+++ b/net/netfilter/Makefile 
    326 @@ -33,6 +33,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co 
     326@@ -33,6 +33,7 @@ 
    327327 obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o 
    328328 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o 
     
    334334--- a/net/ipv4/netfilter/Kconfig 
    335335+++ b/net/ipv4/netfilter/Kconfig 
    336 @@ -268,6 +268,11 @@ config NF_NAT_IRC 
     336@@ -257,6 +257,11 @@ 
    337337        depends on NF_CONNTRACK && NF_NAT 
    338338        default NF_NAT && NF_CONNTRACK_IRC 
  • trunk/target/linux/generic-2.6/patches-2.6.28/205-skb_padding.patch

    r15158 r15655  
    11--- a/include/linux/skbuff.h 
    22+++ b/include/linux/skbuff.h 
    3 @@ -1256,9 +1256,12 @@ static inline int skb_network_offset(con 
     3@@ -1270,9 +1270,12 @@ 
    44  * 
    55  * Various parts of the networking layer expect at least 16 bytes of 
  • trunk/target/linux/generic-2.6/patches-2.6.29/150-netfilter_imq.patch

    r15251 r15655  
    11--- /dev/null 
    22+++ b/drivers/net/imq.c 
    3 @@ -0,0 +1,474 @@ 
     3@@ -0,0 +1,571 @@ 
    44+/* 
    55+ *             Pseudo-driver for the intermediate queue device. 
     
    5252+ * 
    5353+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
    54 + *            of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
     54+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
    5555+ *             recursive locking. New initialization routines to fix 'rmmod' not 
    5656+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna) 
     57+ * 
     58+ *             2008/08/06 - 2.6.26 - (JK) 
     59+ *              - Replaced tasklet with 'netif_schedule()'. 
     60+ *              - Cleaned up and added comments for imq_nf_queue(). 
     61+ * 
     62+ *             2009/04/12 
     63+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping 
     64+ *                control buffer. This is needed because qdisc-layer on kernels 
     65+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna) 
     66+ *              - Add better locking for IMQ device. Hopefully this will solve 
     67+ *                SMP issues. (Jussi Kivilinna) 
     68+ *              - Port to 2.6.27 
     69+ *              - Port to 2.6.28 
     70+ *              - Port to 2.6.29 + fix rmmod not working 
     71+ * 
     72+ *             2009/04/20 - (Jussi Kivilinna) 
     73+ *              - Use netdevice feature flags to avoid extra packet handling 
     74+ *                by core networking layer and possibly increase performance. 
    5775+ * 
    5876+ *            Also, many thanks to pablo Sebastian Greco for making the initial 
     
    6583+#include <linux/kernel.h> 
    6684+#include <linux/moduleparam.h> 
     85+#include <linux/list.h> 
    6786+#include <linux/skbuff.h> 
    6887+#include <linux/netdevice.h> 
     88+#include <linux/etherdevice.h> 
    6989+#include <linux/rtnetlink.h> 
    7090+#include <linux/if_arp.h> 
     
    7797+#include <net/pkt_sched.h> 
    7898+#include <net/netfilter/nf_queue.h> 
    79 + 
    80 +struct imq_private { 
    81 +       struct tasklet_struct tasklet; 
    82 +       unsigned long tasklet_pending; 
    83 +}; 
    8499+ 
    85100+static nf_hookfn imq_nf_hook; 
     
    141156+#endif 
    142157+ 
     158+static DEFINE_SPINLOCK(imq_nf_queue_lock); 
     159+ 
    143160+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; 
     161+ 
    144162+ 
    145163+static struct net_device_stats *imq_get_stats(struct net_device *dev) 
     
    154172+ 
    155173+       if (entry) { 
    156 +               if (entry->indev) 
    157 +                       dev_put(entry->indev); 
    158 +               if (entry->outdev) 
    159 +                       dev_put(entry->outdev); 
     174+               nf_queue_entry_release_refs(entry); 
    160175+               kfree(entry); 
    161176+       } 
     177+ 
     178+       skb_restore_cb(skb); /* kfree backup */ 
     179+} 
     180+ 
     181+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 
     182+{ 
     183+       int status; 
     184+ 
     185+       if (!entry->next_outfn) { 
     186+               spin_lock_bh(&imq_nf_queue_lock); 
     187+               nf_reinject(entry, verdict); 
     188+               spin_unlock_bh(&imq_nf_queue_lock); 
     189+               return; 
     190+       } 
     191+ 
     192+       rcu_read_lock(); 
     193+       local_bh_disable(); 
     194+       status = entry->next_outfn(entry, entry->next_queuenum); 
     195+       local_bh_enable(); 
     196+       if (status < 0) { 
     197+               nf_queue_entry_release_refs(entry); 
     198+               kfree_skb(entry->skb); 
     199+               kfree(entry); 
     200+       } 
     201+ 
     202+       rcu_read_unlock(); 
    162203+} 
    163204+ 
     
    170211+       skb->destructor = NULL; 
    171212+ 
     213+       skb_restore_cb(skb); /* restore skb->cb */ 
     214+ 
    172215+       dev->trans_start = jiffies; 
    173 +       nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
     216+       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
    174217+       return 0; 
    175218+} 
     
    178221+{ 
    179222+       struct net_device *dev; 
    180 +       struct imq_private *priv; 
    181 +       struct sk_buff *skb2 = NULL; 
     223+       struct sk_buff *skb_orig, *skb, *skb_shared; 
    182224+       struct Qdisc *q; 
    183 +       unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; 
    184 +       int ret = -1; 
    185 + 
    186 +       if (index > numdevs) 
    187 +               return -1; 
     225+       struct netdev_queue *txq; 
     226+       int users, index; 
     227+       int retval = -EINVAL; 
     228+ 
     229+       index = entry->skb->imq_flags & IMQ_F_IFMASK; 
     230+       if (unlikely(index > numdevs - 1)) { 
     231+               if (net_ratelimit()) 
     232+                       printk(KERN_WARNING 
     233+                              "IMQ: invalid device specified, highest is %u\n", 
     234+                              numdevs - 1); 
     235+               retval = -EINVAL; 
     236+               goto out; 
     237+       } 
    188238+ 
    189239+       /* check for imq device by index from cache */ 
    190240+       dev = imq_devs_cache[index]; 
    191 +       if (!dev) { 
     241+       if (unlikely(!dev)) { 
    192242+               char buf[8]; 
    193243+ 
     
    198248+                       /* not found ?!*/ 
    199249+                       BUG(); 
    200 +                       return -1; 
     250+                       retval = -ENODEV; 
     251+                       goto out; 
    201252+               } 
    202253+ 
    203254+               imq_devs_cache[index] = dev; 
    204 +       } 
    205 + 
    206 +       priv = netdev_priv(dev); 
    207 +       if (!(dev->flags & IFF_UP)) { 
     255+               dev_put(dev); 
     256+       } 
     257+ 
     258+       if (unlikely(!(dev->flags & IFF_UP))) { 
    208259+               entry->skb->imq_flags = 0; 
    209 +               nf_reinject(entry, NF_ACCEPT); 
    210 +               return 0; 
     260+               imq_nf_reinject(entry, NF_ACCEPT); 
     261+               retval = 0; 
     262+               goto out; 
    211263+       } 
    212264+       dev->last_rx = jiffies; 
    213265+ 
    214 +       if (entry->skb->destructor) { 
    215 +               skb2 = entry->skb; 
    216 +               entry->skb = skb_clone(entry->skb, GFP_ATOMIC); 
    217 +               if (!entry->skb) 
    218 +                       return -1; 
    219 +       } 
    220 +       entry->skb->nf_queue_entry = entry; 
    221 + 
    222 +       dev->stats.rx_bytes += entry->skb->len; 
     266+       skb = entry->skb; 
     267+       skb_orig = NULL; 
     268+ 
     269+       /* skb has owner? => make clone */ 
     270+       if (unlikely(skb->destructor)) { 
     271+               skb_orig = skb; 
     272+               skb = skb_clone(skb, GFP_ATOMIC); 
     273+               if (!skb) { 
     274+                       retval = -ENOMEM; 
     275+                       goto out; 
     276+               } 
     277+               entry->skb = skb; 
     278+       } 
     279+ 
     280+       skb->nf_queue_entry = entry; 
     281+ 
     282+       dev->stats.rx_bytes += skb->len; 
    223283+       dev->stats.rx_packets++; 
    224284+ 
    225 +       spin_lock_bh(&dev->queue_lock); 
    226 +       q = dev->qdisc; 
    227 +       if (q->enqueue) { 
    228 +               q->enqueue(skb_get(entry->skb), q); 
    229 +               if (skb_shared(entry->skb)) { 
    230 +                       entry->skb->destructor = imq_skb_destructor; 
    231 +                       kfree_skb(entry->skb); 
    232 +                       ret = 0; 
    233 +               } 
    234 +       } 
    235 +       if (!test_and_set_bit(1, &priv->tasklet_pending)) 
    236 +               tasklet_schedule(&priv->tasklet); 
    237 +       spin_unlock_bh(&dev->queue_lock); 
    238 + 
    239 +       if (skb2) 
    240 +               kfree_skb(ret ? entry->skb : skb2); 
    241 + 
    242 +       return ret; 
     285+       txq = dev_pick_tx(dev, skb); 
     286+ 
     287+       q = rcu_dereference(txq->qdisc); 
     288+       if (unlikely(!q->enqueue)) 
     289+               goto packet_not_eaten_by_imq_dev; 
     290+ 
     291+       spin_lock_bh(qdisc_lock(q)); 
     292+ 
     293+       users = atomic_read(&skb->users); 
     294+ 
     295+       skb_shared = skb_get(skb); /* increase reference count by one */ 
     296+       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will 
     297+                                       overwrite it */ 
     298+       qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ 
     299+ 
     300+       if (likely(atomic_read(&skb_shared->users) == users + 1)) { 
     301+               kfree_skb(skb_shared); /* decrease reference count by one */ 
     302+ 
     303+               skb->destructor = &imq_skb_destructor; 
     304+ 
     305+               /* cloned? */ 
     306+               if (skb_orig) 
     307+                       kfree_skb(skb_orig); /* free original */ 
     308+ 
     309+               spin_unlock_bh(qdisc_lock(q)); 
     310+ 
     311+               /* schedule qdisc dequeue */ 
     312+               __netif_schedule(q); 
     313+ 
     314+               retval = 0; 
     315+               goto out; 
     316+       } else { 
     317+               skb_restore_cb(skb_shared); /* restore skb->cb */ 
     318+               /* qdisc dropped packet and decreased skb reference count of 
     319+                * skb, so we don't really want to and try refree as that would 
     320+                * actually destroy the skb. */ 
     321+               spin_unlock_bh(qdisc_lock(q)); 
     322+               goto packet_not_eaten_by_imq_dev; 
     323+       } 
     324+ 
     325+packet_not_eaten_by_imq_dev: 
     326+       /* cloned? restore original */ 
     327+       if (skb_orig) { 
     328+               kfree_skb(skb); 
     329+               entry->skb = skb_orig; 
     330+       } 
     331+       retval = -1; 
     332+out: 
     333+       return retval; 
    243334+} 
    244335+ 
     
    248339+}; 
    249340+ 
    250 +static void qdisc_run_tasklet(unsigned long arg) 
    251 +{ 
    252 +       struct net_device *dev = (struct net_device *)arg; 
    253 +       struct imq_private *priv = netdev_priv(dev); 
    254 + 
    255 +       spin_lock(&dev->queue_lock); 
    256 +       qdisc_run(dev); 
    257 +       clear_bit(1, &priv->tasklet_pending); 
    258 +       spin_unlock(&dev->queue_lock); 
    259 +} 
    260 + 
    261341+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, 
    262342+                               const struct net_device *indev, 
     
    272352+static int imq_close(struct net_device *dev) 
    273353+{ 
    274 +       struct imq_private *priv = netdev_priv(dev); 
    275 + 
    276 +       tasklet_kill(&priv->tasklet); 
    277354+       netif_stop_queue(dev); 
    278 + 
    279355+       return 0; 
    280356+} 
     
    282358+static int imq_open(struct net_device *dev) 
    283359+{ 
    284 +       struct imq_private *priv = netdev_priv(dev); 
    285 + 
    286 +       tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev); 
    287360+       netif_start_queue(dev); 
    288 + 
    289361+       return 0; 
    290362+} 
    291363+ 
     364+static const struct net_device_ops imq_netdev_ops = { 
     365+       .ndo_open               = imq_open, 
     366+       .ndo_stop               = imq_close, 
     367+       .ndo_start_xmit         = imq_dev_xmit, 
     368+       .ndo_get_stats          = imq_get_stats, 
     369+}; 
     370+ 
    292371+static void imq_setup(struct net_device *dev) 
    293372+{ 
    294 +       dev->hard_start_xmit    = imq_dev_xmit; 
    295 +       dev->open               = imq_open; 
    296 +       dev->get_stats          = imq_get_stats; 
    297 +       dev->stop               = imq_close; 
     373+       dev->netdev_ops         = &imq_netdev_ops; 
    298374+       dev->type               = ARPHRD_VOID; 
    299375+       dev->mtu                = 16000; 
    300376+       dev->tx_queue_len       = 11000; 
    301377+       dev->flags              = IFF_NOARP; 
     378+       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST | 
     379+                                 NETIF_F_GSO | NETIF_F_HW_CSUM | 
     380+                                 NETIF_F_HIGHDMA; 
     381+} 
     382+ 
     383+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) 
     384+{ 
     385+       int ret = 0; 
     386+ 
     387+       if (tb[IFLA_ADDRESS]) { 
     388+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 
     389+                       ret = -EINVAL; 
     390+                       goto end; 
     391+               } 
     392+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { 
     393+                       ret = -EADDRNOTAVAIL; 
     394+                       goto end; 
     395+               } 
     396+       } 
     397+       return 0; 
     398+end: 
     399+       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); 
     400+       return ret; 
    302401+} 
    303402+ 
    304403+static struct rtnl_link_ops imq_link_ops __read_mostly = { 
    305404+       .kind           = "imq", 
    306 +       .priv_size      = sizeof(struct imq_private), 
     405+       .priv_size      = 0, 
    307406+       .setup          = imq_setup, 
     407+       .validate       = imq_validate, 
    308408+}; 
    309409+ 
     
    312412+       int err; 
    313413+ 
    314 +       err = nf_register_queue_handler(PF_INET, &nfqh); 
     414+       nf_register_queue_imq_handler(&nfqh); 
     415+ 
     416+       err = nf_register_hook(&imq_ingress_ipv4); 
    315417+       if (err) 
    316418+               goto err1; 
    317419+ 
    318 +       err = nf_register_hook(&imq_ingress_ipv4); 
     420+       err = nf_register_hook(&imq_egress_ipv4); 
    319421+       if (err) 
    320422+               goto err2; 
    321423+ 
    322 +       err = nf_register_hook(&imq_egress_ipv4); 
     424+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     425+       err = nf_register_hook(&imq_ingress_ipv6); 
    323426+       if (err) 
    324427+               goto err3; 
    325428+ 
    326 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    327 +       err = nf_register_queue_handler(PF_INET6, &nfqh); 
     429+       err = nf_register_hook(&imq_egress_ipv6); 
    328430+       if (err) 
    329431+               goto err4; 
    330 + 
    331 +       err = nf_register_hook(&imq_ingress_ipv6); 
    332 +       if (err) 
    333 +               goto err5; 
    334 + 
    335 +       err = nf_register_hook(&imq_egress_ipv6); 
    336 +       if (err) 
    337 +               goto err6; 
    338432+#endif 
    339433+ 
     
    341435+ 
    342436+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    343 +err6: 
     437+err4: 
    344438+       nf_unregister_hook(&imq_ingress_ipv6); 
    345 +err5: 
    346 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    347 +err4: 
     439+err3: 
    348440+       nf_unregister_hook(&imq_egress_ipv4); 
    349441+#endif 
    350 +err3: 
     442+err2: 
    351443+       nf_unregister_hook(&imq_ingress_ipv4); 
    352 +err2: 
    353 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
    354444+err1: 
     445+       nf_unregister_queue_imq_handler(); 
    355446+       return err; 
    356447+} 
     
    361452+       int ret; 
    362453+ 
    363 +       dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup); 
     454+       dev = alloc_netdev(0, "imq%d", imq_setup); 
    364455+       if (!dev) 
    365456+               return -ENOMEM; 
     
    384475+       int err, i; 
    385476+ 
    386 +       if (!numdevs || numdevs > IMQ_MAX_DEVS) { 
     477+       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { 
    387478+               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", 
    388479+                      IMQ_MAX_DEVS); 
     
    408499+{ 
    409500+       int err; 
     501+ 
     502+#if defined(CONFIG_IMQ_NUM_DEVS) 
     503+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); 
     504+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); 
     505+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); 
     506+#endif 
    410507+ 
    411508+       err = imq_init_devs(); 
     
    444541+       nf_unregister_hook(&imq_ingress_ipv6); 
    445542+       nf_unregister_hook(&imq_egress_ipv6); 
    446 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    447543+#endif 
    448544+       nf_unregister_hook(&imq_ingress_ipv4); 
    449545+       nf_unregister_hook(&imq_egress_ipv4); 
    450 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
     546+ 
     547+       nf_unregister_queue_imq_handler(); 
    451548+} 
    452549+ 
     
    478575--- a/drivers/net/Kconfig 
    479576+++ b/drivers/net/Kconfig 
    480 @@ -110,6 +110,129 @@ config EQUALIZER 
     577@@ -110,6 +110,129 @@ 
    481578          To compile this driver as a module, choose M here: the module 
    482579          will be called eql.  If unsure, say N. 
     
    610707--- a/drivers/net/Makefile 
    611708+++ b/drivers/net/Makefile 
    612 @@ -150,6 +150,7 @@ obj-$(CONFIG_SLHC) += slhc.o 
     709@@ -150,6 +150,7 @@ 
    613710 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o 
    614711  
     
    620717--- /dev/null 
    621718+++ b/include/linux/imq.h 
    622 @@ -0,0 +1,9 @@ 
     719@@ -0,0 +1,13 @@ 
    623720+#ifndef _IMQ_H 
    624721+#define _IMQ_H 
    625722+ 
    626 +#define IMQ_MAX_DEVS   16 
    627 + 
    628 +#define IMQ_F_IFMASK   0x7f 
    629 +#define IMQ_F_ENQUEUE  0x80 
     723+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ 
     724+#define IMQ_F_BITS     5 
     725+ 
     726+#define IMQ_F_IFMASK   0x0f 
     727+#define IMQ_F_ENQUEUE  0x10 
     728+ 
     729+#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1) 
    630730+ 
    631731+#endif /* _IMQ_H */ 
     732+ 
    632733--- /dev/null 
    633734+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 
    634 @@ -0,0 +1,8 @@ 
     735@@ -0,0 +1,10 @@ 
    635736+#ifndef _IPT_IMQ_H 
    636737+#define _IPT_IMQ_H 
    637738+ 
    638 +struct ipt_imq_info { 
    639 +       unsigned int todev;     /* target imq device */ 
    640 +}; 
     739+/* Backwards compatibility for old userspace */ 
     740+#include <linux/netfilter/xt_IMQ.h> 
     741+ 
     742+#define ipt_imq_info xt_imq_info 
    641743+ 
    642744+#endif /* _IPT_IMQ_H */ 
     745+ 
    643746--- /dev/null 
    644747+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 
    645 @@ -0,0 +1,8 @@ 
     748@@ -0,0 +1,10 @@ 
    646749+#ifndef _IP6T_IMQ_H 
    647750+#define _IP6T_IMQ_H 
    648751+ 
    649 +struct ip6t_imq_info { 
    650 +       unsigned int todev;     /* target imq device */ 
    651 +}; 
     752+/* Backwards compatibility for old userspace */ 
     753+#include <linux/netfilter/xt_IMQ.h> 
     754+ 
     755+#define ip6t_imq_info xt_imq_info 
    652756+ 
    653757+#endif /* _IP6T_IMQ_H */ 
     758+ 
    654759--- a/include/linux/skbuff.h 
    655760+++ b/include/linux/skbuff.h 
    656 @@ -312,6 +312,10 @@ struct sk_buff { 
     761@@ -28,6 +28,9 @@ 
     762 #include <linux/rcupdate.h> 
     763 #include <linux/dmaengine.h> 
     764 #include <linux/hrtimer.h> 
     765+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     766+#include <linux/imq.h> 
     767+#endif 
     768  
     769 #define HAVE_ALLOC_SKB         /* For the drivers to know */ 
     770 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */ 
     771@@ -282,6 +285,9 @@ 
     772         * first. This is owned by whoever has the skb queued ATM. 
     773         */ 
     774        char                    cb[48]; 
     775+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     776+       void                    *cb_next; 
     777+#endif 
     778  
     779        unsigned int            len, 
     780                                data_len; 
     781@@ -312,6 +318,9 @@ 
    657782        struct nf_conntrack     *nfct; 
    658783        struct sk_buff          *nfct_reasm; 
    659784 #endif 
    660785+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
    661 +       unsigned char                   imq_flags; 
    662786+       struct nf_queue_entry   *nf_queue_entry; 
    663787+#endif 
     
    665789        struct nf_bridge_info   *nf_bridge; 
    666790 #endif 
    667 @@ -1844,6 +1848,10 @@ static inline void __nf_copy(struct sk_b 
     791@@ -332,6 +341,9 @@ 
     792        __u8                    requeue:1; 
     793 #endif 
     794        /* 0/13/14 bit hole */ 
     795+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     796+       __u8                    imq_flags:IMQ_F_BITS; 
     797+#endif 
     798  
     799 #ifdef CONFIG_NET_DMA 
     800        dma_cookie_t            dma_cookie; 
     801@@ -372,6 +384,12 @@ 
     802                          enum dma_data_direction dir); 
     803 #endif 
     804  
     805+ 
     806+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     807+extern int skb_save_cb(struct sk_buff *skb); 
     808+extern int skb_restore_cb(struct sk_buff *skb); 
     809+#endif 
     810+ 
     811 extern void kfree_skb(struct sk_buff *skb); 
     812 extern void           __kfree_skb(struct sk_buff *skb); 
     813 extern struct sk_buff *__alloc_skb(unsigned int size, 
     814@@ -1844,6 +1862,10 @@ 
    668815        dst->nfct_reasm = src->nfct_reasm; 
    669816        nf_conntrack_get_reasm(src->nfct_reasm); 
     
    688835 #include <linux/seq_file.h> 
    689836 #include <linux/stat.h> 
    690 @@ -1671,7 +1674,11 @@ int dev_hard_start_xmit(struct sk_buff * 
     837@@ -1671,7 +1674,11 @@ 
    691838  
    692839        prefetch(&dev->netdev_ops->ndo_start_xmit); 
     
    701848  
    702849                if (netif_needs_gso(dev, skb)) { 
     850@@ -1762,8 +1769,7 @@ 
     851        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); 
     852 } 
     853  
     854-static struct netdev_queue *dev_pick_tx(struct net_device *dev, 
     855-                                       struct sk_buff *skb) 
     856+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) 
     857 { 
     858        const struct net_device_ops *ops = dev->netdev_ops; 
     859        u16 queue_index = 0; 
     860@@ -1776,6 +1782,7 @@ 
     861        skb_set_queue_mapping(skb, queue_index); 
     862        return netdev_get_tx_queue(dev, queue_index); 
     863 } 
     864+EXPORT_SYMBOL(dev_pick_tx); 
     865  
     866 /** 
     867  *     dev_queue_xmit - transmit a buffer 
     868--- a/include/linux/netdevice.h 
     869+++ b/include/linux/netdevice.h 
     870@@ -1071,6 +1071,7 @@ 
     871 extern int             dev_open(struct net_device *dev); 
     872 extern int             dev_close(struct net_device *dev); 
     873 extern void            dev_disable_lro(struct net_device *dev); 
     874+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb); 
     875 extern int             dev_queue_xmit(struct sk_buff *skb); 
     876 extern int             register_netdevice(struct net_device *dev); 
     877 extern void            unregister_netdevice(struct net_device *dev); 
    703878--- /dev/null 
    704 +++ b/net/ipv4/netfilter/ipt_IMQ.c 
    705 @@ -0,0 +1,69 @@ 
     879+++ b/include/linux/netfilter/xt_IMQ.h 
     880@@ -0,0 +1,9 @@ 
     881+#ifndef _XT_IMQ_H 
     882+#define _XT_IMQ_H 
     883+ 
     884+struct xt_imq_info { 
     885+       unsigned int todev;     /* target imq device */ 
     886+}; 
     887+ 
     888+#endif /* _XT_IMQ_H */ 
     889+ 
     890--- a/include/net/netfilter/nf_queue.h 
     891+++ b/include/net/netfilter/nf_queue.h 
     892@@ -13,6 +13,12 @@ 
     893        struct net_device       *indev; 
     894        struct net_device       *outdev; 
     895        int                     (*okfn)(struct sk_buff *); 
     896+ 
     897+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     898+       int                     (*next_outfn)(struct nf_queue_entry *entry, 
     899+                                             unsigned int queuenum); 
     900+       unsigned int            next_queuenum; 
     901+#endif 
     902 }; 
     903  
     904 #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) 
     905@@ -30,5 +36,11 @@ 
     906                                       const struct nf_queue_handler *qh); 
     907 extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); 
     908 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); 
     909+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry); 
     910+ 
     911+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     912+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh); 
     913+extern void nf_unregister_queue_imq_handler(void); 
     914+#endif 
     915  
     916 #endif /* _NF_QUEUE_H */ 
     917--- a/net/core/skbuff.c 
     918+++ b/net/core/skbuff.c 
     919@@ -69,6 +69,9 @@ 
     920  
     921 static struct kmem_cache *skbuff_head_cache __read_mostly; 
     922 static struct kmem_cache *skbuff_fclone_cache __read_mostly; 
     923+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     924+static struct kmem_cache *skbuff_cb_store_cache __read_mostly; 
     925+#endif 
     926  
     927 static void sock_pipe_buf_release(struct pipe_inode_info *pipe, 
     928                                  struct pipe_buffer *buf) 
     929@@ -88,6 +91,80 @@ 
     930        return 1; 
     931 } 
     932  
     933+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     934+/* Control buffer save/restore for IMQ devices */ 
     935+struct skb_cb_table { 
     936+       void                    *cb_next; 
     937+       atomic_t                refcnt; 
     938+       char                    cb[48]; 
     939+}; 
     940+ 
     941+static DEFINE_SPINLOCK(skb_cb_store_lock); 
     942+ 
     943+int skb_save_cb(struct sk_buff *skb) 
     944+{ 
     945+       struct skb_cb_table *next; 
     946+ 
     947+       next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC); 
     948+       if (!next) 
     949+               return -ENOMEM; 
     950+ 
     951+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     952+ 
     953+       memcpy(next->cb, skb->cb, sizeof(skb->cb)); 
     954+       next->cb_next = skb->cb_next; 
     955+ 
     956+       atomic_set(&next->refcnt, 1); 
     957+ 
     958+       skb->cb_next = next; 
     959+       return 0; 
     960+} 
     961+EXPORT_SYMBOL(skb_save_cb); 
     962+ 
     963+int skb_restore_cb(struct sk_buff *skb) 
     964+{ 
     965+       struct skb_cb_table *next; 
     966+ 
     967+       if (!skb->cb_next) 
     968+               return 0; 
     969+ 
     970+       next = skb->cb_next; 
     971+ 
     972+       BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); 
     973+ 
     974+       memcpy(skb->cb, next->cb, sizeof(skb->cb)); 
     975+       skb->cb_next = next->cb_next; 
     976+ 
     977+       spin_lock(&skb_cb_store_lock); 
     978+ 
     979+       if (atomic_dec_and_test(&next->refcnt)) { 
     980+               kmem_cache_free(skbuff_cb_store_cache, next); 
     981+       } 
     982+ 
     983+       spin_unlock(&skb_cb_store_lock); 
     984+ 
     985+       return 0; 
     986+} 
     987+EXPORT_SYMBOL(skb_restore_cb); 
     988+ 
     989+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old) 
     990+{ 
     991+       struct skb_cb_table *next; 
     992+ 
     993+       if (!old->cb_next) { 
     994+               new->cb_next = 0; 
     995+               return; 
     996+       } 
     997+ 
     998+       spin_lock(&skb_cb_store_lock); 
     999+ 
     1000+       next = old->cb_next; 
     1001+       atomic_inc(&next->refcnt); 
     1002+       new->cb_next = next; 
     1003+ 
     1004+       spin_unlock(&skb_cb_store_lock); 
     1005+} 
     1006+#endif 
     1007  
     1008 /* Pipe buffer operations for a socket. */ 
     1009 static struct pipe_buf_operations sock_pipe_buf_ops = { 
     1010@@ -381,6 +458,15 @@ 
     1011                WARN_ON(in_irq()); 
     1012                skb->destructor(skb); 
     1013        } 
     1014+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1015+       /* This should not happen. When it does, avoid memleak by restoring 
     1016+       the chain of cb-backups. */ 
     1017+       while(skb->cb_next != NULL) { 
     1018+               printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n", 
     1019+                       skb->cb_next); 
     1020+               skb_restore_cb(skb); 
     1021+       } 
     1022+#endif 
     1023 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 
     1024        nf_conntrack_put(skb->nfct); 
     1025        nf_conntrack_put_reasm(skb->nfct_reasm); 
     1026@@ -493,6 +579,9 @@ 
     1027        new->sp                 = secpath_get(old->sp); 
     1028 #endif 
     1029        memcpy(new->cb, old->cb, sizeof(old->cb)); 
     1030+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1031+       skb_copy_stored_cb(new, old); 
     1032+#endif 
     1033        new->csum_start         = old->csum_start; 
     1034        new->csum_offset        = old->csum_offset; 
     1035        new->local_df           = old->local_df; 
     1036@@ -2664,6 +2753,13 @@ 
     1037                                                0, 
     1038                                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1039                                                NULL); 
     1040+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1041+       skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache", 
     1042+                                                 sizeof(struct skb_cb_table), 
     1043+                                                 0, 
     1044+                                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, 
     1045+                                                 NULL); 
     1046+#endif 
     1047 } 
     1048  
     1049 /** 
     1050--- a/net/netfilter/Kconfig 
     1051+++ b/net/netfilter/Kconfig 
     1052@@ -357,6 +357,18 @@ 
     1053  
     1054          To compile it as a module, choose M here.  If unsure, say N. 
     1055  
     1056+config NETFILTER_XT_TARGET_IMQ 
     1057+        tristate '"IMQ" target support' 
     1058+       depends on NETFILTER_XTABLES 
     1059+       depends on IP_NF_MANGLE || IP6_NF_MANGLE 
     1060+       select IMQ 
     1061+       default m if NETFILTER_ADVANCED=n 
     1062+        help 
     1063+          This option adds a `IMQ' target which is used to specify if and 
     1064+          to which imq device packets should get enqueued/dequeued. 
     1065+ 
     1066+          To compile it as a module, choose M here.  If unsure, say N. 
     1067+ 
     1068 config NETFILTER_XT_TARGET_MARK 
     1069        tristate '"MARK" target support' 
     1070        default m if NETFILTER_ADVANCED=n 
     1071--- a/net/netfilter/Makefile 
     1072+++ b/net/netfilter/Makefile 
     1073@@ -45,6 +45,7 @@ 
     1074 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 
     1075 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 
     1076 obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 
     1077+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o 
     1078 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o 
     1079 obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o 
     1080 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o 
     1081--- a/net/netfilter/nf_queue.c 
     1082+++ b/net/netfilter/nf_queue.c 
     1083@@ -20,6 +20,26 @@ 
     1084  
     1085 static DEFINE_MUTEX(queue_handler_mutex); 
     1086  
     1087+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1088+static const struct nf_queue_handler *queue_imq_handler; 
     1089+ 
     1090+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh) 
     1091+{ 
     1092+       mutex_lock(&queue_handler_mutex); 
     1093+       rcu_assign_pointer(queue_imq_handler, qh); 
     1094+       mutex_unlock(&queue_handler_mutex); 
     1095+} 
     1096+EXPORT_SYMBOL(nf_register_queue_imq_handler); 
     1097+ 
     1098+void nf_unregister_queue_imq_handler(void) 
     1099+{ 
     1100+       mutex_lock(&queue_handler_mutex); 
     1101+       rcu_assign_pointer(queue_imq_handler, NULL); 
     1102+       mutex_unlock(&queue_handler_mutex); 
     1103+} 
     1104+EXPORT_SYMBOL(nf_unregister_queue_imq_handler); 
     1105+#endif 
     1106+ 
     1107 /* return EBUSY when somebody else is registered, return EEXIST if the 
     1108  * same handler is registered, return 0 in case of success. */ 
     1109 int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) 
     1110@@ -80,7 +100,7 @@ 
     1111 } 
     1112 EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); 
     1113  
     1114-static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1115+void nf_queue_entry_release_refs(struct nf_queue_entry *entry) 
     1116 { 
     1117        /* Release those devices we held, or Alexey will kill me. */ 
     1118        if (entry->indev) 
     1119@@ -100,6 +120,7 @@ 
     1120        /* Drop reference to owner of hook which queued us. */ 
     1121        module_put(entry->elem->owner); 
     1122 } 
     1123+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); 
     1124  
     1125 /* 
     1126  * Any packet that leaves via this function must come back 
     1127@@ -121,12 +142,26 @@ 
     1128 #endif 
     1129        const struct nf_afinfo *afinfo; 
     1130        const struct nf_queue_handler *qh; 
     1131+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1132+       const struct nf_queue_handler *qih = NULL; 
     1133+#endif 
     1134  
     1135        /* QUEUE == DROP if noone is waiting, to be safe. */ 
     1136        rcu_read_lock(); 
     1137  
     1138        qh = rcu_dereference(queue_handler[pf]); 
     1139+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1140+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     1141+       if (pf == PF_INET || pf == PF_INET6) 
     1142+#else 
     1143+       if (pf == PF_INET) 
     1144+#endif 
     1145+               qih = rcu_dereference(queue_imq_handler); 
     1146+ 
     1147+       if (!qh && !qih) 
     1148+#else /* !IMQ */ 
     1149        if (!qh) 
     1150+#endif 
     1151                goto err_unlock; 
     1152  
     1153        afinfo = nf_get_afinfo(pf); 
     1154@@ -145,6 +180,10 @@ 
     1155                .indev  = indev, 
     1156                .outdev = outdev, 
     1157                .okfn   = okfn, 
     1158+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1159+               .next_outfn = qh ? qh->outfn : NULL, 
     1160+               .next_queuenum = queuenum, 
     1161+#endif 
     1162        }; 
     1163  
     1164        /* If it's going away, ignore hook. */ 
     1165@@ -170,8 +209,19 @@ 
     1166        } 
     1167 #endif 
     1168        afinfo->saveroute(skb, entry); 
     1169+ 
     1170+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1171+       if (qih) { 
     1172+               status = qih->outfn(entry, queuenum); 
     1173+               goto imq_skip_queue; 
     1174+       } 
     1175+#endif 
     1176+ 
     1177        status = qh->outfn(entry, queuenum); 
     1178  
     1179+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     1180+imq_skip_queue: 
     1181+#endif 
     1182        rcu_read_unlock(); 
     1183  
     1184        if (status < 0) { 
     1185--- /dev/null 
     1186+++ b/net/netfilter/xt_IMQ.c 
     1187@@ -0,0 +1,73 @@ 
    7061188+/* 
    7071189+ * This target marks packets to be enqueued to an imq device 
     
    7091191+#include <linux/module.h> 
    7101192+#include <linux/skbuff.h> 
    711 +#include <linux/netfilter_ipv4/ip_tables.h> 
    712 +#include <linux/netfilter_ipv4/ipt_IMQ.h> 
     1193+#include <linux/netfilter/x_tables.h> 
     1194+#include <linux/netfilter/xt_IMQ.h> 
    7131195+#include <linux/imq.h> 
    7141196+ 
    7151197+static unsigned int imq_target(struct sk_buff *pskb, 
    716 +                              const struct net_device *in, 
    717 +                              const struct net_device *out, 
    718 +                              unsigned int hooknum, 
    719 +                              const struct xt_target *target, 
    720 +                              const void *targinfo) 
    721 +{ 
    722 +       struct ipt_imq_info *mr = (struct ipt_imq_info *)targinfo; 
    723 + 
    724 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
     1198+                               const struct xt_target_param *par) 
     1199+{ 
     1200+       const struct xt_imq_info *mr = par->targinfo; 
     1201+ 
     1202+       pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE; 
    7251203+ 
    7261204+       return XT_CONTINUE; 
    7271205+} 
    7281206+ 
    729 +static bool imq_checkentry(const char *tablename, 
    730 +                         const void *e, 
    731 +                         const struct xt_target *target, 
    732 +                         void *targinfo, 
    733 +                         unsigned int hook_mask) 
    734 +{ 
    735 +       struct ipt_imq_info *mr; 
    736 + 
    737 +       mr = (struct ipt_imq_info *)targinfo; 
    738 + 
    739 +       if (mr->todev > IMQ_MAX_DEVS) { 
     1207+static bool imq_checkentry(const struct xt_tgchk_param *par) 
     1208+{ 
     1209+       struct xt_imq_info *mr = par->targinfo; 
     1210+ 
     1211+       if (mr->todev > IMQ_MAX_DEVS - 1) { 
    7401212+               printk(KERN_WARNING 
    7411213+                      "IMQ: invalid device specified, highest is %u\n", 
    742 +                      IMQ_MAX_DEVS); 
     1214+                      IMQ_MAX_DEVS - 1); 
    7431215+               return 0; 
    7441216+       } 
     
    7471219+} 
    7481220+ 
    749 +static struct xt_target ipt_imq_reg = { 
    750 +       .name           = "IMQ", 
    751 +       .family         = AF_INET, 
    752 +       .target         = imq_target, 
    753 +       .targetsize     = sizeof(struct ipt_imq_info), 
    754 +       .checkentry     = imq_checkentry, 
    755 +       .me             = THIS_MODULE, 
    756 +       .table          = "mangle" 
     1221+static struct xt_target xt_imq_reg[] __read_mostly = { 
     1222+       { 
     1223+               .name           = "IMQ", 
     1224+               .family         = AF_INET, 
     1225+               .checkentry     = imq_checkentry, 
     1226+               .target         = imq_target, 
     1227+               .targetsize     = sizeof(struct xt_imq_info), 
     1228+               .table          = "mangle", 
     1229+               .me             = THIS_MODULE 
     1230+       }, 
     1231+       { 
     1232+               .name           = "IMQ", 
     1233+               .family         = AF_INET6, 
     1234+               .checkentry     = imq_checkentry, 
     1235+               .target         = imq_target, 
     1236+               .targetsize     = sizeof(struct xt_imq_info), 
     1237+               .table          = "mangle", 
     1238+               .me             = THIS_MODULE 
     1239+       }, 
    7571240+}; 
    7581241+ 
    759 +static int __init init(void) 
    760 +{ 
    761 +       return xt_register_target(&ipt_imq_reg); 
    762 +} 
    763 + 
    764 +static void __exit fini(void) 
    765 +{ 
    766 +       xt_unregister_target(&ipt_imq_reg); 
    767 +} 
    768 + 
    769 +module_init(init); 
    770 +module_exit(fini); 
     1242+static int __init imq_init(void) 
     1243+{ 
     1244+       return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1245+} 
     1246+ 
     1247+static void __exit imq_fini(void) 
     1248+{ 
     1249+       xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); 
     1250+} 
     1251+ 
     1252+module_init(imq_init); 
     1253+module_exit(imq_fini); 
    7711254+ 
    7721255+MODULE_AUTHOR("http://www.linuximq.net"); 
    7731256+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    7741257+MODULE_LICENSE("GPL"); 
    775 --- a/net/ipv4/netfilter/Kconfig 
    776 +++ b/net/ipv4/netfilter/Kconfig 
    777 @@ -112,6 +112,17 @@ config IP_NF_FILTER 
    778   
    779           To compile it as a module, choose M here.  If unsure, say N. 
    780   
    781 +config IP_NF_TARGET_IMQ 
    782 +       tristate "IMQ target support" 
    783 +       depends on IP_NF_MANGLE && IMQ 
    784 +       help 
    785 +         This option adds a `IMQ' target which is used to specify if and 
    786 +         to which IMQ device packets should get enqueued/dequeued. 
    787 + 
    788 +        For more information visit: http://www.linuximq.net/ 
    789 + 
    790 +         To compile it as a module, choose M here.  If unsure, say N. 
    791 + 
    792  config IP_NF_TARGET_REJECT 
    793         tristate "REJECT target support" 
    794         depends on IP_NF_FILTER 
    795 --- a/net/ipv4/netfilter/Makefile 
    796 +++ b/net/ipv4/netfilter/Makefile 
    797 @@ -58,6 +58,7 @@ obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set 
    798  obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 
    799  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 
    800  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 
    801 +obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o 
    802  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 
    803  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 
    804  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 
    805 --- /dev/null 
    806 +++ b/net/ipv6/netfilter/ip6t_IMQ.c 
    807 @@ -0,0 +1,69 @@ 
    808 +/* 
    809 + * This target marks packets to be enqueued to an imq device 
    810 + */ 
    811 +#include <linux/module.h> 
    812 +#include <linux/skbuff.h> 
    813 +#include <linux/netfilter_ipv6/ip6_tables.h> 
    814 +#include <linux/netfilter_ipv6/ip6t_IMQ.h> 
    815 +#include <linux/imq.h> 
    816 + 
    817 +static unsigned int imq_target(struct sk_buff *pskb, 
    818 +                              const struct net_device *in, 
    819 +                              const struct net_device *out, 
    820 +                              unsigned int hooknum, 
    821 +                              const struct xt_target *target, 
    822 +                              const void *targinfo) 
    823 +{ 
    824 +       struct ip6t_imq_info *mr = (struct ip6t_imq_info *)targinfo; 
    825 + 
    826 +       pskb->imq_flags = mr->todev | IMQ_F_ENQUEUE; 
    827 + 
    828 +       return XT_CONTINUE; 
    829 +} 
    830 + 
    831 +static bool imq_checkentry(const char *tablename, 
    832 +                         const void *entry, 
    833 +                         const struct xt_target *target, 
    834 +                         void *targinfo, 
    835 +                         unsigned int hook_mask) 
    836 +{ 
    837 +       struct ip6t_imq_info *mr; 
    838 + 
    839 +       mr = (struct ip6t_imq_info *)targinfo; 
    840 + 
    841 +       if (mr->todev > IMQ_MAX_DEVS) { 
    842 +               printk(KERN_WARNING 
    843 +                      "IMQ: invalid device specified, highest is %u\n", 
    844 +                      IMQ_MAX_DEVS); 
    845 +               return 0; 
    846 +       } 
    847 + 
    848 +       return 1; 
    849 +} 
    850 + 
    851 +static struct xt_target ip6t_imq_reg = { 
    852 +       .name           = "IMQ", 
    853 +       .family         = AF_INET6, 
    854 +       .target         = imq_target, 
    855 +       .targetsize     = sizeof(struct ip6t_imq_info), 
    856 +       .table          = "mangle", 
    857 +       .checkentry     = imq_checkentry, 
    858 +       .me             = THIS_MODULE 
    859 +}; 
    860 + 
    861 +static int __init init(void) 
    862 +{ 
    863 +       return xt_register_target(&ip6t_imq_reg); 
    864 +} 
    865 + 
    866 +static void __exit fini(void) 
    867 +{ 
    868 +       xt_unregister_target(&ip6t_imq_reg); 
    869 +} 
    870 + 
    871 +module_init(init); 
    872 +module_exit(fini); 
    873 + 
    874 +MODULE_AUTHOR("http://www.linuximq.net"); 
    875 +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); 
    876 +MODULE_LICENSE("GPL"); 
    877 --- a/net/ipv6/netfilter/Kconfig 
    878 +++ b/net/ipv6/netfilter/Kconfig 
    879 @@ -170,6 +170,15 @@ config IP6_NF_MANGLE 
    880   
    881           To compile it as a module, choose M here.  If unsure, say N. 
    882   
    883 +config IP6_NF_TARGET_IMQ 
    884 +       tristate "IMQ target support" 
    885 +       depends on IP6_NF_MANGLE && IMQ 
    886 +       help 
    887 +          This option adds a `IMQ' target which is used to specify if and 
    888 +          to which imq device packets should get enqueued/dequeued. 
    889 + 
    890 +          To compile it as a module, choose M here.  If unsure, say N. 
    891 + 
    892  config IP6_NF_TARGET_HL 
    893         tristate  'HL (hoplimit) target support' 
    894         depends on IP6_NF_MANGLE 
    895 --- a/net/ipv6/netfilter/Makefile 
    896 +++ b/net/ipv6/netfilter/Makefile 
    897 @@ -6,6 +6,7 @@ 
    898  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 
    899  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 
    900  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 
    901 +obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o 
    902  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 
    903  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 
    904  obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o 
    905 --- a/net/sched/sch_generic.c 
    906 +++ b/net/sched/sch_generic.c 
    907 @@ -195,6 +195,7 @@ void __qdisc_run(struct Qdisc *q) 
    908   
    909         clear_bit(__QDISC_STATE_RUNNING, &q->state); 
    910  } 
    911 +EXPORT_SYMBOL(__qdisc_run); 
    912   
    913  static void dev_watchdog(unsigned long arg) 
    914  { 
     1258+MODULE_ALIAS("ipt_IMQ"); 
     1259+MODULE_ALIAS("ip6t_IMQ"); 
     1260+ 
  • trunk/target/linux/generic-2.6/patches-2.6.29/180-netfilter_depends.patch

    r15251 r15655  
    11--- a/net/netfilter/Kconfig 
    22+++ b/net/netfilter/Kconfig 
    3 @@ -160,7 +160,6 @@ config NF_CONNTRACK_FTP 
     3@@ -160,7 +160,6 @@ 
    44  
    55 config NF_CONNTRACK_H323 
     
    99        help 
    1010          H.323 is a VoIP signalling protocol from ITU-T. As one of the most 
    11 @@ -454,7 +453,6 @@ config NETFILTER_XT_TARGET_SECMARK 
     11@@ -466,7 +465,6 @@ 
    1212  
    1313 config NETFILTER_XT_TARGET_TCPMSS 
  • trunk/target/linux/generic-2.6/patches-2.6.29/190-netfilter_rtsp.patch

    r15251 r15655  
    295295--- a/net/ipv4/netfilter/Makefile 
    296296+++ b/net/ipv4/netfilter/Makefile 
    297 @@ -26,6 +26,7 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_am 
     297@@ -26,6 +26,7 @@ 
    298298 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 
    299299 obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 
     
    305305--- a/net/netfilter/Kconfig 
    306306+++ b/net/netfilter/Kconfig 
    307 @@ -267,6 +267,16 @@ config NF_CONNTRACK_TFTP 
     307@@ -267,6 +267,16 @@ 
    308308  
    309309          To compile it as a module, choose M here.  If unsure, say N. 
     
    324324--- a/net/netfilter/Makefile 
    325325+++ b/net/netfilter/Makefile 
    326 @@ -33,6 +33,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co 
     326@@ -33,6 +33,7 @@ 
    327327 obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o 
    328328 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o 
     
    334334--- a/net/ipv4/netfilter/Kconfig 
    335335+++ b/net/ipv4/netfilter/Kconfig 
    336 @@ -268,6 +268,11 @@ config NF_NAT_IRC 
     336@@ -257,6 +257,11 @@ 
    337337        depends on NF_CONNTRACK && NF_NAT 
    338338        default NF_NAT && NF_CONNTRACK_IRC 
  • trunk/target/linux/generic-2.6/patches-2.6.29/205-skb_padding.patch

    r15251 r15655  
    11--- a/include/linux/skbuff.h 
    22+++ b/include/linux/skbuff.h 
    3 @@ -1292,9 +1292,12 @@ static inline int skb_network_offset(con 
     3@@ -1306,9 +1306,12 @@ 
    44  * 
    55  * Various parts of the networking layer expect at least 16 bytes of 
  • trunk/target/linux/generic-2.6/patches-2.6.30/150-netfilter_imq.patch

    r15548 r15655  
    11--- /dev/null 
    22+++ b/drivers/net/imq.c 
    3 @@ -0,0 +1,474 @@ 
     3@@ -0,0 +1,571 @@ 
    44+/* 
    55+ *             Pseudo-driver for the intermediate queue device. 
     
    5252+ * 
    5353+ *             2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead 
    54 + *            of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
     54+ *             of qdisc_restart() and moved qdisc_run() to tasklet to avoid 
    5555+ *             recursive locking. New initialization routines to fix 'rmmod' not 
    5656+ *             working anymore. Used code from ifb.c. (Jussi Kivilinna) 
     57+ * 
     58+ *             2008/08/06 - 2.6.26 - (JK) 
     59+ *              - Replaced tasklet with 'netif_schedule()'. 
     60+ *              - Cleaned up and added comments for imq_nf_queue(). 
     61+ * 
     62+ *             2009/04/12 
     63+ *              - Add skb_save_cb/skb_restore_cb helper functions for backuping 
     64+ *                control buffer. This is needed because qdisc-layer on kernels 
     65+ *                2.6.27 and newer overwrite control buffer. (Jussi Kivilinna) 
     66+ *              - Add better locking for IMQ device. Hopefully this will solve 
     67+ *                SMP issues. (Jussi Kivilinna) 
     68+ *              - Port to 2.6.27 
     69+ *              - Port to 2.6.28 
     70+ *              - Port to 2.6.29 + fix rmmod not working 
     71+ * 
     72+ *             2009/04/20 - (Jussi Kivilinna) 
     73+ *              - Use netdevice feature flags to avoid extra packet handling 
     74+ *                by core networking layer and possibly increase performance. 
    5775+ * 
    5876+ *            Also, many thanks to pablo Sebastian Greco for making the initial 
     
    6583+#include <linux/kernel.h> 
    6684+#include <linux/moduleparam.h> 
     85+#include <linux/list.h> 
    6786+#include <linux/skbuff.h> 
    6887+#include <linux/netdevice.h> 
     88+#include <linux/etherdevice.h> 
    6989+#include <linux/rtnetlink.h> 
    7090+#include <linux/if_arp.h> 
     
    7797+#include <net/pkt_sched.h> 
    7898+#include <net/netfilter/nf_queue.h> 
    79 + 
    80 +struct imq_private { 
    81 +       struct tasklet_struct tasklet; 
    82 +       unsigned long tasklet_pending; 
    83 +}; 
    8499+ 
    85100+static nf_hookfn imq_nf_hook; 
     
    141156+#endif 
    142157+ 
     158+static DEFINE_SPINLOCK(imq_nf_queue_lock); 
     159+ 
    143160+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; 
     161+ 
    144162+ 
    145163+static struct net_device_stats *imq_get_stats(struct net_device *dev) 
     
    154172+ 
    155173+       if (entry) { 
    156 +               if (entry->indev) 
    157 +                       dev_put(entry->indev); 
    158 +               if (entry->outdev) 
    159 +                       dev_put(entry->outdev); 
     174+               nf_queue_entry_release_refs(entry); 
    160175+               kfree(entry); 
    161176+       } 
     177+ 
     178+       skb_restore_cb(skb); /* kfree backup */ 
     179+} 
     180+ 
     181+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) 
     182+{ 
     183+       int status; 
     184+ 
     185+       if (!entry->next_outfn) { 
     186+               spin_lock_bh(&imq_nf_queue_lock); 
     187+               nf_reinject(entry, verdict); 
     188+               spin_unlock_bh(&imq_nf_queue_lock); 
     189+               return; 
     190+       } 
     191+ 
     192+       rcu_read_lock(); 
     193+       local_bh_disable(); 
     194+       status = entry->next_outfn(entry, entry->next_queuenum); 
     195+       local_bh_enable(); 
     196+       if (status < 0) { 
     197+               nf_queue_entry_release_refs(entry); 
     198+               kfree_skb(entry->skb); 
     199+               kfree(entry); 
     200+       } 
     201+ 
     202+       rcu_read_unlock(); 
    162203+} 
    163204+ 
     
    170211+       skb->destructor = NULL; 
    171212+ 
     213+       skb_restore_cb(skb); /* restore skb->cb */ 
     214+ 
    172215+       dev->trans_start = jiffies; 
    173 +       nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
     216+       imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); 
    174217+       return 0; 
    175218+} 
     
    178221+{ 
    179222+       struct net_device *dev; 
    180 +       struct imq_private *priv; 
    181 +       struct sk_buff *skb2 = NULL; 
     223+       struct sk_buff *skb_orig, *skb, *skb_shared; 
    182224+       struct Qdisc *q; 
    183 +       unsigned int index = entry->skb->imq_flags & IMQ_F_IFMASK; 
    184 +       int ret = -1; 
    185 + 
    186 +       if (index > numdevs) 
    187 +               return -1; 
     225+       struct netdev_queue *txq; 
     226+       int users, index; 
     227+       int retval = -EINVAL; 
     228+ 
     229+       index = entry->skb->imq_flags & IMQ_F_IFMASK; 
     230+       if (unlikely(index > numdevs - 1)) { 
     231+               if (net_ratelimit()) 
     232+                       printk(KERN_WARNING 
     233+                              "IMQ: invalid device specified, highest is %u\n", 
     234+                              numdevs - 1); 
     235+               retval = -EINVAL; 
     236+               goto out; 
     237+       } 
    188238+ 
    189239+       /* check for imq device by index from cache */ 
    190240+       dev = imq_devs_cache[index]; 
    191 +       if (!dev) { 
     241+       if (unlikely(!dev)) { 
    192242+               char buf[8]; 
    193243+ 
     
    198248+                       /* not found ?!*/ 
    199249+                       BUG(); 
    200 +                       return -1; 
     250+                       retval = -ENODEV; 
     251+                       goto out; 
    201252+               } 
    202253+ 
    203254+               imq_devs_cache[index] = dev; 
    204 +       } 
    205 + 
    206 +       priv = netdev_priv(dev); 
    207 +       if (!(dev->flags & IFF_UP)) { 
     255+               dev_put(dev); 
     256+       } 
     257+ 
     258+       if (unlikely(!(dev->flags & IFF_UP))) { 
    208259+               entry->skb->imq_flags = 0; 
    209 +               nf_reinject(entry, NF_ACCEPT); 
    210 +               return 0; 
     260+               imq_nf_reinject(entry, NF_ACCEPT); 
     261+               retval = 0; 
     262+               goto out; 
    211263+       } 
    212264+       dev->last_rx = jiffies; 
    213265+ 
    214 +       if (entry->skb->destructor) { 
    215 +               skb2 = entry->skb; 
    216 +               entry->skb = skb_clone(entry->skb, GFP_ATOMIC); 
    217 +               if (!entry->skb) 
    218 +                       return -1; 
    219 +       } 
    220 +       entry->skb->nf_queue_entry = entry; 
    221 + 
    222 +       dev->stats.rx_bytes += entry->skb->len; 
     266+       skb = entry->skb; 
     267+       skb_orig = NULL; 
     268+ 
     269+       /* skb has owner? => make clone */ 
     270+       if (unlikely(skb->destructor)) { 
     271+               skb_orig = skb; 
     272+               skb = skb_clone(skb, GFP_ATOMIC); 
     273+               if (!skb) { 
     274+                       retval = -ENOMEM; 
     275+                       goto out; 
     276+               } 
     277+               entry->skb = skb; 
     278+       } 
     279+ 
     280+       skb->nf_queue_entry = entry; 
     281+ 
     282+       dev->stats.rx_bytes += skb->len; 
    223283+       dev->stats.rx_packets++; 
    224284+ 
    225 +       spin_lock_bh(&dev->queue_lock); 
    226 +       q = dev->qdisc; 
    227 +       if (q->enqueue) { 
    228 +               q->enqueue(skb_get(entry->skb), q); 
    229 +               if (skb_shared(entry->skb)) { 
    230 +                       entry->skb->destructor = imq_skb_destructor; 
    231 +                       kfree_skb(entry->skb); 
    232 +                       ret = 0; 
    233 +               } 
    234 +       } 
    235 +       if (!test_and_set_bit(1, &priv->tasklet_pending)) 
    236 +               tasklet_schedule(&priv->tasklet); 
    237 +       spin_unlock_bh(&dev->queue_lock); 
    238 + 
    239 +       if (skb2) 
    240 +               kfree_skb(ret ? entry->skb : skb2); 
    241 + 
    242 +       return ret; 
     285+       txq = dev_pick_tx(dev, skb); 
     286+ 
     287+       q = rcu_dereference(txq->qdisc); 
     288+       if (unlikely(!q->enqueue)) 
     289+               goto packet_not_eaten_by_imq_dev; 
     290+ 
     291+       spin_lock_bh(qdisc_lock(q)); 
     292+ 
     293+       users = atomic_read(&skb->users); 
     294+ 
     295+       skb_shared = skb_get(skb); /* increase reference count by one */ 
     296+       skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will 
     297+                                       overwrite it */ 
     298+       qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ 
     299+ 
     300+       if (likely(atomic_read(&skb_shared->users) == users + 1)) { 
     301+               kfree_skb(skb_shared); /* decrease reference count by one */ 
     302+ 
     303+               skb->destructor = &imq_skb_destructor; 
     304+ 
     305+               /* cloned? */ 
     306+               if (skb_orig) 
     307+                       kfree_skb(skb_orig); /* free original */ 
     308+ 
     309+               spin_unlock_bh(qdisc_lock(q)); 
     310+ 
     311+               /* schedule qdisc dequeue */ 
     312+               __netif_schedule(q); 
     313+ 
     314+               retval = 0; 
     315+               goto out; 
     316+       } else { 
     317+               skb_restore_cb(skb_shared); /* restore skb->cb */ 
     318+               /* qdisc dropped packet and decreased skb reference count of 
     319+                * skb, so we don't really want to and try refree as that would 
     320+                * actually destroy the skb. */ 
     321+               spin_unlock_bh(qdisc_lock(q)); 
     322+               goto packet_not_eaten_by_imq_dev; 
     323+       } 
     324+ 
     325+packet_not_eaten_by_imq_dev: 
     326+       /* cloned? restore original */ 
     327+       if (skb_orig) { 
     328+               kfree_skb(skb); 
     329+               entry->skb = skb_orig; 
     330+       } 
     331+       retval = -1; 
     332+out: 
     333+       return retval; 
    243334+} 
    244335+ 
     
    248339+}; 
    249340+ 
    250 +static void qdisc_run_tasklet(unsigned long arg) 
    251 +{ 
    252 +       struct net_device *dev = (struct net_device *)arg; 
    253 +       struct imq_private *priv = netdev_priv(dev); 
    254 + 
    255 +       spin_lock(&dev->queue_lock); 
    256 +       qdisc_run(dev); 
    257 +       clear_bit(1, &priv->tasklet_pending); 
    258 +       spin_unlock(&dev->queue_lock); 
    259 +} 
    260 + 
    261341+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, 
    262342+                               const struct net_device *indev, 
     
    272352+static int imq_close(struct net_device *dev) 
    273353+{ 
    274 +       struct imq_private *priv = netdev_priv(dev); 
    275 + 
    276 +       tasklet_kill(&priv->tasklet); 
    277354+       netif_stop_queue(dev); 
    278 + 
    279355+       return 0; 
    280356+} 
     
    282358+static int imq_open(struct net_device *dev) 
    283359+{ 
    284 +       struct imq_private *priv = netdev_priv(dev); 
    285 + 
    286 +       tasklet_init(&priv->tasklet, qdisc_run_tasklet, (unsigned long)dev); 
    287360+       netif_start_queue(dev); 
    288 + 
    289361+       return 0; 
    290362+} 
    291363+ 
     364+static const struct net_device_ops imq_netdev_ops = { 
     365+       .ndo_open               = imq_open, 
     366+       .ndo_stop               = imq_close, 
     367+       .ndo_start_xmit         = imq_dev_xmit, 
     368+       .ndo_get_stats          = imq_get_stats, 
     369+}; 
     370+ 
    292371+static void imq_setup(struct net_device *dev) 
    293372+{ 
    294 +       dev->hard_start_xmit    = imq_dev_xmit; 
    295 +       dev->open               = imq_open; 
    296 +       dev->get_stats          = imq_get_stats; 
    297 +       dev->stop               = imq_close; 
     373+       dev->netdev_ops         = &imq_netdev_ops; 
    298374+       dev->type               = ARPHRD_VOID; 
    299375+       dev->mtu                = 16000; 
    300376+       dev->tx_queue_len       = 11000; 
    301377+       dev->flags              = IFF_NOARP; 
     378+       dev->features           = NETIF_F_SG | NETIF_F_FRAGLIST | 
     379+                                 NETIF_F_GSO | NETIF_F_HW_CSUM | 
     380+                                 NETIF_F_HIGHDMA; 
     381+} 
     382+ 
     383+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) 
     384+{ 
     385+       int ret = 0; 
     386+ 
     387+       if (tb[IFLA_ADDRESS]) { 
     388+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 
     389+                       ret = -EINVAL; 
     390+                       goto end; 
     391+               } 
     392+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { 
     393+                       ret = -EADDRNOTAVAIL; 
     394+                       goto end; 
     395+               } 
     396+       } 
     397+       return 0; 
     398+end: 
     399+       printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); 
     400+       return ret; 
    302401+} 
    303402+ 
    304403+static struct rtnl_link_ops imq_link_ops __read_mostly = { 
    305404+       .kind           = "imq", 
    306 +       .priv_size      = sizeof(struct imq_private), 
     405+       .priv_size      = 0, 
    307406+       .setup          = imq_setup, 
     407+       .validate       = imq_validate, 
    308408+}; 
    309409+ 
     
    312412+       int err; 
    313413+ 
    314 +       err = nf_register_queue_handler(PF_INET, &nfqh); 
     414+       nf_register_queue_imq_handler(&nfqh); 
     415+ 
     416+       err = nf_register_hook(&imq_ingress_ipv4); 
    315417+       if (err) 
    316418+               goto err1; 
    317419+ 
    318 +       err = nf_register_hook(&imq_ingress_ipv4); 
     420+       err = nf_register_hook(&imq_egress_ipv4); 
    319421+       if (err) 
    320422+               goto err2; 
    321423+ 
    322 +       err = nf_register_hook(&imq_egress_ipv4); 
     424+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
     425+       err = nf_register_hook(&imq_ingress_ipv6); 
    323426+       if (err) 
    324427+               goto err3; 
    325428+ 
    326 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    327 +       err = nf_register_queue_handler(PF_INET6, &nfqh); 
     429+       err = nf_register_hook(&imq_egress_ipv6); 
    328430+       if (err) 
    329431+               goto err4; 
    330 + 
    331 +       err = nf_register_hook(&imq_ingress_ipv6); 
    332 +       if (err) 
    333 +               goto err5; 
    334 + 
    335 +       err = nf_register_hook(&imq_egress_ipv6); 
    336 +       if (err) 
    337 +               goto err6; 
    338432+#endif 
    339433+ 
     
    341435+ 
    342436+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 
    343 +err6: 
     437+err4: 
    344438+       nf_unregister_hook(&imq_ingress_ipv6); 
    345 +err5: 
    346 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    347 +err4: 
     439+err3: 
    348440+       nf_unregister_hook(&imq_egress_ipv4); 
    349441+#endif 
    350 +err3: 
     442+err2: 
    351443+       nf_unregister_hook(&imq_ingress_ipv4); 
    352 +err2: 
    353 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
    354444+err1: 
     445+       nf_unregister_queue_imq_handler(); 
    355446+       return err; 
    356447+} 
     
    361452+       int ret; 
    362453+ 
    363 +       dev = alloc_netdev(sizeof(struct imq_private), "imq%d", imq_setup); 
     454+       dev = alloc_netdev(0, "imq%d", imq_setup); 
    364455+       if (!dev) 
    365456+               return -ENOMEM; 
     
    384475+       int err, i; 
    385476+ 
    386 +       if (!numdevs || numdevs > IMQ_MAX_DEVS) { 
     477+       if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { 
    387478+               printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", 
    388479+                      IMQ_MAX_DEVS); 
     
    408499+{ 
    409500+       int err; 
     501+ 
     502+#if defined(CONFIG_IMQ_NUM_DEVS) 
     503+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); 
     504+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); 
     505+       BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); 
     506+#endif 
    410507+ 
    411508+       err = imq_init_devs(); 
     
    444541+       nf_unregister_hook(&imq_ingress_ipv6); 
    445542+       nf_unregister_hook(&imq_egress_ipv6); 
    446 +       nf_unregister_queue_handler(PF_INET6, &nfqh); 
    447543+#endif 
    448544+       nf_unregister_hook(&imq_ingress_ipv4); 
    449545+       nf_unregister_hook(&imq_egress_ipv4); 
    450 +       nf_unregister_queue_handler(PF_INET, &nfqh); 
     546+ 
     547+       nf_unregister_queue_imq_handler(); 
    451548+} 
    452549+ 
     
    478575--- a/drivers/net/Kconfig 
    479576+++ b/drivers/net/Kconfig 
    480 @@ -119,6 +119,129 @@ config EQUALIZER 
     577@@ -119,6 +119,129 @@ 
    481578          To compile this driver as a module, choose M here: the module 
    482579          will be called eql.  If unsure, say N. 
     
    610707--- a/drivers/net/Makefile 
    611708+++ b/drivers/net/Makefile 
    612 @@ -152,6 +152,7 @@ obj-$(CONFIG_SLHC) += slhc.o 
     709@@ -152,6 +152,7 @@ 
    613710 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o 
    614711  
     
    620717--- /dev/null 
    621718+++ b/include/linux/imq.h 
    622 @@ -0,0 +1,9 @@ 
     719@@ -0,0 +1,13 @@ 
    623720+#ifndef _IMQ_H 
    624721+#define _IMQ_H 
    625722+ 
    626 +#define IMQ_MAX_DEVS   16 
    627 + 
    628 +#define IMQ_F_IFMASK   0x7f 
    629 +#define IMQ_F_ENQUEUE  0x80 
     723+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ 
     724+#define IMQ_F_BITS     5 
     725+ 
     726+#define IMQ_F_IFMASK   0x0f 
     727+#define IMQ_F_ENQUEUE  0x10 
     728+ 
     729+#define IMQ_MAX_DEVS   (IMQ_F_IFMASK + 1) 
    630730+ 
    631731+#endif /* _IMQ_H */ 
     732+ 
    632733--- /dev/null 
    633734+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 
    634 @@ -0,0 +1,8 @@ 
     735@@ -0,0 +1,10 @@ 
    635736+#ifndef _IPT_IMQ_H 
    636737+#define _IPT_IMQ_H 
    637738+ 
    638 +struct ipt_imq_info { 
    639 +       unsigned int todev;     /* target imq device */ 
    640 +}; 
     739+/* Backwards compatibility for old userspace */ 
     740+#include <linux/netfilter/xt_IMQ.h> 
     741+ 
     742+#define ipt_imq_info xt_imq_info 
    641743+ 
    642744+#endif /* _IPT_IMQ_H */ 
     745+ 
    643746--- /dev/null 
    644747+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 
    645 @@ -0,0 +1,8 @@ 
     748@@ -0,0 +1,10 @@ 
    646749+#ifndef _IP6T_IMQ_H 
    647750+#define _IP6T_IMQ_H 
    648751+ 
    649 +struct ip6t_imq_info { 
    650 +       unsigned int todev;     /* target imq device */ 
    651 +}; 
     752+/* Backwards compatibility for old userspace */ 
     753+#include <linux/netfilter/xt_IMQ.h> 
     754+ 
     755+#define ip6t_imq_info xt_imq_info 
    652756+ 
    653757+#endif /* _IP6T_IMQ_H */ 
     758+ 
    654759--- a/include/linux/skbuff.h 
    655760+++ b/include/linux/skbuff.h 
    656 @@ -363,6 +363,10 @@ struct sk_buff { 
     761@@ -28,6 +28,9 @@ 
     762 #include <linux/rcupdate.h> 
     763 #include <linux/dmaengine.h> 
     764 #include <linux/hrtimer.h> 
     765+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     766+#include <linux/imq.h> 
     767+#endif 
     768  
     769 /* Don't change this without changing skb_csum_unnecessary! */ 
     770 #define CHECKSUM_NONE 0 
     771@@ -333,6 +336,9 @@ 
     772         * first. This is owned by whoever has the skb queued ATM. 
     773         */ 
     774        char                    cb[48]; 
     775+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) 
     776+       void                    *cb_next; 
     777+#endif 
     778  
     779        unsigned int            len, 
     780            &nbs