diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-02-27 16:00:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-02-27 16:00:40 -0500 |
commit | 752c1f4c78fe86d0fd6497387f763306b0d8fc53 (patch) | |
tree | 50d7e52940d1adf0936805645d52e2419e5922cf | |
parent | 4bf05eceecf2efb4c883e9e9b17825682e7330dd (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.h | 1 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 128 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 7 |
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 */ | ||
16 | struct esp_decap_data { | ||
17 | xfrm_address_t saddr; | ||
18 | __u16 sport; | ||
19 | __u8 proto; | ||
20 | }; | ||
21 | |||
22 | static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | 15 | static 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 | ||
248 | static 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 | |||
305 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | 263 | static 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 | ||
470 | static int __init esp4_init(void) | 427 | static 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 | ||