diff options
Diffstat (limited to 'net/ipv6/xfrm6_tunnel.c')
-rw-r--r-- | net/ipv6/xfrm6_tunnel.c | 82 |
1 files changed, 15 insertions, 67 deletions
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 8cfc58b96fc2..a8f6776c518d 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -28,9 +28,9 @@ | |||
28 | #include <net/ip.h> | 28 | #include <net/ip.h> |
29 | #include <net/xfrm.h> | 29 | #include <net/xfrm.h> |
30 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
31 | #include <net/protocol.h> | ||
32 | #include <linux/ipv6.h> | 31 | #include <linux/ipv6.h> |
33 | #include <linux/icmpv6.h> | 32 | #include <linux/icmpv6.h> |
33 | #include <linux/mutex.h> | ||
34 | 34 | ||
35 | #ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG | 35 | #ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG |
36 | # define X6TDEBUG 3 | 36 | # define X6TDEBUG 3 |
@@ -356,71 +356,18 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec | |||
356 | return 0; | 356 | return 0; |
357 | } | 357 | } |
358 | 358 | ||
359 | static struct xfrm6_tunnel *xfrm6_tunnel_handler; | 359 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) |
360 | static DECLARE_MUTEX(xfrm6_tunnel_sem); | ||
361 | |||
362 | int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) | ||
363 | { | 360 | { |
364 | int ret; | ||
365 | |||
366 | down(&xfrm6_tunnel_sem); | ||
367 | ret = 0; | ||
368 | if (xfrm6_tunnel_handler != NULL) | ||
369 | ret = -EINVAL; | ||
370 | if (!ret) | ||
371 | xfrm6_tunnel_handler = handler; | ||
372 | up(&xfrm6_tunnel_sem); | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | EXPORT_SYMBOL(xfrm6_tunnel_register); | ||
378 | |||
379 | int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) | ||
380 | { | ||
381 | int ret; | ||
382 | |||
383 | down(&xfrm6_tunnel_sem); | ||
384 | ret = 0; | ||
385 | if (xfrm6_tunnel_handler != handler) | ||
386 | ret = -EINVAL; | ||
387 | if (!ret) | ||
388 | xfrm6_tunnel_handler = NULL; | ||
389 | up(&xfrm6_tunnel_sem); | ||
390 | |||
391 | synchronize_net(); | ||
392 | |||
393 | return ret; | ||
394 | } | ||
395 | |||
396 | EXPORT_SYMBOL(xfrm6_tunnel_deregister); | ||
397 | |||
398 | static int xfrm6_tunnel_rcv(struct sk_buff **pskb) | ||
399 | { | ||
400 | struct sk_buff *skb = *pskb; | ||
401 | struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; | ||
402 | struct ipv6hdr *iph = skb->nh.ipv6h; | 361 | struct ipv6hdr *iph = skb->nh.ipv6h; |
403 | u32 spi; | 362 | u32 spi; |
404 | 363 | ||
405 | /* device-like_ip6ip6_handler() */ | ||
406 | if (handler && handler->handler(pskb) == 0) | ||
407 | return 0; | ||
408 | |||
409 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); | 364 | spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); |
410 | return xfrm6_rcv_spi(pskb, spi); | 365 | return xfrm6_rcv_spi(skb, spi); |
411 | } | 366 | } |
412 | 367 | ||
413 | static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 368 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
414 | int type, int code, int offset, __u32 info) | 369 | int type, int code, int offset, __u32 info) |
415 | { | 370 | { |
416 | struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; | ||
417 | |||
418 | /* call here first for device-like ip6ip6 err handling */ | ||
419 | if (handler) { | ||
420 | handler->err_handler(skb, opt, type, code, offset, info); | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | /* xfrm6_tunnel native err handling */ | 371 | /* xfrm6_tunnel native err handling */ |
425 | switch (type) { | 372 | switch (type) { |
426 | case ICMPV6_DEST_UNREACH: | 373 | case ICMPV6_DEST_UNREACH: |
@@ -461,7 +408,8 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
461 | default: | 408 | default: |
462 | break; | 409 | break; |
463 | } | 410 | } |
464 | return; | 411 | |
412 | return 0; | ||
465 | } | 413 | } |
466 | 414 | ||
467 | static int xfrm6_tunnel_init_state(struct xfrm_state *x) | 415 | static int xfrm6_tunnel_init_state(struct xfrm_state *x) |
@@ -492,10 +440,10 @@ static struct xfrm_type xfrm6_tunnel_type = { | |||
492 | .output = xfrm6_tunnel_output, | 440 | .output = xfrm6_tunnel_output, |
493 | }; | 441 | }; |
494 | 442 | ||
495 | static struct inet6_protocol xfrm6_tunnel_protocol = { | 443 | static struct xfrm6_tunnel xfrm6_tunnel_handler = { |
496 | .handler = xfrm6_tunnel_rcv, | 444 | .handler = xfrm6_tunnel_rcv, |
497 | .err_handler = xfrm6_tunnel_err, | 445 | .err_handler = xfrm6_tunnel_err, |
498 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 446 | .priority = 2, |
499 | }; | 447 | }; |
500 | 448 | ||
501 | static int __init xfrm6_tunnel_init(void) | 449 | static int __init xfrm6_tunnel_init(void) |
@@ -507,16 +455,16 @@ static int __init xfrm6_tunnel_init(void) | |||
507 | "xfrm6_tunnel init: can't add xfrm type\n"); | 455 | "xfrm6_tunnel init: can't add xfrm type\n"); |
508 | return -EAGAIN; | 456 | return -EAGAIN; |
509 | } | 457 | } |
510 | if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) { | 458 | if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { |
511 | X6TPRINTK1(KERN_ERR | 459 | X6TPRINTK1(KERN_ERR |
512 | "xfrm6_tunnel init(): can't add protocol\n"); | 460 | "xfrm6_tunnel init(): can't add handler\n"); |
513 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 461 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
514 | return -EAGAIN; | 462 | return -EAGAIN; |
515 | } | 463 | } |
516 | if (xfrm6_tunnel_spi_init() < 0) { | 464 | if (xfrm6_tunnel_spi_init() < 0) { |
517 | X6TPRINTK1(KERN_ERR | 465 | X6TPRINTK1(KERN_ERR |
518 | "xfrm6_tunnel init: failed to initialize spi\n"); | 466 | "xfrm6_tunnel init: failed to initialize spi\n"); |
519 | inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); | 467 | xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); |
520 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); | 468 | xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); |
521 | return -EAGAIN; | 469 | return -EAGAIN; |
522 | } | 470 | } |
@@ -528,9 +476,9 @@ static void __exit xfrm6_tunnel_fini(void) | |||
528 | X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); | 476 | X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); |
529 | 477 | ||
530 | xfrm6_tunnel_spi_fini(); | 478 | xfrm6_tunnel_spi_fini(); |
531 | if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) | 479 | if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler)) |
532 | X6TPRINTK1(KERN_ERR | 480 | X6TPRINTK1(KERN_ERR |
533 | "xfrm6_tunnel close: can't remove protocol\n"); | 481 | "xfrm6_tunnel close: can't remove handler\n"); |
534 | if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) | 482 | if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) |
535 | X6TPRINTK1(KERN_ERR | 483 | X6TPRINTK1(KERN_ERR |
536 | "xfrm6_tunnel close: can't remove xfrm type\n"); | 484 | "xfrm6_tunnel close: can't remove xfrm type\n"); |