net/interfaces, net/netns: move default route interface code to interfaces

To populate interfaces.State.DefaultRouteInterface.

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2020-09-22 14:20:01 -07:00
parent fda9dc8815
commit 8893c2ee78
3 changed files with 75 additions and 40 deletions

View File

@ -5,6 +5,7 @@
package interfaces
import (
"fmt"
"os/exec"
"syscall"
@ -77,18 +78,73 @@ func likelyHomeRouterIPWindows() (ret netaddr.IP, ok bool) {
// NonTailscaleMTUs returns a map of interface LUID to interface MTU,
// for all interfaces except Tailscale tunnels.
func NonTailscaleMTUs() (map[uint64]uint32, error) {
ifs, err := winipcfg.GetInterfaces()
mtus := map[uint64]uint32{}
ifs, err := NonTailscaleInterfaces()
for luid, iface := range ifs {
mtus[luid] = iface.Mtu
}
return mtus, err
}
// NonTailscaleInterfaces returns a map of interface LUID to interface
// for all interfaces except Tailscale tunnels.
func NonTailscaleInterfaces() (map[uint64]*winipcfg.Interface, error) {
ifs, err := winipcfg.GetInterfacesEx(&winipcfg.GetAdapterAddressesFlags{
GAA_FLAG_INCLUDE_ALL_INTERFACES: true,
})
if err != nil {
return nil, err
}
ret := map[uint64]uint32{}
ret := map[uint64]*winipcfg.Interface{}
for _, iface := range ifs {
if iface.Description == tsconst.WintunInterfaceDesc {
continue
}
ret[iface.Luid] = iface.Mtu
ret[iface.Luid] = iface
}
return ret, nil
}
// GetWindowsDefault returns the interface that has the non-Tailscale
// default route for the given address family.
//
// It returns (nil, nil) if no interface is found.
func GetWindowsDefault(family winipcfg.AddressFamily) (*winipcfg.Interface, error) {
ifs, err := NonTailscaleInterfaces()
if err != nil {
return nil, err
}
routes, err := winipcfg.GetRoutes(family)
if err != nil {
return nil, err
}
bestMetric := ^uint32(0)
var bestIface *winipcfg.Interface
for _, route := range routes {
iface := ifs[route.InterfaceLuid]
if route.DestinationPrefix.PrefixLength != 0 || iface == nil {
continue
}
if iface.OperStatus == winipcfg.IfOperStatusUp && route.Metric < bestMetric {
bestMetric = route.Metric
bestIface = iface
}
}
return bestIface, nil
}
func DefaultRouteInterface() (string, error) {
iface, err := GetWindowsDefault(winipcfg.AF_INET)
if err != nil {
return "", err
}
if iface == nil {
return "(none)", nil
}
return fmt.Sprintf("%s (%s)", iface.FriendlyName, iface.Description), nil
}