debugging save/restore staticinterface settings

postRun should not restore static settings

put back validInterface check

better debug logs for os resolver init, use mutex to prevent duplicate initializations

use WMI instead of registry keys for static DNS data on Windows

use WMI instead of registry keys for static DNS data on Windows

use winipcfg DNS method

use WMI with registry fallback

go back to registry method

restore saved static configs on stop and uninstall

restore ipv6 DHCP if no saved static ipv6 addresses

do not save loopback IPs for static configs

handle watchdog interface changed for new interfaces

dont overwrite static file on start when staticdns is set to loopback

dont overwrite static file on start when staticdns is set to loopback

dont overwrite static file on start when staticdns is set to loopback

no need to resetDNS on start, uninstall already takes care of this
This commit is contained in:
Alex
2025-02-19 02:30:10 -05:00
committed by Cuong Manh Le
parent a582195cec
commit 332f8ccc37
6 changed files with 182 additions and 53 deletions
+66 -27
View File
@@ -147,15 +147,32 @@ func restoreDNS(iface *net.Interface) (err error) {
}
}
for _, ns := range [][]string{v4ns, v6ns} {
if len(ns) == 0 {
continue
}
mainLog.Load().Debug().Msgf("setting static DNS for interface %q", iface.Name)
err = setDNS(iface, ns)
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
if err != nil {
return fmt.Errorf("restoreDNS: %w", err)
}
if err != nil {
return err
if len(v4ns) > 0 {
mainLog.Load().Debug().Msgf("restoring IPv4 static DNS for interface %q: %v", iface.Name, v4ns)
if err := setDNS(iface, v4ns); err != nil {
return fmt.Errorf("restoreDNS (IPv4): %w", err)
}
} else {
mainLog.Load().Debug().Msgf("restoring IPv4 DHCP for interface %q", iface.Name)
if err := luid.SetDNS(windows.AF_INET, nil, nil); err != nil {
return fmt.Errorf("restoreDNS (IPv4 clear): %w", err)
}
}
if len(v6ns) > 0 {
mainLog.Load().Debug().Msgf("restoring IPv6 static DNS for interface %q: %v", iface.Name, v6ns)
if err := setDNS(iface, v6ns); err != nil {
return fmt.Errorf("restoreDNS (IPv6): %w", err)
}
} else {
mainLog.Load().Debug().Msgf("restoring IPv6 DHCP for interface %q", iface.Name)
if err := luid.SetDNS(windows.AF_INET6, nil, nil); err != nil {
return fmt.Errorf("restoreDNS (IPv6 clear): %w", err)
}
}
}
@@ -180,43 +197,65 @@ func currentDNS(iface *net.Interface) []string {
return ns
}
// currentStaticDNS returns the current static DNS settings of given interface.
// currentStaticDNS checks both the IPv4 and IPv6 paths for static DNS values using keys
// like "NameServer" and "ProfileNameServer".
func currentStaticDNS(iface *net.Interface) ([]string, error) {
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
if err != nil {
return nil, fmt.Errorf("winipcfg.LUIDFromIndex: %w", err)
return nil, fmt.Errorf("fallback winipcfg.LUIDFromIndex: %w", err)
}
guid, err := luid.GUID()
if err != nil {
return nil, fmt.Errorf("luid.GUID: %w", err)
return nil, fmt.Errorf("fallback luid.GUID: %w", err)
}
var ns []string
for _, path := range []string{v4InterfaceKeyPathFormat, v6InterfaceKeyPathFormat} {
found := false
keyPaths := []string{v4InterfaceKeyPathFormat, v6InterfaceKeyPathFormat}
for _, path := range keyPaths {
interfaceKeyPath := path + guid.String()
k, err := registry.OpenKey(registry.LOCAL_MACHINE, interfaceKeyPath, registry.QUERY_VALUE)
if err != nil {
return nil, fmt.Errorf("%s: %w", interfaceKeyPath, err)
mainLog.Load().Debug().Err(err).Msgf("failed to open registry key %q for interface %q; trying next key", interfaceKeyPath, iface.Name)
continue
}
for _, key := range []string{"NameServer", "ProfileNameServer"} {
if found {
continue
}
value, _, err := k.GetStringValue(key)
if err != nil && !errors.Is(err, registry.ErrNotExist) {
return nil, fmt.Errorf("%s: %w", key, err)
}
if len(value) > 0 {
found = true
for _, e := range strings.Split(value, ",") {
ns = append(ns, strings.TrimRight(e, "\x00"))
func() {
defer k.Close()
for _, keyName := range []string{"NameServer", "ProfileNameServer"} {
value, _, err := k.GetStringValue(keyName)
if err != nil && !errors.Is(err, registry.ErrNotExist) {
mainLog.Load().Debug().Err(err).Msgf("error reading %s registry key", keyName)
continue
}
if len(value) > 0 {
mainLog.Load().Debug().Msgf("found static DNS for interface %q: %s", iface.Name, value)
parsed := parseDNSServers(value)
ns = append(ns, parsed...)
}
}
}
}()
}
if len(ns) == 0 {
mainLog.Load().Debug().Msgf("no static DNS values found for interface %q", iface.Name)
}
return ns, nil
}
// parseDNSServers splits a DNS server string that may be comma- or space-separated,
// and trims any extraneous whitespace or null characters.
func parseDNSServers(val string) []string {
fields := strings.FieldsFunc(val, func(r rune) bool {
return r == ' ' || r == ','
})
var servers []string
for _, f := range fields {
trimmed := strings.TrimSpace(f)
if len(trimmed) > 0 {
servers = append(servers, trimmed)
}
}
return servers
}
// addDnsServerForwarders adds given nameservers to DNS server forwarders list,
// and also removing old forwarders if provided.
func addDnsServerForwarders(nameservers, old []string) error {