1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C)2003,2004 USAGI/WIDE Project 4 * 5 * Authors Mitsuru KANDA <mk@linux-ipv6.org> 6 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> 7 */ 8 9 #define pr_fmt(fmt) "IPv6: " fmt 10 11 #include <linux/icmpv6.h> 12 #include <linux/init.h> 13 #include <linux/module.h> 14 #include <linux/mutex.h> 15 #include <linux/netdevice.h> 16 #include <linux/skbuff.h> 17 #include <linux/slab.h> 18 #include <net/ipv6.h> 19 #include <net/protocol.h> 20 #include <net/xfrm.h> 21 22 static struct xfrm6_tunnel __rcu *tunnel6_handlers __read_mostly; 23 static struct xfrm6_tunnel __rcu *tunnel46_handlers __read_mostly; 24 static struct xfrm6_tunnel __rcu *tunnelmpls6_handlers __read_mostly; 25 static DEFINE_MUTEX(tunnel6_mutex); 26 27 static inline int xfrm6_tunnel_mpls_supported(void) 28 { 29 return IS_ENABLED(CONFIG_MPLS); 30 } 31 32 int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) 33 { 34 struct xfrm6_tunnel __rcu **pprev; 35 struct xfrm6_tunnel *t; 36 int ret = -EEXIST; 37 int priority = handler->priority; 38 39 mutex_lock(&tunnel6_mutex); 40 41 switch (family) { 42 case AF_INET6: 43 pprev = &tunnel6_handlers; 44 break; 45 case AF_INET: 46 pprev = &tunnel46_handlers; 47 break; 48 case AF_MPLS: 49 pprev = &tunnelmpls6_handlers; 50 break; 51 default: 52 goto err; 53 } 54 55 for (; (t = rcu_dereference_protected(*pprev, 56 lockdep_is_held(&tunnel6_mutex))) != NULL; 57 pprev = &t->next) { 58 if (t->priority > priority) 59 break; 60 if (t->priority == priority) 61 goto err; 62 } 63 64 handler->next = *pprev; 65 rcu_assign_pointer(*pprev, handler); 66 67 ret = 0; 68 69 err: 70 mutex_unlock(&tunnel6_mutex); 71 72 return ret; 73 } 74 EXPORT_SYMBOL(xfrm6_tunnel_register); 75 76 int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) 77 { 78 struct xfrm6_tunnel __rcu **pprev; 79 struct xfrm6_tunnel *t; 80 int ret = -ENOENT; 81 82 mutex_lock(&tunnel6_mutex); 83 84 switch (family) { 85 case AF_INET6: 86 pprev = &tunnel6_handlers; 87 break; 88 case AF_INET: 89 pprev = &tunnel46_handlers; 90 break; 91 case AF_MPLS: 92 pprev = &tunnelmpls6_handlers; 93 break; 94 default: 95 goto err; 96 } 97 98 for (; (t = rcu_dereference_protected(*pprev, 99 lockdep_is_held(&tunnel6_mutex))) != NULL; 100 pprev = &t->next) { 101 if (t == handler) { 102 *pprev = handler->next; 103 ret = 0; 104 break; 105 } 106 } 107 108 err: 109 mutex_unlock(&tunnel6_mutex); 110 111 synchronize_net(); 112 113 return ret; 114 } 115 EXPORT_SYMBOL(xfrm6_tunnel_deregister); 116 117 #define for_each_tunnel_rcu(head, handler) \ 118 for (handler = rcu_dereference(head); \ 119 handler != NULL; \ 120 handler = rcu_dereference(handler->next)) \ 121 122 static int tunnelmpls6_rcv(struct sk_buff *skb) 123 { 124 struct xfrm6_tunnel *handler; 125 126 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 127 goto drop; 128 129 for_each_tunnel_rcu(tunnelmpls6_handlers, handler) 130 if (!handler->handler(skb)) 131 return 0; 132 133 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 134 135 drop: 136 kfree_skb(skb); 137 return 0; 138 } 139 140 static int tunnel6_rcv(struct sk_buff *skb) 141 { 142 struct xfrm6_tunnel *handler; 143 144 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 145 goto drop; 146 147 for_each_tunnel_rcu(tunnel6_handlers, handler) 148 if (!handler->handler(skb)) 149 return 0; 150 151 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 152 153 drop: 154 kfree_skb(skb); 155 return 0; 156 } 157 158 #if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL) 159 static int tunnel6_rcv_cb(struct sk_buff *skb, u8 proto, int err) 160 { 161 struct xfrm6_tunnel __rcu *head; 162 struct xfrm6_tunnel *handler; 163 int ret; 164 165 head = (proto == IPPROTO_IPV6) ? tunnel6_handlers : tunnel46_handlers; 166 167 for_each_tunnel_rcu(head, handler) { 168 if (handler->cb_handler) { 169 ret = handler->cb_handler(skb, err); 170 if (ret <= 0) 171 return ret; 172 } 173 } 174 175 return 0; 176 } 177 178 static const struct xfrm_input_afinfo tunnel6_input_afinfo = { 179 .family = AF_INET6, 180 .is_ipip = true, 181 .callback = tunnel6_rcv_cb, 182 }; 183 #endif 184 185 static int tunnel46_rcv(struct sk_buff *skb) 186 { 187 struct xfrm6_tunnel *handler; 188 189 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 190 goto drop; 191 192 for_each_tunnel_rcu(tunnel46_handlers, handler) 193 if (!handler->handler(skb)) 194 return 0; 195 196 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 197 198 drop: 199 kfree_skb(skb); 200 return 0; 201 } 202 203 static int tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 204 u8 type, u8 code, int offset, __be32 info) 205 { 206 struct xfrm6_tunnel *handler; 207 208 for_each_tunnel_rcu(tunnel6_handlers, handler) 209 if (!handler->err_handler(skb, opt, type, code, offset, info)) 210 return 0; 211 212 return -ENOENT; 213 } 214 215 static int tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 216 u8 type, u8 code, int offset, __be32 info) 217 { 218 struct xfrm6_tunnel *handler; 219 220 for_each_tunnel_rcu(tunnel46_handlers, handler) 221 if (!handler->err_handler(skb, opt, type, code, offset, info)) 222 return 0; 223 224 return -ENOENT; 225 } 226 227 static int tunnelmpls6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 228 u8 type, u8 code, int offset, __be32 info) 229 { 230 struct xfrm6_tunnel *handler; 231 232 for_each_tunnel_rcu(tunnelmpls6_handlers, handler) 233 if (!handler->err_handler(skb, opt, type, code, offset, info)) 234 return 0; 235 236 return -ENOENT; 237 } 238 239 static const struct inet6_protocol tunnel6_protocol = { 240 .handler = tunnel6_rcv, 241 .err_handler = tunnel6_err, 242 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 243 }; 244 245 static const struct inet6_protocol tunnel46_protocol = { 246 .handler = tunnel46_rcv, 247 .err_handler = tunnel46_err, 248 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 249 }; 250 251 static const struct inet6_protocol tunnelmpls6_protocol = { 252 .handler = tunnelmpls6_rcv, 253 .err_handler = tunnelmpls6_err, 254 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 255 }; 256 257 static int __init tunnel6_init(void) 258 { 259 if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { 260 pr_err("%s: can't add protocol\n", __func__); 261 return -EAGAIN; 262 } 263 if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) { 264 pr_err("%s: can't add protocol\n", __func__); 265 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); 266 return -EAGAIN; 267 } 268 if (xfrm6_tunnel_mpls_supported() && 269 inet6_add_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS)) { 270 pr_err("%s: can't add protocol\n", __func__); 271 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); 272 inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP); 273 return -EAGAIN; 274 } 275 #if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL) 276 if (xfrm_input_register_afinfo(&tunnel6_input_afinfo)) { 277 pr_err("%s: can't add input afinfo\n", __func__); 278 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); 279 inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP); 280 if (xfrm6_tunnel_mpls_supported()) 281 inet6_del_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS); 282 return -EAGAIN; 283 } 284 #endif 285 return 0; 286 } 287 288 static void __exit tunnel6_fini(void) 289 { 290 #if IS_ENABLED(CONFIG_INET6_XFRM_TUNNEL) 291 if (xfrm_input_unregister_afinfo(&tunnel6_input_afinfo)) 292 pr_err("%s: can't remove input afinfo\n", __func__); 293 #endif 294 if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP)) 295 pr_err("%s: can't remove protocol\n", __func__); 296 if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) 297 pr_err("%s: can't remove protocol\n", __func__); 298 if (xfrm6_tunnel_mpls_supported() && 299 inet6_del_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS)) 300 pr_err("%s: can't remove protocol\n", __func__); 301 } 302 303 module_init(tunnel6_init); 304 module_exit(tunnel6_fini); 305 MODULE_LICENSE("GPL"); 306