mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
net/netmon: swap to swift-derived defaultRoute on macos (#11936)
Updates tailscale/corp#18960 iOS uses Apple's NetworkMonitor to track the default interface and there's no reason we shouldn't also use this on macOS, for the same reasons noted in the comments for why this change was made on iOS. This eliminates the need to load and parse the routing table when querying the defaultRouter() in almost all cases. A slight modification here (on both platforms) to fallback to the default BSD logic in the unhappy-path rather than making assumptions that may not hold. If netmon is eventually parsing AF_ROUTE and able to give a consistently correct answer for the default interface index, we can fall back to that and eliminate the Swift dependency. Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
parent
de85610be0
commit
fa1303d632
@ -1,11 +1,11 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Common code for FreeBSD and Darwin. This might also work on other
|
||||
// Common code for FreeBSD. This might also work on other
|
||||
// BSD systems (e.g. OpenBSD) but has not been tested.
|
||||
// Not used on iOS. See defaultroute_ios.go.
|
||||
// Not used on iOS or macOS. See defaultroute_darwin.go.
|
||||
|
||||
//go:build !ios && (darwin || freebsd)
|
||||
//go:build freebsd
|
||||
|
||||
package netmon
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build ios
|
||||
//go:build darwin || ios
|
||||
|
||||
package netmon
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"tailscale.com/syncs"
|
||||
)
|
||||
@ -22,12 +23,12 @@ func UpdateLastKnownDefaultRouteInterface(ifName string) {
|
||||
return
|
||||
}
|
||||
if old := lastKnownDefaultRouteIfName.Swap(ifName); old != ifName {
|
||||
log.Printf("defaultroute_ios: update from Swift, ifName = %s (was %s)", ifName, old)
|
||||
log.Printf("defaultroute_darwin: update from Swift, ifName = %s (was %s)", ifName, old)
|
||||
}
|
||||
}
|
||||
|
||||
func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
// We cannot rely on the delegated interface data on iOS. The NetworkExtension framework
|
||||
// We cannot rely on the delegated interface data on darwin. The NetworkExtension framework
|
||||
// seems to set the delegate interface only once, upon the *creation* of the VPN tunnel.
|
||||
// If a network transition (e.g. from Wi-Fi to Cellular) happens while the tunnel is
|
||||
// connected, it will be ignored and we will still try to set Wi-Fi as the default route
|
||||
@ -37,16 +38,13 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
// the interface name of the first currently satisfied network path. Our Swift code will
|
||||
// call into `UpdateLastKnownDefaultRouteInterface`, so we can rely on that when it is set.
|
||||
//
|
||||
// If for any reason the Swift machinery didn't work and we don't get any updates, here
|
||||
// we also have some fallback logic: we try finding a hardcoded Wi-Fi interface called en0.
|
||||
// If en0 is down, we fall back to cellular (pdp_ip0) as a last resort. This doesn't handle
|
||||
// all edge cases like USB-Ethernet adapters or multiple Ethernet interfaces, but is good
|
||||
// enough to ensure connectivity isn't broken.
|
||||
// If for any reason the Swift machinery didn't work and we don't get any updates, we will
|
||||
// fallback to the BSD logic.
|
||||
|
||||
// Start by getting all available interfaces.
|
||||
interfaces, err := netInterfaces()
|
||||
if err != nil {
|
||||
log.Printf("defaultroute_ios: could not get interfaces: %v", err)
|
||||
log.Printf("defaultroute_darwin: could not get interfaces: %v", err)
|
||||
return d, ErrNoGatewayIndexFound
|
||||
}
|
||||
|
||||
@ -57,13 +55,13 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
}
|
||||
|
||||
if !ifc.IsUp() {
|
||||
log.Printf("defaultroute_ios: %s is down", name)
|
||||
log.Printf("defaultroute_darwin: %s is down", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
addrs, _ := ifc.Addrs()
|
||||
if len(addrs) == 0 {
|
||||
log.Printf("defaultroute_ios: %s has no addresses", name)
|
||||
log.Printf("defaultroute_darwin: %s has no addresses", name)
|
||||
return nil
|
||||
}
|
||||
return &ifc
|
||||
@ -79,30 +77,22 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
if ifc != nil {
|
||||
d.InterfaceName = ifc.Name
|
||||
d.InterfaceIndex = ifc.Index
|
||||
log.Printf("defaultroute_darwin: using lastKnownDefaultRouteInterface %s %v", d.InterfaceName, d.InterfaceIndex)
|
||||
return d, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Start of our fallback logic if Swift didn't give us an interface name, or gave us an invalid
|
||||
// one.
|
||||
// We start by attempting to use the Wi-Fi interface, which on iPhone is always called en0.
|
||||
enZeroIf := getInterfaceByName("en0")
|
||||
if enZeroIf != nil {
|
||||
log.Println("defaultroute_ios: using en0 (fallback)")
|
||||
d.InterfaceName = enZeroIf.Name
|
||||
d.InterfaceIndex = enZeroIf.Index
|
||||
return d, nil
|
||||
// Fallback to the BSD logic
|
||||
idx, err := DefaultRouteInterfaceIndex()
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
|
||||
// Did it not work? Let's try with Cellular (pdp_ip0).
|
||||
cellIf := getInterfaceByName("pdp_ip0")
|
||||
if cellIf != nil {
|
||||
log.Println("defaultroute_ios: using pdp_ip0 (fallback)")
|
||||
d.InterfaceName = cellIf.Name
|
||||
d.InterfaceIndex = cellIf.Index
|
||||
return d, nil
|
||||
iface, err := net.InterfaceByIndex(idx)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
|
||||
log.Println("defaultroute_ios: no running interfaces available")
|
||||
return d, ErrNoGatewayIndexFound
|
||||
d.InterfaceName = iface.Name
|
||||
d.InterfaceIndex = idx
|
||||
log.Printf("defaultroute_darwin: using table dervied default if %s %v", d.InterfaceName, d.InterfaceIndex)
|
||||
return d, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user