aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/xfrm6_tunnel.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-03-28 04:12:13 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-28 20:02:46 -0500
commitd2acc3479cbccd5cfbca6c787be713ef1de12ec6 (patch)
treeaa348e19e15027db9abdd2da175a0c9055047858 /net/ipv6/xfrm6_tunnel.c
parentf0088a50e7c49d1ba285c88fe06345f223652fd3 (diff)
[INET]: Introduce tunnel4/tunnel6
Basically this patch moves the generic tunnel protocol stuff out of xfrm4_tunnel/xfrm6_tunnel and moves it into the new files of tunnel4.c and tunnel6 respectively. The reason for this is that the problem that Hugo uncovered is only the tip of the iceberg. The real problem is that when we removed the dependency of ipip on xfrm4_tunnel we didn't really consider the module case at all. For instance, as it is it's possible to build both ipip and xfrm4_tunnel as modules and if the latter is loaded then ipip simply won't load. After considering the alternatives I've decided that the best way out of this is to restore the dependency of ipip on the non-xfrm-specific part of xfrm4_tunnel. This is acceptable IMHO because the intention of the removal was really to be able to use ipip without the xfrm subsystem. This is still preserved by this patch. So now both ipip/xfrm4_tunnel depend on the new tunnel4.c which handles the arbitration between the two. The order of processing is determined by a simple integer which ensures that ipip gets processed before xfrm4_tunnel. The situation for ICMP handling is a little bit more complicated since we may not have enough information to determine who it's for. It's not a big deal at the moment since the xfrm ICMP handlers are basically no-ops. In future we can deal with this when we look at ICMP caching in general. The user-visible change to this is the removal of the TUNNEL Kconfig prompts. This makes sense because it can only be used through IPCOMP as it stands. The addition of the new modules shouldn't introduce any problems since module dependency will cause them to be loaded. Oh and I also turned some unnecessary pskb's in IPv6 related to this patch to skb's. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/xfrm6_tunnel.c')
-rw-r--r--net/ipv6/xfrm6_tunnel.c81
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
360static struct xfrm6_tunnel *xfrm6_tunnel_handler; 359static int xfrm6_tunnel_rcv(struct sk_buff *skb)
361static DEFINE_MUTEX(xfrm6_tunnel_mutex);
362
363int 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
378EXPORT_SYMBOL(xfrm6_tunnel_register);
379
380int 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
397EXPORT_SYMBOL(xfrm6_tunnel_deregister);
398
399static 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
414static 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,
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
468static int xfrm6_tunnel_init_state(struct xfrm_state *x) 415static 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
496static struct inet6_protocol xfrm6_tunnel_protocol = { 443static 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
502static int __init xfrm6_tunnel_init(void) 449static 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");