cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tunnel4.c (6657B)


      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");