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