This adds support for the old NAT Traversal packet format described in draft-ietf-ipsec-udp-encaps-00/01. More recent Internet Drafts define an improved format, but some ipsec implementations still don't support that. Andreas Gruenbacher , SUSE Labs, 2004. Index: linux-2.6.5/net/ipv4/udp.c =================================================================== --- linux-2.6.5.orig/net/ipv4/udp.c +++ linux-2.6.5/net/ipv4/udp.c @@ -975,6 +975,7 @@ static int udp_encap_rcv(struct sock * s /* Must be an IKE packet.. pass it through */ return 1; + decaps: /* At this point we are sure that this is an ESPinUDP packet, * so we need to remove 'len' bytes from the packet (the UDP * header and optional ESP marker bytes) and then modify the @@ -1002,6 +1003,20 @@ static int udp_encap_rcv(struct sock * s /* and let the caller know to send this into the ESP processor... */ return -1; + case UDP_ENCAP_ESPINUDP_NON_IKE: + /* Check if this is a keepalive packet. If so, eat it. */ + if (len == 1 && udpdata[0] == 0xff) { + return 0; + } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && + udpdata32[0] == 0 && udpdata32[1] == 0) { + + /* ESP Packet with Non-IKE marker */ + len = sizeof(struct udphdr) + 2 * sizeof(u32); + goto decaps; + } else + /* Must be an IKE packet.. pass it through */ + return 1; + default: if (net_ratelimit()) printk(KERN_INFO "udp_encap_rcv(): Unhandled UDP encap type: %u\n", Index: linux-2.6.5/net/ipv4/esp4.c =================================================================== --- linux-2.6.5.orig/net/ipv4/esp4.c +++ linux-2.6.5/net/ipv4/esp4.c @@ -31,6 +31,7 @@ int esp_output(struct sk_buff *skb) struct esp_data *esp; struct sk_buff *trailer; struct udphdr *uh = NULL; + u32 *udpdata32; struct xfrm_encap_tmpl *encap = NULL; int blksize; int clen; @@ -97,6 +98,13 @@ int esp_output(struct sk_buff *skb) esph = (struct ip_esp_hdr*)(uh+1); top_iph->protocol = IPPROTO_UDP; break; + case UDP_ENCAP_ESPINUDP_NON_IKE: + uh = (struct udphdr*) esph; + udpdata32 = (u32*)(uh+1); + udpdata32[0] = udpdata32[1] = 0; + esph = (struct ip_esp_hdr*)(udpdata32+2); + top_iph->protocol = IPPROTO_UDP; + break; default: printk(KERN_INFO "esp_output(): Unhandled encap: %u\n", @@ -132,6 +140,13 @@ int esp_output(struct sk_buff *skb) esph = (struct ip_esp_hdr*)(uh+1); top_iph->protocol = IPPROTO_UDP; break; + case UDP_ENCAP_ESPINUDP_NON_IKE: + uh = (struct udphdr*) esph; + udpdata32 = (u32*)(uh+1); + udpdata32[0] = udpdata32[1] = 0; + esph = (struct ip_esp_hdr*)(udpdata32+2); + top_iph->protocol = IPPROTO_UDP; + break; default: printk(KERN_INFO "esp_output(): Unhandled encap: %u\n", @@ -294,6 +309,7 @@ int esp_input(struct xfrm_state *x, stru switch (decap->decap_type) { case UDP_ENCAP_ESPINUDP: + case UDP_ENCAP_ESPINUDP_NON_IKE: if ((void*)uh == (void*)esph) { printk(KERN_DEBUG @@ -354,6 +370,7 @@ int esp_post_input(struct xfrm_state *x, switch (encap->encap_type) { case UDP_ENCAP_ESPINUDP: + case UDP_ENCAP_ESPINUDP_NON_IKE: /* * 1) if the NAT-T peer's IP or port changed then * advertize the change to the keying daemon. @@ -534,6 +551,9 @@ int esp_init_state(struct xfrm_state *x, case UDP_ENCAP_ESPINUDP: x->props.header_len += sizeof(struct udphdr); break; + case UDP_ENCAP_ESPINUDP_NON_IKE: + x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32); + break; default: printk (KERN_INFO "esp_init_state(): Unhandled encap type: %u\n", Index: linux-2.6.5/include/linux/udp.h =================================================================== --- linux-2.6.5.orig/include/linux/udp.h +++ linux-2.6.5/include/linux/udp.h @@ -31,6 +31,7 @@ struct udphdr { #define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */ /* UDP encapsulation types */ +#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ #define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ #ifdef __KERNEL__