func (r *Resolver) resolve(question dns.Question, result *dns.Msg, servers, original []string, loopcount int) ([]dns.RR, error) { if len(servers) == 0 { if r.Debug { log.Println("No more servers to query...") } result.Rcode = dns.RcodeServerFailure return nil, nil } //infinite loop prevention if loopcount == 30 { if r.Debug { log.Println("Loop count exhausted") } result.Rcode = dns.RcodeServerFailure return nil, nil } loopcount++ //Pick a server randomly shuffle(servers) server := servers[0] + ":53" nservers := []string{} for i, s := range servers { if i != 0 { nservers = append(nservers, s) } } if r.Debug { log.Println(server) log.Println(nservers) } m := &dns.Msg{} m.SetQuestion(question.Name, question.Qtype) m.RecursionDesired = false res, err := r.exchange(m, server, original) if r.Debug { if err != nil { log.Println(res, err) } } if err != nil { if r.Debug { log.Println(err) } //Restart with remaining servers return r.resolve(question, result, nservers, original, loopcount) } //Check status... if res.Rcode != dns.RcodeSuccess { //Restart with remaining servers return r.resolve(question, result, nservers, original, loopcount) } answerfound := false var cname dns.Question //Check for answers for _, ans := range res.Answer { result.Answer = append(result.Answer, ans) if ans.Header().Rrtype == question.Qtype { answerfound = true } if ans.Header().Rrtype == dns.TypeCNAME { c, _ := ans.(*dns.CNAME) cname.Name = c.Target cname.Qtype = question.Qtype } } if answerfound { return nil, nil } if cname.Name != "" { if r.Debug { log.Println("CNAME", cname, cname.Name) } return r.resolve(cname, result, r.Roothints, r.Roothints, loopcount) } //OK no ans of target type.... or CNAME found... process NS... ns := make(map[string]string) for _, n := range res.Ns { nsrec, _ := n.(*dns.NS) if nsrec != nil { ns[nsrec.Ns] = "" } } //Try to populate ips from additional... for _, a := range res.Extra { extra, ok := a.(*dns.A) if ok { _, ok := ns[extra.Header().Name] if ok { ns[extra.Header().Name] = extra.A.String() } } } newservers := []string{} //Fill in the missing ips for k, ip := range ns { if ip == "" { nsmsg := &dns.Msg{} nsmsg.SetQuestion(k, dns.TypeA) //Lets cheat and ask a recursive... nsmsg.RecursionDesired = true nsres, err := r.exchange(nsmsg, "8.8.8.8:53", []string{"8.8.8.8"}) if err == nil { for _, ans := range nsres.Answer { arec, ok := ans.(*dns.A) if ok { newservers = append(newservers, arec.A.String()) } } } } else { newservers = append(newservers, ip) } } if r.Debug { log.Println(ns) log.Println(newservers) } if len(newservers) == 0 { //Restart return r.resolve(question, result, nservers, original, loopcount) //return nil, errors.New("No NS record") } return r.resolve(question, result, newservers, newservers, 0) return nil, nil }