@ -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"
)
@ -27,7 +28,7 @@ func UpdateLastKnownDefaultRouteInterface(ifName string) {
}
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,11 +38,8 @@ 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 ( )
@ -83,26 +81,17 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
}
}
// 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
// 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
idx , err := DefaultRouteInterfaceIndex ( )
if err != nil {
return d , err
}
log . Println ( "defaultroute_ios: no running interfaces available" )
return d , ErrNoGatewayIndexFound
iface , err := net . InterfaceByIndex ( idx )
if err != nil {
return d , err
}
d . InterfaceName = iface . Name
d . InterfaceIndex = idx
return d , nil
}