1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6. 3 * 4 * Copyright (C) 2013 secunet Security Networks AG 5 * 6 * Author: 7 * Steffen Klassert <steffen.klassert@secunet.com> 8 * 9 * Based on: 10 * net/ipv4/xfrm4_protocol.c 11 */ 12 13 #include <linux/init.h> 14 #include <linux/mutex.h> 15 #include <linux/skbuff.h> 16 #include <linux/icmpv6.h> 17 #include <net/ip6_route.h> 18 #include <net/ipv6.h> 19 #include <net/protocol.h> 20 #include <net/xfrm.h> 21 22 static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly; 23 static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly; 24 static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly; 25 static DEFINE_MUTEX(xfrm6_protocol_mutex); 26 27 static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol) 28 { 29 switch (protocol) { 30 case IPPROTO_ESP: 31 return &esp6_handlers; 32 case IPPROTO_AH: 33 return &ah6_handlers; 34 case IPPROTO_COMP: 35 return &ipcomp6_handlers; 36 } 37 38 return NULL; 39 } 40 41 #define for_each_protocol_rcu(head, handler) \ 42 for (handler = rcu_dereference(head); \ 43 handler != NULL; \ 44 handler = rcu_dereference(handler->next)) \ 45 46 static int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err) 47 { 48 int ret; 49 struct xfrm6_protocol *handler; 50 struct xfrm6_protocol __rcu **head = proto_handlers(protocol); 51 52 if (!head) 53 return 0; 54 55 for_each_protocol_rcu(*proto_handlers(protocol), handler) 56 if ((ret = handler->cb_handler(skb, err)) <= 0) 57 return ret; 58 59 return 0; 60 } 61 62 int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, 63 int encap_type) 64 { 65 int ret; 66 struct xfrm6_protocol *handler; 67 struct xfrm6_protocol __rcu **head = proto_handlers(nexthdr); 68 69 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; 70 XFRM_SPI_SKB_CB(skb)->family = AF_INET6; 71 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); 72 73 if (!head) 74 goto out; 75 76 if (!skb_dst(skb)) { 77 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 78 int flags = RT6_LOOKUP_F_HAS_SADDR; 79 struct dst_entry *dst; 80 struct flowi6 fl6 = { 81 .flowi6_iif = skb->dev->ifindex, 82 .daddr = ip6h->daddr, 83 .saddr = ip6h->saddr, 84 .flowlabel = ip6_flowinfo(ip6h), 85 .flowi6_mark = skb->mark, 86 .flowi6_proto = ip6h->nexthdr, 87 }; 88 89 dst = ip6_route_input_lookup(dev_net(skb->dev), skb->dev, &fl6, 90 skb, flags); 91 if (dst->error) { 92 dst_release(dst); 93 goto drop; 94 } 95 skb_dst_set(skb, dst); 96 } 97 98 for_each_protocol_rcu(*head, handler) 99 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) 100 return ret; 101 102 out: 103 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 104 105 drop: 106 kfree_skb(skb); 107 return 0; 108 } 109 EXPORT_SYMBOL(xfrm6_rcv_encap); 110 111 static int xfrm6_esp_rcv(struct sk_buff *skb) 112 { 113 int ret; 114 struct xfrm6_protocol *handler; 115 116 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; 117 118 for_each_protocol_rcu(esp6_handlers, handler) 119 if ((ret = handler->handler(skb)) != -EINVAL) 120 return ret; 121 122 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 123 124 kfree_skb(skb); 125 return 0; 126 } 127 128 static int xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 129 u8 type, u8 code, int offset, __be32 info) 130 { 131 struct xfrm6_protocol *handler; 132 133 for_each_protocol_rcu(esp6_handlers, handler) 134 if (!handler->err_handler(skb, opt, type, code, offset, info)) 135 return 0; 136 137 return -ENOENT; 138 } 139 140 static int xfrm6_ah_rcv(struct sk_buff *skb) 141 { 142 int ret; 143 struct xfrm6_protocol *handler; 144 145 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; 146 147 for_each_protocol_rcu(ah6_handlers, handler) 148 if ((ret = handler->handler(skb)) != -EINVAL) 149 return ret; 150 151 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 152 153 kfree_skb(skb); 154 return 0; 155 } 156 157 static int xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 158 u8 type, u8 code, int offset, __be32 info) 159 { 160 struct xfrm6_protocol *handler; 161 162 for_each_protocol_rcu(ah6_handlers, handler) 163 if (!handler->err_handler(skb, opt, type, code, offset, info)) 164 return 0; 165 166 return -ENOENT; 167 } 168 169 static int xfrm6_ipcomp_rcv(struct sk_buff *skb) 170 { 171 int ret; 172 struct xfrm6_protocol *handler; 173 174 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; 175 176 for_each_protocol_rcu(ipcomp6_handlers, handler) 177 if ((ret = handler->handler(skb)) != -EINVAL) 178 return ret; 179 180 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); 181 182 kfree_skb(skb); 183 return 0; 184 } 185 186 static int xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 187 u8 type, u8 code, int offset, __be32 info) 188 { 189 struct xfrm6_protocol *handler; 190 191 for_each_protocol_rcu(ipcomp6_handlers, handler) 192 if (!handler->err_handler(skb, opt, type, code, offset, info)) 193 return 0; 194 195 return -ENOENT; 196 } 197 198 static const struct inet6_protocol esp6_protocol = { 199 .handler = xfrm6_esp_rcv, 200 .err_handler = xfrm6_esp_err, 201 .flags = INET6_PROTO_NOPOLICY, 202 }; 203 204 static const struct inet6_protocol ah6_protocol = { 205 .handler = xfrm6_ah_rcv, 206 .err_handler = xfrm6_ah_err, 207 .flags = INET6_PROTO_NOPOLICY, 208 }; 209 210 static const struct inet6_protocol ipcomp6_protocol = { 211 .handler = xfrm6_ipcomp_rcv, 212 .err_handler = xfrm6_ipcomp_err, 213 .flags = INET6_PROTO_NOPOLICY, 214 }; 215 216 static const struct xfrm_input_afinfo xfrm6_input_afinfo = { 217 .family = AF_INET6, 218 .callback = xfrm6_rcv_cb, 219 }; 220 221 static inline const struct inet6_protocol *netproto(unsigned char protocol) 222 { 223 switch (protocol) { 224 case IPPROTO_ESP: 225 return &esp6_protocol; 226 case IPPROTO_AH: 227 return &ah6_protocol; 228 case IPPROTO_COMP: 229 return &ipcomp6_protocol; 230 } 231 232 return NULL; 233 } 234 235 int xfrm6_protocol_register(struct xfrm6_protocol *handler, 236 unsigned char protocol) 237 { 238 struct xfrm6_protocol __rcu **pprev; 239 struct xfrm6_protocol *t; 240 bool add_netproto = false; 241 int ret = -EEXIST; 242 int priority = handler->priority; 243 244 if (!proto_handlers(protocol) || !netproto(protocol)) 245 return -EINVAL; 246 247 mutex_lock(&xfrm6_protocol_mutex); 248 249 if (!rcu_dereference_protected(*proto_handlers(protocol), 250 lockdep_is_held(&xfrm6_protocol_mutex))) 251 add_netproto = true; 252 253 for (pprev = proto_handlers(protocol); 254 (t = rcu_dereference_protected(*pprev, 255 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL; 256 pprev = &t->next) { 257 if (t->priority < priority) 258 break; 259 if (t->priority == priority) 260 goto err; 261 } 262 263 handler->next = *pprev; 264 rcu_assign_pointer(*pprev, handler); 265 266 ret = 0; 267 268 err: 269 mutex_unlock(&xfrm6_protocol_mutex); 270 271 if (add_netproto) { 272 if (inet6_add_protocol(netproto(protocol), protocol)) { 273 pr_err("%s: can't add protocol\n", __func__); 274 ret = -EAGAIN; 275 } 276 } 277 278 return ret; 279 } 280 EXPORT_SYMBOL(xfrm6_protocol_register); 281 282 int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, 283 unsigned char protocol) 284 { 285 struct xfrm6_protocol __rcu **pprev; 286 struct xfrm6_protocol *t; 287 int ret = -ENOENT; 288 289 if (!proto_handlers(protocol) || !netproto(protocol)) 290 return -EINVAL; 291 292 mutex_lock(&xfrm6_protocol_mutex); 293 294 for (pprev = proto_handlers(protocol); 295 (t = rcu_dereference_protected(*pprev, 296 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL; 297 pprev = &t->next) { 298 if (t == handler) { 299 *pprev = handler->next; 300 ret = 0; 301 break; 302 } 303 } 304 305 if (!rcu_dereference_protected(*proto_handlers(protocol), 306 lockdep_is_held(&xfrm6_protocol_mutex))) { 307 if (inet6_del_protocol(netproto(protocol), protocol) < 0) { 308 pr_err("%s: can't remove protocol\n", __func__); 309 ret = -EAGAIN; 310 } 311 } 312 313 mutex_unlock(&xfrm6_protocol_mutex); 314 315 synchronize_net(); 316 317 return ret; 318 } 319 EXPORT_SYMBOL(xfrm6_protocol_deregister); 320 321 int __init xfrm6_protocol_init(void) 322 { 323 return xfrm_input_register_afinfo(&xfrm6_input_afinfo); 324 } 325 326 void xfrm6_protocol_fini(void) 327 { 328 xfrm_input_unregister_afinfo(&xfrm6_input_afinfo); 329 } 330