*** /vol/sony/linux-2.6.16/include/net/xfrmudp.h	1969-12-31 19:00:00.000000000 -0500
--- include/net/xfrmudp.h	2006-05-12 17:18:27.000000000 -0400
***************
*** 0 ****
--- 1,10 ----
+ /*
+  * pointer to function for type that xfrm4_input wants, to permit
+  * decoupling of XFRM from udp.c
+  */
+ #define HAVE_XFRM4_UDP_REGISTER
+ 
+ typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);
+ extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
+ 				      , xfrm4_rcv_encap_t *oldfunc);
+ extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);
*** /vol/sony/linux-2.6.16/net/ipv4/Kconfig	2006-03-20 00:53:29.000000000 -0500
--- net/ipv4/Kconfig	2006-05-12 17:18:27.000000000 -0400
***************
*** 367,372 ****
--- 367,378 ----
  
  	  If unsure, say N.
  
+ config IPSEC_NAT_TRAVERSAL
+ 	bool "IPSEC NAT-Traversal (KLIPS compatible)"
+ 	depends on INET
+ 	---help---
+           Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.
+ 
  config INET_AH
  	tristate "IP: AH transformation"
  	select XFRM
*** /vol/sony/linux-2.6.16/net/ipv4/udp.c	2006-03-20 00:53:29.000000000 -0500
--- net/ipv4/udp.c	2006-05-12 17:18:27.000000000 -0400
***************
*** 109,119 ****
--- 109,122 ----
  #include <net/inet_common.h>
  #include <net/checksum.h>
  #include <net/xfrm.h>
+ #include <net/xfrmudp.h>
  
  /*
   *	Snmp MIB for the UDP layer
   */
  
+ static xfrm4_rcv_encap_t xfrm4_rcv_encap_func;
+ 
  DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly;
  
  struct hlist_head udp_hash[UDP_HTABLE_SIZE];
***************
*** 497,502 ****
--- 500,507 ----
  	int err;
  	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
  
+ 	memset(&ipc, 0, sizeof(ipc));
+ 
  	if (len > 0xFFFF)
  		return -EMSGSIZE;
  
***************
*** 658,663 ****
--- 663,672 ----
  	ip_rt_put(rt);
  	if (free)
  		kfree(ipc.opt);
+ 	if(ipc.sp) {
+ 		secpath_put(ipc.sp);
+ 		ipc.sp=NULL;
+ 	}
  	if (!err) {
  		UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS);
  		return len;
***************
*** 882,887 ****
--- 891,932 ----
  	sk_common_release(sk);
  }
  
+ #if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+ 
+ /* if XFRM isn't a module, then register it directly. */
+ #if 0 && !defined(CONFIG_XFRM_MODULE) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+ static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = xfrm4_rcv_encap;
+ #else
+ static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;
+ #endif
+ 
+ int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
+ 			       , xfrm4_rcv_encap_t *oldfunc)
+ {
+   if(oldfunc != NULL) {
+     *oldfunc = xfrm4_rcv_encap_func;
+   }
+ 
+ #if 0
+   if(xfrm4_rcv_encap_func != NULL)
+     return -1;
+ #endif
+ 
+   xfrm4_rcv_encap_func = func;
+   return 0;
+ }
+ 
+ int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)
+ {
+   if(xfrm4_rcv_encap_func != func)
+     return -1;
+ 
+   xfrm4_rcv_encap_func = NULL;
+   return 0;
+ }
+ #endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */
+ 
+ 
  /* return:
   * 	1  if the the UDP system should process it
   *	0  if we should drop this packet
***************
*** 889,897 ****
   */
  static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
  {
! #ifndef CONFIG_XFRM
  	return 1; 
! #else
  	struct udp_sock *up = udp_sk(sk);
    	struct udphdr *uh = skb->h.uh;
  	struct iphdr *iph;
--- 934,942 ----
   */
  static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
  {
! #if !defined(CONFIG_XFRM) && !defined(CONFIG_IPSEC_NAT_TRAVERSAL)
  	return 1; 
! #else /* either CONFIG_XFRM or CONFIG_IPSEC_NAT_TRAVERSAL */
  	struct udp_sock *up = udp_sk(sk);
    	struct udphdr *uh = skb->h.uh;
  	struct iphdr *iph;
***************
*** 903,913 ****
  
  	/* if we're overly short, let UDP handle it */
  	if (udpdata > skb->tail)
! 		return 1;
  
  	/* if this is not encapsulated socket, then just return now */
  	if (!encap_type)
! 		return 1;
  
  	len = skb->tail - udpdata;
  
--- 948,958 ----
  
  	/* if we're overly short, let UDP handle it */
  	if (udpdata > skb->tail)
! 		return 2;
  
  	/* if this is not encapsulated socket, then just return now */
  	if (!encap_type)
! 		return 3;
  
  	len = skb->tail - udpdata;
  
***************
*** 922,928 ****
  			len = sizeof(struct udphdr);
  		} else
  			/* Must be an IKE packet.. pass it through */
! 			return 1;
  		break;
  	case UDP_ENCAP_ESPINUDP_NON_IKE:
  		/* Check if this is a keepalive packet.  If so, eat it. */
--- 967,973 ----
  			len = sizeof(struct udphdr);
  		} else
  			/* Must be an IKE packet.. pass it through */
! 			return 4;
  		break;
  	case UDP_ENCAP_ESPINUDP_NON_IKE:
  		/* Check if this is a keepalive packet.  If so, eat it. */
***************
*** 935,941 ****
  			len = sizeof(struct udphdr) + 2 * sizeof(u32);
  		} else
  			/* Must be an IKE packet.. pass it through */
! 			return 1;
  		break;
  	}
  
--- 980,986 ----
  			len = sizeof(struct udphdr) + 2 * sizeof(u32);
  		} else
  			/* Must be an IKE packet.. pass it through */
! 			return 5;
  		break;
  	}
  
***************
*** 1010,1018 ****
  			return 0;
  		}
  		if (ret < 0) {
! 			/* process the ESP packet */
! 			ret = xfrm4_rcv_encap(skb, up->encap_type);
! 			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
  			return -ret;
  		}
  		/* FALLTHROUGH -- it's a UDP Packet */
--- 1055,1067 ----
  			return 0;
  		}
  		if (ret < 0) {
!  			if(xfrm4_rcv_encap_func != NULL) {
!  			  ret = (*xfrm4_rcv_encap_func)(skb, up->encap_type);
!  			  UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
!  			} else {
!  			  UDP_INC_STATS_BH(UDP_MIB_INERRORS);
!  			  ret = 1;
!  			}
  			return -ret;
  		}
  		/* FALLTHROUGH -- it's a UDP Packet */
***************
*** 1102,1108 ****
  /*
   *	All we need to do is get the socket, and then do a checksum. 
   */
-  
  int udp_rcv(struct sk_buff *skb)
  {
    	struct sock *sk;
--- 1151,1156 ----
***************
*** 1135,1141 ****
  		return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
  
  	sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
- 
  	if (sk != NULL) {
  		int ret = udp_queue_rcv_skb(sk, skb);
  		sock_put(sk);
--- 1183,1188 ----
***************
*** 1559,1561 ****
--- 1606,1614 ----
  EXPORT_SYMBOL(udp_proc_register);
  EXPORT_SYMBOL(udp_proc_unregister);
  #endif
+ 
+ #if defined(CONFIG_IPSEC_NAT_TRAVERSAL)
+ EXPORT_SYMBOL(udp4_register_esp_rcvencap);
+ EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);
+ #endif
+ 
