mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
refactor: consolidate network interface detection logic
Move platform-specific network interface detection from cmd/cli/ to root package as ValidInterfaces function. This eliminates code duplication and provides a consistent interface for determining valid physical network interfaces across all platforms. - Remove duplicate validInterfacesMap functions from platform-specific files - Add context parameter to virtualInterfaces for proper logging - Update all callers to use ctrld.ValidInterfaces instead of local functions - Improve error handling in virtual interface detection on Linux
This commit is contained in:
committed by
Cuong Manh Le
parent
f7c124d99d
commit
fb807d7c37
@@ -1435,7 +1435,7 @@ func (p *prog) monitorNetworkChanges(ctx context.Context) error {
|
||||
|
||||
mon.RegisterChangeCallback(func(delta *netmon.ChangeDelta) {
|
||||
// Get map of valid interfaces
|
||||
validIfaces := validInterfacesMap(ctrld.LoggerCtx(ctx, p.logger.Load()))
|
||||
validIfaces := ctrld.ValidInterfaces(ctrld.LoggerCtx(ctx, p.logger.Load()))
|
||||
|
||||
isMajorChange := mon.IsMajorChangeFrom(delta.Old, delta.New)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package cli
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net"
|
||||
"os/exec"
|
||||
@@ -50,28 +49,3 @@ func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bo
|
||||
_, ok := validIfacesMap[iface.Name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// validInterfacesMap returns a set of all valid hardware ports.
|
||||
func validInterfacesMap(ctx context.Context) map[string]struct{} {
|
||||
b, err := exec.Command("networksetup", "-listallhardwareports").Output()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return parseListAllHardwarePorts(bytes.NewReader(b))
|
||||
}
|
||||
|
||||
// parseListAllHardwarePorts parses output of "networksetup -listallhardwareports"
|
||||
// and returns map presents all hardware ports.
|
||||
func parseListAllHardwarePorts(r io.Reader) map[string]struct{} {
|
||||
m := make(map[string]struct{})
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
after, ok := strings.CutPrefix(line, "Device: ")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
m[after] = struct{}{}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/net/netmon"
|
||||
|
||||
"github.com/Control-D-Inc/ctrld"
|
||||
)
|
||||
|
||||
// patchNetIfaceName patches network interface names on Linux
|
||||
@@ -23,45 +15,3 @@ func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bo
|
||||
_, ok := validIfacesMap[iface.Name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// validInterfacesMap returns a set containing non virtual interfaces.
|
||||
// This filters out virtual interfaces to ensure DNS is only configured on physical interfaces
|
||||
func validInterfacesMap(ctx context.Context) map[string]struct{} {
|
||||
m := make(map[string]struct{})
|
||||
vis := virtualInterfaces(ctx)
|
||||
netmon.ForeachInterface(func(i netmon.Interface, prefixes []netip.Prefix) {
|
||||
if _, existed := vis[i.Name]; existed {
|
||||
return
|
||||
}
|
||||
m[i.Name] = struct{}{}
|
||||
})
|
||||
// Fallback to the default route interface if found nothing.
|
||||
// This ensures we always have at least one interface to configure
|
||||
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 the current machine.
|
||||
// This reads from /sys/devices/virtual/net to identify virtual network interfaces
|
||||
// Virtual interfaces should not have DNS configured as they don't represent physical network connections
|
||||
func virtualInterfaces(ctx context.Context) map[string]struct{} {
|
||||
logger := ctrld.LoggerFromCtx(ctx)
|
||||
s := make(map[string]struct{})
|
||||
entries, err := os.ReadDir("/sys/devices/virtual/net")
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Msg("Failed to read /sys/devices/virtual/net")
|
||||
return nil
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
s[strings.TrimSpace(entry.Name())] = struct{}{}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"tailscale.com/net/netmon"
|
||||
)
|
||||
|
||||
// patchNetIfaceName patches network interface names on non-Linux/Darwin platforms
|
||||
@@ -14,12 +11,3 @@ func patchNetIfaceName(iface *net.Interface) (bool, error) { return true, nil }
|
||||
|
||||
// validInterface checks if an interface is valid on non-Linux/Darwin platforms
|
||||
func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bool { return true }
|
||||
|
||||
// validInterfacesMap returns a set containing only default route interfaces.
|
||||
func validInterfacesMap(ctx context.Context) map[string]struct{} {
|
||||
defaultRoute, err := netmon.DefaultRoute()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return map[string]struct{}{defaultRoute.InterfaceName: {}}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/Control-D-Inc/ctrld"
|
||||
)
|
||||
|
||||
func patchNetIfaceName(iface *net.Interface) (bool, error) {
|
||||
@@ -17,12 +14,3 @@ func validInterface(iface *net.Interface, validIfacesMap map[string]struct{}) bo
|
||||
_, ok := validIfacesMap[iface.Name]
|
||||
return ok
|
||||
}
|
||||
|
||||
// validInterfacesMap returns a set of all physical interfaces.
|
||||
func validInterfacesMap(ctx context.Context) map[string]struct{} {
|
||||
m := make(map[string]struct{})
|
||||
for ifaceName := range ctrld.ValidInterfaces(ctx) {
|
||||
m[ifaceName] = struct{}{}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -1291,7 +1291,7 @@ func canBeLocalUpstream(addr string) bool {
|
||||
// the interface that matches excludeIfaceName. The context is used to clarify the
|
||||
// log message when error happens.
|
||||
func withEachPhysicalInterfaces(excludeIfaceName, contextStr string, f func(i *net.Interface) error) {
|
||||
validIfacesMap := validInterfacesMap(ctrld.LoggerCtx(context.Background(), mainLog.Load()))
|
||||
validIfacesMap := ctrld.ValidInterfaces(ctrld.LoggerCtx(context.Background(), mainLog.Load()))
|
||||
netmon.ForeachInterface(func(i netmon.Interface, prefixes []netip.Prefix) {
|
||||
// Skip loopback/virtual/down interface.
|
||||
if i.IsLoopback() || len(i.HardwareAddr) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user