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