From bd29b189fe8b15783b59c63ec5ebbb2584a9d5f7 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 18 Nov 2025 07:25:10 -0800 Subject: [PATCH] types/netmap,*: remove some redundant fields from NetMap Updates #12639 Change-Id: Ia50b15529bd1c002cdd2c937cdfbe69c06fa2dc8 Signed-off-by: Brad Fitzpatrick --- cmd/tsconnect/wasm/wasm_js.go | 2 +- control/controlclient/auto.go | 2 +- control/controlclient/direct.go | 2 +- control/controlclient/map.go | 2 -- ipn/ipnlocal/c2n_test.go | 1 - ipn/ipnlocal/dnsconfig_test.go | 14 ++++++++------ ipn/ipnlocal/local.go | 4 ++-- ipn/ipnlocal/local_test.go | 8 ++++---- ipn/ipnlocal/node_backend.go | 2 +- ipn/ipnlocal/state_test.go | 21 ++++++++++++++------- net/tsdial/dnsmap.go | 8 ++++---- net/tsdial/dnsmap_test.go | 6 +++--- types/netmap/netmap.go | 23 +++++++++++++++++------ wgengine/magicsock/magicsock_test.go | 6 +++--- 14 files changed, 59 insertions(+), 42 deletions(-) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 2e81fa4a8..c7aa00d1d 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -261,7 +261,7 @@ func (i *jsIPN) run(jsCallbacks js.Value) { jsNetMap := jsNetMap{ Self: jsNetMapSelfNode{ jsNetMapNode: jsNetMapNode{ - Name: nm.Name, + Name: nm.SelfName(), Addresses: mapSliceView(nm.GetAddresses(), func(a netip.Prefix) string { return a.Addr().String() }), NodeKey: nm.NodeKey.String(), MachineKey: nm.MachineKey.String(), diff --git a/control/controlclient/auto.go b/control/controlclient/auto.go index 20795d5a7..3cbfe8581 100644 --- a/control/controlclient/auto.go +++ b/control/controlclient/auto.go @@ -443,7 +443,7 @@ func (mrs mapRoutineState) UpdateFullNetmap(nm *netmap.NetworkMap) { c.mu.Lock() c.inMapPoll = true - c.expiry = nm.Expiry + c.expiry = nm.SelfKeyExpiry() stillAuthed := c.loggedIn c.logf("[v1] mapRoutine: netmap received: loggedIn=%v inMapPoll=true", stillAuthed) c.mu.Unlock() diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 1e1ce781f..62bbb3586 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -1093,7 +1093,7 @@ func (c *Direct) sendMapRequest(ctx context.Context, isStreaming bool, nu Netmap c.persist = newPersist.View() persist = c.persist } - c.expiry = nm.Expiry + c.expiry = nm.SelfKeyExpiry() } // gotNonKeepAliveMessage is whether we've yet received a MapResponse message without diff --git a/control/controlclient/map.go b/control/controlclient/map.go index a9db25517..9aa8e3710 100644 --- a/control/controlclient/map.go +++ b/control/controlclient/map.go @@ -891,8 +891,6 @@ func (ms *mapSession) netmap() *netmap.NetworkMap { if node := ms.lastNode; node.Valid() { nm.SelfNode = node - nm.Expiry = node.KeyExpiry() - nm.Name = node.Name() nm.AllCaps = ms.lastCapSet } diff --git a/ipn/ipnlocal/c2n_test.go b/ipn/ipnlocal/c2n_test.go index 420633c87..86cc6a549 100644 --- a/ipn/ipnlocal/c2n_test.go +++ b/ipn/ipnlocal/c2n_test.go @@ -142,7 +142,6 @@ func TestHandleC2NTLSCertStatus(t *testing.T) { func TestHandleC2NDebugNetmap(t *testing.T) { nm := &netmap.NetworkMap{ - Name: "myhost", SelfNode: (&tailcfg.Node{ ID: 100, Name: "myhost", diff --git a/ipn/ipnlocal/dnsconfig_test.go b/ipn/ipnlocal/dnsconfig_test.go index 71f175148..e23d8a057 100644 --- a/ipn/ipnlocal/dnsconfig_test.go +++ b/ipn/ipnlocal/dnsconfig_test.go @@ -70,8 +70,8 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "self_name_and_peers", nm: &netmap.NetworkMap{ - Name: "myname.net", SelfNode: (&tailcfg.Node{ + Name: "myname.net.", Addresses: ipps("100.101.101.101"), }).View(), }, @@ -109,15 +109,15 @@ func TestDNSConfigForNetmap(t *testing.T) { // even if they have IPv4. name: "v6_only_self", nm: &netmap.NetworkMap{ - Name: "myname.net", SelfNode: (&tailcfg.Node{ + Name: "myname.net.", Addresses: ipps("fe75::1"), }).View(), }, peers: nodeViews([]*tailcfg.Node{ { ID: 1, - Name: "peera.net", + Name: "peera.net.", Addresses: ipps("100.102.0.1", "100.102.0.2", "fe75::1001"), }, { @@ -146,8 +146,8 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "extra_records", nm: &netmap.NetworkMap{ - Name: "myname.net", SelfNode: (&tailcfg.Node{ + Name: "myname.net.", Addresses: ipps("100.101.101.101"), }).View(), DNS: tailcfg.DNSConfig{ @@ -171,7 +171,9 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "corp_dns_misc", nm: &netmap.NetworkMap{ - Name: "host.some.domain.net.", + SelfNode: (&tailcfg.Node{ + Name: "host.some.domain.net.", + }).View(), DNS: tailcfg.DNSConfig{ Proxied: true, Domains: []string{"foo.com", "bar.com"}, @@ -331,8 +333,8 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "self_expired", nm: &netmap.NetworkMap{ - Name: "myname.net", SelfNode: (&tailcfg.Node{ + Name: "myname.net.", Addresses: ipps("100.101.101.101"), }).View(), }, diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 24ab41735..7eb673e6d 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -1301,7 +1301,7 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) { if hi := nm.SelfNode.Hostinfo(); hi.Valid() { ss.HostName = hi.Hostname() } - ss.DNSName = nm.Name + ss.DNSName = nm.SelfName() ss.UserID = nm.User() if sn := nm.SelfNode; sn.Valid() { peerStatusFromNode(ss, sn) @@ -1617,7 +1617,7 @@ func (b *LocalBackend) SetControlClientStatus(c controlclient.Client, st control keyExpiryExtended := false if st.NetMap != nil { wasExpired := b.keyExpired - isExpired := !st.NetMap.Expiry.IsZero() && st.NetMap.Expiry.Before(b.clock.Now()) + isExpired := !st.NetMap.SelfKeyExpiry().IsZero() && st.NetMap.SelfKeyExpiry().Before(b.clock.Now()) if wasExpired && !isExpired { keyExpiryExtended = true } diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 5df0ae5bb..f17fabb60 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -2712,8 +2712,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) { exitNodeIPWant: "127.0.0.1", prefsChanged: false, nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), @@ -2749,8 +2749,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) { exitNodeIDWant: "123", prefsChanged: true, nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), @@ -2787,8 +2787,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) { exitNodeIDWant: "123", prefsChanged: true, nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), @@ -2827,8 +2827,8 @@ func TestSetExitNodeIDPolicy(t *testing.T) { exitNodeIDWant: "123", prefsChanged: true, nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), diff --git a/ipn/ipnlocal/node_backend.go b/ipn/ipnlocal/node_backend.go index 6880440bd..efef57ea4 100644 --- a/ipn/ipnlocal/node_backend.go +++ b/ipn/ipnlocal/node_backend.go @@ -748,7 +748,7 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg. } dcfg.Hosts[fqdn] = ips } - set(nm.Name, nm.GetAddresses()) + set(nm.SelfName(), nm.GetAddresses()) for _, peer := range peers { set(peer.Name(), peer.Addresses()) } diff --git a/ipn/ipnlocal/state_test.go b/ipn/ipnlocal/state_test.go index 0c95ef4fc..b7325e957 100644 --- a/ipn/ipnlocal/state_test.go +++ b/ipn/ipnlocal/state_test.go @@ -999,8 +999,10 @@ func runTestStateMachine(t *testing.T, seamless bool) { t.Logf("\n\nExpireKey") notifies.expect(1) cc.send(sendOpt{nm: &netmap.NetworkMap{ - Expiry: time.Now().Add(-time.Minute), - SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), + SelfNode: (&tailcfg.Node{ + KeyExpiry: time.Now().Add(-time.Minute), + MachineAuthorized: true, + }).View(), }}) { nn := notifies.drain(1) @@ -1015,8 +1017,10 @@ func runTestStateMachine(t *testing.T, seamless bool) { t.Logf("\n\nExtendKey") notifies.expect(1) cc.send(sendOpt{nm: &netmap.NetworkMap{ - Expiry: time.Now().Add(time.Minute), - SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), + SelfNode: (&tailcfg.Node{ + MachineAuthorized: true, + KeyExpiry: time.Now().Add(time.Minute), + }).View(), }}) { nn := notifies.drain(1) @@ -1427,7 +1431,9 @@ func TestEngineReconfigOnStateChange(t *testing.T) { mustDo2(t)(lb.EditPrefs(connect)) cc().authenticated(node1) cc().send(sendOpt{nm: &netmap.NetworkMap{ - Expiry: time.Now().Add(-time.Minute), + SelfNode: (&tailcfg.Node{ + KeyExpiry: time.Now().Add(-time.Minute), + }).View(), }}) }, wantState: ipn.NeedsLogin, @@ -1550,7 +1556,9 @@ func TestEngineReconfigOnStateChange(t *testing.T) { mustDo2(t)(lb.EditPrefs(connect)) cc().authenticated(node1) cc().send(sendOpt{nm: &netmap.NetworkMap{ - Expiry: time.Now().Add(-time.Minute), + SelfNode: (&tailcfg.Node{ + KeyExpiry: time.Now().Add(-time.Minute), + }).View(), }}) }, // Even with seamless, if the key we are using expires, we want to disconnect: @@ -1725,7 +1733,6 @@ func buildNetmapWithPeers(self tailcfg.NodeView, peers ...tailcfg.NodeView) *net return &netmap.NetworkMap{ SelfNode: self, - Name: self.Name(), Domain: domain, Peers: peers, UserProfiles: users, diff --git a/net/tsdial/dnsmap.go b/net/tsdial/dnsmap.go index 2ef1cb1f1..37fedd14c 100644 --- a/net/tsdial/dnsmap.go +++ b/net/tsdial/dnsmap.go @@ -36,11 +36,11 @@ func dnsMapFromNetworkMap(nm *netmap.NetworkMap) dnsMap { suffix := nm.MagicDNSSuffix() have4 := false addrs := nm.GetAddresses() - if nm.Name != "" && addrs.Len() > 0 { + if name := nm.SelfName(); name != "" && addrs.Len() > 0 { ip := addrs.At(0).Addr() - ret[canonMapKey(nm.Name)] = ip - if dnsname.HasSuffix(nm.Name, suffix) { - ret[canonMapKey(dnsname.TrimSuffix(nm.Name, suffix))] = ip + ret[canonMapKey(name)] = ip + if dnsname.HasSuffix(name, suffix) { + ret[canonMapKey(dnsname.TrimSuffix(name, suffix))] = ip } for _, p := range addrs.All() { if p.Addr().Is4() { diff --git a/net/tsdial/dnsmap_test.go b/net/tsdial/dnsmap_test.go index 43461a135..41a957f18 100644 --- a/net/tsdial/dnsmap_test.go +++ b/net/tsdial/dnsmap_test.go @@ -31,8 +31,8 @@ func TestDNSMapFromNetworkMap(t *testing.T) { { name: "self", nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), @@ -47,8 +47,8 @@ func TestDNSMapFromNetworkMap(t *testing.T) { { name: "self_and_peers", nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), @@ -82,8 +82,8 @@ func TestDNSMapFromNetworkMap(t *testing.T) { { name: "self_has_v6_only", nm: &netmap.NetworkMap{ - Name: "foo.tailnet", SelfNode: (&tailcfg.Node{ + Name: "foo.tailnet.", Addresses: []netip.Prefix{ pfx("100::123/128"), }, diff --git a/types/netmap/netmap.go b/types/netmap/netmap.go index 0a2f3ea71..c54562f4d 100644 --- a/types/netmap/netmap.go +++ b/types/netmap/netmap.go @@ -29,10 +29,6 @@ type NetworkMap struct { SelfNode tailcfg.NodeView AllCaps set.Set[tailcfg.NodeCapability] // set version of SelfNode.Capabilities + SelfNode.CapMap NodeKey key.NodePublic - Expiry time.Time - // Name is the DNS name assigned to this node. - // It is the MapResponse.Node.Name value and ends with a period. - Name string MachineKey key.MachinePublic @@ -235,10 +231,25 @@ func MagicDNSSuffixOfNodeName(nodeName string) string { // // It will neither start nor end with a period. func (nm *NetworkMap) MagicDNSSuffix() string { - if nm == nil { + return MagicDNSSuffixOfNodeName(nm.SelfName()) +} + +// SelfName returns nm.SelfNode.Name, or the empty string +// if nm is nil or nm.SelfNode is invalid. +func (nm *NetworkMap) SelfName() string { + if nm == nil || !nm.SelfNode.Valid() { return "" } - return MagicDNSSuffixOfNodeName(nm.Name) + return nm.SelfNode.Name() +} + +// SelfKeyExpiry returns nm.SelfNode.KeyExpiry, or the zero +// value if nil or nm.SelfNode is invalid. +func (nm *NetworkMap) SelfKeyExpiry() time.Time { + if nm == nil || !nm.SelfNode.Valid() { + return time.Time{} + } + return nm.SelfNode.KeyExpiry() } // DomainName returns the name of the NetworkMap's diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index f9d761052..2a20b3cf6 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -2200,9 +2200,9 @@ func TestIsWireGuardOnlyPeer(t *testing.T) { defer m.Close() nm := &netmap.NetworkMap{ - Name: "ts", NodeKey: m.privateKey.Public(), SelfNode: (&tailcfg.Node{ + Name: "ts.", Addresses: []netip.Prefix{tsaip}, }).View(), Peers: nodeViews([]*tailcfg.Node{ @@ -2264,9 +2264,9 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) { defer m.Close() nm := &netmap.NetworkMap{ - Name: "ts", NodeKey: m.privateKey.Public(), SelfNode: (&tailcfg.Node{ + Name: "ts.", Addresses: []netip.Prefix{tsaip}, }).View(), Peers: nodeViews([]*tailcfg.Node{ @@ -2400,9 +2400,9 @@ func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) { wgEpV6 := netip.MustParseAddrPort(v6.LocalAddr().String()) nm := &netmap.NetworkMap{ - Name: "ts", NodeKey: m.privateKey.Public(), SelfNode: (&tailcfg.Node{ + Name: "ts.", Addresses: []netip.Prefix{tsaip}, }).View(), Peers: nodeViews([]*tailcfg.Node{