WIP: rebase for 2026-05-18 #7
@@ -607,6 +607,24 @@ func (lc *Client) DebugResultJSON(ctx context.Context, action string) (any, erro
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDebugResultJSON invokes a debug action and decodes the JSON response
|
||||||
|
// into a value of type T. It avoids the marshal/unmarshal roundtrip that
|
||||||
|
// callers of [Client.DebugResultJSON] otherwise need to do to get a typed
|
||||||
|
// value.
|
||||||
|
//
|
||||||
|
// These are development tools and subject to change or removal over time.
|
||||||
|
func GetDebugResultJSON[T any](ctx context.Context, lc *Client, action string) (T, error) {
|
||||||
|
var v T
|
||||||
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug?action="+url.QueryEscape(action), 200, nil)
|
||||||
|
if err != nil {
|
||||||
|
return v, fmt.Errorf("error %w: %s", err, body)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &v); err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
// QueryOptionalFeatures queries the optional features supported by the Tailscale daemon.
|
// QueryOptionalFeatures queries the optional features supported by the Tailscale daemon.
|
||||||
func (lc *Client) QueryOptionalFeatures(ctx context.Context) (*apitype.OptionalFeatures, error) {
|
func (lc *Client) QueryOptionalFeatures(ctx context.Context) (*apitype.OptionalFeatures, error) {
|
||||||
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-optional-features", 200, nil)
|
body, err := lc.send(ctx, "POST", "/localapi/v0/debug-optional-features", 200, nil)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func visitDoctor(ctx context.Context, b *ipnlocal.LocalBackend, logf logger.Logf
|
|||||||
// IPs; this can interfere with our ability to connect to the Tailscale
|
// IPs; this can interfere with our ability to connect to the Tailscale
|
||||||
// controlplane.
|
// controlplane.
|
||||||
checks = append(checks, doctor.CheckFunc("dns-resolvers", func(_ context.Context, logf logger.Logf) error {
|
checks = append(checks, doctor.CheckFunc("dns-resolvers", func(_ context.Context, logf logger.Logf) error {
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -909,7 +909,7 @@ func (b *LocalBackend) resolveCertDomain(domain string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the netmap once to get both CertDomains and capabilities atomically.
|
// Read the netmap once to get both CertDomains and capabilities atomically.
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return "", errors.New("no netmap available")
|
return "", errors.New("no netmap available")
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-5
@@ -701,7 +701,9 @@ func (b *LocalBackend) onHomeDERPUpdateLocked(du magicsock.HomeDERPChanged) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.writeNetmapToDiskLocked(b.NetMap()); err != nil {
|
// Persist the full netmap (including up-to-date Peers) to disk for
|
||||||
|
// fast restart.
|
||||||
|
if err := b.writeNetmapToDiskLocked(b.NetMapWithPeers()); err != nil {
|
||||||
b.logf("write netmap to cache: %v", err)
|
b.logf("write netmap to cache: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1025,7 @@ func (b *LocalBackend) pauseOrResumeControlClientLocked() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
networkUp := b.interfaceState.AnyInterfaceUp()
|
networkUp := b.interfaceState.AnyInterfaceUp()
|
||||||
pauseForNetwork := (b.state == ipn.Stopped && b.NetMap() != nil) || (!networkUp && !testenv.InTest() && !envknob.AssumeNetworkUp())
|
pauseForNetwork := (b.state == ipn.Stopped && b.NetMapNoPeers() != nil) || (!networkUp && !testenv.InTest() && !envknob.AssumeNetworkUp())
|
||||||
|
|
||||||
prefs := b.pm.CurrentPrefs()
|
prefs := b.pm.CurrentPrefs()
|
||||||
pauseForSyncPref := prefs.Valid() && prefs.Sync().EqualBool(false)
|
pauseForSyncPref := prefs.Valid() && prefs.Sync().EqualBool(false)
|
||||||
@@ -4057,7 +4059,8 @@ func (b *LocalBackend) pingPeerAPI(ctx context.Context, ip netip.Addr) (peer tai
|
|||||||
var zero tailcfg.NodeView
|
var zero tailcfg.NodeView
|
||||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
nm := b.NetMap()
|
// PeerByTailscaleIP needs an up-to-date Peers slice.
|
||||||
|
nm := b.NetMapWithPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return zero, "", errors.New("no netmap")
|
return zero, "", errors.New("no netmap")
|
||||||
}
|
}
|
||||||
@@ -4967,7 +4970,7 @@ func (b *LocalBackend) handlePeerAPIConn(remote, local netip.AddrPort, c net.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) isLocalIP(ip netip.Addr) bool {
|
func (b *LocalBackend) isLocalIP(ip netip.Addr) bool {
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
return nm != nil && views.SliceContains(nm.GetAddresses(), netip.PrefixFrom(ip, ip.BitLen()))
|
return nm != nil && views.SliceContains(nm.GetAddresses(), netip.PrefixFrom(ip, ip.BitLen()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5119,10 +5122,46 @@ func extractPeerAPIPorts(services []tailcfg.Service) portPair {
|
|||||||
|
|
||||||
// NetMap returns the latest cached network map received from
|
// NetMap returns the latest cached network map received from
|
||||||
// controlclient, or nil if no network map was received yet.
|
// controlclient, or nil if no network map was received yet.
|
||||||
|
//
|
||||||
|
// Deprecated: callers should declare their needs explicitly by calling
|
||||||
|
// either [LocalBackend.NetMapNoPeers] (cheap; for code that reads
|
||||||
|
// non-Peers fields like SelfNode, DNS, PacketFilter, capabilities) or
|
||||||
|
// [LocalBackend.NetMapWithPeers] (currently the same; will be made to
|
||||||
|
// return an up-to-date Peers slice in a follow-up change, at the cost of
|
||||||
|
// O(N) work per call). NetMap will eventually be removed.
|
||||||
func (b *LocalBackend) NetMap() *netmap.NetworkMap {
|
func (b *LocalBackend) NetMap() *netmap.NetworkMap {
|
||||||
return b.currentNode().NetMap()
|
return b.currentNode().NetMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetMapNoPeers returns the latest cached network map received from
|
||||||
|
// controlclient WITHOUT a freshly-built Peers slice.
|
||||||
|
//
|
||||||
|
// On a tailnet with frequent peer churn the cached netmap's Peers slice
|
||||||
|
// can be stale relative to the live per-node-backend peers map; non-Peers
|
||||||
|
// fields (SelfNode, DNS, PacketFilter, capabilities, ...) are always
|
||||||
|
// current. Use this for any caller that does not need to iterate Peers,
|
||||||
|
// since it's O(1) regardless of tailnet size.
|
||||||
|
//
|
||||||
|
// Returns nil if no network map has been received yet.
|
||||||
|
func (b *LocalBackend) NetMapNoPeers() *netmap.NetworkMap {
|
||||||
|
return b.currentNode().NetMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetMapWithPeers returns the latest network map with the Peers slice
|
||||||
|
// populated.
|
||||||
|
//
|
||||||
|
// Currently this is the same as [LocalBackend.NetMapNoPeers]: the cached
|
||||||
|
// netmap's Peers slice may be stale relative to the live per-node-backend
|
||||||
|
// peers map. A follow-up change will switch this method to return a
|
||||||
|
// freshly-built netmap with up-to-date Peers, at O(N) cost per call.
|
||||||
|
// Callers that genuinely need the up-to-date peer set should use this
|
||||||
|
// method (and document why) so the upcoming change reaches them.
|
||||||
|
//
|
||||||
|
// Returns nil if no network map has been received yet.
|
||||||
|
func (b *LocalBackend) NetMapWithPeers() *netmap.NetworkMap {
|
||||||
|
return b.currentNode().NetMap()
|
||||||
|
}
|
||||||
|
|
||||||
// lookupPeerByIP returns the node public key for the peer that owns the
|
// lookupPeerByIP returns the node public key for the peer that owns the
|
||||||
// given IP address. It is the fast path for [Engine.SetPeerByIPPacketFunc],
|
// given IP address. It is the fast path for [Engine.SetPeerByIPPacketFunc],
|
||||||
// handling exact-IP matches against node addresses; subnet routes and exit
|
// handling exact-IP matches against node addresses; subnet routes and exit
|
||||||
@@ -6978,7 +7017,7 @@ func (b *LocalBackend) AppConnector() *appc.AppConnector {
|
|||||||
func (b *LocalBackend) allowExitNodeDNSProxyToServeName(name string) bool {
|
func (b *LocalBackend) allowExitNodeDNSProxyToServeName(name string) bool {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ func (pln *peerAPIListener) ServeConn(src netip.AddrPort, c net.Conn) {
|
|||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := pln.lb.NetMap()
|
nm := pln.lb.NetMapNoPeers()
|
||||||
if nm == nil || !nm.SelfNode.Valid() {
|
if nm == nil || !nm.SelfNode.Valid() {
|
||||||
logf("peerapi: no netmap")
|
logf("peerapi: no netmap")
|
||||||
c.Close()
|
c.Close()
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ func (b *LocalBackend) updateServeTCPPortNetMapAddrListenersLocked(ports []uint1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
b.logf("netMap is nil")
|
b.logf("netMap is nil")
|
||||||
return
|
return
|
||||||
@@ -333,7 +333,7 @@ func (b *LocalBackend) setServeConfigLocked(config *ipn.ServeConfig, etag string
|
|||||||
return errors.New("can't reconfigure tailscaled when using a config file; config file is locked")
|
return errors.New("can't reconfigure tailscaled when using a config file; config file is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return errors.New("netMap is nil")
|
return errors.New("netMap is nil")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func (b *LocalBackend) waitWebClientAuthURL(ctx context.Context, id string, src
|
|||||||
// one to be completed, based on the presence or absence of the
|
// one to be completed, based on the presence or absence of the
|
||||||
// provided id value.
|
// provided id value.
|
||||||
func (b *LocalBackend) doWebClientNoiseRequest(ctx context.Context, id string, src tailcfg.NodeID) (*tailcfg.WebClientAuthResponse, error) {
|
func (b *LocalBackend) doWebClientNoiseRequest(ctx context.Context, id string, src tailcfg.NodeID) (*tailcfg.WebClientAuthResponse, error) {
|
||||||
nm := b.NetMap()
|
nm := b.NetMapNoPeers()
|
||||||
if nm == nil || !nm.SelfNode.Valid() {
|
if nm == nil || !nm.SelfNode.Valid() {
|
||||||
return nil, errors.New("[unexpected] no self node")
|
return nil, errors.New("[unexpected] no self node")
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-2
@@ -9,6 +9,7 @@ import (
|
|||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@@ -249,6 +250,22 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
case "clear-netmap-cache":
|
case "clear-netmap-cache":
|
||||||
h.b.ClearNetmapCache(r.Context())
|
h.b.ClearNetmapCache(r.Context())
|
||||||
|
case "current-netmap":
|
||||||
|
// Return the current netmap (with peers populated) as JSON. This
|
||||||
|
// is a debug-only path: the netmap.NetworkMap shape is an
|
||||||
|
// internal type and may change without notice. Production
|
||||||
|
// callers should fetch the narrower bits they need via their
|
||||||
|
// own LocalAPI methods instead.
|
||||||
|
nm := h.b.NetMapWithPeers()
|
||||||
|
if nm == nil {
|
||||||
|
err = errors.New("no netmap")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
err = json.NewEncoder(w).Encode(nm)
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
case "":
|
case "":
|
||||||
err = fmt.Errorf("missing parameter 'action'")
|
err = fmt.Errorf("missing parameter 'action'")
|
||||||
default:
|
default:
|
||||||
@@ -284,7 +301,7 @@ func (h *Handler) serveDebugPacketFilterRules(w http.ResponseWriter, r *http.Req
|
|||||||
http.Error(w, "debug access denied", http.StatusForbidden)
|
http.Error(w, "debug access denied", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := h.b.NetMap()
|
nm := h.b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
http.Error(w, "no netmap", http.StatusNotFound)
|
http.Error(w, "no netmap", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
@@ -301,7 +318,7 @@ func (h *Handler) serveDebugPacketFilterMatches(w http.ResponseWriter, r *http.R
|
|||||||
http.Error(w, "debug access denied", http.StatusForbidden)
|
http.Error(w, "debug access denied", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := h.b.NetMap()
|
nm := h.b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
http.Error(w, "no netmap", http.StatusNotFound)
|
http.Error(w, "no netmap", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ func (h *Handler) serveIDToken(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "id-token access denied", http.StatusForbidden)
|
http.Error(w, "id-token access denied", http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := h.b.NetMap()
|
nm := h.b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
@@ -417,7 +417,7 @@ func (h *Handler) serveBugReport(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Information about the current node from the netmap
|
// Information about the current node from the netmap
|
||||||
if nm := h.b.NetMap(); nm != nil {
|
if nm := h.b.NetMapNoPeers(); nm != nil {
|
||||||
if self := nm.SelfNode; self.Valid() {
|
if self := nm.SelfNode; self.Valid() {
|
||||||
h.logf("user bugreport node info: nodeid=%q stableid=%q expiry=%q", self.ID(), self.StableID(), self.KeyExpiry().Format(time.RFC3339))
|
h.logf("user bugreport node info: nodeid=%q stableid=%q expiry=%q", self.ID(), self.StableID(), self.KeyExpiry().Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
@@ -1476,7 +1476,7 @@ func (h *Handler) serveQueryFeature(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "missing feature", http.StatusInternalServerError)
|
http.Error(w, "missing feature", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := h.b.NetMap()
|
nm := h.b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
@@ -1731,7 +1731,7 @@ func (h *Handler) serveServices(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "only GET allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "only GET allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nm := h.b.NetMap()
|
nm := h.b.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
http.Error(w, "no netmap", http.StatusServiceUnavailable)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ func (ss *sshSession) newIncubatorCommand(logf logger.Logf) (cmd *exec.Cmd, err
|
|||||||
incubatorArgs = append(incubatorArgs, "--is-selinux-enforcing")
|
incubatorArgs = append(incubatorArgs, "--is-selinux-enforcing")
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := ss.conn.srv.lb.NetMap()
|
nm := ss.conn.srv.lb.NetMapNoPeers()
|
||||||
forceV1Behavior := nm.HasCap(tailcfg.NodeAttrSSHBehaviorV1) && !nm.HasCap(tailcfg.NodeAttrSSHBehaviorV2)
|
forceV1Behavior := nm.HasCap(tailcfg.NodeAttrSSHBehaviorV1) && !nm.HasCap(tailcfg.NodeAttrSSHBehaviorV2)
|
||||||
if forceV1Behavior {
|
if forceV1Behavior {
|
||||||
incubatorArgs = append(incubatorArgs, "--force-v1-behavior")
|
incubatorArgs = append(incubatorArgs, "--force-v1-behavior")
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (ss *sshSession) newIncubatorCommand(logf logger.Logf) (cmd *exec.Cmd, err
|
|||||||
"--tty-name=", // updated in-place by startWithPTY
|
"--tty-name=", // updated in-place by startWithPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
nm := ss.conn.srv.lb.NetMap()
|
nm := ss.conn.srv.lb.NetMapNoPeers()
|
||||||
forceV1Behavior := nm.HasCap(tailcfg.NodeAttrSSHBehaviorV1) && !nm.HasCap(tailcfg.NodeAttrSSHBehaviorV2)
|
forceV1Behavior := nm.HasCap(tailcfg.NodeAttrSSHBehaviorV1) && !nm.HasCap(tailcfg.NodeAttrSSHBehaviorV2)
|
||||||
if forceV1Behavior {
|
if forceV1Behavior {
|
||||||
incubatorArgs = append(incubatorArgs, "--force-v1-behavior")
|
incubatorArgs = append(incubatorArgs, "--force-v1-behavior")
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ const (
|
|||||||
type ipnLocalBackend interface {
|
type ipnLocalBackend interface {
|
||||||
ShouldRunSSH() bool
|
ShouldRunSSH() bool
|
||||||
NetMap() *netmap.NetworkMap
|
NetMap() *netmap.NetworkMap
|
||||||
|
NetMapNoPeers() *netmap.NetworkMap
|
||||||
WhoIs(proto string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool)
|
WhoIs(proto string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool)
|
||||||
DoNoiseRequest(req *http.Request) (*http.Response, error)
|
DoNoiseRequest(req *http.Request) (*http.Response, error)
|
||||||
Dialer() *tsdial.Dialer
|
Dialer() *tsdial.Dialer
|
||||||
@@ -598,7 +599,7 @@ func (c *conn) sshPolicy() (_ *tailcfg.SSHPolicy, ok bool) {
|
|||||||
if !lb.ShouldRunSSH() {
|
if !lb.ShouldRunSSH() {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
nm := lb.NetMap()
|
nm := lb.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@@ -717,7 +718,7 @@ func (c *conn) handleSessionPostSSHAuth(s gliderssh.Session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) expandDelegateURLLocked(actionURL string) string {
|
func (c *conn) expandDelegateURLLocked(actionURL string) string {
|
||||||
nm := c.srv.lb.NetMap()
|
nm := c.srv.lb.NetMapNoPeers()
|
||||||
ci := c.info
|
ci := c.info
|
||||||
lu := c.localUser
|
lu := c.localUser
|
||||||
var dstNodeID string
|
var dstNodeID string
|
||||||
|
|||||||
@@ -910,6 +910,8 @@ func (tb *testBackend) NetMap() *netmap.NetworkMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tb *testBackend) NetMapNoPeers() *netmap.NetworkMap { return tb.NetMap() }
|
||||||
|
|
||||||
func (tb *testBackend) WhoIs(_ string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool) {
|
func (tb *testBackend) WhoIs(_ string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool) {
|
||||||
return (&tailcfg.Node{}).View(), tailcfg.UserProfile{
|
return (&tailcfg.Node{}).View(), tailcfg.UserProfile{
|
||||||
LoginName: tb.localUser + "@example.com",
|
LoginName: tb.localUser + "@example.com",
|
||||||
|
|||||||
@@ -422,6 +422,8 @@ func (ts *localState) NetMap() *netmap.NetworkMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ts *localState) NetMapNoPeers() *netmap.NetworkMap { return ts.NetMap() }
|
||||||
|
|
||||||
func (ts *localState) WhoIs(proto string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool) {
|
func (ts *localState) WhoIs(proto string, ipp netip.AddrPort) (n tailcfg.NodeView, u tailcfg.UserProfile, ok bool) {
|
||||||
if proto != "tcp" {
|
if proto != "tcp" {
|
||||||
return tailcfg.NodeView{}, tailcfg.UserProfile{}, false
|
return tailcfg.NodeView{}, tailcfg.UserProfile{}, false
|
||||||
|
|||||||
+2
-2
@@ -668,7 +668,7 @@ func (s *Server) doInit() {
|
|||||||
// Server.
|
// Server.
|
||||||
// If the server is not running, it returns nil.
|
// If the server is not running, it returns nil.
|
||||||
func (s *Server) CertDomains() []string {
|
func (s *Server) CertDomains() []string {
|
||||||
nm := s.lb.NetMap()
|
nm := s.lb.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -679,7 +679,7 @@ func (s *Server) CertDomains() []string {
|
|||||||
// has not yet joined a tailnet or is otherwise unaware of its own IP addresses,
|
// has not yet joined a tailnet or is otherwise unaware of its own IP addresses,
|
||||||
// the returned ip4, ip6 will be !netip.IsValid().
|
// the returned ip4, ip6 will be !netip.IsValid().
|
||||||
func (s *Server) TailscaleIPs() (ip4, ip6 netip.Addr) {
|
func (s *Server) TailscaleIPs() (ip4, ip6 netip.Addr) {
|
||||||
nm := s.lb.NetMap()
|
nm := s.lb.NetMapNoPeers()
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user