mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-07 08:07:42 +00:00
wgengine/monitor: add Windows linkchange monitor
Updates tailscale/corp#553 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
85c3d17b3c
commit
dbb4c246fa
@ -43,7 +43,8 @@ func Tailscale() (net.IP, *net.Interface, error) {
|
|||||||
// maybeTailscaleInterfaceName reports whether s is an interface
|
// maybeTailscaleInterfaceName reports whether s is an interface
|
||||||
// name that might be used by Tailscale.
|
// name that might be used by Tailscale.
|
||||||
func maybeTailscaleInterfaceName(s string) bool {
|
func maybeTailscaleInterfaceName(s string) bool {
|
||||||
return strings.HasPrefix(s, "wg") ||
|
return s == "Tailscale" ||
|
||||||
|
strings.HasPrefix(s, "wg") ||
|
||||||
strings.HasPrefix(s, "ts") ||
|
strings.HasPrefix(s, "ts") ||
|
||||||
strings.HasPrefix(s, "tailscale") ||
|
strings.HasPrefix(s, "tailscale") ||
|
||||||
strings.HasPrefix(s, "utun")
|
strings.HasPrefix(s, "utun")
|
||||||
@ -179,7 +180,8 @@ func (s *State) Equal(s2 *State) bool {
|
|||||||
// /^tailscale/)
|
// /^tailscale/)
|
||||||
func (s *State) RemoveTailscaleInterfaces() {
|
func (s *State) RemoveTailscaleInterfaces() {
|
||||||
for name := range s.InterfaceIPs {
|
for name := range s.InterfaceIPs {
|
||||||
if strings.HasPrefix(name, "tailscale") { // TODO: use --tun flag value, etc; see TODO in method doc
|
if name == "Tailscale" || // as it is on Windows
|
||||||
|
strings.HasPrefix(name, "tailscale") { // TODO: use --tun flag value, etc; see TODO in method doc
|
||||||
delete(s.InterfaceIPs, name)
|
delete(s.InterfaceIPs, name)
|
||||||
delete(s.InterfaceUp, name)
|
delete(s.InterfaceUp, name)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !linux,!freebsd android
|
// +build !linux,!freebsd,!windows android
|
||||||
|
|
||||||
package monitor
|
package monitor
|
||||||
|
|
||||||
|
131
wgengine/monitor/monitor_windows.go
Normal file
131
wgengine/monitor/monitor_windows.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package monitor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"tailscale.com/types/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
iphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
|
||||||
|
notifyAddrChangeProc = iphlpapi.NewProc("NotifyAddrChange")
|
||||||
|
notifyRouteChangeProc = iphlpapi.NewProc("NotifyRouteChange")
|
||||||
|
)
|
||||||
|
|
||||||
|
type unspecifiedMessage struct{}
|
||||||
|
|
||||||
|
func (unspecifiedMessage) ignore() bool { return false }
|
||||||
|
|
||||||
|
type winMon struct {
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
|
||||||
|
logf logger.Logf
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
event windows.Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOSMon(logf logger.Logf) (osMon, error) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
return &winMon{
|
||||||
|
logf: logf,
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *winMon) Close() error {
|
||||||
|
m.cancel()
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
if h := m.event; h != 0 {
|
||||||
|
// Wake up any reader blocked in Receive.
|
||||||
|
windows.SetEvent(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errClosed = errors.New("closed")
|
||||||
|
|
||||||
|
func (m *winMon) Receive() (message, error) {
|
||||||
|
if m.ctx.Err() != nil {
|
||||||
|
return nil, errClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
var o windows.Overlapped
|
||||||
|
h, err := windows.CreateEvent(nil, 1 /* true*/, 0 /* unsignaled */, nil /* no name */)
|
||||||
|
if err != nil {
|
||||||
|
m.logf("CreateEvent: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer windows.CloseHandle(h)
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
m.event = h
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
o.HEvent = h
|
||||||
|
|
||||||
|
err = notifyAddrChange(&h, &o)
|
||||||
|
if err != nil {
|
||||||
|
m.logf("notifyAddrChange: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = notifyRouteChange(&h, &o)
|
||||||
|
if err != nil {
|
||||||
|
m.logf("notifyRouteChange: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t0 := time.Now()
|
||||||
|
evt, err := windows.WaitForSingleObject(o.HEvent, windows.INFINITE)
|
||||||
|
if m.ctx.Err() != nil {
|
||||||
|
return nil, errClosed
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
m.logf("notifyRouteChange: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d := time.Since(t0)
|
||||||
|
m.logf("got windows change event after %v: %+v", d, evt)
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
m.event = 0
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
return unspecifiedMessage{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyAddrChange(h *windows.Handle, o *windows.Overlapped) error {
|
||||||
|
return callNotifyProc(notifyAddrChangeProc, h, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyRouteChange(h *windows.Handle, o *windows.Overlapped) error {
|
||||||
|
return callNotifyProc(notifyAddrChangeProc, h, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func callNotifyProc(p *syscall.LazyProc, h *windows.Handle, o *windows.Overlapped) error {
|
||||||
|
r1, _, e1 := p.Call(uintptr(unsafe.Pointer(h)), uintptr(unsafe.Pointer(o)))
|
||||||
|
expect := uintptr(0)
|
||||||
|
if h != nil || o != nil {
|
||||||
|
const ERROR_IO_PENDING = 997
|
||||||
|
expect = ERROR_IO_PENDING
|
||||||
|
}
|
||||||
|
if r1 == expect {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e1
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user