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 static int tunnel46_rcv(struct sk_buff *skb) 159 { 160 struct xfrm6_tunnel *handler; 161 162 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 163 goto drop; 164 165 for_each_tunnel_rcu(tunnel46_handlers, handler) 166 if (!handler->handler(skb)) 167 return 0; 168 169 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 170 171 drop: 172 kfree_skb(skb); 173 return 0; 174 } 175 176 static int tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 177 u8 type, u8 code, int offset, __be32 info) 178 { 179 struct xfrm6_tunnel *handler; 180 181 for_each_tunnel_rcu(tunnel6_handlers, handler) 182 if (!handler->err_handler(skb, opt, type, code, offset, info)) 183 return 0; 184 185 return -ENOENT; 186 } 187 188 static int tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 189 u8 type, u8 code, int offset, __be32 info) 190 { 191 struct xfrm6_tunnel *handler; 192 193 for_each_tunnel_rcu(tunnel46_handlers, handler) 194 if (!handler->err_handler(skb, opt, type, code, offset, info)) 195 return 0; 196 197 return -ENOENT; 198 } 199 200 static int tunnelmpls6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 201 u8 type, u8 code, int offset, __be32 info) 202 { 203 struct xfrm6_tunnel *handler; 204 205 for_each_tunnel_rcu(tunnelmpls6_handlers, handler) 206 if (!handler->err_handler(skb, opt, type, code, offset, info)) 207 return 0; 208 209 return -ENOENT; 210 } 211 212 static const struct inet6_protocol tunnel6_protocol = { 213 .handler = tunnel6_rcv, 214 .err_handler = tunnel6_err, 215 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 216 }; 217 218 static const struct inet6_protocol tunnel46_protocol = { 219 .handler = tunnel46_rcv, 220 .err_handler = tunnel46_err, 221 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 222 }; 223 224 static const struct inet6_protocol tunnelmpls6_protocol = { 225 .handler = tunnelmpls6_rcv, 226 .err_handler = tunnelmpls6_err, 227 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, 228 }; 229 230 static int __init tunnel6_init(void) 231 { 232 if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { 233 pr_err("%s: can't add protocol\n", __func__); 234 return -EAGAIN; 235 } 236 if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) { 237 pr_err("%s: can't add protocol\n", __func__); 238 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); 239 return -EAGAIN; 240 } 241 if (xfrm6_tunnel_mpls_supported() && 242 inet6_add_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS)) { 243 pr_err("%s: can't add protocol\n", __func__); 244 inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); 245 inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP); 246 return -EAGAIN; 247 } 248 return 0; 249 } 250 251 static void __exit tunnel6_fini(void) 252 { 253 if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP)) 254 pr_err("%s: can't remove protocol\n", __func__); 255 if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) 256 pr_err("%s: can't remove protocol\n", __func__); 257 if (xfrm6_tunnel_mpls_supported() && 258 inet6_del_protocol(&tunnelmpls6_protocol, IPPROTO_MPLS)) 259 pr_err("%s: can't remove protocol\n", __func__); 260 } 261 262 module_init(tunnel6_init); 263 module_exit(tunnel6_fini); 264 MODULE_LICENSE("GPL"); 265