From 745931415c58f0ebc90ccf8e20b426f82652ce24 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 26 Apr 2024 10:12:46 -0700 Subject: [PATCH] health, all: remove health.Global, finish plumbing health.Tracker Updates #11874 Updates #4136 Change-Id: I414470f71d90be9889d44c3afd53956d9f26cd61 Signed-off-by: Brad Fitzpatrick --- cmd/tailscaled/tailscaled.go | 8 ++++---- cmd/tsconnect/wasm/wasm_js.go | 7 ++++--- control/controlclient/direct.go | 17 +++++++++-------- control/controlclient/noise.go | 6 ++++++ control/controlhttp/client.go | 3 +-- control/controlhttp/constants.go | 4 ++++ health/health.go | 12 +++--------- ipn/ipnlocal/local.go | 2 +- log/sockstatlog/logger.go | 5 +++-- log/sockstatlog/logger_test.go | 2 +- logpolicy/logpolicy.go | 14 +++++++------- net/dns/direct.go | 13 ++++++++----- net/dns/direct_linux.go | 4 ++-- net/dns/manager.go | 16 +++++++++------- net/dns/manager_darwin.go | 3 ++- net/dns/manager_default.go | 10 +++++----- net/dns/manager_freebsd.go | 11 ++++++----- net/dns/manager_linux.go | 14 +++++++------- net/dns/manager_linux_test.go | 2 +- net/dns/manager_openbsd.go | 11 ++++++----- net/dns/manager_tcp_test.go | 4 ++-- net/dns/manager_test.go | 2 +- net/dns/manager_windows.go | 5 +++-- net/dns/manager_windows_test.go | 4 ++-- net/dns/resolved.go | 16 +++++++++------- net/dns/wsl_windows.go | 11 +++++++---- tsd/tsd.go | 8 -------- tsnet/tsnet.go | 9 +++++---- wgengine/netlog/logger.go | 5 +++-- wgengine/router/ifconfig_windows.go | 6 +++--- wgengine/router/router.go | 5 +++-- wgengine/router/router_darwin.go | 5 +++-- wgengine/router/router_default.go | 3 ++- wgengine/router/router_freebsd.go | 5 +++-- wgengine/router/router_linux.go | 3 ++- wgengine/router/router_linux_test.go | 2 +- wgengine/router/router_openbsd.go | 3 ++- wgengine/router/router_userspace_bsd.go | 5 ++++- wgengine/router/router_windows.go | 7 +++++-- wgengine/userspace.go | 4 ++-- 40 files changed, 151 insertions(+), 125 deletions(-) diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 9a915a8b4..8e28bb50d 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -358,7 +358,7 @@ func run() (err error) { sys.Set(netMon) } - pol := logpolicy.New(logtail.CollectionNode, netMon, nil /* use log.Printf */) + pol := logpolicy.New(logtail.CollectionNode, netMon, sys.HealthTracker(), nil /* use log.Printf */) pol.SetVerbosityLevel(args.verbose) logPol = pol defer func() { @@ -677,7 +677,7 @@ func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack boo // configuration being unavailable (from the noop // manager). More in Issue 4017. // TODO(bradfitz): add a Synology-specific DNS manager. - conf.DNS, err = dns.NewOSConfigurator(logf, "") // empty interface name + conf.DNS, err = dns.NewOSConfigurator(logf, sys.HealthTracker(), "") // empty interface name if err != nil { return false, fmt.Errorf("dns.NewOSConfigurator: %w", err) } @@ -699,13 +699,13 @@ func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack boo return false, err } - r, err := router.New(logf, dev, sys.NetMon.Get()) + r, err := router.New(logf, dev, sys.NetMon.Get(), sys.HealthTracker()) if err != nil { dev.Close() return false, fmt.Errorf("creating router: %w", err) } - d, err := dns.NewOSConfigurator(logf, devName) + d, err := dns.NewOSConfigurator(logf, sys.HealthTracker(), devName) if err != nil { dev.Close() r.Close() diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index cb1f4fff1..0724af395 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -104,9 +104,10 @@ func newIPN(jsConfig js.Value) map[string]any { sys.Set(store) dialer := &tsdial.Dialer{Logf: logf} eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ - Dialer: dialer, - SetSubsystem: sys.Set, - ControlKnobs: sys.ControlKnobs(), + Dialer: dialer, + SetSubsystem: sys.Set, + ControlKnobs: sys.ControlKnobs(), + HealthTracker: sys.HealthTracker(), }) if err != nil { log.Fatal(err) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 89d670f6c..db2475e66 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -1453,14 +1453,15 @@ func (c *Direct) getNoiseClient() (*NoiseClient, error) { } c.logf("[v1] creating new noise client") nc, err := NewNoiseClient(NoiseOpts{ - PrivKey: k, - ServerPubKey: serverNoiseKey, - ServerURL: c.serverURL, - Dialer: c.dialer, - DNSCache: c.dnsCache, - Logf: c.logf, - NetMon: c.netMon, - DialPlan: dp, + PrivKey: k, + ServerPubKey: serverNoiseKey, + ServerURL: c.serverURL, + Dialer: c.dialer, + DNSCache: c.dnsCache, + Logf: c.logf, + NetMon: c.netMon, + HealthTracker: c.health, + DialPlan: dp, }) if err != nil { return nil, err diff --git a/control/controlclient/noise.go b/control/controlclient/noise.go index f3e5f1bde..5a1c25e96 100644 --- a/control/controlclient/noise.go +++ b/control/controlclient/noise.go @@ -19,6 +19,7 @@ import ( "golang.org/x/net/http2" "tailscale.com/control/controlbase" "tailscale.com/control/controlhttp" + "tailscale.com/health" "tailscale.com/net/dnscache" "tailscale.com/net/netmon" "tailscale.com/net/tsdial" @@ -174,6 +175,7 @@ type NoiseClient struct { logf logger.Logf netMon *netmon.Monitor + health *health.Tracker // mu only protects the following variables. mu sync.Mutex @@ -204,6 +206,8 @@ type NoiseOpts struct { // network interface state. This field can be nil; if so, the current // state will be looked up dynamically. NetMon *netmon.Monitor + // HealthTracker, if non-nil, is the health tracker to use. + HealthTracker *health.Tracker // DialPlan, if set, is a function that should return an explicit plan // on how to connect to the server. DialPlan func() *tailcfg.ControlDialPlan @@ -247,6 +251,7 @@ func NewNoiseClient(opts NoiseOpts) (*NoiseClient, error) { dialPlan: opts.DialPlan, logf: opts.Logf, netMon: opts.NetMon, + health: opts.HealthTracker, } // Create the HTTP/2 Transport using a net/http.Transport @@ -453,6 +458,7 @@ func (nc *NoiseClient) dial(ctx context.Context) (*noiseConn, error) { DialPlan: dialPlan, Logf: nc.logf, NetMon: nc.netMon, + HealthTracker: nc.health, Clock: tstime.StdClock{}, }).Dial(ctx) if err != nil { diff --git a/control/controlhttp/client.go b/control/controlhttp/client.go index 762a2eba1..f517ad91e 100644 --- a/control/controlhttp/client.go +++ b/control/controlhttp/client.go @@ -38,7 +38,6 @@ import ( "tailscale.com/control/controlbase" "tailscale.com/envknob" - "tailscale.com/health" "tailscale.com/net/dnscache" "tailscale.com/net/dnsfallback" "tailscale.com/net/netutil" @@ -434,7 +433,7 @@ func (a *Dialer) tryURLUpgrade(ctx context.Context, u *url.URL, addr netip.Addr, // Disable HTTP2, since h2 can't do protocol switching. tr.TLSClientConfig.NextProtos = []string{} tr.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{} - tr.TLSClientConfig = tlsdial.Config(a.Hostname, health.Global, tr.TLSClientConfig) + tr.TLSClientConfig = tlsdial.Config(a.Hostname, a.HealthTracker, tr.TLSClientConfig) if !tr.TLSClientConfig.InsecureSkipVerify { panic("unexpected") // should be set by tlsdial.Config } diff --git a/control/controlhttp/constants.go b/control/controlhttp/constants.go index 72161336e..6b5116262 100644 --- a/control/controlhttp/constants.go +++ b/control/controlhttp/constants.go @@ -8,6 +8,7 @@ import ( "net/url" "time" + "tailscale.com/health" "tailscale.com/net/dnscache" "tailscale.com/net/netmon" "tailscale.com/tailcfg" @@ -79,6 +80,9 @@ type Dialer struct { NetMon *netmon.Monitor + // HealthTracker, if non-nil, is the health tracker to use. + HealthTracker *health.Tracker + // DialPlan, if set, contains instructions from the control server on // how to connect to it. If present, we will try the methods in this // plan before falling back to DNS. diff --git a/health/health.go b/health/health.go index 7ef9abe36..2c095e2fd 100644 --- a/health/health.go +++ b/health/health.go @@ -30,15 +30,9 @@ var ( debugHandler map[string]http.Handler ) -// Global is a global health tracker for the process. -// -// TODO(bradfitz): finish moving all reference to this plumb it (ultimately out -// from tsd.System) so a process can have multiple tsnet/etc instances with -// their own health trackers. But for now (2024-04-25), the tsd.System value -// given out is just this one, until that's the only remaining Global reference -// remaining. -var Global = new(Tracker) - +// Tracker tracks the health of various Tailscale subsystems, +// comparing each subsystems' state with each other to make sure +// they're consistent based on the user's intended state. type Tracker struct { // mu guards everything in this var block. mu sync.Mutex diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 5ab0c05ac..dea812ef9 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -415,7 +415,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo } netMon := sys.NetMon.Get() - b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID, netMon) + b.sockstatLogger, err = sockstatlog.NewLogger(logpolicy.LogsDir(logf), logf, logID, netMon, sys.HealthTracker()) if err != nil { log.Printf("error setting up sockstat logger: %v", err) } diff --git a/log/sockstatlog/logger.go b/log/sockstatlog/logger.go index 6d258cf9b..e34dee483 100644 --- a/log/sockstatlog/logger.go +++ b/log/sockstatlog/logger.go @@ -17,6 +17,7 @@ import ( "sync/atomic" "time" + "tailscale.com/health" "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/logtail/filch" @@ -93,7 +94,7 @@ func SockstatLogID(logID logid.PublicID) logid.PrivateID { // The returned Logger is not yet enabled, and must be shut down with Shutdown when it is no longer needed. // Logs will be uploaded to the log server using a new log ID derived from the provided backend logID. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups. -func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor) (*Logger, error) { +func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID, netMon *netmon.Monitor, health *health.Tracker) (*Logger, error) { if !sockstats.IsAvailable { return nil, nil } @@ -113,7 +114,7 @@ func NewLogger(logdir string, logf logger.Logf, logID logid.PublicID, netMon *ne logger := &Logger{ logf: logf, filch: filch, - tr: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon, logf), + tr: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon, health, logf), } logger.logger = logtail.NewLogger(logtail.Config{ BaseURL: logpolicy.LogURL(), diff --git a/log/sockstatlog/logger_test.go b/log/sockstatlog/logger_test.go index 1e2d67d97..b5779b932 100644 --- a/log/sockstatlog/logger_test.go +++ b/log/sockstatlog/logger_test.go @@ -23,7 +23,7 @@ func TestResourceCleanup(t *testing.T) { if err != nil { t.Fatal(err) } - lg, err := NewLogger(td, logger.Discard, id.Public(), nil) + lg, err := NewLogger(td, logger.Discard, id.Public(), nil, nil) if err != nil { t.Fatal(err) } diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index 610e6e2df..4097ce898 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -453,13 +453,13 @@ func tryFixLogStateLocation(dir, cmdname string, logf logger.Logf) { // The logf parameter is optional; if non-nil, information logs (e.g. when // migrating state) are sent to that logger, and global changes to the log // package are avoided. If nil, logs will be printed using log.Printf. -func New(collection string, netMon *netmon.Monitor, logf logger.Logf) *Policy { - return NewWithConfigPath(collection, "", "", netMon, logf) +func New(collection string, netMon *netmon.Monitor, health *health.Tracker, logf logger.Logf) *Policy { + return NewWithConfigPath(collection, "", "", netMon, health, logf) } // NewWithConfigPath is identical to New, but uses the specified directory and // command name. If either is empty, it derives them automatically. -func NewWithConfigPath(collection, dir, cmdName string, netMon *netmon.Monitor, logf logger.Logf) *Policy { +func NewWithConfigPath(collection, dir, cmdName string, netMon *netmon.Monitor, health *health.Tracker, logf logger.Logf) *Policy { var lflags int if term.IsTerminal(2) || runtime.GOOS == "windows" { lflags = 0 @@ -555,7 +555,7 @@ func NewWithConfigPath(collection, dir, cmdName string, netMon *netmon.Monitor, PrivateID: newc.PrivateID, Stderr: logWriter{console}, CompressLogs: true, - HTTPC: &http.Client{Transport: NewLogtailTransport(logtail.DefaultHost, netMon, logf)}, + HTTPC: &http.Client{Transport: NewLogtailTransport(logtail.DefaultHost, netMon, health, logf)}, } if collection == logtail.CollectionNode { conf.MetricsDelta = clientmetric.EncodeLogTailMetricsDelta @@ -570,7 +570,7 @@ func NewWithConfigPath(collection, dir, cmdName string, netMon *netmon.Monitor, logf("You have enabled a non-default log target. Doing without being told to by Tailscale staff or your network administrator will make getting support difficult.") conf.BaseURL = val u, _ := url.Parse(val) - conf.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host, netMon, logf)} + conf.HTTPC = &http.Client{Transport: NewLogtailTransport(u.Host, netMon, health, logf)} } filchOptions := filch.Options{ @@ -742,7 +742,7 @@ func dialContext(ctx context.Context, netw, addr string, netMon *netmon.Monitor, // // The logf parameter is optional; if non-nil, logs are printed using the // provided function; if nil, log.Printf will be used instead. -func NewLogtailTransport(host string, netMon *netmon.Monitor, logf logger.Logf) http.RoundTripper { +func NewLogtailTransport(host string, netMon *netmon.Monitor, health *health.Tracker, logf logger.Logf) http.RoundTripper { if testenv.InTest() { return noopPretendSuccessTransport{} } @@ -783,7 +783,7 @@ func NewLogtailTransport(host string, netMon *netmon.Monitor, logf logger.Logf) tr.TLSNextProto = map[string]func(authority string, c *tls.Conn) http.RoundTripper{} } - tr.TLSClientConfig = tlsdial.Config(host, health.Global, tr.TLSClientConfig) + tr.TLSClientConfig = tlsdial.Config(host, health, tr.TLSClientConfig) return tr } diff --git a/net/dns/direct.go b/net/dns/direct.go index 69753d91c..23a9a04df 100644 --- a/net/dns/direct.go +++ b/net/dns/direct.go @@ -21,6 +21,7 @@ import ( "sync" "time" + "tailscale.com/health" "tailscale.com/net/dns/resolvconffile" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" @@ -116,8 +117,9 @@ func restartResolved() error { // The caller must call Down before program shutdown // or as cleanup if the program terminates unexpectedly. type directManager struct { - logf logger.Logf - fs wholeFileFS + logf logger.Logf + health *health.Tracker + fs wholeFileFS // renameBroken is set if fs.Rename to or from /etc/resolv.conf // fails. This can happen in some container runtimes, where // /etc/resolv.conf is bind-mounted from outside the container, @@ -140,14 +142,15 @@ type directManager struct { } //lint:ignore U1000 used in manager_{freebsd,openbsd}.go -func newDirectManager(logf logger.Logf) *directManager { - return newDirectManagerOnFS(logf, directFS{}) +func newDirectManager(logf logger.Logf, health *health.Tracker) *directManager { + return newDirectManagerOnFS(logf, health, directFS{}) } -func newDirectManagerOnFS(logf logger.Logf, fs wholeFileFS) *directManager { +func newDirectManagerOnFS(logf logger.Logf, health *health.Tracker, fs wholeFileFS) *directManager { ctx, cancel := context.WithCancel(context.Background()) m := &directManager{ logf: logf, + health: health, fs: fs, ctx: ctx, ctxClose: cancel, diff --git a/net/dns/direct_linux.go b/net/dns/direct_linux.go index eb6c4c6e2..1de22e1b9 100644 --- a/net/dns/direct_linux.go +++ b/net/dns/direct_linux.go @@ -78,7 +78,7 @@ func (m *directManager) checkForFileTrample() { return } if bytes.Equal(cur, want) { - health.Global.SetWarnable(warnTrample, nil) + m.health.SetWarnable(warnTrample, nil) if lastWarn != nil { m.mu.Lock() m.lastWarnContents = nil @@ -101,7 +101,7 @@ func (m *directManager) checkForFileTrample() { show = show[:1024] } m.logf("trample: resolv.conf changed from what we expected. did some other program interfere? current contents: %q", show) - health.Global.SetWarnable(warnTrample, errors.New("Linux DNS config not ideal. /etc/resolv.conf overwritten. See https://tailscale.com/s/dns-fight")) + m.health.SetWarnable(warnTrample, errors.New("Linux DNS config not ideal. /etc/resolv.conf overwritten. See https://tailscale.com/s/dns-fight")) } func (m *directManager) closeInotifyOnDone(ctx context.Context, in *gonotify.Inotify) { diff --git a/net/dns/manager.go b/net/dns/manager.go index bb9fce611..bea078a2b 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -42,7 +42,8 @@ const maxActiveQueries = 256 // Manager manages system DNS settings. type Manager struct { - logf logger.Logf + logf logger.Logf + health *health.Tracker activeQueriesAtomic int32 @@ -55,7 +56,7 @@ type Manager struct { // NewManagers created a new manager from the given config. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups. -func NewManager(logf logger.Logf, oscfg OSConfigurator, netMon *netmon.Monitor, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector, knobs *controlknobs.Knobs) *Manager { +func NewManager(logf logger.Logf, oscfg OSConfigurator, netMon *netmon.Monitor, health *health.Tracker, dialer *tsdial.Dialer, linkSel resolver.ForwardLinkSelector, knobs *controlknobs.Knobs) *Manager { if dialer == nil { panic("nil Dialer") } @@ -64,6 +65,7 @@ func NewManager(logf logger.Logf, oscfg OSConfigurator, netMon *netmon.Monitor, logf: logf, resolver: resolver.New(logf, netMon, linkSel, dialer, knobs), os: oscfg, + health: health, } m.ctx, m.ctxCancel = context.WithCancel(context.Background()) m.logf("using %T", m.os) @@ -94,10 +96,10 @@ func (m *Manager) Set(cfg Config) error { return err } if err := m.os.SetDNS(ocfg); err != nil { - health.Global.SetDNSOSHealth(err) + m.health.SetDNSOSHealth(err) return err } - health.Global.SetDNSOSHealth(nil) + m.health.SetDNSOSHealth(nil) return nil } @@ -248,7 +250,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig // This is currently (2022-10-13) expected on certain iOS and macOS // builds. } else { - health.Global.SetDNSOSHealth(err) + m.health.SetDNSOSHealth(err) return resolver.Config{}, OSConfig{}, err } } @@ -453,12 +455,12 @@ func (m *Manager) FlushCaches() error { // in case the Tailscale daemon terminated without closing the router. // No other state needs to be instantiated before this runs. func CleanUp(logf logger.Logf, interfaceName string) { - oscfg, err := NewOSConfigurator(logf, interfaceName) + oscfg, err := NewOSConfigurator(logf, nil, interfaceName) if err != nil { logf("creating dns cleanup: %v", err) return } - dns := NewManager(logf, oscfg, nil, &tsdial.Dialer{Logf: logf}, nil, nil) + dns := NewManager(logf, oscfg, nil, nil, &tsdial.Dialer{Logf: logf}, nil, nil) if err := dns.Down(); err != nil { logf("dns down: %v", err) } diff --git a/net/dns/manager_darwin.go b/net/dns/manager_darwin.go index 1f0887c71..3ccdd6103 100644 --- a/net/dns/manager_darwin.go +++ b/net/dns/manager_darwin.go @@ -8,11 +8,12 @@ import ( "os" "go4.org/mem" + "tailscale.com/health" "tailscale.com/types/logger" "tailscale.com/util/mak" ) -func NewOSConfigurator(logf logger.Logf, ifName string) (OSConfigurator, error) { +func NewOSConfigurator(logf logger.Logf, health *health.Tracker, ifName string) (OSConfigurator, error) { return &darwinConfigurator{logf: logf, ifName: ifName}, nil } diff --git a/net/dns/manager_default.go b/net/dns/manager_default.go index 41828ef82..838d0761c 100644 --- a/net/dns/manager_default.go +++ b/net/dns/manager_default.go @@ -5,11 +5,11 @@ package dns -import "tailscale.com/types/logger" +import ( + "tailscale.com/health" + "tailscale.com/types/logger" +) -func NewOSConfigurator(logger.Logf, string) (OSConfigurator, error) { - // TODO(dmytro): on darwin, we should use a macOS-specific method such as scutil. - // This is currently not implemented. Editing /etc/resolv.conf does not work, - // as most applications use the system resolver, which disregards it. +func NewOSConfigurator(logger.Logf, *health.Tracker, string) (OSConfigurator, error) { return NewNoopManager() } diff --git a/net/dns/manager_freebsd.go b/net/dns/manager_freebsd.go index 9d935d2e7..ac4567a6f 100644 --- a/net/dns/manager_freebsd.go +++ b/net/dns/manager_freebsd.go @@ -7,13 +7,14 @@ import ( "fmt" "os" + "tailscale.com/health" "tailscale.com/types/logger" ) -func NewOSConfigurator(logf logger.Logf, _ string) (OSConfigurator, error) { +func NewOSConfigurator(logf logger.Logf, health *health.Tracker, _ string) (OSConfigurator, error) { bs, err := os.ReadFile("/etc/resolv.conf") if os.IsNotExist(err) { - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil } if err != nil { return nil, fmt.Errorf("reading /etc/resolv.conf: %w", err) @@ -23,16 +24,16 @@ func NewOSConfigurator(logf logger.Logf, _ string) (OSConfigurator, error) { case "resolvconf": switch resolvconfStyle() { case "": - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil case "debian": return newDebianResolvconfManager(logf) case "openresolv": return newOpenresolvManager(logf) default: logf("[unexpected] got unknown flavor of resolvconf %q, falling back to direct manager", resolvconfStyle()) - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil } default: - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil } } diff --git a/net/dns/manager_linux.go b/net/dns/manager_linux.go index 17162153c..7ce0494ee 100644 --- a/net/dns/manager_linux.go +++ b/net/dns/manager_linux.go @@ -31,7 +31,7 @@ func (kv kv) String() string { var publishOnce sync.Once -func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurator, err error) { +func NewOSConfigurator(logf logger.Logf, health *health.Tracker, interfaceName string) (ret OSConfigurator, err error) { env := newOSConfigEnv{ fs: directFS{}, dbusPing: dbusPing, @@ -40,7 +40,7 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurat nmVersionBetween: nmVersionBetween, resolvconfStyle: resolvconfStyle, } - mode, err := dnsMode(logf, env) + mode, err := dnsMode(logf, health, env) if err != nil { return nil, err } @@ -52,9 +52,9 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurat logf("dns: using %q mode", mode) switch mode { case "direct": - return newDirectManagerOnFS(logf, env.fs), nil + return newDirectManagerOnFS(logf, health, env.fs), nil case "systemd-resolved": - return newResolvedManager(logf, interfaceName) + return newResolvedManager(logf, health, interfaceName) case "network-manager": return newNMManager(interfaceName) case "debian-resolvconf": @@ -63,7 +63,7 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurat return newOpenresolvManager(logf) default: logf("[unexpected] detected unknown DNS mode %q, using direct manager as last resort", mode) - return newDirectManagerOnFS(logf, env.fs), nil + return newDirectManagerOnFS(logf, health, env.fs), nil } } @@ -77,7 +77,7 @@ type newOSConfigEnv struct { resolvconfStyle func() string } -func dnsMode(logf logger.Logf, env newOSConfigEnv) (ret string, err error) { +func dnsMode(logf logger.Logf, health *health.Tracker, env newOSConfigEnv) (ret string, err error) { var debug []kv dbg := func(k, v string) { debug = append(debug, kv{k, v}) @@ -271,7 +271,7 @@ func dnsMode(logf logger.Logf, env newOSConfigEnv) (ret string, err error) { return "direct", nil } - health.Global.SetDNSManagerHealth(errors.New("systemd-resolved and NetworkManager are wired together incorrectly; MagicDNS will probably not work. For more info, see https://tailscale.com/s/resolved-nm")) + health.SetDNSManagerHealth(errors.New("systemd-resolved and NetworkManager are wired together incorrectly; MagicDNS will probably not work. For more info, see https://tailscale.com/s/resolved-nm")) dbg("nm-safe", "no") return "systemd-resolved", nil default: diff --git a/net/dns/manager_linux_test.go b/net/dns/manager_linux_test.go index bbaa7ddc1..c60701295 100644 --- a/net/dns/manager_linux_test.go +++ b/net/dns/manager_linux_test.go @@ -286,7 +286,7 @@ func TestLinuxDNSMode(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var logBuf tstest.MemLogger - got, err := dnsMode(logBuf.Logf, tt.env) + got, err := dnsMode(logBuf.Logf, nil, tt.env) if err != nil { t.Fatal(err) } diff --git a/net/dns/manager_openbsd.go b/net/dns/manager_openbsd.go index b4e32b733..c55efa509 100644 --- a/net/dns/manager_openbsd.go +++ b/net/dns/manager_openbsd.go @@ -8,6 +8,7 @@ import ( "fmt" "os" + "tailscale.com/health" "tailscale.com/types/logger" ) @@ -19,8 +20,8 @@ func (kv kv) String() string { return fmt.Sprintf("%s=%s", kv.k, kv.v) } -func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) { - return newOSConfigurator(logf, interfaceName, +func NewOSConfigurator(logf logger.Logf, health *health.Tracker, interfaceName string) (OSConfigurator, error) { + return newOSConfigurator(logf, health, interfaceName, newOSConfigEnv{ rcIsResolvd: rcIsResolvd, fs: directFS{}, @@ -33,7 +34,7 @@ type newOSConfigEnv struct { rcIsResolvd func(resolvConfContents []byte) bool } -func newOSConfigurator(logf logger.Logf, interfaceName string, env newOSConfigEnv) (ret OSConfigurator, err error) { +func newOSConfigurator(logf logger.Logf, health *health.Tracker, interfaceName string, env newOSConfigEnv) (ret OSConfigurator, err error) { var debug []kv dbg := func(k, v string) { debug = append(debug, kv{k, v}) @@ -48,7 +49,7 @@ func newOSConfigurator(logf logger.Logf, interfaceName string, env newOSConfigEn bs, err := env.fs.ReadFile(resolvConf) if os.IsNotExist(err) { dbg("rc", "missing") - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil } if err != nil { return nil, fmt.Errorf("reading /etc/resolv.conf: %w", err) @@ -60,7 +61,7 @@ func newOSConfigurator(logf logger.Logf, interfaceName string, env newOSConfigEn } dbg("resolvd", "missing") - return newDirectManager(logf), nil + return newDirectManager(logf, health), nil } func rcIsResolvd(resolvConfContents []byte) bool { diff --git a/net/dns/manager_tcp_test.go b/net/dns/manager_tcp_test.go index 4883a3b6f..77fab0179 100644 --- a/net/dns/manager_tcp_test.go +++ b/net/dns/manager_tcp_test.go @@ -87,7 +87,7 @@ func TestDNSOverTCP(t *testing.T) { SearchDomains: fqdns("coffee.shop"), }, } - m := NewManager(t.Logf, &f, nil, new(tsdial.Dialer), nil, nil) + m := NewManager(t.Logf, &f, nil, nil, new(tsdial.Dialer), nil, nil) m.resolver.TestOnlySetHook(f.SetResolver) m.Set(Config{ Hosts: hosts( @@ -172,7 +172,7 @@ func TestDNSOverTCP_TooLarge(t *testing.T) { SearchDomains: fqdns("coffee.shop"), }, } - m := NewManager(log, &f, nil, new(tsdial.Dialer), nil, nil) + m := NewManager(log, &f, nil, nil, new(tsdial.Dialer), nil, nil) m.resolver.TestOnlySetHook(f.SetResolver) m.Set(Config{ Hosts: hosts("andrew.ts.com.", "1.2.3.4"), diff --git a/net/dns/manager_test.go b/net/dns/manager_test.go index 65b86bab4..46a1e288c 100644 --- a/net/dns/manager_test.go +++ b/net/dns/manager_test.go @@ -613,7 +613,7 @@ func TestManager(t *testing.T) { SplitDNS: test.split, BaseConfig: test.bs, } - m := NewManager(t.Logf, &f, nil, new(tsdial.Dialer), nil, nil) + m := NewManager(t.Logf, &f, nil, nil, new(tsdial.Dialer), nil, nil) m.resolver.TestOnlySetHook(f.SetResolver) if err := m.Set(test.in); err != nil { diff --git a/net/dns/manager_windows.go b/net/dns/manager_windows.go index e46d0562c..ad358dc26 100644 --- a/net/dns/manager_windows.go +++ b/net/dns/manager_windows.go @@ -23,6 +23,7 @@ import ( "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "tailscale.com/atomicfile" "tailscale.com/envknob" + "tailscale.com/health" "tailscale.com/types/logger" "tailscale.com/util/dnsname" "tailscale.com/util/winutil" @@ -44,11 +45,11 @@ type windowsManager struct { closing bool } -func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) { +func NewOSConfigurator(logf logger.Logf, health *health.Tracker, interfaceName string) (OSConfigurator, error) { ret := &windowsManager{ logf: logf, guid: interfaceName, - wslManager: newWSLManager(logf), + wslManager: newWSLManager(logf, health), } if isWindows10OrBetter() { diff --git a/net/dns/manager_windows_test.go b/net/dns/manager_windows_test.go index 167eae2b6..917738ec0 100644 --- a/net/dns/manager_windows_test.go +++ b/net/dns/manager_windows_test.go @@ -84,7 +84,7 @@ func TestManagerWindowsGPCopy(t *testing.T) { } defer delIfKey() - cfg, err := NewOSConfigurator(logf, fakeInterface.String()) + cfg, err := NewOSConfigurator(logf, nil, fakeInterface.String()) if err != nil { t.Fatalf("NewOSConfigurator: %v\n", err) } @@ -213,7 +213,7 @@ func runTest(t *testing.T, isLocal bool) { } defer delIfKey() - cfg, err := NewOSConfigurator(logf, fakeInterface.String()) + cfg, err := NewOSConfigurator(logf, nil, fakeInterface.String()) if err != nil { t.Fatalf("NewOSConfigurator: %v\n", err) } diff --git a/net/dns/resolved.go b/net/dns/resolved.go index 47469c125..d82d3fc31 100644 --- a/net/dns/resolved.go +++ b/net/dns/resolved.go @@ -63,13 +63,14 @@ type resolvedManager struct { ctx context.Context cancel func() // terminate the context, for close - logf logger.Logf - ifidx int + logf logger.Logf + health *health.Tracker + ifidx int configCR chan changeRequest // tracks OSConfigs changes and error responses } -func newResolvedManager(logf logger.Logf, interfaceName string) (*resolvedManager, error) { +func newResolvedManager(logf logger.Logf, health *health.Tracker, interfaceName string) (*resolvedManager, error) { iface, err := net.InterfaceByName(interfaceName) if err != nil { return nil, err @@ -82,8 +83,9 @@ func newResolvedManager(logf logger.Logf, interfaceName string) (*resolvedManage ctx: ctx, cancel: cancel, - logf: logf, - ifidx: iface.Index, + logf: logf, + health: health, + ifidx: iface.Index, configCR: make(chan changeRequest), } @@ -163,7 +165,7 @@ func (m *resolvedManager) run(ctx context.Context) { // Reset backoff and SetNSOSHealth after successful on reconnect. bo.BackOff(ctx, nil) - health.Global.SetDNSOSHealth(nil) + m.health.SetDNSOSHealth(nil) return nil } @@ -241,7 +243,7 @@ func (m *resolvedManager) run(ctx context.Context) { // Set health while holding the lock, because this will // graciously serialize the resync's health outcome with a // concurrent SetDNS call. - health.Global.SetDNSOSHealth(err) + m.health.SetDNSOSHealth(err) if err != nil { m.logf("failed to configure systemd-resolved: %v", err) } diff --git a/net/dns/wsl_windows.go b/net/dns/wsl_windows.go index 90632ce5f..e4b25cca8 100644 --- a/net/dns/wsl_windows.go +++ b/net/dns/wsl_windows.go @@ -16,6 +16,7 @@ import ( "time" "golang.org/x/sys/windows" + "tailscale.com/health" "tailscale.com/types/logger" "tailscale.com/util/winutil" ) @@ -54,12 +55,14 @@ func wslDistros() ([]string, error) { // wslManager is a DNS manager for WSL2 linux distributions. // It configures /etc/wsl.conf and /etc/resolv.conf. type wslManager struct { - logf logger.Logf + logf logger.Logf + health *health.Tracker } -func newWSLManager(logf logger.Logf) *wslManager { +func newWSLManager(logf logger.Logf, health *health.Tracker) *wslManager { m := &wslManager{ - logf: logf, + logf: logf, + health: health, } return m } @@ -73,7 +76,7 @@ func (wm *wslManager) SetDNS(cfg OSConfig) error { } managers := make(map[string]*directManager) for _, distro := range distros { - managers[distro] = newDirectManagerOnFS(wm.logf, wslFS{ + managers[distro] = newDirectManagerOnFS(wm.logf, wm.health, wslFS{ user: "root", distro: distro, }) diff --git a/tsd/tsd.go b/tsd/tsd.go index d9e8a5e94..2b5e65626 100644 --- a/tsd/tsd.go +++ b/tsd/tsd.go @@ -139,14 +139,6 @@ func (s *System) ProxyMapper() *proxymap.Mapper { // HealthTracker returns the system health tracker. func (s *System) HealthTracker() *health.Tracker { - // TODO(bradfitz): plumb the tsd.System.HealthTracker() value - // everywhere and then then remove this use of the global - // and remove health.Global entirely. But for now we keep - // the two in sync during plumbing. - const stillPlumbing = true - if stillPlumbing { - return health.Global - } return &s.healthTracker } diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 1dd60eef9..c665282ff 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -31,6 +31,7 @@ import ( "tailscale.com/client/tailscale" "tailscale.com/control/controlclient" "tailscale.com/envknob" + "tailscale.com/health" "tailscale.com/hostinfo" "tailscale.com/ipn" "tailscale.com/ipn/ipnlocal" @@ -504,7 +505,8 @@ func (s *Server) start() (reterr error) { return fmt.Errorf("%v is not a directory", s.rootPath) } - if err := s.startLogger(&closePool); err != nil { + sys := new(tsd.System) + if err := s.startLogger(&closePool, sys.HealthTracker()); err != nil { return err } @@ -514,7 +516,6 @@ func (s *Server) start() (reterr error) { } closePool.add(s.netMon) - sys := new(tsd.System) s.dialer = &tsdial.Dialer{Logf: logf} // mutated below (before used) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{ ListenPort: s.Port, @@ -627,7 +628,7 @@ func (s *Server) start() (reterr error) { return nil } -func (s *Server) startLogger(closePool *closeOnErrorPool) error { +func (s *Server) startLogger(closePool *closeOnErrorPool, health *health.Tracker) error { if testenv.InTest() { return nil } @@ -658,7 +659,7 @@ func (s *Server) startLogger(closePool *closeOnErrorPool) error { Stderr: io.Discard, // log everything to Buffer Buffer: s.logbuffer, CompressLogs: true, - HTTPC: &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, s.netMon, s.logf)}, + HTTPC: &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, s.netMon, health, s.logf)}, MetricsDelta: clientmetric.EncodeLogTailMetricsDelta, } s.logtail = logtail.NewLogger(c, s.logf) diff --git a/wgengine/netlog/logger.go b/wgengine/netlog/logger.go index 5eaa52375..4614caf24 100644 --- a/wgengine/netlog/logger.go +++ b/wgengine/netlog/logger.go @@ -16,6 +16,7 @@ import ( "sync" "time" + "tailscale.com/health" "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/net/connstats" @@ -92,7 +93,7 @@ var testClient *http.Client // The IP protocol and source port are always zero. // The sock is used to populated the PhysicalTraffic field in Message. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups. -func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID logid.PrivateID, tun, sock Device, netMon *netmon.Monitor) error { +func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID logid.PrivateID, tun, sock Device, netMon *netmon.Monitor, health *health.Tracker) error { nl.mu.Lock() defer nl.mu.Unlock() if nl.logger != nil { @@ -101,7 +102,7 @@ func (nl *Logger) Startup(nodeID tailcfg.StableNodeID, nodeLogID, domainLogID lo // Startup a log stream to Tailscale's logging service. logf := log.Printf - httpc := &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon, logf)} + httpc := &http.Client{Transport: logpolicy.NewLogtailTransport(logtail.DefaultHost, netMon, health, logf)} if testClient != nil { httpc = testClient } diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index 3e5c37a45..7901ba211 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -237,7 +237,7 @@ func interfaceFromLUID(luid winipcfg.LUID, flags winipcfg.GAAFlags) (*winipcfg.I var networkCategoryWarning = health.NewWarnable(health.WithMapDebugFlag("warn-network-category-unhealthy")) -func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { +func configureInterface(cfg *Config, tun *tun.NativeTun, health *health.Tracker) (retErr error) { var mtu = tstun.DefaultTUNMTU() luid := winipcfg.LUID(tun.LUID()) iface, err := interfaceFromLUID(luid, @@ -268,10 +268,10 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { for i := range tries { found, err := setPrivateNetwork(luid) if err != nil { - health.Global.SetWarnable(networkCategoryWarning, fmt.Errorf("set-network-category: %w", err)) + health.SetWarnable(networkCategoryWarning, fmt.Errorf("set-network-category: %w", err)) log.Printf("setPrivateNetwork(try=%d): %v", i, err) } else { - health.Global.SetWarnable(networkCategoryWarning, nil) + health.SetWarnable(networkCategoryWarning, nil) if found { if i > 0 { log.Printf("setPrivateNetwork(try=%d): success", i) diff --git a/wgengine/router/router.go b/wgengine/router/router.go index 485d058f3..9a81771a1 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -10,6 +10,7 @@ import ( "reflect" "github.com/tailscale/wireguard-go/tun" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/types/preftype" @@ -44,9 +45,9 @@ type Router interface { // // If netMon is nil, it's not used. It's currently (2021-07-20) only // used on Linux in some situations. -func New(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { +func New(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { logf = logger.WithPrefix(logf, "router: ") - return newUserspaceRouter(logf, tundev, netMon) + return newUserspaceRouter(logf, tundev, netMon, health) } // CleanUp restores the system network configuration to its original state diff --git a/wgengine/router/router_darwin.go b/wgengine/router/router_darwin.go index 9c3cdac29..73e394b04 100644 --- a/wgengine/router/router_darwin.go +++ b/wgengine/router/router_darwin.go @@ -5,12 +5,13 @@ package router import ( "github.com/tailscale/wireguard-go/tun" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" ) -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { - return newUserspaceBSDRouter(logf, tundev, netMon) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, netMon, health) } func cleanUp(logger.Logf, string) { diff --git a/wgengine/router/router_default.go b/wgengine/router/router_default.go index 61f6eddae..1e675d1fc 100644 --- a/wgengine/router/router_default.go +++ b/wgengine/router/router_default.go @@ -10,11 +10,12 @@ import ( "runtime" "github.com/tailscale/wireguard-go/tun" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" ) -func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { return nil, fmt.Errorf("unsupported OS %q", runtime.GOOS) } diff --git a/wgengine/router/router_freebsd.go b/wgengine/router/router_freebsd.go index 41fcd2606..40523b4fd 100644 --- a/wgengine/router/router_freebsd.go +++ b/wgengine/router/router_freebsd.go @@ -5,6 +5,7 @@ package router import ( "github.com/tailscale/wireguard-go/tun" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" ) @@ -14,8 +15,8 @@ import ( // Work is currently underway for an in-kernel FreeBSD implementation of wireguard // https://svnweb.freebsd.org/base?view=revision&revision=357986 -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { - return newUserspaceBSDRouter(logf, tundev, netMon) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, netMon, health) } func cleanUp(logf logger.Logf, interfaceName string) { diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 8b25243a5..4b1a0ae5f 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -22,6 +22,7 @@ import ( "golang.org/x/sys/unix" "golang.org/x/time/rate" "tailscale.com/envknob" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/types/preftype" @@ -69,7 +70,7 @@ type linuxRouter struct { magicsockPortV6 uint16 } -func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { tunname, err := tunDev.Name() if err != nil { return nil, err diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index db985d841..cf8e7f517 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -886,7 +886,7 @@ func newLinuxRootTest(t *testing.T) *linuxTest { mon.Start() lt.mon = mon - r, err := newUserspaceRouter(logf, lt.tun, mon) + r, err := newUserspaceRouter(logf, lt.tun, mon, nil) if err != nil { lt.Close() t.Fatal(err) diff --git a/wgengine/router/router_openbsd.go b/wgengine/router/router_openbsd.go index 7c0316cf1..6fdd47ac9 100644 --- a/wgengine/router/router_openbsd.go +++ b/wgengine/router/router_openbsd.go @@ -12,6 +12,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "go4.org/netipx" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/types/logger" "tailscale.com/util/set" @@ -30,7 +31,7 @@ type openbsdRouter struct { routes set.Set[netip.Prefix] } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err diff --git a/wgengine/router/router_userspace_bsd.go b/wgengine/router/router_userspace_bsd.go index 87d47115e..0b7e4f36a 100644 --- a/wgengine/router/router_userspace_bsd.go +++ b/wgengine/router/router_userspace_bsd.go @@ -14,6 +14,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "go4.org/netipx" + "tailscale.com/health" "tailscale.com/net/netmon" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" @@ -23,12 +24,13 @@ import ( type userspaceBSDRouter struct { logf logger.Logf netMon *netmon.Monitor + health *health.Tracker tunname string local []netip.Prefix routes map[netip.Prefix]bool } -func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { +func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err @@ -37,6 +39,7 @@ func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.M return &userspaceBSDRouter{ logf: logf, netMon: netMon, + health: health, tunname: tunname, }, nil } diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index 152661335..711de03da 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -22,6 +22,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" + "tailscale.com/health" "tailscale.com/logtail/backoff" "tailscale.com/net/dns" "tailscale.com/net/netmon" @@ -31,12 +32,13 @@ import ( type winRouter struct { logf func(fmt string, args ...any) netMon *netmon.Monitor // may be nil + health *health.Tracker nativeTun *tun.NativeTun routeChangeCallback *winipcfg.RouteChangeCallback firewall *firewallTweaker } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Monitor, health *health.Tracker) (Router, error) { nativeTun := tundev.(*tun.NativeTun) luid := winipcfg.LUID(nativeTun.LUID()) guid, err := luid.GUID() @@ -47,6 +49,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device, netMon *netmon.Moni return &winRouter{ logf: logf, netMon: netMon, + health: health, nativeTun: nativeTun, firewall: &firewallTweaker{ logf: logger.WithPrefix(logf, "firewall: "), @@ -80,7 +83,7 @@ func (r *winRouter) Set(cfg *Config) error { } r.firewall.set(localAddrs, cfg.Routes, cfg.LocalRoutes) - err := configureInterface(cfg, r.nativeTun) + err := configureInterface(cfg, r.nativeTun, r.health) if err != nil { r.logf("ConfigureInterface: %v", err) return err diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 7bc7341f8..34eec9c16 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -341,7 +341,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) tunName, _ := conf.Tun.Name() conf.Dialer.SetTUNName(tunName) conf.Dialer.SetNetMon(e.netMon) - e.dns = dns.NewManager(logf, conf.DNS, e.netMon, conf.Dialer, fwdDNSLinkSelector{e, tunName}, conf.ControlKnobs) + e.dns = dns.NewManager(logf, conf.DNS, e.netMon, e.health, conf.Dialer, fwdDNSLinkSelector{e, tunName}, conf.ControlKnobs) // TODO: there's probably a better place for this sockstats.SetNetMon(e.netMon) @@ -966,7 +966,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, nid := cfg.NetworkLogging.NodeID tid := cfg.NetworkLogging.DomainID e.logf("wgengine: Reconfig: starting up network logger (node:%s tailnet:%s)", nid.Public(), tid.Public()) - if err := e.networkLogger.Startup(cfg.NodeID, nid, tid, e.tundev, e.magicConn, e.netMon); err != nil { + if err := e.networkLogger.Startup(cfg.NodeID, nid, tid, e.tundev, e.magicConn, e.netMon, e.health); err != nil { e.logf("wgengine: Reconfig: error starting up network logger: %v", err) } e.networkLogger.ReconfigRoutes(routerCfg)