0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/mutex.h>
0015 #include <linux/skbuff.h>
0016 #include <linux/icmpv6.h>
0017 #include <net/ip6_route.h>
0018 #include <net/ipv6.h>
0019 #include <net/protocol.h>
0020 #include <net/xfrm.h>
0021
0022 static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly;
0023 static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly;
0024 static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly;
0025 static DEFINE_MUTEX(xfrm6_protocol_mutex);
0026
0027 static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
0028 {
0029 switch (protocol) {
0030 case IPPROTO_ESP:
0031 return &esp6_handlers;
0032 case IPPROTO_AH:
0033 return &ah6_handlers;
0034 case IPPROTO_COMP:
0035 return &ipcomp6_handlers;
0036 }
0037
0038 return NULL;
0039 }
0040
0041 #define for_each_protocol_rcu(head, handler) \
0042 for (handler = rcu_dereference(head); \
0043 handler != NULL; \
0044 handler = rcu_dereference(handler->next)) \
0045
0046 static int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
0047 {
0048 int ret;
0049 struct xfrm6_protocol *handler;
0050 struct xfrm6_protocol __rcu **head = proto_handlers(protocol);
0051
0052 if (!head)
0053 return 0;
0054
0055 for_each_protocol_rcu(*proto_handlers(protocol), handler)
0056 if ((ret = handler->cb_handler(skb, err)) <= 0)
0057 return ret;
0058
0059 return 0;
0060 }
0061
0062 int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
0063 int encap_type)
0064 {
0065 int ret;
0066 struct xfrm6_protocol *handler;
0067 struct xfrm6_protocol __rcu **head = proto_handlers(nexthdr);
0068
0069 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
0070 XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
0071 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
0072
0073 if (!head)
0074 goto out;
0075
0076 if (!skb_dst(skb)) {
0077 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
0078 int flags = RT6_LOOKUP_F_HAS_SADDR;
0079 struct dst_entry *dst;
0080 struct flowi6 fl6 = {
0081 .flowi6_iif = skb->dev->ifindex,
0082 .daddr = ip6h->daddr,
0083 .saddr = ip6h->saddr,
0084 .flowlabel = ip6_flowinfo(ip6h),
0085 .flowi6_mark = skb->mark,
0086 .flowi6_proto = ip6h->nexthdr,
0087 };
0088
0089 dst = ip6_route_input_lookup(dev_net(skb->dev), skb->dev, &fl6,
0090 skb, flags);
0091 if (dst->error)
0092 goto drop;
0093 skb_dst_set(skb, dst);
0094 }
0095
0096 for_each_protocol_rcu(*head, handler)
0097 if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
0098 return ret;
0099
0100 out:
0101 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
0102
0103 drop:
0104 kfree_skb(skb);
0105 return 0;
0106 }
0107 EXPORT_SYMBOL(xfrm6_rcv_encap);
0108
0109 static int xfrm6_esp_rcv(struct sk_buff *skb)
0110 {
0111 int ret;
0112 struct xfrm6_protocol *handler;
0113
0114 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
0115
0116 for_each_protocol_rcu(esp6_handlers, handler)
0117 if ((ret = handler->handler(skb)) != -EINVAL)
0118 return ret;
0119
0120 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
0121
0122 kfree_skb(skb);
0123 return 0;
0124 }
0125
0126 static int xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
0127 u8 type, u8 code, int offset, __be32 info)
0128 {
0129 struct xfrm6_protocol *handler;
0130
0131 for_each_protocol_rcu(esp6_handlers, handler)
0132 if (!handler->err_handler(skb, opt, type, code, offset, info))
0133 return 0;
0134
0135 return -ENOENT;
0136 }
0137
0138 static int xfrm6_ah_rcv(struct sk_buff *skb)
0139 {
0140 int ret;
0141 struct xfrm6_protocol *handler;
0142
0143 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
0144
0145 for_each_protocol_rcu(ah6_handlers, handler)
0146 if ((ret = handler->handler(skb)) != -EINVAL)
0147 return ret;
0148
0149 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
0150
0151 kfree_skb(skb);
0152 return 0;
0153 }
0154
0155 static int xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
0156 u8 type, u8 code, int offset, __be32 info)
0157 {
0158 struct xfrm6_protocol *handler;
0159
0160 for_each_protocol_rcu(ah6_handlers, handler)
0161 if (!handler->err_handler(skb, opt, type, code, offset, info))
0162 return 0;
0163
0164 return -ENOENT;
0165 }
0166
0167 static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
0168 {
0169 int ret;
0170 struct xfrm6_protocol *handler;
0171
0172 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
0173
0174 for_each_protocol_rcu(ipcomp6_handlers, handler)
0175 if ((ret = handler->handler(skb)) != -EINVAL)
0176 return ret;
0177
0178 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
0179
0180 kfree_skb(skb);
0181 return 0;
0182 }
0183
0184 static int xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
0185 u8 type, u8 code, int offset, __be32 info)
0186 {
0187 struct xfrm6_protocol *handler;
0188
0189 for_each_protocol_rcu(ipcomp6_handlers, handler)
0190 if (!handler->err_handler(skb, opt, type, code, offset, info))
0191 return 0;
0192
0193 return -ENOENT;
0194 }
0195
0196 static const struct inet6_protocol esp6_protocol = {
0197 .handler = xfrm6_esp_rcv,
0198 .err_handler = xfrm6_esp_err,
0199 .flags = INET6_PROTO_NOPOLICY,
0200 };
0201
0202 static const struct inet6_protocol ah6_protocol = {
0203 .handler = xfrm6_ah_rcv,
0204 .err_handler = xfrm6_ah_err,
0205 .flags = INET6_PROTO_NOPOLICY,
0206 };
0207
0208 static const struct inet6_protocol ipcomp6_protocol = {
0209 .handler = xfrm6_ipcomp_rcv,
0210 .err_handler = xfrm6_ipcomp_err,
0211 .flags = INET6_PROTO_NOPOLICY,
0212 };
0213
0214 static const struct xfrm_input_afinfo xfrm6_input_afinfo = {
0215 .family = AF_INET6,
0216 .callback = xfrm6_rcv_cb,
0217 };
0218
0219 static inline const struct inet6_protocol *netproto(unsigned char protocol)
0220 {
0221 switch (protocol) {
0222 case IPPROTO_ESP:
0223 return &esp6_protocol;
0224 case IPPROTO_AH:
0225 return &ah6_protocol;
0226 case IPPROTO_COMP:
0227 return &ipcomp6_protocol;
0228 }
0229
0230 return NULL;
0231 }
0232
0233 int xfrm6_protocol_register(struct xfrm6_protocol *handler,
0234 unsigned char protocol)
0235 {
0236 struct xfrm6_protocol __rcu **pprev;
0237 struct xfrm6_protocol *t;
0238 bool add_netproto = false;
0239 int ret = -EEXIST;
0240 int priority = handler->priority;
0241
0242 if (!proto_handlers(protocol) || !netproto(protocol))
0243 return -EINVAL;
0244
0245 mutex_lock(&xfrm6_protocol_mutex);
0246
0247 if (!rcu_dereference_protected(*proto_handlers(protocol),
0248 lockdep_is_held(&xfrm6_protocol_mutex)))
0249 add_netproto = true;
0250
0251 for (pprev = proto_handlers(protocol);
0252 (t = rcu_dereference_protected(*pprev,
0253 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
0254 pprev = &t->next) {
0255 if (t->priority < priority)
0256 break;
0257 if (t->priority == priority)
0258 goto err;
0259 }
0260
0261 handler->next = *pprev;
0262 rcu_assign_pointer(*pprev, handler);
0263
0264 ret = 0;
0265
0266 err:
0267 mutex_unlock(&xfrm6_protocol_mutex);
0268
0269 if (add_netproto) {
0270 if (inet6_add_protocol(netproto(protocol), protocol)) {
0271 pr_err("%s: can't add protocol\n", __func__);
0272 ret = -EAGAIN;
0273 }
0274 }
0275
0276 return ret;
0277 }
0278 EXPORT_SYMBOL(xfrm6_protocol_register);
0279
0280 int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
0281 unsigned char protocol)
0282 {
0283 struct xfrm6_protocol __rcu **pprev;
0284 struct xfrm6_protocol *t;
0285 int ret = -ENOENT;
0286
0287 if (!proto_handlers(protocol) || !netproto(protocol))
0288 return -EINVAL;
0289
0290 mutex_lock(&xfrm6_protocol_mutex);
0291
0292 for (pprev = proto_handlers(protocol);
0293 (t = rcu_dereference_protected(*pprev,
0294 lockdep_is_held(&xfrm6_protocol_mutex))) != NULL;
0295 pprev = &t->next) {
0296 if (t == handler) {
0297 *pprev = handler->next;
0298 ret = 0;
0299 break;
0300 }
0301 }
0302
0303 if (!rcu_dereference_protected(*proto_handlers(protocol),
0304 lockdep_is_held(&xfrm6_protocol_mutex))) {
0305 if (inet6_del_protocol(netproto(protocol), protocol) < 0) {
0306 pr_err("%s: can't remove protocol\n", __func__);
0307 ret = -EAGAIN;
0308 }
0309 }
0310
0311 mutex_unlock(&xfrm6_protocol_mutex);
0312
0313 synchronize_net();
0314
0315 return ret;
0316 }
0317 EXPORT_SYMBOL(xfrm6_protocol_deregister);
0318
0319 int __init xfrm6_protocol_init(void)
0320 {
0321 return xfrm_input_register_afinfo(&xfrm6_input_afinfo);
0322 }
0323
0324 void xfrm6_protocol_fini(void)
0325 {
0326 xfrm_input_unregister_afinfo(&xfrm6_input_afinfo);
0327 }