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