mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-10-12 01:58:46 +02:00
Retain master's context-aware VPN and resolver APIs, per-program logger, shutdown fencing, native CLAT service identity and firewall behavior. Keep saved-DNS paths owned by the root ctrld package; isolate the added ownership/sweep tests with a shared path seam and temporary backups. Preserve the source DNS64 DNSSEC/cache gates, longest-suffix VPN routing, DNS-journal convergence, scoped IPv6 handling, target ownership checks, custom-listener regressions and documented native QA limits.
46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
package ctrld
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"net/netip"
|
|
"strings"
|
|
)
|
|
|
|
// Link-local addresses identify a host only within their interface's zone.
|
|
// In particular, an unzoned local fe80::1 must not exclude fe80::1%en0.
|
|
func scutilLocalAddressKey(addr netip.Addr) netip.Addr {
|
|
addr = addr.Unmap()
|
|
if addr.IsLinkLocalUnicast() {
|
|
return addr
|
|
}
|
|
return addr.WithZone("")
|
|
}
|
|
|
|
// parseScutilNameservers retains IPv6 zones for the eventual socket dial.
|
|
func parseScutilNameservers(output []byte, local []netip.Addr) ([]string, error) {
|
|
excluded := make(map[netip.Addr]bool, len(local))
|
|
for _, addr := range local {
|
|
excluded[scutilLocalAddressKey(addr)] = true
|
|
}
|
|
var servers []string
|
|
seen := make(map[netip.Addr]bool)
|
|
scanner := bufio.NewScanner(bytes.NewReader(output))
|
|
for scanner.Scan() {
|
|
key, value, ok := strings.Cut(strings.TrimSpace(scanner.Text()), ":")
|
|
if !ok || !strings.HasPrefix(key, "nameserver[") {
|
|
continue
|
|
}
|
|
addr, err := netip.ParseAddr(strings.TrimSpace(value))
|
|
if err != nil || excluded[scutilLocalAddressKey(addr)] || seen[addr] {
|
|
continue
|
|
}
|
|
seen[addr] = true
|
|
servers = append(servers, addr.String())
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return servers, nil
|
|
}
|