mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-12 05:37:32 +00:00
types/netmap, all: use read-only tailcfg.NodeView in NetworkMap
Updates #8948 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
b040094b90
commit
58a4fd43d8
@@ -101,10 +101,10 @@ func (c *Conn) ServeHTTPDebug(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
sort.Slice(ent, func(i, j int) bool { return ent[i].pub.Less(ent[j].pub) })
|
||||
|
||||
peers := map[key.NodePublic]*tailcfg.Node{}
|
||||
peers := map[key.NodePublic]tailcfg.NodeView{}
|
||||
if c.netMap != nil {
|
||||
for _, p := range c.netMap.Peers {
|
||||
peers[p.Key] = p
|
||||
peers[p.Key()] = p
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,15 +187,15 @@ func printEndpointHTML(w io.Writer, ep *endpoint) {
|
||||
|
||||
}
|
||||
|
||||
func peerDebugName(p *tailcfg.Node) string {
|
||||
if p == nil {
|
||||
func peerDebugName(p tailcfg.NodeView) string {
|
||||
if !p.Valid() {
|
||||
return ""
|
||||
}
|
||||
n := p.Name
|
||||
n := p.Name()
|
||||
if base, _, ok := strings.Cut(n, "."); ok {
|
||||
return base
|
||||
}
|
||||
return p.Hostinfo.Hostname()
|
||||
return p.Hostinfo().Hostname()
|
||||
}
|
||||
|
||||
func ipPortLess(a, b netip.AddrPort) bool {
|
||||
|
@@ -725,15 +725,15 @@ func (de *endpoint) setLastPing(ipp netip.AddrPort, now mono.Time) {
|
||||
|
||||
// updateFromNode updates the endpoint based on a tailcfg.Node from a NetMap
|
||||
// update.
|
||||
func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
|
||||
if n == nil {
|
||||
func (de *endpoint) updateFromNode(n tailcfg.NodeView, heartbeatDisabled bool) {
|
||||
if !n.Valid() {
|
||||
panic("nil node when updating endpoint")
|
||||
}
|
||||
de.mu.Lock()
|
||||
defer de.mu.Unlock()
|
||||
|
||||
de.heartbeatDisabled = heartbeatDisabled
|
||||
de.expired = n.Expired
|
||||
de.expired = n.Expired()
|
||||
|
||||
epDisco := de.disco.Load()
|
||||
var discoKey key.DiscoPublic
|
||||
@@ -741,11 +741,11 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
|
||||
discoKey = epDisco.key
|
||||
}
|
||||
|
||||
if discoKey != n.DiscoKey {
|
||||
de.c.logf("[v1] magicsock: disco: node %s changed from %s to %s", de.publicKey.ShortString(), discoKey, n.DiscoKey)
|
||||
if discoKey != n.DiscoKey() {
|
||||
de.c.logf("[v1] magicsock: disco: node %s changed from %s to %s", de.publicKey.ShortString(), discoKey, n.DiscoKey())
|
||||
de.disco.Store(&endpointDisco{
|
||||
key: n.DiscoKey,
|
||||
short: n.DiscoKey.ShortString(),
|
||||
key: n.DiscoKey(),
|
||||
short: n.DiscoKey().ShortString(),
|
||||
})
|
||||
de.debugUpdates.Add(EndpointChange{
|
||||
When: time.Now(),
|
||||
@@ -753,7 +753,7 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
|
||||
})
|
||||
de.resetLocked()
|
||||
}
|
||||
if n.DERP == "" {
|
||||
if n.DERP() == "" {
|
||||
if de.derpAddr.IsValid() {
|
||||
de.debugUpdates.Add(EndpointChange{
|
||||
When: time.Now(),
|
||||
@@ -763,7 +763,7 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
|
||||
}
|
||||
de.derpAddr = netip.AddrPort{}
|
||||
} else {
|
||||
newDerp, _ := netip.ParseAddrPort(n.DERP)
|
||||
newDerp, _ := netip.ParseAddrPort(n.DERP())
|
||||
if de.derpAddr != newDerp {
|
||||
de.debugUpdates.Add(EndpointChange{
|
||||
When: time.Now(),
|
||||
@@ -780,7 +780,8 @@ func (de *endpoint) updateFromNode(n *tailcfg.Node, heartbeatDisabled bool) {
|
||||
}
|
||||
|
||||
var newIpps []netip.AddrPort
|
||||
for i, epStr := range n.Endpoints {
|
||||
for i := range n.Endpoints().LenIter() {
|
||||
epStr := n.Endpoints().At(i)
|
||||
if i > math.MaxInt16 {
|
||||
// Seems unlikely.
|
||||
continue
|
||||
|
@@ -711,7 +711,7 @@ func (c *Conn) LastRecvActivityOfNodeKey(nk key.NodePublic) string {
|
||||
}
|
||||
|
||||
// Ping handles a "tailscale ping" CLI query.
|
||||
func (c *Conn) Ping(peer *tailcfg.Node, res *ipnstate.PingResult, size int, cb func(*ipnstate.PingResult)) {
|
||||
func (c *Conn) Ping(peer tailcfg.NodeView, res *ipnstate.PingResult, size int, cb func(*ipnstate.PingResult)) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.privateKey.IsZero() {
|
||||
@@ -719,17 +719,17 @@ func (c *Conn) Ping(peer *tailcfg.Node, res *ipnstate.PingResult, size int, cb f
|
||||
cb(res)
|
||||
return
|
||||
}
|
||||
if len(peer.Addresses) > 0 {
|
||||
res.NodeIP = peer.Addresses[0].Addr().String()
|
||||
if peer.Addresses().Len() > 0 {
|
||||
res.NodeIP = peer.Addresses().At(0).Addr().String()
|
||||
}
|
||||
res.NodeName = peer.Name // prefer DNS name
|
||||
res.NodeName = peer.Name() // prefer DNS name
|
||||
if res.NodeName == "" {
|
||||
res.NodeName = peer.Hostinfo.Hostname() // else hostname
|
||||
res.NodeName = peer.Hostinfo().Hostname() // else hostname
|
||||
} else {
|
||||
res.NodeName, _, _ = strings.Cut(res.NodeName, ".")
|
||||
}
|
||||
|
||||
ep, ok := c.peerMap.endpointForNodeKey(peer.Key)
|
||||
ep, ok := c.peerMap.endpointForNodeKey(peer.Key())
|
||||
if !ok {
|
||||
res.Err = "unknown peer"
|
||||
cb(res)
|
||||
@@ -753,13 +753,13 @@ func (c *Conn) populateCLIPingResponseLocked(res *ipnstate.PingResult, latency t
|
||||
// GetEndpointChanges returns the most recent changes for a particular
|
||||
// endpoint. The returned EndpointChange structs are for debug use only and
|
||||
// there are no guarantees about order, size, or content.
|
||||
func (c *Conn) GetEndpointChanges(peer *tailcfg.Node) ([]EndpointChange, error) {
|
||||
func (c *Conn) GetEndpointChanges(peer tailcfg.NodeView) ([]EndpointChange, error) {
|
||||
c.mu.Lock()
|
||||
if c.privateKey.IsZero() {
|
||||
c.mu.Unlock()
|
||||
return nil, fmt.Errorf("tailscaled stopped")
|
||||
}
|
||||
ep, ok := c.peerMap.endpointForNodeKey(peer.Key)
|
||||
ep, ok := c.peerMap.endpointForNodeKey(peer.Key())
|
||||
c.mu.Unlock()
|
||||
|
||||
if !ok {
|
||||
@@ -1729,7 +1729,7 @@ func (c *Conn) UpdatePeers(newPeers map[key.NodePublic]struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func nodesEqual(x, y []*tailcfg.Node) bool {
|
||||
func nodesEqual(x, y []tailcfg.NodeView) bool {
|
||||
if len(x) != len(y) {
|
||||
return false
|
||||
}
|
||||
@@ -1800,8 +1800,8 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
|
||||
// we'll fall through to the next pass, which allocates but can
|
||||
// handle full set updates.
|
||||
for _, n := range nm.Peers {
|
||||
if ep, ok := c.peerMap.endpointForNodeKey(n.Key); ok {
|
||||
if n.DiscoKey.IsZero() && !n.IsWireGuardOnly {
|
||||
if ep, ok := c.peerMap.endpointForNodeKey(n.Key()); ok {
|
||||
if n.DiscoKey().IsZero() && !n.IsWireGuardOnly() {
|
||||
// Discokey transitioned from non-zero to zero? This should not
|
||||
// happen in the wild, however it could mean:
|
||||
// 1. A node was downgraded from post 0.100 to pre 0.100.
|
||||
@@ -1820,7 +1820,7 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
|
||||
c.peerMap.upsertEndpoint(ep, oldDiscoKey) // maybe update discokey mappings in peerMap
|
||||
continue
|
||||
}
|
||||
if n.DiscoKey.IsZero() && !n.IsWireGuardOnly {
|
||||
if n.DiscoKey().IsZero() && !n.IsWireGuardOnly() {
|
||||
// Ancient pre-0.100 node, which does not have a disco key, and will only be reachable via DERP.
|
||||
continue
|
||||
}
|
||||
@@ -1828,30 +1828,30 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
|
||||
ep := &endpoint{
|
||||
c: c,
|
||||
debugUpdates: ringbuffer.New[EndpointChange](entriesPerBuffer),
|
||||
publicKey: n.Key,
|
||||
publicKeyHex: n.Key.UntypedHexString(),
|
||||
publicKey: n.Key(),
|
||||
publicKeyHex: n.Key().UntypedHexString(),
|
||||
sentPing: map[stun.TxID]sentPing{},
|
||||
endpointState: map[netip.AddrPort]*endpointState{},
|
||||
heartbeatDisabled: heartbeatDisabled,
|
||||
isWireguardOnly: n.IsWireGuardOnly,
|
||||
isWireguardOnly: n.IsWireGuardOnly(),
|
||||
}
|
||||
if len(n.Addresses) > 0 {
|
||||
ep.nodeAddr = n.Addresses[0].Addr()
|
||||
if n.Addresses().Len() > 0 {
|
||||
ep.nodeAddr = n.Addresses().At(0).Addr()
|
||||
}
|
||||
ep.initFakeUDPAddr()
|
||||
if n.DiscoKey.IsZero() {
|
||||
if n.DiscoKey().IsZero() {
|
||||
ep.disco.Store(nil)
|
||||
} else {
|
||||
ep.disco.Store(&endpointDisco{
|
||||
key: n.DiscoKey,
|
||||
short: n.DiscoKey.ShortString(),
|
||||
key: n.DiscoKey(),
|
||||
short: n.DiscoKey().ShortString(),
|
||||
})
|
||||
|
||||
if debugDisco() { // rather than making a new knob
|
||||
c.logf("magicsock: created endpoint key=%s: disco=%s; %v", n.Key.ShortString(), n.DiscoKey.ShortString(), logger.ArgWriter(func(w *bufio.Writer) {
|
||||
c.logf("magicsock: created endpoint key=%s: disco=%s; %v", n.Key().ShortString(), n.DiscoKey().ShortString(), logger.ArgWriter(func(w *bufio.Writer) {
|
||||
const derpPrefix = "127.3.3.40:"
|
||||
if strings.HasPrefix(n.DERP, derpPrefix) {
|
||||
ipp, _ := netip.ParseAddrPort(n.DERP)
|
||||
if strings.HasPrefix(n.DERP(), derpPrefix) {
|
||||
ipp, _ := netip.ParseAddrPort(n.DERP())
|
||||
regionID := int(ipp.Port())
|
||||
code := c.derpRegionCodeLocked(regionID)
|
||||
if code != "" {
|
||||
@@ -1860,14 +1860,16 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
|
||||
fmt.Fprintf(w, "derp=%v%s ", regionID, code)
|
||||
}
|
||||
|
||||
for _, a := range n.AllowedIPs {
|
||||
for i := range n.AllowedIPs().LenIter() {
|
||||
a := n.AllowedIPs().At(i)
|
||||
if a.IsSingleIP() {
|
||||
fmt.Fprintf(w, "aip=%v ", a.Addr())
|
||||
} else {
|
||||
fmt.Fprintf(w, "aip=%v ", a)
|
||||
}
|
||||
}
|
||||
for _, ep := range n.Endpoints {
|
||||
for i := range n.Endpoints().LenIter() {
|
||||
ep := n.Endpoints().At(i)
|
||||
fmt.Fprintf(w, "ep=%v ", ep)
|
||||
}
|
||||
}))
|
||||
@@ -1885,7 +1887,7 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) {
|
||||
if c.peerMap.nodeCount() != len(nm.Peers) {
|
||||
keep := make(map[key.NodePublic]bool, len(nm.Peers))
|
||||
for _, n := range nm.Peers {
|
||||
keep[n.Key] = true
|
||||
keep[n.Key()] = true
|
||||
}
|
||||
c.peerMap.forEachEndpoint(func(ep *endpoint) {
|
||||
if !keep[ep.publicKey] {
|
||||
|
@@ -284,7 +284,7 @@ func meshStacks(logf logger.Logf, mutateNetmap func(idx int, nm *netmap.NetworkM
|
||||
Endpoints: epStrings(eps[i]),
|
||||
DERP: "127.3.3.40:1",
|
||||
}
|
||||
nm.Peers = append(nm.Peers, peer)
|
||||
nm.Peers = append(nm.Peers, peer.View())
|
||||
}
|
||||
|
||||
if mutateNetmap != nil {
|
||||
@@ -304,7 +304,7 @@ func meshStacks(logf logger.Logf, mutateNetmap func(idx int, nm *netmap.NetworkM
|
||||
m.conn.SetNetworkMap(nm)
|
||||
peerSet := make(map[key.NodePublic]struct{}, len(nm.Peers))
|
||||
for _, peer := range nm.Peers {
|
||||
peerSet[peer.Key] = struct{}{}
|
||||
peerSet[peer.Key()] = struct{}{}
|
||||
}
|
||||
m.conn.UpdatePeers(peerSet)
|
||||
wg, err := nmcfg.WGCfg(nm, logf, netmap.AllowSingleHosts, "")
|
||||
@@ -657,7 +657,9 @@ func TestDiscokeyChange(t *testing.T) {
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
nm.Peers[0].DiscoKey = m1DiscoKey
|
||||
mut := nm.Peers[0].AsStruct()
|
||||
mut.DiscoKey = m1DiscoKey
|
||||
nm.Peers[0] = mut.View()
|
||||
}
|
||||
|
||||
cleanupMesh := meshStacks(t.Logf, setm1Key, m1, m2)
|
||||
@@ -1248,13 +1250,13 @@ func addTestEndpoint(tb testing.TB, conn *Conn, sendConn net.PacketConn) (key.No
|
||||
discoKey := key.DiscoPublicFromRaw32(mem.B([]byte{31: 1}))
|
||||
nodeKey := key.NodePublicFromRaw32(mem.B([]byte{0: 'N', 1: 'K', 31: 0}))
|
||||
conn.SetNetworkMap(&netmap.NetworkMap{
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: nodeKey,
|
||||
DiscoKey: discoKey,
|
||||
Endpoints: []string{sendConn.LocalAddr().String()},
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
conn.SetPrivateKey(key.NodePrivateFromRaw32(mem.B([]byte{0: 1, 31: 0})))
|
||||
_, err := conn.ParseEndpoint(nodeKey.UntypedHexString())
|
||||
@@ -1427,6 +1429,14 @@ func BenchmarkReceiveFrom_Native(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func nodeViews(v []*tailcfg.Node) []tailcfg.NodeView {
|
||||
nv := make([]tailcfg.NodeView, len(v))
|
||||
for i, n := range v {
|
||||
nv[i] = n.View()
|
||||
}
|
||||
return nv
|
||||
}
|
||||
|
||||
// Test that a netmap update where node changes its node key but
|
||||
// doesn't change its disco key doesn't result in a broken state.
|
||||
//
|
||||
@@ -1444,13 +1454,13 @@ func TestSetNetworkMapChangingNodeKey(t *testing.T) {
|
||||
nodeKey2 := key.NodePublicFromRaw32(mem.B([]byte{0: 'N', 1: 'K', 2: '2', 31: 0}))
|
||||
|
||||
conn.SetNetworkMap(&netmap.NetworkMap{
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: nodeKey1,
|
||||
DiscoKey: discoKey,
|
||||
Endpoints: []string{"192.168.1.2:345"},
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
_, err := conn.ParseEndpoint(nodeKey1.UntypedHexString())
|
||||
if err != nil {
|
||||
@@ -1459,13 +1469,13 @@ func TestSetNetworkMapChangingNodeKey(t *testing.T) {
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
conn.SetNetworkMap(&netmap.NetworkMap{
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: nodeKey2,
|
||||
DiscoKey: discoKey,
|
||||
Endpoints: []string{"192.168.1.2:345"},
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1792,7 +1802,7 @@ func TestStressSetNetworkMap(t *testing.T) {
|
||||
}
|
||||
// Set the netmap.
|
||||
conn.SetNetworkMap(&netmap.NetworkMap{
|
||||
Peers: peers,
|
||||
Peers: nodeViews(peers),
|
||||
})
|
||||
// Check invariants.
|
||||
if err := conn.peerMap.validate(); err != nil {
|
||||
@@ -2237,7 +2247,7 @@ func TestIsWireGuardOnlyPeer(t *testing.T) {
|
||||
PrivateKey: m.privateKey,
|
||||
NodeKey: m.privateKey.Public(),
|
||||
Addresses: []netip.Prefix{tsaip},
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: wgkey.Public(),
|
||||
Endpoints: []string{wgEp.String()},
|
||||
@@ -2245,7 +2255,7 @@ func TestIsWireGuardOnlyPeer(t *testing.T) {
|
||||
Addresses: []netip.Prefix{wgaip},
|
||||
AllowedIPs: []netip.Prefix{wgaip},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
m.conn.SetNetworkMap(nm)
|
||||
|
||||
@@ -2295,7 +2305,7 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) {
|
||||
PrivateKey: m.privateKey,
|
||||
NodeKey: m.privateKey.Public(),
|
||||
Addresses: []netip.Prefix{tsaip},
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: wgkey.Public(),
|
||||
Endpoints: []string{wgEp.String()},
|
||||
@@ -2304,7 +2314,7 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) {
|
||||
AllowedIPs: []netip.Prefix{wgaip},
|
||||
SelfNodeV4MasqAddrForThisPeer: ptr.To(masqip.Addr()),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
m.conn.SetNetworkMap(nm)
|
||||
|
||||
@@ -2421,7 +2431,7 @@ func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) {
|
||||
PrivateKey: m.privateKey,
|
||||
NodeKey: m.privateKey.Public(),
|
||||
Addresses: []netip.Prefix{tsaip},
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: wgkey.Public(),
|
||||
Endpoints: []string{wgEp.String(), wgEp2.String(), wgEpV6.String()},
|
||||
@@ -2429,7 +2439,7 @@ func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) {
|
||||
Addresses: []netip.Prefix{wgaip},
|
||||
AllowedIPs: []netip.Prefix{wgaip},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
applyNetworkMap(t, m, nm)
|
||||
|
Reference in New Issue
Block a user