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
@@ -96,7 +96,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip.
|
||||
eps = append(eps, ep.Addr.String())
|
||||
}
|
||||
|
||||
n := tailcfg.Node{
|
||||
n := &tailcfg.Node{
|
||||
ID: tailcfg.NodeID(0),
|
||||
Name: "n1",
|
||||
Addresses: []netip.Prefix{a1},
|
||||
@@ -106,7 +106,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip.
|
||||
e2.SetNetworkMap(&netmap.NetworkMap{
|
||||
NodeKey: k2.Public(),
|
||||
PrivateKey: k2,
|
||||
Peers: []*tailcfg.Node{&n},
|
||||
Peers: []tailcfg.NodeView{n.View()},
|
||||
})
|
||||
|
||||
p := wgcfg.Peer{
|
||||
@@ -133,7 +133,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip.
|
||||
eps = append(eps, ep.Addr.String())
|
||||
}
|
||||
|
||||
n := tailcfg.Node{
|
||||
n := &tailcfg.Node{
|
||||
ID: tailcfg.NodeID(0),
|
||||
Name: "n2",
|
||||
Addresses: []netip.Prefix{a2},
|
||||
@@ -143,7 +143,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip.
|
||||
e1.SetNetworkMap(&netmap.NetworkMap{
|
||||
NodeKey: k1.Public(),
|
||||
PrivateKey: k1,
|
||||
Peers: []*tailcfg.Node{&n},
|
||||
Peers: []tailcfg.NodeView{n.View()},
|
||||
})
|
||||
|
||||
p := wgcfg.Peer{
|
||||
|
||||
@@ -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)
|
||||
|
||||
+16
-15
@@ -146,21 +146,22 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) {
|
||||
return
|
||||
}
|
||||
n := pip.Node
|
||||
if !n.IsWireGuardOnly {
|
||||
if n.DiscoKey.IsZero() {
|
||||
e.logf("open-conn-track: timeout opening %v; peer node %v running pre-0.100", flow, n.Key.ShortString())
|
||||
if !n.IsWireGuardOnly() {
|
||||
if n.DiscoKey().IsZero() {
|
||||
e.logf("open-conn-track: timeout opening %v; peer node %v running pre-0.100", flow, n.Key().ShortString())
|
||||
return
|
||||
}
|
||||
if n.DERP == "" {
|
||||
e.logf("open-conn-track: timeout opening %v; peer node %v not connected to any DERP relay", flow, n.Key.ShortString())
|
||||
if n.DERP() == "" {
|
||||
e.logf("open-conn-track: timeout opening %v; peer node %v not connected to any DERP relay", flow, n.Key().ShortString())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ps, found := e.getPeerStatusLite(n.Key)
|
||||
ps, found := e.getPeerStatusLite(n.Key())
|
||||
if !found {
|
||||
onlyZeroRoute := true // whether peerForIP returned n only because its /0 route matched
|
||||
for _, r := range n.AllowedIPs {
|
||||
for i := range n.AllowedIPs().LenIter() {
|
||||
r := n.AllowedIPs().At(i)
|
||||
if r.Bits() != 0 && r.Contains(flow.Dst.Addr()) {
|
||||
onlyZeroRoute = false
|
||||
break
|
||||
@@ -178,7 +179,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) {
|
||||
// node.
|
||||
return
|
||||
}
|
||||
e.logf("open-conn-track: timeout opening %v; target node %v in netmap but unknown to WireGuard", flow, n.Key.ShortString())
|
||||
e.logf("open-conn-track: timeout opening %v; target node %v in netmap but unknown to WireGuard", flow, n.Key().ShortString())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -189,24 +190,24 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) {
|
||||
_ = ps.LastHandshake
|
||||
|
||||
online := "?"
|
||||
if n.IsWireGuardOnly {
|
||||
if n.IsWireGuardOnly() {
|
||||
online = "wg"
|
||||
} else {
|
||||
if n.Online != nil {
|
||||
if *n.Online {
|
||||
if v := n.Online(); v != nil {
|
||||
if *v {
|
||||
online = "yes"
|
||||
} else {
|
||||
online = "no"
|
||||
}
|
||||
}
|
||||
if n.LastSeen != nil && online != "yes" {
|
||||
online += fmt.Sprintf(", lastseen=%v", durFmt(*n.LastSeen))
|
||||
if n.LastSeen() != nil && online != "yes" {
|
||||
online += fmt.Sprintf(", lastseen=%v", durFmt(*n.LastSeen()))
|
||||
}
|
||||
}
|
||||
e.logf("open-conn-track: timeout opening %v to node %v; online=%v, lastRecv=%v",
|
||||
flow, n.Key.ShortString(),
|
||||
flow, n.Key().ShortString(),
|
||||
online,
|
||||
e.magicConn.LastRecvActivityOfNodeKey(n.Key))
|
||||
e.magicConn.LastRecvActivityOfNodeKey(n.Key()))
|
||||
}
|
||||
|
||||
func durFmt(t time.Time) string {
|
||||
|
||||
@@ -1226,7 +1226,7 @@ func (e *userspaceEngine) Ping(ip netip.Addr, pingType tailcfg.PingType, size in
|
||||
}
|
||||
peer := pip.Node
|
||||
|
||||
e.logf("ping(%v): sending %v ping to %v %v ...", ip, pingType, peer.Key.ShortString(), peer.ComputedName)
|
||||
e.logf("ping(%v): sending %v ping to %v %v ...", ip, pingType, peer.Key().ShortString(), peer.ComputedName())
|
||||
switch pingType {
|
||||
case "disco":
|
||||
e.magicConn.Ping(peer, res, size, cb)
|
||||
@@ -1254,7 +1254,7 @@ func (e *userspaceEngine) mySelfIPMatchingFamily(dst netip.Addr) (src netip.Addr
|
||||
return netip.Addr{}, errors.New("no self address in netmap matching address family")
|
||||
}
|
||||
|
||||
func (e *userspaceEngine) sendICMPEchoRequest(destIP netip.Addr, peer *tailcfg.Node, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) {
|
||||
func (e *userspaceEngine) sendICMPEchoRequest(destIP netip.Addr, peer tailcfg.NodeView, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) {
|
||||
srcIP, err := e.mySelfIPMatchingFamily(destIP)
|
||||
if err != nil {
|
||||
res.Err = err.Error()
|
||||
@@ -1295,7 +1295,7 @@ func (e *userspaceEngine) sendICMPEchoRequest(destIP netip.Addr, peer *tailcfg.N
|
||||
d := time.Since(t0)
|
||||
res.LatencySeconds = d.Seconds()
|
||||
res.NodeIP = destIP.String()
|
||||
res.NodeName = peer.ComputedName
|
||||
res.NodeName = peer.ComputedName()
|
||||
cb(res)
|
||||
})
|
||||
|
||||
@@ -1303,7 +1303,7 @@ func (e *userspaceEngine) sendICMPEchoRequest(destIP netip.Addr, peer *tailcfg.N
|
||||
e.tundev.InjectOutbound(icmpPing)
|
||||
}
|
||||
|
||||
func (e *userspaceEngine) sendTSMPPing(ip netip.Addr, peer *tailcfg.Node, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) {
|
||||
func (e *userspaceEngine) sendTSMPPing(ip netip.Addr, peer tailcfg.NodeView, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) {
|
||||
srcIP, err := e.mySelfIPMatchingFamily(ip)
|
||||
if err != nil {
|
||||
res.Err = err.Error()
|
||||
@@ -1337,7 +1337,7 @@ func (e *userspaceEngine) sendTSMPPing(ip netip.Addr, peer *tailcfg.Node, res *i
|
||||
d := time.Since(t0)
|
||||
res.LatencySeconds = d.Seconds()
|
||||
res.NodeIP = ip.String()
|
||||
res.NodeName = peer.ComputedName
|
||||
res.NodeName = peer.ComputedName()
|
||||
res.PeerAPIPort = pong.PeerAPIPort
|
||||
cb(res)
|
||||
})
|
||||
@@ -1436,7 +1436,8 @@ func (e *userspaceEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) {
|
||||
// Check for exact matches before looking for subnet matches.
|
||||
// TODO(bradfitz): add maps for these. on NetworkMap?
|
||||
for _, p := range nm.Peers {
|
||||
for _, a := range p.Addresses {
|
||||
for i := range p.Addresses().LenIter() {
|
||||
a := p.Addresses().At(i)
|
||||
if a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
|
||||
return PeerForIP{Node: p, Route: a}, true
|
||||
}
|
||||
@@ -1444,7 +1445,7 @@ func (e *userspaceEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) {
|
||||
}
|
||||
for _, a := range nm.Addresses {
|
||||
if a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) {
|
||||
return PeerForIP{Node: nm.SelfNode, IsSelf: true, Route: a}, true
|
||||
return PeerForIP{Node: nm.SelfNode.View(), IsSelf: true, Route: a}, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1469,7 +1470,7 @@ func (e *userspaceEngine) PeerForIP(ip netip.Addr) (ret PeerForIP, ok bool) {
|
||||
// call. But TODO(bradfitz): add a lookup map to netmap.NetworkMap.
|
||||
if !bestKey.IsZero() {
|
||||
for _, p := range nm.Peers {
|
||||
if p.Key == bestKey {
|
||||
if p.Key() == bestKey {
|
||||
return PeerForIP{Node: p, Route: best}, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,14 @@ func TestNoteReceiveActivity(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func nodeViews(v []*tailcfg.Node) []tailcfg.NodeView {
|
||||
nv := make([]tailcfg.NodeView, len(v))
|
||||
for i, n := range v {
|
||||
nv[i] = n.View()
|
||||
}
|
||||
return nv
|
||||
}
|
||||
|
||||
func TestUserspaceEngineReconfig(t *testing.T) {
|
||||
e, err := NewFakeUserspaceEngine(t.Logf, 0)
|
||||
if err != nil {
|
||||
@@ -99,11 +107,11 @@ func TestUserspaceEngineReconfig(t *testing.T) {
|
||||
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
} {
|
||||
nm := &netmap.NetworkMap{
|
||||
Peers: []*tailcfg.Node{
|
||||
Peers: nodeViews([]*tailcfg.Node{
|
||||
{
|
||||
Key: nkFromHex(nodeHex),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
nk, err := key.ParseNodePublicUntyped(mem.S(nodeHex))
|
||||
if err != nil {
|
||||
|
||||
@@ -19,30 +19,31 @@ import (
|
||||
"tailscale.com/wgengine/wgcfg"
|
||||
)
|
||||
|
||||
func nodeDebugName(n *tailcfg.Node) string {
|
||||
name := n.Name
|
||||
func nodeDebugName(n tailcfg.NodeView) string {
|
||||
name := n.Name()
|
||||
if name == "" {
|
||||
name = n.Hostinfo.Hostname()
|
||||
name = n.Hostinfo().Hostname()
|
||||
}
|
||||
if i := strings.Index(name, "."); i != -1 {
|
||||
name = name[:i]
|
||||
}
|
||||
if name == "" && len(n.Addresses) != 0 {
|
||||
return n.Addresses[0].String()
|
||||
if name == "" && n.Addresses().Len() != 0 {
|
||||
return n.Addresses().At(0).String()
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// cidrIsSubnet reports whether cidr is a non-default-route subnet
|
||||
// exported by node that is not one of its own self addresses.
|
||||
func cidrIsSubnet(node *tailcfg.Node, cidr netip.Prefix) bool {
|
||||
func cidrIsSubnet(node tailcfg.NodeView, cidr netip.Prefix) bool {
|
||||
if cidr.Bits() == 0 {
|
||||
return false
|
||||
}
|
||||
if !cidr.IsSingleIP() {
|
||||
return true
|
||||
}
|
||||
for _, selfCIDR := range node.Addresses {
|
||||
for i := range node.Addresses().LenIter() {
|
||||
selfCIDR := node.Addresses().At(i)
|
||||
if cidr == selfCIDR {
|
||||
return false
|
||||
}
|
||||
@@ -85,22 +86,23 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
|
||||
skippedSubnets := new(bytes.Buffer)
|
||||
|
||||
for _, peer := range nm.Peers {
|
||||
if peer.DiscoKey.IsZero() && peer.DERP == "" && !peer.IsWireGuardOnly {
|
||||
if peer.DiscoKey().IsZero() && peer.DERP() == "" && !peer.IsWireGuardOnly() {
|
||||
// Peer predates both DERP and active discovery, we cannot
|
||||
// communicate with it.
|
||||
logf("[v1] wgcfg: skipped peer %s, doesn't offer DERP or disco", peer.Key.ShortString())
|
||||
logf("[v1] wgcfg: skipped peer %s, doesn't offer DERP or disco", peer.Key().ShortString())
|
||||
continue
|
||||
}
|
||||
cfg.Peers = append(cfg.Peers, wgcfg.Peer{
|
||||
PublicKey: peer.Key,
|
||||
DiscoKey: peer.DiscoKey,
|
||||
PublicKey: peer.Key(),
|
||||
DiscoKey: peer.DiscoKey(),
|
||||
})
|
||||
cpeer := &cfg.Peers[len(cfg.Peers)-1]
|
||||
|
||||
didExitNodeWarn := false
|
||||
cpeer.V4MasqAddr = peer.SelfNodeV4MasqAddrForThisPeer
|
||||
for _, allowedIP := range peer.AllowedIPs {
|
||||
if allowedIP.Bits() == 0 && peer.StableID != exitNode {
|
||||
cpeer.V4MasqAddr = peer.SelfNodeV4MasqAddrForThisPeer()
|
||||
for i := range peer.AllowedIPs().LenIter() {
|
||||
allowedIP := peer.AllowedIPs().At(i)
|
||||
if allowedIP.Bits() == 0 && peer.StableID() != exitNode {
|
||||
if didExitNodeWarn {
|
||||
// Don't log about both the IPv4 /0 and IPv6 /0.
|
||||
continue
|
||||
@@ -109,20 +111,20 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
|
||||
if skippedUnselected.Len() > 0 {
|
||||
skippedUnselected.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(skippedUnselected, "%q (%v)", nodeDebugName(peer), peer.Key.ShortString())
|
||||
fmt.Fprintf(skippedUnselected, "%q (%v)", nodeDebugName(peer), peer.Key().ShortString())
|
||||
continue
|
||||
} else if allowedIP.IsSingleIP() && tsaddr.IsTailscaleIP(allowedIP.Addr()) && (flags&netmap.AllowSingleHosts) == 0 {
|
||||
if skippedIPs.Len() > 0 {
|
||||
skippedIPs.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(skippedIPs, "%v from %q (%v)", allowedIP.Addr(), nodeDebugName(peer), peer.Key.ShortString())
|
||||
fmt.Fprintf(skippedIPs, "%v from %q (%v)", allowedIP.Addr(), nodeDebugName(peer), peer.Key().ShortString())
|
||||
continue
|
||||
} else if cidrIsSubnet(peer, allowedIP) {
|
||||
if (flags & netmap.AllowSubnetRoutes) == 0 {
|
||||
if skippedSubnets.Len() > 0 {
|
||||
skippedSubnets.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(skippedSubnets, "%v from %q (%v)", allowedIP, nodeDebugName(peer), peer.Key.ShortString())
|
||||
fmt.Fprintf(skippedSubnets, "%v from %q (%v)", allowedIP, nodeDebugName(peer), peer.Key().ShortString())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,9 @@ var ErrNoChanges = errors.New("no changes made to Engine config")
|
||||
|
||||
// PeerForIP is the type returned by Engine.PeerForIP.
|
||||
type PeerForIP struct {
|
||||
// Node is the matched node. It's always non-nil when
|
||||
// Node is the matched node. It's always a valid value when
|
||||
// Engine.PeerForIP returns ok==true.
|
||||
Node *tailcfg.Node
|
||||
Node tailcfg.NodeView
|
||||
|
||||
// IsSelf is whether the Node is the local process.
|
||||
IsSelf bool
|
||||
|
||||
Reference in New Issue
Block a user