aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvery Pennarun <apenwarr@tailscale.com>2019-11-06 00:28:02 -0800
committerDavid Crawshaw <david@zentus.com>2020-04-02 14:40:52 +1100
commit98b3828351a135e6a1e9cf51501e704c8a5e1d6e (patch)
treea99c7fd49d95db30913c0925a94325d02ed572a3
parentdevice: give handshake state a type (diff)
downloadwireguard-go-98b3828351a135e6a1e9cf51501e704c8a5e1d6e.tar.xz
wireguard-go-98b3828351a135e6a1e9cf51501e704c8a5e1d6e.zip
tun: NetlinkListener: don't send EventDown before sending EventUp
This works around a startup race condition when competing with HackListener, which is trying to do the same job. If HackListener detects that the tundev is running while there is still an event in the netlink queue that says it isn't running, then the device receives a string of events like EventUp (HackListener) EventDown (NetlinkListener) EventUp (NetlinkListener) Unfortunately, after the first EventDown, the device stops itself, thinking incorrectly that the administrator has downed its tundev. The device is ignoring the initial EventDown anyway, so just don't emit it. Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
-rw-r--r--tun/tun_linux.go14
1 files changed, 13 insertions, 1 deletions
diff --git a/tun/tun_linux.go b/tun/tun_linux.go
index 2f97ebb..1e44b59 100644
--- a/tun/tun_linux.go
+++ b/tun/tun_linux.go
@@ -66,14 +66,19 @@ func (tun *NativeTun) routineHackListener() {
}
switch err {
case unix.EINVAL:
+ // If the tunnel is up, it reports that write() is
+ // allowed but we provided invalid data.
tun.events <- EventUp
case unix.EIO:
+ // If the tunnel is down, it reports that no I/O
+ // is possible, without checking our provided data.
tun.events <- EventDown
default:
return
}
select {
case <-time.After(time.Second):
+ // nothing
case <-tun.statusListenersShutdown:
return
}
@@ -128,6 +133,7 @@ func (tun *NativeTun) routineNetlinkListener() {
default:
}
+ wasEverUp := false
for remain := msg[:msgn]; len(remain) >= unix.SizeofNlMsghdr; {
hdr := *(*unix.NlMsghdr)(unsafe.Pointer(&remain[0]))
@@ -151,10 +157,16 @@ func (tun *NativeTun) routineNetlinkListener() {
if info.Flags&unix.IFF_RUNNING != 0 {
tun.events <- EventUp
+ wasEverUp = true
}
if info.Flags&unix.IFF_RUNNING == 0 {
- tun.events <- EventDown
+ // Don't emit EventDown before we've ever emitted EventUp.
+ // This avoids a startup race with HackListener, which
+ // might detect Up before we have finished reporting Down.
+ if wasEverUp {
+ tun.events <- EventDown
+ }
}
tun.events <- EventMTUUpdate