Exemple #1
0
func TestMDNSService_ServiceAddr(t *testing.T) {
	s := makeService(t)
	q := dns.Question{
		Name:  "_http._tcp.local.",
		Qtype: dns.TypeANY,
	}
	recs := s.Records(q)
	if got, want := len(recs), 5; got != want {
		t.Fatalf("got %d records, want %d: %v", got, want, recs)
	}

	if ptr, ok := recs[0].(*dns.PTR); !ok {
		t.Errorf("recs[0] should be PTR record, got: %v, all records: %v", recs[0], recs)
	} else if got, want := ptr.Ptr, "hostname._http._tcp.local."; got != want {
		t.Fatalf("bad PTR record %v: got %v, want %v", ptr, got, want)
	}

	if _, ok := recs[1].(*dns.SRV); !ok {
		t.Errorf("recs[1] should be SRV record, got: %v, all reccords: %v", recs[1], recs)
	}
	if _, ok := recs[2].(*dns.A); !ok {
		t.Errorf("recs[2] should be A record, got: %v, all records: %v", recs[2], recs)
	}
	if _, ok := recs[3].(*dns.AAAA); !ok {
		t.Errorf("recs[3] should be AAAA record, got: %v, all records: %v", recs[3], recs)
	}
	if _, ok := recs[4].(*dns.TXT); !ok {
		t.Errorf("recs[4] should be TXT record, got: %v, all records: %v", recs[4], recs)
	}

	q.Qtype = dns.TypePTR
	if recs2 := s.Records(q); !reflect.DeepEqual(recs, recs2) {
		t.Fatalf("PTR question should return same result as ANY question: ANY => %v, PTR => %v", recs, recs2)
	}
}
Exemple #2
0
func getRRStr(q dns.Question) (string, bool) {
	client := connectToRedis()
	defer client.Close()
	res := client.HMGet("rr:"+q.Name, "TTL", "CLASS", dns.TypeToString[q.Qtype]).Val()
	if res == nil {
		logStuff("No information on name %v", q.Name)
		return "", true
	}
	if res[0] == nil {
		logStuff("RR for %v is malformed: TTL missing", q.Name)
		return "", true
	}
	if res[1] == nil {
		logStuff("RR for %v is malformed: CLASS missing", q.Name)
		return "", true
	}
	if res[2] == nil {
		logStuff("No %v RR for %v. Trying CNAME", dns.TypeToString[q.Qtype], q.Name)

		res = client.HMGet("rr:"+q.Name, "TTL", "CLASS", "CNAME").Val()
		if res != nil && res[2] != nil {
			q.Qtype = dns.StringToType["CNAME"]
		} else {
			return "", true
		}
	}
	return fmt.Sprintf("%v %v %v %v %v", q.Name, res[0], res[1], dns.TypeToString[q.Qtype], res[2]), false
}
Exemple #3
0
func TestMDNSService_ServiceAddr(t *testing.T) {
	s := makeService(t)
	q := dns.Question{
		Name:  "_http._tcp.local.",
		Qtype: dns.TypeANY,
	}
	recs := s.Records(q)
	if len(recs) != 5 {
		t.Fatalf("bad: %v", recs)
	}

	ptr, ok := recs[0].(*dns.PTR)
	if !ok {
		t.Fatalf("bad: %v", recs[0])
	}
	if _, ok := recs[1].(*dns.SRV); !ok {
		t.Fatalf("bad: %v", recs[1])
	}
	if _, ok := recs[2].(*dns.A); !ok {
		t.Fatalf("bad: %v", recs[2])
	}
	if _, ok := recs[3].(*dns.AAAA); !ok {
		t.Fatalf("bad: %v", recs[3])
	}
	if _, ok := recs[4].(*dns.TXT); !ok {
		t.Fatalf("bad: %v", recs[4])
	}

	if ptr.Ptr != s.instanceAddr {
		t.Fatalf("bad: %v", recs[0])
	}

	q.Qtype = dns.TypePTR
	recs2 := s.Records(q)
	if !reflect.DeepEqual(recs, recs2) {
		t.Fatalf("no match: %v %v", recs, recs2)
	}
}
Exemple #4
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
}