From 5f903d1fbf1a1fa41ca66704be4aa4c06cd1a8be Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 17 Feb 2026 16:19:45 +0000 Subject: [PATCH] chore(pmtud): remove calls to syscall in favor of unix and windows - syscall is deprecated and is not kept up-to-date - each OS is inherently different hence the syscall being deprecated --- .golangci.yml | 2 +- internal/pmtud/constants/syscall_unix.go | 16 +++++++ internal/pmtud/constants/syscall_windows.go | 13 ++++++ internal/pmtud/icmp/df_linux.go | 6 +-- internal/pmtud/icmp/df_windows.go | 4 +- internal/pmtud/ip/ipheader.go | 5 +- internal/pmtud/ip/ipv4_unix.go | 4 +- internal/pmtud/ip/ipv4_windows.go | 6 +-- internal/pmtud/ip/ipv6_linux.go | 5 +- internal/pmtud/ip/ipv6_windows.go | 4 +- internal/pmtud/ip/source.go | 41 +++++------------ internal/pmtud/ip/source_unix.go | 51 +++++++++++++++++++++ internal/pmtud/ip/source_windows.go | 49 ++++++++++++++++++++ internal/pmtud/tcp/multi.go | 6 +-- internal/pmtud/tcp/packet.go | 3 +- internal/pmtud/tcp/tcp.go | 28 +++-------- internal/pmtud/tcp/tcp_linux.go | 4 +- internal/pmtud/tcp/tcp_test.go | 25 +++++----- internal/pmtud/tcp/tcp_unix.go | 39 ++++++++++++---- internal/pmtud/tcp/tcp_windows.go | 41 +++++++++++++---- internal/pmtud/tcp/tracker.go | 4 +- 21 files changed, 246 insertions(+), 110 deletions(-) create mode 100644 internal/pmtud/constants/syscall_unix.go create mode 100644 internal/pmtud/constants/syscall_windows.go create mode 100644 internal/pmtud/ip/source_unix.go create mode 100644 internal/pmtud/ip/source_windows.go diff --git a/.golangci.yml b/.golangci.yml index 0fd6c949..2d15bd21 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -48,7 +48,7 @@ linters: path: internal\/server\/.+\.go - linters: - ireturn - text: returns interface \(github\.com\/vishvananda\/netlink\.Link\) + text: returns interface \(golang\.org\/x\/sys\/unix\.Sockaddr\) - linters: - ireturn path: internal\/openvpn\/pkcs8\/descbc\.go diff --git a/internal/pmtud/constants/syscall_unix.go b/internal/pmtud/constants/syscall_unix.go new file mode 100644 index 00000000..aa3d6eec --- /dev/null +++ b/internal/pmtud/constants/syscall_unix.go @@ -0,0 +1,16 @@ +//go:build linux || darwin + +package constants + +import "golang.org/x/sys/unix" + +//nolint:revive +const ( + SOCK_RAW = unix.SOCK_RAW + SOCK_STREAM = unix.SOCK_STREAM + AF_INET = unix.AF_INET + AF_INET6 = unix.AF_INET6 + IPPROTO_TCP = unix.IPPROTO_TCP + EAGAIN = unix.EAGAIN + EWOULDBLOCK = unix.EWOULDBLOCK +) diff --git a/internal/pmtud/constants/syscall_windows.go b/internal/pmtud/constants/syscall_windows.go new file mode 100644 index 00000000..cface1fa --- /dev/null +++ b/internal/pmtud/constants/syscall_windows.go @@ -0,0 +1,13 @@ +package constants + +import "golang.org/x/sys/windows" + +const ( + SOCK_RAW = windows.SOCK_RAW + SOCK_STREAM = windows.SOCK_STREAM + AF_INET = windows.AF_INET + AF_INET6 = windows.AF_INET6 + IPPROTO_TCP = windows.IPPROTO_TCP + EAGAIN = windows.WSAEWOULDBLOCK + EWOULDBLOCK = windows.WSAEWOULDBLOCK +) diff --git a/internal/pmtud/icmp/df_linux.go b/internal/pmtud/icmp/df_linux.go index d4334aff..06e247fc 100644 --- a/internal/pmtud/icmp/df_linux.go +++ b/internal/pmtud/icmp/df_linux.go @@ -1,10 +1,10 @@ package icmp import ( - "syscall" + "golang.org/x/sys/unix" ) func setDontFragment(fd uintptr) (err error) { - return syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, - syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_PROBE) + return unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, + unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_PROBE) } diff --git a/internal/pmtud/icmp/df_windows.go b/internal/pmtud/icmp/df_windows.go index 3416ff51..709271dd 100644 --- a/internal/pmtud/icmp/df_windows.go +++ b/internal/pmtud/icmp/df_windows.go @@ -1,11 +1,11 @@ package icmp import ( - "syscall" + "golang.org/x/sys/windows" ) func setDontFragment(fd uintptr) (err error) { // https://docs.microsoft.com/en-us/troubleshoot/windows/win32/header-library-requirement-socket-ipproto-ip // #define IP_DONTFRAGMENT 14 /* don't fragment IP datagrams */ - return syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, 14, 1) + return windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, 14, 1) } diff --git a/internal/pmtud/ip/ipheader.go b/internal/pmtud/ip/ipheader.go index 89d86623..eb662607 100644 --- a/internal/pmtud/ip/ipheader.go +++ b/internal/pmtud/ip/ipheader.go @@ -3,7 +3,6 @@ package ip import ( "encoding/binary" "net/netip" - "syscall" "github.com/qdm12/gluetun/internal/pmtud/constants" ) @@ -19,7 +18,7 @@ func HeaderV4(srcIP, dstIP netip.Addr, payloadLength uint32) []byte { const flagsAndOffset uint16 = 0x4000 // DF bit set putUint16(ipHeader[6:], flagsAndOffset) ipHeader[8] = 64 // ttl - ipHeader[9] = syscall.IPPROTO_TCP + ipHeader[9] = constants.IPPROTO_TCP srcIPBytes := srcIP.As4() copy(ipHeader[12:16], srcIPBytes[:]) dstIPBytes := dstIP.As4() @@ -51,7 +50,7 @@ func ipChecksum(header []byte) uint16 { // HeaderV6 makes an IPv6 header. // payloadLen is the length of the payload following the header. -// nextHeader can be byte([syscall.IPPROTO_TCP]) for example. +// nextHeader can be byte([constants.IPPROTO_TCP]) for example. func HeaderV6(srcIP, dstIP netip.Addr, payloadLen uint16, nextHeader byte, ) []byte { diff --git a/internal/pmtud/ip/ipv4_unix.go b/internal/pmtud/ip/ipv4_unix.go index 6d70b427..9d0e7141 100644 --- a/internal/pmtud/ip/ipv4_unix.go +++ b/internal/pmtud/ip/ipv4_unix.go @@ -2,8 +2,8 @@ package ip -import "syscall" +import "golang.org/x/sys/unix" func SetIPv4HeaderIncluded(fd int) error { - return syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1) + return unix.SetsockoptInt(fd, unix.IPPROTO_IP, unix.IP_HDRINCL, 1) } diff --git a/internal/pmtud/ip/ipv4_windows.go b/internal/pmtud/ip/ipv4_windows.go index 66263b6b..4ee02a5b 100644 --- a/internal/pmtud/ip/ipv4_windows.go +++ b/internal/pmtud/ip/ipv4_windows.go @@ -1,12 +1,10 @@ package ip import ( - "syscall" - "golang.org/x/sys/windows" ) -func SetIPv4HeaderIncluded(handle syscall.Handle) error { +func SetIPv4HeaderIncluded(handle windows.Handle) error { const ipHdrIncluded = windows.IP_HDRINCL - return syscall.SetsockoptInt(handle, syscall.IPPROTO_IP, ipHdrIncluded, 1) + return windows.SetsockoptInt(handle, windows.IPPROTO_IP, ipHdrIncluded, 1) } diff --git a/internal/pmtud/ip/ipv6_linux.go b/internal/pmtud/ip/ipv6_linux.go index 8b1ba81b..d0e151b4 100644 --- a/internal/pmtud/ip/ipv6_linux.go +++ b/internal/pmtud/ip/ipv6_linux.go @@ -1,8 +1,7 @@ package ip -import "syscall" +import "golang.org/x/sys/unix" func SetIPv6HeaderIncluded(fd int) error { - const ipv6HdrIncluded = 36 // IPV6_HDRINCL - return syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, ipv6HdrIncluded, 1) + return unix.SetsockoptInt(fd, unix.IPPROTO_IPV6, unix.IPV6_HDRINCL, 1) } diff --git a/internal/pmtud/ip/ipv6_windows.go b/internal/pmtud/ip/ipv6_windows.go index 882db5cf..8f4b757e 100644 --- a/internal/pmtud/ip/ipv6_windows.go +++ b/internal/pmtud/ip/ipv6_windows.go @@ -1,7 +1,7 @@ package ip -import "syscall" +import "golang.org/x/sys/windows" -func SetIPv6HeaderIncluded(fd syscall.Handle) error { +func SetIPv6HeaderIncluded(fd windows.Handle) error { panic("windows does not allow an application to build IPv6 headers") } diff --git a/internal/pmtud/ip/source.go b/internal/pmtud/ip/source.go index 64d1705e..349ff555 100644 --- a/internal/pmtud/ip/source.go +++ b/internal/pmtud/ip/source.go @@ -3,9 +3,9 @@ package ip import ( "fmt" "net/netip" - "syscall" "github.com/jsimonetti/rtnetlink" + "github.com/qdm12/gluetun/internal/pmtud/constants" ) // SrcAddr determines the appropriate source IP address to use when sending a packet to the @@ -35,9 +35,9 @@ func srcIP(dst netip.Addr) (netip.Addr, error) { } defer conn.Close() - family := uint8(syscall.AF_INET) + family := uint8(constants.AF_INET) if dst.Is6() { - family = syscall.AF_INET6 + family = constants.AF_INET6 } // Request route to destination @@ -71,53 +71,34 @@ func srcIP(dst netip.Addr) (netip.Addr, error) { // It doesn't actually listen on the port. // The cleanup function returned should be called to release the port when done. func srcPort(srcAddr netip.Addr, proto int) (srcPort uint16, cleanup func(), err error) { - family := syscall.AF_INET + family := constants.AF_INET if srcAddr.Is6() { - family = syscall.AF_INET6 + family = constants.AF_INET6 } - fd, err := syscall.Socket(family, syscall.SOCK_STREAM, proto) + fd, err := socket(family, constants.SOCK_STREAM, proto) if err != nil { return 0, nil, fmt.Errorf("creating reservation socket: %w", err) } cleanup = func() { - _ = syscall.Close(fd) + _ = closeSocket(fd) } // Bind to port 0 to get an ephemeral port const port = 0 - var bindAddr syscall.Sockaddr - if srcAddr.Is4() { - bindAddr = &syscall.SockaddrInet4{ - Port: port, - Addr: srcAddr.As4(), - } - } else { - bindAddr = &syscall.SockaddrInet6{ - Port: port, - Addr: srcAddr.As16(), - } - } + bindAddr := makeSockAddr(srcAddr, port) - err = syscall.Bind(fd, bindAddr) + err = bind(fd, bindAddr) if err != nil { cleanup() return 0, nil, fmt.Errorf("binding reservation socket: %w", err) } - sockAddr, err := syscall.Getsockname(fd) + srcPort, err = extractPortFromFD(fd) if err != nil { cleanup() - return 0, nil, fmt.Errorf("getting bound socket name: %w", err) + return 0, nil, fmt.Errorf("extracting port from socket fd: %w", err) } - switch typedSockAddr := sockAddr.(type) { - case *syscall.SockaddrInet4: - srcPort = uint16(typedSockAddr.Port) //nolint:gosec - case *syscall.SockaddrInet6: - srcPort = uint16(typedSockAddr.Port) //nolint:gosec - default: - panic(fmt.Sprintf("unexpected sockaddr type: %T", typedSockAddr)) - } return srcPort, cleanup, nil } diff --git a/internal/pmtud/ip/source_unix.go b/internal/pmtud/ip/source_unix.go new file mode 100644 index 00000000..8207fa92 --- /dev/null +++ b/internal/pmtud/ip/source_unix.go @@ -0,0 +1,51 @@ +//go:build linux || darwin + +package ip + +import ( + "fmt" + "net/netip" + + "golang.org/x/sys/unix" +) + +func socket(domain int, typ int, proto int) (fd int, err error) { + return unix.Socket(domain, typ, proto) +} + +func closeSocket(fd int) error { + return unix.Close(fd) +} + +func bind(fd int, addr unix.Sockaddr) error { + return unix.Bind(fd, addr) +} + +func makeSockAddr(ip netip.Addr, port uint16) unix.Sockaddr { + if ip.Is4() { + return &unix.SockaddrInet4{ + Port: int(port), + Addr: ip.As4(), + } + } + return &unix.SockaddrInet6{ + Port: int(port), + Addr: ip.As16(), + } +} + +func extractPortFromFD(fd int) (uint16, error) { + sockAddr, err := unix.Getsockname(fd) + if err != nil { + return 0, fmt.Errorf("getting sockname: %w", err) + } + + switch typedSockAddr := sockAddr.(type) { + case *unix.SockaddrInet4: + return uint16(typedSockAddr.Port), nil //nolint:gosec + case *unix.SockaddrInet6: + return uint16(typedSockAddr.Port), nil //nolint:gosec + default: + panic(fmt.Sprintf("unexpected sockaddr type: %T", typedSockAddr)) + } +} diff --git a/internal/pmtud/ip/source_windows.go b/internal/pmtud/ip/source_windows.go new file mode 100644 index 00000000..5d29d6ad --- /dev/null +++ b/internal/pmtud/ip/source_windows.go @@ -0,0 +1,49 @@ +package ip + +import ( + "fmt" + "net/netip" + + "golang.org/x/sys/windows" +) + +func socket(domain int, typ int, proto int) (fd windows.Handle, err error) { + return windows.Socket(domain, typ, proto) +} + +func closeSocket(fd windows.Handle) error { + return windows.Close(fd) +} + +func bind(fd windows.Handle, addr windows.Sockaddr) error { + return windows.Bind(fd, addr) +} + +func makeSockAddr(ip netip.Addr, port uint16) windows.Sockaddr { + if ip.Is4() { + return &windows.SockaddrInet4{ + Port: int(port), + Addr: ip.As4(), + } + } + return &windows.SockaddrInet6{ + Port: int(port), + Addr: ip.As16(), + } +} + +func extractPortFromFD(fd windows.Handle) (uint16, error) { + sockAddr, err := windows.Getsockname(fd) + if err != nil { + return 0, fmt.Errorf("getting sockname: %w", err) + } + + switch typedSockAddr := sockAddr.(type) { + case *windows.SockaddrInet4: + return uint16(typedSockAddr.Port), nil //nolint:gosec + case *windows.SockaddrInet6: + return uint16(typedSockAddr.Port), nil //nolint:gosec + default: + panic(fmt.Sprintf("unexpected sockaddr type: %T", typedSockAddr)) + } +} diff --git a/internal/pmtud/tcp/multi.go b/internal/pmtud/tcp/multi.go index 9ac48a94..0849daca 100644 --- a/internal/pmtud/tcp/multi.go +++ b/internal/pmtud/tcp/multi.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" "net/netip" - "syscall" "time" + "github.com/qdm12/gluetun/internal/pmtud/constants" "github.com/qdm12/gluetun/internal/pmtud/test" ) @@ -32,9 +32,9 @@ func PathMTUDiscover(ctx context.Context, addrPort netip.AddrPort, tests[i] = testUnit{mtu: mtusToTest[i]} } - family := syscall.AF_INET + family := constants.AF_INET if addrPort.Addr().Is6() { - family = syscall.AF_INET6 + family = constants.AF_INET6 } fd, stop, err := startRawSocket(family) if err != nil { diff --git a/internal/pmtud/tcp/packet.go b/internal/pmtud/tcp/packet.go index 7a8055aa..e3135bfe 100644 --- a/internal/pmtud/tcp/packet.go +++ b/internal/pmtud/tcp/packet.go @@ -4,7 +4,6 @@ import ( "encoding/binary" "math/rand/v2" "net/netip" - "syscall" "github.com/qdm12/gluetun/internal/pmtud/constants" "github.com/qdm12/gluetun/internal/pmtud/ip" @@ -67,7 +66,7 @@ func createPacket(src, dst netip.AddrPort, ipHeader = ip.HeaderV4(src.Addr(), dst.Addr(), payloadLength) } else { ipHeader = ip.HeaderV6(src.Addr(), dst.Addr(), - uint16(payloadLength), byte(syscall.IPPROTO_TCP)) //nolint:gosec + uint16(payloadLength), byte(constants.IPPROTO_TCP)) //nolint:gosec } tcpHeader := makeTCPHeader(src.Port(), dst.Port(), seq, ack, flags) diff --git a/internal/pmtud/tcp/tcp.go b/internal/pmtud/tcp/tcp.go index ad9e544e..0e5c128f 100644 --- a/internal/pmtud/tcp/tcp.go +++ b/internal/pmtud/tcp/tcp.go @@ -5,32 +5,31 @@ import ( "errors" "fmt" "net/netip" - "syscall" "github.com/qdm12/gluetun/internal/pmtud/constants" "github.com/qdm12/gluetun/internal/pmtud/ip" ) func startRawSocket(family int) (fd fileDescriptor, stop func(), err error) { - fdPlatform, err := syscall.Socket(family, syscall.SOCK_RAW, syscall.IPPROTO_TCP) + fdPlatform, err := socket(family, constants.SOCK_RAW, constants.IPPROTO_TCP) if err != nil { return 0, nil, fmt.Errorf("creating raw socket: %w", err) } - if family == syscall.AF_INET { + if family == constants.AF_INET { err = ip.SetIPv4HeaderIncluded(fdPlatform) } else { err = ip.SetIPv6HeaderIncluded(fdPlatform) } if err != nil { - _ = syscall.Close(fdPlatform) + _ = closeSocket(fdPlatform) return 0, nil, fmt.Errorf("setting header option on raw socket: %w", err) } // Allow sending packets larger than cached PMTU (for PMTUD probing) err = setMTUDiscovery(fdPlatform) if err != nil { - _ = syscall.Close(fdPlatform) + _ = closeSocket(fdPlatform) return 0, nil, fmt.Errorf("setting IP_MTU_DISCOVER: %w", err) } @@ -39,12 +38,12 @@ func startRawSocket(family int) (fd fileDescriptor, stop func(), err error) { // which would cause things to hang indefinitely. err = setNonBlock(fdPlatform) if err != nil { - _ = syscall.Close(fdPlatform) + _ = closeSocket(fdPlatform) return 0, nil, fmt.Errorf("setting non-blocking mode: %w", err) } stop = func() { - _ = syscall.Close(fdPlatform) + _ = closeSocket(fdPlatform) } return fileDescriptor(fdPlatform), stop, nil } @@ -61,7 +60,7 @@ var ( func runTest(ctx context.Context, fd fileDescriptor, tracker *tracker, dst netip.AddrPort, mtu uint32, ) error { - const proto = syscall.IPPROTO_TCP + const proto = constants.IPPROTO_TCP src, cleanup, err := ip.SrcAddr(dst, proto) if err != nil { return fmt.Errorf("getting source address: %w", err) @@ -137,19 +136,6 @@ func runTest(ctx context.Context, fd fileDescriptor, } } -func makeSockAddr(addr netip.AddrPort) syscall.Sockaddr { - if addr.Addr().Is4() { - return &syscall.SockaddrInet4{ - Port: int(addr.Port()), - Addr: addr.Addr().As4(), - } - } - return &syscall.SockaddrInet6{ - Port: int(addr.Port()), - Addr: addr.Addr().As16(), - } -} - var errTCPPacketNotRST = errors.New("TCP packet is not an RST") func handleRSTReply(ctx context.Context, fd fileDescriptor, ch <-chan []byte, diff --git a/internal/pmtud/tcp/tcp_linux.go b/internal/pmtud/tcp/tcp_linux.go index 4ddbb81c..69bfa902 100644 --- a/internal/pmtud/tcp/tcp_linux.go +++ b/internal/pmtud/tcp/tcp_linux.go @@ -1,7 +1,7 @@ package tcp -import "syscall" +import "golang.org/x/sys/unix" func setMTUDiscovery(fd int) error { - return syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_PROBE) + return unix.SetsockoptInt(fd, unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_PROBE) } diff --git a/internal/pmtud/tcp/tcp_test.go b/internal/pmtud/tcp/tcp_test.go index 53c98d62..2abe72a4 100644 --- a/internal/pmtud/tcp/tcp_test.go +++ b/internal/pmtud/tcp/tcp_test.go @@ -1,3 +1,5 @@ +//go:build linux + package tcp import ( @@ -5,15 +7,16 @@ import ( "errors" "fmt" "net/netip" - "syscall" "testing" "time" "github.com/qdm12/gluetun/internal/netlink" + "github.com/qdm12/gluetun/internal/pmtud/constants" "github.com/qdm12/gluetun/internal/routing" "github.com/qdm12/log" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sys/unix" ) func Test_runTest(t *testing.T) { @@ -30,7 +33,7 @@ func Test_runTest(t *testing.T) { ctx, cancel := context.WithCancel(t.Context()) - const family = syscall.AF_INET + const family = constants.AF_INET fd, stop, err := startRawSocket(family) require.NoError(t, err) @@ -158,33 +161,33 @@ func findDefaultIPv4RouteMTU(netlinker *netlink.NetLink) (mtu uint32, err error) func reserveClosedPort(t *testing.T) (port uint16) { t.Helper() - fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) + fd, err := unix.Socket(constants.AF_INET, constants.SOCK_STREAM, constants.IPPROTO_TCP) require.NoError(t, err) t.Cleanup(func() { - err := syscall.Close(fd) + err := unix.Close(fd) assert.NoError(t, err) }) - addr := &syscall.SockaddrInet4{ + addr := &unix.SockaddrInet4{ Port: 0, Addr: [4]byte{127, 0, 0, 1}, } - err = syscall.Bind(fd, addr) + err = unix.Bind(fd, addr) if err != nil { - _ = syscall.Close(fd) + _ = unix.Close(fd) t.Fatal(err) } - sockAddr, err := syscall.Getsockname(fd) + sockAddr, err := unix.Getsockname(fd) if err != nil { - _ = syscall.Close(fd) + _ = unix.Close(fd) t.Fatal(err) } - sockAddr4, ok := sockAddr.(*syscall.SockaddrInet4) + sockAddr4, ok := sockAddr.(*unix.SockaddrInet4) if !ok { - _ = syscall.Close(fd) + _ = unix.Close(fd) t.Fatal("not an IPv4 address") } diff --git a/internal/pmtud/tcp/tcp_unix.go b/internal/pmtud/tcp/tcp_unix.go index 0b2b24ea..61c468fd 100644 --- a/internal/pmtud/tcp/tcp_unix.go +++ b/internal/pmtud/tcp/tcp_unix.go @@ -3,26 +3,49 @@ package tcp import ( - "syscall" + "net/netip" "time" + + "golang.org/x/sys/unix" ) // fileDescriptor is a platform-independent type for socket file descriptors. type fileDescriptor int -func sendTo(fd fileDescriptor, p []byte, flags int, to syscall.Sockaddr) (err error) { - return syscall.Sendto(int(fd), p, flags, to) +func socket(domain int, typ int, proto int) (fd int, err error) { + return unix.Socket(domain, typ, proto) +} + +func closeSocket(fd int) error { + return unix.Close(fd) +} + +func sendTo(fd fileDescriptor, p []byte, flags int, to unix.Sockaddr) (err error) { + return unix.Sendto(int(fd), p, flags, to) } func setSocketTimeout(fd fileDescriptor, timeout time.Duration) (err error) { - timeval := syscall.NsecToTimeval(timeout.Nanoseconds()) - return syscall.SetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &timeval) + timeval := unix.NsecToTimeval(timeout.Nanoseconds()) + return unix.SetsockoptTimeval(int(fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, &timeval) } -func recvFrom(fd fileDescriptor, p []byte, flags int) (n int, from syscall.Sockaddr, err error) { - return syscall.Recvfrom(int(fd), p, flags) +func recvFrom(fd fileDescriptor, p []byte, flags int) (n int, from unix.Sockaddr, err error) { + return unix.Recvfrom(int(fd), p, flags) } func setNonBlock(fd int) error { - return syscall.SetNonblock(fd, true) + return unix.SetNonblock(fd, true) +} + +func makeSockAddr(addr netip.AddrPort) unix.Sockaddr { + if addr.Addr().Is4() { + return &unix.SockaddrInet4{ + Port: int(addr.Port()), + Addr: addr.Addr().As4(), + } + } + return &unix.SockaddrInet6{ + Port: int(addr.Port()), + Addr: addr.Addr().As16(), + } } diff --git a/internal/pmtud/tcp/tcp_windows.go b/internal/pmtud/tcp/tcp_windows.go index 9cab5507..842093f5 100644 --- a/internal/pmtud/tcp/tcp_windows.go +++ b/internal/pmtud/tcp/tcp_windows.go @@ -1,37 +1,58 @@ package tcp import ( - "syscall" + "net/netip" "time" "unsafe" "golang.org/x/sys/windows" ) -type fileDescriptor syscall.Handle +type fileDescriptor windows.Handle -func sendTo(fd fileDescriptor, p []byte, flags int, to syscall.Sockaddr) (err error) { - return syscall.Sendto(syscall.Handle(fd), p, flags, to) +func socket(domain int, typ int, proto int) (fd windows.Handle, err error) { + return windows.Socket(domain, typ, proto) +} + +func closeSocket(fd windows.Handle) error { + return windows.Close(fd) +} + +func sendTo(fd fileDescriptor, p []byte, flags int, to windows.Sockaddr) (err error) { + return windows.Sendto(windows.Handle(fd), p, flags, to) } func setSocketTimeout(fd fileDescriptor, timeout time.Duration) (err error) { timeval := int(timeout.Milliseconds()) - return syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET, windows.SO_RCVTIMEO, timeval) + return windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_RCVTIMEO, timeval) } -func recvFrom(fd fileDescriptor, p []byte, flags int) (n int, from syscall.Sockaddr, err error) { - return syscall.Recvfrom(syscall.Handle(fd), p, flags) +func recvFrom(fd fileDescriptor, p []byte, flags int) (n int, from windows.Sockaddr, err error) { + return windows.Recvfrom(windows.Handle(fd), p, flags) } -func setMTUDiscovery(fd syscall.Handle) error { +func setMTUDiscovery(fd windows.Handle) error { panic("not implemented") } -func setNonBlock(fd syscall.Handle) error { +func setNonBlock(fd windows.Handle) error { // Windows: Use ioctlsocket with FIONBIO var arg uint32 = 1 // 1 to enable non-blocking mode var bytesReturned uint32 const FIONBIO = 0x8004667e - return syscall.WSAIoctl(fd, FIONBIO, (*byte)(unsafe.Pointer(&arg)), + return windows.WSAIoctl(fd, FIONBIO, (*byte)(unsafe.Pointer(&arg)), uint32(unsafe.Sizeof(arg)), nil, 0, &bytesReturned, nil, 0) } + +func makeSockAddr(addr netip.AddrPort) windows.Sockaddr { + if addr.Addr().Is4() { + return &windows.SockaddrInet4{ + Port: int(addr.Port()), + Addr: addr.Addr().As4(), + } + } + return &windows.SockaddrInet6{ + Port: int(addr.Port()), + Addr: addr.Addr().As16(), + } +} diff --git a/internal/pmtud/tcp/tracker.go b/internal/pmtud/tcp/tracker.go index 13a7167b..a178b7f0 100644 --- a/internal/pmtud/tcp/tracker.go +++ b/internal/pmtud/tcp/tracker.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "sync" - "syscall" "time" "github.com/qdm12/gluetun/internal/pmtud/constants" @@ -80,8 +79,7 @@ func (t *tracker) listen(ctx context.Context) error { n, _, err := recvFrom(t.fd, reply, 0) if err != nil { switch { - case errors.Is(err, syscall.EAGAIN), - errors.Is(err, syscall.EWOULDBLOCK): + case errors.Is(err, constants.EAGAIN), errors.Is(err, constants.EWOULDBLOCK): pollSleep(ctx) continue case ctx.Err() != nil: