aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-02-27 16:00:40 -0500
committerDavid S. Miller <davem@davemloft.net>2006-02-27 16:00:40 -0500
commit752c1f4c78fe86d0fd6497387f763306b0d8fc53 (patch)
tree50d7e52940d1adf0936805645d52e2419e5922cf
parent4bf05eceecf2efb4c883e9e9b17825682e7330dd (diff)
[IPSEC]: Kill post_input hook and do NAT-T in esp_input directly
The only reason post_input exists at all is that it gives us the potential to adjust the checksums incrementally in future which we ought to do. However, after thinking about it for a bit we can adjust the checksums without using this post_input stuff at all. The crucial point is that only the inner-most NAT-T SA needs to be considered when adjusting checksums. What's more, the checksum adjustment comes down to a single u32 due to the linearity of IP checksums. We just happen to have a spare u32 lying around in our skb structure :) When ip_summed is set to CHECKSUM_NONE on input, the value of skb->csum is currently unused. All we have to do is to make that the checksum adjustment and voila, there goes all the post_input and decap structures! I've left in the decap data structures for now since it's intricately woven into the sec_path stuff. We can kill them later too. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/xfrm.h1
-rw-r--r--net/ipv4/esp4.c128
-rw-r--r--net/xfrm/xfrm_policy.c7
3 files changed, 38 insertions, 98 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 004e645f3e18..8d362c49b8a9 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -233,7 +233,6 @@ struct xfrm_type
233 int (*init_state)(struct xfrm_state *x); 233 int (*init_state)(struct xfrm_state *x);
234 void (*destructor)(struct xfrm_state *); 234 void (*destructor)(struct xfrm_state *);
235 int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); 235 int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
236 int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
237 int (*output)(struct xfrm_state *, struct sk_buff *pskb); 236 int (*output)(struct xfrm_state *, struct sk_buff *pskb);
238 /* Estimate maximal size of result of transformation of a dgram */ 237 /* Estimate maximal size of result of transformation of a dgram */
239 u32 (*get_max_size)(struct xfrm_state *, int size); 238 u32 (*get_max_size)(struct xfrm_state *, int size);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 3f47419cb9c5..09590f356086 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -12,13 +12,6 @@
12#include <net/protocol.h> 12#include <net/protocol.h>
13#include <net/udp.h> 13#include <net/udp.h>
14 14
15/* decapsulation data for use when post-processing */
16struct esp_decap_data {
17 xfrm_address_t saddr;
18 __u16 sport;
19 __u8 proto;
20};
21
22static int esp_output(struct xfrm_state *x, struct sk_buff *skb) 15static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
23{ 16{
24 int err; 17 int err;
@@ -210,25 +203,47 @@ static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc
210 203
211 /* ... check padding bits here. Silly. :-) */ 204 /* ... check padding bits here. Silly. :-) */
212 205
213 if (x->encap && decap && decap->decap_type) { 206 if (x->encap) {
214 struct esp_decap_data *encap_data; 207 struct xfrm_encap_tmpl *encap = x->encap;
215 struct udphdr *uh = (struct udphdr *) (iph+1); 208 struct udphdr *uh;
216
217 encap_data = (struct esp_decap_data *) (decap->decap_data);
218 encap_data->proto = 0;
219
220 switch (decap->decap_type) {
221 case UDP_ENCAP_ESPINUDP:
222 case UDP_ENCAP_ESPINUDP_NON_IKE:
223 encap_data->proto = AF_INET;
224 encap_data->saddr.a4 = iph->saddr;
225 encap_data->sport = uh->source;
226 encap_len = (void*)esph - (void*)uh;
227 break;
228 209
229 default: 210 if (encap->encap_type != decap->decap_type)
230 goto out; 211 goto out;
212
213 uh = (struct udphdr *)(iph + 1);
214 encap_len = (void*)esph - (void*)uh;
215
216 /*
217 * 1) if the NAT-T peer's IP or port changed then
218 * advertize the change to the keying daemon.
219 * This is an inbound SA, so just compare
220 * SRC ports.
221 */
222 if (iph->saddr != x->props.saddr.a4 ||
223 uh->source != encap->encap_sport) {
224 xfrm_address_t ipaddr;
225
226 ipaddr.a4 = iph->saddr;
227 km_new_mapping(x, &ipaddr, uh->source);
228
229 /* XXX: perhaps add an extra
230 * policy check here, to see
231 * if we should allow or
232 * reject a packet from a
233 * different source
234 * address/port.
235 */
231 } 236 }
237
238 /*
239 * 2) ignore UDP/TCP checksums in case
240 * of NAT-T in Transport Mode, or
241 * perform other post-processing fixes
242 * as per draft-ietf-ipsec-udp-encaps-06,
243 * section 3.1.2
244 */
245 if (!x->props.mode)
246 skb->ip_summed = CHECKSUM_UNNECESSARY;
232 } 247 }
233 248
234 iph->protocol = nexthdr[1]; 249 iph->protocol = nexthdr[1];
@@ -245,63 +260,6 @@ out:
245 return -EINVAL; 260 return -EINVAL;
246} 261}
247 262
248static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
249{
250
251 if (x->encap) {
252 struct xfrm_encap_tmpl *encap;
253 struct esp_decap_data *decap_data;
254
255 encap = x->encap;
256 decap_data = (struct esp_decap_data *)(decap->decap_data);
257
258 /* first, make sure that the decap type == the encap type */
259 if (encap->encap_type != decap->decap_type)
260 return -EINVAL;
261
262 switch (encap->encap_type) {
263 default:
264 case UDP_ENCAP_ESPINUDP:
265 case UDP_ENCAP_ESPINUDP_NON_IKE:
266 /*
267 * 1) if the NAT-T peer's IP or port changed then
268 * advertize the change to the keying daemon.
269 * This is an inbound SA, so just compare
270 * SRC ports.
271 */
272 if (decap_data->proto == AF_INET &&
273 (decap_data->saddr.a4 != x->props.saddr.a4 ||
274 decap_data->sport != encap->encap_sport)) {
275 xfrm_address_t ipaddr;
276
277 ipaddr.a4 = decap_data->saddr.a4;
278 km_new_mapping(x, &ipaddr, decap_data->sport);
279
280 /* XXX: perhaps add an extra
281 * policy check here, to see
282 * if we should allow or
283 * reject a packet from a
284 * different source
285 * address/port.
286 */
287 }
288
289 /*
290 * 2) ignore UDP/TCP checksums in case
291 * of NAT-T in Transport Mode, or
292 * perform other post-processing fixes
293 * as per * draft-ietf-ipsec-udp-encaps-06,
294 * section 3.1.2
295 */
296 if (!x->props.mode)
297 skb->ip_summed = CHECKSUM_UNNECESSARY;
298
299 break;
300 }
301 }
302 return 0;
303}
304
305static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) 263static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
306{ 264{
307 struct esp_data *esp = x->data; 265 struct esp_data *esp = x->data;
@@ -457,7 +415,6 @@ static struct xfrm_type esp_type =
457 .destructor = esp_destroy, 415 .destructor = esp_destroy,
458 .get_max_size = esp4_get_max_size, 416 .get_max_size = esp4_get_max_size,
459 .input = esp_input, 417 .input = esp_input,
460 .post_input = esp_post_input,
461 .output = esp_output 418 .output = esp_output
462}; 419};
463 420
@@ -469,15 +426,6 @@ static struct net_protocol esp4_protocol = {
469 426
470static int __init esp4_init(void) 427static int __init esp4_init(void)
471{ 428{
472 struct xfrm_decap_state decap;
473
474 if (sizeof(struct esp_decap_data) >
475 sizeof(decap.decap_data)) {
476 extern void decap_data_too_small(void);
477
478 decap_data_too_small();
479 }
480
481 if (xfrm_register_type(&esp_type, AF_INET) < 0) { 429 if (xfrm_register_type(&esp_type, AF_INET) < 0) {
482 printk(KERN_INFO "ip esp init: can't add xfrm type\n"); 430 printk(KERN_INFO "ip esp init: can't add xfrm type\n");
483 return -EAGAIN; 431 return -EAGAIN;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8206025d8e46..ae62054a9fc4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -996,13 +996,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
996 struct sec_decap_state *xvec = &(skb->sp->x[i]); 996 struct sec_decap_state *xvec = &(skb->sp->x[i]);
997 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family)) 997 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
998 return 0; 998 return 0;
999
1000 /* If there is a post_input processor, try running it */
1001 if (xvec->xvec->type->post_input &&
1002 (xvec->xvec->type->post_input)(xvec->xvec,
1003 &(xvec->decap),
1004 skb) != 0)
1005 return 0;
1006 } 999 }
1007 } 1000 }
1008 1001