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