From 0d991249e1330541ba8b25e221d0678a4b82db04 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 18 Sep 2023 07:31:34 +0100 Subject: [PATCH] types/netmap: remove NetworkMap.{Addresses,MachineStatus} And convert all callers over to the methods that check SelfNode. Now we don't have multiple ways to express things in tests (setting fields on SelfNode vs NetworkMap, sometimes inconsistently) and don't have multiple ways to check those two fields (often only checking one or the other). Updates #9443 Change-Id: I2d7ba1cf6556142d219fae2be6f484f528756e3c Signed-off-by: Brad Fitzpatrick --- cmd/tsconnect/wasm/wasm_js.go | 11 +++++- control/controlclient/map.go | 6 ---- ipn/ipnlocal/dnsconfig_test.go | 18 ++++++---- ipn/ipnlocal/local.go | 14 ++++---- ipn/ipnlocal/local_test.go | 51 ++++++++++++++++------------ ipn/ipnlocal/state_test.go | 20 +++++------ net/tsaddr/tsaddr.go | 28 ++++++++------- net/tsaddr/tsaddr_test.go | 13 +++---- net/tsdial/dnsmap_test.go | 28 +++++++++------ types/netmap/netmap.go | 44 +++--------------------- wgengine/magicsock/magicsock_test.go | 16 ++++++--- wgengine/netstack/netstack.go | 6 ++-- wgengine/userspace.go | 29 +++++++++------- wgengine/wgcfg/nmcfg/nmcfg.go | 2 +- 14 files changed, 146 insertions(+), 140 deletions(-) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 9556fe043..bdcd749fe 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -37,6 +37,7 @@ import ( "tailscale.com/safesocket" "tailscale.com/tailcfg" "tailscale.com/tsd" + "tailscale.com/types/views" "tailscale.com/wgengine" "tailscale.com/wgengine/netstack" "tailscale.com/words" @@ -249,7 +250,7 @@ func (i *jsIPN) run(jsCallbacks js.Value) { Self: jsNetMapSelfNode{ jsNetMapNode: jsNetMapNode{ Name: nm.Name, - Addresses: mapSlice(nm.Addresses, func(a netip.Prefix) string { return a.Addr().String() }), + Addresses: mapSliceView(nm.GetAddresses(), func(a netip.Prefix) string { return a.Addr().String() }), NodeKey: nm.NodeKey.String(), MachineKey: nm.MachineKey.String(), }, @@ -578,6 +579,14 @@ func mapSlice[T any, M any](a []T, f func(T) M) []M { return n } +func mapSliceView[T any, M any](a views.Slice[T], f func(T) M) []M { + n := make([]M, a.Len()) + for i := range a.LenIter() { + n[i] = f(a.At(i)) + } + return n +} + func filterSlice[T any](a []T, f func(T) bool) []T { n := make([]T, 0, len(a)) for _, e := range a { diff --git a/control/controlclient/map.go b/control/controlclient/map.go index 136ac5003..7a71dd29f 100644 --- a/control/controlclient/map.go +++ b/control/controlclient/map.go @@ -752,12 +752,6 @@ func (ms *mapSession) netmap() *netmap.NetworkMap { nm.SelfNode = node nm.Expiry = node.KeyExpiry() nm.Name = node.Name() - nm.Addresses = filterSelfAddresses(node.Addresses().AsSlice()) - if node.MachineAuthorized() { - nm.MachineStatus = tailcfg.MachineAuthorized - } else { - nm.MachineStatus = tailcfg.MachineUnauthorized - } } ms.addUserProfile(nm, nm.User()) diff --git a/ipn/ipnlocal/dnsconfig_test.go b/ipn/ipnlocal/dnsconfig_test.go index 944ea7252..dbb40cd76 100644 --- a/ipn/ipnlocal/dnsconfig_test.go +++ b/ipn/ipnlocal/dnsconfig_test.go @@ -69,8 +69,10 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "self_name_and_peers", nm: &netmap.NetworkMap{ - Name: "myname.net", - Addresses: ipps("100.101.101.101"), + Name: "myname.net", + SelfNode: (&tailcfg.Node{ + Addresses: ipps("100.101.101.101"), + }).View(), }, peers: nodeViews([]*tailcfg.Node{ { @@ -106,8 +108,10 @@ func TestDNSConfigForNetmap(t *testing.T) { // even if they have IPv4. name: "v6_only_self", nm: &netmap.NetworkMap{ - Name: "myname.net", - Addresses: ipps("fe75::1"), + Name: "myname.net", + SelfNode: (&tailcfg.Node{ + Addresses: ipps("fe75::1"), + }).View(), }, peers: nodeViews([]*tailcfg.Node{ { @@ -141,8 +145,10 @@ func TestDNSConfigForNetmap(t *testing.T) { { name: "extra_records", nm: &netmap.NetworkMap{ - Name: "myname.net", - Addresses: ipps("100.101.101.101"), + Name: "myname.net", + SelfNode: (&tailcfg.Node{ + Addresses: ipps("100.101.101.101"), + }).View(), DNS: tailcfg.DNSConfig{ ExtraRecords: []tailcfg.DNSRecord{ {Name: "foo.com", Value: "1.2.3.4"}, diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index ab22c8c8f..d2000c6ac 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -2411,13 +2411,13 @@ func (b *LocalBackend) setAtomicValuesFromPrefsLocked(p ipn.PrefsView) { b.sshAtomicBool.Store(p.Valid() && p.RunSSH() && envknob.CanSSHD()) if !p.Valid() { - b.containsViaIPFuncAtomic.Store(tsaddr.NewContainsIPFunc(nil)) + b.containsViaIPFuncAtomic.Store(tsaddr.FalseContainsIPFunc()) b.setTCPPortsIntercepted(nil) b.lastServeConfJSON = mem.B(nil) b.serveConfig = ipn.ServeConfigView{} } else { filtered := tsaddr.FilterPrefixesCopy(p.AdvertiseRoutes(), tsaddr.IsViaPrefix) - b.containsViaIPFuncAtomic.Store(tsaddr.NewContainsIPFunc(filtered)) + b.containsViaIPFuncAtomic.Store(tsaddr.NewContainsIPFunc(views.SliceOf(filtered))) b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(p) } } @@ -3211,8 +3211,8 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg. } // selfV6Only is whether we only have IPv6 addresses ourselves. - selfV6Only := slices.ContainsFunc(nm.Addresses, tsaddr.PrefixIs6) && - !slices.ContainsFunc(nm.Addresses, tsaddr.PrefixIs4) + selfV6Only := views.SliceContainsFunc(nm.GetAddresses(), tsaddr.PrefixIs6) && + !views.SliceContainsFunc(nm.GetAddresses(), tsaddr.PrefixIs4) dcfg.OnlyIPv6 = selfV6Only // Populate MagicDNS records. We do this unconditionally so that @@ -3259,7 +3259,7 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg. } dcfg.Hosts[fqdn] = ips } - set(nm.Name, views.SliceOf(nm.Addresses)) + set(nm.Name, nm.GetAddresses()) for _, peer := range peers { set(peer.Name(), peer.Addresses()) } @@ -4595,7 +4595,9 @@ func peerAPIBase(nm *netmap.NetworkMap, peer tailcfg.NodeView) string { } var have4, have6 bool - for _, a := range nm.Addresses { + addrs := nm.GetAddresses() + for i := range addrs.LenIter() { + a := addrs.At(i) if !a.IsSingleIP() { continue } diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 7cb7a2ea6..a55b6f638 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -279,9 +279,11 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_only_4_them_both", nm: &netmap.NetworkMap{ - Addresses: []netip.Prefix{ - netip.MustParsePrefix("100.64.1.1/32"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + netip.MustParsePrefix("100.64.1.1/32"), + }, + }).View(), }, peer: &tailcfg.Node{ Addresses: []netip.Prefix{ @@ -300,9 +302,11 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_only_6_them_both", nm: &netmap.NetworkMap{ - Addresses: []netip.Prefix{ - netip.MustParsePrefix("fe70::1/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + netip.MustParsePrefix("fe70::1/128"), + }, + }).View(), }, peer: &tailcfg.Node{ Addresses: []netip.Prefix{ @@ -321,10 +325,12 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_only_4", nm: &netmap.NetworkMap{ - Addresses: []netip.Prefix{ - netip.MustParsePrefix("100.64.1.1/32"), - netip.MustParsePrefix("fe70::1/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + netip.MustParsePrefix("100.64.1.1/32"), + netip.MustParsePrefix("fe70::1/128"), + }, + }).View(), }, peer: &tailcfg.Node{ Addresses: []netip.Prefix{ @@ -342,10 +348,12 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_only_6", nm: &netmap.NetworkMap{ - Addresses: []netip.Prefix{ - netip.MustParsePrefix("100.64.1.1/32"), - netip.MustParsePrefix("fe70::1/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + netip.MustParsePrefix("100.64.1.1/32"), + netip.MustParsePrefix("fe70::1/128"), + }, + }).View(), }, peer: &tailcfg.Node{ Addresses: []netip.Prefix{ @@ -363,10 +371,12 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_no_peerapi_service", nm: &netmap.NetworkMap{ - Addresses: []netip.Prefix{ - netip.MustParsePrefix("100.64.1.1/32"), - netip.MustParsePrefix("fe70::1/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + netip.MustParsePrefix("100.64.1.1/32"), + netip.MustParsePrefix("fe70::1/128"), + }, + }).View(), }, peer: &tailcfg.Node{ Addresses: []netip.Prefix{ @@ -689,10 +699,9 @@ func TestStatusWithoutPeers(t *testing.T) { b.Start(ipn.Options{}) b.Login(nil) cc.send(nil, "", false, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, - Addresses: ipps("100.101.101.101"), SelfNode: (&tailcfg.Node{ - Addresses: ipps("100.101.101.101"), + MachineAuthorized: true, + Addresses: ipps("100.101.101.101"), }).View(), }) got := b.StatusWithoutPeers() diff --git a/ipn/ipnlocal/state_test.go b/ipn/ipnlocal/state_test.go index 53c94ee6f..193c43909 100644 --- a/ipn/ipnlocal/state_test.go +++ b/ipn/ipnlocal/state_test.go @@ -501,7 +501,7 @@ func TestStateMachine(t *testing.T) { // (ie. I suspect it would be better to change false->true in send() // below, and do the same in the real controlclient.) cc.send(nil, "", false, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(1) @@ -665,7 +665,7 @@ func TestStateMachine(t *testing.T) { cc.persist.UserProfile.LoginName = "user2" cc.persist.NodeID = "node2" cc.send(nil, "", true, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(3) @@ -732,7 +732,7 @@ func TestStateMachine(t *testing.T) { t.Logf("\n\nStart4 -> netmap") notifies.expect(0) cc.send(nil, "", true, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { notifies.drain(0) @@ -801,7 +801,7 @@ func TestStateMachine(t *testing.T) { cc.persist.UserProfile.LoginName = "user3" cc.persist.NodeID = "node3" cc.send(nil, "", true, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(3) @@ -845,7 +845,7 @@ func TestStateMachine(t *testing.T) { t.Logf("\n\nLoginFinished5") notifies.expect(2) cc.send(nil, "", true, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(2) @@ -862,8 +862,8 @@ func TestStateMachine(t *testing.T) { t.Logf("\n\nExpireKey") notifies.expect(1) cc.send(nil, "", false, &netmap.NetworkMap{ - Expiry: time.Now().Add(-time.Minute), - MachineStatus: tailcfg.MachineAuthorized, + Expiry: time.Now().Add(-time.Minute), + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(1) @@ -877,8 +877,8 @@ func TestStateMachine(t *testing.T) { t.Logf("\n\nExtendKey") notifies.expect(1) cc.send(nil, "", false, &netmap.NetworkMap{ - Expiry: time.Now().Add(time.Minute), - MachineStatus: tailcfg.MachineAuthorized, + Expiry: time.Now().Add(time.Minute), + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) { nn := notifies.drain(1) @@ -1023,7 +1023,7 @@ func TestWGEngineStatusRace(t *testing.T) { // Assert that we are logged in and authorized. cc.send(nil, "", true, &netmap.NetworkMap{ - MachineStatus: tailcfg.MachineAuthorized, + SelfNode: (&tailcfg.Node{MachineAuthorized: true}).View(), }) wantState(ipn.Starting) diff --git a/net/tsaddr/tsaddr.go b/net/tsaddr/tsaddr.go index 6319e30f4..088ff35e1 100644 --- a/net/tsaddr/tsaddr.go +++ b/net/tsaddr/tsaddr.go @@ -161,6 +161,11 @@ type oncePrefix struct { v netip.Prefix } +// FalseContainsIPFunc is shorthand for NewContainsIPFunc(views.Slice[netip.Prefix]{}). +func FalseContainsIPFunc() func(ip netip.Addr) bool { + return func(ip netip.Addr) bool { return false } +} + // NewContainsIPFunc returns a func that reports whether ip is in addrs. // // It's optimized for the cases of addrs being empty and addrs @@ -168,20 +173,17 @@ type oncePrefix struct { // one IPv6 address). // // Otherwise the implementation is somewhat slow. -func NewContainsIPFunc(addrs []netip.Prefix) func(ip netip.Addr) bool { +func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool { // Specialize the three common cases: no address, just IPv4 // (or just IPv6), and both IPv4 and IPv6. - if len(addrs) == 0 { + if addrs.Len() == 0 { return func(netip.Addr) bool { return false } } // If any addr is more than a single IP, then just do the slow // linear thing until // https://github.com/inetaf/netaddr/issues/139 is done. - for _, a := range addrs { - if a.IsSingleIP() { - continue - } - acopy := append([]netip.Prefix(nil), addrs...) + if views.SliceContainsFunc(addrs, func(p netip.Prefix) bool { return !p.IsSingleIP() }) { + acopy := addrs.AsSlice() return func(ip netip.Addr) bool { for _, a := range acopy { if a.Contains(ip) { @@ -192,18 +194,18 @@ func NewContainsIPFunc(addrs []netip.Prefix) func(ip netip.Addr) bool { } } // Fast paths for 1 and 2 IPs: - if len(addrs) == 1 { - a := addrs[0] + if addrs.Len() == 1 { + a := addrs.At(0) return func(ip netip.Addr) bool { return ip == a.Addr() } } - if len(addrs) == 2 { - a, b := addrs[0], addrs[1] + if addrs.Len() == 2 { + a, b := addrs.At(0), addrs.At(1) return func(ip netip.Addr) bool { return ip == a.Addr() || ip == b.Addr() } } // General case: m := map[netip.Addr]bool{} - for _, a := range addrs { - m[a.Addr()] = true + for i := range addrs.LenIter() { + m[addrs.At(i).Addr()] = true } return func(ip netip.Addr) bool { return m[ip] } } diff --git a/net/tsaddr/tsaddr_test.go b/net/tsaddr/tsaddr_test.go index e74502005..7cc1a3881 100644 --- a/net/tsaddr/tsaddr_test.go +++ b/net/tsaddr/tsaddr_test.go @@ -8,6 +8,7 @@ import ( "testing" "tailscale.com/net/netaddr" + "tailscale.com/types/views" ) func TestInCrostiniRange(t *testing.T) { @@ -66,29 +67,29 @@ func TestCGNATRange(t *testing.T) { } func TestNewContainsIPFunc(t *testing.T) { - f := NewContainsIPFunc([]netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")}) + f := NewContainsIPFunc(views.SliceOf([]netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")})) if f(netip.MustParseAddr("8.8.8.8")) { t.Fatal("bad") } if !f(netip.MustParseAddr("10.1.2.3")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netip.Prefix{netip.MustParsePrefix("10.1.2.3/32")}) + f = NewContainsIPFunc(views.SliceOf([]netip.Prefix{netip.MustParsePrefix("10.1.2.3/32")})) if !f(netip.MustParseAddr("10.1.2.3")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netip.Prefix{ + f = NewContainsIPFunc(views.SliceOf([]netip.Prefix{ netip.MustParsePrefix("10.1.2.3/32"), netip.MustParsePrefix("::2/128"), - }) + })) if !f(netip.MustParseAddr("::2")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netip.Prefix{ + f = NewContainsIPFunc(views.SliceOf([]netip.Prefix{ netip.MustParsePrefix("10.1.2.3/32"), netip.MustParsePrefix("10.1.2.4/32"), netip.MustParsePrefix("::2/128"), - }) + })) if !f(netip.MustParseAddr("10.1.2.4")) { t.Fatal("bad") } diff --git a/net/tsdial/dnsmap_test.go b/net/tsdial/dnsmap_test.go index 33eda8b59..43461a135 100644 --- a/net/tsdial/dnsmap_test.go +++ b/net/tsdial/dnsmap_test.go @@ -32,10 +32,12 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netip.Prefix{ - pfx("100.102.103.104/32"), - pfx("100::123/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + pfx("100.102.103.104/32"), + pfx("100::123/128"), + }, + }).View(), }, want: dnsMap{ "foo": ip("100.102.103.104"), @@ -46,10 +48,12 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self_and_peers", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netip.Prefix{ - pfx("100.102.103.104/32"), - pfx("100::123/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + pfx("100.102.103.104/32"), + pfx("100::123/128"), + }, + }).View(), Peers: []tailcfg.NodeView{ (&tailcfg.Node{ Name: "a.tailnet", @@ -79,9 +83,11 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self_has_v6_only", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netip.Prefix{ - pfx("100::123/128"), - }, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{ + pfx("100::123/128"), + }, + }).View(), Peers: nodeViews([]*tailcfg.Node{ { Name: "a.tailnet", diff --git a/types/netmap/netmap.go b/types/netmap/netmap.go index df950401d..a3570ff74 100644 --- a/types/netmap/netmap.go +++ b/types/netmap/netmap.go @@ -33,20 +33,6 @@ type NetworkMap struct { // It is the MapResponse.Node.Name value and ends with a period. Name string - // Addresses is SelfNode.Addresses. (IP addresses of this Node directly) - // - // Deprecated: use GetAddresses instead. As of 2023-09-17, this field - // is being phased out. - Addresses []netip.Prefix - - // MachineStatus is either tailcfg.MachineAuthorized or tailcfg.MachineUnauthorized, - // depending on SelfNode.MachineAuthorized. - // - // Deprecated: use GetMachineStatus instead. This field exists still - // exists (as of 2023-09-13) for some tests in other repos that haven't - // yet been migrated. TODO(bradfitz): remove this field. - MachineStatus tailcfg.MachineStatus - MachineKey key.MachinePublic Peers []tailcfg.NodeView // sorted by Node.ID @@ -104,12 +90,6 @@ func (nm *NetworkMap) User() tailcfg.UserID { // if SelfNode is invalid. func (nm *NetworkMap) GetAddresses() views.Slice[netip.Prefix] { var zero views.Slice[netip.Prefix] - if nm.Addresses != nil { - // For now (2023-09-17), let the deprecated Addressees field take - // precedence. This is a migration mechanism while we update tests & - // code cross-repo. - return views.SliceOf(nm.Addresses) - } if !nm.SelfNode.Valid() { return zero } @@ -128,12 +108,6 @@ func (nm *NetworkMap) AnyPeersAdvertiseRoutes() bool { // GetMachineStatus returns the MachineStatus of the local node. func (nm *NetworkMap) GetMachineStatus() tailcfg.MachineStatus { - if nm.MachineStatus != tailcfg.MachineUnknown { - // For now (2023-09-13), let the deprecated MachineStatus field take - // precedence. This is a migration mechanism while we update tests & - // code cross-repo. - return nm.MachineStatus - } if !nm.SelfNode.Valid() { return tailcfg.MachineUnknown } @@ -258,25 +232,17 @@ func (nm *NetworkMap) printConciseHeader(buf *strings.Builder) { } } fmt.Fprintf(buf, " u=%s", login) - fmt.Fprintf(buf, " %v", nm.Addresses) + fmt.Fprintf(buf, " %v", nm.GetAddresses().AsSlice()) buf.WriteByte('\n') } // equalConciseHeader reports whether a and b are equal for the fields // used by printConciseHeader. func (a *NetworkMap) equalConciseHeader(b *NetworkMap) bool { - if a.NodeKey != b.NodeKey || - a.GetMachineStatus() != b.GetMachineStatus() || - a.User() != b.User() || - len(a.Addresses) != len(b.Addresses) { - return false - } - for i, a := range a.Addresses { - if b.Addresses[i] != a { - return false - } - } - return true + return a.NodeKey == b.NodeKey && + a.GetMachineStatus() == b.GetMachineStatus() && + a.User() == b.User() && + views.SliceEqual(a.GetAddresses(), b.GetAddresses()) } // printPeerConcise appends to buf a line representing the peer p. diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 7700f6ca8..970483f56 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -274,7 +274,9 @@ func meshStacks(logf logger.Logf, mutateNetmap func(idx int, nm *netmap.NetworkM nm := &netmap.NetworkMap{ PrivateKey: me.privateKey, NodeKey: me.privateKey.Public(), - Addresses: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(1, 0, 0, byte(myIdx+1)), 32)}, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(1, 0, 0, byte(myIdx+1)), 32)}, + }).View(), } for i, peer := range ms { if i == myIdx { @@ -2267,7 +2269,9 @@ func TestIsWireGuardOnlyPeer(t *testing.T) { Name: "ts", PrivateKey: m.privateKey, NodeKey: m.privateKey.Public(), - Addresses: []netip.Prefix{tsaip}, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{tsaip}, + }).View(), Peers: nodeViews([]*tailcfg.Node{ { ID: 1, @@ -2326,7 +2330,9 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) { Name: "ts", PrivateKey: m.privateKey, NodeKey: m.privateKey.Public(), - Addresses: []netip.Prefix{tsaip}, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{tsaip}, + }).View(), Peers: nodeViews([]*tailcfg.Node{ { ID: 1, @@ -2453,7 +2459,9 @@ func TestIsWireGuardOnlyPickEndpointByPing(t *testing.T) { Name: "ts", PrivateKey: m.privateKey, NodeKey: m.privateKey.Public(), - Addresses: []netip.Prefix{tsaip}, + SelfNode: (&tailcfg.Node{ + Addresses: []netip.Prefix{tsaip}, + }).View(), Peers: nodeViews([]*tailcfg.Node{ { Key: wgkey.Public(), diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index d0fe23169..e2f930b4c 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -221,7 +221,7 @@ func Create(logf logger.Logf, tundev *tstun.Wrapper, e wgengine.Engine, mc *magi dns: dns, } ns.ctx, ns.ctxCancel = context.WithCancel(context.Background()) - ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nil)) + ns.atomicIsLocalIPFunc.Store(tsaddr.FalseContainsIPFunc()) ns.tundev.PostFilterPacketInboundFromWireGaurd = ns.injectInbound ns.tundev.PreFilterPacketOutboundToWireGuardNetstackIntercept = ns.handleLocalPackets return ns, nil @@ -324,10 +324,10 @@ var v4broadcast = netaddr.IPv4(255, 255, 255, 255) func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) { var selfNode tailcfg.NodeView if nm != nil { - ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nm.Addresses)) + ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nm.GetAddresses())) selfNode = nm.SelfNode } else { - ns.atomicIsLocalIPFunc.Store(tsaddr.NewContainsIPFunc(nil)) + ns.atomicIsLocalIPFunc.Store(tsaddr.FalseContainsIPFunc()) } oldIPs := make(map[tcpip.AddressWithPrefix]bool) diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 8f59b2faf..c90a4b2be 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -286,8 +286,8 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error) return nil, err } } - e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(nil)) - e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(nil)) + e.isLocalAddr.Store(tsaddr.FalseContainsIPFunc()) + e.isDNSIPOverTailscale.Store(tsaddr.FalseContainsIPFunc()) if conf.NetMon != nil { e.netMon = conf.NetMon @@ -782,7 +782,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, panic("dnsCfg must not be nil") } - e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(routerCfg.LocalAddrs)) + e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(views.SliceOf(routerCfg.LocalAddrs))) e.wgLock.Lock() defer e.wgLock.Unlock() @@ -836,7 +836,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config, // instead have ipnlocal populate a map of DNS IP => linkName and // put that in the *dns.Config instead, and plumb it down to the // dns.Manager. Maybe also with isLocalAddr above. - e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(dnsIPsOverTailscale(dnsCfg, routerCfg))) + e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(views.SliceOf(dnsIPsOverTailscale(dnsCfg, routerCfg)))) // See if any peers have changed disco keys, which means they've restarted. // If so, we need to update the wireguard-go/device.Device in two phases: @@ -1205,20 +1205,22 @@ func (e *userspaceEngine) Ping(ip netip.Addr, pingType tailcfg.PingType, size in } func (e *userspaceEngine) mySelfIPMatchingFamily(dst netip.Addr) (src netip.Addr, err error) { + var zero netip.Addr e.mu.Lock() defer e.mu.Unlock() if e.netMap == nil { - return netip.Addr{}, errors.New("no netmap") + return zero, errors.New("no netmap") } - for _, a := range e.netMap.Addresses { - if a.IsSingleIP() && a.Addr().BitLen() == dst.BitLen() { + addrs := e.netMap.GetAddresses() + if addrs.Len() == 0 { + return zero, errors.New("no self address in netmap") + } + for i := range addrs.LenIter() { + if a := addrs.At(i); a.IsSingleIP() && a.Addr().BitLen() == dst.BitLen() { return a.Addr(), nil } } - if len(e.netMap.Addresses) == 0 { - return netip.Addr{}, errors.New("no self address in netmap") - } - return netip.Addr{}, errors.New("no self address in netmap matching address family") + return zero, errors.New("no self address in netmap matching address family") } func (e *userspaceEngine) sendICMPEchoRequest(destIP netip.Addr, peer tailcfg.NodeView, res *ipnstate.PingResult, cb func(*ipnstate.PingResult)) { @@ -1366,8 +1368,9 @@ 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) { + addrs := nm.GetAddresses() + for i := range addrs.LenIter() { + if a := addrs.At(i); a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { return PeerForIP{Node: nm.SelfNode, IsSelf: true, Route: a}, true } } diff --git a/wgengine/wgcfg/nmcfg/nmcfg.go b/wgengine/wgcfg/nmcfg/nmcfg.go index 35ec23304..c64992524 100644 --- a/wgengine/wgcfg/nmcfg/nmcfg.go +++ b/wgengine/wgcfg/nmcfg/nmcfg.go @@ -56,7 +56,7 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags, cfg := &wgcfg.Config{ Name: "tailscale", PrivateKey: nm.PrivateKey, - Addresses: nm.Addresses, + Addresses: nm.GetAddresses().AsSlice(), Peers: make([]wgcfg.Peer, 0, len(nm.Peers)), }