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 10 int 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 50 error: 51 if (sock) { 52 kernel_sock_shutdown(sock, SHUT_RDWR); 53 sock_release(sock); 54 } 55 *sockp = NULL; 56 return err; 57 } 58 EXPORT_SYMBOL(udp_sock_create4); 59 60 void 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_clear_bit(MC_LOOP, sk); 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_rcv = cfg->encap_err_rcv; 76 udp_sk(sk)->encap_err_lookup = cfg->encap_err_lookup; 77 udp_sk(sk)->encap_destroy = cfg->encap_destroy; 78 udp_sk(sk)->gro_receive = cfg->gro_receive; 79 udp_sk(sk)->gro_complete = cfg->gro_complete; 80 81 udp_tunnel_encap_enable(sk); 82 } 83 EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); 84 85 void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock, 86 unsigned short type) 87 { 88 struct sock *sk = sock->sk; 89 struct udp_tunnel_info ti; 90 91 ti.type = type; 92 ti.sa_family = sk->sk_family; 93 ti.port = inet_sk(sk)->inet_sport; 94 95 udp_tunnel_nic_add_port(dev, &ti); 96 } 97 EXPORT_SYMBOL_GPL(udp_tunnel_push_rx_port); 98 99 void udp_tunnel_drop_rx_port(struct net_device *dev, struct socket *sock, 100 unsigned short type) 101 { 102 struct sock *sk = sock->sk; 103 struct udp_tunnel_info ti; 104 105 ti.type = type; 106 ti.sa_family = sk->sk_family; 107 ti.port = inet_sk(sk)->inet_sport; 108 109 udp_tunnel_nic_del_port(dev, &ti); 110 } 111 EXPORT_SYMBOL_GPL(udp_tunnel_drop_rx_port); 112 113 /* Notify netdevs that UDP port started listening */ 114 void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type) 115 { 116 struct sock *sk = sock->sk; 117 struct net *net = sock_net(sk); 118 struct udp_tunnel_info ti; 119 struct net_device *dev; 120 121 ti.type = type; 122 ti.sa_family = sk->sk_family; 123 ti.port = inet_sk(sk)->inet_sport; 124 125 rcu_read_lock(); 126 for_each_netdev_rcu(net, dev) { 127 udp_tunnel_nic_add_port(dev, &ti); 128 } 129 rcu_read_unlock(); 130 } 131 EXPORT_SYMBOL_GPL(udp_tunnel_notify_add_rx_port); 132 133 /* Notify netdevs that UDP port is no more listening */ 134 void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type) 135 { 136 struct sock *sk = sock->sk; 137 struct net *net = sock_net(sk); 138 struct udp_tunnel_info ti; 139 struct net_device *dev; 140 141 ti.type = type; 142 ti.sa_family = sk->sk_family; 143 ti.port = inet_sk(sk)->inet_sport; 144 145 rcu_read_lock(); 146 for_each_netdev_rcu(net, dev) { 147 udp_tunnel_nic_del_port(dev, &ti); 148 } 149 rcu_read_unlock(); 150 } 151 EXPORT_SYMBOL_GPL(udp_tunnel_notify_del_rx_port); 152 153 void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, 154 __be32 src, __be32 dst, __u8 tos, __u8 ttl, 155 __be16 df, __be16 src_port, __be16 dst_port, 156 bool xnet, bool nocheck) 157 { 158 struct udphdr *uh; 159 160 __skb_push(skb, sizeof(*uh)); 161 skb_reset_transport_header(skb); 162 uh = udp_hdr(skb); 163 164 uh->dest = dst_port; 165 uh->source = src_port; 166 uh->len = htons(skb->len); 167 168 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 169 170 udp_set_csum(nocheck, skb, src, dst, skb->len); 171 172 iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet); 173 } 174 EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); 175 176 void udp_tunnel_sock_release(struct socket *sock) 177 { 178 rcu_assign_sk_user_data(sock->sk, NULL); 179 synchronize_rcu(); 180 kernel_sock_shutdown(sock, SHUT_RDWR); 181 sock_release(sock); 182 } 183 EXPORT_SYMBOL_GPL(udp_tunnel_sock_release); 184 185 struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb, unsigned short family, 186 const unsigned long *flags, 187 __be64 tunnel_id, int md_size) 188 { 189 struct metadata_dst *tun_dst; 190 struct ip_tunnel_info *info; 191 192 if (family == AF_INET) 193 tun_dst = ip_tun_rx_dst(skb, flags, tunnel_id, md_size); 194 else 195 tun_dst = ipv6_tun_rx_dst(skb, flags, tunnel_id, md_size); 196 if (!tun_dst) 197 return NULL; 198 199 info = &tun_dst->u.tun_info; 200 info->key.tp_src = udp_hdr(skb)->source; 201 info->key.tp_dst = udp_hdr(skb)->dest; 202 if (udp_hdr(skb)->check) 203 __set_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags); 204 return tun_dst; 205 } 206 EXPORT_SYMBOL_GPL(udp_tun_rx_dst); 207 208 struct rtable *udp_tunnel_dst_lookup(struct sk_buff *skb, 209 struct net_device *dev, 210 struct net *net, int oif, 211 __be32 *saddr, 212 const struct ip_tunnel_key *key, 213 __be16 sport, __be16 dport, u8 tos, 214 struct dst_cache *dst_cache) 215 { 216 struct rtable *rt = NULL; 217 struct flowi4 fl4; 218 219 #ifdef CONFIG_DST_CACHE 220 if (dst_cache) { 221 rt = dst_cache_get_ip4(dst_cache, saddr); 222 if (rt) 223 return rt; 224 } 225 #endif 226 227 memset(&fl4, 0, sizeof(fl4)); 228 fl4.flowi4_mark = skb->mark; 229 fl4.flowi4_proto = IPPROTO_UDP; 230 fl4.flowi4_oif = oif; 231 fl4.daddr = key->u.ipv4.dst; 232 fl4.saddr = key->u.ipv4.src; 233 fl4.fl4_dport = dport; 234 fl4.fl4_sport = sport; 235 fl4.flowi4_tos = RT_TOS(tos); 236 fl4.flowi4_flags = key->flow_flags; 237 238 rt = ip_route_output_key(net, &fl4); 239 if (IS_ERR(rt)) { 240 netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr); 241 return ERR_PTR(-ENETUNREACH); 242 } 243 if (rt->dst.dev == dev) { /* is this necessary? */ 244 netdev_dbg(dev, "circular route to %pI4\n", &fl4.daddr); 245 ip_rt_put(rt); 246 return ERR_PTR(-ELOOP); 247 } 248 #ifdef CONFIG_DST_CACHE 249 if (dst_cache) 250 dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); 251 #endif 252 *saddr = fl4.saddr; 253 return rt; 254 } 255 EXPORT_SYMBOL_GPL(udp_tunnel_dst_lookup); 256 257 MODULE_DESCRIPTION("IPv4 Foo over UDP tunnel driver"); 258 MODULE_LICENSE("GPL"); 259
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.