xfrm4_protocol.c (6710B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* xfrm4_protocol.c - Generic xfrm protocol multiplexer. 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/tunnel4.c 11 */ 12 13#include <linux/init.h> 14#include <linux/mutex.h> 15#include <linux/skbuff.h> 16#include <net/icmp.h> 17#include <net/ip.h> 18#include <net/protocol.h> 19#include <net/xfrm.h> 20 21static struct xfrm4_protocol __rcu *esp4_handlers __read_mostly; 22static struct xfrm4_protocol __rcu *ah4_handlers __read_mostly; 23static struct xfrm4_protocol __rcu *ipcomp4_handlers __read_mostly; 24static DEFINE_MUTEX(xfrm4_protocol_mutex); 25 26static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol) 27{ 28 switch (protocol) { 29 case IPPROTO_ESP: 30 return &esp4_handlers; 31 case IPPROTO_AH: 32 return &ah4_handlers; 33 case IPPROTO_COMP: 34 return &ipcomp4_handlers; 35 } 36 37 return NULL; 38} 39 40#define for_each_protocol_rcu(head, handler) \ 41 for (handler = rcu_dereference(head); \ 42 handler != NULL; \ 43 handler = rcu_dereference(handler->next)) \ 44 45static int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) 46{ 47 int ret; 48 struct xfrm4_protocol *handler; 49 struct xfrm4_protocol __rcu **head = proto_handlers(protocol); 50 51 if (!head) 52 return 0; 53 54 for_each_protocol_rcu(*head, handler) 55 if ((ret = handler->cb_handler(skb, err)) <= 0) 56 return ret; 57 58 return 0; 59} 60 61int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, 62 int encap_type) 63{ 64 int ret; 65 struct xfrm4_protocol *handler; 66 struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr); 67 68 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 69 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 70 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 71 72 if (!head) 73 goto out; 74 75 if (!skb_dst(skb)) { 76 const struct iphdr *iph = ip_hdr(skb); 77 78 if (ip_route_input_noref(skb, iph->daddr, iph->saddr, 79 iph->tos, skb->dev)) 80 goto drop; 81 } 82 83 for_each_protocol_rcu(*head, handler) 84 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) 85 return ret; 86 87out: 88 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 89 90drop: 91 kfree_skb(skb); 92 return 0; 93} 94EXPORT_SYMBOL(xfrm4_rcv_encap); 95 96static int xfrm4_esp_rcv(struct sk_buff *skb) 97{ 98 int ret; 99 struct xfrm4_protocol *handler; 100 101 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 102 103 for_each_protocol_rcu(esp4_handlers, handler) 104 if ((ret = handler->handler(skb)) != -EINVAL) 105 return ret; 106 107 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 108 109 kfree_skb(skb); 110 return 0; 111} 112 113static int xfrm4_esp_err(struct sk_buff *skb, u32 info) 114{ 115 struct xfrm4_protocol *handler; 116 117 for_each_protocol_rcu(esp4_handlers, handler) 118 if (!handler->err_handler(skb, info)) 119 return 0; 120 121 return -ENOENT; 122} 123 124static int xfrm4_ah_rcv(struct sk_buff *skb) 125{ 126 int ret; 127 struct xfrm4_protocol *handler; 128 129 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 130 131 for_each_protocol_rcu(ah4_handlers, handler) 132 if ((ret = handler->handler(skb)) != -EINVAL) 133 return ret; 134 135 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 136 137 kfree_skb(skb); 138 return 0; 139} 140 141static int xfrm4_ah_err(struct sk_buff *skb, u32 info) 142{ 143 struct xfrm4_protocol *handler; 144 145 for_each_protocol_rcu(ah4_handlers, handler) 146 if (!handler->err_handler(skb, info)) 147 return 0; 148 149 return -ENOENT; 150} 151 152static int xfrm4_ipcomp_rcv(struct sk_buff *skb) 153{ 154 int ret; 155 struct xfrm4_protocol *handler; 156 157 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; 158 159 for_each_protocol_rcu(ipcomp4_handlers, handler) 160 if ((ret = handler->handler(skb)) != -EINVAL) 161 return ret; 162 163 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 164 165 kfree_skb(skb); 166 return 0; 167} 168 169static int xfrm4_ipcomp_err(struct sk_buff *skb, u32 info) 170{ 171 struct xfrm4_protocol *handler; 172 173 for_each_protocol_rcu(ipcomp4_handlers, handler) 174 if (!handler->err_handler(skb, info)) 175 return 0; 176 177 return -ENOENT; 178} 179 180static const struct net_protocol esp4_protocol = { 181 .handler = xfrm4_esp_rcv, 182 .err_handler = xfrm4_esp_err, 183 .no_policy = 1, 184}; 185 186static const struct net_protocol ah4_protocol = { 187 .handler = xfrm4_ah_rcv, 188 .err_handler = xfrm4_ah_err, 189 .no_policy = 1, 190}; 191 192static const struct net_protocol ipcomp4_protocol = { 193 .handler = xfrm4_ipcomp_rcv, 194 .err_handler = xfrm4_ipcomp_err, 195 .no_policy = 1, 196}; 197 198static const struct xfrm_input_afinfo xfrm4_input_afinfo = { 199 .family = AF_INET, 200 .callback = xfrm4_rcv_cb, 201}; 202 203static inline const struct net_protocol *netproto(unsigned char protocol) 204{ 205 switch (protocol) { 206 case IPPROTO_ESP: 207 return &esp4_protocol; 208 case IPPROTO_AH: 209 return &ah4_protocol; 210 case IPPROTO_COMP: 211 return &ipcomp4_protocol; 212 } 213 214 return NULL; 215} 216 217int xfrm4_protocol_register(struct xfrm4_protocol *handler, 218 unsigned char protocol) 219{ 220 struct xfrm4_protocol __rcu **pprev; 221 struct xfrm4_protocol *t; 222 bool add_netproto = false; 223 int ret = -EEXIST; 224 int priority = handler->priority; 225 226 if (!proto_handlers(protocol) || !netproto(protocol)) 227 return -EINVAL; 228 229 mutex_lock(&xfrm4_protocol_mutex); 230 231 if (!rcu_dereference_protected(*proto_handlers(protocol), 232 lockdep_is_held(&xfrm4_protocol_mutex))) 233 add_netproto = true; 234 235 for (pprev = proto_handlers(protocol); 236 (t = rcu_dereference_protected(*pprev, 237 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; 238 pprev = &t->next) { 239 if (t->priority < priority) 240 break; 241 if (t->priority == priority) 242 goto err; 243 } 244 245 handler->next = *pprev; 246 rcu_assign_pointer(*pprev, handler); 247 248 ret = 0; 249 250err: 251 mutex_unlock(&xfrm4_protocol_mutex); 252 253 if (add_netproto) { 254 if (inet_add_protocol(netproto(protocol), protocol)) { 255 pr_err("%s: can't add protocol\n", __func__); 256 ret = -EAGAIN; 257 } 258 } 259 260 return ret; 261} 262EXPORT_SYMBOL(xfrm4_protocol_register); 263 264int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, 265 unsigned char protocol) 266{ 267 struct xfrm4_protocol __rcu **pprev; 268 struct xfrm4_protocol *t; 269 int ret = -ENOENT; 270 271 if (!proto_handlers(protocol) || !netproto(protocol)) 272 return -EINVAL; 273 274 mutex_lock(&xfrm4_protocol_mutex); 275 276 for (pprev = proto_handlers(protocol); 277 (t = rcu_dereference_protected(*pprev, 278 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; 279 pprev = &t->next) { 280 if (t == handler) { 281 *pprev = handler->next; 282 ret = 0; 283 break; 284 } 285 } 286 287 if (!rcu_dereference_protected(*proto_handlers(protocol), 288 lockdep_is_held(&xfrm4_protocol_mutex))) { 289 if (inet_del_protocol(netproto(protocol), protocol) < 0) { 290 pr_err("%s: can't remove protocol\n", __func__); 291 ret = -EAGAIN; 292 } 293 } 294 295 mutex_unlock(&xfrm4_protocol_mutex); 296 297 synchronize_net(); 298 299 return ret; 300} 301EXPORT_SYMBOL(xfrm4_protocol_deregister); 302 303void __init xfrm4_protocol_init(void) 304{ 305 xfrm_input_register_afinfo(&xfrm4_input_afinfo); 306}