diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index bff905caa..188933c0e 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -21,7 +21,6 @@ import ( "strings" "sync" "sync/atomic" - "syscall" "time" "github.com/tailscale/wireguard-go/conn" @@ -1290,34 +1289,6 @@ func (c *Conn) sendUDP(ipp netip.AddrPort, b []byte, isDisco bool) (sent bool, e return } -// maybeRebindOnError performs a rebind and restun if the error is defined and -// any conditionals are met. -func (c *Conn) maybeRebindOnError(os string, err error) bool { - switch { - case errors.Is(err, syscall.EPERM): - why := "operation-not-permitted-rebind" - switch os { - // We currently will only rebind and restun on a syscall.EPERM if it is experienced - // on a client running darwin. - // TODO(charlotte, raggi): expand os options if required. - case "darwin": - // TODO(charlotte): implement a backoff, so we don't end up in a rebind loop for persistent - // EPERMs. - if c.lastEPERMRebind.Load().Before(time.Now().Add(-5 * time.Second)) { - c.logf("magicsock: performing %q", why) - c.lastEPERMRebind.Store(time.Now()) - c.Rebind() - go c.ReSTUN(why) - return true - } - default: - c.logf("magicsock: not performing %q", why) - return false - } - } - return false -} - // sendUDPNetcheck sends b via UDP to addr. It is used exclusively by netcheck. // It returns the number of bytes sent along with any error encountered. It // returns errors.ErrUnsupported if the client is explicitly configured to only diff --git a/wgengine/magicsock/magicsock_notplan9.go b/wgengine/magicsock/magicsock_notplan9.go new file mode 100644 index 000000000..44f08cb1c --- /dev/null +++ b/wgengine/magicsock/magicsock_notplan9.go @@ -0,0 +1,49 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !plan9 + +package magicsock + +import ( + "errors" + "syscall" + "time" +) + +// maybeRebindOnError performs a rebind and restun if the error is defined and +// any conditionals are met. +func (c *Conn) maybeRebindOnError(os string, err error) bool { + switch { + case errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ENOTCONN): + // EPIPE/ENOTCONN are common errors when a send fails due to a closed + // socket. There is some platform and version inconsistency in which + // error is returned, but the meaning is the same. + why := "broken-pipe-rebind" + c.logf("magicsock: performing %q", why) + c.Rebind() + go c.ReSTUN(why) + return true + case errors.Is(err, syscall.EPERM): + why := "operation-not-permitted-rebind" + switch os { + // We currently will only rebind and restun on a syscall.EPERM if it is experienced + // on a client running darwin. + // TODO(charlotte, raggi): expand os options if required. + case "darwin": + // TODO(charlotte): implement a backoff, so we don't end up in a rebind loop for persistent + // EPERMs. + if c.lastEPERMRebind.Load().Before(time.Now().Add(-5 * time.Second)) { + c.logf("magicsock: performing %q", why) + c.lastEPERMRebind.Store(time.Now()) + c.Rebind() + go c.ReSTUN(why) + return true + } + default: + c.logf("magicsock: not performing %q", why) + return false + } + } + return false +} diff --git a/wgengine/magicsock/magicsock_plan9.go b/wgengine/magicsock/magicsock_plan9.go new file mode 100644 index 000000000..23f710430 --- /dev/null +++ b/wgengine/magicsock/magicsock_plan9.go @@ -0,0 +1,12 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build plan9 + +package magicsock + +// maybeRebindOnError performs a rebind and restun if the error is defined and +// any conditionals are met. +func (c *Conn) maybeRebindOnError(os string, err error) bool { + return false +}