1 /* xfrm4_protocol.c - Generic xfrm protocol multiplexer. 2 * 3 * Copyright (C) 2013 secunet Security Networks AG 4 * 5 * Author: 6 * Steffen Klassert <steffen.klassert@secunet.com> 7 * 8 * Based on: 9 * net/ipv4/tunnel4.c 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 14 * 2 of the License, or (at your option) any later version. 15 */ 16 17 #include <linux/init.h> 18 #include <linux/mutex.h> 19 #include <linux/skbuff.h> 20 #include <net/icmp.h> 21 #include <net/ip.h> 22 #include <net/protocol.h> 23 #include <net/xfrm.h> 24 25 static struct xfrm4_protocol __rcu *esp4_handlers __read_mostly; 26 static struct xfrm4_protocol __rcu *ah4_handlers __read_mostly; 27 static struct xfrm4_protocol __rcu *ipcomp4_handlers __read_mostly; 28 static DEFINE_MUTEX(xfrm4_protocol_mutex); 29 30 static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol) 31 { 32 switch (protocol) { 33 case IPPROTO_ESP: 34 return &esp4_handlers; 35 case IPPROTO_AH: 36 return &ah4_handlers; 37 case IPPROTO_COMP: 38 return &ipcomp4_handlers; 39 } 40 41 return NULL; 42 } 43 44 #define for_each_protocol_rcu(head, handler) \ 45 for (handler = rcu_dereference(head); \ 46 handler != NULL; \ 47 handler = rcu_dereference(handler->next)) \ 48 49 int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) 50 { 51 int ret; 52 struct xfrm4_protocol *handler; 53 54 for_each_protocol_rcu(*proto_handlers(protocol), handler) 55 if ((ret = handler->cb_handler(skb, err)) <= 0) 56 return ret; 57 58 return 0; 59 } 60 EXPORT_SYMBOL(xfrm4_rcv_cb); 61 62 int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, 63 int encap_type) 64 { 65 int ret; 66 struct xfrm4_protocol *handler; 67 68 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 69 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 70 71 for_each_protocol_rcu(*proto_handlers(nexthdr), handler) 72 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) 73 return ret; 74 75 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 76 77 kfree_skb(skb); 78 return 0; 79 } 80 EXPORT_SYMBOL(xfrm4_rcv_encap); 81 82 static int xfrm4_esp_rcv(struct sk_buff *skb) 83 { 84 int ret; 85 struct xfrm4_protocol *handler; 86 87 for_each_protocol_rcu(esp4_handlers, handler) 88 if ((ret = handler->handler(skb)) != -EINVAL) 89 return ret; 90 91 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 92 93 kfree_skb(skb); 94 return 0; 95 } 96 97 static void xfrm4_esp_err(struct sk_buff *skb, u32 info) 98 { 99 struct xfrm4_protocol *handler; 100 101 for_each_protocol_rcu(esp4_handlers, handler) 102 if (!handler->err_handler(skb, info)) 103 break; 104 } 105 106 static int xfrm4_ah_rcv(struct sk_buff *skb) 107 { 108 int ret; 109 struct xfrm4_protocol *handler; 110 111 for_each_protocol_rcu(ah4_handlers, handler) 112 if ((ret = handler->handler(skb)) != -EINVAL) 113 return ret;; 114 115 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 116 117 kfree_skb(skb); 118 return 0; 119 } 120 121 static void xfrm4_ah_err(struct sk_buff *skb, u32 info) 122 { 123 struct xfrm4_protocol *handler; 124 125 for_each_protocol_rcu(ah4_handlers, handler) 126 if (!handler->err_handler(skb, info)) 127 break; 128 } 129 130 static int xfrm4_ipcomp_rcv(struct sk_buff *skb) 131 { 132 int ret; 133 struct xfrm4_protocol *handler; 134 135 for_each_protocol_rcu(ipcomp4_handlers, handler) 136 if ((ret = handler->handler(skb)) != -EINVAL) 137 return ret; 138 139 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 140 141 kfree_skb(skb); 142 return 0; 143 } 144 145 static void xfrm4_ipcomp_err(struct sk_buff *skb, u32 info) 146 { 147 struct xfrm4_protocol *handler; 148 149 for_each_protocol_rcu(ipcomp4_handlers, handler) 150 if (!handler->err_handler(skb, info)) 151 break; 152 } 153 154 static const struct net_protocol esp4_protocol = { 155 .handler = xfrm4_esp_rcv, 156 .err_handler = xfrm4_esp_err, 157 .no_policy = 1, 158 .netns_ok = 1, 159 }; 160 161 static const struct net_protocol ah4_protocol = { 162 .handler = xfrm4_ah_rcv, 163 .err_handler = xfrm4_ah_err, 164 .no_policy = 1, 165 .netns_ok = 1, 166 }; 167 168 static const struct net_protocol ipcomp4_protocol = { 169 .handler = xfrm4_ipcomp_rcv, 170 .err_handler = xfrm4_ipcomp_err, 171 .no_policy = 1, 172 .netns_ok = 1, 173 }; 174 175 static inline const struct net_protocol *netproto(unsigned char protocol) 176 { 177 switch (protocol) { 178 case IPPROTO_ESP: 179 return &esp4_protocol; 180 case IPPROTO_AH: 181 return &ah4_protocol; 182 case IPPROTO_COMP: 183 return &ipcomp4_protocol; 184 } 185 186 return NULL; 187 } 188 189 int xfrm4_protocol_register(struct xfrm4_protocol *handler, 190 unsigned char protocol) 191 { 192 struct xfrm4_protocol __rcu **pprev; 193 struct xfrm4_protocol *t; 194 bool add_netproto = false; 195 196 int ret = -EEXIST; 197 int priority = handler->priority; 198 199 mutex_lock(&xfrm4_protocol_mutex); 200 201 if (!rcu_dereference_protected(*proto_handlers(protocol), 202 lockdep_is_held(&xfrm4_protocol_mutex))) 203 add_netproto = true; 204 205 for (pprev = proto_handlers(protocol); 206 (t = rcu_dereference_protected(*pprev, 207 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; 208 pprev = &t->next) { 209 if (t->priority < priority) 210 break; 211 if (t->priority == priority) 212 goto err; 213 } 214 215 handler->next = *pprev; 216 rcu_assign_pointer(*pprev, handler); 217 218 ret = 0; 219 220 err: 221 mutex_unlock(&xfrm4_protocol_mutex); 222 223 if (add_netproto) { 224 if (inet_add_protocol(netproto(protocol), protocol)) { 225 pr_err("%s: can't add protocol\n", __func__); 226 ret = -EAGAIN; 227 } 228 } 229 230 return ret; 231 } 232 EXPORT_SYMBOL(xfrm4_protocol_register); 233 234 int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, 235 unsigned char protocol) 236 { 237 struct xfrm4_protocol __rcu **pprev; 238 struct xfrm4_protocol *t; 239 int ret = -ENOENT; 240 241 mutex_lock(&xfrm4_protocol_mutex); 242 243 for (pprev = proto_handlers(protocol); 244 (t = rcu_dereference_protected(*pprev, 245 lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; 246 pprev = &t->next) { 247 if (t == handler) { 248 *pprev = handler->next; 249 ret = 0; 250 break; 251 } 252 } 253 254 if (!rcu_dereference_protected(*proto_handlers(protocol), 255 lockdep_is_held(&xfrm4_protocol_mutex))) { 256 if (inet_del_protocol(netproto(protocol), protocol) < 0) { 257 pr_err("%s: can't remove protocol\n", __func__); 258 ret = -EAGAIN; 259 } 260 } 261 262 mutex_unlock(&xfrm4_protocol_mutex); 263 264 synchronize_net(); 265 266 return ret; 267 } 268 EXPORT_SYMBOL(xfrm4_protocol_deregister); 269