diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index c0dd70528..caac3977c 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -651,6 +651,7 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) { func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func(*ipnstate.StatusBuilder)) { b.mu.Lock() defer b.mu.Unlock() + sb.MutateStatus(func(s *ipnstate.Status) { s.Version = version.Long() s.TUN = !b.sys.IsNetstack() @@ -701,7 +702,19 @@ func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func } } }) + + var tailscaleIPs []netip.Addr + if b.netMap != nil { + for _, addr := range b.netMap.Addresses { + if addr.IsSingleIP() { + sb.AddTailscaleIP(addr.Addr()) + tailscaleIPs = append(tailscaleIPs, addr.Addr()) + } + } + } + sb.MutateSelfStatus(func(ss *ipnstate.PeerStatus) { + ss.OS = version.OS() ss.Online = health.GetInPollNetMap() if b.netMap != nil { ss.InNetworkMap = true @@ -716,6 +729,10 @@ func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func ss.Capabilities = c.AsSlice() } } + for _, addr := range tailscaleIPs { + ss.TailscaleIPs = append(ss.TailscaleIPs, addr) + } + } else { ss.HostName, _ = os.Hostname() } @@ -783,6 +800,7 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { // peerStatusFromNode copies fields that exist in the Node struct for // current node and peers into the provided PeerStatus. func peerStatusFromNode(ps *ipnstate.PeerStatus, n tailcfg.NodeView) { + ps.PublicKey = n.Key() ps.ID = n.StableID() ps.Created = n.Created() ps.ExitNodeOption = tsaddr.ContainsExitRoutes(n.AllowedIPs()) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 7cea3877c..65eb564a8 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -54,7 +54,6 @@ import ( "tailscale.com/util/mak" "tailscale.com/util/ringbuffer" "tailscale.com/util/uniq" - "tailscale.com/version" "tailscale.com/wgengine/capture" ) @@ -2508,54 +2507,38 @@ func simpleDur(d time.Duration) time.Duration { return d.Round(time.Minute) } +// UpdateStatus implements the interface nede by ipnstate.StatusBuilder. +// +// This method adds in the magicsock-specific information only. Most +// of the status is otherwise populated by LocalBackend. func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { c.mu.Lock() defer c.mu.Unlock() - var tailscaleIPs []netip.Addr - if c.netMap != nil { - tailscaleIPs = make([]netip.Addr, 0, len(c.netMap.Addresses)) - for _, addr := range c.netMap.Addresses { - if !addr.IsSingleIP() { - continue - } - sb.AddTailscaleIP(addr.Addr()) - tailscaleIPs = append(tailscaleIPs, addr.Addr()) - } - } - sb.MutateSelfStatus(func(ss *ipnstate.PeerStatus) { - if !c.privateKey.IsZero() { - ss.PublicKey = c.privateKey.Public() - } else { - ss.PublicKey = key.NodePublic{} - } ss.Addrs = make([]string, 0, len(c.lastEndpoints)) for _, ep := range c.lastEndpoints { ss.Addrs = append(ss.Addrs, ep.Addr.String()) } - ss.OS = version.OS() if c.derpMap != nil { - derpRegion, ok := c.derpMap.Regions[c.myDerp] - if ok { - ss.Relay = derpRegion.RegionCode + if reg, ok := c.derpMap.Regions[c.myDerp]; ok { + ss.Relay = reg.RegionCode } } - ss.TailscaleIPs = tailscaleIPs }) if sb.WantPeers { c.peerMap.forEachEndpoint(func(ep *endpoint) { ps := &ipnstate.PeerStatus{InMagicSock: true} - //ps.Addrs = append(ps.Addrs, n.Endpoints...) ep.populatePeerStatus(ps) sb.AddPeer(ep.publicKey, ps) }) } c.foreachActiveDerpSortedLocked(func(node int, ad activeDerp) { - // TODO(bradfitz): add to ipnstate.StatusBuilder - //f("
  • derp-%v: cr%v,wr%v
  • ", node, simpleDur(now.Sub(ad.createTime)), simpleDur(now.Sub(*ad.lastWrite))) + // TODO(bradfitz): add a method to ipnstate.StatusBuilder + // to include all the DERP connections we have open + // and add it here. See the other caller of foreachActiveDerpSortedLocked. }) } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index bd5a07624..ac6a89aa1 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -226,6 +226,8 @@ func (s *magicStack) Public() key.NodePublic { return s.privateKey.Public() } +// Status returns a subset of the ipnstate.Status, only involving +// the magicsock-specific parts. func (s *magicStack) Status() *ipnstate.Status { var sb ipnstate.StatusBuilder sb.WantPeers = true @@ -240,9 +242,11 @@ func (s *magicStack) Status() *ipnstate.Status { // address. See meshStacks for one possible source of netmaps and IPs. func (s *magicStack) IP() netip.Addr { for deadline := time.Now().Add(5 * time.Second); time.Now().Before(deadline); time.Sleep(10 * time.Millisecond) { - st := s.Status() - if len(st.TailscaleIPs) > 0 { - return st.TailscaleIPs[0] + s.conn.mu.Lock() + nm := s.conn.netMap + s.conn.mu.Unlock() + if nm != nil && len(nm.Addresses) > 0 { + return nm.Addresses[0].Addr() } } panic("timed out waiting for magicstack to get an IP assigned")