net/interfaces: better handle multiple interfaces in LikelyHomeRouterIP
Currently, we get the "likely home router" gateway IP and then iterate through all IPs for all interfaces trying to match IPs to determine the source IP. However, on many platforms we know what interface the gateway is through, and thus we don't need to iterate through all interfaces checking IPs. Instead, use the IP address of the associated interface. This better handles the case where we have multiple interfaces on a system all connected to the same gateway, and where the first interface that we visit (as iterated by ForeachInterfaceAddress) isn't also the default internet route. Updates #8992 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I8632f577f1136930f4ec60c76376527a19a47d1f
This commit is contained in:
@ -45,14 +45,14 @@ Iface Destination Gateway Flags RefCnt Use Metric Mask
|
||||
ens18 00000000 0100000A 0003 0 0 0 00000000 0 0 0
|
||||
ens18 0000000A 00000000 0001 0 0 0 0000FFFF 0 0 0
|
||||
*/
|
||||
func likelyHomeRouterIPLinux() (ret netip.Addr, ok bool) {
|
||||
func likelyHomeRouterIPLinux() (ret netip.Addr, myIP netip.Addr, ok bool) {
|
||||
if procNetRouteErr.Load() {
|
||||
// If we failed to read /proc/net/route previously, don't keep trying.
|
||||
// But if we're on Android, go into the Android path.
|
||||
if runtime.GOOS == "android" {
|
||||
return likelyHomeRouterIPAndroid()
|
||||
}
|
||||
return ret, false
|
||||
return ret, myIP, false
|
||||
}
|
||||
lineNum := 0
|
||||
var f []mem.RO
|
||||
@ -99,7 +99,27 @@ func likelyHomeRouterIPLinux() (ret netip.Addr, ok bool) {
|
||||
log.Printf("interfaces: failed to read /proc/net/route: %v", err)
|
||||
}
|
||||
if ret.IsValid() {
|
||||
return ret, true
|
||||
// Try to get the local IP of the interface associated with
|
||||
// this route to short-circuit finding the IP associated with
|
||||
// this gateway. This isn't fatal if it fails.
|
||||
if len(f) > 0 && !disableLikelyHomeRouterIPSelf() {
|
||||
ForeachInterface(func(ni Interface, pfxs []netip.Prefix) {
|
||||
// Ensure this is the same interface
|
||||
if !f[0].EqualString(ni.Name) {
|
||||
return
|
||||
}
|
||||
|
||||
// Find the first IPv4 address and use it.
|
||||
for _, pfx := range pfxs {
|
||||
if addr := pfx.Addr(); addr.Is4() {
|
||||
myIP = addr
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return ret, myIP, true
|
||||
}
|
||||
if lineNum >= maxProcNetRouteRead {
|
||||
// If we went over our line limit without finding an answer, assume
|
||||
@ -113,12 +133,12 @@ func likelyHomeRouterIPLinux() (ret netip.Addr, ok bool) {
|
||||
// find one in the future.
|
||||
procNetRouteErr.Store(true)
|
||||
}
|
||||
return netip.Addr{}, false
|
||||
return netip.Addr{}, netip.Addr{}, false
|
||||
}
|
||||
|
||||
// Android apps don't have permission to read /proc/net/route, at
|
||||
// least on Google devices and the Android emulator.
|
||||
func likelyHomeRouterIPAndroid() (ret netip.Addr, ok bool) {
|
||||
func likelyHomeRouterIPAndroid() (ret netip.Addr, _ netip.Addr, ok bool) {
|
||||
cmd := exec.Command("/system/bin/ip", "route", "show", "table", "0")
|
||||
out, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
@ -148,7 +168,7 @@ func likelyHomeRouterIPAndroid() (ret netip.Addr, ok bool) {
|
||||
})
|
||||
cmd.Process.Kill()
|
||||
cmd.Wait()
|
||||
return ret, ret.IsValid()
|
||||
return ret, netip.Addr{}, ret.IsValid()
|
||||
}
|
||||
|
||||
func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
|
Reference in New Issue
Block a user