dns intercept: port DNS-less network recovery to master

Port !997 from v1.0 onto the context-aware master recovery lifecycle. Preserve master logging and resolver APIs while adding macOS default-route DHCP detection, temporary DNS-target cleanup, and atomic recovery ownership.

Includes parser, lifecycle, failure, and concurrency regressions plus the corrected macOS QA helper. Relates to #533 and #597.
This commit is contained in:
Dev Scribe
2026-09-02 16:54:35 +07:00
committed by Cuong Manh Le
parent f96868c266
commit 80d1acdfd5
19 changed files with 1386 additions and 352 deletions
+44
View File
@@ -0,0 +1,44 @@
package ctrld
import (
"net"
"strings"
"unicode"
)
func parseDHCPOptionNameservers(output []byte) []string {
return parseIPv4Nameservers(string(output))
}
func parseDHCPPacketNameservers(output []byte) []string {
for _, line := range strings.Split(string(output), "\n") {
field := strings.TrimSpace(line)
if strings.HasPrefix(field, "domain_name_server ") ||
strings.HasPrefix(field, "domain_name_server:") ||
strings.HasPrefix(field, "domain_name_servers ") ||
strings.HasPrefix(field, "domain_name_servers:") {
return parseIPv4Nameservers(field)
}
}
return nil
}
func parseIPv4Nameservers(value string) []string {
seen := make(map[string]struct{})
var nameservers []string
for _, token := range strings.FieldsFunc(value, func(r rune) bool {
return r != '.' && !unicode.IsDigit(r)
}) {
ip := net.ParseIP(token)
if ip == nil || ip.To4() == nil {
continue
}
ns := ip.String()
if _, ok := seen[ns]; ok {
continue
}
seen[ns] = struct{}{}
nameservers = append(nameservers, ns)
}
return nameservers
}