From 9f7683e2a1059889fbeee61795400ef74df220d4 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 25 Aug 2024 20:37:25 -0700 Subject: [PATCH] logpolicy: extend the gokrazy/natlab wait-for-network delay for IPv6 Really we need to fix logpolicy + bootstrapDNS to not be so aggressive, but this is a quick workaround meanwhile. Without this, tailscaled starts immediately while IPv6 DAD is happening for a couple seconds and logpolicy freaks out without the network available and starts spamming stderr about bootstrap DNS options. But we see that regularly anyway from people whose wifi is down. So we need to fix the general case. This is not that fix. Updates #13038 Change-Id: Iba7e536d08e59d34abded1d279f88fdc9c46d94d Signed-off-by: Brad Fitzpatrick --- logpolicy/logpolicy.go | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index f40ede86a..9e00a3ad4 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -18,6 +18,7 @@ import ( "log" "net" "net/http" + "net/netip" "net/url" "os" "os/exec" @@ -835,7 +836,19 @@ func awaitGokrazyNetwork() { // Before DHCP finishes, the /etc/resolv.conf file has just "#MANUAL". all, _ := os.ReadFile("/etc/resolv.conf") if bytes.Contains(all, []byte("nameserver ")) { - return + good := true + firstLine, _, ok := strings.Cut(string(all), "\n") + if ok { + ns, ok := strings.CutPrefix(firstLine, "nameserver ") + if ok { + if ip, err := netip.ParseAddr(ns); err == nil && ip.Is6() && !ip.IsLinkLocalUnicast() { + good = haveGlobalUnicastIPv6() + } + } + } + if good { + return + } } select { case <-ctx.Done(): @@ -844,3 +857,27 @@ func awaitGokrazyNetwork() { } } } + +// haveGlobalUnicastIPv6 reports whether the machine has a IPv6 non-private +// (non-ULA) global unicast address. +// +// It's only intended for use in natlab integration tests so only works on +// Linux/macOS now and not environments (such as Android) where net.Interfaces +// doesn't work directly. +func haveGlobalUnicastIPv6() bool { + ifs, _ := net.Interfaces() + for _, ni := range ifs { + aa, _ := ni.Addrs() + for _, a := range aa { + ipn, ok := a.(*net.IPNet) + if !ok { + continue + } + ip, _ := netip.AddrFromSlice(ipn.IP) + if ip.Is6() && ip.IsGlobalUnicast() && !ip.IsPrivate() { + return true + } + } + } + return false +}