//go:build windows package client import ( "strings" ) // probeDNS returns the DNS servers and search domains currently active on // this machine's non-loopback network interfaces (Windows). // // Uses Get-DnsClientServerAddress (fast, built into Windows 8+/2012+). // Falls back to ipconfig /all parsing if the CIM call fails (older OSes). func probeDNS() *DNSConfig { cfg := &DNSConfig{} // Primary: CIM-based — deduped, IPv4+IPv6, excludes loopback adapters const script = ` $addrs = Get-DnsClientServerAddress -ErrorAction SilentlyContinue | Where-Object { $_.InterfaceAlias -notmatch 'Loopback|Npcap|VirtualBox|VMware' } | Select-Object -ExpandProperty ServerAddresses | Where-Object { $_ -ne '' -and $_ -ne '::1' -and $_ -ne '127.0.0.1' } | Sort-Object -Unique $search = (Get-DnsClient -ErrorAction SilentlyContinue | Where-Object { $_.ConnectionSpecificSuffix -ne '' } | Select-Object -ExpandProperty ConnectionSpecificSuffix | Sort-Object -Unique) -join ',' [PSCustomObject]@{ servers = ($addrs -join ','); search = $search } | ConvertTo-Json -Compress ` if out, err := silentOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script); err == nil { raw := strings.TrimSpace(string(out)) if idx := strings.LastIndex(raw, "{"); idx >= 0 { raw = raw[idx:] } cfg = parseDNSJSON(raw) } // Fallback: ipconfig /all if the CIM call returned nothing if len(cfg.Servers) == 0 { cfg = parseDNSIpconfig() } return cfg } // parseDNSIpconfig extracts DNS servers from ipconfig /all output. func parseDNSIpconfig() *DNSConfig { cfg := &DNSConfig{} out, err := silentOutput("ipconfig", "/all") if err != nil { return cfg } seen := map[string]bool{} for _, line := range strings.Split(string(out), "\n") { line = strings.TrimSpace(line) if strings.HasPrefix(strings.ToLower(line), "dns servers") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { addr := strings.TrimSpace(parts[1]) if addr != "" && addr != "127.0.0.1" && addr != "::1" && !seen[addr] { seen[addr] = true cfg.Servers = append(cfg.Servers, addr) } } } } return cfg }