Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
0003  *
0004  * Copyright (C) 2013 secunet Security Networks AG
0005  *
0006  * Author:
0007  * Steffen Klassert <steffen.klassert@secunet.com>
0008  *
0009  * Based on:
0010  * net/ipv4/xfrm4_protocol.c
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 }