|
|
|
|
@ -28,7 +28,7 @@ var LoginEndpointForProxyDetermination = "https://controlplane.tailscale.com/" |
|
|
|
|
// If none is found, all zero values are returned.
|
|
|
|
|
// A non-nil error is only returned on a problem listing the system interfaces.
|
|
|
|
|
func Tailscale() ([]netaddr.IP, *net.Interface, error) { |
|
|
|
|
ifs, err := net.Interfaces() |
|
|
|
|
ifs, err := netInterfaces() |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, nil, err |
|
|
|
|
} |
|
|
|
|
@ -50,7 +50,7 @@ func Tailscale() ([]netaddr.IP, *net.Interface, error) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if len(tsIPs) > 0 { |
|
|
|
|
return tsIPs, &iface, nil |
|
|
|
|
return tsIPs, iface.Interface, nil |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return nil, nil, nil |
|
|
|
|
@ -87,20 +87,20 @@ func isProblematicInterface(nif *net.Interface) bool { |
|
|
|
|
// know of environments where these are used with NAT to provide connectivity.
|
|
|
|
|
func LocalAddresses() (regular, loopback []netaddr.IP, err error) { |
|
|
|
|
// TODO(crawshaw): don't serve interface addresses that we are routing
|
|
|
|
|
ifaces, err := net.Interfaces() |
|
|
|
|
ifaces, err := netInterfaces() |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, nil, err |
|
|
|
|
} |
|
|
|
|
var regular4, regular6, linklocal4, ula6 []netaddr.IP |
|
|
|
|
for i := range ifaces { |
|
|
|
|
iface := &ifaces[i] |
|
|
|
|
if !isUp(iface) || isProblematicInterface(iface) { |
|
|
|
|
for _, iface := range ifaces { |
|
|
|
|
stdIf := iface.Interface |
|
|
|
|
if !isUp(stdIf) || isProblematicInterface(stdIf) { |
|
|
|
|
// Skip down interfaces and ones that are
|
|
|
|
|
// problematic that we don't want to try to
|
|
|
|
|
// send Tailscale traffic over.
|
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
ifcIsLoopback := isLoopback(iface) |
|
|
|
|
ifcIsLoopback := isLoopback(stdIf) |
|
|
|
|
|
|
|
|
|
addrs, err := iface.Addrs() |
|
|
|
|
if err != nil { |
|
|
|
|
@ -171,21 +171,27 @@ func sortIPs(s []netaddr.IP) { |
|
|
|
|
// Interface is a wrapper around Go's net.Interface with some extra methods.
|
|
|
|
|
type Interface struct { |
|
|
|
|
*net.Interface |
|
|
|
|
AltAddrs []net.Addr // if non-nil, returned by Addrs
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (i Interface) IsLoopback() bool { return isLoopback(i.Interface) } |
|
|
|
|
func (i Interface) IsUp() bool { return isUp(i.Interface) } |
|
|
|
|
func (i Interface) Addrs() ([]net.Addr, error) { |
|
|
|
|
if i.AltAddrs != nil { |
|
|
|
|
return i.AltAddrs, nil |
|
|
|
|
} |
|
|
|
|
return i.Interface.Addrs() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ForeachInterfaceAddress calls fn for each interface's address on
|
|
|
|
|
// the machine. The IPPrefix's IP is the IP address assigned to the
|
|
|
|
|
// interface, and Bits are the subnet mask.
|
|
|
|
|
func ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { |
|
|
|
|
ifaces, err := net.Interfaces() |
|
|
|
|
ifaces, err := netInterfaces() |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
for i := range ifaces { |
|
|
|
|
iface := &ifaces[i] |
|
|
|
|
for _, iface := range ifaces { |
|
|
|
|
addrs, err := iface.Addrs() |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
@ -194,7 +200,7 @@ func ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { |
|
|
|
|
switch v := a.(type) { |
|
|
|
|
case *net.IPNet: |
|
|
|
|
if pfx, ok := netaddr.FromStdIPNet(v); ok { |
|
|
|
|
fn(Interface{iface}, pfx) |
|
|
|
|
fn(iface, pfx) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -206,12 +212,11 @@ func ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { |
|
|
|
|
// all its addresses. The IPPrefix's IP is the IP address assigned to
|
|
|
|
|
// the interface, and Bits are the subnet mask.
|
|
|
|
|
func ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { |
|
|
|
|
ifaces, err := net.Interfaces() |
|
|
|
|
ifaces, err := netInterfaces() |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
for i := range ifaces { |
|
|
|
|
iface := &ifaces[i] |
|
|
|
|
for _, iface := range ifaces { |
|
|
|
|
addrs, err := iface.Addrs() |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
@ -228,7 +233,7 @@ func ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { |
|
|
|
|
sort.Slice(pfxs, func(i, j int) bool { |
|
|
|
|
return pfxs[i].IP().Less(pfxs[j].IP()) |
|
|
|
|
}) |
|
|
|
|
fn(Interface{iface}, pfxs) |
|
|
|
|
fn(iface, pfxs) |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
@ -575,3 +580,31 @@ func isInterestingIP(ip netaddr.IP) bool { |
|
|
|
|
} |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var altNetInterfaces func() ([]Interface, error) |
|
|
|
|
|
|
|
|
|
// RegisterInterfaceGetter sets the function that's used to query
|
|
|
|
|
// the system network interfaces.
|
|
|
|
|
func RegisterInterfaceGetter(getInterfaces func() ([]Interface, error)) { |
|
|
|
|
altNetInterfaces = getInterfaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// netInterfaces is a wrapper around the standard library's net.Interfaces
|
|
|
|
|
// that returns a []*Interface instead of a []net.Interface.
|
|
|
|
|
// It exists because Android SDK 30 no longer permits Go's net.Interfaces
|
|
|
|
|
// to work (Issue 2293); this wrapper lets us the Android app register
|
|
|
|
|
// an alternate implementation.
|
|
|
|
|
func netInterfaces() ([]Interface, error) { |
|
|
|
|
if altNetInterfaces != nil { |
|
|
|
|
return altNetInterfaces() |
|
|
|
|
} |
|
|
|
|
ifs, err := net.Interfaces() |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
ret := make([]Interface, len(ifs)) |
|
|
|
|
for i := range ifs { |
|
|
|
|
ret[i].Interface = &ifs[i] |
|
|
|
|
} |
|
|
|
|
return ret, nil |
|
|
|
|
} |
|
|
|
|
|