diff --git a/cmd/k8s-operator/depaware.txt b/cmd/k8s-operator/depaware.txt index ea0e08b19..2adbd5f5d 100644 --- a/cmd/k8s-operator/depaware.txt +++ b/cmd/k8s-operator/depaware.txt @@ -185,7 +185,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/ LD github.com/prometheus/procfs from github.com/prometheus/client_golang/prometheus LD github.com/prometheus/procfs/internal/fs from github.com/prometheus/procfs LD github.com/prometheus/procfs/internal/util from github.com/prometheus/procfs - L 💣 github.com/safchain/ethtool from tailscale.com/doctor/ethtool+ + L 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf github.com/spf13/pflag from k8s.io/client-go/tools/clientcmd W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient W 💣 github.com/tailscale/go-winio from tailscale.com/safesocket @@ -200,7 +200,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/ github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+ github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tailscale/hujson from tailscale.com/ipn/conffile+ - L 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+ + L 💣 github.com/tailscale/netlink from tailscale.com/util/linuxfw+ L 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink github.com/tailscale/peercred from tailscale.com/ipn/ipnauth github.com/tailscale/web-client-prebuilt from tailscale.com/client/web @@ -787,10 +787,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/ tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+ tailscale.com/derp/derphttp from tailscale.com/ipn/localapi+ tailscale.com/disco from tailscale.com/net/tstun+ - tailscale.com/doctor from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/ethtool from tailscale.com/ipn/ipnlocal - 💣 tailscale.com/doctor/permissions from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal tailscale.com/drive from tailscale.com/client/local+ tailscale.com/envknob from tailscale.com/client/local+ tailscale.com/envknob/featureknob from tailscale.com/client/web+ @@ -868,7 +864,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/ tailscale.com/net/portmapper from tailscale.com/feature/portmapper tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+ tailscale.com/net/proxymux from tailscale.com/tsnet - tailscale.com/net/routetable from tailscale.com/doctor/routetable 💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock tailscale.com/net/socks5 from tailscale.com/tsnet tailscale.com/net/sockstats from tailscale.com/control/controlclient+ diff --git a/cmd/tailscaled/depaware-minbox.txt b/cmd/tailscaled/depaware-minbox.txt index 144871c9b..08d7d59c6 100644 --- a/cmd/tailscaled/depaware-minbox.txt +++ b/cmd/tailscaled/depaware-minbox.txt @@ -37,9 +37,9 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de github.com/mdlayher/sdnotify from tailscale.com/util/systemd 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+ github.com/mitchellh/go-ps from tailscale.com/safesocket - 💣 github.com/safchain/ethtool from tailscale.com/doctor/ethtool+ + 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf github.com/tailscale/hujson from tailscale.com/ipn/conffile - 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+ + 💣 github.com/tailscale/netlink from tailscale.com/util/linuxfw+ 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink github.com/tailscale/peercred from tailscale.com/ipn/ipnauth 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ @@ -69,10 +69,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+ tailscale.com/derp/derphttp from tailscale.com/cmd/tailscaled+ tailscale.com/disco from tailscale.com/net/tstun+ - tailscale.com/doctor from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/ethtool from tailscale.com/ipn/ipnlocal - 💣 tailscale.com/doctor/permissions from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal tailscale.com/drive from tailscale.com/ipn+ tailscale.com/envknob from tailscale.com/cmd/tailscaled+ tailscale.com/envknob/featureknob from tailscale.com/ipn/ipnlocal @@ -127,7 +123,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/packet/checksum from tailscale.com/net/tstun tailscale.com/net/ping from tailscale.com/net/netcheck+ tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+ - tailscale.com/net/routetable from tailscale.com/doctor/routetable tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock tailscale.com/net/sockstats from tailscale.com/control/controlclient+ tailscale.com/net/stun from tailscale.com/ipn/localapi+ @@ -242,7 +237,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box golang.org/x/crypto/poly1305 from github.com/tailscale/wireguard-go/device golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+ - golang.org/x/exp/constraints from tailscale.com/doctor/permissions+ + golang.org/x/exp/constraints from tailscale.com/tsweb/varz+ golang.org/x/exp/maps from tailscale.com/ipn/store/mem golang.org/x/net/bpf from github.com/mdlayher/genetlink+ golang.org/x/net/dns/dnsmessage from net+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index acd8e0459..579af5c0d 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -259,10 +259,10 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+ tailscale.com/derp/derphttp from tailscale.com/cmd/tailscaled+ tailscale.com/disco from tailscale.com/feature/relayserver+ - tailscale.com/doctor from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/ethtool from tailscale.com/ipn/ipnlocal - 💣 tailscale.com/doctor/permissions from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal + tailscale.com/doctor from tailscale.com/feature/doctor + tailscale.com/doctor/ethtool from tailscale.com/feature/doctor + 💣 tailscale.com/doctor/permissions from tailscale.com/feature/doctor + tailscale.com/doctor/routetable from tailscale.com/feature/doctor tailscale.com/drive from tailscale.com/client/local+ tailscale.com/drive/driveimpl from tailscale.com/cmd/tailscaled tailscale.com/drive/driveimpl/compositedav from tailscale.com/drive/driveimpl @@ -276,6 +276,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/feature/condregister from tailscale.com/cmd/tailscaled tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister tailscale.com/feature/debugportmapper from tailscale.com/feature/condregister + tailscale.com/feature/doctor from tailscale.com/feature/condregister tailscale.com/feature/drive from tailscale.com/feature/condregister L tailscale.com/feature/linuxdnsfight from tailscale.com/feature/condregister tailscale.com/feature/portlist from tailscale.com/feature/condregister diff --git a/cmd/tsidp/depaware.txt b/cmd/tsidp/depaware.txt index 69904c976..270edd371 100644 --- a/cmd/tsidp/depaware.txt +++ b/cmd/tsidp/depaware.txt @@ -132,7 +132,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar L 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+ 💣 github.com/mitchellh/go-ps from tailscale.com/safesocket D github.com/prometheus-community/pro-bing from tailscale.com/wgengine/netstack - L 💣 github.com/safchain/ethtool from tailscale.com/doctor/ethtool+ + L 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient W 💣 github.com/tailscale/go-winio from tailscale.com/safesocket W 💣 github.com/tailscale/go-winio/internal/fs from github.com/tailscale/go-winio @@ -146,7 +146,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+ github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tailscale/hujson from tailscale.com/ipn/conffile - L 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+ + L 💣 github.com/tailscale/netlink from tailscale.com/util/linuxfw+ L 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink github.com/tailscale/peercred from tailscale.com/ipn/ipnauth github.com/tailscale/web-client-prebuilt from tailscale.com/client/web @@ -229,10 +229,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+ tailscale.com/derp/derphttp from tailscale.com/ipn/localapi+ tailscale.com/disco from tailscale.com/net/tstun+ - tailscale.com/doctor from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/ethtool from tailscale.com/ipn/ipnlocal - 💣 tailscale.com/doctor/permissions from tailscale.com/ipn/ipnlocal - tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal tailscale.com/drive from tailscale.com/client/local+ tailscale.com/envknob from tailscale.com/client/local+ tailscale.com/envknob/featureknob from tailscale.com/client/web+ @@ -299,7 +295,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar tailscale.com/net/portmapper from tailscale.com/feature/portmapper tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+ tailscale.com/net/proxymux from tailscale.com/tsnet - tailscale.com/net/routetable from tailscale.com/doctor/routetable 💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock tailscale.com/net/socks5 from tailscale.com/tsnet tailscale.com/net/sockstats from tailscale.com/control/controlclient+ diff --git a/feature/buildfeatures/feature_doctor_disabled.go b/feature/buildfeatures/feature_doctor_disabled.go new file mode 100644 index 000000000..8c15e951e --- /dev/null +++ b/feature/buildfeatures/feature_doctor_disabled.go @@ -0,0 +1,13 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// Code generated by gen.go; DO NOT EDIT. + +//go:build ts_omit_doctor + +package buildfeatures + +// HasDoctor is whether the binary was built with support for modular feature "Diagnose possible issues with Tailscale and its host environment". +// Specifically, it's whether the binary was NOT built with the "ts_omit_doctor" build tag. +// It's a const so it can be used for dead code elimination. +const HasDoctor = false diff --git a/feature/buildfeatures/feature_doctor_enabled.go b/feature/buildfeatures/feature_doctor_enabled.go new file mode 100644 index 000000000..a8a0bb7d2 --- /dev/null +++ b/feature/buildfeatures/feature_doctor_enabled.go @@ -0,0 +1,13 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// Code generated by gen.go; DO NOT EDIT. + +//go:build !ts_omit_doctor + +package buildfeatures + +// HasDoctor is whether the binary was built with support for modular feature "Diagnose possible issues with Tailscale and its host environment". +// Specifically, it's whether the binary was NOT built with the "ts_omit_doctor" build tag. +// It's a const so it can be used for dead code elimination. +const HasDoctor = true diff --git a/feature/condregister/maybe_doctor.go b/feature/condregister/maybe_doctor.go new file mode 100644 index 000000000..3dc9ffa53 --- /dev/null +++ b/feature/condregister/maybe_doctor.go @@ -0,0 +1,8 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !ts_omit_doctor + +package condregister + +import _ "tailscale.com/feature/doctor" diff --git a/feature/doctor/doctor.go b/feature/doctor/doctor.go new file mode 100644 index 000000000..875b57d14 --- /dev/null +++ b/feature/doctor/doctor.go @@ -0,0 +1,95 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +// The doctor package registers the "doctor" problem diagnosis support into the +// rest of Tailscale. +package doctor + +import ( + "context" + "fmt" + "html" + "net/http" + "time" + + "tailscale.com/doctor" + "tailscale.com/doctor/ethtool" + "tailscale.com/doctor/permissions" + "tailscale.com/doctor/routetable" + "tailscale.com/ipn/ipnlocal" + "tailscale.com/net/tsaddr" + "tailscale.com/types/logger" +) + +func init() { + ipnlocal.HookDoctor.Set(visitDoctor) + ipnlocal.RegisterPeerAPIHandler("/v0/doctor", handleServeDoctor) +} + +func handleServeDoctor(h ipnlocal.PeerAPIHandler, w http.ResponseWriter, r *http.Request) { + if !h.CanDebug() { + http.Error(w, "denied; no debug access", http.StatusForbidden) + return + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + fmt.Fprintln(w, "
")
+
+ b := h.LocalBackend()
+ visitDoctor(r.Context(), b, func(format string, args ...any) {
+ line := fmt.Sprintf(format, args...)
+ fmt.Fprintln(w, html.EscapeString(line))
+ })
+
+ fmt.Fprintln(w, "")
+}
+
+func visitDoctor(ctx context.Context, b *ipnlocal.LocalBackend, logf logger.Logf) {
+ // We can write logs too fast for logtail to handle, even when
+ // opting-out of rate limits. Limit ourselves to at most one message
+ // per 20ms and a burst of 60 log lines, which should be fast enough to
+ // not block for too long but slow enough that we can upload all lines.
+ logf = logger.SlowLoggerWithClock(ctx, logf, 20*time.Millisecond, 60, b.Clock().Now)
+
+ var checks []doctor.Check
+ checks = append(checks,
+ permissions.Check{},
+ routetable.Check{},
+ ethtool.Check{},
+ )
+
+ // Print a log message if any of the global DNS resolvers are Tailscale
+ // IPs; this can interfere with our ability to connect to the Tailscale
+ // controlplane.
+ checks = append(checks, doctor.CheckFunc("dns-resolvers", func(_ context.Context, logf logger.Logf) error {
+ nm := b.NetMap()
+ if nm == nil {
+ return nil
+ }
+
+ for i, resolver := range nm.DNS.Resolvers {
+ ipp, ok := resolver.IPPort()
+ if ok && tsaddr.IsTailscaleIP(ipp.Addr()) {
+ logf("resolver %d is a Tailscale address: %v", i, resolver)
+ }
+ }
+ for i, resolver := range nm.DNS.FallbackResolvers {
+ ipp, ok := resolver.IPPort()
+ if ok && tsaddr.IsTailscaleIP(ipp.Addr()) {
+ logf("fallback resolver %d is a Tailscale address: %v", i, resolver)
+ }
+ }
+ return nil
+ }))
+
+ // TODO(andrew): more
+
+ numChecks := len(checks)
+ checks = append(checks, doctor.CheckFunc("numchecks", func(_ context.Context, log logger.Logf) error {
+ log("%d checks", numChecks)
+ return nil
+ }))
+
+ doctor.RunChecks(ctx, logf, checks...)
+}
diff --git a/feature/featuretags/featuretags.go b/feature/featuretags/featuretags.go
index 25426c973..2edecef58 100644
--- a/feature/featuretags/featuretags.go
+++ b/feature/featuretags/featuretags.go
@@ -105,6 +105,7 @@ var Features = map[FeatureTag]FeatureMeta{
Deps: []FeatureTag{"portmapper"},
},
"desktop_sessions": {"DesktopSessions", "Desktop sessions support", nil},
+ "doctor": {"Doctor", "Diagnose possible issues with Tailscale and its host environment", nil},
"drive": {"Drive", "Tailscale Drive (file server) support", nil},
"gro": {
Sym: "GRO",
diff --git a/feature/taildrop/peerapi_test.go b/feature/taildrop/peerapi_test.go
index 633997354..254d8794e 100644
--- a/feature/taildrop/peerapi_test.go
+++ b/feature/taildrop/peerapi_test.go
@@ -33,11 +33,13 @@ type peerAPIHandler struct {
isSelf bool // whether peerNode is owned by same user as this node
selfNode tailcfg.NodeView // this node; always non-nil
peerNode tailcfg.NodeView // peerNode is who's making the request
+ canDebug bool // whether peerNode can debug this node (goroutines, metrics, magicsock internal state, etc)
}
func (h *peerAPIHandler) IsSelfUntagged() bool {
return !h.selfNode.IsTagged() && !h.peerNode.IsTagged() && h.isSelf
}
+func (h *peerAPIHandler) CanDebug() bool { return h.canDebug }
func (h *peerAPIHandler) Peer() tailcfg.NodeView { return h.peerNode }
func (h *peerAPIHandler) Self() tailcfg.NodeView { return h.selfNode }
func (h *peerAPIHandler) RemoteAddr() netip.AddrPort { return h.remoteAddr }
diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go
index 4b8032e9c..dd0a2f9f1 100644
--- a/ipn/ipnlocal/local.go
+++ b/ipn/ipnlocal/local.go
@@ -43,10 +43,6 @@ import (
"tailscale.com/clientupdate"
"tailscale.com/control/controlclient"
"tailscale.com/control/controlknobs"
- "tailscale.com/doctor"
- "tailscale.com/doctor/ethtool"
- "tailscale.com/doctor/permissions"
- "tailscale.com/doctor/routetable"
"tailscale.com/drive"
"tailscale.com/envknob"
"tailscale.com/envknob/featureknob"
@@ -6706,56 +6702,8 @@ func (b *LocalBackend) handleQuad100Port80Conn(w http.ResponseWriter, r *http.Re
io.WriteString(w, "\n")
}
-func (b *LocalBackend) Doctor(ctx context.Context, logf logger.Logf) {
- // We can write logs too fast for logtail to handle, even when
- // opting-out of rate limits. Limit ourselves to at most one message
- // per 20ms and a burst of 60 log lines, which should be fast enough to
- // not block for too long but slow enough that we can upload all lines.
- logf = logger.SlowLoggerWithClock(ctx, logf, 20*time.Millisecond, 60, b.clock.Now)
-
- var checks []doctor.Check
- checks = append(checks,
- permissions.Check{},
- routetable.Check{},
- ethtool.Check{},
- )
-
- // Print a log message if any of the global DNS resolvers are Tailscale
- // IPs; this can interfere with our ability to connect to the Tailscale
- // controlplane.
- checks = append(checks, doctor.CheckFunc("dns-resolvers", func(_ context.Context, logf logger.Logf) error {
- b.mu.Lock()
- nm := b.NetMap()
- b.mu.Unlock()
- if nm == nil {
- return nil
- }
-
- for i, resolver := range nm.DNS.Resolvers {
- ipp, ok := resolver.IPPort()
- if ok && tsaddr.IsTailscaleIP(ipp.Addr()) {
- logf("resolver %d is a Tailscale address: %v", i, resolver)
- }
- }
- for i, resolver := range nm.DNS.FallbackResolvers {
- ipp, ok := resolver.IPPort()
- if ok && tsaddr.IsTailscaleIP(ipp.Addr()) {
- logf("fallback resolver %d is a Tailscale address: %v", i, resolver)
- }
- }
- return nil
- }))
-
- // TODO(andrew): more
-
- numChecks := len(checks)
- checks = append(checks, doctor.CheckFunc("numchecks", func(_ context.Context, log logger.Logf) error {
- log("%d checks", numChecks)
- return nil
- }))
-
- doctor.RunChecks(ctx, logf, checks...)
-}
+// HookDoctor is an optional hook for the "doctor" problem diagnosis feature.
+var HookDoctor feature.Hook[func(context.Context, *LocalBackend, logger.Logf)]
// SetDevStateStore updates the LocalBackend's state storage to the provided values.
//
diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go
index 886a71291..9d2b49a38 100644
--- a/ipn/ipnlocal/peerapi.go
+++ b/ipn/ipnlocal/peerapi.go
@@ -217,6 +217,7 @@ type peerAPIHandler struct {
type PeerAPIHandler interface {
Peer() tailcfg.NodeView
PeerCaps() tailcfg.PeerCapMap
+ CanDebug() bool // can remote node can debug this node (internal state, etc)
Self() tailcfg.NodeView
LocalBackend() *LocalBackend
IsSelfUntagged() bool // whether the peer is untagged and the same as this user
@@ -380,9 +381,6 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case "/v0/interfaces":
h.handleServeInterfaces(w, r)
return
- case "/v0/doctor":
- h.handleServeDoctor(w, r)
- return
case "/v0/sockstats":
h.handleServeSockStats(w, r)
return
@@ -455,24 +453,6 @@ func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Re
fmt.Fprintln(w, "")
}
-func (h *peerAPIHandler) handleServeDoctor(w http.ResponseWriter, r *http.Request) {
- if !h.canDebug() {
- http.Error(w, "denied; no debug access", http.StatusForbidden)
- return
- }
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- fmt.Fprintln(w, "")
-
- h.ps.b.Doctor(r.Context(), func(format string, args ...any) {
- line := fmt.Sprintf(format, args...)
- fmt.Fprintln(w, html.EscapeString(line))
- })
-
- fmt.Fprintln(w, "")
-}
-
func (h *peerAPIHandler) handleServeSockStats(w http.ResponseWriter, r *http.Request) {
if !h.canDebug() {
http.Error(w, "denied; no debug access", http.StatusForbidden)
@@ -571,6 +551,8 @@ func (h *peerAPIHandler) handleServeSockStats(w http.ResponseWriter, r *http.Req
fmt.Fprintln(w, "")
}
+func (h *peerAPIHandler) CanDebug() bool { return h.canDebug() }
+
// canDebug reports whether h can debug this node (goroutines, metrics,
// magicsock internal state, etc).
func (h *peerAPIHandler) canDebug() bool {
diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go
index a83a2e17e..e8801e1ba 100644
--- a/ipn/localapi/localapi.go
+++ b/ipn/localapi/localapi.go
@@ -402,7 +402,9 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) {
}
if defBool(r.URL.Query().Get("diagnose"), false) {
- h.b.Doctor(r.Context(), logger.WithPrefix(h.logf, "diag: "))
+ if f, ok := ipnlocal.HookDoctor.GetOk(); ok {
+ f(r.Context(), h.b, logger.WithPrefix(h.logf, "diag: "))
+ }
}
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintln(w, startMarker)
diff --git a/tsnet/depaware.txt b/tsnet/depaware.txt
index ece4345d5..c196cc14d 100644
--- a/tsnet/depaware.txt
+++ b/tsnet/depaware.txt
@@ -132,7 +132,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
LA 💣 github.com/mdlayher/socket from github.com/mdlayher/netlink+
LDW 💣 github.com/mitchellh/go-ps from tailscale.com/safesocket
DI github.com/prometheus-community/pro-bing from tailscale.com/wgengine/netstack
- L 💣 github.com/safchain/ethtool from tailscale.com/doctor/ethtool+
+ L 💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf
W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient
W 💣 github.com/tailscale/go-winio from tailscale.com/safesocket
W 💣 github.com/tailscale/go-winio/internal/fs from github.com/tailscale/go-winio
@@ -146,7 +146,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
LDW github.com/tailscale/hujson from tailscale.com/ipn/conffile
- L 💣 github.com/tailscale/netlink from tailscale.com/net/routetable+
+ L 💣 github.com/tailscale/netlink from tailscale.com/util/linuxfw+
L 💣 github.com/tailscale/netlink/nl from github.com/tailscale/netlink
github.com/tailscale/peercred from tailscale.com/ipn/ipnauth
LDW github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
@@ -225,10 +225,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
tailscale.com/derp/derpconst from tailscale.com/derp/derphttp+
tailscale.com/derp/derphttp from tailscale.com/ipn/localapi+
tailscale.com/disco from tailscale.com/net/tstun+
- tailscale.com/doctor from tailscale.com/ipn/ipnlocal
- tailscale.com/doctor/ethtool from tailscale.com/ipn/ipnlocal
- 💣 tailscale.com/doctor/permissions from tailscale.com/ipn/ipnlocal
- tailscale.com/doctor/routetable from tailscale.com/ipn/ipnlocal
tailscale.com/drive from tailscale.com/client/local+
tailscale.com/envknob from tailscale.com/client/local+
tailscale.com/envknob/featureknob from tailscale.com/client/web+
@@ -295,7 +291,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
tailscale.com/net/portmapper from tailscale.com/feature/portmapper
tailscale.com/net/portmapper/portmappertype from tailscale.com/net/netcheck+
tailscale.com/net/proxymux from tailscale.com/tsnet
- tailscale.com/net/routetable from tailscale.com/doctor/routetable
💣 tailscale.com/net/sockopts from tailscale.com/wgengine/magicsock
tailscale.com/net/socks5 from tailscale.com/tsnet
tailscale.com/net/sockstats from tailscale.com/control/controlclient+