net/interfaces: use syscalls to find private gateway IP address

iOS doesn't let you run subprocesses,
which means we can't use netstat to get routing information.
Instead, use syscalls and grub around in the results.
We keep the old netstat version around,
both for use in non-cgo builds,
and for use testing the syscall-based version.

Note that iOS doesn't ship route.h,
so we include a copy here from the macOS 10.15 SDK
(which is itself unchanged from the 10.14 SDK).

I have tested manually that this yields the correct
gateway IP address on my own macOS and iOS devices.
More coverage would be most welcome.

Signed-off-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Josh Bleecher Snyder
2020-08-04 14:20:38 -07:00
parent 08949d4ef1
commit a16a793605
5 changed files with 417 additions and 7 deletions

View File

@@ -13,10 +13,6 @@ import (
"tailscale.com/version"
)
func init() {
likelyHomeRouterIP = likelyHomeRouterIPDarwin
}
/*
Parse out 10.0.0.1 from:
@@ -32,12 +28,11 @@ default link#14 UCSI utun2
...
*/
func likelyHomeRouterIPDarwin() (ret netaddr.IP, ok bool) {
func likelyHomeRouterIPDarwinExec() (ret netaddr.IP, ok bool) {
if version.IsMobile() {
// Don't try to do subprocesses on iOS. Ends up with log spam like:
// kernel: "Sandbox: IPNExtension(86580) deny(1) process-fork"
// TODO(bradfitz): let our iOS app register a func with this package
// and have it call into C/Swift to get the routing table.
// This is why we have likelyHomeRouterIPDarwinSyscall.
return ret, false
}
cmd := exec.Command("/usr/sbin/netstat", "-r", "-n", "-f", "inet")