tun: openbsd: check for interface already being up

In some cases, we operate on an already-up interface, or the user brings
up the interface before we start monitoring. For those situations, we
should first check if the interface is already up.

This still technically races between the initial check and the start of
the route loop, but fixing that is a bit ugly and probably not worth it
at the moment.

Reported-by: Theo Buehler <tb@theobuehler.org>
This commit is contained in:
Jason A. Donenfeld 2019-09-07 00:02:07 -05:00
parent d12eb91f9a
commit 4cd06c0925

View file

@ -42,34 +42,11 @@ func (tun *NativeTun) routineRouteListener(tunIfindex int) {
defer close(tun.events) defer close(tun.events)
data := make([]byte, os.Getpagesize()) check := func() bool {
for { iface, err := net.InterfaceByIndex(tunIfindex)
retry:
n, err := unix.Read(tun.routeSocket, data)
if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto retry
}
tun.errors <- err
return
}
if n < 8 {
continue
}
if data[3 /* type */] != unix.RTM_IFINFO {
continue
}
ifindex := int(*(*uint16)(unsafe.Pointer(&data[6 /* ifindex */])))
if ifindex != tunIfindex {
continue
}
iface, err := net.InterfaceByIndex(ifindex)
if err != nil { if err != nil {
tun.errors <- err tun.errors <- err
return return true
} }
// Up / Down event // Up / Down event
@ -87,6 +64,38 @@ func (tun *NativeTun) routineRouteListener(tunIfindex int) {
tun.events <- EventMTUUpdate tun.events <- EventMTUUpdate
} }
statusMTU = iface.MTU statusMTU = iface.MTU
return false
}
if check() {
return
}
data := make([]byte, os.Getpagesize())
for {
n, err := unix.Read(tun.routeSocket, data)
if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
continue
}
tun.errors <- err
return
}
if n < 8 {
continue
}
if data[3 /* type */] != unix.RTM_IFINFO {
continue
}
ifindex := int(*(*uint16)(unsafe.Pointer(&data[6 /* ifindex */])))
if ifindex != tunIfindex {
continue
}
if check() {
return
}
} }
} }
@ -140,7 +149,6 @@ func CreateTUN(name string, mtu int) (Device, error) {
} }
func CreateTUNFromFile(file *os.File, mtu int) (Device, error) { func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
tun := &NativeTun{ tun := &NativeTun{
tunFile: file, tunFile: file,
events: make(chan Event, 10), events: make(chan Event, 10),