~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv4/udp_tunnel_core.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php