ipn/ipnlocal: clear magicsock's netmap on logout

magicsock was hanging onto its netmap on logout,
which caused tailscale status to display partial
information about a bunch of zombie peers.
After logout, there should be no peers.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
pull/3577/head
Josh Bleecher Snyder 3 years ago committed by Josh Bleecher Snyder
parent 84a1106fa7
commit 93ae11105d

@ -536,6 +536,7 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) {
// Since st.NetMap==nil means "netmap is unchanged", there is
// no other way to represent this change.
b.setNetMapLocked(nil)
b.e.SetNetworkMap(new(netmap.NetworkMap))
}
prefs := b.prefs

@ -409,6 +409,56 @@ func TestOneNodeUpWindowsStyle(t *testing.T) {
d1.MustCleanShutdown(t)
}
func TestLogoutRemovesAllPeers(t *testing.T) {
t.Parallel()
env := newTestEnv(t)
// Spin up some nodes.
nodes := make([]*testNode, 2)
for i := range nodes {
nodes[i] = newTestNode(t, env)
nodes[i].StartDaemon(t)
nodes[i].AwaitResponding(t)
nodes[i].MustUp()
nodes[i].AwaitIP(t)
nodes[i].AwaitRunning(t)
}
// Make every node ping every other node.
// This makes sure magicsock is fully populated.
for i := range nodes {
for j := range nodes {
if i <= j {
continue
}
if err := tstest.WaitFor(20*time.Second, func() error {
return nodes[i].Ping(nodes[j])
}); err != nil {
t.Fatalf("ping %v -> %v: %v", nodes[i].AwaitIP(t), nodes[j].AwaitIP(t), err)
}
}
}
// wantNode0PeerCount waits until node[0] status includes exactly want peers.
wantNode0PeerCount := func(want int) {
if err := tstest.WaitFor(20*time.Second, func() error {
s := nodes[0].MustStatus(t)
if peers := s.Peers(); len(peers) != want {
return fmt.Errorf("want %d peer(s) in status, got %v", want, peers)
}
return nil
}); err != nil {
t.Fatal(err)
}
}
wantNode0PeerCount(len(nodes) - 1) // all other nodes are peers
nodes[0].MustLogOut()
wantNode0PeerCount(0) // node[0] is logged out, so it should not have any peers
nodes[0].MustUp()
nodes[0].AwaitIP(t)
wantNode0PeerCount(len(nodes) - 1) // all other nodes are peers again
}
// testEnv contains the test environment (set of servers) used by one
// or more nodes.
type testEnv struct {
@ -703,6 +753,21 @@ func (n *testNode) MustDown() {
}
}
func (n *testNode) MustLogOut() {
t := n.env.t
t.Logf("Running logout ...")
if err := n.Tailscale("logout").Run(); err != nil {
t.Fatalf("logout: %v", err)
}
}
func (n *testNode) Ping(otherNode *testNode) error {
t := n.env.t
ip := otherNode.AwaitIP(t).String()
t.Logf("Running ping %v (from %v)...", ip, n.AwaitIP(t))
return n.Tailscale("ping", ip).Run()
}
// AwaitListening waits for the tailscaled to be serving local clients
// over its localhost IPC mechanism. (Unix socket, etc)
func (n *testNode) AwaitListening(t testing.TB) {

@ -239,13 +239,15 @@ func (ns *Impl) updateIPs(nm *netmap.NetworkMap) {
newIPs := make(map[tcpip.AddressWithPrefix]bool)
isAddr := map[netaddr.IPPrefix]bool{}
for _, ipp := range nm.SelfNode.Addresses {
isAddr[ipp] = true
}
for _, ipp := range nm.SelfNode.AllowedIPs {
local := isAddr[ipp]
if local && ns.ProcessLocalIPs || !local && ns.ProcessSubnets {
newIPs[ipPrefixToAddressWithPrefix(ipp)] = true
if nm.SelfNode != nil {
for _, ipp := range nm.SelfNode.Addresses {
isAddr[ipp] = true
}
for _, ipp := range nm.SelfNode.AllowedIPs {
local := isAddr[ipp]
if local && ns.ProcessLocalIPs || !local && ns.ProcessSubnets {
newIPs[ipPrefixToAddressWithPrefix(ipp)] = true
}
}
}

Loading…
Cancel
Save