wgengine/magicsock,net/sockopts: export Windows ICMP suppression logic (#16917)

For eventual use by net/udprelay.Server.

Updates tailscale/corp#31506

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited
2025-08-21 13:44:13 -07:00
committed by GitHub
parent cf739256ca
commit b17cfe4aed
7 changed files with 27 additions and 21 deletions

View File

@@ -0,0 +1,15 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !windows
package sockopts
import (
"tailscale.com/types/nettype"
)
// SetICMPErrImmunity is no-op on non-Windows.
func SetICMPErrImmunity(pconn nettype.PacketConn) error {
return nil
}

View File

@@ -0,0 +1,62 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build windows
package sockopts
import (
"fmt"
"net"
"unsafe"
"golang.org/x/sys/windows"
"tailscale.com/types/nettype"
)
// SetICMPErrImmunity sets socket options on pconn to prevent ICMP reception,
// e.g. ICMP Port Unreachable, from surfacing as a syscall error.
//
// If pconn is not a [*net.UDPConn], then SetICMPErrImmunity is no-op.
func SetICMPErrImmunity(pconn nettype.PacketConn) error {
c, ok := pconn.(*net.UDPConn)
if !ok {
// not a UDP connection; nothing to do
return nil
}
sysConn, err := c.SyscallConn()
if err != nil {
return fmt.Errorf("SetICMPErrImmunity: getting SyscallConn failed: %v", err)
}
// Similar to https://github.com/golang/go/issues/5834 (which involved
// WSAECONNRESET), Windows can return a WSAENETRESET error, even on UDP
// reads. Disable this.
const SIO_UDP_NETRESET = windows.IOC_IN | windows.IOC_VENDOR | 15
var ioctlErr error
err = sysConn.Control(func(fd uintptr) {
ret := uint32(0)
flag := uint32(0)
size := uint32(unsafe.Sizeof(flag))
ioctlErr = windows.WSAIoctl(
windows.Handle(fd),
SIO_UDP_NETRESET, // iocc
(*byte)(unsafe.Pointer(&flag)), // inbuf
size, // cbif
nil, // outbuf
0, // cbob
&ret, // cbbr
nil, // overlapped
0, // completionRoutine
)
})
if ioctlErr != nil {
return fmt.Errorf("SetICMPErrImmunity: could not set SIO_UDP_NETRESET: %v", ioctlErr)
}
if err != nil {
return fmt.Errorf("SetICMPErrImmunity: SyscallConn.Control failed: %v", err)
}
return nil
}