++ next = old->cb_next;
++ atomic_inc(&next->refcnt);
++ new->cb_next = next;
++
++ spin_unlock(&skb_cb_store_lock);
++}
++#endif
+
+ /* Pipe buffer operations for a socket. */
+ static struct pipe_buf_operations sock_pipe_buf_ops = {
+@@ -381,6 +458,15 @@
+ WARN_ON(in_irq());
+ skb->destructor(skb);
+ }
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ /* This should not happen. When it does, avoid memleak by restoring
++ the chain of cb-backups. */
++ while(skb->cb_next != NULL) {
++ printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n",
++ skb->cb_next);
++ skb_restore_cb(skb);
++ }
++#endif
+ #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+ nf_conntrack_put(skb->nfct);
+ nf_conntrack_put_reasm(skb->nfct_reasm);
+@@ -493,6 +579,9 @@
+ new->sp = secpath_get(old->sp);
+ #endif
+ memcpy(new->cb, old->cb, sizeof(old->cb));
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ skb_copy_stored_cb(new, old);
++#endif
+ new->csum_start = old->csum_start;
+ new->csum_offset = old->csum_offset;
+ new->local_df = old->local_df;
+@@ -2397,6 +2486,13 @@
+ 0,
+ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
+ NULL);
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++ skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache",
++ sizeof(struct skb_cb_table),
++ 0,
++ SLAB_HWCACHE_ALIGN|SLAB_PANIC,
++ NULL);
++#endif
+ }
+
+ /**
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -357,6 +357,18 @@
+
+ To compile it as a module, choose M here. If unsure, say N.
+
++config NETFILTER_XT_TARGET_IMQ
++ tristate '"IMQ" target support'
++ depends on NETFILTER_XTABLES
++ depends on IP_NF_MANGLE || IP6_NF_MANGLE
++ select IMQ
++ default m if NETFILTER_ADVANCED=n
++ help
++ This option adds a `IMQ' target which is used to specify if and
++ to which imq device packets should get enqueued/dequeued.
++
++ To compile it as a module, choose M here. If unsure, say N.
++
+ config NETFILTER_XT_TARGET_MARK
+ tristate '"MARK" target support'
+ default m if NETFILTER_ADVANCED=n
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -45,6 +45,7 @@
+ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
++obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
+ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
+--- a/net/netfilter/nf_queue.c
++++ b/net/netfilter/nf_queue.c
+@@ -20,6 +20,26 @@
+
+ static DEFINE_MUTEX(queue_handler_mutex);
+
++#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
++static const struct nf_queue_handler *queue_imq_handler;
++
++void nf_register_queue_imq_handler(const struct nf_queue_handler *qh)