//go:build unix package ctrld import ( "context" "net" "slices" "time" "tailscale.com/net/netmon" ) // dnsFromResolvConf reads usable nameservers from /etc/resolv.conf file. // A nameserver is usable if it's not one of current machine's IP addresses // and loopback IP addresses. func dnsFromResolvConf(_ context.Context) []string { const ( maxRetries = 10 retryInterval = 100 * time.Millisecond ) regularIPs, loopbackIPs, _ := netmon.LocalAddresses() var dns []string for attempt := 0; attempt < maxRetries; attempt++ { if attempt > 0 { time.Sleep(retryInterval) } nss := CurrentNameserversFromResolvconf() var localDNS []string seen := make(map[string]bool) for _, ns := range nss { if ip := net.ParseIP(ns); ip != nil { // skip loopback IPs for _, v := range slices.Concat(regularIPs, loopbackIPs) { ipStr := v.String() if ip.String() == ipStr { continue } } if !seen[ip.String()] { seen[ip.String()] = true localDNS = append(localDNS, ip.String()) } } } // If we successfully read the file and found nameservers, return them if len(localDNS) > 0 { return localDNS } } return dns }