mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-23 09:06:24 +00:00
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:
15
net/sockopts/sockopts_notwindows.go
Normal file
15
net/sockopts/sockopts_notwindows.go
Normal 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
|
||||
}
|
||||
62
net/sockopts/sockopts_windows.go
Normal file
62
net/sockopts/sockopts_windows.go
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user