mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-09 17:16:50 +00:00
all: use syncs.AtomicValue
Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
parent
b75f81ec00
commit
a9f6cd41fd
@ -12,11 +12,12 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/syncs"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dnsCache atomic.Value // of []byte
|
var dnsCache syncs.AtomicValue[[]byte]
|
||||||
|
|
||||||
var bootstrapDNSRequests = expvar.NewInt("counter_bootstrap_dns_requests")
|
var bootstrapDNSRequests = expvar.NewInt("counter_bootstrap_dns_requests")
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ func refreshBootstrapDNS() {
|
|||||||
func handleBootstrapDNS(w http.ResponseWriter, r *http.Request) {
|
func handleBootstrapDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
bootstrapDNSRequests.Add(1)
|
bootstrapDNSRequests.Add(1)
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
j, _ := dnsCache.Load().([]byte)
|
j := dnsCache.Load()
|
||||||
// Bootstrap DNS requests occur cross-regions,
|
// Bootstrap DNS requests occur cross-regions,
|
||||||
// and are randomized per request,
|
// and are randomized per request,
|
||||||
// so keeping a connection open is pointlessly expensive.
|
// so keeping a connection open is pointlessly expensive.
|
||||||
|
@ -71,7 +71,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+
|
||||||
tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/syncs from tailscale.com/net/netcheck
|
tailscale.com/syncs from tailscale.com/net/netcheck+
|
||||||
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/tka from tailscale.com/types/key
|
tailscale.com/tka from tailscale.com/types/key
|
||||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||||
|
@ -23,7 +23,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
@ -41,6 +40,7 @@ import (
|
|||||||
"tailscale.com/net/tlsdial"
|
"tailscale.com/net/tlsdial"
|
||||||
"tailscale.com/net/tsdial"
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/net/tshttpproxy"
|
"tailscale.com/net/tshttpproxy"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
@ -939,8 +939,8 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, readOnly bool
|
|||||||
if resp.Debug.GoroutineDumpURL != "" {
|
if resp.Debug.GoroutineDumpURL != "" {
|
||||||
go dumpGoroutinesToURL(c.httpc, resp.Debug.GoroutineDumpURL)
|
go dumpGoroutinesToURL(c.httpc, resp.Debug.GoroutineDumpURL)
|
||||||
}
|
}
|
||||||
setControlAtomic(&controlUseDERPRoute, resp.Debug.DERPRoute)
|
controlUseDERPRoute.Store(resp.Debug.DERPRoute)
|
||||||
setControlAtomic(&controlTrimWGConfig, resp.Debug.TrimWGConfig)
|
controlTrimWGConfig.Store(resp.Debug.TrimWGConfig)
|
||||||
if sleep := time.Duration(resp.Debug.SleepSeconds * float64(time.Second)); sleep > 0 {
|
if sleep := time.Duration(resp.Debug.SleepSeconds * float64(time.Second)); sleep > 0 {
|
||||||
if err := sleepAsRequested(ctx, c.logf, timeoutReset, sleep); err != nil {
|
if err := sleepAsRequested(ctx, c.logf, timeoutReset, sleep); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1151,29 +1151,20 @@ var clockNow = time.Now
|
|||||||
|
|
||||||
// opt.Bool configs from control.
|
// opt.Bool configs from control.
|
||||||
var (
|
var (
|
||||||
controlUseDERPRoute atomic.Value // of opt.Bool
|
controlUseDERPRoute syncs.AtomicValue[opt.Bool]
|
||||||
controlTrimWGConfig atomic.Value // of opt.Bool
|
controlTrimWGConfig syncs.AtomicValue[opt.Bool]
|
||||||
)
|
)
|
||||||
|
|
||||||
func setControlAtomic(dst *atomic.Value, v opt.Bool) {
|
|
||||||
old, ok := dst.Load().(opt.Bool)
|
|
||||||
if !ok || old != v {
|
|
||||||
dst.Store(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DERPRouteFlag reports the last reported value from control for whether
|
// DERPRouteFlag reports the last reported value from control for whether
|
||||||
// DERP route optimization (Issue 150) should be enabled.
|
// DERP route optimization (Issue 150) should be enabled.
|
||||||
func DERPRouteFlag() opt.Bool {
|
func DERPRouteFlag() opt.Bool {
|
||||||
v, _ := controlUseDERPRoute.Load().(opt.Bool)
|
return controlUseDERPRoute.Load()
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrimWGConfig reports the last reported value from control for whether
|
// TrimWGConfig reports the last reported value from control for whether
|
||||||
// we should do lazy wireguard configuration.
|
// we should do lazy wireguard configuration.
|
||||||
func TrimWGConfig() opt.Bool {
|
func TrimWGConfig() opt.Bool {
|
||||||
v, _ := controlTrimWGConfig.Load().(opt.Bool)
|
return controlTrimWGConfig.Load()
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ipForwardingBroken reports whether the system's IP forwarding is disabled
|
// ipForwardingBroken reports whether the system's IP forwarding is disabled
|
||||||
|
@ -13,11 +13,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
)
|
)
|
||||||
@ -39,8 +39,8 @@ type Client struct {
|
|||||||
rate *rate.Limiter // if non-nil, rate limiter to use
|
rate *rate.Limiter // if non-nil, rate limiter to use
|
||||||
|
|
||||||
// Owned by Recv:
|
// Owned by Recv:
|
||||||
peeked int // bytes to discard on next Recv
|
peeked int // bytes to discard on next Recv
|
||||||
readErr atomic.Value // of error; sticky (set by Recv)
|
readErr syncs.AtomicValue[error] // sticky (set by Recv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientOpt is an option passed to NewClient.
|
// ClientOpt is an option passed to NewClient.
|
||||||
@ -445,7 +445,7 @@ func (c *Client) Recv() (m ReceivedMessage, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err error) {
|
func (c *Client) recvTimeout(timeout time.Duration) (m ReceivedMessage, err error) {
|
||||||
readErr, _ := c.readErr.Load().(error)
|
readErr := c.readErr.Load()
|
||||||
if readErr != nil {
|
if readErr != nil {
|
||||||
return nil, readErr
|
return nil, readErr
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
@ -37,6 +36,7 @@ import (
|
|||||||
"tailscale.com/net/netns"
|
"tailscale.com/net/netns"
|
||||||
"tailscale.com/net/tlsdial"
|
"tailscale.com/net/tlsdial"
|
||||||
"tailscale.com/net/tshttpproxy"
|
"tailscale.com/net/tshttpproxy"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
@ -69,7 +69,7 @@ type Client struct {
|
|||||||
// by SetAddressFamilySelector. It's an atomic because it needs
|
// by SetAddressFamilySelector. It's an atomic because it needs
|
||||||
// to be accessed by multiple racing routines started while
|
// to be accessed by multiple racing routines started while
|
||||||
// Client.conn holds mu.
|
// Client.conn holds mu.
|
||||||
addrFamSelAtomic atomic.Value // of AddressFamilySelector
|
addrFamSelAtomic syncs.AtomicValue[AddressFamilySelector]
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
preferred bool
|
preferred bool
|
||||||
|
@ -8,10 +8,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/util/winutil"
|
"tailscale.com/util/winutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,10 +20,10 @@ func init() {
|
|||||||
packageType = packageTypeWindows
|
packageType = packageTypeWindows
|
||||||
}
|
}
|
||||||
|
|
||||||
var winVerCache atomic.Value // of string
|
var winVerCache syncs.AtomicValue[string]
|
||||||
|
|
||||||
func osVersionWindows() string {
|
func osVersionWindows() string {
|
||||||
if s, ok := winVerCache.Load().(string); ok {
|
if s, ok := winVerCache.LoadOk(); ok {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
major, minor, build := windows.RtlGetNtVersionNumbers()
|
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||||
|
@ -40,6 +40,7 @@ import (
|
|||||||
"tailscale.com/net/tsdial"
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/paths"
|
"tailscale.com/paths"
|
||||||
"tailscale.com/portlist"
|
"tailscale.com/portlist"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/tka"
|
"tailscale.com/tka"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
@ -130,7 +131,7 @@ type LocalBackend struct {
|
|||||||
shutdownCalled bool // if Shutdown has been called
|
shutdownCalled bool // if Shutdown has been called
|
||||||
|
|
||||||
filterAtomic atomic.Pointer[filter.Filter]
|
filterAtomic atomic.Pointer[filter.Filter]
|
||||||
containsViaIPFuncAtomic atomic.Value // of func(netip.Addr) bool
|
containsViaIPFuncAtomic syncs.AtomicValue[func(netip.Addr) bool]
|
||||||
|
|
||||||
// The mutex protects the following elements.
|
// The mutex protects the following elements.
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
@ -1500,17 +1501,17 @@ func (b *LocalBackend) tellClientToBrowseToURL(url string) {
|
|||||||
var panicOnMachineKeyGeneration = envknob.Bool("TS_DEBUG_PANIC_MACHINE_KEY")
|
var panicOnMachineKeyGeneration = envknob.Bool("TS_DEBUG_PANIC_MACHINE_KEY")
|
||||||
|
|
||||||
func (b *LocalBackend) createGetMachinePrivateKeyFunc() func() (key.MachinePrivate, error) {
|
func (b *LocalBackend) createGetMachinePrivateKeyFunc() func() (key.MachinePrivate, error) {
|
||||||
var cache atomic.Value
|
var cache syncs.AtomicValue[key.MachinePrivate]
|
||||||
return func() (key.MachinePrivate, error) {
|
return func() (key.MachinePrivate, error) {
|
||||||
if panicOnMachineKeyGeneration {
|
if panicOnMachineKeyGeneration {
|
||||||
panic("machine key generated")
|
panic("machine key generated")
|
||||||
}
|
}
|
||||||
if v, ok := cache.Load().(key.MachinePrivate); ok {
|
if v, ok := cache.LoadOk(); ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
if v, ok := cache.Load().(key.MachinePrivate); ok {
|
if v, ok := cache.LoadOk(); ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
if err := b.initMachineKeyLocked(); err != nil {
|
if err := b.initMachineKeyLocked(); err != nil {
|
||||||
@ -1522,11 +1523,11 @@ func (b *LocalBackend) createGetMachinePrivateKeyFunc() func() (key.MachinePriva
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) createGetNLPublicKeyFunc() func() (key.NLPublic, error) {
|
func (b *LocalBackend) createGetNLPublicKeyFunc() func() (key.NLPublic, error) {
|
||||||
var cache atomic.Value
|
var cache syncs.AtomicValue[key.NLPublic]
|
||||||
return func() (key.NLPublic, error) {
|
return func() (key.NLPublic, error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
if v, ok := cache.Load().(key.NLPublic); ok {
|
if v, ok := cache.LoadOk(); ok {
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2524,8 +2525,7 @@ func (b *LocalBackend) TailscaleVarRoot() string {
|
|||||||
}
|
}
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "ios", "android", "darwin":
|
case "ios", "android", "darwin":
|
||||||
dir, _ := paths.AppSharedDir.Load().(string)
|
return paths.AppSharedDir.Load()
|
||||||
return dir
|
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -3058,7 +3058,7 @@ func (b *LocalBackend) ShouldRunSSH() bool { return b.sshAtomicBool.Load() && ca
|
|||||||
// Tailscale ULA's v6 "via" range embedding an IPv4 address to be forwarded to
|
// Tailscale ULA's v6 "via" range embedding an IPv4 address to be forwarded to
|
||||||
// by Tailscale.
|
// by Tailscale.
|
||||||
func (b *LocalBackend) ShouldHandleViaIP(ip netip.Addr) bool {
|
func (b *LocalBackend) ShouldHandleViaIP(ip netip.Addr) bool {
|
||||||
if f, ok := b.containsViaIPFuncAtomic.Load().(func(netip.Addr) bool); ok {
|
if f, ok := b.containsViaIPFuncAtomic.LoadOk(); ok {
|
||||||
return f(ip)
|
return f(ip)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -63,8 +63,8 @@ const _RP_FORCE = 1 // Flag for RefreshPolicyEx
|
|||||||
type nrptRuleDatabase struct {
|
type nrptRuleDatabase struct {
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
watcher *gpNotificationWatcher
|
watcher *gpNotificationWatcher
|
||||||
isGPRefreshPending atomic.Value // of bool
|
isGPRefreshPending atomic.Bool
|
||||||
mu sync.Mutex // protects the fields below
|
mu sync.Mutex // protects the fields below
|
||||||
ruleIDs []string
|
ruleIDs []string
|
||||||
isGPDirty bool
|
isGPDirty bool
|
||||||
writeAsGP bool
|
writeAsGP bool
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
dns "golang.org/x/net/dns/dnsmessage"
|
dns "golang.org/x/net/dns/dnsmessage"
|
||||||
@ -29,6 +28,7 @@ import (
|
|||||||
"tailscale.com/net/netaddr"
|
"tailscale.com/net/netaddr"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/net/tsdial"
|
"tailscale.com/net/tsdial"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
@ -495,7 +495,7 @@ type resolvConfCache struct {
|
|||||||
|
|
||||||
// resolvConfCacheValue contains the most recent stat metadata and parsed
|
// resolvConfCacheValue contains the most recent stat metadata and parsed
|
||||||
// version of /etc/resolv.conf.
|
// version of /etc/resolv.conf.
|
||||||
var resolvConfCacheValue atomic.Value // of resolvConfCache
|
var resolvConfCacheValue syncs.AtomicValue[resolvConfCache]
|
||||||
|
|
||||||
var errEmptyResolvConf = errors.New("resolv.conf has no nameservers")
|
var errEmptyResolvConf = errors.New("resolv.conf has no nameservers")
|
||||||
|
|
||||||
@ -510,7 +510,7 @@ func stubResolverForOS() (ip netip.Addr, err error) {
|
|||||||
mod: fi.ModTime(),
|
mod: fi.ModTime(),
|
||||||
size: fi.Size(),
|
size: fi.Size(),
|
||||||
}
|
}
|
||||||
if c, ok := resolvConfCacheValue.Load().(resolvConfCache); ok && c.mod == cur.mod && c.size == cur.size {
|
if c, ok := resolvConfCacheValue.LoadOk(); ok && c.mod == cur.mod && c.size == cur.size {
|
||||||
return c.ip, nil
|
return c.ip, nil
|
||||||
}
|
}
|
||||||
conf, err := resolvconffile.ParseFile(resolvconffile.Path)
|
conf, err := resolvconffile.ParseFile(resolvconffile.Path)
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -43,8 +42,6 @@ type Dialer struct {
|
|||||||
// If nil, it's not used.
|
// If nil, it's not used.
|
||||||
NetstackDialTCP func(context.Context, netip.AddrPort) (net.Conn, error)
|
NetstackDialTCP func(context.Context, netip.AddrPort) (net.Conn, error)
|
||||||
|
|
||||||
peerDialControlFuncAtomic atomic.Value // of func() func(network, address string, c syscall.RawConn) error
|
|
||||||
|
|
||||||
peerClientOnce sync.Once
|
peerClientOnce sync.Once
|
||||||
peerClient *http.Client
|
peerClient *http.Client
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -22,6 +21,7 @@ import (
|
|||||||
"github.com/alexbrainman/sspi/negotiate"
|
"github.com/alexbrainman/sspi/negotiate"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/cmpver"
|
"tailscale.com/util/cmpver"
|
||||||
)
|
)
|
||||||
@ -155,10 +155,10 @@ const win8dot1Ver = "6.3"
|
|||||||
|
|
||||||
// accessType is the flag we must pass to WinHttpOpen for proxy resolution
|
// accessType is the flag we must pass to WinHttpOpen for proxy resolution
|
||||||
// depending on whether or not we're running Windows < 8.1
|
// depending on whether or not we're running Windows < 8.1
|
||||||
var accessType atomic.Value // of uint32
|
var accessType syncs.AtomicValue[uint32]
|
||||||
|
|
||||||
func getAccessFlag() uint32 {
|
func getAccessFlag() uint32 {
|
||||||
if flag, ok := accessType.Load().(uint32); ok {
|
if flag, ok := accessType.LoadOk(); ok {
|
||||||
return flag
|
return flag
|
||||||
}
|
}
|
||||||
var flag uint32
|
var flag uint32
|
||||||
|
@ -341,8 +341,7 @@ func run(prog string, args ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Wrapper) destMAC() [6]byte {
|
func (t *Wrapper) destMAC() [6]byte {
|
||||||
mac, _ := t.destMACAtomic.Load().([6]byte)
|
return t.destMACAtomic.Load()
|
||||||
return mac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Wrapper) tapWrite(buf []byte, offset int) (int, error) {
|
func (t *Wrapper) tapWrite(buf []byte, offset int) (int, error) {
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"tailscale.com/disco"
|
"tailscale.com/disco"
|
||||||
"tailscale.com/net/packet"
|
"tailscale.com/net/packet"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tstime/mono"
|
"tailscale.com/tstime/mono"
|
||||||
"tailscale.com/types/ipproto"
|
"tailscale.com/types/ipproto"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
@ -82,9 +83,9 @@ type Wrapper struct {
|
|||||||
// you might need to add a pad32.Four field here.
|
// you might need to add a pad32.Four field here.
|
||||||
lastActivityAtomic mono.Time // time of last send or receive
|
lastActivityAtomic mono.Time // time of last send or receive
|
||||||
|
|
||||||
destIPActivity atomic.Value // of map[netip.Addr]func()
|
destIPActivity syncs.AtomicValue[map[netip.Addr]func()]
|
||||||
destMACAtomic atomic.Value // of [6]byte
|
destMACAtomic syncs.AtomicValue[[6]byte]
|
||||||
discoKey atomic.Value // of key.DiscoPublic
|
discoKey syncs.AtomicValue[key.DiscoPublic]
|
||||||
|
|
||||||
// buffer stores the oldest unconsumed packet from tdev.
|
// buffer stores the oldest unconsumed packet from tdev.
|
||||||
// It is made a static buffer in order to avoid allocations.
|
// It is made a static buffer in order to avoid allocations.
|
||||||
@ -247,8 +248,8 @@ func (t *Wrapper) isSelfDisco(p *packet.Parsed) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
discoSrc := key.DiscoPublicFromRaw32(mem.B(discobs))
|
discoSrc := key.DiscoPublicFromRaw32(mem.B(discobs))
|
||||||
selfDiscoPub, ok := t.discoKey.Load().(key.DiscoPublic)
|
selfDiscoPub := t.discoKey.Load()
|
||||||
return ok && selfDiscoPub == discoSrc
|
return selfDiscoPub == discoSrc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Wrapper) Close() error {
|
func (t *Wrapper) Close() error {
|
||||||
@ -543,7 +544,7 @@ func (t *Wrapper) Read(buf []byte, offset int) (int, error) {
|
|||||||
defer parsedPacketPool.Put(p)
|
defer parsedPacketPool.Put(p)
|
||||||
p.Decode(buf[offset : offset+n])
|
p.Decode(buf[offset : offset+n])
|
||||||
|
|
||||||
if m, ok := t.destIPActivity.Load().(map[netip.Addr]func()); ok {
|
if m := t.destIPActivity.Load(); m != nil {
|
||||||
if fn := m[p.Dst.Addr()]; fn != nil {
|
if fn := m[p.Dst.Addr()]; fn != nil {
|
||||||
fn()
|
fn()
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,14 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/version/distro"
|
"tailscale.com/version/distro"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AppSharedDir is a string set by the iOS or Android app on start
|
// AppSharedDir is a string set by the iOS or Android app on start
|
||||||
// containing a directory we can read/write in.
|
// containing a directory we can read/write in.
|
||||||
var AppSharedDir atomic.Value // of string
|
var AppSharedDir syncs.AtomicValue[string]
|
||||||
|
|
||||||
// DefaultTailscaledSocket returns the path to the tailscaled Unix socket
|
// DefaultTailscaledSocket returns the path to the tailscaled Unix socket
|
||||||
// or the empty string if there's no reasonable default.
|
// or the empty string if there's no reasonable default.
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
"tailscale.com/ipn/store"
|
"tailscale.com/ipn/store"
|
||||||
"tailscale.com/safesocket"
|
"tailscale.com/safesocket"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
"tailscale.com/tstest/integration/testcontrol"
|
"tailscale.com/tstest/integration/testcontrol"
|
||||||
@ -46,7 +47,7 @@ var (
|
|||||||
verboseTailscale = flag.Bool("verbose-tailscale", false, "verbose tailscale CLI logging")
|
verboseTailscale = flag.Bool("verbose-tailscale", false, "verbose tailscale CLI logging")
|
||||||
)
|
)
|
||||||
|
|
||||||
var mainError atomic.Value // of error
|
var mainError syncs.AtomicValue[error]
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
// Have to disable UPnP which hits the network, otherwise it fails due to HTTP proxy.
|
// Have to disable UPnP which hits the network, otherwise it fails due to HTTP proxy.
|
||||||
@ -57,7 +58,7 @@ func TestMain(m *testing.M) {
|
|||||||
if v != 0 {
|
if v != 0 {
|
||||||
os.Exit(v)
|
os.Exit(v)
|
||||||
}
|
}
|
||||||
if err, ok := mainError.Load().(error); ok {
|
if err := mainError.Load(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "FAIL: %v\n", err)
|
fmt.Fprintf(os.Stderr, "FAIL: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -936,14 +937,11 @@ func (n *testNode) MustStatus() *ipnstate.Status {
|
|||||||
// HTTP traffic tries to leave localhost from tailscaled. We don't
|
// HTTP traffic tries to leave localhost from tailscaled. We don't
|
||||||
// expect any, so any request triggers a failure.
|
// expect any, so any request triggers a failure.
|
||||||
type trafficTrap struct {
|
type trafficTrap struct {
|
||||||
atomicErr atomic.Value // of error
|
atomicErr syncs.AtomicValue[error]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tt *trafficTrap) Err() error {
|
func (tt *trafficTrap) Err() error {
|
||||||
if err, ok := tt.atomicErr.Load().(error); ok {
|
return tt.atomicErr.Load()
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tt *trafficTrap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (tt *trafficTrap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -107,3 +107,13 @@ func (k NLPublic) MarshalText() ([]byte, error) {
|
|||||||
func (k NLPublic) Verifier() ed25519.PublicKey {
|
func (k NLPublic) Verifier() ed25519.PublicKey {
|
||||||
return ed25519.PublicKey(k.k[:])
|
return ed25519.PublicKey(k.k[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsZero reports whether k is the zero value.
|
||||||
|
func (k NLPublic) IsZero() bool {
|
||||||
|
return k.Equal(NLPublic{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal reports whether k and other are the same key.
|
||||||
|
func (k NLPublic) Equal(other NLPublic) bool {
|
||||||
|
return subtle.ConstantTimeCompare(k.k[:], other.k[:]) == 1
|
||||||
|
}
|
||||||
|
@ -14,8 +14,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/syncs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommonNonRoutableMetadataIP is the IP address of the metadata server
|
// CommonNonRoutableMetadataIP is the IP address of the metadata server
|
||||||
@ -69,15 +70,14 @@ func (c Cloud) HasInternalTLD() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var cloudAtomic atomic.Value // of Cloud
|
var cloudAtomic syncs.AtomicValue[Cloud]
|
||||||
|
|
||||||
// Get returns the current cloud, or the empty string if unknown.
|
// Get returns the current cloud, or the empty string if unknown.
|
||||||
func Get() Cloud {
|
func Get() Cloud {
|
||||||
c, ok := cloudAtomic.Load().(Cloud)
|
if c, ok := cloudAtomic.LoadOk(); ok {
|
||||||
if ok {
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
c = getCloud()
|
c := getCloud()
|
||||||
cloudAtomic.Store(c) // even if empty
|
cloudAtomic.Store(c) // even if empty
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
|
||||||
|
"tailscale.com/syncs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Distro string
|
type Distro string
|
||||||
@ -28,14 +29,14 @@ const (
|
|||||||
WDMyCloud = Distro("wdmycloud")
|
WDMyCloud = Distro("wdmycloud")
|
||||||
)
|
)
|
||||||
|
|
||||||
var distroAtomic atomic.Value // of Distro
|
var distroAtomic syncs.AtomicValue[Distro]
|
||||||
|
|
||||||
// Get returns the current distro, or the empty string if unknown.
|
// Get returns the current distro, or the empty string if unknown.
|
||||||
func Get() Distro {
|
func Get() Distro {
|
||||||
d, ok := distroAtomic.Load().(Distro)
|
if d, ok := distroAtomic.LoadOk(); ok {
|
||||||
if ok {
|
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
var d Distro
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
d = linuxDistro()
|
d = linuxDistro()
|
||||||
|
@ -9,7 +9,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
|
||||||
|
"tailscale.com/syncs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsMobile reports whether this is a mobile client build.
|
// IsMobile reports whether this is a mobile client build.
|
||||||
@ -43,7 +44,7 @@ func IsSandboxedMacOS() bool {
|
|||||||
return strings.HasSuffix(exe, "/Contents/MacOS/Tailscale")
|
return strings.HasSuffix(exe, "/Contents/MacOS/Tailscale")
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMacSysExt atomic.Value // of bool
|
var isMacSysExt syncs.AtomicValue[bool]
|
||||||
|
|
||||||
// IsMacSysExt whether this binary is from the standalone "System
|
// IsMacSysExt whether this binary is from the standalone "System
|
||||||
// Extension" (a.k.a. "macsys") version of Tailscale for macOS.
|
// Extension" (a.k.a. "macsys") version of Tailscale for macOS.
|
||||||
@ -51,7 +52,7 @@ func IsMacSysExt() bool {
|
|||||||
if runtime.GOOS != "darwin" {
|
if runtime.GOOS != "darwin" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if b, ok := isMacSysExt.Load().(bool); ok {
|
if b, ok := isMacSysExt.LoadOk(); ok {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
|
@ -264,7 +264,7 @@ type Conn struct {
|
|||||||
|
|
||||||
// stunReceiveFunc holds the current STUN packet processing func.
|
// stunReceiveFunc holds the current STUN packet processing func.
|
||||||
// Its Loaded value is always non-nil.
|
// Its Loaded value is always non-nil.
|
||||||
stunReceiveFunc atomic.Value // of func(p []byte, fromAddr *net.UDPAddr)
|
stunReceiveFunc syncs.AtomicValue[func(p []byte, fromAddr netip.AddrPort)]
|
||||||
|
|
||||||
// derpRecvCh is used by receiveDERP to read DERP messages.
|
// derpRecvCh is used by receiveDERP to read DERP messages.
|
||||||
// It must have buffer size > 0; see issue 3736.
|
// It must have buffer size > 0; see issue 3736.
|
||||||
@ -300,7 +300,7 @@ type Conn struct {
|
|||||||
|
|
||||||
// havePrivateKey is whether privateKey is non-zero.
|
// havePrivateKey is whether privateKey is non-zero.
|
||||||
havePrivateKey atomic.Bool
|
havePrivateKey atomic.Bool
|
||||||
publicKeyAtomic atomic.Value // of key.NodePublic (or NodeKey zero value if !havePrivateKey)
|
publicKeyAtomic syncs.AtomicValue[key.NodePublic] // or NodeKey zero value if !havePrivateKey
|
||||||
|
|
||||||
// derpMapAtomic is the same as derpMap, but without requiring
|
// derpMapAtomic is the same as derpMap, but without requiring
|
||||||
// sync.Mutex. For use with NewRegionClient's callback, to avoid
|
// sync.Mutex. For use with NewRegionClient's callback, to avoid
|
||||||
@ -1668,7 +1668,7 @@ func (c *Conn) receiveIPv4(b []byte) (n int, ep conn.Endpoint, err error) {
|
|||||||
// caller).
|
// caller).
|
||||||
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (ep *endpoint, ok bool) {
|
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (ep *endpoint, ok bool) {
|
||||||
if stun.Is(b) {
|
if stun.Is(b) {
|
||||||
c.stunReceiveFunc.Load().(func([]byte, netip.AddrPort))(b, ipp)
|
c.stunReceiveFunc.Load()(b, ipp)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if c.handleDiscoMessage(b, ipp, key.NodePublic{}) {
|
if c.handleDiscoMessage(b, ipp, key.NodePublic{}) {
|
||||||
@ -2979,10 +2979,8 @@ type RebindingUDPConn struct {
|
|||||||
// check pconn (after acquiring mu) to see if there's been a rebind
|
// check pconn (after acquiring mu) to see if there's been a rebind
|
||||||
// meanwhile.
|
// meanwhile.
|
||||||
// pconn isn't really needed, but makes some of the code simpler
|
// pconn isn't really needed, but makes some of the code simpler
|
||||||
// to keep it in a type safe form. TODO(bradfitz): really we should make a generic
|
// to keep it in a type safe form.
|
||||||
// atomic.Value. Unfortunately Go 1.19's atomic.Pointer[T] is only for pointers,
|
pconnAtomic syncs.AtomicValue[nettype.PacketConn]
|
||||||
// not interfaces.
|
|
||||||
pconnAtomic atomic.Value // of nettype.PacketConn
|
|
||||||
|
|
||||||
mu sync.Mutex // held while changing pconn (and pconnAtomic)
|
mu sync.Mutex // held while changing pconn (and pconnAtomic)
|
||||||
pconn nettype.PacketConn
|
pconn nettype.PacketConn
|
||||||
@ -3004,7 +3002,7 @@ func (c *RebindingUDPConn) currentConn() nettype.PacketConn {
|
|||||||
// It returns the number of bytes copied and the source address.
|
// It returns the number of bytes copied and the source address.
|
||||||
func (c *RebindingUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
func (c *RebindingUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||||
for {
|
for {
|
||||||
pconn := c.pconnAtomic.Load().(nettype.PacketConn)
|
pconn := c.pconnAtomic.Load()
|
||||||
n, addr, err := pconn.ReadFrom(b)
|
n, addr, err := pconn.ReadFrom(b)
|
||||||
if err != nil && pconn != c.currentConn() {
|
if err != nil && pconn != c.currentConn() {
|
||||||
continue
|
continue
|
||||||
@ -3022,7 +3020,7 @@ func (c *RebindingUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
|||||||
// when c's underlying connection is a net.UDPConn.
|
// when c's underlying connection is a net.UDPConn.
|
||||||
func (c *RebindingUDPConn) ReadFromNetaddr(b []byte) (n int, ipp netip.AddrPort, err error) {
|
func (c *RebindingUDPConn) ReadFromNetaddr(b []byte) (n int, ipp netip.AddrPort, err error) {
|
||||||
for {
|
for {
|
||||||
pconn := c.pconnAtomic.Load().(nettype.PacketConn)
|
pconn := c.pconnAtomic.Load()
|
||||||
|
|
||||||
// Optimization: Treat *net.UDPConn specially.
|
// Optimization: Treat *net.UDPConn specially.
|
||||||
// This lets us avoid allocations by calling ReadFromUDPAddrPort.
|
// This lets us avoid allocations by calling ReadFromUDPAddrPort.
|
||||||
@ -3081,7 +3079,7 @@ func (c *RebindingUDPConn) closeLocked() error {
|
|||||||
|
|
||||||
func (c *RebindingUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
func (c *RebindingUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||||
for {
|
for {
|
||||||
pconn := c.pconnAtomic.Load().(nettype.PacketConn)
|
pconn := c.pconnAtomic.Load()
|
||||||
|
|
||||||
n, err := pconn.WriteTo(b, addr)
|
n, err := pconn.WriteTo(b, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -3095,7 +3093,7 @@ func (c *RebindingUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
|||||||
|
|
||||||
func (c *RebindingUDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
func (c *RebindingUDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
||||||
for {
|
for {
|
||||||
pconn := c.pconnAtomic.Load().(nettype.PacketConn)
|
pconn := c.pconnAtomic.Load()
|
||||||
|
|
||||||
n, err := pconn.WriteToUDPAddrPort(b, addr)
|
n, err := pconn.WriteToUDPAddrPort(b, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -3643,10 +3641,9 @@ func (de *endpoint) removeSentPingLocked(txid stun.TxID, sp sentPing) {
|
|||||||
// The caller should use de.discoKey as the discoKey argument.
|
// The caller should use de.discoKey as the discoKey argument.
|
||||||
// It is passed in so that sendDiscoPing doesn't need to lock de.mu.
|
// It is passed in so that sendDiscoPing doesn't need to lock de.mu.
|
||||||
func (de *endpoint) sendDiscoPing(ep netip.AddrPort, discoKey key.DiscoPublic, txid stun.TxID, logLevel discoLogLevel) {
|
func (de *endpoint) sendDiscoPing(ep netip.AddrPort, discoKey key.DiscoPublic, txid stun.TxID, logLevel discoLogLevel) {
|
||||||
selfPubKey, _ := de.c.publicKeyAtomic.Load().(key.NodePublic)
|
|
||||||
sent, _ := de.c.sendDiscoMessage(ep, de.publicKey, discoKey, &disco.Ping{
|
sent, _ := de.c.sendDiscoMessage(ep, de.publicKey, discoKey, &disco.Ping{
|
||||||
TxID: [12]byte(txid),
|
TxID: [12]byte(txid),
|
||||||
NodeKey: selfPubKey,
|
NodeKey: de.c.publicKeyAtomic.Load(),
|
||||||
}, logLevel)
|
}, logLevel)
|
||||||
if !sent {
|
if !sent {
|
||||||
de.forgetPing(txid)
|
de.forgetPing(txid)
|
||||||
|
@ -117,7 +117,7 @@ type Impl struct {
|
|||||||
// is a local (non-subnet) Tailscale IP address of this
|
// is a local (non-subnet) Tailscale IP address of this
|
||||||
// machine. It's always a non-nil func. It's changed on netmap
|
// machine. It's always a non-nil func. It's changed on netmap
|
||||||
// updates.
|
// updates.
|
||||||
atomicIsLocalIPFunc atomic.Value // of func(netip.Addr) bool
|
atomicIsLocalIPFunc syncs.AtomicValue[func(netip.Addr) bool]
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
// connsOpenBySubnetIP keeps track of number of connections open
|
// connsOpenBySubnetIP keeps track of number of connections open
|
||||||
@ -513,7 +513,7 @@ func (ns *Impl) inject() {
|
|||||||
// isLocalIP reports whether ip is a Tailscale IP assigned to this
|
// isLocalIP reports whether ip is a Tailscale IP assigned to this
|
||||||
// node directly (but not a subnet-routed IP).
|
// node directly (but not a subnet-routed IP).
|
||||||
func (ns *Impl) isLocalIP(ip netip.Addr) bool {
|
func (ns *Impl) isLocalIP(ip netip.Addr) bool {
|
||||||
return ns.atomicIsLocalIPFunc.Load().(func(netip.Addr) bool)(ip)
|
return ns.atomicIsLocalIPFunc.Load()(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *Impl) processSSH() bool {
|
func (ns *Impl) processSSH() bool {
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
@ -36,6 +35,7 @@ import (
|
|||||||
"tailscale.com/net/tsdial"
|
"tailscale.com/net/tsdial"
|
||||||
"tailscale.com/net/tshttpproxy"
|
"tailscale.com/net/tshttpproxy"
|
||||||
"tailscale.com/net/tstun"
|
"tailscale.com/net/tstun"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/tstime/mono"
|
"tailscale.com/tstime/mono"
|
||||||
"tailscale.com/types/dnstype"
|
"tailscale.com/types/dnstype"
|
||||||
@ -107,11 +107,11 @@ type userspaceEngine struct {
|
|||||||
// isLocalAddr reports the whether an IP is assigned to the local
|
// isLocalAddr reports the whether an IP is assigned to the local
|
||||||
// tunnel interface. It's used to reflect local packets
|
// tunnel interface. It's used to reflect local packets
|
||||||
// incorrectly sent to us.
|
// incorrectly sent to us.
|
||||||
isLocalAddr atomic.Value // of func(netip.Addr)bool
|
isLocalAddr syncs.AtomicValue[func(netip.Addr) bool]
|
||||||
|
|
||||||
// isDNSIPOverTailscale reports the whether a DNS resolver's IP
|
// isDNSIPOverTailscale reports the whether a DNS resolver's IP
|
||||||
// is being routed over Tailscale.
|
// is being routed over Tailscale.
|
||||||
isDNSIPOverTailscale atomic.Value // of func(netip.Addr)bool
|
isDNSIPOverTailscale syncs.AtomicValue[func(netip.Addr) bool]
|
||||||
|
|
||||||
wgLock sync.Mutex // serializes all wgdev operations; see lock order comment below
|
wgLock sync.Mutex // serializes all wgdev operations; see lock order comment below
|
||||||
lastCfgFull wgcfg.Config
|
lastCfgFull wgcfg.Config
|
||||||
@ -497,7 +497,7 @@ func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||||
isLocalAddr, ok := e.isLocalAddr.Load().(func(netip.Addr) bool)
|
isLocalAddr, ok := e.isLocalAddr.LoadOk()
|
||||||
if !ok {
|
if !ok {
|
||||||
e.logf("[unexpected] e.isLocalAddr was nil, can't check for loopback packet")
|
e.logf("[unexpected] e.isLocalAddr was nil, can't check for loopback packet")
|
||||||
} else if isLocalAddr(p.Dst.Addr()) {
|
} else if isLocalAddr(p.Dst.Addr()) {
|
||||||
@ -1621,7 +1621,7 @@ type fwdDNSLinkSelector struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ls fwdDNSLinkSelector) PickLink(ip netip.Addr) (linkName string) {
|
func (ls fwdDNSLinkSelector) PickLink(ip netip.Addr) (linkName string) {
|
||||||
if ls.ue.isDNSIPOverTailscale.Load().(func(netip.Addr) bool)(ip) {
|
if ls.ue.isDNSIPOverTailscale.Load()(ip) {
|
||||||
return ls.tunName
|
return ls.tunName
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
|
"tailscale.com/syncs"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/wgengine/wgcfg"
|
"tailscale.com/wgengine/wgcfg"
|
||||||
@ -21,7 +21,7 @@ import (
|
|||||||
// It can be modified at run time to adjust to new wireguard-go configurations.
|
// It can be modified at run time to adjust to new wireguard-go configurations.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
DeviceLogger *device.Logger
|
DeviceLogger *device.Logger
|
||||||
replace atomic.Value // of map[string]string
|
replace syncs.AtomicValue[map[string]string]
|
||||||
mu sync.Mutex // protects strs
|
mu sync.Mutex // protects strs
|
||||||
strs map[key.NodePublic]*strCache // cached strs used to populate replace
|
strs map[key.NodePublic]*strCache // cached strs used to populate replace
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ func NewLogger(logf logger.Logf) *Logger {
|
|||||||
// See https://github.com/tailscale/tailscale/issues/1388.
|
// See https://github.com/tailscale/tailscale/issues/1388.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
replace, _ := ret.replace.Load().(map[string]string)
|
replace := ret.replace.Load()
|
||||||
if replace == nil {
|
if replace == nil {
|
||||||
// No replacements specified; log as originally planned.
|
// No replacements specified; log as originally planned.
|
||||||
logf(format, args...)
|
logf(format, args...)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user