aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/xfrm6_tunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/xfrm6_tunnel.c')
-rw-r--r--net/ipv6/xfrm6_tunnel.c82
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
359static struct xfrm6_tunnel *xfrm6_tunnel_handler; 359static int xfrm6_tunnel_rcv(struct sk_buff *skb)
360static DECLARE_MUTEX(xfrm6_tunnel_sem);
361
362int 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
377EXPORT_SYMBOL(xfrm6_tunnel_register);
378
379int 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
396EXPORT_SYMBOL(xfrm6_tunnel_deregister);
397
398static 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
413static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 368static 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
467static int xfrm6_tunnel_init_state(struct xfrm_state *x) 415static 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
495static struct inet6_protocol xfrm6_tunnel_protocol = { 443static 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
501static int __init xfrm6_tunnel_init(void) 449static 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");