memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
        }
 
-       ip_send_check(top_iph);
-
        err = 0;
 
 error:
 
 static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err;
-       struct iphdr *top_iph;
        struct ip_esp_hdr *esph;
        struct crypto_blkcipher *tfm;
        struct blkcipher_desc desc;
        pskb_put(skb, trailer, clen - skb->len);
 
        skb_push(skb, -skb_network_offset(skb));
-       top_iph = ip_hdr(skb);
        esph = ip_esp_hdr(skb);
-       top_iph->tot_len = htons(skb->len + alen);
        *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
        *skb_mac_header(skb) = IPPROTO_ESP;
 
                uh = (struct udphdr *)esph;
                uh->source = encap->encap_sport;
                uh->dest = encap->encap_dport;
-               uh->len = htons(skb->len + alen - top_iph->ihl*4);
+               uh->len = htons(skb->len + alen - skb_transport_offset(skb));
                uh->check = 0;
 
                switch (encap->encap_type) {
 unlock:
        spin_unlock_bh(&x->lock);
 
-       ip_send_check(top_iph);
-
 error:
        return err;
 }
 
 static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
 {
        struct ipcomp_data *ipcd = x->data;
-       const int ihlen = skb_transport_offset(skb);
-       const int plen = skb->len - ihlen;
+       const int plen = skb->len;
        int dlen = IPCOMP_SCRATCH_SIZE;
-       u8 *start = skb_transport_header(skb);
+       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);
        memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
        put_cpu();
 
-       pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr));
+       pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
        return 0;
 
 out:
        int err;
        struct ip_comp_hdr *ipch;
        struct ipcomp_data *ipcd = x->data;
-       int hdr_len = 0;
-       struct iphdr *iph = ip_hdr(skb);
 
-       skb_push(skb, -skb_network_offset(skb));
-       iph->tot_len = htons(skb->len);
-       hdr_len = iph->ihl * 4;
-       if ((skb->len - hdr_len) < ipcd->threshold) {
+       if (skb->len < ipcd->threshold) {
                /* Don't bother compressing */
                goto out_ok;
        }
                goto out_ok;
 
        err = ipcomp_compress(x, skb);
-       iph = ip_hdr(skb);
 
        if (err) {
                goto out_ok;
        }
 
        /* Install ipcomp header, convert into ipcomp datagram. */
-       iph->tot_len = htons(skb->len);
        ipch = ip_comp_hdr(skb);
        ipch->nexthdr = *skb_mac_header(skb);
        ipch->flags = 0;
        ipch->cpi = htons((u16 )ntohl(x->id.spi));
        *skb_mac_header(skb) = IPPROTO_COMP;
-       ip_send_check(iph);
-       return 0;
-
 out_ok:
-       if (x->props.mode == XFRM_MODE_TUNNEL)
-               ip_send_check(iph);
+       skb_push(skb, -skb_network_offset(skb));
        return 0;
 }
 
 
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- * The following fields in it shall be filled in by x->type->output:
- *      tot_len
- *      check
  */
 static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 
 
 /* Add encapsulation header.
  *
- * The top IP header will be constructed per RFC 2401.  The following fields
- * in it shall be filled in by x->type->output:
- *      tot_len
- *      check
+ * The top IP header will be constructed per RFC 2401.
  */
 static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 
 {
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
+       struct iphdr *iph;
        int err;
 
        if (x->props.mode == XFRM_MODE_TUNNEL) {
        if (err)
                goto error_nolock;
 
+       iph = ip_hdr(skb);
+       iph->tot_len = htons(skb->len);
+       ip_send_check(iph);
+
        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
        err = 0;
 
 
 
 static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct iphdr *iph = ip_hdr(skb);
-
        skb_push(skb, -skb_network_offset(skb));
-       iph->tot_len = htons(skb->len);
-       ip_send_check(iph);
-
        return 0;
 }
 
 
 static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err;
-       struct ipv6hdr *top_iph;
        struct ip_esp_hdr *esph;
        struct crypto_blkcipher *tfm;
        struct blkcipher_desc desc;
        pskb_put(skb, trailer, clen - skb->len);
 
        skb_push(skb, -skb_network_offset(skb));
-       top_iph = ipv6_hdr(skb);
        esph = ip_esp_hdr(skb);
-       top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
        *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
        *skb_mac_header(skb) = IPPROTO_ESP;
 
 
 static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err;
-       struct ipv6hdr *top_iph;
        struct ip_comp_hdr *ipch;
        struct ipcomp_data *ipcd = x->data;
        int plen, dlen;
        u8 *start, *scratch;
        struct crypto_comp *tfm;
        int cpu;
-       int hdr_len;
-
-       skb_push(skb, -skb_network_offset(skb));
-       hdr_len = skb_transport_offset(skb);
 
        /* check whether datagram len is larger than threshold */
-       if ((skb->len - hdr_len) < ipcd->threshold) {
+       if (skb->len < ipcd->threshold) {
                goto out_ok;
        }
 
                goto out_ok;
 
        /* compression */
-       plen = skb->len - hdr_len;
+       plen = skb->len;
        dlen = IPCOMP_SCRATCH_SIZE;
-       start = skb_transport_header(skb);
+       start = skb->data;
 
        cpu = get_cpu();
        scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
        }
        memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
        put_cpu();
-       pskb_trim(skb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
+       pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
 
        /* insert ipcomp header and replace datagram */
-       top_iph = ipv6_hdr(skb);
-
-       top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-
        ipch = ip_comp_hdr(skb);
        ipch->nexthdr = *skb_mac_header(skb);
        ipch->flags = 0;
        *skb_mac_header(skb) = IPPROTO_COMP;
 
 out_ok:
+       skb_push(skb, -skb_network_offset(skb));
+
        return 0;
 }
 
 
 
        skb_push(skb, -skb_network_offset(skb));
        iph = ipv6_hdr(skb);
-       iph->payload_len = htons(skb->len - sizeof(*iph));
 
        nexthdr = *skb_mac_header(skb);
        *skb_mac_header(skb) = IPPROTO_DSTOPTS;
 
        skb_push(skb, -skb_network_offset(skb));
        iph = ipv6_hdr(skb);
-       iph->payload_len = htons(skb->len - sizeof(*iph));
 
        nexthdr = *skb_mac_header(skb);
        *skb_mac_header(skb) = IPPROTO_ROUTING;
 
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- * The following fields in it shall be filled in by x->type->output:
- *     payload_len
  */
 static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 
 
 /* Add encapsulation header.
  *
- * The top IP header will be constructed per RFC 2401.  The following fields
- * in it shall be filled in by x->type->output:
- *     payload_len
+ * The top IP header will be constructed per RFC 2401.
  */
 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 
 {
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
+       struct ipv6hdr *iph;
        int err;
 
        if (x->props.mode == XFRM_MODE_TUNNEL) {
        if (err)
                goto error_nolock;
 
+       iph = ipv6_hdr(skb);
+       iph->payload_len = htons(skb->len - sizeof(*iph));
+
        IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
        err = 0;
 
 
 
 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct ipv6hdr *top_iph;
-
        skb_push(skb, -skb_network_offset(skb));
-       top_iph = ipv6_hdr(skb);
-       top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-
        return 0;
 }