__u16                   srcrt;
        __u16                   dst1;
        __u16                   lastopt;
+       __u32                   nhoff;
 };
 
 #define IP6CB(skb)     ((struct inet6_skb_parm*)((skb)->cb))
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 struct inet6_protocol 
 {
-       int     (*handler)(struct sk_buff **skb, unsigned int *nhoffp);
+       int     (*handler)(struct sk_buff **skb);
 
        void    (*err_handler)(struct sk_buff *skb,
                               struct inet6_skb_parm *opt,
 
 };
 
 struct xfrm6_tunnel {
-       int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp);
+       int (*handler)(struct sk_buff **pskb);
        void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
                            int type, int code, int offset, __u32 info);
 };
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
-extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv(struct sk_buff **pskb);
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
 extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
 
        return 0;
 }
 
-static int dccp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int dccp_v6_rcv(struct sk_buff **pskb)
 {
        const struct dccp_hdr *dh;
        struct sk_buff *skb = *pskb;
 
        {-1,                    NULL}
 };
 
-static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_destopt_rcv(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp;
        struct inet6_skb_parm *opt = IP6CB(skb);
 
        if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
                skb->h.raw += ((skb->h.raw[1]+1)<<3);
-               *nhoffp = opt->dst1;
+               opt->nhoff = opt->dst1;
                return 1;
        }
 
   NONE header. No data in packet.
  ********************************/
 
-static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_nodata_rcv(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp;
 
   Routing header.
  ********************************/
 
-static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_rthdr_rcv(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp;
        struct inet6_skb_parm *opt = IP6CB(skb);
                skb->h.raw += (hdr->hdrlen + 1) << 3;
                opt->dst0 = opt->dst1;
                opt->dst1 = 0;
-               *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
+               opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
                return 1;
        }
 
 
 int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
 {
-       IP6CB(skb)->hop = sizeof(struct ipv6hdr);
-       if (ip6_parse_tlv(tlvprochopopt_lst, skb))
+       struct inet6_skb_parm *opt = IP6CB(skb);
+
+       opt->hop = sizeof(struct ipv6hdr);
+       if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
+               skb->h.raw += (skb->h.raw[1]+1)<<3;
+               opt->nhoff = sizeof(struct ipv6hdr);
                return sizeof(struct ipv6hdr);
+       }
        return -1;
 }
 
 
 static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
 #define icmpv6_socket  __get_cpu_var(__icmpv6_socket)
 
-static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+static int icmpv6_rcv(struct sk_buff **pskb);
 
 static struct inet6_protocol icmpv6_protocol = {
        .handler        =       icmpv6_rcv,
  *     Handle icmp messages
  */
 
-static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int icmpv6_rcv(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct net_device *dev = skb->dev;
 
        if (hdr->version != 6)
                goto err;
 
+       skb->h.raw = (u8 *)(hdr + 1);
+       IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
+
        pkt_len = ntohs(hdr->payload_len);
 
        /* pkt_len may be zero if Jumbo payload option is present */
        }
 
        if (hdr->nexthdr == NEXTHDR_HOP) {
-               skb->h.raw = (u8*)(hdr+1);
-               if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) {
+               if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
                        IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
                        return 0;
                }
        int nexthdr;
        u8 hash;
 
-       skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
-
        /*
         *      Parse extension headers
         */
 
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       nhoff = offsetof(struct ipv6hdr, nexthdr);
-
-       /* Skip hop-by-hop options, they are already parsed. */
-       if (nexthdr == NEXTHDR_HOP) {
-               nhoff = sizeof(struct ipv6hdr);
-               nexthdr = skb->h.raw[0];
-               skb->h.raw += (skb->h.raw[1]+1)<<3;
-       }
-
        rcu_read_lock();
 resubmit:
        if (!pskb_pull(skb, skb->h.raw - skb->data))
                goto discard;
+       nhoff = IP6CB(skb)->nhoff;
        nexthdr = skb->nh.raw[nhoff];
 
        raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
                    !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 
                        goto discard;
                
-               ret = ipprot->handler(&skb, &nhoff);
+               ret = ipprot->handler(&skb);
                if (ret > 0)
                        goto resubmit;
                else if (ret == 0)
 
  **/
 
 static int 
-ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+ip6ip6_rcv(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct ipv6hdr *ipv6h;
 
  *     the last and the first frames arrived and all the bits are here.
  */
 static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
-                         unsigned int *nhoffp,
                          struct net_device *dev)
 {
        struct sk_buff *fp, *head = fq->fragments;
        head->dev = dev;
        skb_set_timestamp(head, &fq->stamp);
        head->nh.ipv6h->payload_len = htons(payload_len);
+       IP6CB(head)->nhoff = nhoff;
 
        *skb_in = head;
 
 
        IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
        fq->fragments = NULL;
-       *nhoffp = nhoff;
        return 1;
 
 out_oversize:
        return -1;
 }
 
-static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_frag_rcv(struct sk_buff **skbp)
 {
        struct sk_buff *skb = *skbp; 
        struct net_device *dev = skb->dev;
                skb->h.raw += sizeof(struct frag_hdr);
                IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
 
-               *nhoffp = (u8*)fhdr - skb->nh.raw;
+               IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw;
                return 1;
        }
 
 
                spin_lock(&fq->lock);
 
-               ip6_frag_queue(fq, skb, fhdr, *nhoffp);
+               ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
 
                if (fq->last_in == (FIRST_IN|LAST_IN) &&
                    fq->meat == fq->len)
-                       ret = ip6_frag_reasm(fq, skbp, nhoffp, dev);
+                       ret = ip6_frag_reasm(fq, skbp, dev);
 
                spin_unlock(&fq->lock);
                fq_put(fq, NULL);
 
        return 0;
 }
 
-static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int tcp_v6_rcv(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct tcphdr *th;      
 
        read_unlock(&udp_hash_lock);
 }
 
-static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int udpv6_rcv(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct sock *sk;
 
                IP6_ECN_set_ce(inner_iph);
 }
 
-int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
 {
        struct sk_buff *skb = *pskb;
        int err;
        int nexthdr;
        unsigned int nhoff;
 
-       nhoff = *nhoffp;
+       nhoff = IP6CB(skb)->nhoff;
        nexthdr = skb->nh.raw[nhoff];
 
        seq = 0;
 
 EXPORT_SYMBOL(xfrm6_rcv_spi);
 
-int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+int xfrm6_rcv(struct sk_buff **pskb)
 {
-       return xfrm6_rcv_spi(pskb, nhoffp, 0);
+       return xfrm6_rcv_spi(pskb, 0);
 }
 
 
 EXPORT_SYMBOL(xfrm6_tunnel_deregister);
 
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
 {
        struct sk_buff *skb = *pskb;
        struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
        u32 spi;
 
        /* device-like_ip6ip6_handler() */
-       if (handler && handler->handler(pskb, nhoffp) == 0)
+       if (handler && handler->handler(pskb) == 0)
                return 0;
 
        spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
-       return xfrm6_rcv_spi(pskb, nhoffp, spi);
+       return xfrm6_rcv_spi(pskb, spi);
 }
 
 static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        .flags         = SCTP_PROTOSW_FLAG,
 };
 
-static int sctp6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int sctp6_rcv(struct sk_buff **pskb)
 {
        return sctp_rcv(*pskb) ? -1 : 0;
 }