func Test(t *T) { m1 := new(dns.Msg) m1.SetQuestion(testDomain, dns.TypeA) w1 := getWriter() go func() { handleRequest(w1, m1) }() r1 := <-w1.ReplyCh require.Len(t, r1.Answer, 1) m2 := new(dns.Msg) m2.SetQuestion(testDomain, dns.TypeA) r2, err := dns.Exchange(m2, "8.8.8.8:53") require.Nil(t, err) require.Len(t, r2.Answer, 1) assert.Equal(t, r2.Rcode, r1.Rcode) a1 := strings.Split(r1.Answer[0].String(), "\t") //example: a-test.mysuperfancyapi.com., 245, IN, A, 192.95.20.208 //we want to overwrite the TTL since that will be different a2 := strings.Split(r2.Answer[0].String(), "\t") a1[1] = "" a2[1] = "" assert.Equal(t, a2, a1) }
func TestDNS_Recurse(t *testing.T) { recursor := makeRecursor(t, []dns.RR{dnsA("apple.com", "1.2.3.4")}) defer recursor.Shutdown() dir, srv := makeDNSServerConfig(t, func(c *Config) { c.DNSRecursor = recursor.Addr }, nil) defer os.RemoveAll(dir) defer srv.agent.Shutdown() m := new(dns.Msg) m.SetQuestion("apple.com.", dns.TypeANY) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) == 0 { t.Fatalf("Bad: %#v", in) } if in.Rcode != dns.RcodeSuccess { t.Fatalf("Bad: %#v", in) } }
// Perform DNS resolution func resolve(w http.ResponseWriter, r *http.Request, server string, domain string, querytype uint16) { m := new(dns.Msg) m.SetQuestion(domain, querytype) m.MsgHdr.RecursionDesired = true w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") c := new(dns.Client) Redo: if in, _, err := c.Exchange(m, server); err == nil { // Second return value is RTT, not used for now if in.MsgHdr.Truncated { c.Net = "tcp" goto Redo } switch in.MsgHdr.Rcode { case dns.RcodeServerFailure: error(w, 500, 502, "The name server encountered an internal failure while processing this request (SERVFAIL)") case dns.RcodeNameError: error(w, 500, 503, "Some name that ought to exist, does not exist (NXDOMAIN)") case dns.RcodeRefused: error(w, 500, 505, "The name server refuses to perform the specified operation for policy or security reasons (REFUSED)") default: jsonify(w, r, in.Question, in.Answer, in.Ns, in.Extra) } } else { error(w, 500, 501, "DNS server could not be reached") } }
// Check that we can prune an answer func TestPrune(t *testing.T) { InitDefaultLogging(testing.Verbose()) Info.Println("TestPrune starting") questionMsg := new(dns.Msg) questionMsg.SetQuestion("name", dns.TypeA) questionMsg.RecursionDesired = true question := &questionMsg.Question[0] records := []ZoneRecord{ Record{"name", net.ParseIP("10.0.1.1"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.2"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.3"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.4"), 0, 0, 0}, } reply := makeAddressReply(questionMsg, question, records, DefaultLocalTTL) reply.Answer[0].Header().Ttl = DefaultLocalTTL pruned := pruneAnswers(reply.Answer, 1) require.Equal(t, 1, len(pruned), "wrong number of answers") pruned = pruneAnswers(reply.Answer, 2) require.Equal(t, 2, len(pruned), "wrong number of answers") pruned = pruneAnswers(reply.Answer, 0) require.Equal(t, len(records), len(pruned), "wrong number of answers") }
func TestDNS_CaseInsensitiveNodeLookup(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() testutil.WaitForLeader(t, srv.agent.RPC, "dc1") // Register node args := &structs.RegisterRequest{ Datacenter: "dc1", Node: "Foo", Address: "127.0.0.1", } var out struct{} if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { t.Fatalf("err: %v", err) } m := new(dns.Msg) m.SetQuestion("fOO.node.dc1.consul.", dns.TypeANY) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) != 1 { t.Fatalf("empty lookup: %#v", in) } }
func TestDNSTtlRRset(t *testing.T) { s := newTestServerDNSSEC(t, false) defer s.Stop() ttl := uint32(60) for _, serv := range services { addService(t, s, serv.Key, uint64(ttl), serv) defer delService(t, s, serv.Key) ttl += 60 } c := new(dns.Client) tc := dnsTestCases[9] t.Logf("%v\n", tc) m := new(dns.Msg) m.SetQuestion(tc.Qname, tc.Qtype) if tc.dnssec == true { m.SetEdns0(4096, true) } resp, _, err := c.Exchange(m, "127.0.0.1:"+StrPort) if err != nil { t.Fatalf("failing: %s: %s\n", m.String(), err.Error()) } t.Logf("%s\n", resp) ttl = 360 for i, a := range resp.Answer { if a.Header().Ttl != ttl { t.Errorf("Answer %d should have a Header TTL of %d, but has %d", i, ttl, a.Header().Ttl) } } }
// resolveCNAME is used to recursively resolve CNAME records func (d *DNSServer) resolveCNAME(name string) []dns.RR { // Do nothing if we don't have a recursor if len(d.recursors) == 0 { return nil } // Ask for any A records m := new(dns.Msg) m.SetQuestion(name, dns.TypeA) // Make a DNS lookup request c := &dns.Client{Net: "udp"} var r *dns.Msg var rtt time.Duration var err error for _, recursor := range d.recursors { r, rtt, err = c.Exchange(m, recursor) if err == nil { d.logger.Printf("[DEBUG] dns: cname recurse RTT for %v (%v)", name, rtt) return r.Answer } d.logger.Printf("[ERR] dns: cname recurse failed for %v: %v", name, err) } d.logger.Printf("[ERR] dns: all resolvers failed for %v", name) return nil }
func (c *Client) Discover(domain string, cb func(*dns.Msg)) { m := new(dns.Msg) m.SetQuestion(dns.Fqdn(domain), dns.TypePTR) m.RecursionDesired = true addr := &net.UDPAddr{ IP: net.ParseIP("224.0.0.251"), Port: 5353, } conn, err := net.ListenMulticastUDP("udp4", nil, addr) if err != nil { panic(err) } defer conn.Close() c.conn = conn out, err := m.Pack() if err != nil { panic(err) } _, err = conn.WriteToUDP(out, addr) if err != nil { panic(err) } c.handleReceiveMsg(domain, cb) }
func TestDNS_IsAlive(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() m := new(dns.Msg) m.SetQuestion("_test.consul.", dns.TypeANY) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener(srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) != 1 { t.Fatalf("Bad: %#v", in) } txt, ok := in.Answer[0].(*dns.TXT) if !ok { t.Fatalf("Bad: %#v", in.Answer[0]) } if txt.Txt[0] != "ok" { t.Fatalf("Bad: %#v", in.Answer[0]) } }
// Performs the actual query by service name (browse) or service instance name (lookup), // start response listeners goroutines and loops over the entries channel. func (c *client) query(params *LookupParams) error { var serviceName, serviceInstanceName string serviceName = fmt.Sprintf("%s.%s.", trimDot(params.Service), trimDot(params.Domain)) if params.Instance != "" { serviceInstanceName = fmt.Sprintf("%s.%s", params.Instance, serviceName) } // send the query m := new(dns.Msg) if serviceInstanceName != "" { m.Question = []dns.Question{ dns.Question{serviceInstanceName, dns.TypeSRV, dns.ClassINET}, dns.Question{serviceInstanceName, dns.TypeTXT, dns.ClassINET}, } m.RecursionDesired = false } else { m.SetQuestion(serviceName, dns.TypePTR) m.RecursionDesired = false } if err := c.sendQuery(m); err != nil { return err } return nil }
func TestDNSForward(t *testing.T) { s := newTestServer("", "", "8.8.8.8:53") defer s.Stop() c := new(dns.Client) m := new(dns.Msg) m.SetQuestion("www.example.com.", dns.TypeA) resp, _, err := c.Exchange(m, "localhost:"+StrPort) if err != nil { t.Fatal(err) } if len(resp.Answer) == 0 || resp.Rcode != dns.RcodeSuccess { t.Fatal("Answer expected to have A records or rcode not equal to RcodeSuccess") } // TCP c.Net = "tcp" resp, _, err = c.Exchange(m, "localhost:"+StrPort) if err != nil { t.Fatal(err) } if len(resp.Answer) == 0 || resp.Rcode != dns.RcodeSuccess { t.Fatal("Answer expected to have A records or rcode not equal to RcodeSuccess") } // TODO(miek): DNSSEC DO query }
func DnsQuery(query string, wg *sync.WaitGroup, config *dns.ClientConfig, cm *chanman.ChanMan) { defer wg.Done() dnsClient := new(dns.Client) message := new(dns.Msg) message.SetQuestion(dns.Fqdn(query), dns.TypeA) message.RecursionDesired = true response, rtt, err := dnsClient.Exchange(message, net.JoinHostPort(config.Servers[0], "53")) if err != nil { log.Println(err) cm.RunChan <- true } if response == nil { } else { if response.Rcode != dns.RcodeSuccess { log.Println(" query fail") } var stat = new(dnsstat.Info) stat.Rtt = rtt cm.StatsChan <- stat cm.RunChan <- true } }
// perform a DNS query and assert the reply code, number or answers, etc func assertExchange(t *testing.T, z string, ty uint16, minAnswers int, maxAnswers int, expErr int) *dns.Msg { c := new(dns.Client) c.UDPSize = testUDPBufSize m := new(dns.Msg) m.RecursionDesired = true m.SetQuestion(z, ty) m.SetEdns0(testUDPBufSize, false) // we don't want to play with truncation here... r, _, err := c.Exchange(m, fmt.Sprintf("127.0.0.1:%d", testPort)) t.Logf("Response:\n%+v\n", r) wt.AssertNoErr(t, err) if minAnswers == 0 && maxAnswers == 0 { wt.AssertStatus(t, r.Rcode, expErr, "DNS response code") } else { wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS response code") } answers := len(r.Answer) if minAnswers >= 0 && answers < minAnswers { wt.Fatalf(t, "Number of answers >= %d", minAnswers) } if maxAnswers >= 0 && answers > maxAnswers { wt.Fatalf(t, "Number of answers <= %d", maxAnswers) } return r }
func ExamplePrivateHandle() { dns.PrivateHandle("APAIR", TypeAPAIR, NewAPAIR) defer dns.PrivateHandleRemove(TypeAPAIR) rr, err := dns.NewRR("miek.nl. APAIR (1.2.3.4 1.2.3.5)") if err != nil { log.Fatal("could not parse APAIR record: ", err) } fmt.Println(rr) // Output: miek.nl. 3600 IN APAIR 1.2.3.4 1.2.3.5 m := new(dns.Msg) m.Id = 12345 m.SetQuestion("miek.nl.", TypeAPAIR) m.Answer = append(m.Answer, rr) fmt.Println(m) // ;; opcode: QUERY, status: NOERROR, id: 12345 // ;; flags: rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 // // ;; QUESTION SECTION: // ;miek.nl. IN APAIR // // ;; ANSWER SECTION: // miek.nl. 3600 IN APAIR 1.2.3.4 1.2.3.5 }
func (p *Parser) handleExplanation() string { resolvedDomain, err := ParseMacroToken(p, p.Explanation) if err != nil || isEmpty(&resolvedDomain) { // TODO(zaccone): Should we return some internal error return "" } resolvedDomain = NormalizeHost(resolvedDomain) query := new(dns.Msg) query.SetQuestion(resolvedDomain, dns.TypeTXT) c := new(dns.Client) response, _, err := c.Exchange(query, Nameserver) if err != nil || (response != nil && response.Rcode != dns.RcodeSuccess) { return "" } explanation := make([]string, 0, len(response.Answer)) for _, answer := range response.Answer { if q, ok := answer.(*dns.TXT); ok { for _, txt := range q.Txt { explanation = append(explanation, txt) } } } // RFC 7208, section 6.2 specifies that result string should be // concatenated with no spaces. parsedExplanation, err := ParseMacro(p, strings.Join(explanation, "")) if err != nil { return "" } return parsedExplanation }
func makeDnsTxtRequest(domain string, server string) (string, error) { var err error var conn *dns.Conn if conn, err = dns.Dial("udp", server); err != nil { return "", err } m := new(dns.Msg) m.SetQuestion(dns.Fqdn(domain), dns.TypeTXT) m.RecursionDesired = true if err = conn.WriteMsg(m); err != nil { return "", err } var rm *dns.Msg if rm, err = conn.ReadMsg(); err != nil { return "", err } if txt, ok := rm.Answer[0].(*dns.TXT); !ok { return "", fmt.Errorf("No TXT Answer") } else { return strings.Join(txt.Txt, ""), nil } }
func TestMsgOverflow(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } s := newTestServer(t, false) defer s.Stop() c := new(dns.Client) m := new(dns.Msg) // TODO(miek): rethink how to enable metrics in tests. if !metricsDone { Metrics() } for i := 0; i < 2000; i++ { is := strconv.Itoa(i) m := &msg.Service{ Host: "2001::" + is, Key: "machine" + is + ".machines.skydns.test.", } addService(t, s, m.Key, 0, m) defer delService(t, s, m.Key) } m.SetQuestion("machines.skydns.test.", dns.TypeSRV) resp, _, err := c.Exchange(m, "127.0.0.1:"+StrPort) if err != nil { t.Fatal(err) } t.Logf("%s", resp) if resp.Rcode != dns.RcodeServerFailure { t.Fatalf("expecting server failure, got %d", resp.Rcode) } }
func GetExternalIP() (string, error) { // dig +short myip.opendns.com @resolver1.opendns.com target := "myip.opendns.com." server := "resolver1.opendns.com:53" c := dns.Client{} m := dns.Msg{} m.SetQuestion(target, dns.TypeA) r, t, err := c.Exchange(&m, server) CheckErr(err) if len(r.Answer) < 1 { log.Fatal("No results") } firstRecord := r.Answer[0].(*dns.A) ip := fmt.Sprintf("%s", firstRecord.A) log.Printf("found external IP %s in %v", firstRecord.A, t) if !ValidIP(ip) { return "", errors.New(fmt.Sprintf("Error: %s is not a valid IP", ip)) } return ip, nil }
func addresses(conf *dns.ClientConfig, c *dns.Client, name string) []string { m4 := new(dns.Msg) m4.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeA) m6 := new(dns.Msg) m6.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeAAAA) addr := make(chan []string) defer close(addr) c.Do(m4, conf.Servers[0]+":"+conf.Port, addr, qhandler) c.Do(m6, conf.Servers[0]+":"+conf.Port, addr, qhandler) var ips []string i := 2 // two outstanding queries forever: for { select { case ip := <-addr: ips = append(ips, ip...) i-- if i == 0 { break forever } } } return ips }
// updateCacheByName updates the cache entry for the FQDN name func updateCacheByName(name string) { name = dns.Fqdn(name) fmt.Println("Updating entry for", name) m := new(dns.Msg) m.SetQuestion(name, dns.TypeA) // dns.TypeA updateAddressCache(m) }
func (self *TrivialDnsServer) redirectQuery(w dns.ResponseWriter, r *dns.Msg, newName string) { self.Count("redirected_requests") if !strings.HasSuffix(newName, ".") { newName = newName + "." } newR := new(dns.Msg) newR.SetQuestion(dns.Fqdn(newName), dns.TypeA) if response, _, err := self.exchangeWithUpstream(newR); err == nil { ip := self.getSingleSimpleAnswer(response) if ip == nil { debug("%s redirect to %s yielded no answer", w.RemoteAddr(), newName) self.Count("redirected_nowhere") self.refuse(w, r) return } self.Count("redirected_successively") self.respondSuccessively(w, r, *ip) } else { self.Count("upstream_errors") self.refuse(w, r) log.Printf("%s: error: %s", w.RemoteAddr(), err) } }
func TestMsgOverflow(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } s := newTestServer(t, false) defer s.Stop() c := new(dns.Client) m := new(dns.Msg) for i := 0; i < 2000; i++ { is := strconv.Itoa(i) m := &msg.Service{ Host: "2001::" + is, Key: "machine" + is + ".machines.skydns.test.", } addService(t, s, m.Key, 0, m) defer delService(t, s, m.Key) } m.SetQuestion("machines.skydns.test.", dns.TypeSRV) resp, _, err := c.Exchange(m, "127.0.0.1:"+StrPort) if err != nil { // Unpack can fail, and it should (i.e. msg too large) t.Logf("%s", err) return } t.Logf("%s", resp) if resp.Rcode != dns.RcodeSuccess { t.Fatalf("expecting server failure, got %d", resp.Rcode) } }
func TestDNS_NonExistingLookup(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) // lookup a non-existing node, we should receive a SOA m := new(dns.Msg) m.SetQuestion("nonexisting.consul.", dns.TypeANY) c := new(dns.Client) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Ns) != 1 { t.Fatalf("Bad: %#v %#v", in, len(in.Answer)) } soaRec, ok := in.Ns[0].(*dns.SOA) if !ok { t.Fatalf("Bad: %#v", in.Ns[0]) } if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } }
func TestDNSTtlRR(t *testing.T) { s := newTestServerDNSSEC(t, false) defer s.Stop() serv := &msg.Service{Host: "10.0.0.2", Key: "ttl.skydns.test.", Ttl: 360} addService(t, s, serv.Key, time.Duration(serv.Ttl)*time.Second, serv) defer delService(t, s, serv.Key) c := new(dns.Client) tc := dnsTestCases[9] // TTL Test t.Logf("%v\n", tc) m := new(dns.Msg) m.SetQuestion(tc.Qname, tc.Qtype) if tc.dnssec == true { m.SetEdns0(4096, true) } resp, _, err := c.Exchange(m, "127.0.0.1:"+StrPort) if err != nil { t.Errorf("failing: %s: %s\n", m.String(), err.Error()) } t.Logf("%s\n", resp) for i, a := range resp.Answer { if a.Header().Ttl != 360 { t.Errorf("Answer %d should have a Header TTL of %d, but has %d", i, 360, a.Header().Ttl) } } }
func TestDNS_ServiceLookup_TagPeriod(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() testutil.WaitForLeader(t, srv.agent.RPC, "dc1") // Register node args := &structs.RegisterRequest{ Datacenter: "dc1", Node: "foo", Address: "127.0.0.1", Service: &structs.NodeService{ Service: "db", Tags: []string{"v1.master"}, Port: 12345, }, } var out struct{} if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { t.Fatalf("err: %v", err) } m := new(dns.Msg) m.SetQuestion("v1.master.db.service.consul.", dns.TypeSRV) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) != 1 { t.Fatalf("Bad: %#v", in) } srvRec, ok := in.Answer[0].(*dns.SRV) if !ok { t.Fatalf("Bad: %#v", in.Answer[0]) } if srvRec.Port != 12345 { t.Fatalf("Bad: %#v", srvRec) } if srvRec.Target != "foo.node.dc1.consul." { t.Fatalf("Bad: %#v", srvRec) } aRec, ok := in.Extra[0].(*dns.A) if !ok { t.Fatalf("Bad: %#v", in.Extra[0]) } if aRec.Hdr.Name != "foo.node.dc1.consul." { t.Fatalf("Bad: %#v", in.Extra[0]) } if aRec.A.String() != "127.0.0.1" { t.Fatalf("Bad: %#v", in.Extra[0]) } }
func forwardQuestion(q *dns.Question, forwarders []string) []dns.RR { //qType := dns.Type(q.Qtype).String() // query type //log.Printf("[Forwarder Lookup [%s] [%s]]\n", q.Name, qType) myReq := new(dns.Msg) myReq.SetQuestion(q.Name, q.Qtype) if len(forwarders) == 0 { // we have no upstreams, so we'll just not use any } else if strings.TrimSpace(forwarders[0]) == "!" { // we've been told explicitly to not pass anything along to any upsteams } else { c := new(dns.Client) for _, server := range forwarders { c.Net = "udp" m, _, err := c.Exchange(myReq, strings.TrimSpace(server)) if m != nil && m.MsgHdr.Truncated { c.Net = "tcp" m, _, err = c.Exchange(myReq, strings.TrimSpace(server)) } // FIXME: Cache misses. And cache hits, too. if err != nil { //log.Printf("[Forwarder Lookup [%s] [%s] failed: [%s]]\n", q.Name, qType, err) log.Println(err) } else { //log.Printf("[Forwarder Lookup [%s] [%s] success]\n", q.Name, qType) return m.Answer } } } return nil }
/* Get a domain's IPs from a specific name server. Parameters: domain the domain you want to query nameserver name server's IP address port 53 in general net tcp or udp timeout in seconds, can be omitted Here's an example: r, e := ARecords("www.example.com", "8.8.8.8", 53, "tcp") if e != nil { fmt.Println(e) } else { fmt.Println(r) } */ func ARecords(domain, nameserver string, port uint16, net string, timeout ...uint8) ([]string, error) { var result []string if net != "tcp" && net != "udp" { return result, errors.New("The parameter 'net' should only be 'tcp' or 'udp'.") } msg := new(mdns.Msg) msg.SetQuestion(mdns.Fqdn(domain), mdns.TypeA) var client *mdns.Client if len(timeout) > 0 { tm := time.Duration(timeout[0]) * time.Second client = &mdns.Client{Net: net, DialTimeout: tm, ReadTimeout: tm, WriteTimeout: tm} } else { client = &mdns.Client{Net: net} } r, _, err := client.Exchange(msg, fmt.Sprintf("%s:%d", nameserver, port)) if err != nil { return result, err } for _, i := range r.Answer { if t, ok := i.(*mdns.A); ok { result = append(result, t.A.String()) } } return result, nil }
func get_serial(zone_name, query_dest string) (uint32, error) { var in *dns.Msg m := new(dns.Msg) m.SetQuestion(zone_name, dns.TypeSOA) if conf.Transfer_source != nil { d := net.Dialer{LocalAddr: conf.Transfer_source} c, err := d.Dial("tcp", query_dest) if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem dialing query_dest %s", query_dest)) return 0, err } co := &dns.Conn{Conn: c} co.WriteMsg(m) in, err = co.ReadMsg() if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem querying query_dest %s", query_dest)) return 0, err } co.Close() } else { c := &dns.Client{DialTimeout: conf.Query_timeout, ReadTimeout: conf.Query_timeout} if conf.All_tcp == true { c.Net = "tcp" } // _ is query time, might be useful later var err error in, _, err = c.Exchange(m, query_dest) if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem querying query_dest %s", query_dest)) return 0, err } } return serial_query_parse(in), nil }
func (c *Client) lookupIPs(host string) (ips []net.IP, err error) { m := new(dns.Msg) for _, resolver := range c.Resolvers { m.SetQuestion(dns.Fqdn(host), dns.TypeA) if in, err := dns.Exchange(m, resolver); err == nil { for _, rr := range in.Answer { if a, ok := rr.(*dns.A); ok { ips = append(ips, a.A) } } } else { log.Debug(err) } m.SetQuestion(dns.Fqdn(host), dns.TypeAAAA) if in, err := dns.Exchange(m, resolver); err == nil { for _, rr := range in.Answer { if aaaa, ok := rr.(*dns.AAAA); ok { ips = append(ips, aaaa.AAAA) } } } else { log.Debug(err) } } if len(ips) != 0 { return ips, nil } return net.LookupIP(host) }
func TestInFlightEDns0(t *T) { m1 := new(dns.Msg) m1.SetQuestion(testAnyDomain, dns.TypeA) m1.SetEdns0(4096, false) w1 := getWriter() m2 := new(dns.Msg) m2.SetQuestion(testAnyDomain, dns.TypeA) w2 := getWriter() go func() { handleRequest(w1, m1) }() go func() { handleRequest(w2, m2) }() var r1 *dns.Msg var r2 *dns.Msg for r1 == nil || r2 == nil { select { case r1 = <-w1.ReplyCh: case r2 = <-w2.ReplyCh: } } //note: this test could be flaky since we're relying on google to return //edns0 response when we send one vs when we don't send one assert.NotNil(t, r1.IsEdns0()) assert.Nil(t, r2.IsEdns0()) }