diff --git a/control/controlknobs/controlknobs.go b/control/controlknobs/controlknobs.go index e64bc8011..4bc309840 100644 --- a/control/controlknobs/controlknobs.go +++ b/control/controlknobs/controlknobs.go @@ -52,6 +52,8 @@ type Knobs struct { // DisableDNSForwarderTCPRetries is whether the DNS forwarder should // skip retrying truncated queries over TCP. DisableDNSForwarderTCPRetries atomic.Bool + + SilentDisco atomic.Bool } // UpdateFromNodeAttributes updates k (if non-nil) based on the provided self @@ -74,6 +76,7 @@ func (k *Knobs) UpdateFromNodeAttributes(selfNodeAttrs []tailcfg.NodeCapability, forceBackgroundSTUN = has(tailcfg.NodeAttrDebugForceBackgroundSTUN) peerMTUEnable = has(tailcfg.NodeAttrPeerMTUEnable) dnsForwarderDisableTCPRetries = has(tailcfg.NodeAttrDNSForwarderDisableTCPRetries) + silentDisco = has(tailcfg.NodeAttrSilentDisco) ) if has(tailcfg.NodeAttrOneCGNATEnable) { @@ -91,6 +94,7 @@ func (k *Knobs) UpdateFromNodeAttributes(selfNodeAttrs []tailcfg.NodeCapability, k.DisableDeltaUpdates.Store(disableDeltaUpdates) k.PeerMTUEnable.Store(peerMTUEnable) k.DisableDNSForwarderTCPRetries.Store(dnsForwarderDisableTCPRetries) + k.SilentDisco.Store(silentDisco) } // AsDebugJSON returns k as something that can be marshalled with json.Marshal diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 7180bb8a4..f063ea240 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -4348,6 +4348,8 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) { } b.capFileSharing = fs + b.magicConn().SetSilentDisco(b.ControlKnobs().SilentDisco.Load()) + b.setDebugLogsByCapabilityLocked(nm) // See the netns package for documentation on what this capability does. diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 54f3b24f7..845595d5f 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -2126,6 +2126,8 @@ const ( // fixed port. NodeAttrRandomizeClientPort NodeCapability = "randomize-client-port" + NodeAttrSilentDisco NodeCapability = "silent-disco" + // NodeAttrOneCGNATEnable makes the client prefer one big CGNAT /10 route // rather than a /32 per peer. At most one of this or // NodeAttrOneCGNATDisable may be set; if neither are, it's automatic. diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 5f1288e0e..60c9bf670 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -139,6 +139,8 @@ type Conn struct { // logging. noV4, noV6 atomic.Bool + silentDiscoOn atomic.Bool // whether silent disco is enabled + // noV4Send is whether IPv4 UDP is known to be unable to transmit // at all. This could happen if the socket is in an invalid state // (as can happen on darwin after a network link status change). @@ -1801,6 +1803,14 @@ func (c *Conn) debugFlagsLocked() (f debugFlags) { return } +func (c *Conn) SetSilentDisco(v bool) { + old := c.silentDiscoOn.Swap(v) + if old == v { + return + } + // .... +} + // SetNetworkMap is called when the control client gets a new network // map from the control server. It must always be non-nil. //