linux/net/ipv4/tunnel4.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* tunnel4.c: Generic IP tunnel transformer.
   3 *
   4 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
   5 */
   6
   7#include <linux/init.h>
   8#include <linux/module.h>
   9#include <linux/mutex.h>
  10#include <linux/mpls.h>
  11#include <linux/netdevice.h>
  12#include <linux/skbuff.h>
  13#include <linux/slab.h>
  14#include <net/icmp.h>
  15#include <net/ip.h>
  16#include <net/protocol.h>
  17#include <net/xfrm.h>
  18
  19static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly;
  20static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly;
  21static struct xfrm_tunnel __rcu *tunnelmpls4_handlers __read_mostly;
  22static DEFINE_MUTEX(tunnel4_mutex);
  23
  24static inline struct xfrm_tunnel __rcu **fam_handlers(unsigned short family)
  25{
  26        return (family == AF_INET) ? &tunnel4_handlers :
  27                (family == AF_INET6) ? &tunnel64_handlers :
  28                &tunnelmpls4_handlers;
  29}
  30
  31int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
  32{
  33        struct xfrm_tunnel __rcu **pprev;
  34        struct xfrm_tunnel *t;
  35
  36        int ret = -EEXIST;
  37        int priority = handler->priority;
  38
  39        mutex_lock(&tunnel4_mutex);
  40
  41        for (pprev = fam_handlers(family);
  42             (t = rcu_dereference_protected(*pprev,
  43                        lockdep_is_held(&tunnel4_mutex))) != NULL;
  44             pprev = &t->next) {
  45                if (t->priority > priority)
  46                        break;
  47                if (t->priority == priority)
  48                        goto err;
  49        }
  50
  51        handler->next = *pprev;
  52        rcu_assign_pointer(*pprev, handler);
  53
  54        ret = 0;
  55
  56err:
  57        mutex_unlock(&tunnel4_mutex);
  58
  59        return ret;
  60}
  61EXPORT_SYMBOL(xfrm4_tunnel_register);
  62
  63int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
  64{
  65        struct xfrm_tunnel __rcu **pprev;
  66        struct xfrm_tunnel *t;
  67        int ret = -ENOENT;
  68
  69        mutex_lock(&tunnel4_mutex);
  70
  71        for (pprev = fam_handlers(family);
  72             (t = rcu_dereference_protected(*pprev,
  73                        lockdep_is_held(&tunnel4_mutex))) != NULL;
  74             pprev = &t->next) {
  75                if (t == handler) {
  76                        *pprev = handler->next;
  77                        ret = 0;
  78                        break;
  79                }
  80        }
  81
  82        mutex_unlock(&tunnel4_mutex);
  83
  84        synchronize_net();
  85
  86        return ret;
  87}
  88EXPORT_SYMBOL(xfrm4_tunnel_deregister);
  89
  90#define for_each_tunnel_rcu(head, handler)              \
  91        for (handler = rcu_dereference(head);           \
  92             handler != NULL;                           \
  93             handler = rcu_dereference(handler->next))  \
  94
  95static int tunnel4_rcv(struct sk_buff *skb)
  96{
  97        struct xfrm_tunnel *handler;
  98
  99        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 100                goto drop;
 101
 102        for_each_tunnel_rcu(tunnel4_handlers, handler)
 103                if (!handler->handler(skb))
 104                        return 0;
 105
 106        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 107
 108drop:
 109        kfree_skb(skb);
 110        return 0;
 111}
 112
 113#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
 114static int tunnel4_rcv_cb(struct sk_buff *skb, u8 proto, int err)
 115{
 116        struct xfrm_tunnel __rcu *head;
 117        struct xfrm_tunnel *handler;
 118        int ret;
 119
 120        head = (proto == IPPROTO_IPIP) ? tunnel4_handlers : tunnel64_handlers;
 121
 122        for_each_tunnel_rcu(head, handler) {
 123                if (handler->cb_handler) {
 124                        ret = handler->cb_handler(skb, err);
 125                        if (ret <= 0)
 126                                return ret;
 127                }
 128        }
 129
 130        return 0;
 131}
 132
 133static const struct xfrm_input_afinfo tunnel4_input_afinfo = {
 134        .family         =       AF_INET,
 135        .is_ipip        =       true,
 136        .callback       =       tunnel4_rcv_cb,
 137};
 138#endif
 139
 140#if IS_ENABLED(CONFIG_IPV6)
 141static int tunnel64_rcv(struct sk_buff *skb)
 142{
 143        struct xfrm_tunnel *handler;
 144
 145        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 146                goto drop;
 147
 148        for_each_tunnel_rcu(tunnel64_handlers, handler)
 149                if (!handler->handler(skb))
 150                        return 0;
 151
 152        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 153
 154drop:
 155        kfree_skb(skb);
 156        return 0;
 157}
 158#endif
 159
 160#if IS_ENABLED(CONFIG_MPLS)
 161static int tunnelmpls4_rcv(struct sk_buff *skb)
 162{
 163        struct xfrm_tunnel *handler;
 164
 165        if (!pskb_may_pull(skb, sizeof(struct mpls_label)))
 166                goto drop;
 167
 168        for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
 169                if (!handler->handler(skb))
 170                        return 0;
 171
 172        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 173
 174drop:
 175        kfree_skb(skb);
 176        return 0;
 177}
 178#endif
 179
 180static int tunnel4_err(struct sk_buff *skb, u32 info)
 181{
 182        struct xfrm_tunnel *handler;
 183
 184        for_each_tunnel_rcu(tunnel4_handlers, handler)
 185                if (!handler->err_handler(skb, info))
 186                        return 0;
 187
 188        return -ENOENT;
 189}
 190
 191#if IS_ENABLED(CONFIG_IPV6)
 192static int tunnel64_err(struct sk_buff *skb, u32 info)
 193{
 194        struct xfrm_tunnel *handler;
 195
 196        for_each_tunnel_rcu(tunnel64_handlers, handler)
 197                if (!handler->err_handler(skb, info))
 198                        return 0;
 199
 200        return -ENOENT;
 201}
 202#endif
 203
 204#if IS_ENABLED(CONFIG_MPLS)
 205static int tunnelmpls4_err(struct sk_buff *skb, u32 info)
 206{
 207        struct xfrm_tunnel *handler;
 208
 209        for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
 210                if (!handler->err_handler(skb, info))
 211                        return 0;
 212
 213        return -ENOENT;
 214}
 215#endif
 216
 217static const struct net_protocol tunnel4_protocol = {
 218        .handler        =       tunnel4_rcv,
 219        .err_handler    =       tunnel4_err,
 220        .no_policy      =       1,
 221};
 222
 223#if IS_ENABLED(CONFIG_IPV6)
 224static const struct net_protocol tunnel64_protocol = {
 225        .handler        =       tunnel64_rcv,
 226        .err_handler    =       tunnel64_err,
 227        .no_policy      =       1,
 228};
 229#endif
 230
 231#if IS_ENABLED(CONFIG_MPLS)
 232static const struct net_protocol tunnelmpls4_protocol = {
 233        .handler        =       tunnelmpls4_rcv,
 234        .err_handler    =       tunnelmpls4_err,
 235        .no_policy      =       1,
 236};
 237#endif
 238
 239static int __init tunnel4_init(void)
 240{
 241        if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 242                goto err;
 243#if IS_ENABLED(CONFIG_IPV6)
 244        if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
 245                inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 246                goto err;
 247        }
 248#endif
 249#if IS_ENABLED(CONFIG_MPLS)
 250        if (inet_add_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS)) {
 251                inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 252#if IS_ENABLED(CONFIG_IPV6)
 253                inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6);
 254#endif
 255                goto err;
 256        }
 257#endif
 258#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
 259        if (xfrm_input_register_afinfo(&tunnel4_input_afinfo)) {
 260                inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 261#if IS_ENABLED(CONFIG_IPV6)
 262                inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6);
 263#endif
 264#if IS_ENABLED(CONFIG_MPLS)
 265                inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS);
 266#endif
 267                goto err;
 268        }
 269#endif
 270        return 0;
 271
 272err:
 273        pr_err("%s: can't add protocol\n", __func__);
 274        return -EAGAIN;
 275}
 276
 277static void __exit tunnel4_fini(void)
 278{
 279#if IS_ENABLED(CONFIG_INET_XFRM_TUNNEL)
 280        if (xfrm_input_unregister_afinfo(&tunnel4_input_afinfo))
 281                pr_err("tunnel4 close: can't remove input afinfo\n");
 282#endif
 283#if IS_ENABLED(CONFIG_MPLS)
 284        if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
 285                pr_err("tunnelmpls4 close: can't remove protocol\n");
 286#endif
 287#if IS_ENABLED(CONFIG_IPV6)
 288        if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
 289                pr_err("tunnel64 close: can't remove protocol\n");
 290#endif
 291        if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 292                pr_err("tunnel4 close: can't remove protocol\n");
 293}
 294
 295module_init(tunnel4_init);
 296module_exit(tunnel4_fini);
 297MODULE_LICENSE("GPL");
 298