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

udp_tunnel_core.c (5123B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#include <linux/module.h>
      3#include <linux/errno.h>
      4#include <linux/socket.h>
      5#include <linux/kernel.h>
      6#include <net/dst_metadata.h>
      7#include <net/udp.h>
      8#include <net/udp_tunnel.h>
      9
     10int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
     11		     struct socket **sockp)
     12{
     13	int err;
     14	struct socket *sock = NULL;
     15	struct sockaddr_in udp_addr;
     16
     17	err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock);
     18	if (err < 0)
     19		goto error;
     20
     21	if (cfg->bind_ifindex) {
     22		err = sock_bindtoindex(sock->sk, cfg->bind_ifindex, true);
     23		if (err < 0)
     24			goto error;
     25	}
     26
     27	udp_addr.sin_family = AF_INET;
     28	udp_addr.sin_addr = cfg->local_ip;
     29	udp_addr.sin_port = cfg->local_udp_port;
     30	err = kernel_bind(sock, (struct sockaddr *)&udp_addr,
     31			  sizeof(udp_addr));
     32	if (err < 0)
     33		goto error;
     34
     35	if (cfg->peer_udp_port) {
     36		udp_addr.sin_family = AF_INET;
     37		udp_addr.sin_addr = cfg->peer_ip;
     38		udp_addr.sin_port = cfg->peer_udp_port;
     39		err = kernel_connect(sock, (struct sockaddr *)&udp_addr,
     40				     sizeof(udp_addr), 0);
     41		if (err < 0)
     42			goto error;
     43	}
     44
     45	sock->sk->sk_no_check_tx = !cfg->use_udp_checksums;
     46
     47	*sockp = sock;
     48	return 0;
     49
     50error:
     51	if (sock) {
     52		kernel_sock_shutdown(sock, SHUT_RDWR);
     53		sock_release(sock);
     54	}
     55	*sockp = NULL;
     56	return err;
     57}
     58EXPORT_SYMBOL(udp_sock_create4);
     59
     60void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
     61			   struct udp_tunnel_sock_cfg *cfg)
     62{
     63	struct sock *sk = sock->sk;
     64
     65	/* Disable multicast loopback */
     66	inet_sk(sk)->mc_loop = 0;
     67
     68	/* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
     69	inet_inc_convert_csum(sk);
     70
     71	rcu_assign_sk_user_data(sk, cfg->sk_user_data);
     72
     73	udp_sk(sk)->encap_type = cfg->encap_type;
     74	udp_sk(sk)->encap_rcv = cfg->encap_rcv;
     75	udp_sk(sk)->encap_err_lookup = cfg->encap_err_lookup;
     76	udp_sk(sk)->encap_destroy = cfg->encap_destroy;
     77	udp_sk(sk)->gro_receive = cfg->gro_receive;
     78	udp_sk(sk)->gro_complete = cfg->gro_complete;
     79
     80	udp_tunnel_encap_enable(sock);
     81}
     82EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
     83
     84void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock,
     85			     unsigned short type)
     86{
     87	struct sock *sk = sock->sk;
     88	struct udp_tunnel_info ti;
     89
     90	ti.type = type;
     91	ti.sa_family = sk->sk_family;
     92	ti.port = inet_sk(sk)->inet_sport;
     93
     94	udp_tunnel_nic_add_port(dev, &ti);
     95}
     96EXPORT_SYMBOL_GPL(udp_tunnel_push_rx_port);
     97
     98void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock,
     99			     unsigned short type)
    100{
    101	struct sock *sk = sock->sk;
    102	struct udp_tunnel_info ti;
    103
    104	ti.type = type;
    105	ti.sa_family = sk->sk_family;
    106	ti.port = inet_sk(sk)->inet_sport;
    107
    108	udp_tunnel_nic_del_port(dev, &ti);
    109}
    110EXPORT_SYMBOL_GPL(udp_tunnel_drop_rx_port);
    111
    112/* Notify netdevs that UDP port started listening */
    113void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type)
    114{
    115	struct sock *sk = sock->sk;
    116	struct net *net = sock_net(sk);
    117	struct udp_tunnel_info ti;
    118	struct net_device *dev;
    119
    120	ti.type = type;
    121	ti.sa_family = sk->sk_family;
    122	ti.port = inet_sk(sk)->inet_sport;
    123
    124	rcu_read_lock();
    125	for_each_netdev_rcu(net, dev) {
    126		udp_tunnel_nic_add_port(dev, &ti);
    127	}
    128	rcu_read_unlock();
    129}
    130EXPORT_SYMBOL_GPL(udp_tunnel_notify_add_rx_port);
    131
    132/* Notify netdevs that UDP port is no more listening */
    133void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type)
    134{
    135	struct sock *sk = sock->sk;
    136	struct net *net = sock_net(sk);
    137	struct udp_tunnel_info ti;
    138	struct net_device *dev;
    139
    140	ti.type = type;
    141	ti.sa_family = sk->sk_family;
    142	ti.port = inet_sk(sk)->inet_sport;
    143
    144	rcu_read_lock();
    145	for_each_netdev_rcu(net, dev) {
    146		udp_tunnel_nic_del_port(dev, &ti);
    147	}
    148	rcu_read_unlock();
    149}
    150EXPORT_SYMBOL_GPL(udp_tunnel_notify_del_rx_port);
    151
    152void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
    153			 __be32 src, __be32 dst, __u8 tos, __u8 ttl,
    154			 __be16 df, __be16 src_port, __be16 dst_port,
    155			 bool xnet, bool nocheck)
    156{
    157	struct udphdr *uh;
    158
    159	__skb_push(skb, sizeof(*uh));
    160	skb_reset_transport_header(skb);
    161	uh = udp_hdr(skb);
    162
    163	uh->dest = dst_port;
    164	uh->source = src_port;
    165	uh->len = htons(skb->len);
    166
    167	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
    168
    169	udp_set_csum(nocheck, skb, src, dst, skb->len);
    170
    171	iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet);
    172}
    173EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
    174
    175void udp_tunnel_sock_release(struct socket *sock)
    176{
    177	rcu_assign_sk_user_data(sock->sk, NULL);
    178	kernel_sock_shutdown(sock, SHUT_RDWR);
    179	sock_release(sock);
    180}
    181EXPORT_SYMBOL_GPL(udp_tunnel_sock_release);
    182
    183struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb,  unsigned short family,
    184				    __be16 flags, __be64 tunnel_id, int md_size)
    185{
    186	struct metadata_dst *tun_dst;
    187	struct ip_tunnel_info *info;
    188
    189	if (family == AF_INET)
    190		tun_dst = ip_tun_rx_dst(skb, flags, tunnel_id, md_size);
    191	else
    192		tun_dst = ipv6_tun_rx_dst(skb, flags, tunnel_id, md_size);
    193	if (!tun_dst)
    194		return NULL;
    195
    196	info = &tun_dst->u.tun_info;
    197	info->key.tp_src = udp_hdr(skb)->source;
    198	info->key.tp_dst = udp_hdr(skb)->dest;
    199	if (udp_hdr(skb)->check)
    200		info->key.tun_flags |= TUNNEL_CSUM;
    201	return tun_dst;
    202}
    203EXPORT_SYMBOL_GPL(udp_tun_rx_dst);
    204
    205MODULE_LICENSE("GPL");