wgengine/magicsock: fix panic when rebinding fails

We would replace the existing real implementation of nettype.PacketConn
with a blockForeverConn, but that violates the contract of atomic.Value
(where the type cannot change). Fix by switching to a pointer value
(atomic.Pointer[nettype.PacketConn]).

A longstanding issue, but became more prevalent when we started binding
connections to interfaces on macOS and iOS (#6566), which could lead to
the bind call failing if the interface was no longer available.

Fixes #6641

Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This commit is contained in:
Mihai Parparita
2022-12-06 17:42:40 -08:00
committed by Mihai Parparita
parent e27f4f022e
commit bdc45b9066
2 changed files with 29 additions and 21 deletions
+13
View File
@@ -1803,3 +1803,16 @@ func TestDiscoMagicMatches(t *testing.T) {
t.Errorf("last 2 bytes of disco magic don't match, got %v want %v", discoMagic2, m2)
}
}
func TestRebindingUDPConn(t *testing.T) {
// Test that RebindingUDPConn can be re-bound to different connection
// types.
c := RebindingUDPConn{}
realConn, err := net.ListenPacket("udp4", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer realConn.Close()
c.setConnLocked(realConn.(nettype.PacketConn))
c.setConnLocked(newBlockForeverConn())
}