X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fxfrm4_tunnel.c;fp=net%2Fipv4%2Fxfrm4_tunnel.c;h=afbb0d4cc305317add1c93b719abbcdcd2bb41ca;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=f8ceaa127c836d4bc6e626ae95eebf22f190a04d;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index f8ceaa127..afbb0d4cc 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -21,11 +20,69 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) return 0; } -static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) +static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { return 0; } +static struct xfrm_tunnel *ipip_handler; +static DECLARE_MUTEX(xfrm4_tunnel_sem); + +int xfrm4_tunnel_register(struct xfrm_tunnel *handler) +{ + int ret; + + down(&xfrm4_tunnel_sem); + ret = 0; + if (ipip_handler != NULL) + ret = -EINVAL; + if (!ret) + ipip_handler = handler; + up(&xfrm4_tunnel_sem); + + return ret; +} + +EXPORT_SYMBOL(xfrm4_tunnel_register); + +int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) +{ + int ret; + + down(&xfrm4_tunnel_sem); + ret = 0; + if (ipip_handler != handler) + ret = -EINVAL; + if (!ret) + ipip_handler = NULL; + up(&xfrm4_tunnel_sem); + + synchronize_net(); + + return ret; +} + +EXPORT_SYMBOL(xfrm4_tunnel_deregister); + +static int ipip_rcv(struct sk_buff *skb) +{ + struct xfrm_tunnel *handler = ipip_handler; + + /* Tunnel devices take precedence. */ + if (handler && handler->handler(skb) == 0) + return 0; + + return xfrm4_rcv(skb); +} + +static void ipip_err(struct sk_buff *skb, u32 info) +{ + struct xfrm_tunnel *handler = ipip_handler; + + if (handler) + handler->err_handler(skb, info); +} + static int ipip_init_state(struct xfrm_state *x) { if (!x->props.mode) @@ -53,15 +110,10 @@ static struct xfrm_type ipip_type = { .output = ipip_output }; -static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) -{ - return -ENOENT; -} - -static struct xfrm_tunnel xfrm_tunnel_handler = { - .handler = xfrm4_rcv, - .err_handler = xfrm_tunnel_err, - .priority = 2, +static struct net_protocol ipip_protocol = { + .handler = ipip_rcv, + .err_handler = ipip_err, + .no_policy = 1, }; static int __init ipip_init(void) @@ -70,8 +122,8 @@ static int __init ipip_init(void) printk(KERN_INFO "ipip init: can't add xfrm type\n"); return -EAGAIN; } - if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) { - printk(KERN_INFO "ipip init: can't add xfrm handler\n"); + if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) { + printk(KERN_INFO "ipip init: can't add protocol\n"); xfrm_unregister_type(&ipip_type, AF_INET); return -EAGAIN; } @@ -80,8 +132,8 @@ static int __init ipip_init(void) static void __exit ipip_fini(void) { - if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler)) - printk(KERN_INFO "ipip close: can't remove xfrm handler\n"); + if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) + printk(KERN_INFO "ipip close: can't remove protocol\n"); if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) printk(KERN_INFO "ipip close: can't remove xfrm type\n"); }