]>
Commit | Line | Data |
---|---|---|
202f35e2 AF |
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 | |
9 | @@ -367,6 +367,12 @@ | |
10 | tristate | |
11 | default n | |
12 | ||
13 | +config IPSEC_NAT_TRAVERSAL | |
14 | + bool "IPSEC NAT-Traversal (KLIPS compatible)" | |
15 | + depends on INET | |
16 | + ---help--- | |
17 | + Includes support for RFC3947/RFC3948 NAT-Traversal of ESP over UDP. | |
18 | + | |
19 | config INET_XFRM_MODE_TRANSPORT | |
20 | tristate "IP: IPsec transport mode" | |
21 | default y | |
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 | |
29 | @@ -102,6 +102,7 @@ | |
30 | #include <net/route.h> | |
31 | #include <net/checksum.h> | |
32 | #include <net/xfrm.h> | |
33 | +#include <net/xfrmudp.h> | |
34 | #include "udp_impl.h" | |
35 | ||
36 | /* | |
37 | @@ -920,6 +921,128 @@ | |
38 | return 0; | |
39 | } | |
40 | ||
41 | +#if defined(CONFIG_XFRM) || defined(CONFIG_IPSEC_NAT_TRAVERSAL) | |
42 | + | |
43 | +static xfrm4_rcv_encap_t xfrm4_rcv_encap_func = NULL; | |
44 | + | |
45 | +/* | |
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> | |
50 | + */ | |
51 | + | |
52 | +static int xfrm4_udp_encap_rcv_wrapper(struct sock *sk, struct sk_buff *skb) | |
53 | +{ | |
54 | + struct udp_sock *up = udp_sk(sk); | |
55 | + struct udphdr *uh; | |
56 | + struct iphdr *iph; | |
57 | + int iphlen, len; | |
58 | + int ret; | |
59 | + | |
60 | + __u8 *udpdata; | |
61 | + __be32 *udpdata32; | |
62 | + __u16 encap_type = up->encap_type; | |
63 | + | |
64 | + /* if this is not encapsulated socket, then just return now */ | |
65 | + if (!encap_type && !xfrm4_rcv_encap_func) | |
66 | + return 1; | |
67 | + | |
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))) | |
72 | + return 1; | |
73 | + | |
74 | + /* Now we can get the pointers */ | |
75 | + uh = udp_hdr(skb); | |
76 | + udpdata = (__u8 *)uh + sizeof(struct udphdr); | |
77 | + udpdata32 = (__be32 *)udpdata; | |
78 | + | |
79 | + switch (encap_type) { | |
80 | + default: | |
81 | + case UDP_ENCAP_ESPINUDP: | |
82 | + /* Check if this is a keepalive packet. If so, eat it. */ | |
83 | + if (len == 1 && udpdata[0] == 0xff) { | |
84 | + goto drop; | |
85 | + } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) { | |
86 | + /* ESP Packet without Non-ESP header */ | |
87 | + len = sizeof(struct udphdr); | |
88 | + } else | |
89 | + /* Must be an IKE packet.. pass it through */ | |
90 | + return 1; | |
91 | + break; | |
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) { | |
95 | + goto drop; | |
96 | + } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) && | |
97 | + udpdata32[0] == 0 && udpdata32[1] == 0) { | |
98 | + | |
99 | + /* ESP Packet with Non-IKE marker */ | |
100 | + len = sizeof(struct udphdr) + 2 * sizeof(u32); | |
101 | + } else | |
102 | + /* Must be an IKE packet.. pass it through */ | |
103 | + return 1; | |
104 | + break; | |
105 | + } | |
106 | + | |
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. | |
111 | + */ | |
112 | + if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | |
113 | + goto drop; | |
114 | + | |
115 | + /* Now we can update and verify the packet length... */ | |
116 | + iph = ip_hdr(skb); | |
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!?! */ | |
121 | + goto drop; | |
122 | + } | |
123 | + | |
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 | |
126 | + * for later. | |
127 | + */ | |
128 | + __skb_pull(skb, len); | |
129 | + skb_reset_transport_header(skb); | |
130 | + | |
131 | + /* modify the protocol (it's ESP!) */ | |
132 | + iph->protocol = IPPROTO_ESP; | |
133 | + | |
134 | + /* process ESP */ | |
135 | + ret = (*xfrm4_rcv_encap_func)(skb, encap_type); | |
136 | + return ret; | |
137 | + | |
138 | +drop: | |
139 | + kfree_skb(skb); | |
140 | + return 0; | |
141 | +} | |
142 | + | |
143 | +int udp4_register_esp_rcvencap(xfrm4_rcv_encap_t func, | |
144 | + xfrm4_rcv_encap_t *oldfunc) | |
145 | +{ | |
146 | + if (oldfunc != NULL) | |
147 | + *oldfunc = xfrm4_rcv_encap_func; | |
148 | + xfrm4_rcv_encap_func = func; | |
149 | + return 0; | |
150 | +} | |
151 | + | |
152 | +int udp4_unregister_esp_rcvencap(xfrm4_rcv_encap_t func) | |
153 | +{ | |
154 | + if (xfrm4_rcv_encap_func != func) | |
155 | + return -1; | |
156 | + | |
157 | + xfrm4_rcv_encap_func = NULL; | |
158 | + return 0; | |
159 | +} | |
160 | + | |
161 | +#endif /* CONFIG_XFRM_MODULE || CONFIG_IPSEC_NAT_TRAVERSAL */ | |
162 | + | |
163 | /* returns: | |
164 | * -1: error | |
165 | * 0: success | |
166 | @@ -1252,6 +1375,11 @@ | |
167 | case 0: | |
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; | |
173 | + else | |
174 | +#endif | |
175 | up->encap_rcv = xfrm4_udp_encap_rcv; | |
176 | /* FALLTHROUGH */ | |
177 | case UDP_ENCAP_L2TPINUDP: | |
178 | @@ -1648,3 +1776,9 @@ | |
179 | EXPORT_SYMBOL(udp_proc_register); | |
180 | EXPORT_SYMBOL(udp_proc_unregister); | |
181 | #endif | |
182 | + | |
183 | +#if defined(CONFIG_IPSEC_NAT_TRAVERSAL) | |
184 | +EXPORT_SYMBOL(udp4_register_esp_rcvencap); | |
185 | +EXPORT_SYMBOL(udp4_unregister_esp_rcvencap); | |
186 | +#endif | |
187 | + | |
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 | |
194 | @@ -0,0 +1,10 @@ | |
195 | +/* | |
196 | + * pointer to function for type that xfrm4_input wants, to permit | |
197 | + * decoupling of XFRM from udp.c | |
198 | + */ | |
199 | +#define HAVE_XFRM4_UDP_REGISTER | |
200 | + | |
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); |