if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
            proto == htons(ETH_P_ARP) ||
            (proto == htons(ETH_P_IP) &&
-            IN_MULTICAST(ntohl(skb->nh.iph->daddr)))) {
+            IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
                tx_type = ETH1394_GASP;
                dest_node = LOCAL_BUS | ALL_NODES;
                max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD;
 
                if (mss)
                        flags |= LargeSend | ((mss & MSSMask) << MSSShift);
                else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-                       const struct iphdr *ip = skb->nh.iph;
+                       const struct iphdr *ip = ip_hdr(skb);
                        if (ip->protocol == IPPROTO_TCP)
                                flags |= IPCS | TCPCS;
                        else if (ip->protocol == IPPROTO_UDP)
                u32 first_len, first_eor;
                dma_addr_t first_mapping;
                int frag, first_entry = entry;
-               const struct iphdr *ip = skb->nh.iph;
+               const struct iphdr *ip = ip_hdr(skb);
 
                /* We must give this initial chunk to the device last.
                 * Otherwise we could race with the device.
 
                }
 
                if (skb->protocol == ntohs(ETH_P_IP)) {
-                       skb->nh.iph->tot_len = 0;
-                       skb->nh.iph->check = 0;
-                       skb->h.th->check =
-                           ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                              skb->nh.iph->daddr, 0,
-                                              IPPROTO_TCP, 0);
+                       struct iphdr *iph = ip_hdr(skb);
+
+                       iph->tot_len = 0;
+                       iph->check = 0;
+                       skb->h.th->check = ~csum_tcpudp_magic(iph->saddr,
+                                                             iph->daddr, 0,
+                                                             IPPROTO_TCP, 0);
                        ipofst = skb_network_offset(skb);
                        if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */
                                tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT;
 
-                       tso->tsopl |= (skb->nh.iph->ihl &
+                       tso->tsopl |= (iph->ihl &
                                CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT;
                        tso->tsopl |= ((skb->h.th->doff << 2) &
                                TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT;
 
        if ((mss = skb_shinfo(skb)->gso_size) &&
                (skb->len > (bp->dev->mtu + ETH_HLEN))) {
                u32 tcp_opt_len, ip_tcp_len;
+               struct iphdr *iph;
 
                if (skb_header_cloned(skb) &&
                    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
                }
                ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
 
-               skb->nh.iph->check = 0;
-               skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-               skb->h.th->check =
-                       ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                           skb->nh.iph->daddr,
-                                           0, IPPROTO_TCP, 0);
+               iph = ip_hdr(skb);
+               iph->check = 0;
+               iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+               skb->h.th->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+                                                     0, IPPROTO_TCP, 0);
 
-               if (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
-                       vlan_tag_flags |= ((skb->nh.iph->ihl - 5) +
-                               (tcp_opt_len >> 2)) << 8;
+               if (tcp_opt_len || (iph->ihl > 5)) {
+                       vlan_tag_flags |= ((iph->ihl - 5) +
+                                          (tcp_opt_len >> 2)) << 8;
                }
        }
        else
 
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
 
-static inline u8 _simple_hash(u8 *hash_start, int hash_size)
+static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
 {
        int i;
        u8 hash = 0;
        int hash_size = 0;
        int do_tx_balance = 1;
        u32 hash_index = 0;
-       u8 *hash_start = NULL;
+       const u8 *hash_start = NULL;
        int res = 1;
 
        skb_reset_mac_header(skb);
        }
 
        switch (ntohs(skb->protocol)) {
-       case ETH_P_IP:
+       case ETH_P_IP: {
+               const struct iphdr *iph = ip_hdr(skb);
+
                if ((memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) ||
-                   (skb->nh.iph->daddr == ip_bcast) ||
-                   (skb->nh.iph->protocol == IPPROTO_IGMP)) {
+                   (iph->daddr == ip_bcast) ||
+                   (iph->protocol == IPPROTO_IGMP)) {
                        do_tx_balance = 0;
                        break;
                }
-               hash_start = (char*)&(skb->nh.iph->daddr);
-               hash_size = sizeof(skb->nh.iph->daddr);
+               hash_start = (char *)&(iph->daddr);
+               hash_size = sizeof(iph->daddr);
+       }
                break;
        case ETH_P_IPV6:
                if (memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) {
 
                                    struct net_device *bond_dev, int count)
 {
        struct ethhdr *data = (struct ethhdr *)skb->data;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        u16 *layer4hdr = (u16 *)((u32 *)iph + iph->ihl);
        int layer4_xor = 0;
 
 
                hdr = (struct cpl_tx_pkt_lso *)skb_push(skb, sizeof(*hdr));
                hdr->opcode = CPL_TX_PKT_LSO;
                hdr->ip_csum_dis = hdr->l4_csum_dis = 0;
-               hdr->ip_hdr_words = skb->nh.iph->ihl;
+               hdr->ip_hdr_words = ip_hdr(skb)->ihl;
                hdr->tcp_hdr_words = skb->h.th->doff;
                hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
                                                          skb_shinfo(skb)->gso_size));
 
                if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
                    skb->ip_summed == CHECKSUM_PARTIAL &&
-                   skb->nh.iph->protocol == IPPROTO_UDP) {
+                   ip_hdr(skb)->protocol == IPPROTO_UDP) {
                        if (unlikely(skb_checksum_help(skb))) {
                                pr_debug("%s: unable to do udp checksum\n", dev->name);
                                dev_kfree_skb_any(skb);
 
                eth_type = skb_network_offset(skb) == ETH_HLEN ?
                    CPL_ETH_II : CPL_ETH_II_VLAN;
                tso_info |= V_LSO_ETH_TYPE(eth_type) |
-                   V_LSO_IPHDR_WORDS(skb->nh.iph->ihl) |
+                   V_LSO_IPHDR_WORDS(ip_hdr(skb)->ihl) |
                    V_LSO_TCPHDR_WORDS(skb->h.th->doff);
                hdr->lso_info = htonl(tso_info);
                flits = 3;
 
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
                mss = skb_shinfo(skb)->gso_size;
                if (skb->protocol == htons(ETH_P_IP)) {
-                       skb->nh.iph->tot_len = 0;
-                       skb->nh.iph->check = 0;
-                       skb->h.th->check =
-                               ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                                  skb->nh.iph->daddr,
-                                                  0,
-                                                  IPPROTO_TCP,
-                                                  0);
+                       struct iphdr *iph = ip_hdr(skb);
+                       iph->tot_len = 0;
+                       iph->check = 0;
+                       skb->h.th->check = ~csum_tcpudp_magic(iph->saddr,
+                                                             iph->daddr, 0,
+                                                             IPPROTO_TCP, 0);
                        cmd_length = E1000_TXD_CMD_IP;
                        ipcse = skb->h.raw - skb->data - 1;
                } else if (skb->protocol == htons(ETH_P_IPV6)) {
                        ipcse = 0;
                }
                ipcss = skb_network_offset(skb);
-               ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
+               ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
                tucss = skb->h.raw - skb->data;
                tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
                tucse = 0;
 
 static inline void write_ip_start_end(struct ehea_swqe *swqe,
                                      const struct sk_buff *skb)
 {
-       swqe->ip_start = (u8)(((u64)skb->nh.iph) - ((u64)skb->data));
+       swqe->ip_start = skb_network_offset(skb);
        swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
 }
 
                       struct ehea_swqe *swqe, u32 lkey)
 {
        if (skb->protocol == htons(ETH_P_IP)) {
+               const struct iphdr *iph = ip_hdr(skb);
                /* IPv4 */
                swqe->tx_control |= EHEA_SWQE_CRC
                                 | EHEA_SWQE_IP_CHECKSUM
 
                write_ip_start_end(swqe, skb);
 
-               if (skb->nh.iph->protocol == IPPROTO_UDP) {
-                       if ((skb->nh.iph->frag_off & IP_MF) ||
-                           (skb->nh.iph->frag_off & IP_OFFSET))
+               if (iph->protocol == IPPROTO_UDP) {
+                       if ((iph->frag_off & IP_MF) ||
+                           (iph->frag_off & IP_OFFSET))
                                /* IP fragment, so don't change cs */
                                swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
                        else
                                write_udp_offset_end(swqe, skb);
 
-               } else if (skb->nh.iph->protocol == IPPROTO_TCP) {
+               } else if (iph->protocol == IPPROTO_TCP) {
                        write_tcp_offset_end(swqe, skb);
                }
 
        int i;
 
        if (skb->protocol == htons(ETH_P_IP)) {
+               const struct iphdr *iph = ip_hdr(skb);
                /* IPv4 */
                write_ip_start_end(swqe, skb);
 
-               if (skb->nh.iph->protocol == IPPROTO_TCP) {
+               if (iph->protocol == IPPROTO_TCP) {
                        swqe->tx_control |= EHEA_SWQE_CRC
                                         | EHEA_SWQE_IP_CHECKSUM
                                         | EHEA_SWQE_TCP_CHECKSUM
 
                        write_tcp_offset_end(swqe, skb);
 
-               } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
-                       if ((skb->nh.iph->frag_off & IP_MF) ||
-                           (skb->nh.iph->frag_off & IP_OFFSET))
+               } else if (iph->protocol == IPPROTO_UDP) {
+                       if ((iph->frag_off & IP_MF) ||
+                           (iph->frag_off & IP_OFFSET))
                                /* IP fragment, so don't change cs */
                                swqe->tx_control |= EHEA_SWQE_CRC
                                                 | EHEA_SWQE_IMM_DATA_PRESENT;
 
 
        /* Tell the controller what the protocol is */
        /* And provide the already calculated phcs */
-       if (skb->nh.iph->protocol == IPPROTO_UDP) {
+       if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
                flags |= TXFCB_UDP;
                fcb->phcs = skb->h.uh->check;
        } else
 
         * manually.
         */
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               int proto = ntohs(skb->nh.iph->protocol);
+               const struct iphdr *ih = ip_hdr(skb);
+               const int proto = ntohs(ih->protocol);
                unsigned int csoff;
-               struct iphdr *ih = skb->nh.iph;
                uint32_t csum, ehsum;
                uint16_t *eh;
 
 
 
        if (likely(skb_is_gso(skb))) {
                struct ixgb_buffer *buffer_info;
+               struct iphdr *iph;
+
                if (skb_header_cloned(skb)) {
                        err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
                        if (err)
 
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
                mss = skb_shinfo(skb)->gso_size;
-               skb->nh.iph->tot_len = 0;
-               skb->nh.iph->check = 0;
-               skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                                     skb->nh.iph->daddr,
+               iph = ip_hdr(skb);
+               iph->tot_len = 0;
+               iph->check = 0;
+               skb->h.th->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
                                                      0, IPPROTO_TCP, 0);
                ipcss = skb_network_offset(skb);
-               ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
+               ipcso = (void *)&(iph->check) - (void *)skb->data;
                ipcse = skb->h.raw - skb->data - 1;
                tucss = skb->h.raw - skb->data;
                tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
 
 #ifdef LOOPBACK_TSO
 static void emulate_large_send_offload(struct sk_buff *skb)
 {
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct tcphdr *th = (struct tcphdr *)(skb_network_header(skb) +
                                              (iph->ihl * 4));
        unsigned int doffset = (iph->ihl + th->doff) * 4;
                skb_reserve(nskb, 32);
                skb_set_mac_header(nskb, -ETH_HLEN);
                skb_reset_network_header(nskb);
-               iph = nskb->nh.iph;
+               iph = ip_hdr(nskb);
                memcpy(nskb->data, skb_network_header(skb), doffset);
                if (skb_copy_bits(skb,
                                  doffset + offset,
 #ifdef LOOPBACK_TSO
        if (skb_is_gso(skb)) {
                BUG_ON(skb->protocol != htons(ETH_P_IP));
-               BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
+               BUG_ON(ip_hdr(skb)->protocol != IPPROTO_TCP);
 
                emulate_large_send_offload(skb);
                return 0;
 
 
                cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
                           ETH_GEN_IP_V_4_CHECKSUM  |
-                          skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
+                          ip_hdr(skb)->ihl << ETH_TX_IHL_SHIFT;
 
-               switch (skb->nh.iph->protocol) {
+               switch (ip_hdr(skb)->protocol) {
                case IPPROTO_UDP:
                        cmd_sts |= ETH_UDP_FRAME;
                        desc->l4i_chk = skb->h.uh->check;
 
                                          skb->h.th->doff * 4);
                netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               if (skb->nh.iph->protocol == IPPROTO_TCP) {
+               if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
                        netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
-               } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+               } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
                        netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
                } else {
                        return;
 
        extsts = 0;
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                extsts |= EXTSTS_IPPKT;
-               if (IPPROTO_TCP == skb->nh.iph->protocol)
+               if (IPPROTO_TCP == ip_hdr(skb)->protocol)
                        extsts |= EXTSTS_TCPPKT;
-               else if (IPPROTO_UDP == skb->nh.iph->protocol)
+               else if (IPPROTO_UDP == ip_hdr(skb)->protocol)
                        extsts |= EXTSTS_UDPPKT;
        }
 
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                const unsigned char *nh = skb_network_header(skb);
 
-               switch (skb->nh.iph->protocol) {
+               switch (ip_hdr(skb)->protocol) {
                case IPPROTO_TCP:
                        dflags |= XCT_MACTX_CSUM_TCP;
                        dflags |= XCT_MACTX_IPH((skb->h.raw - skb->nh.raw) >> 2);
 
                        return LargeSend | ((mss & MSSMask) << MSSShift);
        }
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               const struct iphdr *ip = skb->nh.iph;
+               const struct iphdr *ip = ip_hdr(skb);
 
                if (ip->protocol == IPPROTO_TCP)
                        return IPCS | TCPCS;
 
                tcpsum |= offset + skb->csum_offset;    /* sum write */
 
                ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
-               if (skb->nh.iph->protocol == IPPROTO_UDP)
+               if (ip_hdr(skb)->protocol == IPPROTO_UDP)
                        ctrl |= UDPTCP;
 
                if (tcpsum != sky2->tx_tcpsum) {
 
        spin_unlock_irqrestore(&chain->lock, flags);
 
        if (skb->protocol == htons(ETH_P_IP) && skb->ip_summed == CHECKSUM_PARTIAL)
-               switch (skb->nh.iph->protocol) {
+               switch (ip_hdr(skb)->protocol) {
                case IPPROTO_TCP:
                        hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
                        break;
 
                if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
                        mss |= (skb_headlen(skb) - ETH_HLEN) << 9;
                else {
+                       struct iphdr *iph = ip_hdr(skb);
+
                        tcp_opt_len = ((skb->h.th->doff - 5) * 4);
                        ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
 
-                       skb->nh.iph->check = 0;
-                       skb->nh.iph->tot_len = htons(mss + ip_tcp_len +
-                                                    tcp_opt_len);
+                       iph->check = 0;
+                       iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
                        mss |= (ip_tcp_len + tcp_opt_len) << 9;
                }
 
        mss = 0;
        if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
            (mss = skb_shinfo(skb)->gso_size) != 0) {
+               struct iphdr *iph;
                int tcp_opt_len, ip_tcp_len, hdr_len;
 
                if (skb_header_cloned(skb) &&
                base_flags |= (TXD_FLAG_CPU_PRE_DMA |
                               TXD_FLAG_CPU_POST_DMA);
 
-               skb->nh.iph->check = 0;
-               skb->nh.iph->tot_len = htons(mss + hdr_len);
+               iph = ip_hdr(skb);
+               iph->check = 0;
+               iph->tot_len = htons(mss + hdr_len);
                if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
                        skb->h.th->check = 0;
                        base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
                }
                else {
-                       skb->h.th->check =
-                               ~csum_tcpudp_magic(skb->nh.iph->saddr,
-                                                  skb->nh.iph->daddr,
-                                                  0, IPPROTO_TCP, 0);
+                       skb->h.th->check = ~csum_tcpudp_magic(iph->saddr,
+                                                             iph->daddr, 0,
+                                                             IPPROTO_TCP, 0);
                }
 
                if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) ||
                    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
-                       if (tcp_opt_len || skb->nh.iph->ihl > 5) {
+                       if (tcp_opt_len || iph->ihl > 5) {
                                int tsflags;
 
-                               tsflags = ((skb->nh.iph->ihl - 5) +
-                                          (tcp_opt_len >> 2));
+                               tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
                                mss |= (tsflags << 11);
                        }
                } else {
-                       if (tcp_opt_len || skb->nh.iph->ihl > 5) {
+                       if (tcp_opt_len || iph->ihl > 5) {
                                int tsflags;
 
-                               tsflags = ((skb->nh.iph->ihl - 5) +
-                                          (tcp_opt_len >> 2));
+                               tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
                                base_flags |= tsflags << 12;
                        }
                }
 
         */
        if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM)
                                 && (skb->ip_summed == CHECKSUM_PARTIAL)) {
-               struct iphdr *ip = skb->nh.iph;
+               const struct iphdr *ip = ip_hdr(skb);
                if (ip->protocol == IPPROTO_TCP)
                        td_ptr->tdesc1.TCR |= TCR0_TCPCK;
                else if (ip->protocol == IPPROTO_UDP)
 
                        return card->info.is_multicast_different &
                                (card->qdio.no_out_queues - 1);
                if (card->qdio.do_prio_queueing && (ipv == 4)) {
+                       const u8 tos = ip_hdr(skb)->tos;
+
                        if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_TOS){
-                               if (skb->nh.iph->tos & IP_TOS_NOTIMPORTANT)
+                               if (tos & IP_TOS_NOTIMPORTANT)
                                        return 3;
-                               if (skb->nh.iph->tos & IP_TOS_HIGHRELIABILITY)
+                               if (tos & IP_TOS_HIGHRELIABILITY)
                                        return 2;
-                               if (skb->nh.iph->tos & IP_TOS_HIGHTHROUGHPUT)
+                               if (tos & IP_TOS_HIGHTHROUGHPUT)
                                        return 1;
-                               if (skb->nh.iph->tos & IP_TOS_LOWDELAY)
+                               if (tos & IP_TOS_LOWDELAY)
                                        return 0;
                        }
                        if (card->qdio.do_prio_queueing==QETH_PRIO_Q_ING_PREC)
-                               return 3 - (skb->nh.iph->tos >> 6);
+                               return 3 - (tos >> 6);
                } else if (card->qdio.do_prio_queueing && (ipv == 6)) {
                        /* TODO: IPv6!!! */
                }
                            *((u32 *) skb->dst->neighbour->primary_key);
                } else {
                        /* fill in destination address used in ip header */
-                       *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = skb->nh.iph->daddr;
+                       *((u32 *)(&hdr->hdr.l3.dest_addr[12])) =
+                                                          ip_hdr(skb)->daddr;
                }
        } else if (ipv == 6) { /* IPv6 or passthru */
                hdr->hdr.l3.flags = qeth_get_qeth_hdr_flags6(cast_type);
 
        QETH_DBF_TEXT(trace, 5, "tsofhdr");
 
        hdr  = (struct qeth_hdr_tso *) skb->data;
-       iph  = skb->nh.iph;
+       iph  = ip_hdr(skb);
        tcph = skb->h.th;
        /*fix header to TSO values ...*/
        hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
 static inline void
 qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
 {
-       struct iphdr *iph;
-       struct ipv6hdr *ip6h;
-       struct tcphdr *tcph;
-
-       iph  = skb->nh.iph;
-       ip6h = skb->nh.ipv6h;
-       tcph = skb->h.th;
+       struct iphdr *iph    = ip_hdr(skb);
+       struct ipv6hdr *ip6h = skb->nh.ipv6h;
+       struct tcphdr *tcph  = skb->h.th;
 
        tcph->check = 0;
        if (skb->protocol == ETH_P_IPV6) {
 
        /*The options start here. */
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
+{
+       return (struct iphdr *)skb_network_header(skb);
+}
+#endif
+
 struct ip_auth_hdr {
        __u8  nexthdr;
        __u8  hdrlen;           /* This one is measured in 32 bit units! */
 
        } h;
 
        union {
-               struct iphdr    *iph;
                struct ipv6hdr  *ipv6h;
                struct arphdr   *arph;
                unsigned char   *raw;
 
        case __constant_htons(ETH_P_IP):
                if (skb_network_header(skb) + sizeof(struct iphdr) <=
                    skb->tail)
-                       return IP_ECN_set_ce(skb->nh.iph);
+                       return IP_ECN_set_ce(ip_hdr(skb));
                break;
 
        case __constant_htons(ETH_P_IPV6):
 
 
 static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
 {
-       return skb->nh.iph->ihl * 4;
+       return ip_hdr(skb)->ihl * 4;
 }
 
 struct ipcm_cookie
 
        return NULL;
 }
 
-static inline int tcf_valid_offset(struct sk_buff *skb, unsigned char *ptr,
-                                  int len)
+static inline int tcf_valid_offset(const struct sk_buff *skb,
+                                  const unsigned char *ptr, const int len)
 {
        return unlikely((ptr + len) < skb->tail && ptr > skb->head);
 }
 
        new_skb->protocol = eth_type_trans(new_skb, dev);
        skb_reset_network_header(new_skb);
 
-       eg->latest_ip_addr = new_skb->nh.iph->saddr;
+       eg->latest_ip_addr = ip_hdr(new_skb)->saddr;
        eg->packets_rcvd++;
        mpc->eg_ops->put(eg);
 
 
 
 #define skb_origaddr(skb)       (((struct bridge_skb_cb *) \
                                 (skb->nf_bridge->data))->daddr.ipv4)
-#define store_orig_dstaddr(skb)         (skb_origaddr(skb) = (skb)->nh.iph->daddr)
-#define dnat_took_place(skb)    (skb_origaddr(skb) != (skb)->nh.iph->daddr)
+#define store_orig_dstaddr(skb)         (skb_origaddr(skb) = ip_hdr(skb)->daddr)
+#define dnat_took_place(skb)    (skb_origaddr(skb) != ip_hdr(skb)->daddr)
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int br_nf_pre_routing_finish(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct nf_bridge_info *nf_bridge = skb->nf_bridge;
        int err;
 
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto inhdr_error;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        if (iph->ihl < 5 || iph->version != 4)
                goto inhdr_error;
 
        if (!pskb_may_pull(skb, 4 * iph->ihl))
                goto inhdr_error;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        if (ip_fast_csum((__u8 *) iph, iph->ihl) != 0)
                goto inhdr_error;
 
 
 
        skb_push(skb, sizeof(*iph));
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        /* iph->version = 4; iph->ihl = 5; */
        put_unaligned(0x45, (unsigned char *)iph);
 
                VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
        skb->dev = odev;
        skb->pkt_type = PACKET_HOST;
-       skb->nh.iph = iph;
+       skb->nh.raw = (unsigned char *)iph;
        skb->h.uh = udph;
 
        if (pkt_dev->nfrags <= 0)
 
 
 static inline u64 dccp_v4_init_sequence(const struct sk_buff *skb)
 {
-       return secure_dccp_sequence_number(skb->nh.iph->daddr,
-                                          skb->nh.iph->saddr,
+       return secure_dccp_sequence_number(ip_hdr(skb)->daddr,
+                                          ip_hdr(skb)->saddr,
                                           dccp_hdr(skb)->dccph_dport,
                                           dccp_hdr(skb)->dccph_sport);
 }
        newinet->opt       = ireq->opt;
        ireq->opt          = NULL;
        newinet->mc_index  = inet_iif(skb);
-       newinet->mc_ttl    = skb->nh.iph->ttl;
+       newinet->mc_ttl    = ip_hdr(skb)->ttl;
        newinet->id        = jiffies;
 
        dccp_sync_mss(newsk, dst_mtu(dst));
 static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
        const struct dccp_hdr *dh = dccp_hdr(skb);
-       const struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        struct sock *nsk;
        struct request_sock **prev;
        /* Find possible connection requests. */
        struct rtable *rt;
        struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif,
                            .nl_u = { .ip4_u =
-                                     { .daddr = skb->nh.iph->saddr,
-                                       .saddr = skb->nh.iph->daddr,
+                                     { .daddr = ip_hdr(skb)->saddr,
+                                       .saddr = ip_hdr(skb)->daddr,
                                        .tos = RT_CONN_FLAGS(sk) } },
                            .proto = sk->sk_protocol,
                            .uli_u = { .ports =
 {
        int err;
        struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
+       const struct iphdr *rxiph;
        const int dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
                                       sizeof(struct dccp_hdr_ext) +
                                       sizeof(struct dccp_hdr_reset);
        dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), DCCP_SKB_CB(rxskb)->dccpd_seq);
 
        dccp_csum_outgoing(skb);
-       dh->dccph_checksum = dccp_v4_csum_finish(skb, rxskb->nh.iph->saddr,
-                                                     rxskb->nh.iph->daddr);
+       rxiph = ip_hdr(rxskb);
+       dh->dccph_checksum = dccp_v4_csum_finish(skb, rxiph->saddr,
+                                                rxiph->daddr);
 
        bh_lock_sock(dccp_v4_ctl_socket->sk);
        err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
-                                   rxskb->nh.iph->daddr,
-                                   rxskb->nh.iph->saddr, NULL);
+                                   rxiph->daddr, rxiph->saddr, NULL);
        bh_unlock_sock(dccp_v4_ctl_socket->sk);
 
        if (net_xmit_eval(err) == 0) {
                goto drop_and_free;
 
        ireq = inet_rsk(req);
-       ireq->loc_addr = skb->nh.iph->daddr;
-       ireq->rmt_addr = skb->nh.iph->saddr;
+       ireq->loc_addr = ip_hdr(skb)->daddr;
+       ireq->rmt_addr = ip_hdr(skb)->saddr;
        ireq->opt       = NULL;
 
        /*
 static int dccp_v4_rcv(struct sk_buff *skb)
 {
        const struct dccp_hdr *dh;
+       const struct iphdr *iph;
        struct sock *sk;
        int min_cov;
 
        if (dccp_invalid_packet(skb))
                goto discard_it;
 
+       iph = ip_hdr(skb);
        /* Step 1: If header checksum is incorrect, drop packet and return */
-       if (dccp_v4_csum_finish(skb, skb->nh.iph->saddr, skb->nh.iph->daddr)) {
+       if (dccp_v4_csum_finish(skb, iph->saddr, iph->daddr)) {
                DCCP_WARN("dropped packet with invalid checksum\n");
                goto discard_it;
        }
                      "src=%u.%u.%u.%u@%-5d "
                      "dst=%u.%u.%u.%u@%-5d seq=%llu",
                      dccp_packet_name(dh->dccph_type),
-                     NIPQUAD(skb->nh.iph->saddr), ntohs(dh->dccph_sport),
-                     NIPQUAD(skb->nh.iph->daddr), ntohs(dh->dccph_dport),
+                     NIPQUAD(iph->saddr), ntohs(dh->dccph_sport),
+                     NIPQUAD(iph->daddr), ntohs(dh->dccph_dport),
                      (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
 
        if (dccp_packet_without_ack(skb)) {
        /* Step 2:
         *      Look up flow ID in table and get corresponding socket */
        sk = __inet_lookup(&dccp_hashinfo,
-                          skb->nh.iph->saddr, dh->dccph_sport,
-                          skb->nh.iph->daddr, dh->dccph_dport,
-                          inet_iif(skb));
-
+                          iph->saddr, dh->dccph_sport,
+                          iph->daddr, dh->dccph_dport, inet_iif(skb));
        /*
         * Step 2:
         *      If no socket ...
 
 
 static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
 {
-       struct iphdr *ip = skb->nh.iph;
+       struct iphdr *ip = ip_hdr(skb);
        unsigned char stn = ntohl(ip->saddr) & 0xff;
        struct sock *sk;
        struct sk_buff *newskb;
        data = skb->h.raw + sizeof(struct udphdr);
        ah = (struct aunhdr *)data;
        len = skb->len - sizeof(struct udphdr);
-       ip = skb->nh.iph;
+       ip = ip_hdr(skb);
 
        switch (ah->code)
        {
 
        if (eth->h_proto != htons(ETH_P_IP))
                return 0;
 
-       ip = skb->nh.iph;
+       ip = ip_hdr(skb);
        switch (ip->tos & 0xfc) {
        case 0x20:
                return 2;
 
        if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ihl = iph->ihl * 4;
        if (ihl < sizeof(*iph))
                goto out;
                goto out;
 
        skb->h.raw = __skb_pull(skb, ihl);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        proto = iph->protocol & (MAX_INET_PROTOS - 1);
        err = -EPROTONOSUPPORT;
 
        if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ihl = iph->ihl * 4;
        if (ihl < sizeof(*iph))
                goto out;
                goto out;
 
        skb->h.raw = __skb_pull(skb, ihl);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        id = ntohs(iph->id);
        proto = iph->protocol & (MAX_INET_PROTOS - 1);
        segs = ERR_PTR(-EPROTONOSUPPORT);
 
        skb = segs;
        do {
-               iph = skb->nh.iph;
+               iph = ip_hdr(skb);
                iph->id = htons(id++);
                iph->tot_len = htons(skb->len - skb->mac_len);
                iph->check = 0;
 
                char            buf[60];
        } tmp_iph;
 
-       top_iph = skb->nh.iph;
+       top_iph = ip_hdr(skb);
        iph = &tmp_iph.iph;
 
        iph->tos = top_iph->tos;
        skb->ip_summed = CHECKSUM_NONE;
 
        ah = (struct ip_auth_hdr*)skb->data;
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        ihl = skb->data - skb_network_header(skb);
        memcpy(work_buf, iph, ihl);
 
        switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
        default:
        case 0:         /* By default announce any local IP */
-               if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
-                       saddr = skb->nh.iph->saddr;
+               if (skb && inet_addr_type(ip_hdr(skb)->saddr) == RTN_LOCAL)
+                       saddr = ip_hdr(skb)->saddr;
                break;
        case 1:         /* Restrict announcements of saddr in same subnet */
                if (!skb)
                        break;
-               saddr = skb->nh.iph->saddr;
+               saddr = ip_hdr(skb)->saddr;
                if (inet_addr_type(saddr) == RTN_LOCAL) {
                        /* saddr should be known to target */
                        if (inet_addr_onlink(in_dev, target, saddr))
 
  */
 void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 {
-       if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES)
+       if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
                return;
 
        if (gateway)
 
        pskb_put(skb, trailer, clen - skb->len);
 
        __skb_push(skb, skb->data - skb_network_header(skb));
-       top_iph = skb->nh.iph;
+       top_iph = ip_hdr(skb);
        esph = (struct ip_esp_hdr *)(skb_network_header(skb) +
                                     top_iph->ihl * 4);
        top_iph->tot_len = htons(skb->len + alen);
 
        /* ... check padding bits here. Silly. :-) */
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ihl = iph->ihl * 4;
 
        if (x->encap) {
 
        icmp_param->data.icmph.checksum = 0;
        icmp_out_count(icmp_param->data.icmph.type);
 
-       inet->tos = skb->nh.iph->tos;
+       inet->tos = ip_hdr(skb)->tos;
        daddr = ipc.addr = rt->rt_src;
        ipc.opt = NULL;
        if (icmp_param->replyopts.optlen) {
                struct flowi fl = { .nl_u = { .ip4_u =
                                              { .daddr = daddr,
                                                .saddr = rt->rt_spec_dst,
-                                               .tos = RT_TOS(skb->nh.iph->tos) } },
+                                               .tos = RT_TOS(ip_hdr(skb)->tos) } },
                                    .proto = IPPROTO_ICMP };
                security_skb_classify_flow(skb, &fl);
                if (ip_route_output_key(&rt, &fl))
         *      Check this, icmp_send is called from the most obscure devices
         *      sometimes.
         */
-       iph = skb_in->nh.iph;
+       iph = ip_hdr(skb_in);
 
        if ((u8 *)iph < skb_in->head || (u8 *)(iph + 1) > skb_in->tail)
                goto out;
                        printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
                                            "type %u, code %u "
                                            "error to a broadcast: %u.%u.%u.%u on %s\n",
-                              NIPQUAD(skb->nh.iph->saddr),
+                              NIPQUAD(ip_hdr(skb)->saddr),
                               icmph->type, icmph->code,
                               NIPQUAD(iph->daddr),
                               skb->dev->name);
                 */
        case ICMP_REDIR_HOST:
        case ICMP_REDIR_HOSTTOS:
-               ip_rt_redirect(skb->nh.iph->saddr, iph->daddr,
+               ip_rt_redirect(ip_hdr(skb)->saddr, iph->daddr,
                               skb->h.icmph->un.gateway,
                               iph->saddr, skb->dev);
                break;
 
        skb_reserve(skb, LL_RESERVED_SPACE(dev));
 
        skb_reset_network_header(skb);
-       pip = skb->nh.iph;
+       pip = ip_hdr(skb);
        skb_put(skb, sizeof(struct iphdr) + 4);
 
        pip->version  = 4;
 
 static int igmpv3_sendpack(struct sk_buff *skb)
 {
-       struct iphdr *pip = skb->nh.iph;
+       struct iphdr *pip = ip_hdr(skb);
        struct igmphdr *pig = skb->h.igmph;
-       int iplen, igmplen;
+       const int iplen = skb->tail - skb->nh.raw;
+       const int igmplen = skb->tail - skb->h.raw;
 
-       iplen = skb->tail - (unsigned char *)skb->nh.iph;
        pip->tot_len = htons(iplen);
        ip_send_check(pip);
-
-       igmplen = skb->tail - (unsigned char *)skb->h.igmph;
-       pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
+       pig->csum = ip_compute_csum(skb->h.igmph, igmplen);
 
        return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
                       dst_output);
        skb_reserve(skb, LL_RESERVED_SPACE(dev));
 
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        skb_put(skb, sizeof(struct iphdr) + 4);
 
        iph->version  = 4;
 
         *      that reaches zero, we must reply an ICMP control message telling
         *      that the packet's lifetime expired.
         */
-       if (skb->nh.iph->ttl <= 1)
+       if (ip_hdr(skb)->ttl <= 1)
                goto too_many_hops;
 
        if (!xfrm4_route_forward(skb))
        /* We are about to mangle packet. Copy it! */
        if (skb_cow(skb, LL_RESERVED_SPACE(rt->u.dst.dev)+rt->u.dst.header_len))
                goto drop;
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        /* Decrease ttl after skb cow done */
        ip_decrease_ttl(iph);
 
                goto err;
        }
 
-       offset = ntohs(skb->nh.iph->frag_off);
+       offset = ntohs(ip_hdr(skb)->frag_off);
        flags = offset & ~IP_OFFSET;
        offset &= IP_OFFSET;
        offset <<= 3;           /* offset is in 8-byte chunks */
        head->dev = dev;
        head->tstamp = qp->stamp;
 
-       iph = head->nh.iph;
+       iph = ip_hdr(head);
        iph->frag_off = 0;
        iph->tot_len = htons(len);
        IP_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
 /* Process an incoming IP datagram fragment. */
 struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
 {
-       struct iphdr *iph = skb->nh.iph;
        struct ipq *qp;
        struct net_device *dev;
 
        dev = skb->dev;
 
        /* Lookup (or create) queue header */
-       if ((qp = ip_find(iph, user)) != NULL) {
+       if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
                struct sk_buff *ret = NULL;
 
                spin_lock(&qp->lock);
 
 {
        if (INET_ECN_is_ce(iph->tos)) {
                if (skb->protocol == htons(ETH_P_IP)) {
-                       IP_ECN_set_ce(skb->nh.iph);
+                       IP_ECN_set_ce(ip_hdr(skb));
                } else if (skb->protocol == htons(ETH_P_IPV6)) {
                        IP6_ECN_set_ce(skb->nh.ipv6h);
                }
        if (!pskb_may_pull(skb, 16))
                goto drop_nolock;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        h = skb->data;
        flags = *(__be16*)h;
 
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct net_device_stats *stats = &tunnel->stat;
-       struct iphdr  *old_iph = skb->nh.iph;
+       struct iphdr  *old_iph = ip_hdr(skb);
        struct iphdr  *tiph;
        u8     tos;
        __be16 df;
                        skb_set_owner_w(new_skb, skb->sk);
                dev_kfree_skb(skb);
                skb = new_skb;
-               old_iph = skb->nh.iph;
+               old_iph = ip_hdr(skb);
        }
 
        skb->h.raw = skb->nh.raw;
         *      Push down and install the IPIP header.
         */
 
-       iph                     =       skb->nh.iph;
+       iph                     =       ip_hdr(skb);
        iph->version            =       4;
        iph->ihl                =       sizeof(struct iphdr) >> 2;
        iph->frag_off           =       df;
 
 int ip_call_ra_chain(struct sk_buff *skb)
 {
        struct ip_ra_chain *ra;
-       u8 protocol = skb->nh.iph->protocol;
+       u8 protocol = ip_hdr(skb)->protocol;
        struct sock *last = NULL;
 
        read_lock(&ip_ra_lock);
                if (sk && inet_sk(sk)->num == protocol &&
                    (!sk->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == skb->dev->ifindex)) {
-                       if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+                       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                                skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
                                if (skb == NULL) {
                                        read_unlock(&ip_ra_lock);
        rcu_read_lock();
        {
                /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
-               int protocol = skb->nh.iph->protocol;
+               int protocol = ip_hdr(skb)->protocol;
                int hash;
                struct sock *raw_sk;
                struct net_protocol *ipprot;
                /* If there maybe a raw socket we must check - if not we
                 * don't care less
                 */
-               if (raw_sk && !raw_v4_input(skb, skb->nh.iph, hash))
+               if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
                        raw_sk = NULL;
 
                if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
         *      Reassemble IP fragments.
         */
 
-       if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
                if (!skb)
                        return 0;
                goto drop;
        }
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        if (ip_options_compile(NULL, skb)) {
                IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
 
 static inline int ip_rcv_finish(struct sk_buff *skb)
 {
-       struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
 
        /*
         *      Initialise the virtual path cache for the packet. It describes
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
                goto inhdr_error;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        /*
         *      RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
        if (!pskb_may_pull(skb, iph->ihl*4))
                goto inhdr_error;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
                goto inhdr_error;
 
        if (skb->dst)
                daddr = ((struct rtable*)skb->dst)->rt_spec_dst;
        else
-               daddr = skb->nh.iph->daddr;
+               daddr = ip_hdr(skb)->daddr;
 
        if (sopt->rr) {
                optlen  = sptr[sopt->rr+1];
                        /*
                         * RFC1812 requires to fix illegal source routes.
                         */
-                       if (memcmp(&skb->nh.iph->saddr, &start[soffset+3], 4) == 0)
+                       if (memcmp(&ip_hdr(skb)->saddr,
+                                  &start[soffset + 3], 4) == 0)
                                doffset -= 4;
                }
                if (doffset > 3) {
                optptr = iph + sizeof(struct iphdr);
                opt->is_data = 0;
        } else {
-               optptr = opt->is_data ? opt->__data : (unsigned char*)&(skb->nh.iph[1]);
+               optptr = opt->is_data ? opt->__data :
+                                       (unsigned char *)&(ip_hdr(skb)[1]);
                iph = optptr - sizeof(struct iphdr);
        }
 
                if (srrptr + 3 <= srrspace) {
                        opt->is_changed = 1;
                        ip_rt_get_source(&optptr[srrptr-1], rt);
-                       skb->nh.iph->daddr = rt->rt_dst;
+                       ip_hdr(skb)->daddr = rt->rt_dst;
                        optptr[2] = srrptr+4;
                } else if (net_ratelimit())
                        printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
        }
        if (opt->is_changed) {
                opt->is_changed = 0;
-               ip_send_check(skb->nh.iph);
+               ip_send_check(ip_hdr(skb));
        }
 }
 
        struct ip_options *opt = &(IPCB(skb)->opt);
        int srrspace, srrptr;
        __be32 nexthop;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        unsigned char *optptr = skb_network_header(skb) + opt->srr;
        struct rtable *rt = (struct rtable*)skb->dst;
        struct rtable *rt2;
 
        /* Build the IP header. */
        skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        iph->version  = 4;
        iph->ihl      = 5;
        iph->tos      = inet->tos;
 
                /* Multicasts with ttl 0 must not go beyond the host */
 
-               if (skb->nh.iph->ttl == 0) {
+               if (ip_hdr(skb)->ttl == 0) {
                        kfree_skb(skb);
                        return 0;
                }
        /* OK, we know where to send it, allocate and build IP header. */
        skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
        iph->tot_len = htons(skb->len);
        if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)
         *      Point into the IP datagram header.
         */
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
                IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
                                __skb_push(frag, hlen);
                                skb_reset_network_header(frag);
                                memcpy(skb_network_header(frag), iph, hlen);
-                               iph = frag->nh.iph;
+                               iph = ip_hdr(frag);
                                iph->tot_len = htons(frag->len);
                                ip_copy_metadata(frag, skb);
                                if (offset == 0)
                /*
                 *      Fill in the new header fields.
                 */
-               iph = skb2->nh.iph;
+               iph = ip_hdr(skb2);
                iph->frag_off = htons((offset >> 3));
 
                /* ANK: dirty, but effective trick. Upgrade options only if
                         */
                        data = skb_put(skb, fragheaderlen + fraggap);
                        skb_reset_network_header(skb);
-                       iph = skb->nh.iph;
+                       iph = ip_hdr(skb);
                        data += fragheaderlen;
                        skb->h.raw = data;
 
                struct flowi fl = { .nl_u = { .ip4_u =
                                              { .daddr = daddr,
                                                .saddr = rt->rt_spec_dst,
-                                               .tos = RT_TOS(skb->nh.iph->tos) } },
+                                               .tos = RT_TOS(ip_hdr(skb)->tos) } },
                                    /* Not quite clean, but right. */
                                    .uli_u = { .ports =
                                               { .sport = skb->h.th->dest,
           with locally disabled BH and that sk cannot be already spinlocked.
         */
        bh_lock_sock(sk);
-       inet->tos = skb->nh.iph->tos;
+       inet->tos = ip_hdr(skb)->tos;
        sk->sk_priority = skb->priority;
-       sk->sk_protocol = skb->nh.iph->protocol;
+       sk->sk_protocol = ip_hdr(skb)->protocol;
        ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
                       &ipc, rt, MSG_DONTWAIT);
        if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
 
        struct in_pktinfo info;
        struct rtable *rt = (struct rtable *)skb->dst;
 
-       info.ipi_addr.s_addr = skb->nh.iph->daddr;
+       info.ipi_addr.s_addr = ip_hdr(skb)->daddr;
        if (rt) {
                info.ipi_ifindex = rt->rt_iif;
                info.ipi_spec_dst.s_addr = rt->rt_spec_dst;
 
 static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb)
 {
-       int ttl = skb->nh.iph->ttl;
+       int ttl = ip_hdr(skb)->ttl;
        put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl);
 }
 
 static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb)
 {
-       put_cmsg(msg, SOL_IP, IP_TOS, 1, &skb->nh.iph->tos);
+       put_cmsg(msg, SOL_IP, IP_TOS, 1, &ip_hdr(skb)->tos);
 }
 
 static void ip_cmsg_recv_opts(struct msghdr *msg, struct sk_buff *skb)
        if (IPCB(skb)->opt.optlen == 0)
                return;
 
-       put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen, skb->nh.iph+1);
+       put_cmsg(msg, SOL_IP, IP_RECVOPTS, IPCB(skb)->opt.optlen,
+                ip_hdr(skb) + 1);
 }
 
 
 
        skb_put(skb, sizeof(struct iphdr));
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        iph->daddr = daddr;
 
        serr = SKB_EXT_ERR(skb);
                struct inet_sock *inet = inet_sk(sk);
 
                sin->sin_family = AF_INET;
-               sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                sin->sin_port = 0;
                memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
                if (inet->cmsg_flags)
 
 
 static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 {
-       int err, plen, dlen;
        struct ipcomp_data *ipcd = x->data;
-       u8 *start, *scratch;
-       struct crypto_comp *tfm;
-       int cpu;
-
-       plen = skb->len;
-       dlen = IPCOMP_SCRATCH_SIZE;
-       start = skb->data;
+       const int plen = skb->len;
+       int dlen = IPCOMP_SCRATCH_SIZE;
+       const u8 *start = skb->data;
+       const int cpu = get_cpu();
+       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+       int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
 
-       cpu = get_cpu();
-       scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-       tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
-       err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
        if (err)
                goto out;
 
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Remove ipcomp header and decompress original payload */
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        ipch = (void *)skb->data;
        iph->protocol = ipch->nexthdr;
        skb->h.raw = skb->nh.raw + sizeof(*ipch);
 
 static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
 {
-       int err, plen, dlen, ihlen;
-       struct iphdr *iph = skb->nh.iph;
        struct ipcomp_data *ipcd = x->data;
-       u8 *start, *scratch;
-       struct crypto_comp *tfm;
-       int cpu;
+       const int ihlen = ip_hdrlen(skb);
+       const int plen = skb->len - ihlen;
+       int dlen = IPCOMP_SCRATCH_SIZE;
+       u8 *start = skb->data + ihlen;
+       const int cpu = get_cpu();
+       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+       int err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
 
-       ihlen = iph->ihl * 4;
-       plen = skb->len - ihlen;
-       dlen = IPCOMP_SCRATCH_SIZE;
-       start = skb->data + ihlen;
-
-       cpu = get_cpu();
-       scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-       tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-
-       err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
        if (err)
                goto out;
 
 static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err;
-       struct iphdr *iph;
        struct ip_comp_hdr *ipch;
        struct ipcomp_data *ipcd = x->data;
        int hdr_len = 0;
+       struct iphdr *iph = ip_hdr(skb);
 
-       iph = skb->nh.iph;
        iph->tot_len = htons(skb->len);
        hdr_len = iph->ihl * 4;
        if ((skb->len - hdr_len) < ipcd->threshold) {
                goto out_ok;
 
        err = ipcomp_compress(x, skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        if (err) {
                goto out_ok;
 
 
        /* Construct IP header */
        skb_reset_network_header(skb);
-       h = skb->nh.iph;
+       h = ip_hdr(skb);
        h->version = 4;
        h->ihl = 5;
        h->tot_len = htons(sizeof(struct bootp_pkt));
                           sizeof(struct udphdr)))
                goto drop;
 
-       b = (struct bootp_pkt *) skb->nh.iph;
+       b = (struct bootp_pkt *)skb_network_header(skb);
        h = &b->iph;
 
        if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP)
        if (!pskb_may_pull(skb, skb->len))
                goto drop;
 
-       b = (struct bootp_pkt *) skb->nh.iph;
+       b = (struct bootp_pkt *)skb_network_header(skb);
        h = &b->iph;
 
        /* One reply at a time, please. */
 
 #endif
 }
 
-static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
+static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph,
+                                       struct sk_buff *skb)
 {
-       struct iphdr *inner_iph = skb->nh.iph;
+       struct iphdr *inner_iph = ip_hdr(skb);
 
        if (INET_ECN_is_ce(outer_iph->tos))
                IP_ECN_set_ce(inner_iph);
 
 static int ipip_rcv(struct sk_buff *skb)
 {
-       struct iphdr *iph;
        struct ip_tunnel *tunnel;
-
-       iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
 
        read_lock(&ipip_lock);
        if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
        __be16 df = tiph->frag_off;
        struct rtable *rt;                      /* Route to the other host */
        struct net_device *tdev;                        /* Device to other host */
-       struct iphdr  *old_iph = skb->nh.iph;
+       struct iphdr  *old_iph = ip_hdr(skb);
        struct iphdr  *iph;                     /* Our new IP header */
        int    max_headroom;                    /* The extra header space needed */
        __be32 dst = tiph->daddr;
                        skb_set_owner_w(new_skb, skb->sk);
                dev_kfree_skb(skb);
                skb = new_skb;
-               old_iph = skb->nh.iph;
+               old_iph = ip_hdr(skb);
        }
 
        skb->h.raw = skb->nh.raw;
         *      Push down and install the IPIP header.
         */
 
-       iph                     =       skb->nh.iph;
+       iph                     =       ip_hdr(skb);
        iph->version            =       4;
        iph->ihl                =       sizeof(struct iphdr)>>2;
        iph->frag_off           =       df;
 
        atomic_dec(&cache_resolve_queue_len);
 
        while ((skb=skb_dequeue(&c->mfc_un.unres.unresolved))) {
-               if (skb->nh.iph->version == 0) {
+               if (ip_hdr(skb)->version == 0) {
                        struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
                        nlh->nlmsg_type = NLMSG_ERROR;
                        nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
         */
 
        while ((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) {
-               if (skb->nh.iph->version == 0) {
+               if (ip_hdr(skb)->version == 0) {
                        struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr));
 
                        if (ipmr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) {
                msg->im_msgtype = IGMPMSG_WHOLEPKT;
                msg->im_mbz = 0;
                msg->im_vif = reg_vif_num;
-               skb->nh.iph->ihl = sizeof(struct iphdr) >> 2;
-               skb->nh.iph->tot_len = htons(ntohs(pkt->nh.iph->tot_len) + sizeof(struct iphdr));
+               ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
+               ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
+                                            sizeof(struct iphdr));
        } else
 #endif
        {
         *      Copy the IP header
         */
 
-       skb->nh.iph = (struct iphdr *)skb_put(skb, ihl);
+       skb->nh.raw = skb_put(skb, ihl);
        memcpy(skb->data,pkt->data,ihl);
-       skb->nh.iph->protocol = 0;                      /* Flag to the kernel this is a route add */
-       msg = (struct igmpmsg*)skb->nh.iph;
+       ip_hdr(skb)->protocol = 0;                      /* Flag to the kernel this is a route add */
+       msg = (struct igmpmsg *)skb_network_header(skb);
        msg->im_vif = vifi;
        skb->dst = dst_clone(pkt->dst);
 
        igmp->type      =
        msg->im_msgtype = assert;
        igmp->code      =       0;
-       skb->nh.iph->tot_len=htons(skb->len);                   /* Fix the length */
+       ip_hdr(skb)->tot_len = htons(skb->len);                 /* Fix the length */
        skb->h.raw = skb->nh.raw;
        }
 
 {
        int err;
        struct mfc_cache *c;
+       const struct iphdr *iph = ip_hdr(skb);
 
        spin_lock_bh(&mfc_unres_lock);
        for (c=mfc_unres_queue; c; c=c->next) {
-               if (c->mfc_mcastgrp == skb->nh.iph->daddr &&
-                   c->mfc_origin == skb->nh.iph->saddr)
+               if (c->mfc_mcastgrp == iph->daddr &&
+                   c->mfc_origin == iph->saddr)
                        break;
        }
 
                /*
                 *      Fill in the new cache entry
                 */
-               c->mfc_parent=-1;
-               c->mfc_origin=skb->nh.iph->saddr;
-               c->mfc_mcastgrp=skb->nh.iph->daddr;
+               c->mfc_parent   = -1;
+               c->mfc_origin   = iph->saddr;
+               c->mfc_mcastgrp = iph->daddr;
 
                /*
                 *      Reflect first query at mrouted.
 static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
 {
        struct iphdr *iph;
-       struct iphdr *old_iph = skb->nh.iph;
+       struct iphdr *old_iph = ip_hdr(skb);
 
        skb_push(skb, sizeof(struct iphdr));
-       skb->h.ipiph = skb->nh.iph;
+       skb->h.raw = skb->nh.raw;
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        iph->version    =       4;
        iph->tos        =       old_iph->tos;
 
 static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
 {
-       struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        struct vif_device *vif = &vif_table[vifi];
        struct net_device *dev;
        struct rtable *rt;
 
        dst_release(skb->dst);
        skb->dst = &rt->u.dst;
-       iph = skb->nh.iph;
-       ip_decrease_ttl(iph);
+       ip_decrease_ttl(ip_hdr(skb));
 
        /* FIXME: forward and output firewalls used to be called here.
         * What do we do with netfilter? -- RR */
         *      Forward the frame
         */
        for (ct = cache->mfc_un.res.maxvif-1; ct >= cache->mfc_un.res.minvif; ct--) {
-               if (skb->nh.iph->ttl > cache->mfc_un.res.ttls[ct]) {
+               if (ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
                        if (psend != -1) {
                                struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2)
                    if (IPCB(skb)->opt.router_alert) {
                            if (ip_call_ra_chain(skb))
                                    return 0;
-                   } else if (skb->nh.iph->protocol == IPPROTO_IGMP){
+                   } else if (ip_hdr(skb)->protocol == IPPROTO_IGMP){
                            /* IGMPv1 (and broken IGMPv2 implementations sort of
                               Cisco IOS <= 11.2(8)) do not put router alert
                               option to IGMP packets destined to routable
        }
 
        read_lock(&mrt_lock);
-       cache = ipmr_cache_find(skb->nh.iph->saddr, skb->nh.iph->daddr);
+       cache = ipmr_cache_find(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
 
        /*
         *      No usable cache entry
 
        if (cache==NULL) {
                struct sk_buff *skb2;
+               struct iphdr *iph;
                struct net_device *dev;
                int vif;
 
 
                skb_push(skb2, sizeof(struct iphdr));
                skb_reset_network_header(skb2);
-               skb2->nh.iph->ihl = sizeof(struct iphdr)>>2;
-               skb2->nh.iph->saddr = rt->rt_src;
-               skb2->nh.iph->daddr = rt->rt_dst;
-               skb2->nh.iph->version = 0;
+               iph = ip_hdr(skb2);
+               iph->ihl = sizeof(struct iphdr) >> 2;
+               iph->saddr = rt->rt_src;
+               iph->daddr = rt->rt_dst;
+               iph->version = 0;
                err = ipmr_cache_unresolved(vif, skb2);
                read_unlock(&mrt_lock);
                return err;
 
 int ip_vs_skb_replace(struct sk_buff *skb, gfp_t pri,
                      char *o_buf, int o_len, char *n_buf, int n_len)
 {
-       struct iphdr *iph;
        int diff;
        int o_offset;
        int o_left;
        }
 
        /* must update the iph total length here */
-       iph = skb->nh.iph;
-       iph->tot_len = htons(skb->len);
+       ip_hdr(skb)->tot_len = htons(skb->len);
 
        LeaveFunction(9);
        return 0;
 
                    __be16 ports[2])
 {
        struct ip_vs_conn *cp = NULL;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct ip_vs_dest *dest;
        struct ip_vs_conn *ct;
        __be16  dport;   /* destination port to forward */
 ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 {
        struct ip_vs_conn *cp = NULL;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct ip_vs_dest *dest;
        __be16 _ports[2], *pptr;
 
                struct ip_vs_protocol *pp)
 {
        __be16 _ports[2], *pptr;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        pptr = skb_header_pointer(skb, iph->ihl*4,
                                  sizeof(_ports), _ports);
 {
        skb = ip_defrag(skb, user);
        if (skb)
-               ip_send_check(skb->nh.iph);
+               ip_send_check(ip_hdr(skb));
        return skb;
 }
 
 void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
                    struct ip_vs_conn *cp, int inout)
 {
-       struct iphdr *iph        = skb->nh.iph;
+       struct iphdr *iph        = ip_hdr(skb);
        unsigned int icmp_offset = iph->ihl*4;
        struct icmphdr *icmph    = (struct icmphdr *)(skb_network_header(skb) +
                                                      icmp_offset);
        *related = 1;
 
        /* reassemble IP fragments */
-       if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
                if (!skb)
                        return NF_STOLEN;
                *pskb = skb;
        }
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        offset = ihl = iph->ihl * 4;
        ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
        if (ic == NULL)
        if (skb->ipvs_property)
                return NF_ACCEPT;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        if (unlikely(iph->protocol == IPPROTO_ICMP)) {
                int related, verdict = ip_vs_out_icmp(pskb, &related);
 
                if (related)
                        return verdict;
                skb = *pskb;
-               iph = skb->nh.iph;
+               iph = ip_hdr(skb);
        }
 
        pp = ip_vs_proto_get(iph->protocol);
                skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
                if (!skb)
                        return NF_STOLEN;
-               iph = skb->nh.iph;
+               iph = ip_hdr(skb);
                *pskb = skb;
        }
 
        if (pp->snat_handler && !pp->snat_handler(pskb, pp, cp))
                goto drop;
        skb = *pskb;
-       skb->nh.iph->saddr = cp->vaddr;
-       ip_send_check(skb->nh.iph);
+       ip_hdr(skb)->saddr = cp->vaddr;
+       ip_send_check(ip_hdr(skb));
 
        /* For policy routing, packets originating from this
         * machine itself may be routed differently to packets
        *related = 1;
 
        /* reassemble IP fragments */
-       if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                skb = ip_vs_gather_frags(skb,
                                         hooknum == NF_IP_LOCAL_IN ?
                                         IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
                *pskb = skb;
        }
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        offset = ihl = iph->ihl * 4;
        ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
        if (ic == NULL)
                     || skb->dev == &loopback_dev || skb->sk)) {
                IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
                          skb->pkt_type,
-                         skb->nh.iph->protocol,
-                         NIPQUAD(skb->nh.iph->daddr));
+                         ip_hdr(skb)->protocol,
+                         NIPQUAD(ip_hdr(skb)->daddr));
                return NF_ACCEPT;
        }
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        if (unlikely(iph->protocol == IPPROTO_ICMP)) {
                int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
 
                if (related)
                        return verdict;
                skb = *pskb;
-               iph = skb->nh.iph;
+               iph = ip_hdr(skb);
        }
 
        /* Protocol supported? */
 {
        int r;
 
-       if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP)
+       if (ip_hdr(*pskb)->protocol != IPPROTO_ICMP)
                return NF_ACCEPT;
 
        return ip_vs_in_icmp(pskb, &r, hooknum);
 
 {
        struct ip_vs_dest *dest;
        struct ip_vs_dh_bucket *tbl;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        IP_VS_DBG(6, "ip_vs_dh_schedule(): Scheduling...\n");
 
 
                return 0;
 
        if (cp->app_data == &ip_vs_ftp_pasv) {
-               iph = (*pskb)->nh.iph;
+               iph = ip_hdr(*pskb);
                th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
                data = (char *)th + (th->doff << 2);
                data_limit = (*pskb)->tail;
        /*
         * Detecting whether it is passive
         */
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
 
        /* Since there may be OPTIONS in the TCP packet and the HLEN is
 
        struct ip_vs_dest *dest;
        struct ip_vs_lblc_table *tbl;
        struct ip_vs_lblc_entry *en;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n");
 
 
        struct ip_vs_dest *dest;
        struct ip_vs_lblcr_table *tbl;
        struct ip_vs_lblcr_entry *en;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n");
 
 
        }
 
        if (th->syn &&
-           (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
-                                    skb->nh.iph->daddr, th->dest))) {
+           (svc = ip_vs_service_get(skb->mark, ip_hdr(skb)->protocol,
+                                    ip_hdr(skb)->daddr, th->dest))) {
                if (ip_vs_todrop()) {
                        /*
                         * It seems that we are very loaded.
                        return 0;
        }
 
-       tcph = (void *)(*pskb)->nh.iph + tcphoff;
+       tcph = (void *)ip_hdr(*pskb) + tcphoff;
        tcph->source = cp->vport;
 
        /* Adjust TCP checksums */
                        return 0;
        }
 
-       tcph = (void *)(*pskb)->nh.iph + tcphoff;
+       tcph = (void *)ip_hdr(*pskb) + tcphoff;
        tcph->dest = cp->dport;
 
        /*
        case CHECKSUM_NONE:
                skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
        case CHECKSUM_COMPLETE:
-               if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
+               if (csum_tcpudp_magic(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
                                      skb->len - tcphoff,
-                                     skb->nh.iph->protocol, skb->csum)) {
+                                     ip_hdr(skb)->protocol, skb->csum)) {
                        IP_VS_DBG_RL_PKT(0, pp, skb, 0,
                                         "Failed checksum for");
                        return 0;
 
                return 0;
        }
 
-       if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
-                                    skb->nh.iph->daddr, uh->dest))) {
+       if ((svc = ip_vs_service_get(skb->mark, ip_hdr(skb)->protocol,
+                                    ip_hdr(skb)->daddr, uh->dest))) {
                if (ip_vs_todrop()) {
                        /*
                         * It seems that we are very loaded.
                        return 0;
        }
 
-       udph = (void *)(*pskb)->nh.iph + udphoff;
+       udph = (void *)ip_hdr(*pskb) + udphoff;
        udph->source = cp->vport;
 
        /*
                        return 0;
        }
 
-       udph = (void *)(*pskb)->nh.iph + udphoff;
+       udph = (void *)ip_hdr(*pskb) + udphoff;
        udph->dest = cp->dport;
 
        /*
                        skb->csum = skb_checksum(skb, udphoff,
                                                 skb->len - udphoff, 0);
                case CHECKSUM_COMPLETE:
-                       if (csum_tcpudp_magic(skb->nh.iph->saddr,
-                                             skb->nh.iph->daddr,
+                       if (csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                             ip_hdr(skb)->daddr,
                                              skb->len - udphoff,
-                                             skb->nh.iph->protocol,
+                                             ip_hdr(skb)->protocol,
                                              skb->csum)) {
                                IP_VS_DBG_RL_PKT(0, pp, skb, 0,
                                                 "Failed checksum for");
 
 {
        struct ip_vs_dest *dest;
        struct ip_vs_sh_bucket *tbl;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
 
 
                  struct ip_vs_protocol *pp)
 {
        struct rtable *rt;                      /* Route to the other host */
-       struct iphdr  *iph = skb->nh.iph;
+       struct iphdr  *iph = ip_hdr(skb);
        u8     tos = iph->tos;
        int    mtu;
        struct flowi fl = {
                ip_rt_put(rt);
                return NF_STOLEN;
        }
-       ip_send_check(skb->nh.iph);
+       ip_send_check(ip_hdr(skb));
 
        /* drop old route */
        dst_release(skb->dst);
 {
        struct rtable *rt;              /* Route to the other host */
        int mtu;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
 
        EnterFunction(10);
 
        /* mangle the packet */
        if (pp->dnat_handler && !pp->dnat_handler(&skb, pp, cp))
                goto tx_error;
-       skb->nh.iph->daddr = cp->daddr;
-       ip_send_check(skb->nh.iph);
+       ip_hdr(skb)->daddr = cp->daddr;
+       ip_send_check(ip_hdr(skb));
 
        IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
 
 {
        struct rtable *rt;                      /* Route to the other host */
        struct net_device *tdev;                /* Device to other host */
-       struct iphdr  *old_iph = skb->nh.iph;
+       struct iphdr  *old_iph = ip_hdr(skb);
        u8     tos = old_iph->tos;
        __be16 df = old_iph->frag_off;
        struct iphdr  *iph;                     /* Our new IP header */
                }
                kfree_skb(skb);
                skb = new_skb;
-               old_iph = skb->nh.iph;
+               old_iph = ip_hdr(skb);
        }
 
        skb->h.raw = (void *) old_iph;
        /*
         *      Push down and install the IPIP header.
         */
-       iph                     =       skb->nh.iph;
+       iph                     =       ip_hdr(skb);
        iph->version            =       4;
        iph->ihl                =       sizeof(struct iphdr)>>2;
        iph->frag_off           =       df;
              struct ip_vs_protocol *pp)
 {
        struct rtable *rt;                      /* Route to the other host */
-       struct iphdr  *iph = skb->nh.iph;
+       struct iphdr  *iph = ip_hdr(skb);
        int    mtu;
 
        EnterFunction(10);
                ip_rt_put(rt);
                return NF_STOLEN;
        }
-       ip_send_check(skb->nh.iph);
+       ip_send_check(ip_hdr(skb));
 
        /* drop old route */
        dst_release(skb->dst);
         * mangle and send the packet here (only for VS/NAT)
         */
 
-       if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(skb->nh.iph->tos))))
+       if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(ip_hdr(skb)->tos))))
                goto tx_error_icmp;
 
        /* MTU checking */
        mtu = dst_mtu(&rt->u.dst);
-       if ((skb->len > mtu) && (skb->nh.iph->frag_off & htons(IP_DF))) {
+       if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) {
                ip_rt_put(rt);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
                IP_VS_DBG_RL("ip_vs_in_icmp(): frag needed\n");
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
 int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
 {
-       struct iphdr *iph = (*pskb)->nh.iph;
+       const struct iphdr *iph = ip_hdr(*pskb);
        struct rtable *rt;
        struct flowi fl = {};
        struct dst_entry *odst;
        struct ip_rt_info *rt_info = nf_info_reroute(info);
 
        if (info->hook == NF_IP_LOCAL_OUT) {
-               const struct iphdr *iph = skb->nh.iph;
+               const struct iphdr *iph = ip_hdr(skb);
 
                rt_info->tos = iph->tos;
                rt_info->daddr = iph->daddr;
        const struct ip_rt_info *rt_info = nf_info_reroute(info);
 
        if (info->hook == NF_IP_LOCAL_OUT) {
-               struct iphdr *iph = (*pskb)->nh.iph;
+               const struct iphdr *iph = ip_hdr(*pskb);
 
                if (!(iph->tos == rt_info->tos
                      && iph->daddr == rt_info->daddr
 __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
                            unsigned int dataoff, u_int8_t protocol)
 {
-       struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        __sum16 csum = 0;
 
        switch (skb->ip_summed) {
 
        struct ip_conntrack_tuple_hash *h;
        struct ip_conntrack *ct;
 
-       IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
+       IP_NF_ASSERT((ip_hdr(skb)->frag_off & htons(IP_OFFSET)) == 0);
 
-       if (!ip_ct_get_tuple(skb->nh.iph, skb, ip_hdrlen(skb), &tuple,proto))
+       if (!ip_ct_get_tuple(ip_hdr(skb), skb, ip_hdrlen(skb), &tuple,proto))
                return NULL;
 
        /* look for tuple match */
        }
 
        /* Never happen */
-       if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
+       if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) {
                if (net_ratelimit()) {
                printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
-                      (*pskb)->nh.iph->protocol, hooknum);
+                      ip_hdr(*pskb)->protocol, hooknum);
                }
                return NF_DROP;
        }
        if ((*pskb)->pkt_type == PACKET_BROADCAST) {
                printk("Broadcast packet!\n");
                return NF_ACCEPT;
-       } else if (((*pskb)->nh.iph->daddr & htonl(0x000000FF))
+       } else if ((ip_hdr(*pskb)->daddr & htonl(0x000000FF))
                   == htonl(0x000000FF)) {
                printk("Should bcast: %u.%u.%u.%u->%u.%u.%u.%u (sk=%p, ptype=%u)\n",
-                      NIPQUAD((*pskb)->nh.iph->saddr),
-                      NIPQUAD((*pskb)->nh.iph->daddr),
+                      NIPQUAD(ip_hdr(*pskb)->saddr),
+                      NIPQUAD(ip_hdr(*pskb)->daddr),
                       (*pskb)->sk, (*pskb)->pkt_type);
        }
 #endif
 
        /* rcu_read_lock()ed by nf_hook_slow */
-       proto = __ip_conntrack_proto_find((*pskb)->nh.iph->protocol);
+       proto = __ip_conntrack_proto_find(ip_hdr(*pskb)->protocol);
 
        /* It may be an special packet, error, unclean...
         * inverse of the return code tells to the netfilter
        if (do_acct) {
                ct->counters[CTINFO2DIR(ctinfo)].packets++;
                ct->counters[CTINFO2DIR(ctinfo)].bytes +=
-                                               ntohs(skb->nh.iph->tot_len);
+                                               ntohs(ip_hdr(skb)->tot_len);
                if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
                    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
                        event |= IPCT_COUNTER_FILLING;
        local_bh_enable();
 
        if (skb)
-               ip_send_check(skb->nh.iph);
+               ip_send_check(ip_hdr(skb));
        return skb;
 }
 
 
        /* Process each TPKT */
        while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
                DEBUGP("ip_ct_h245: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
-                      NIPQUAD((*pskb)->nh.iph->saddr),
-                      NIPQUAD((*pskb)->nh.iph->daddr), datalen);
+                      NIPQUAD(ip_hdr(*pskb)->saddr),
+                      NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
 
                /* Decode H.245 signal */
                ret = DecodeMultimediaSystemControlMessage(data, datalen,
        /* Process each TPKT */
        while (get_tpkt_data(pskb, ct, ctinfo, &data, &datalen, &dataoff)) {
                DEBUGP("ip_ct_q931: TPKT %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
-                      NIPQUAD((*pskb)->nh.iph->saddr),
-                      NIPQUAD((*pskb)->nh.iph->daddr), datalen);
+                      NIPQUAD(ip_hdr(*pskb)->saddr),
+                      NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
 
                /* Decode Q.931 signal */
                ret = DecodeQ931(data, datalen, &q931);
        if (data == NULL)
                goto accept;
        DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n",
-              NIPQUAD((*pskb)->nh.iph->saddr),
-              NIPQUAD((*pskb)->nh.iph->daddr), datalen);
+              NIPQUAD(ip_hdr(*pskb)->saddr),
+              NIPQUAD(ip_hdr(*pskb)->daddr), datalen);
 
        /* Decode RAS message */
        ret = DecodeRasMessage(data, datalen, &ras);
 
                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
        struct ip_conntrack_expect *exp;
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct rtable *rt = (struct rtable *)(*pskb)->dst;
        struct in_device *in_dev;
        __be32 mask = 0;
 
                       enum ip_conntrack_info ctinfo)
 {
        enum sctp_conntrack newconntrack, oldsctpstate;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        sctp_sctphdr_t _sctph, *sh;
        sctp_chunkhdr_t _sch, *sch;
        u_int32_t offset, count;
                    const struct sk_buff *skb)
 {
        enum sctp_conntrack newconntrack;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        sctp_sctphdr_t _sctph, *sh;
        sctp_chunkhdr_t _sch, *sch;
        u_int32_t offset, count;
 
                             struct ip_conntrack *conntrack,
                             enum ip_conntrack_dir dir)
 {
-       struct iphdr *iph = skb->nh.iph;
-       struct tcphdr *tcph = (void *)skb->nh.iph + ip_hdrlen(skb);
+       struct iphdr *iph = ip_hdr(skb);
+       struct tcphdr *tcph = (void *)iph + ip_hdrlen(skb);
        __u32 end;
 #ifdef DEBUGP_VARS
        struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
                     enum ip_conntrack_info *ctinfo,
                     unsigned int hooknum)
 {
-       struct iphdr *iph = skb->nh.iph;
+       const unsigned int hdrlen = ip_hdrlen(skb);
        struct tcphdr _tcph, *th;
-       unsigned int tcplen = skb->len - iph->ihl * 4;
+       unsigned int tcplen = skb->len - hdrlen;
        u_int8_t tcpflags;
 
        /* Smaller that minimal TCP header? */
-       th = skb_header_pointer(skb, iph->ihl * 4,
+       th = skb_header_pointer(skb, hdrlen,
                                sizeof(_tcph), &_tcph);
        if (th == NULL) {
                if (LOG_INVALID(IPPROTO_TCP))
         */
        /* FIXME: Source route IP option packets --RR */
        if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
-           nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
+           nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_TCP)) {
                if (LOG_INVALID(IPPROTO_TCP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
                                  "ip_ct_tcp: bad TCP checksum ");
 {
        enum tcp_conntrack new_state, old_state;
        enum ip_conntrack_dir dir;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct tcphdr *th, _tcph;
        unsigned long timeout;
        unsigned int index;
                   const struct sk_buff *skb)
 {
        enum tcp_conntrack new_state;
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        struct tcphdr *th, _tcph;
 #ifdef DEBUGP_VARS
        struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
 
 static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
                     unsigned int hooknum)
 {
-       struct iphdr *iph = skb->nh.iph;
-       unsigned int udplen = skb->len - iph->ihl * 4;
+       const unsigned int hdrlen = ip_hdrlen(skb);
+       unsigned int udplen = skb->len - hdrlen;
        struct udphdr _hdr, *hdr;
 
        /* Header is too small? */
-       hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr);
+       hdr = skb_header_pointer(skb, hdrlen, sizeof(_hdr), &_hdr);
        if (hdr == NULL) {
                if (LOG_INVALID(IPPROTO_UDP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
         * because the checksum is assumed to be correct.
         * FIXME: Source route IP option packets --RR */
        if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
-           nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
+           nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_UDP)) {
                if (LOG_INVALID(IPPROTO_UDP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
                                  "ip_ct_udp: bad UDP checksum ");
 
 #endif
 
        /* Gather fragments. */
-       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+       if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                *pskb = ip_ct_gather_frags(*pskb,
                                           hooknum == NF_IP_PRE_ROUTING ?
                                           IP_DEFRAG_CONNTRACK_IN :
 
        unsigned char *data;
 
        BUG_ON(skb_is_nonlinear(skb));
-       data = (unsigned char *)skb->nh.iph + dataoff;
+       data = skb_network_header(skb) + dataoff;
 
        /* move post-replacement */
        memmove(data + match_offset + rep_len,
        }
 
        /* fix IP hdr checksum information */
-       skb->nh.iph->tot_len = htons(skb->len);
-       ip_send_check(skb->nh.iph);
+       ip_hdr(skb)->tot_len = htons(skb->len);
+       ip_send_check(ip_hdr(skb));
 }
 
 /* Unusual, but possible case. */
 
        SKB_LINEAR_ASSERT(*pskb);
 
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        tcph = (void *)iph + iph->ihl*4;
 
        oldlen = (*pskb)->len - iph->ihl*4;
        int datalen, oldlen;
 
        /* UDP helpers might accidentally mangle the wrong packet */
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
                               match_offset + match_len)
                return 0;
            && !enlarge_skb(pskb, rep_len - match_len))
                return 0;
 
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        udph = (void *)iph + iph->ihl*4;
 
        oldlen = (*pskb)->len - iph->ihl*4;
 
        buf.port = htons(port);
        addroff += dataoff;
 
-       if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
+       if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
                if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
                                              addroff, sizeof(buf),
                                              (char *) &buf, sizeof(buf))) {
 
 
        if (hooknum == NF_IP_LOCAL_OUT
            && mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
-               warn_if_extra_mangle((*pskb)->nh.iph->daddr,
+               warn_if_extra_mangle(ip_hdr(*pskb)->daddr,
                                     mr->range[0].min_ip);
 
        return ip_nat_setup_info(ct, &mr->range[0], hooknum);
 
                          enum ip_conntrack_info ctinfo,
                          struct sk_buff **pskb)
 {
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
        u_int16_t udplen = ntohs(udph->len);
        u_int16_t paylen = udplen - sizeof(struct udphdr);
 {
        int dir = CTINFO2DIR(ctinfo);
        unsigned int ret;
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
 
        /* SNMP replies and originating SNMP traps get mangled */
 
 
        /* We never see fragments: conntrack defrags on pre-routing
           and local-out, and ip_nat_out protects post-routing. */
-       IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
+       IP_NF_ASSERT(!(ip_hdr(*pskb)->frag_off
                       & htons(IP_MF|IP_OFFSET)));
 
        ct = ip_conntrack_get(*pskb, &ctinfo);
                /* Exception: ICMP redirect to new connection (not in
                   hash table yet).  We must not let this through, in
                   case we're doing NAT to the same network. */
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+               if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
                        struct icmphdr _hdr, *hp;
 
                        hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
        switch (ctinfo) {
        case IP_CT_RELATED:
        case IP_CT_RELATED+IP_CT_IS_REPLY:
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+               if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
                        if (!ip_nat_icmp_reply_translation(ct, ctinfo,
                                                           hooknum, pskb))
                                return NF_DROP;
          int (*okfn)(struct sk_buff *))
 {
        unsigned int ret;
-       __be32 daddr = (*pskb)->nh.iph->daddr;
+       __be32 daddr = ip_hdr(*pskb)->daddr;
 
        ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
        if (ret != NF_DROP && ret != NF_STOLEN
-           && daddr != (*pskb)->nh.iph->daddr) {
+           && daddr != ip_hdr(*pskb)->daddr) {
                dst_release((*pskb)->dst);
                (*pskb)->dst = NULL;
        }
 
        struct xt_table_info *private;
 
        /* Initialization */
-       ip = (*pskb)->nh.iph;
+       ip = ip_hdr(*pskb);
        datalen = (*pskb)->len - ip->ihl * 4;
        indev = in ? in->name : nulldevname;
        outdev = out ? out->name : nulldevname;
                                        = 0x57acc001;
 #endif
                                /* Target might have changed stuff. */
-                               ip = (*pskb)->nh.iph;
+                               ip = ip_hdr(*pskb);
                                datalen = (*pskb)->len - ip->ihl * 4;
 
                                if (verdict == IPT_CONTINUE)
 
 static inline u_int32_t
 clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
 {
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        unsigned long hashval;
        u_int16_t sport, dport;
        u_int16_t *ports;
 
        /* special case: ICMP error handling. conntrack distinguishes between
         * error messages (RELATED) and information requests (see below) */
-       if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
+       if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP
            && (ctinfo == IP_CT_RELATED
                || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
                return XT_CONTINUE;
 
 static inline int
 set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 {
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
 
        if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
                __u8 oldtos;
                if (!skb_make_writable(pskb, sizeof(struct iphdr)))
                        return 0;
-               iph = (*pskb)->nh.iph;
+               iph = ip_hdr(*pskb);
                oldtos = iph->tos;
                iph->tos &= ~IPT_ECN_IP_MASK;
                iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
 
        if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
                return 0;
-       tcph = (void *)(*pskb)->nh.iph + ip_hdrlen(*pskb);
+       tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
 
        oldval = ((__be16 *)tcph)[6];
        if (einfo->operation & IPT_ECN_OP_SET_ECE)
                        return NF_DROP;
 
        if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR)
-           && (*pskb)->nh.iph->protocol == IPPROTO_TCP)
+           && ip_hdr(*pskb)->protocol == IPPROTO_TCP)
                if (!set_ect_tcp(pskb, einfo))
                        return NF_DROP;
 
 
        netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
 
        if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT)
-               new_ip = (*pskb)->nh.iph->daddr & ~netmask;
+               new_ip = ip_hdr(*pskb)->daddr & ~netmask;
        else
-               new_ip = (*pskb)->nh.iph->saddr & ~netmask;
+               new_ip = ip_hdr(*pskb)->saddr & ~netmask;
        new_ip |= mr->range[0].min_ip & netmask;
 
        newrange = ((struct ip_nat_range)
 
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
        struct sk_buff *nskb;
+       struct iphdr *niph;
        struct tcphdr _otcph, *oth, *tcph;
        __be16 tmp_port;
        __be32 tmp_addr;
        unsigned int addr_type;
 
        /* IP header checks: fragment. */
-       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
+       if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
                return;
 
        oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
        tcph = (struct tcphdr *)(skb_network_header(nskb) + ip_hdrlen(nskb));
 
        /* Swap source and dest */
-       tmp_addr = nskb->nh.iph->saddr;
-       nskb->nh.iph->saddr = nskb->nh.iph->daddr;
-       nskb->nh.iph->daddr = tmp_addr;
+       niph = ip_hdr(nskb);
+       tmp_addr = niph->saddr;
+       niph->saddr = niph->daddr;
+       niph->daddr = tmp_addr;
        tmp_port = tcph->source;
        tcph->source = tcph->dest;
        tcph->dest = tmp_port;
        /* Truncate to length (no data) */
        tcph->doff = sizeof(struct tcphdr)/4;
        skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
-       nskb->nh.iph->tot_len = htons(nskb->len);
+       niph->tot_len = htons(nskb->len);
 
        if (tcph->ack) {
                needs_ack = 0;
        /* Adjust TCP checksum */
        tcph->check = 0;
        tcph->check = tcp_v4_check(sizeof(struct tcphdr),
-                                  nskb->nh.iph->saddr,
-                                  nskb->nh.iph->daddr,
+                                  niph->saddr, niph->daddr,
                                   csum_partial((char *)tcph,
                                                sizeof(struct tcphdr), 0));
 
        /* Set DF, id = 0 */
-       nskb->nh.iph->frag_off = htons(IP_DF);
-       nskb->nh.iph->id = 0;
+       niph->frag_off = htons(IP_DF);
+       niph->id = 0;
 
        addr_type = RTN_UNSPEC;
        if (hook != NF_IP_FORWARD
        nskb->ip_summed = CHECKSUM_NONE;
 
        /* Adjust IP TTL */
-       nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
+       niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
 
        /* Adjust IP checksum */
-       nskb->nh.iph->check = 0;
-       nskb->nh.iph->check = ip_fast_csum(skb_network_header(nskb),
-                                          nskb->nh.iph->ihl);
+       niph->check = 0;
+       niph->check = ip_fast_csum(skb_network_header(nskb), niph->ihl);
 
        /* "Never happens" */
        if (nskb->len > dst_mtu(nskb->dst))
 
        const void *targinfo)
 {
        const struct ipt_tos_target_info *tosinfo = targinfo;
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
 
        if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
                __u8 oldtos;
                if (!skb_make_writable(pskb, sizeof(struct iphdr)))
                        return NF_DROP;
-               iph = (*pskb)->nh.iph;
+               iph = ip_hdr(*pskb);
                oldtos = iph->tos;
                iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
                nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
 
        if (!skb_make_writable(pskb, (*pskb)->len))
                return NF_DROP;
 
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
 
        switch (info->mode) {
                case IPT_TTL_SET:
 
                 int offset, unsigned int protoff, int *hotdrop)
 {
        const struct ipt_addrtype_info *info = matchinfo;
-       const struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        int ret = 1;
 
        if (info->source)
 
 static inline int match_ip(const struct sk_buff *skb,
                           const struct ipt_ecn_info *einfo)
 {
-       return ((skb->nh.iph->tos&IPT_ECN_IP_MASK) == einfo->ip_ect);
+       return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
 }
 
 static inline int match_tcp(const struct sk_buff *skb,
                        return 0;
 
        if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
-               if (skb->nh.iph->protocol != IPPROTO_TCP)
+               if (ip_hdr(skb)->protocol != IPPROTO_TCP)
                        return 0;
                if (!match_tcp(skb, info, hotdrop))
                        return 0;
 
       int offset, unsigned int protoff, int *hotdrop)
 {
        const struct ipt_iprange_info *info = matchinfo;
-       const struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
 
        if (info->flags & IPRANGE_SRC) {
                if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
 
        int ret = info->invert;
 
        if (info->side == IPT_RECENT_DEST)
-               addr = skb->nh.iph->daddr;
+               addr = ip_hdr(skb)->daddr;
        else
-               addr = skb->nh.iph->saddr;
+               addr = ip_hdr(skb)->saddr;
 
-       ttl = skb->nh.iph->ttl;
+       ttl = ip_hdr(skb)->ttl;
        /* use TTL as seen before forwarding */
        if (out && !skb->sk)
                ttl++;
 
 {
        const struct ipt_tos_info *info = matchinfo;
 
-       return (skb->nh.iph->tos == info->tos) ^ info->invert;
+       return (ip_hdr(skb)->tos == info->tos) ^ info->invert;
 }
 
 static struct xt_match tos_match = {
 
                 int offset, unsigned int protoff, int *hotdrop)
 {
        const struct ipt_ttl_info *info = matchinfo;
+       const u8 ttl = ip_hdr(skb)->ttl;
 
        switch (info->mode) {
                case IPT_TTL_EQ:
-                       return (skb->nh.iph->ttl == info->ttl);
+                       return (ttl == info->ttl);
                        break;
                case IPT_TTL_NE:
-                       return (!(skb->nh.iph->ttl == info->ttl));
+                       return (!(ttl == info->ttl));
                        break;
                case IPT_TTL_LT:
-                       return (skb->nh.iph->ttl < info->ttl);
+                       return (ttl < info->ttl);
                        break;
                case IPT_TTL_GT:
-                       return (skb->nh.iph->ttl > info->ttl);
+                       return (ttl > info->ttl);
                        break;
                default:
                        printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
 
                   int (*okfn)(struct sk_buff *))
 {
        unsigned int ret;
+       const struct iphdr *iph;
        u_int8_t tos;
        __be32 saddr, daddr;
        u_int32_t mark;
 
        /* Save things which could affect route */
        mark = (*pskb)->mark;
-       saddr = (*pskb)->nh.iph->saddr;
-       daddr = (*pskb)->nh.iph->daddr;
-       tos = (*pskb)->nh.iph->tos;
+       iph = ip_hdr(*pskb);
+       saddr = iph->saddr;
+       daddr = iph->daddr;
+       tos = iph->tos;
 
        ret = ipt_do_table(pskb, hook, in, out, &packet_mangler);
        /* Reroute for ANY change. */
-       if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
-           && ((*pskb)->nh.iph->saddr != saddr
-               || (*pskb)->nh.iph->daddr != daddr
-               || (*pskb)->mark != mark
-               || (*pskb)->nh.iph->tos != tos))
-               if (ip_route_me_harder(pskb, RTN_UNSPEC))
-                       ret = NF_DROP;
+       if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
+               iph = ip_hdr(*pskb);
+
+               if (iph->saddr != saddr ||
+                   iph->daddr != daddr ||
+                   (*pskb)->mark != mark ||
+                   iph->tos != tos)
+                       if (ip_route_me_harder(pskb, RTN_UNSPEC))
+                               ret = NF_DROP;
+       }
 
        return ret;
 }
 
        local_bh_enable();
 
        if (skb)
-               ip_send_check(skb->nh.iph);
+               ip_send_check(ip_hdr(skb));
 
        return skb;
 }
             u_int8_t *protonum)
 {
        /* Never happen */
-       if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
+       if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) {
                if (net_ratelimit()) {
                        printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n",
-                       (*pskb)->nh.iph->protocol, hooknum);
+                       ip_hdr(*pskb)->protocol, hooknum);
                }
                return -NF_DROP;
        }
 
        *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb);
-       *protonum = (*pskb)->nh.iph->protocol;
+       *protonum = ip_hdr(*pskb)->protocol;
 
        return NF_ACCEPT;
 }
 #endif
 
        /* Gather fragments. */
-       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
+       if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
                *pskb = nf_ct_ipv4_gather_frags(*pskb,
                                                hooknum == NF_IP_PRE_ROUTING ?
                                                IP_DEFRAG_CONNTRACK_IN :
 
        buf.port = port;
        addroff += dataoff;
 
-       if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
+       if (ip_hdr(*pskb)->protocol == IPPROTO_TCP) {
                if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
                                              addroff, sizeof(buf),
                                              (char *) &buf, sizeof(buf))) {
 
        unsigned char *data;
 
        BUG_ON(skb_is_nonlinear(skb));
-       data = (unsigned char *)skb->nh.iph + dataoff;
+       data = skb_network_header(skb) + dataoff;
 
        /* move post-replacement */
        memmove(data + match_offset + rep_len,
        }
 
        /* fix IP hdr checksum information */
-       skb->nh.iph->tot_len = htons(skb->len);
-       ip_send_check(skb->nh.iph);
+       ip_hdr(skb)->tot_len = htons(skb->len);
+       ip_send_check(ip_hdr(skb));
 }
 
 /* Unusual, but possible case. */
 
        SKB_LINEAR_ASSERT(*pskb);
 
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        tcph = (void *)iph + iph->ihl*4;
 
        oldlen = (*pskb)->len - iph->ihl*4;
        int datalen, oldlen;
 
        /* UDP helpers might accidentally mangle the wrong packet */
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
                               match_offset + match_len)
                return 0;
            !enlarge_skb(pskb, rep_len - match_len))
                return 0;
 
-       iph = (*pskb)->nh.iph;
+       iph = ip_hdr(*pskb);
        udph = (void *)iph + iph->ihl*4;
 
        oldlen = (*pskb)->len - iph->ihl*4;
 
 
        if (hooknum == NF_IP_LOCAL_OUT &&
            mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
-               warn_if_extra_mangle((*pskb)->nh.iph->daddr,
+               warn_if_extra_mangle(ip_hdr(*pskb)->daddr,
                                     mr->range[0].min_ip);
 
        return nf_nat_setup_info(ct, &mr->range[0], hooknum);
 
                          enum ip_conntrack_info ctinfo,
                          struct sk_buff **pskb)
 {
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
        u_int16_t udplen = ntohs(udph->len);
        u_int16_t paylen = udplen - sizeof(struct udphdr);
 {
        int dir = CTINFO2DIR(ctinfo);
        unsigned int ret;
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
 
        /* SNMP replies and originating SNMP traps get mangled */
 
 
        /* We never see fragments: conntrack defrags on pre-routing
           and local-out, and nf_nat_out protects post-routing. */
-       NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off
-                      & htons(IP_MF|IP_OFFSET)));
+       NF_CT_ASSERT(!(ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)));
 
        ct = nf_ct_get(*pskb, &ctinfo);
        /* Can't track?  It's not due to stress, or conntrack would
                /* Exception: ICMP redirect to new connection (not in
                   hash table yet).  We must not let this through, in
                   case we're doing NAT to the same network. */
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+               if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
                        struct icmphdr _hdr, *hp;
 
                        hp = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
        switch (ctinfo) {
        case IP_CT_RELATED:
        case IP_CT_RELATED+IP_CT_IS_REPLY:
-               if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
+               if (ip_hdr(*pskb)->protocol == IPPROTO_ICMP) {
                        if (!nf_nat_icmp_reply_translation(ct, ctinfo,
                                                           hooknum, pskb))
                                return NF_DROP;
          int (*okfn)(struct sk_buff *))
 {
        unsigned int ret;
-       __be32 daddr = (*pskb)->nh.iph->daddr;
+       __be32 daddr = ip_hdr(*pskb)->daddr;
 
        ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
        if (ret != NF_DROP && ret != NF_STOLEN &&
-           daddr != (*pskb)->nh.iph->daddr) {
+           daddr != ip_hdr(*pskb)->daddr) {
                dst_release((*pskb)->dst);
                (*pskb)->dst = NULL;
        }
 
        skb->dst = dst_clone(&rt->u.dst);
 
        skb_reset_network_header(skb);
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        skb_put(skb, length);
 
        skb->ip_summed = CHECKSUM_NONE;
        /* Copy the address. */
        if (sin) {
                sin->sin_family = AF_INET;
-               sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                sin->sin_port = 0;
                memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
        }
 
 static int ip_rt_bug(struct sk_buff *skb)
 {
        printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
-               NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
+               NIPQUAD(ip_hdr(skb)->saddr), NIPQUAD(ip_hdr(skb)->daddr),
                skb->dev ? skb->dev->name : "?");
        kfree_skb(skb);
        return 0;
                rcu_read_lock();
                if ((in_dev = __in_dev_get_rcu(dev)) != NULL) {
                        int our = ip_check_mc(in_dev, daddr, saddr,
-                               skb->nh.iph->protocol);
+                               ip_hdr(skb)->protocol);
                        if (our
 #ifdef CONFIG_IP_MROUTE
                            || (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
        skb_reset_network_header(skb);
 
        /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
-       skb->nh.iph->protocol = IPPROTO_ICMP;
+       ip_hdr(skb)->protocol = IPPROTO_ICMP;
        skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
        src = tb[RTA_SRC] ? nla_get_be32(tb[RTA_SRC]) : 0;
 
 
        NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT);
 
-       return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
+       return secure_tcp_syn_cookie(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
                                     skb->h.th->source, skb->h.th->dest,
                                     ntohl(skb->h.th->seq),
                                     jiffies / (HZ * 60), mssind);
 
        seq = ntohl(skb->h.th->seq)-1;
        mssind = check_tcp_syn_cookie(cookie,
-                                     skb->nh.iph->saddr, skb->nh.iph->daddr,
+                                     ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
                                      skb->h.th->source, skb->h.th->dest,
                                      seq, jiffies / (HZ * 60), COUNTER_TRIES);
 
        treq->snt_isn           = cookie;
        req->mss                = mss;
        ireq->rmt_port          = skb->h.th->source;
-       ireq->loc_addr          = skb->nh.iph->daddr;
-       ireq->rmt_addr          = skb->nh.iph->saddr;
+       ireq->loc_addr          = ip_hdr(skb)->daddr;
+       ireq->rmt_addr          = ip_hdr(skb)->saddr;
        ireq->opt               = NULL;
 
        /* We throwed the options of the initial SYN away, so we hope
 
 
 static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
 {
-       return secure_tcp_sequence_number(skb->nh.iph->daddr,
-                                         skb->nh.iph->saddr,
+       return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
+                                         ip_hdr(skb)->saddr,
                                          skb->h.th->dest,
                                          skb->h.th->source);
 }
 
 int tcp_v4_gso_send_check(struct sk_buff *skb)
 {
-       struct iphdr *iph;
+       const struct iphdr *iph;
        struct tcphdr *th;
 
        if (!pskb_may_pull(skb, sizeof(*th)))
                return -EINVAL;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        th = skb->h.th;
 
        th->check = 0;
        arg.iov[0].iov_len  = sizeof(rep.th);
 
 #ifdef CONFIG_TCP_MD5SIG
-       key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL;
+       key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
        if (key) {
                rep.opt[0] = htonl((TCPOPT_NOP << 24) |
                                   (TCPOPT_NOP << 16) |
 
                tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
                                        key,
-                                       skb->nh.iph->daddr,
-                                       skb->nh.iph->saddr,
+                                       ip_hdr(skb)->daddr,
+                                       ip_hdr(skb)->saddr,
                                        &rep.th, IPPROTO_TCP,
                                        arg.iov[0].iov_len);
        }
 #endif
-       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
-                                     skb->nh.iph->saddr, /* XXX */
+       arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
+                                     ip_hdr(skb)->saddr, /* XXX */
                                      sizeof(struct tcphdr), IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 
         * skb->sk) holds true, but we program defensively.
         */
        if (!twsk && skb->sk) {
-               key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr);
+               key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
        } else if (twsk && twsk->tw_md5_keylen) {
                tw_key.key = twsk->tw_md5_key;
                tw_key.keylen = twsk->tw_md5_keylen;
 
                tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
                                        key,
-                                       skb->nh.iph->daddr,
-                                       skb->nh.iph->saddr,
+                                       ip_hdr(skb)->daddr,
+                                       ip_hdr(skb)->saddr,
                                        &rep.th, IPPROTO_TCP,
                                        arg.iov[0].iov_len);
        }
 #endif
-       arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
-                                     skb->nh.iph->saddr, /* XXX */
+       arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
+                                     ip_hdr(skb)->saddr, /* XXX */
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 
         */
        __u8 *hash_location = NULL;
        struct tcp_md5sig_key *hash_expected;
-       struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        struct tcphdr *th = skb->h.th;
        int length = (th->doff << 2) - sizeof(struct tcphdr);
        int genhash;
        struct inet_request_sock *ireq;
        struct tcp_options_received tmp_opt;
        struct request_sock *req;
-       __be32 saddr = skb->nh.iph->saddr;
-       __be32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = ip_hdr(skb)->saddr;
+       __be32 daddr = ip_hdr(skb)->daddr;
        __u32 isn = TCP_SKB_CB(skb)->when;
        struct dst_entry *dst = NULL;
 #ifdef CONFIG_SYN_COOKIES
        newinet->opt          = ireq->opt;
        ireq->opt             = NULL;
        newinet->mc_index     = inet_iif(skb);
-       newinet->mc_ttl       = skb->nh.iph->ttl;
+       newinet->mc_ttl       = ip_hdr(skb)->ttl;
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
        if (newinet->opt)
                inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
 static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 {
        struct tcphdr *th = skb->h.th;
-       struct iphdr *iph = skb->nh.iph;
+       const struct iphdr *iph = ip_hdr(skb);
        struct sock *nsk;
        struct request_sock **prev;
        /* Find possible connection requests. */
        if (req)
                return tcp_check_req(sk, skb, req, prev);
 
-       nsk = inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
-                                     th->source, skb->nh.iph->daddr,
-                                     th->dest, inet_iif(skb));
+       nsk = inet_lookup_established(&tcp_hashinfo, iph->saddr, th->source,
+                                     iph->daddr, th->dest, inet_iif(skb));
 
        if (nsk) {
                if (nsk->sk_state != TCP_TIME_WAIT) {
 
 static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
 {
+       const struct iphdr *iph = ip_hdr(skb);
+
        if (skb->ip_summed == CHECKSUM_COMPLETE) {
-               if (!tcp_v4_check(skb->len, skb->nh.iph->saddr,
-                                 skb->nh.iph->daddr, skb->csum)) {
+               if (!tcp_v4_check(skb->len, iph->saddr,
+                                 iph->daddr, skb->csum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        return 0;
                }
        }
 
-       skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr,
+       skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
                                       skb->len, IPPROTO_TCP, 0);
 
        if (skb->len <= 76) {
 
 int tcp_v4_rcv(struct sk_buff *skb)
 {
+       const struct iphdr *iph;
        struct tcphdr *th;
        struct sock *sk;
        int ret;
                goto bad_packet;
 
        th = skb->h.th;
+       iph = ip_hdr(skb);
        TCP_SKB_CB(skb)->seq = ntohl(th->seq);
        TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                                    skb->len - th->doff * 4);
        TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
        TCP_SKB_CB(skb)->when    = 0;
-       TCP_SKB_CB(skb)->flags   = skb->nh.iph->tos;
+       TCP_SKB_CB(skb)->flags   = iph->tos;
        TCP_SKB_CB(skb)->sacked  = 0;
 
-       sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source,
-                          skb->nh.iph->daddr, th->dest,
-                          inet_iif(skb));
-
+       sk = __inet_lookup(&tcp_hashinfo, iph->saddr, th->source,
+                          iph->daddr, th->dest, inet_iif(skb));
        if (!sk)
                goto no_tcp_socket;
 
        switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
        case TCP_TW_SYN: {
                struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo,
-                                                       skb->nh.iph->daddr,
-                                                       th->dest,
+                                                       iph->daddr, th->dest,
                                                        inet_iif(skb));
                if (sk2) {
                        inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
 
        {
                sin->sin_family = AF_INET;
                sin->sin_port = skb->h.uh->source;
-               sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
        }
        if (inet->cmsg_flags)
                return 0;
 
        /* Now we can update and verify the packet length... */
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        iphlen = iph->ihl << 2;
        iph->tot_len = htons(ntohs(iph->tot_len) - len);
        if (skb->len < iphlen + len) {
 static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
                                 int proto)
 {
+       const struct iphdr *iph;
        int err;
 
        UDP_SKB_CB(skb)->partial_cov = 0;
                        return err;
        }
 
+       iph = ip_hdr(skb);
        if (uh->check == 0) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
-              if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
-                                     skb->len, proto, skb->csum))
+              if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
+                                     proto, skb->csum))
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
        }
        if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-               skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
-                                              skb->nh.iph->daddr,
+               skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
                                               skb->len, proto, 0);
        /* Probably, we should checksum udp header (it should be in cache
         * in any case) and data in tiny packets (< rx copybreak).
        struct udphdr *uh = skb->h.uh;
        unsigned short ulen;
        struct rtable *rt = (struct rtable*)skb->dst;
-       __be32 saddr = skb->nh.iph->saddr;
-       __be32 daddr = skb->nh.iph->daddr;
+       __be32 saddr = ip_hdr(skb)->saddr;
+       __be32 daddr = ip_hdr(skb)->daddr;
 
        /*
         *  Validate the packet.
 
        switch (nexthdr) {
        case IPPROTO_IPIP:
        case IPPROTO_IPV6:
-               *spi = skb->nh.iph->saddr;
+               *spi = ip_hdr(skb)->saddr;
                *seq = 0;
                return 0;
        }
 #ifdef CONFIG_NETFILTER
 static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
 {
-       struct iphdr *iph = skb->nh.iph;
-
        if (skb->dst == NULL) {
+               const struct iphdr *iph = ip_hdr(skb);
+
                if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
                                   skb->dev))
                        goto drop;
 
 int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 {
-       int err;
        __be32 spi, seq;
        struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
        struct xfrm_state *x;
        int xfrm_nr = 0;
        int decaps = 0;
+       int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
 
-       if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
+       if (err != 0)
                goto drop;
 
        do {
-               struct iphdr *iph = skb->nh.iph;
+               const struct iphdr *iph = ip_hdr(skb);
 
                if (xfrm_nr == XFRM_MAX_DEPTH)
                        goto drop;
                        break;
                }
 
-               if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) < 0)
+               err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
+               if (err < 0)
                        goto drop;
        } while (!err);
 
        } else {
 #ifdef CONFIG_NETFILTER
                __skb_push(skb, skb->data - skb_network_header(skb));
-               skb->nh.iph->tot_len = htons(skb->len);
-               ip_send_check(skb->nh.iph);
+               ip_hdr(skb)->tot_len = htons(skb->len);
+               ip_send_check(ip_hdr(skb));
 
                NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
                        xfrm4_rcv_encap_finish);
                return 0;
 #else
-               return -skb->nh.iph->protocol;
+               return -ip_hdr(skb)->protocol;
 #endif
        }
 
 
        struct iphdr *iph, *top_iph = NULL;
        int hdrlen, optlen;
 
-       iph = skb->nh.iph;
-       skb->h.ipiph = iph;
+       iph = ip_hdr(skb);
+       skb->h.raw = skb->nh.raw;
 
        hdrlen = 0;
        optlen = iph->ihl * 4 - sizeof(*iph);
 
        skb_push(skb, x->props.header_len + hdrlen);
        skb_reset_network_header(skb);
-       top_iph = skb->nh.iph;
+       top_iph = ip_hdr(skb);
        skb->h.raw += sizeof(*iph) - hdrlen;
 
        memmove(top_iph, iph, sizeof(*iph));
 
 static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        int phlen = 0;
        int optlen = 0;
        __u8 ph_nexthdr = 0, protocol = 0;
        skb->h.raw = skb->data + (phlen + optlen);
        skb->data = skb->h.raw;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        iph->ihl = (sizeof(*iph) + optlen) / 4;
        iph->tot_len = htons(skb->len + iph->ihl * 4);
        iph->daddr = x->sel.daddr.a4;
 
  */
 static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct iphdr *iph;
-       int ihl;
+       struct iphdr *iph = ip_hdr(skb);
+       int ihl = iph->ihl * 4;
 
-       iph = skb->nh.iph;
-       skb->h.ipiph = iph;
-
-       ihl = iph->ihl * 4;
+       skb->h.raw = skb->nh.raw;
        skb->h.raw += ihl;
 
        skb_push(skb, x->props.header_len);
                memmove(skb->h.raw, skb_network_header(skb), ihl);
                skb->nh.raw = skb->h.raw;
        }
-       skb->nh.iph->tot_len = htons(skb->len + ihl);
+       ip_hdr(skb)->tot_len = htons(skb->len + ihl);
        skb->h.raw = skb->data;
        return 0;
 }
 
 
 static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
 {
-       struct iphdr *outer_iph = skb->nh.iph;
+       struct iphdr *outer_iph = ip_hdr(skb);
        struct iphdr *inner_iph = skb->h.ipiph;
 
        if (INET_ECN_is_ce(outer_iph->tos))
        struct iphdr *iph, *top_iph;
        int flags;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        skb->h.ipiph = iph;
 
        skb_push(skb, x->props.header_len);
        skb_reset_network_header(skb);
-       top_iph = skb->nh.iph;
+       top_iph = ip_hdr(skb);
 
        top_iph->ihl = 5;
        top_iph->version = 4;
 
 static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        const unsigned char *old_mac;
        int err = -EINVAL;
 
            (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
        if (iph->protocol == IPPROTO_IPIP) {
                if (x->props.flags & XFRM_STATE_DECAP_DSCP)
                        ipv4_copy_dscp(iph, skb->h.ipiph);
 
 {
        int mtu, ret = 0;
        struct dst_entry *dst;
-       struct iphdr *iph = skb->nh.iph;
 
        if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
                goto out;
 
        IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
 
-       if (!(iph->frag_off & htons(IP_DF)) || skb->local_df)
+       if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
                goto out;
 
        dst = skb->dst;
 
 static void
 _decode_session4(struct sk_buff *skb, struct flowi *fl)
 {
-       struct iphdr *iph = skb->nh.iph;
+       struct iphdr *iph = ip_hdr(skb);
        u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
 
        memset(fl, 0, sizeof(struct flowi));
 
 
 static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct iphdr *iph;
+       struct iphdr *iph = ip_hdr(skb);
 
-       iph = skb->nh.iph;
        iph->tot_len = htons(skb->len);
        ip_send_check(iph);
 
 
                        struct inet_sock *inet = inet_sk(sk);
 
                        ipv6_addr_set(&sin->sin6_addr, 0, 0,
-                                     htonl(0xffff),
-                                     skb->nh.iph->saddr);
+                                     htonl(0xffff), ip_hdr(skb)->saddr);
                        if (inet->cmsg_flags)
                                ip_cmsg_recv(msg, skb);
                }
 
        skb2->dst = NULL;
        skb_pull(skb2, offset);
        skb_reset_network_header(skb2);
-       eiph = skb2->nh.iph;
+       eiph = ip_hdr(skb2);
 
        /* Try to guess incoming interface */
        memset(&fl, 0, sizeof(fl));
        __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK;
 
        if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
-               ipv4_change_dsfield(skb->nh.iph, INET_ECN_MASK, dsfield);
+               ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield);
 
        if (INET_ECN_is_ce(dsfield))
-               IP_ECN_set_ce(skb->nh.iph);
+               IP_ECN_set_ce(ip_hdr(skb));
 }
 
 static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t,
 ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
-       struct iphdr  *iph = skb->nh.iph;
+       struct iphdr  *iph = ip_hdr(skb);
        int encap_limit = -1;
        struct flowi fl;
        __u8 dsfield;
 
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
                goto out;
 
-       iph = skb->nh.iph;
+       iph = ip_hdr(skb);
 
        read_lock(&ipip6_lock);
        if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
         *      Push down and install the IPIP header.
         */
 
-       iph                     =       skb->nh.iph;
+       iph                     =       ip_hdr(skb);
        iph->version            =       4;
        iph->ihl                =       sizeof(struct iphdr)>>2;
        if (mtu > IPV6_MIN_MTU)
 
 
                if (skb->protocol == htons(ETH_P_IP))
                        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
-                                     htonl(0xffff), skb->nh.iph->saddr);
+                                     htonl(0xffff), ip_hdr(skb)->saddr);
                else {
                        ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
                        if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
 
                struct nf_conn *ct, enum ip_conntrack_info ctinfo)
 {
        struct nf_conntrack_expect *exp;
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        struct rtable *rt = (struct rtable *)(*pskb)->dst;
        struct in_device *in_dev;
        __be32 mask = 0;
 
                           const void *targinfo)
 {
        const struct xt_DSCP_info *dinfo = targinfo;
-       u_int8_t dscp = ipv4_get_dsfield((*pskb)->nh.iph) >> XT_DSCP_SHIFT;
+       u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT;
 
        if (dscp != dinfo->dscp) {
                if (!skb_make_writable(pskb, sizeof(struct iphdr)))
                        return NF_DROP;
 
-               ipv4_change_dsfield((*pskb)->nh.iph, (__u8)(~XT_DSCP_MASK),
+               ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK),
                                    dinfo->dscp << XT_DSCP_SHIFT);
 
        }
 
                  const struct xt_target *target,
                  const void *targinfo)
 {
-       struct iphdr *iph = (*pskb)->nh.iph;
+       struct iphdr *iph = ip_hdr(*pskb);
        __be16 newlen;
        int ret;
 
        if (ret < 0)
                return NF_DROP;
        if (ret > 0) {
-               iph = (*pskb)->nh.iph;
+               iph = ip_hdr(*pskb);
                newlen = htons(ntohs(iph->tot_len) + ret);
                nf_csum_replace2(&iph->check, iph->tot_len, newlen);
                iph->tot_len = newlen;
 
                 int *hotdrop)
 {
        const struct xt_dscp_info *info = matchinfo;
-       u_int8_t dscp = ipv4_get_dsfield(skb->nh.iph) >> XT_DSCP_SHIFT;
+       u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
 
        return (dscp == info->dscp) ^ !!info->invert;
 }
 
        switch (hinfo->family) {
        case AF_INET:
                if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
-                       dst->addr.ip.dst = skb->nh.iph->daddr;
+                       dst->addr.ip.dst = ip_hdr(skb)->daddr;
                if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
-                       dst->addr.ip.src = skb->nh.iph->saddr;
+                       dst->addr.ip.src = ip_hdr(skb)->saddr;
 
                if (!(hinfo->cfg.mode &
                      (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
                        return 0;
-               nexthdr = skb->nh.iph->protocol;
+               nexthdr = ip_hdr(skb)->protocol;
                break;
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
        case AF_INET6:
 
       int *hotdrop)
 {
        const struct xt_length_info *info = matchinfo;
-       u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
+       u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
 
        return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
 }
 
        const struct xt_pkttype_info *info = matchinfo;
 
        if (skb->pkt_type == PACKET_LOOPBACK)
-               type = (MULTICAST(skb->nh.iph->daddr)
+               type = (MULTICAST(ip_hdr(skb)->daddr)
                        ? PACKET_MULTICAST
                        : PACKET_BROADCAST);
        else
 
                /* fill in the specifics */
                candidate->addr.sin_family      = AF_INET;
                candidate->addr.sin_port        = x_port;
-               candidate->addr.sin_addr.s_addr = pkt->nh.iph->saddr;
+               candidate->addr.sin_addr.s_addr = ip_hdr(pkt)->saddr;
                candidate->in_epoch             = x_epoch;
                candidate->out_epoch            = x_epoch;
                candidate->in_clientflag        = RXRPC_CLIENT_INITIATED;
 
                        return;
                }
 
-               addr = pkt->nh.iph->saddr;
+               addr = ip_hdr(pkt)->saddr;
                port = pkt->h.uh->source;
 
                _net("Rx Received UDP packet from %08x:%04hu",
        memset(&sin,0,sizeof(sin));
        sin.sin_family          = AF_INET;
        sin.sin_port            = msg->pkt->h.uh->source;
-       sin.sin_addr.s_addr     = msg->pkt->nh.iph->saddr;
+       sin.sin_addr.s_addr     = ip_hdr(msg->pkt)->saddr;
 
        msghdr.msg_name         = &sin;
        msghdr.msg_namelen      = sizeof(sin);
 
 #if RSVP_DST_LEN == 4
        struct ipv6hdr *nhptr = skb->nh.ipv6h;
 #else
-       struct iphdr *nhptr = skb->nh.iph;
+       struct iphdr *nhptr = ip_hdr(skb);
 #endif
 
 restart:
 
                        }
                        D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow);
                        /* remove any LL header somebody else has attached */
-                       skb_pull(skb,(char *) skb->nh.iph-(char *) skb->data);
+                       skb_pull(skb, skb_network_offset(skb));
                        if (skb_headroom(skb) < flow->hdr_len) {
                                struct sk_buff *new;
 
                                skb = new;
                        }
                        D2PRINTK("sch_atm_dequeue: ip %p, data %p\n",
-                           skb->nh.iph,skb->data);
+                                skb_network_header(skb), skb->data);
                        ATM_SKB(skb)->vcc = flow->vcc;
                        memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
                            flow->hdr_len);
 
                /* FIXME: Safe with non-linear skbs? --RR */
                switch (skb->protocol) {
                        case __constant_htons(ETH_P_IP):
-                               skb->tc_index = ipv4_get_dsfield(skb->nh.iph)
+                               skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
                                        & ~INET_ECN_MASK;
                                break;
                        case __constant_htons(ETH_P_IPV6):
 
        switch (skb->protocol) {
                case __constant_htons(ETH_P_IP):
-                       ipv4_change_dsfield(skb->nh.iph, p->mask[index],
+                       ipv4_change_dsfield(ip_hdr(skb), p->mask[index],
                                            p->value[index]);
                        break;
                case __constant_htons(ETH_P_IPV6):
 
        switch (skb->protocol) {
        case __constant_htons(ETH_P_IP):
        {
-               struct iphdr *iph = skb->nh.iph;
+               const struct iphdr *iph = ip_hdr(skb);
                h = iph->daddr;
                h2 = iph->saddr^iph->protocol;
                if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
 
        if (skb->len < sizeof(struct sctp_chunkhdr))
                goto discard_it;
 
-       family = ipver2af(skb->nh.iph->version);
+       family = ipver2af(ip_hdr(skb)->version);
        af = sctp_get_af_specific(family);
        if (unlikely(!af))
                goto discard_it;
 
 
                /* Map ipv4 address into v4-mapped-on-v6 address. */
                if (sctp_sk(skb->sk)->v4mapped &&
-                   skb->nh.iph->version == 4) {
+                   ip_hdr(skb)->version == 4) {
                        sctp_v4_map_v6((union sctp_addr *)sin6);
-                       sin6->sin6_addr.s6_addr32[3] = skb->nh.iph->saddr;
+                       sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr;
                        return;
                }
 
 
        sh = (struct sctphdr *) skb->h.raw;
        if (is_saddr) {
                *port  = sh->source;
-               from = &skb->nh.iph->saddr;
+               from = &ip_hdr(skb)->saddr;
        } else {
                *port = sh->dest;
-               from = &skb->nh.iph->daddr;
+               from = &ip_hdr(skb)->daddr;
        }
        memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr));
 }
 /* Was this packet marked by Explicit Congestion Notification? */
 static int sctp_v4_is_ce(const struct sk_buff *skb)
 {
-       return INET_ECN_is_ce(skb->nh.iph->tos);
+       return INET_ECN_is_ce(ip_hdr(skb)->tos);
 }
 
 /* Create and initialize a new sk for the socket returned by accept(). */
                sin = (struct sockaddr_in *)msgname;
                sh = (struct sctphdr *)skb->h.raw;
                sin->sin_port = sh->source;
-               sin->sin_addr.s_addr = skb->nh.iph->saddr;
+               sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
        }
 }
 
 
        struct sctp_af *af;
        int iif = 0;
 
-       af = sctp_get_af_specific(ipver2af(chunk->skb->nh.iph->version));
+       af = sctp_get_af_specific(ipver2af(ip_hdr(chunk->skb)->version));
        if (af)
                iif = af->skb_iif(chunk->skb);
 
        asoc->temp = 1;
        skb = chunk->skb;
        /* Create an entry for the source address of the packet.  */
-       af = sctp_get_af_specific(ipver2af(skb->nh.iph->version));
+       af = sctp_get_af_specific(ipver2af(ip_hdr(skb)->version));
        if (unlikely(!af))
                goto fail;
        af->from_skb(&asoc->c.peer_addr, skb, 1);
 
                chunk->ecn_ce_done = 1;
 
                af = sctp_get_af_specific(
-                       ipver2af(chunk->skb->nh.iph->version));
+                       ipver2af(ip_hdr(chunk->skb)->version));
 
                if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) {
                        /* Do real work as sideffect. */