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