root/net/ipv4/tunnel4.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fam_handlers
  2. xfrm4_tunnel_register
  3. xfrm4_tunnel_deregister
  4. tunnel4_rcv
  5. tunnel64_rcv
  6. tunnelmpls4_rcv
  7. tunnel4_err
  8. tunnel64_err
  9. tunnelmpls4_err
  10. tunnel4_init
  11. tunnel4_fini

   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 
  19 static struct xfrm_tunnel __rcu *tunnel4_handlers __read_mostly;
  20 static struct xfrm_tunnel __rcu *tunnel64_handlers __read_mostly;
  21 static struct xfrm_tunnel __rcu *tunnelmpls4_handlers __read_mostly;
  22 static DEFINE_MUTEX(tunnel4_mutex);
  23 
  24 static 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 
  31 int 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 
  56 err:
  57         mutex_unlock(&tunnel4_mutex);
  58 
  59         return ret;
  60 }
  61 EXPORT_SYMBOL(xfrm4_tunnel_register);
  62 
  63 int 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 }
  88 EXPORT_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 
  95 static 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 
 108 drop:
 109         kfree_skb(skb);
 110         return 0;
 111 }
 112 
 113 #if IS_ENABLED(CONFIG_IPV6)
 114 static int tunnel64_rcv(struct sk_buff *skb)
 115 {
 116         struct xfrm_tunnel *handler;
 117 
 118         if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
 119                 goto drop;
 120 
 121         for_each_tunnel_rcu(tunnel64_handlers, handler)
 122                 if (!handler->handler(skb))
 123                         return 0;
 124 
 125         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 126 
 127 drop:
 128         kfree_skb(skb);
 129         return 0;
 130 }
 131 #endif
 132 
 133 #if IS_ENABLED(CONFIG_MPLS)
 134 static int tunnelmpls4_rcv(struct sk_buff *skb)
 135 {
 136         struct xfrm_tunnel *handler;
 137 
 138         if (!pskb_may_pull(skb, sizeof(struct mpls_label)))
 139                 goto drop;
 140 
 141         for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
 142                 if (!handler->handler(skb))
 143                         return 0;
 144 
 145         icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 146 
 147 drop:
 148         kfree_skb(skb);
 149         return 0;
 150 }
 151 #endif
 152 
 153 static int tunnel4_err(struct sk_buff *skb, u32 info)
 154 {
 155         struct xfrm_tunnel *handler;
 156 
 157         for_each_tunnel_rcu(tunnel4_handlers, handler)
 158                 if (!handler->err_handler(skb, info))
 159                         return 0;
 160 
 161         return -ENOENT;
 162 }
 163 
 164 #if IS_ENABLED(CONFIG_IPV6)
 165 static int tunnel64_err(struct sk_buff *skb, u32 info)
 166 {
 167         struct xfrm_tunnel *handler;
 168 
 169         for_each_tunnel_rcu(tunnel64_handlers, handler)
 170                 if (!handler->err_handler(skb, info))
 171                         return 0;
 172 
 173         return -ENOENT;
 174 }
 175 #endif
 176 
 177 #if IS_ENABLED(CONFIG_MPLS)
 178 static int tunnelmpls4_err(struct sk_buff *skb, u32 info)
 179 {
 180         struct xfrm_tunnel *handler;
 181 
 182         for_each_tunnel_rcu(tunnelmpls4_handlers, handler)
 183                 if (!handler->err_handler(skb, info))
 184                         return 0;
 185 
 186         return -ENOENT;
 187 }
 188 #endif
 189 
 190 static const struct net_protocol tunnel4_protocol = {
 191         .handler        =       tunnel4_rcv,
 192         .err_handler    =       tunnel4_err,
 193         .no_policy      =       1,
 194         .netns_ok       =       1,
 195 };
 196 
 197 #if IS_ENABLED(CONFIG_IPV6)
 198 static const struct net_protocol tunnel64_protocol = {
 199         .handler        =       tunnel64_rcv,
 200         .err_handler    =       tunnel64_err,
 201         .no_policy      =       1,
 202         .netns_ok       =       1,
 203 };
 204 #endif
 205 
 206 #if IS_ENABLED(CONFIG_MPLS)
 207 static const struct net_protocol tunnelmpls4_protocol = {
 208         .handler        =       tunnelmpls4_rcv,
 209         .err_handler    =       tunnelmpls4_err,
 210         .no_policy      =       1,
 211         .netns_ok       =       1,
 212 };
 213 #endif
 214 
 215 static int __init tunnel4_init(void)
 216 {
 217         if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 218                 goto err;
 219 #if IS_ENABLED(CONFIG_IPV6)
 220         if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
 221                 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 222                 goto err;
 223         }
 224 #endif
 225 #if IS_ENABLED(CONFIG_MPLS)
 226         if (inet_add_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS)) {
 227                 inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
 228 #if IS_ENABLED(CONFIG_IPV6)
 229                 inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6);
 230 #endif
 231                 goto err;
 232         }
 233 #endif
 234         return 0;
 235 
 236 err:
 237         pr_err("%s: can't add protocol\n", __func__);
 238         return -EAGAIN;
 239 }
 240 
 241 static void __exit tunnel4_fini(void)
 242 {
 243 #if IS_ENABLED(CONFIG_MPLS)
 244         if (inet_del_protocol(&tunnelmpls4_protocol, IPPROTO_MPLS))
 245                 pr_err("tunnelmpls4 close: can't remove protocol\n");
 246 #endif
 247 #if IS_ENABLED(CONFIG_IPV6)
 248         if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
 249                 pr_err("tunnel64 close: can't remove protocol\n");
 250 #endif
 251         if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
 252                 pr_err("tunnel4 close: can't remove protocol\n");
 253 }
 254 
 255 module_init(tunnel4_init);
 256 module_exit(tunnel4_fini);
 257 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */