SKB_GSO_TCPV6 = 1 << 4,
 };
 
+#if BITS_PER_LONG > 32
+#define NET_SKBUFF_DATA_USES_OFFSET 1
+#endif
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+typedef unsigned int sk_buff_data_t;
+#else
+typedef unsigned char *sk_buff_data_t;
+#endif
+
 /** 
  *     struct sk_buff - socket buffer
  *     @next: Next buffer in list
        int                     iif;
        /* 4 byte hole on 64 bit*/
 
-       unsigned char           *transport_header;
-       unsigned char           *network_header;
-       unsigned char           *mac_header;
+       sk_buff_data_t          transport_header;
+       sk_buff_data_t          network_header;
+       sk_buff_data_t          mac_header;
        struct  dst_entry       *dst;
        struct  sec_path        *sp;
 
        skb->tail += len;
 }
 
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 {
-       return skb->transport_header;
+       return skb->head + skb->transport_header;
 }
 
 static inline void skb_reset_transport_header(struct sk_buff *skb)
 {
-       skb->transport_header = skb->data;
+       skb->transport_header = skb->data - skb->head;
 }
 
 static inline void skb_set_transport_header(struct sk_buff *skb,
                                            const int offset)
 {
-       skb->transport_header = skb->data + offset;
-}
-
-static inline int skb_transport_offset(const struct sk_buff *skb)
-{
-       return skb->transport_header - skb->data;
+       skb_reset_transport_header(skb);
+       skb->transport_header += offset;
 }
 
 static inline unsigned char *skb_network_header(const struct sk_buff *skb)
 {
-       return skb->network_header;
+       return skb->head + skb->network_header;
 }
 
 static inline void skb_reset_network_header(struct sk_buff *skb)
 {
-       skb->network_header = skb->data;
+       skb->network_header = skb->data - skb->head;
 }
 
 static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
 {
-       skb->network_header = skb->data + offset;
+       skb_reset_network_header(skb);
+       skb->network_header += offset;
 }
 
-static inline int skb_network_offset(const struct sk_buff *skb)
+static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
 {
-       return skb->network_header - skb->data;
+       return skb->head + skb->mac_header;
 }
 
-static inline u32 skb_network_header_len(const struct sk_buff *skb)
+static inline int skb_mac_header_was_set(const struct sk_buff *skb)
 {
-       return skb->transport_header - skb->network_header;
+       return skb->mac_header != ~0U;
+}
+
+static inline void skb_reset_mac_header(struct sk_buff *skb)
+{
+       skb->mac_header = skb->data - skb->head;
+}
+
+static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
+{
+       skb_reset_mac_header(skb);
+       skb->mac_header += offset;
+}
+
+#else /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
+{
+       return skb->transport_header;
+}
+
+static inline void skb_reset_transport_header(struct sk_buff *skb)
+{
+       skb->transport_header = skb->data;
+}
+
+static inline void skb_set_transport_header(struct sk_buff *skb,
+                                           const int offset)
+{
+       skb->transport_header = skb->data + offset;
+}
+
+static inline unsigned char *skb_network_header(const struct sk_buff *skb)
+{
+       return skb->network_header;
+}
+
+static inline void skb_reset_network_header(struct sk_buff *skb)
+{
+       skb->network_header = skb->data;
+}
+
+static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
+{
+       skb->network_header = skb->data + offset;
 }
 
 static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
 {
        skb->mac_header = skb->data + offset;
 }
+#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+
+static inline int skb_transport_offset(const struct sk_buff *skb)
+{
+       return skb_transport_header(skb) - skb->data;
+}
+
+static inline u32 skb_network_header_len(const struct sk_buff *skb)
+{
+       return skb->transport_header - skb->network_header;
+}
+
+static inline int skb_network_offset(const struct sk_buff *skb)
+{
+       return skb_network_header(skb) - skb->data;
+}
 
 /*
  * CPUs often take a performance hit when accessing unaligned memory
 
 
 static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 {
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
        /*
         *      Shift between the two data areas in bytes
         */
        unsigned long offset = new->data - old->data;
-
+#endif
        new->sk         = NULL;
        new->dev        = old->dev;
        new->priority   = old->priority;
 #ifdef CONFIG_INET
        new->sp         = secpath_get(old->sp);
 #endif
-       new->transport_header = old->transport_header + offset;
-       new->network_header   = old->network_header + offset;
-       new->mac_header       = old->mac_header + offset;
+       new->transport_header = old->transport_header;
+       new->network_header   = old->network_header;
+       new->mac_header       = old->mac_header;
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
+       /* {transport,network,mac}_header are relative to skb->head */
+       new->transport_header += offset;
+       new->network_header   += offset;
+       new->mac_header       += offset;
+#endif
        memcpy(new->cb, old->cb, sizeof(old->cb));
        new->local_df   = old->local_df;
        new->fclone     = SKB_FCLONE_UNAVAILABLE;
        skb->end      = data + size;
        skb->data    += off;
        skb->tail    += off;
+#ifndef NET_SKBUFF_DATA_USES_OFFSET
+       /* {transport,network,mac}_header are relative to skb->head */
        skb->transport_header += off;
        skb->network_header   += off;
        skb->mac_header       += off;
+#endif
        skb->cloned   = 0;
        skb->nohdr    = 0;
        atomic_set(&skb_shinfo(skb)->dataref, 1);
 
        struct sctp_association *asoc = NULL;
        struct sctp_transport *transport;
        struct inet_sock *inet;
-       char *saveip, *savesctp;
+       sk_buff_data_t saveip, savesctp;
        int err;
 
        if (skb->len < ihlen + 8) {
        skb_reset_network_header(skb);
        skb_set_transport_header(skb, ihlen);
        sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
-       /* Put back, the original pointers. */
+       /* Put back, the original values. */
        skb->network_header = saveip;
        skb->transport_header = savesctp;
        if (!sk) {