Blame view
net/ipv6/ip6_udp_tunnel.c
2.69 KB
09c434b8a
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
fd384412e
|
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <linux/module.h> #include <linux/errno.h> #include <linux/socket.h> #include <linux/udp.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/in6.h> #include <net/udp.h> #include <net/udp_tunnel.h> #include <net/net_namespace.h> #include <net/netns/generic.h> #include <net/ip6_tunnel.h> #include <net/ip6_checksum.h> int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, struct socket **sockp) { |
fb2427454
|
19 |
struct sockaddr_in6 udp6_addr = {}; |
fd384412e
|
20 21 |
int err; struct socket *sock = NULL; |
26abe1437
|
22 |
err = sock_create_kern(net, AF_INET6, SOCK_DGRAM, 0, &sock); |
fd384412e
|
23 24 |
if (err < 0) goto error; |
a43a9ef6a
|
25 |
if (cfg->ipv6_v6only) { |
9b115749a
|
26 |
err = ip6_sock_set_v6only(sock->sk); |
a43a9ef6a
|
27 28 29 |
if (err < 0) goto error; } |
da5095d05
|
30 |
if (cfg->bind_ifindex) { |
8ea204c2b
|
31 |
err = sock_bindtoindex(sock->sk, cfg->bind_ifindex, true); |
da5095d05
|
32 33 34 |
if (err < 0) goto error; } |
a43a9ef6a
|
35 |
|
fd384412e
|
36 37 38 39 40 41 42 43 44 45 |
udp6_addr.sin6_family = AF_INET6; memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6, sizeof(udp6_addr.sin6_addr)); udp6_addr.sin6_port = cfg->local_udp_port; err = kernel_bind(sock, (struct sockaddr *)&udp6_addr, sizeof(udp6_addr)); if (err < 0) goto error; if (cfg->peer_udp_port) { |
fb2427454
|
46 |
memset(&udp6_addr, 0, sizeof(udp6_addr)); |
fd384412e
|
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
udp6_addr.sin6_family = AF_INET6; memcpy(&udp6_addr.sin6_addr, &cfg->peer_ip6, sizeof(udp6_addr.sin6_addr)); udp6_addr.sin6_port = cfg->peer_udp_port; err = kernel_connect(sock, (struct sockaddr *)&udp6_addr, sizeof(udp6_addr), 0); } if (err < 0) goto error; udp_set_no_check6_tx(sock->sk, !cfg->use_udp6_tx_checksums); udp_set_no_check6_rx(sock->sk, !cfg->use_udp6_rx_checksums); *sockp = sock; return 0; error: if (sock) { kernel_sock_shutdown(sock, SHUT_RDWR); |
26abe1437
|
67 |
sock_release(sock); |
fd384412e
|
68 69 70 71 72 |
} *sockp = NULL; return err; } EXPORT_SYMBOL_GPL(udp_sock_create6); |
6a93cc905
|
73 |
|
79b16aade
|
74 75 |
int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, |
d998f8efa
|
76 77 |
struct net_device *dev, struct in6_addr *saddr, struct in6_addr *daddr, |
134611446
|
78 79 |
__u8 prio, __u8 ttl, __be32 label, __be16 src_port, __be16 dst_port, bool nocheck) |
6a93cc905
|
80 81 82 |
{ struct udphdr *uh; struct ipv6hdr *ip6h; |
6a93cc905
|
83 84 85 86 87 88 89 90 91 |
__skb_push(skb, sizeof(*uh)); skb_reset_transport_header(skb); uh = udp_hdr(skb); uh->dest = dst_port; uh->source = src_port; uh->len = htons(skb->len); |
6a93cc905
|
92 |
|
6a93cc905
|
93 |
skb_dst_set(skb, dst); |
d998f8efa
|
94 |
udp6_set_csum(nocheck, skb, saddr, daddr, skb->len); |
6a93cc905
|
95 96 97 98 |
__skb_push(skb, sizeof(*ip6h)); skb_reset_network_header(skb); ip6h = ipv6_hdr(skb); |
134611446
|
99 |
ip6_flow_hdr(ip6h, prio, label); |
6a93cc905
|
100 101 102 103 104 |
ip6h->payload_len = htons(skb->len); ip6h->nexthdr = IPPROTO_UDP; ip6h->hop_limit = ttl; ip6h->daddr = *daddr; ip6h->saddr = *saddr; |
79b16aade
|
105 |
ip6tunnel_xmit(sk, skb, dev); |
6a93cc905
|
106 107 108 |
return 0; } EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb); |
3fcb95a84
|
109 110 |
MODULE_LICENSE("GPL"); |