From d2acc3479cbccd5cfbca6c787be713ef1de12ec6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 28 Mar 2006 01:12:13 -0800 Subject: [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 Signed-off-by: David S. Miller --- net/ipv6/xfrm6_tunnel.c | 81 +++++++++---------------------------------------- 1 file changed, 14 insertions(+), 67 deletions(-) (limited to 'net/ipv6/xfrm6_tunnel.c') 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 @@ #include #include #include -#include #include #include #include @@ -357,71 +356,18 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *dec return 0; } -static struct xfrm6_tunnel *xfrm6_tunnel_handler; -static DEFINE_MUTEX(xfrm6_tunnel_mutex); - -int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) +static int xfrm6_tunnel_rcv(struct sk_buff *skb) { - int ret; - - mutex_lock(&xfrm6_tunnel_mutex); - ret = 0; - if (xfrm6_tunnel_handler != NULL) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = handler; - mutex_unlock(&xfrm6_tunnel_mutex); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_register); - -int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) -{ - int ret; - - mutex_lock(&xfrm6_tunnel_mutex); - ret = 0; - if (xfrm6_tunnel_handler != handler) - ret = -EINVAL; - if (!ret) - xfrm6_tunnel_handler = NULL; - mutex_unlock(&xfrm6_tunnel_mutex); - - synchronize_net(); - - return ret; -} - -EXPORT_SYMBOL(xfrm6_tunnel_deregister); - -static int xfrm6_tunnel_rcv(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; struct ipv6hdr *iph = skb->nh.ipv6h; u32 spi; - /* device-like_ip6ip6_handler() */ - if (handler && handler->handler(pskb) == 0) - return 0; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); - return xfrm6_rcv_spi(pskb, spi); + return xfrm6_rcv_spi(skb, spi); } -static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) +static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) { - struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; - - /* call here first for device-like ip6ip6 err handling */ - if (handler) { - handler->err_handler(skb, opt, type, code, offset, info); - return; - } - /* xfrm6_tunnel native err handling */ switch (type) { case ICMPV6_DEST_UNREACH: @@ -462,7 +408,8 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, default: break; } - return; + + return 0; } static int xfrm6_tunnel_init_state(struct xfrm_state *x) @@ -493,10 +440,10 @@ static struct xfrm_type xfrm6_tunnel_type = { .output = xfrm6_tunnel_output, }; -static struct inet6_protocol xfrm6_tunnel_protocol = { +static struct xfrm6_tunnel xfrm6_tunnel_handler = { .handler = xfrm6_tunnel_rcv, - .err_handler = xfrm6_tunnel_err, - .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + .err_handler = xfrm6_tunnel_err, + .priority = 2, }; static int __init xfrm6_tunnel_init(void) @@ -508,16 +455,16 @@ static int __init xfrm6_tunnel_init(void) "xfrm6_tunnel init: can't add xfrm type\n"); return -EAGAIN; } - if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) { + if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { X6TPRINTK1(KERN_ERR - "xfrm6_tunnel init(): can't add protocol\n"); + "xfrm6_tunnel init(): can't add handler\n"); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); return -EAGAIN; } if (xfrm6_tunnel_spi_init() < 0) { X6TPRINTK1(KERN_ERR "xfrm6_tunnel init: failed to initialize spi\n"); - inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6); + xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); return -EAGAIN; } @@ -529,9 +476,9 @@ static void __exit xfrm6_tunnel_fini(void) X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__); xfrm6_tunnel_spi_fini(); - if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) + if (xfrm6_tunnel_deregister(&xfrm6_tunnel_handler)) X6TPRINTK1(KERN_ERR - "xfrm6_tunnel close: can't remove protocol\n"); + "xfrm6_tunnel close: can't remove handler\n"); if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0) X6TPRINTK1(KERN_ERR "xfrm6_tunnel close: can't remove xfrm type\n"); -- cgit v1.2.3