1*d2acc347SHerbert Xu /* tunnel4.c: Generic IP tunnel transformer. 2*d2acc347SHerbert Xu * 3*d2acc347SHerbert Xu * Copyright (C) 2003 David S. Miller (davem@redhat.com) 4*d2acc347SHerbert Xu */ 5*d2acc347SHerbert Xu 6*d2acc347SHerbert Xu #include <linux/init.h> 7*d2acc347SHerbert Xu #include <linux/module.h> 8*d2acc347SHerbert Xu #include <linux/mutex.h> 9*d2acc347SHerbert Xu #include <linux/netdevice.h> 10*d2acc347SHerbert Xu #include <linux/skbuff.h> 11*d2acc347SHerbert Xu #include <net/protocol.h> 12*d2acc347SHerbert Xu #include <net/xfrm.h> 13*d2acc347SHerbert Xu 14*d2acc347SHerbert Xu static struct xfrm_tunnel *tunnel4_handlers; 15*d2acc347SHerbert Xu static DEFINE_MUTEX(tunnel4_mutex); 16*d2acc347SHerbert Xu 17*d2acc347SHerbert Xu int xfrm4_tunnel_register(struct xfrm_tunnel *handler) 18*d2acc347SHerbert Xu { 19*d2acc347SHerbert Xu struct xfrm_tunnel **pprev; 20*d2acc347SHerbert Xu int ret = -EEXIST; 21*d2acc347SHerbert Xu int priority = handler->priority; 22*d2acc347SHerbert Xu 23*d2acc347SHerbert Xu mutex_lock(&tunnel4_mutex); 24*d2acc347SHerbert Xu 25*d2acc347SHerbert Xu for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { 26*d2acc347SHerbert Xu if ((*pprev)->priority > priority) 27*d2acc347SHerbert Xu break; 28*d2acc347SHerbert Xu if ((*pprev)->priority == priority) 29*d2acc347SHerbert Xu goto err; 30*d2acc347SHerbert Xu } 31*d2acc347SHerbert Xu 32*d2acc347SHerbert Xu handler->next = *pprev; 33*d2acc347SHerbert Xu *pprev = handler; 34*d2acc347SHerbert Xu 35*d2acc347SHerbert Xu ret = 0; 36*d2acc347SHerbert Xu 37*d2acc347SHerbert Xu err: 38*d2acc347SHerbert Xu mutex_unlock(&tunnel4_mutex); 39*d2acc347SHerbert Xu 40*d2acc347SHerbert Xu return ret; 41*d2acc347SHerbert Xu } 42*d2acc347SHerbert Xu 43*d2acc347SHerbert Xu EXPORT_SYMBOL(xfrm4_tunnel_register); 44*d2acc347SHerbert Xu 45*d2acc347SHerbert Xu int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) 46*d2acc347SHerbert Xu { 47*d2acc347SHerbert Xu struct xfrm_tunnel **pprev; 48*d2acc347SHerbert Xu int ret = -ENOENT; 49*d2acc347SHerbert Xu 50*d2acc347SHerbert Xu mutex_lock(&tunnel4_mutex); 51*d2acc347SHerbert Xu 52*d2acc347SHerbert Xu for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { 53*d2acc347SHerbert Xu if (*pprev == handler) { 54*d2acc347SHerbert Xu *pprev = handler->next; 55*d2acc347SHerbert Xu ret = 0; 56*d2acc347SHerbert Xu break; 57*d2acc347SHerbert Xu } 58*d2acc347SHerbert Xu } 59*d2acc347SHerbert Xu 60*d2acc347SHerbert Xu mutex_unlock(&tunnel4_mutex); 61*d2acc347SHerbert Xu 62*d2acc347SHerbert Xu synchronize_net(); 63*d2acc347SHerbert Xu 64*d2acc347SHerbert Xu return ret; 65*d2acc347SHerbert Xu } 66*d2acc347SHerbert Xu 67*d2acc347SHerbert Xu EXPORT_SYMBOL(xfrm4_tunnel_deregister); 68*d2acc347SHerbert Xu 69*d2acc347SHerbert Xu static int tunnel4_rcv(struct sk_buff *skb) 70*d2acc347SHerbert Xu { 71*d2acc347SHerbert Xu struct xfrm_tunnel *handler; 72*d2acc347SHerbert Xu 73*d2acc347SHerbert Xu for (handler = tunnel4_handlers; handler; handler = handler->next) 74*d2acc347SHerbert Xu if (!handler->handler(skb)) 75*d2acc347SHerbert Xu return 0; 76*d2acc347SHerbert Xu 77*d2acc347SHerbert Xu kfree_skb(skb); 78*d2acc347SHerbert Xu return 0; 79*d2acc347SHerbert Xu } 80*d2acc347SHerbert Xu 81*d2acc347SHerbert Xu static void tunnel4_err(struct sk_buff *skb, u32 info) 82*d2acc347SHerbert Xu { 83*d2acc347SHerbert Xu struct xfrm_tunnel *handler; 84*d2acc347SHerbert Xu 85*d2acc347SHerbert Xu for (handler = tunnel4_handlers; handler; handler = handler->next) 86*d2acc347SHerbert Xu if (!handler->err_handler(skb, info)) 87*d2acc347SHerbert Xu break; 88*d2acc347SHerbert Xu } 89*d2acc347SHerbert Xu 90*d2acc347SHerbert Xu static struct net_protocol tunnel4_protocol = { 91*d2acc347SHerbert Xu .handler = tunnel4_rcv, 92*d2acc347SHerbert Xu .err_handler = tunnel4_err, 93*d2acc347SHerbert Xu .no_policy = 1, 94*d2acc347SHerbert Xu }; 95*d2acc347SHerbert Xu 96*d2acc347SHerbert Xu static int __init tunnel4_init(void) 97*d2acc347SHerbert Xu { 98*d2acc347SHerbert Xu if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 99*d2acc347SHerbert Xu printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 100*d2acc347SHerbert Xu return -EAGAIN; 101*d2acc347SHerbert Xu } 102*d2acc347SHerbert Xu return 0; 103*d2acc347SHerbert Xu } 104*d2acc347SHerbert Xu 105*d2acc347SHerbert Xu static void __exit tunnel4_fini(void) 106*d2acc347SHerbert Xu { 107*d2acc347SHerbert Xu if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 108*d2acc347SHerbert Xu printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 109*d2acc347SHerbert Xu } 110*d2acc347SHerbert Xu 111*d2acc347SHerbert Xu module_init(tunnel4_init); 112*d2acc347SHerbert Xu module_exit(tunnel4_fini); 113*d2acc347SHerbert Xu MODULE_LICENSE("GPL"); 114