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/icmp.h> 12 #include <net/ip.h> 13 #include <net/protocol.h> 14 #include <net/xfrm.h> 15 16 static struct xfrm_tunnel *tunnel4_handlers; 17 static struct xfrm_tunnel *tunnel64_handlers; 18 static DEFINE_MUTEX(tunnel4_mutex); 19 20 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) 21 { 22 struct xfrm_tunnel **pprev; 23 int ret = -EEXIST; 24 int priority = handler->priority; 25 26 mutex_lock(&tunnel4_mutex); 27 28 for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; 29 *pprev; pprev = &(*pprev)->next) { 30 if ((*pprev)->priority > priority) 31 break; 32 if ((*pprev)->priority == priority) 33 goto err; 34 } 35 36 handler->next = *pprev; 37 *pprev = handler; 38 39 ret = 0; 40 41 err: 42 mutex_unlock(&tunnel4_mutex); 43 44 return ret; 45 } 46 47 EXPORT_SYMBOL(xfrm4_tunnel_register); 48 49 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) 50 { 51 struct xfrm_tunnel **pprev; 52 int ret = -ENOENT; 53 54 mutex_lock(&tunnel4_mutex); 55 56 for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; 57 *pprev; pprev = &(*pprev)->next) { 58 if (*pprev == handler) { 59 *pprev = handler->next; 60 ret = 0; 61 break; 62 } 63 } 64 65 mutex_unlock(&tunnel4_mutex); 66 67 synchronize_net(); 68 69 return ret; 70 } 71 72 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 73 74 static int tunnel4_rcv(struct sk_buff *skb) 75 { 76 struct xfrm_tunnel *handler; 77 78 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 79 goto drop; 80 81 for (handler = tunnel4_handlers; handler; handler = handler->next) 82 if (!handler->handler(skb)) 83 return 0; 84 85 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 86 87 drop: 88 kfree_skb(skb); 89 return 0; 90 } 91 92 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 93 static int tunnel64_rcv(struct sk_buff *skb) 94 { 95 struct xfrm_tunnel *handler; 96 97 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 98 goto drop; 99 100 for (handler = tunnel64_handlers; handler; handler = handler->next) 101 if (!handler->handler(skb)) 102 return 0; 103 104 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 105 106 drop: 107 kfree_skb(skb); 108 return 0; 109 } 110 #endif 111 112 static void tunnel4_err(struct sk_buff *skb, u32 info) 113 { 114 struct xfrm_tunnel *handler; 115 116 for (handler = tunnel4_handlers; handler; handler = handler->next) 117 if (!handler->err_handler(skb, info)) 118 break; 119 } 120 121 static struct net_protocol tunnel4_protocol = { 122 .handler = tunnel4_rcv, 123 .err_handler = tunnel4_err, 124 .no_policy = 1, 125 }; 126 127 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 128 static struct net_protocol tunnel64_protocol = { 129 .handler = tunnel64_rcv, 130 .err_handler = tunnel4_err, 131 .no_policy = 1, 132 }; 133 #endif 134 135 static int __init tunnel4_init(void) 136 { 137 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { 138 printk(KERN_ERR "tunnel4 init: can't add protocol\n"); 139 return -EAGAIN; 140 } 141 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 142 if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { 143 printk(KERN_ERR "tunnel64 init: can't add protocol\n"); 144 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 145 return -EAGAIN; 146 } 147 #endif 148 return 0; 149 } 150 151 static void __exit tunnel4_fini(void) 152 { 153 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 154 if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) 155 printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); 156 #endif 157 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 158 printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); 159 } 160 161 module_init(tunnel4_init); 162 module_exit(tunnel4_fini); 163 MODULE_LICENSE("GPL"); 164