mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
cmd/cli: set DNS for all physical interfaces on Windows/Darwin
This commit is contained in:
committed by
Cuong Manh Le
parent
67d74774a9
commit
0826671809
@@ -42,3 +42,21 @@ func networkServiceName(ifaceName string, r io.Reader) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// validInterface reports whether the *net.Interface is a valid one, which includes:
|
||||
//
|
||||
// - en0: physical wireless
|
||||
// - en1: Thunderbolt 1
|
||||
// - en2: Thunderbolt 2
|
||||
// - en3: Thunderbolt 3
|
||||
// - en4: Thunderbolt 4
|
||||
//
|
||||
// For full list, see: https://unix.stackexchange.com/questions/603506/what-are-these-ifconfig-interfaces-on-macos
|
||||
func validInterface(iface *net.Interface) bool {
|
||||
switch iface.Name {
|
||||
case "en0", "en1", "en2", "en3", "en4":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,5 @@ package cli
|
||||
import "net"
|
||||
|
||||
func patchNetIfaceName(iface *net.Interface) error { return nil }
|
||||
|
||||
func validInterface(iface *net.Interface) bool { return true }
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
@@ -417,8 +418,14 @@ func (p *prog) setDNS() {
|
||||
if iface == "" {
|
||||
return
|
||||
}
|
||||
// allIfaces tracks whether we should set DNS for all physical interfaces.
|
||||
allIfaces := false
|
||||
if iface == "auto" {
|
||||
iface = defaultIfaceName()
|
||||
// If iface is "auto", it means user does not specify "--iface" flag.
|
||||
// In this case, ctrld has to set DNS for all physical interfaces, so
|
||||
// thing will still work when user switch from one to the other.
|
||||
allIfaces = requiredMultiNICsConfig()
|
||||
}
|
||||
lc := cfg.FirstListener()
|
||||
if lc == nil {
|
||||
@@ -460,14 +467,22 @@ func (p *prog) setDNS() {
|
||||
return
|
||||
}
|
||||
logger.Debug().Msg("setting DNS successfully")
|
||||
if allIfaces {
|
||||
withEachPhysicalInterfaces(netIface.Name, "set DNS", func(i *net.Interface) error {
|
||||
return setDNS(i, nameservers)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (p *prog) resetDNS() {
|
||||
if iface == "" {
|
||||
return
|
||||
}
|
||||
allIfaces := false
|
||||
if iface == "auto" {
|
||||
iface = defaultIfaceName()
|
||||
// See corresponding comments in (*prog).setDNS function.
|
||||
allIfaces = requiredMultiNICsConfig()
|
||||
}
|
||||
logger := mainLog.Load().With().Str("iface", iface).Logger()
|
||||
netIface, err := netInterface(iface)
|
||||
@@ -485,6 +500,9 @@ func (p *prog) resetDNS() {
|
||||
return
|
||||
}
|
||||
logger.Debug().Msg("Restoring DNS successfully")
|
||||
if allIfaces {
|
||||
withEachPhysicalInterfaces(netIface.Name, "reset DNS", resetDNS)
|
||||
}
|
||||
}
|
||||
|
||||
func randomLocalIP() string {
|
||||
@@ -649,3 +667,51 @@ func canBeLocalUpstream(addr string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// withEachPhysicalInterfaces runs the function f with each physical interfaces, excluding
|
||||
// the interface that matches excludeIfaceName. The context is used to clarify the
|
||||
// log message when error happens.
|
||||
func withEachPhysicalInterfaces(excludeIfaceName, context string, f func(i *net.Interface) error) {
|
||||
interfaces.ForeachInterface(func(i interfaces.Interface, prefixes []netip.Prefix) {
|
||||
// Skip not-running/local/virtual interface.
|
||||
if !i.IsUp() || i.IsLoopback() || len(i.HardwareAddr) == 0 {
|
||||
return
|
||||
}
|
||||
// Skip non-configured interfaces.
|
||||
if addrs, _ := i.Addrs(); len(addrs) == 0 {
|
||||
return
|
||||
}
|
||||
// Skip invalid interface.
|
||||
if !validInterface(i.Interface) {
|
||||
return
|
||||
}
|
||||
netIface := i.Interface
|
||||
if err := patchNetIfaceName(netIface); err != nil {
|
||||
mainLog.Load().Debug().Err(err).Msg("failed to patch net interface name")
|
||||
return
|
||||
}
|
||||
// Skip excluded interface.
|
||||
if netIface.Name == excludeIfaceName {
|
||||
return
|
||||
}
|
||||
// Skip Windows Hyper-V Default Switch.
|
||||
if strings.Contains(netIface.Name, "vEthernet") {
|
||||
return
|
||||
}
|
||||
if err := f(netIface); err != nil {
|
||||
mainLog.Load().Warn().Err(err).Msgf("failed to %s for interface: %q", context, i.Name)
|
||||
} else {
|
||||
mainLog.Load().Debug().Msgf("%s for interface %q successfully", context, i.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// requiredMultiNicConfig reports whether ctrld needs to set/reset DNS for multiple NICs.
|
||||
func requiredMultiNICsConfig() bool {
|
||||
switch runtime.GOOS {
|
||||
case "windows", "darwin":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user