golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.31k stars 17.7k forks source link

net: UDP sockets on windows error on receive due to ICMP TTL #68614

Open raggi opened 4 months ago

raggi commented 4 months ago

Go version

go1.22.5

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/raggi/Library/Caches/go-build'
GOENV='/Users/raggi/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/raggi/go/pkg/mod'
GONOPROXY='ra66i.org/raggi,rag.pub/raggi'
GONOSUMDB='ra66i.org/raggi,rag.pub/raggi'
GOOS='darwin'
GOPATH='/Users/raggi/go'
GOPRIVATE='ra66i.org/raggi,rag.pub/raggi'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/raggi/.cache/tailscale-go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/raggi/.cache/tailscale-go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/bb/dyr_1n6j575g8nq85nmnfbt00000gn/T/go-build2102863150=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

We have observed errors in RecvFrom as a result of ICMP replies to UDP sockets on Windows, which is an unexpected behavior resulting from a Windows socket behavior quirk.

What did you see happen?

Socket recv generated an error as a result of ICMP replies to earlier sent packets.

What did you expect to see?

Socket recv should not generate an error due to ICMP received.

Detail & Proposal

Background: a prior round of this issue was fixed in https://github.com/golang/go/commit/3114bd6f97492461d2027a49fee9f7fce3742b75 which addressed one case of ICMP reply (https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/263823), but there are two. The Godot project ran into this issue as well, and describes the issue and fix here: https://github.com/godotengine/godot/commit/397b01d590e5850762d25eaaa2951b1a76da46dc

The net package only disables SIO_UDP_CONNRESET, but not SIO_UDP_NETRESET, as such there are still ICMP responses that can lead to wsarecvfrom: The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress.

We should set SIO_UDP_NETRESET as well as SIO_UDP_CONNRESET in order to get behavior that is most similar to bsd sockets on the other major platforms, where asynchronous ICMP replies are ignored unless explicitly opted in to.

gabyhelp commented 4 months ago

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

seankhliao commented 4 months ago

cc @golang/windows

gopherbot commented 4 months ago

Change https://go.dev/cl/601038 mentions this issue: windows: add SIO_UDP_NETRESET for net/ to use

gopherbot commented 4 months ago

Change https://go.dev/cl/601397 mentions this issue: internal/poll: disable SIO_UDP_NETRESET on Windows

alexbrainman commented 4 months ago

The Godot project ran into this issue as well, and describes the issue and fix here: godotengine/godot@397b01d

Is there some official documentation for this?

I searched for SIO_UDP_NETRESET, but I could not find anything.

Or are we supposed to assume that https://github.com/godotengine/godot know how it works.

Thank you.

Alex

gopherbot commented 3 months ago

Change https://go.dev/cl/609295 mentions this issue: windows: add SIO_UDP_NETRESET constant