diff -upN reference/net/ipv4/esp4.c current/net/ipv4/esp4.c
--- reference/net/ipv4/esp4.c	2004-04-30 11:23:58.000000000 -0700
+++ current/net/ipv4/esp4.c	2004-05-02 08:41:26.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/random.h>
 #include <net/icmp.h>
 #include <net/udp.h>
+#include <asm/checksum.h>
 
 #define MAX_SG_ONSTACK 4
 
@@ -343,7 +344,15 @@ int esp_input(struct xfrm_state *x, stru
 		skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
 		skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
 		memcpy(skb->nh.raw, workbuf, iph->ihl*4);
-		skb->nh.iph->tot_len = htons(skb->len);
+		iph = skb->nh.iph;
+		iph->tot_len = htons(skb->len + (skb->data - skb->nh.raw));
+		iph->check = 0;
+		iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
+		{
+			unsigned char *oldmac = skb->mac.raw;
+			skb->mac.raw += encap_len + sizeof(struct ip_esp_hdr) + esp -> conf.ivlen;
+			memmove(skb->mac.raw, oldmac, skb->nh.raw - skb->mac.raw);
+		}
 	}
 
 	return 0;
diff -upN reference/net/ipv4/xfrm4_input.c current/net/ipv4/xfrm4_input.c
--- reference/net/ipv4/xfrm4_input.c	2004-03-11 14:35:49.000000000 -0800
+++ current/net/ipv4/xfrm4_input.c	2004-05-02 08:41:26.000000000 -0700
@@ -95,6 +95,19 @@ int xfrm4_rcv_encap(struct sk_buff *skb,
 		iph = skb->nh.iph;
 
 		if (x->props.mode) {
+			if (iph->protocol == 0xfe) {
+				skb_push(skb, skb->data - skb->nh.raw);
+				if (!(skb->dev->flags&IFF_LOOPBACK)){
+					dst_release(skb->dst);
+					skb->dst = NULL;
+				}
+				if (skb->sp) {
+					secpath_put(skb->sp);
+					skb->sp = NULL;
+				}
+			netif_rx(skb);
+			return 0;
+			}
 			if (iph->protocol != IPPROTO_IPIP)
 				goto drop;
 			if (!pskb_may_pull(skb, sizeof(struct iphdr)))