diff --git a/cli.go b/cli.go index 6b18497..3f24d31 100644 --- a/cli.go +++ b/cli.go @@ -6,6 +6,7 @@ import ( "math/rand" "runtime" "strings" + "unsafe" "git.froth.zone/sam/awl/util" "github.com/miekg/dns" @@ -182,14 +183,77 @@ func parseArgs(args []string) (util.Answers, error) { } } if resp.Answers.Server == "" { - resolv, err := dns.ClientConfigFromFile("/etc/resolv.conf") + var resolv *dns.ClientConfig + if runtime.GOOS == "windows" { + resolv, err = WindowsDnsClientConfig() + } else { + resolv, err = dns.ClientConfigFromFile("/etc/resolv.conf") + } if err != nil { // Query Google by default, needed for Windows since the DNS library doesn't support Windows // TODO: Actually find where windows stuffs its dns resolvers resp.Answers.Server = "8.8.4.4" } else { - resp.Answers.Server = resolv.Servers[rand.Intn(len(resolv.Servers))] + resp.Answers.Server = resolv.Servers[rand.Intn(len(resolv.Servers)-1)] } } return util.Answers{Server: resp.Answers.Server, Request: resp.Answers.Request, Name: resp.Answers.Name}, nil } + +/* +"Stolen" from +https://gist.github.com/moloch--/9fb1c8497b09b45c840fe93dd23b1e98 +*/ + +// WindowsDnsClientConfig - returns all DNS server addresses using windows fuckery. +func WindowsDnsClientConfig() (*dns.ClientConfig, error) { + l := uint32(20000) + b := make([]byte, l) + + // Windows is an utter fucking trash fire of an operating system. + if err := windows.GetAdaptersAddresses(windows.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l); err != nil { + return nil, err + } + var addresses []*windows.IpAdapterAddresses + for addr := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); addr != nil; addr = addr.Next { + addresses = append(addresses, addr) + } + + resolvers := map[string]bool{} + for _, addr := range addresses { + for next := addr.FirstUnicastAddress; next != nil; next = next.Next { + if addr.OperStatus != windows.IfOperStatusUp { + continue + } + if next.Address.IP() != nil { + for dnsServer := addr.FirstDnsServerAddress; dnsServer != nil; dnsServer = dnsServer.Next { + ip := dnsServer.Address.IP() + if ip.IsMulticast() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() { + continue + } + if ip.To16() != nil && strings.HasPrefix(ip.To16().String(), "fec0:") { + continue + } + resolvers[ip.String()] = true + } + break + } + } + } + + // Take unique values only + servers := []string{} + for server := range resolvers { + servers = append(servers, server) + } + + // TODO: Make configurable, based on defaults in https://github.com/miekg/dns/blob/master/clientconfig.go + return &dns.ClientConfig{ + Servers: servers, + Search: []string{}, + Port: "53", + Ndots: 1, + Timeout: 5, + Attempts: 1, + }, nil +}