root/net/ipv4/udp_tunnel.c

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

DEFINITIONS

This source file includes following definitions.
  1. udp_sock_create4
  2. setup_udp_tunnel_sock
  3. udp_tunnel_push_rx_port
  4. udp_tunnel_drop_rx_port
  5. udp_tunnel_notify_add_rx_port
  6. udp_tunnel_notify_del_rx_port
  7. udp_tunnel_xmit_skb
  8. udp_tunnel_sock_release
  9. udp_tun_rx_dst

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

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