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/mpls.h> 10 #include <linux/netdevice.h> 11 #include <linux/skbuff.h> 12 #include <linux/slab.h> 13 #include <net/icmp.h> 14 #include <net/ip.h> 15 #include <net/protocol.h> 16 #include <net/xfrm.h> 17 18 static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly; 19 static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly; 20 static struct xfrm_tunnel __rcu *tunnelmpls4_handlers __read_mostly; 21 static DEFINE_MUTEX(tunnel4_mutex); 22 23 static inline struct xfrm_tunnel __rcu **fam_handlers(unsigned short family) 24 { 25 return (family == AF_INET) ? &tunnel4_handlers : 26 (family == AF_INET6) ? &tunnel64_handlers : 27 &tunnelmpls4_handlers; 28 } 29 30 int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) 31 { 32 struct xfrm_tunnel __rcu **pprev; 33 struct xfrm_tunnel *t; 34 35 int ret = -EEXIST; 36 int priority = handler->priority; 37 38 mutex_lock(&tunnel4_mutex); 39 40 for (pprev = fam_handlers(family); 41 (t = rcu_dereference_protected(*pprev, 42 lockdep_is_held(&tunnel4_mutex))) != NULL; 43 pprev = &t->next) { 44 if (t->priority > priority) 45 break; 46 if (t->priority == priority) 47 goto err; 48 } 49 50 handler->next = *pprev; 51 rcu_assign_pointer(*pprev, handler); 52 53 ret = 0; 54 55 err: 56 mutex_unlock(&tunnel4_mutex); 57 58 return ret; 59 } 60 EXPORT_SYMBOL(xfrm4_tunnel_register); 61 62 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) 63 { 64 struct xfrm_tunnel __rcu **pprev; 65 struct xfrm_tunnel *t; 66 int ret = -ENOENT; 67 68 mutex_lock(&tunnel4_mutex); 69 70 for (pprev = fam_handlers(family); 71 (t = rcu_dereference_protected(*pprev, 72 lockdep_is_held(&tunnel4_mutex))) != NULL; 73 pprev = &t->next) { 74 if (t == handler) { 75 *pprev = handler->next; 76 ret = 0; 77 break; 78 } 79 } 80 81 mutex_unlock(&tunnel4_mutex); 82 83 synchronize_net(); 84 85 return ret; 86 } 87 EXPORT_SYMBOL(xfrm4_tunnel_deregister); 88 89 #define for_each_tunnel_rcu(head, handler) \ 90 for (handler = rcu_dereference(head); \ 91 handler != NULL; \ 92 handler = rcu_dereference(handler->next)) \ 93 94 static int tunnel4_rcv(struct sk_buff *skb) 95 { 96 struct xfrm_tunnel *handler; 97 98 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 99 goto drop; 100 101 for_each_tunnel_rcu(tunnel4_handlers, handler) 102 if (!handler->handler(skb)) 103 return 0; 104 105 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 106 107 drop: 108 kfree_skb(skb); 109 return 0; 110 } 111 112 #if IS_ENABLED(CONFIG_IPV6) 113 static int tunnel64_rcv(struct sk_buff *skb) 114 { 115 struct xfrm_tunnel *handler; 116 117 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 118 goto drop; 119 120 for_each_tunnel_rcu(tunnel64_handlers, handler) 121 if (!handler->handler(skb)) 122 return 0; 123 124 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 125 126 drop: 127 kfree_skb(skb); 128 return 0; 129 } 130 #endif 131 132 #if IS_ENABLED(CONFIG_MPLS) 133 static int tunnelmpls4_rcv(struct sk_buff *skb) 134 { 135 struct xfrm_tunnel *handler; 136 137 if (!pskb_may_pull(skb, sizeof(struct mpls_label))) 138 goto drop; 139 140 for_each_tunnel_rcu(tunnelmpls4_handlers, handler) 141 if (!handler->handler(skb)) 142 return 0; 143 144 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 145 146 drop: 147 kfree_skb(skb); 148 return 0; 149 } 150 #endif 151 152 static int tunnel4_err(struct sk_buff *skb, u32 info) 153 { 154 struct xfrm_tunnel *handler; 155 156 for_each_tunnel_rcu(tunnel4_handlers, handler) 157 if (!handler->err_handler(skb, info)) 158 return 0; 159 160 return -ENOENT; 161 } 162 163 #if IS_ENABLED(CONFIG_IPV6) 164 static int tunnel64_err(struct sk_buff *skb, u32 info) 165 { 166 struct xfrm_tunnel *handler; 167 168 for_each_tunnel_rcu(tunnel64_handlers, handler) 169 if (!handler->err_handler(skb, info)) 170 return 0; 171 172 return -ENOENT; 173 } 174 #endif 175 176 #if IS_ENABLED(CONFIG_MPLS) 177 static int tunnelmpls4_err(struct sk_buff *skb, u32 info) 178 { 179 struct xfrm_tunnel *handler; 180 181 for_each_tunnel_rcu(tunnelmpls4_handlers, handler) 182 if (!handler->err_handler(skb, info)) 183 return 0; 184 185 return -ENOENT; 186 } 187 #endif 188 189 static const struct net_protocol tunnel4_protocol = { 190 .handler = tunnel4_rcv, 191 .err_handler = tunnel4_err, 192 .no_policy = 1, 193 .netns_ok = 1, 194 }; 195 196 #if IS_ENABLED(CONFIG_IPV6) 197 static const struct net_protocol tunnel64_protocol = { 198 .handler = tunnel64_rcv, 199 .err_handler = tunnel64_err, 200 .no_policy = 1, 201 .netns_ok = 1, 202 }; 203 #endif 204 205 #if IS_ENABLED(CONFIG_MPLS) 206 static const struct net_protocol tunnelmpls4_protocol = { 207 .handler = tunnelmpls4_rcv, 208 .err_handler = tunnelmpls4_err, 209 .no_policy = 1, 210 .netns_ok = 1, 211 }; 212 #endif 213 214 static int __init tunnel4_init(void) 215 { 216 if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 217 goto err; 218 #if IS_ENABLED(CONFIG_IPV6) 219 if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { 220 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 221 goto err; 222 } 223 #endif 224 #if IS_ENABLED(CONFIG_MPLS) 225 if (inet_add_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS)) { 226 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); 227 #if IS_ENABLED(CONFIG_IPV6) 228 inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6); 229 #endif 230 goto err; 231 } 232 #endif 233 return 0; 234 235 err: 236 pr_err("%s: can't add protocol\n", __func__); 237 return -EAGAIN; 238 } 239 240 static void __exit tunnel4_fini(void) 241 { 242 #if IS_ENABLED(CONFIG_MPLS) 243 if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS)) 244 pr_err("tunnelmpls4 close: can't remove protocol\n"); 245 #endif 246 #if IS_ENABLED(CONFIG_IPV6) 247 if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) 248 pr_err("tunnel64 close: can't remove protocol\n"); 249 #endif 250 if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) 251 pr_err("tunnel4 close: can't remove protocol\n"); 252 } 253 254 module_init(tunnel4_init); 255 module_exit(tunnel4_fini); 256 MODULE_LICENSE("GPL"); 257