wgengine/netstack: check userspace ping success on Windows

Hacky temporary workaround until we do #13654 correctly.

Updates #13654

Change-Id: I764eaedbb112fb3a34dddb89572fec1b2543fd4a
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-10-02 10:01:46 -07:00
committed by Brad Fitzpatrick
parent 1f8eea53a8
commit 5f88b65764
3 changed files with 118 additions and 1 deletions

View File

@@ -5,6 +5,7 @@
package netstack
import (
"bytes"
"context"
"errors"
"expvar"
@@ -1909,3 +1910,35 @@ func (ns *Impl) ExpVar() expvar.Var {
return m
}
// windowsPingOutputIsSuccess reports whether the ping.exe output b contains a
// success ping response for ip.
//
// See https://github.com/tailscale/tailscale/issues/13654
//
// TODO(bradfitz,nickkhyl): delete this and use the proper Windows APIs.
func windowsPingOutputIsSuccess(ip netip.Addr, b []byte) bool {
// Look for a line that contains " <ip>: " and then three equal signs.
// As a special case, the 2nd equal sign may be a '<' character
// for sub-millisecond pings.
// This heuristic seems to match the ping.exe output in any language.
sub := fmt.Appendf(nil, " %s: ", ip)
eqSigns := func(bb []byte) (n int) {
for _, b := range bb {
if b == '=' || (b == '<' && n == 1) {
n++
}
}
return
}
for len(b) > 0 {
var line []byte
line, b, _ = bytes.Cut(b, []byte("\n"))
if _, rest, ok := bytes.Cut(line, sub); ok && eqSigns(rest) == 3 {
return true
}
}
return false
}