Example #1
0
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
}