*
  */
 
+#include <linux/netfilter.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_nat.h>
 #include <linux/module.h>
 {
        struct ebt_nat_info *info = (struct ebt_nat_info *)data;
 
-       if (skb_shared(*pskb) || skb_cloned(*pskb)) {
-               struct sk_buff *nskb;
+       if (skb_make_writable(*pskb, 0))
+               return NF_DROP;
 
-               nskb = skb_copy(*pskb, GFP_ATOMIC);
-               if (!nskb)
-                       return NF_DROP;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
        memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
        return info->target;
 }
 
  *
  */
 
+#include <linux/netfilter.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_redirect.h>
 #include <linux/module.h>
 {
        struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
 
-       if (skb_shared(*pskb) || skb_cloned(*pskb)) {
-               struct sk_buff *nskb;
+       if (skb_make_writable(*pskb, 0))
+               return NF_DROP;
 
-               nskb = skb_copy(*pskb, GFP_ATOMIC);
-               if (!nskb)
-                       return NF_DROP;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
        if (hooknr != NF_BR_BROUTING)
                memcpy(eth_hdr(*pskb)->h_dest,
                       in->br_port->br->dev->dev_addr, ETH_ALEN);
 
  *
  */
 
+#include <linux/netfilter.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_nat.h>
 #include <linux/module.h>
 {
        struct ebt_nat_info *info = (struct ebt_nat_info *) data;
 
-       if (skb_shared(*pskb) || skb_cloned(*pskb)) {
-               struct sk_buff *nskb;
+       if (skb_make_writable(*pskb, 0))
+               return NF_DROP;
 
-               nskb = skb_copy(*pskb, GFP_ATOMIC);
-               if (!nskb)
-                       return NF_DROP;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
        memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
        if (!(info->target & NAT_ARP_BIT) &&
            eth_hdr(*pskb)->h_proto == htons(ETH_P_ARP)) {
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/ip.h>
+#include <linux/skbuff.h>
 #include <net/route.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 
        /* Change in oif may mean change in hh_len. */
        hh_len = (*pskb)->dst->dev->hard_header_len;
-       if (skb_headroom(*pskb) < hh_len) {
-               struct sk_buff *nskb;
-
-               nskb = skb_realloc_headroom(*pskb, hh_len);
-               if (!nskb)
-                       return -1;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
+       if (skb_headroom(*pskb) < hh_len &&
+           pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0,
+                            GFP_ATOMIC))
+               return -1;
 
        return 0;
 }
 
        /* Change in oif may mean change in hh_len. */
        hh_len = (*pskb)->dst->dev->hard_header_len;
-       if (skb_headroom(*pskb) < hh_len) {
-               struct sk_buff *nskb;
-
-               nskb = skb_realloc_headroom(*pskb, hh_len);
-               if (!nskb)
-                       return -1;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
+       if (skb_headroom(*pskb) < hh_len &&
+           pskb_expand_head(*pskb, hh_len - skb_headroom(*pskb), 0,
+                            GFP_ATOMIC))
+               return -1;
        return 0;
 }
 EXPORT_SYMBOL(ip_xfrm_me_harder);
 
 /* module that allows mangling of the arp payload */
 #include <linux/module.h>
+#include <linux/netfilter.h>
 #include <linux/netfilter_arp/arpt_mangle.h>
 #include <net/sock.h>
 
        unsigned char *arpptr;
        int pln, hln;
 
-       if (skb_shared(*pskb) || skb_cloned(*pskb)) {
-               struct sk_buff *nskb;
-
-               nskb = skb_copy(*pskb, GFP_ATOMIC);
-               if (!nskb)
-                       return NF_DROP;
-               if ((*pskb)->sk)
-                       skb_set_owner_w(nskb, (*pskb)->sk);
-               kfree_skb(*pskb);
-               *pskb = nskb;
-       }
+       if (skb_make_writable(*pskb, (*pskb)->len))
+               return NF_DROP;
 
        arp = arp_hdr(*pskb);
        arpptr = skb_network_header(*pskb) + sizeof(*arp);
 
 ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
 {
        int diff;
+       int err;
        struct iphdr *user_iph = (struct iphdr *)v->payload;
 
        if (v->data_len < sizeof(*user_iph))
                if (v->data_len > 0xFFFF)
                        return -EINVAL;
                if (diff > skb_tailroom(e->skb)) {
-                       struct sk_buff *newskb;
-
-                       newskb = skb_copy_expand(e->skb,
-                                                skb_headroom(e->skb),
-                                                diff,
-                                                GFP_ATOMIC);
-                       if (newskb == NULL) {
-                               printk(KERN_WARNING "ip_queue: OOM "
-                                     "in mangle, dropping packet\n");
-                               return -ENOMEM;
+                       err = pskb_expand_head(e->skb, 0,
+                                              diff - skb_tailroom(e->skb),
+                                              GFP_ATOMIC);
+                       if (err) {
+                               printk(KERN_WARNING "ip_queue: error "
+                                     "in mangle, dropping packet: %d\n", -err);
+                               return err;
                        }
-                       if (e->skb->sk)
-                               skb_set_owner_w(newskb, e->skb->sk);
-                       kfree_skb(e->skb);
-                       e->skb = newskb;
                }
                skb_put(e->skb, diff);
        }
 
 /* Unusual, but possible case. */
 static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
 {
-       struct sk_buff *nskb;
-
        if ((*pskb)->len + extra > 65535)
                return 0;
 
-       nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
-       if (!nskb)
+       if (pskb_expand_head(*pskb, 0, extra - skb_tailroom(*pskb), GFP_ATOMIC))
                return 0;
 
-       /* Transfer socket to new skb. */
-       if ((*pskb)->sk)
-               skb_set_owner_w(nskb, (*pskb)->sk);
-       kfree_skb(*pskb);
-       *pskb = nskb;
        return 1;
 }
 
 
 ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
 {
        int diff;
+       int err;
        struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
 
        if (v->data_len < sizeof(*user_iph))
                if (v->data_len > 0xFFFF)
                        return -EINVAL;
                if (diff > skb_tailroom(e->skb)) {
-                       struct sk_buff *newskb;
-
-                       newskb = skb_copy_expand(e->skb,
-                                                skb_headroom(e->skb),
-                                                diff,
-                                                GFP_ATOMIC);
-                       if (newskb == NULL) {
+                       err = pskb_expand_head(e->skb, 0,
+                                              diff - skb_tailroom(e->skb),
+                                              GFP_ATOMIC);
+                       if (err) {
                                printk(KERN_WARNING "ip6_queue: OOM "
                                      "in mangle, dropping packet\n");
-                               return -ENOMEM;
+                               return err;
                        }
-                       if (e->skb->sk)
-                               skb_set_owner_w(newskb, e->skb->sk);
-                       kfree_skb(e->skb);
-                       e->skb = newskb;
                }
                skb_put(e->skb, diff);
        }
 
 nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
 {
        int diff;
+       int err;
 
        diff = data_len - e->skb->len;
        if (diff < 0) {
                if (data_len > 0xFFFF)
                        return -EINVAL;
                if (diff > skb_tailroom(e->skb)) {
-                       struct sk_buff *newskb;
-
-                       newskb = skb_copy_expand(e->skb,
-                                                skb_headroom(e->skb),
-                                                diff,
-                                                GFP_ATOMIC);
-                       if (newskb == NULL) {
+                       err = pskb_expand_head(e->skb, 0,
+                                              diff - skb_tailroom(e->skb),
+                                              GFP_ATOMIC);
+                       if (err) {
                                printk(KERN_WARNING "nf_queue: OOM "
                                      "in mangle, dropping packet\n");
-                               return -ENOMEM;
+                               return err;
                        }
-                       if (e->skb->sk)
-                               skb_set_owner_w(newskb, e->skb->sk);
-                       kfree_skb(e->skb);
-                       e->skb = newskb;
                }
                skb_put(e->skb, diff);
        }
 
         * MSS Option not found ?! add it..
         */
        if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
-               struct sk_buff *newskb;
-
-               newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
-                                        TCPOLEN_MSS, GFP_ATOMIC);
-               if (!newskb)
+               if (pskb_expand_head(*pskb, 0,
+                                    TCPOLEN_MSS - skb_tailroom(*pskb),
+                                    GFP_ATOMIC))
                        return -1;
-               kfree_skb(*pskb);
-               *pskb = newskb;
                tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff);
        }