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