cmd/cli: implement valid interfaces map for all systems

Previously, a valid interfaces map is only meaningful on Windows and
Darwin, where ctrld needs to set DNS for all physical interfaces.

With new network monitor, the valid interfaces is used for checking new
changes, thus we have to implement the valid interfaces map for all
systems.

 - On Linux, just retrieving all non-virtual interfaces.
 - On others, fallback to use default route interface only.
This commit is contained in:
Cuong Manh Le
2025-02-07 19:09:20 +07:00
committed by Cuong Manh Le
parent 253a57ca01
commit af4b826b68
3 changed files with 67 additions and 4 deletions

View File

@@ -1366,7 +1366,7 @@ func (p *prog) monitorNetworkChanges(ctx context.Context) error {
changed := false
activeInterfaceExists := false
changeIPs := []netip.Prefix{}
var changeIPs []netip.Prefix
// Check each valid interface for changes
for ifaceName := range validIfaces {
oldIface := delta.Old.Interface[ifaceName]

52
cmd/cli/net_linux.go Normal file
View File

@@ -0,0 +1,52 @@
package cli
import (
"net"
"net/netip"
"os"
"strings"
"tailscale.com/net/netmon"
)
func patchNetIfaceName(iface *net.Interface) (bool, error) { return true, nil }
// validInterface reports whether the *net.Interface is a valid one.
// Only non-virtual interfaces are considered valid.
func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bool {
_, ok := validIfacesMap[iface.Name]
return ok
}
// validInterfacesMap returns a set containing non virtual interfaces.
func validInterfacesMap() map[string]struct{} {
m := make(map[string]struct{})
vis := virtualInterfaces()
netmon.ForeachInterface(func(i netmon.Interface, prefixes []netip.Prefix) {
if _, existed := vis[i.Name]; existed {
return
}
m[i.Name] = struct{}{}
})
// Fallback to default route interface if found nothing.
if len(m) == 0 {
defaultRoute, err := netmon.DefaultRoute()
if err != nil {
return m
}
m[defaultRoute.InterfaceName] = struct{}{}
}
return m
}
// virtualInterfaces returns a map of virtual interfaces on current machine.
func virtualInterfaces() map[string]struct{} {
s := make(map[string]struct{})
entries, _ := os.ReadDir("/sys/devices/virtual/net")
for _, entry := range entries {
if entry.IsDir() {
s[strings.TrimSpace(entry.Name())] = struct{}{}
}
}
return s
}

View File

@@ -1,11 +1,22 @@
//go:build !darwin && !windows
//go:build !darwin && !windows && !linux
package cli
import "net"
import (
"net"
"tailscale.com/net/netmon"
)
func patchNetIfaceName(iface *net.Interface) (bool, error) { return true, nil }
func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bool { return true }
func validInterfacesMap() map[string]struct{} { return nil }
// validInterfacesMap returns a set containing only default route interfaces.
func validInterfacesMap() map[string]struct{} {
defaultRoute, err := netmon.DefaultRoute()
if err != nil {
return nil
}
return map[string]struct{}{defaultRoute.InterfaceName: {}}
}