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