1 Index: linux-2.6.x/net/ipv4/Kconfig
2 ===================================================================
3 RCS file: /cvs/sw/linux-2.6.x/net/ipv4/Kconfig,v
4 retrieving revision 1.1.1.28
5 retrieving revision 1.10
6 diff -u -r1.1.1.28 -r1.10
7 --- linux-2.6.x/net/ipv4/Kconfig 10 Oct 2007 00:54:30 -0000 1.1.1.28
8 +++ linux-2.6.x/net/ipv4/Kconfig 10 Oct 2007 04:53:57 -0000 1.10
13 +config IPSEC_NAT_TRAVERSAL
14 + bool "IPSEC NAT-Traversal (KLIPS compatible)"
17 + Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP.
19 config INET_XFRM_MODE_TRANSPORT
20 tristate "IP: IPsec transport mode"
22 Index: linux-2.6.x/net/ipv4/udp.c
23 ===================================================================
24 RCS file: /cvs/sw/linux-2.6.x/net/ipv4/udp.c,v
25 retrieving revision 1.1.1.46
26 diff -u -r1.1.1.46 udp.c
27 --- linux-2.6.x/net/ipv4/udp.c 10 Oct 2007 00:54:30 -0000 1.1.1.46
28 +++ linux-2.6.x/net/ipv4/udp.c 9 Nov 2007 00:11:33 -0000
30 #include <net/route.h>
31 #include <net/checksum.h>
33 +#include <net/xfrmudp.h>
41 +#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
43 +static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL;
46 + * de-encapsulate and pass to the registered xfrm4_rcv_encap_func function.
47 + * Most of this code stolen from net/ipv4/xfrm4_input.c
48 + * which is attributed to YOSHIFUJI Hideaki @USAGI, and
49 + * Derek Atkins <derek@ihtfp.com>
52 +static int xfrm4_udp_encap_rcv_wrapper(struct sock *sk, struct sk_buff *skb)
54 + struct udp_sock *up = udp_sk(sk);
62 + __u16 encap_type = up->encap_type;
64 + /* if this is not encapsulated socket, then just return now */
65 + if (!encap_type && !xfrm4_rcv_encap_func)
68 + /* If this is a paged skb, make sure we pull up
69 + * whatever data we need to look at. */
70 + len = skb->len - sizeof(struct udphdr);
71 + if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
74 + /* Now we can get the pointers */
76 + udpdata = (__u8 *)uh + sizeof(struct udphdr);
77 + udpdata32 = (__be32 *)udpdata;
79 + switch (encap_type) {
81 + case UDP_ENCAP_ESPINUDP:
82 + /* Check if this is a keepalive packet. If so, eat it. */
83 + if (len == 1 && udpdata[0] == 0xff) {
85 + } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
86 + /* ESP Packet without Non-ESP header */
87 + len = sizeof(struct udphdr);
89 + /* Must be an IKE packet.. pass it through */
92 + case UDP_ENCAP_ESPINUDP_NON_IKE:
93 + /* Check if this is a keepalive packet. If so, eat it. */
94 + if (len == 1 && udpdata[0] == 0xff) {
96 + } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
97 + udpdata32[0] == 0 && udpdata32[1] == 0) {
99 + /* ESP Packet with Non-IKE marker */
100 + len = sizeof(struct udphdr) + 2 * sizeof(u32);
102 + /* Must be an IKE packet.. pass it through */
107 + /* At this point we are sure that this is an ESPinUDP packet,
108 + * so we need to remove 'len' bytes from the packet (the UDP
109 + * header and optional ESP marker bytes) and then modify the
110 + * protocol to ESP, and then call into the transform receiver.
112 + if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
115 + /* Now we can update and verify the packet length... */
117 + iphlen = iph->ihl << 2;
118 + iph->tot_len = htons(ntohs(iph->tot_len) - len);
119 + if (skb->len < iphlen + len) {
120 + /* packet is too small!?! */
124 + /* pull the data buffer up to the ESP header and set the
125 + * transport header to point to ESP. Keep UDP on the stack
128 + __skb_pull(skb, len);
129 + skb_reset_transport_header(skb);
131 + /* modify the protocol (it's ESP!) */
132 + iph->protocol = IPPROTO_ESP;
135 + ret = (*xfrm4_rcv_encap_func)(skb, encap_type);
143 +int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func,
144 + xfrm4_rcv_encap_t *oldfunc)
146 + if (oldfunc != NULL)
147 + *oldfunc = xfrm4_rcv_encap_func;
148 + xfrm4_rcv_encap_func = func;
152 +int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func)
154 + if (xfrm4_rcv_encap_func != func)
157 + xfrm4_rcv_encap_func = NULL;
161 +#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */
166 @@ -1252,6 +1375,11 @@
168 case UDP_ENCAP_ESPINUDP:
169 case UDP_ENCAP_ESPINUDP_NON_IKE:
170 +#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL)
171 + if (xfrm4_rcv_encap_func)
172 + up->encap_rcv = xfrm4_udp_encap_rcv_wrapper;
175 up->encap_rcv = xfrm4_udp_encap_rcv;
177 case UDP_ENCAP_L2TPINUDP:
178 @@ -1648,3 +1776,9 @@
179 EXPORT_SYMBOL(udp_proc_register);
180 EXPORT_SYMBOL(udp_proc_unregister);
183 +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL)
184 +EXPORT_SYMBOL(udp4_register_esp_rcvencap);
185 +EXPORT_SYMBOL(udp4_unregister_esp_rcvencap);
188 Index: linux-2.6.x/include/net/xfrmudp.h
189 ===================================================================
190 RCS file: linux-2.6.x/include/net/xfrmudp.h
191 diff -N linux-2.6.x/include/net/xfrmudp.h
192 --- /dev/null 1 Jan 1970 00:00:00 -0000
193 +++ linux-2.6.x/include/net/xfrmudp.h 3 Nov 2005 01:55:55 -0000 1.1
196 + * pointer to function for type that xfrm4_input wants, to permit
197 + * decoupling of XFRM from udp.c
199 +#define HAVE_XFRM4_UDP_REGISTER
201 +typedef int (*xfrm4_rcv_encap_t)(struct sk_buff *skb, __u16 encap_type);
202 +extern int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func
203 + , xfrm4_rcv_encap_t *oldfunc);
204 +extern int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func);