From bba001018f0a8f2fb1c88a6b97adb23690a6512b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 28 Sep 2019 19:20:49 +0200 Subject: tunnel: windows does not always add/remove routes with up/down interface On Linux, we're used to routes being added after an interface is up, and routes being removed as a consequence of an interface going down. On Windows, this isn't always the case, at least not from the perspective of the route notifiers. In order to work around this and make a multi-interface model coherent, we search for a new default route not only whenever the routing table changes but also whenever any interface link parameters change, such as up/down. The practical consequence is that now WireGuard connects properly when wifi is disconnected and then reconnected. Reported-by: Nenad Kozul Signed-off-by: Jason A. Donenfeld --- tunnel/defaultroutemonitor.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'tunnel/defaultroutemonitor.go') diff --git a/tunnel/defaultroutemonitor.go b/tunnel/defaultroutemonitor.go index c1722c45..f9c63e56 100644 --- a/tunnel/defaultroutemonitor.go +++ b/tunnel/defaultroutemonitor.go @@ -7,6 +7,7 @@ package tunnel import ( "log" + "sync" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/device" @@ -29,7 +30,6 @@ func bindSocketRoute(family winipcfg.AddressFamily, device *device.Device, ourLU } ifrow, err := r[i].InterfaceLUID.Interface() if err != nil || ifrow.OperStatus != winipcfg.IfOperStatusUp { - log.Printf("Found default route for interface %d, but not up, so skipping", r[i].InterfaceIndex) continue } if r[i].Metric < lowestMetric { @@ -53,7 +53,7 @@ func bindSocketRoute(family winipcfg.AddressFamily, device *device.Device, ourLU return nil } -func monitorDefaultRoutes(family winipcfg.AddressFamily, device *device.Device, autoMTU bool, tun *tun.NativeTun) (*winipcfg.RouteChangeCallback, error) { +func monitorDefaultRoutes(family winipcfg.AddressFamily, device *device.Device, autoMTU bool, tun *tun.NativeTun) ([]winipcfg.ChangeCallback, error) { var minMTU uint32 if family == windows.AF_INET { minMTU = 576 @@ -64,7 +64,10 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, device *device.Device, lastLUID := winipcfg.LUID(0) lastIndex := uint32(0) lastMTU := uint32(0) + mutex := sync.Mutex{} doIt := func() error { + mutex.Lock() + defer mutex.Unlock() err := bindSocketRoute(family, device, ourLUID, &lastLUID, &lastIndex) if err != nil { return err @@ -104,13 +107,22 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, device *device.Device, if err != nil { return nil, err } - cb, err := winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) { + cbr, err := winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) { if route != nil && route.DestinationPrefix.PrefixLength == 0 { - _ = doIt() + doIt() } }) if err != nil { return nil, err } - return cb, nil + cbi, err := winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) { + if notificationType == winipcfg.MibParameterNotification { + doIt() + } + }) + if err != nil { + cbr.Unregister() + return nil, err + } + return []winipcfg.ChangeCallback{cbr, cbi}, nil } -- cgit v1.2.3-59-g8ed1b