func handleSpecialNames(w dns.ResponseWriter, req *dns.Msg) bool { question := req.Question[0] nameLC := strings.ToLower(question.Name) for _, localRR := range localRRS { if nameLC == localRR.Name { m := new(dns.Msg) m.Id = req.Id m.Answer = []dns.RR{*localRR.RR} m.Response = true w.WriteMsg(m) return true } } if question.Qtype != dns.TypeANY { return false } m := new(dns.Msg) m.Id = req.Id hinfo := new(dns.HINFO) hinfo.Hdr = dns.RR_Header{Name: question.Name, Rrtype: dns.TypeHINFO, Class: dns.ClassINET, Ttl: 86400} hinfo.Cpu = "ANY is not supported any more" hinfo.Os = "See draft-jabley-dnsop-refuse-any" m.Answer = []dns.RR{hinfo} m.Response = true w.WriteMsg(m) return true }
func (r *resolver) forwardQueryEnd(w dns.ResponseWriter, msg *dns.Msg) dns.ResponseWriter { var ( cc clientConn ok bool ) proto := w.LocalAddr().Network() r.queryLock.Lock() defer r.queryLock.Unlock() if r.count == 0 { log.Errorf("Invalid concurrent query count") } else { r.count-- } switch proto { case "tcp": break case "udp": if cc, ok = r.client[msg.Id]; ok == false { log.Debugf("Can't retrieve client context for dns id %v", msg.Id) return nil } log.Debugf("dns msg id %v, client id %v", msg.Id, cc.dnsID) delete(r.client, msg.Id) msg.Id = cc.dnsID w = cc.respWriter default: log.Errorf("Invalid protocol") return nil } return w }
func (r *resolver) forwardQueryStart(w dns.ResponseWriter, msg *dns.Msg, queryID uint16) bool { proto := w.LocalAddr().Network() dnsID := uint16(rand.Intn(maxDNSID)) cc := clientConn{ dnsID: queryID, respWriter: w, } r.queryLock.Lock() defer r.queryLock.Unlock() if r.count == maxConcurrent { return false } r.count++ switch proto { case "tcp": break case "udp": for ok := true; ok == true; dnsID = uint16(rand.Intn(maxDNSID)) { _, ok = r.client[dnsID] } log.Debugf("client dns id %v, changed id %v", queryID, dnsID) r.client[dnsID] = cc msg.Id = dnsID default: log.Errorf("Invalid protocol..") return false } return true }
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 ReverseProxy) ServeDNS(w dns.ResponseWriter, r *dns.Msg, extra []dns.RR) error { var ( reply *dns.Msg err error ) switch { case middleware.Proto(w) == "tcp": reply, err = middleware.Exchange(p.Client.TCP, r, p.Host) default: reply, err = middleware.Exchange(p.Client.UDP, r, p.Host) } if reply != nil && reply.Truncated { // Suppress proxy error for truncated responses err = nil } if err != nil { return err } reply.Compress = true reply.Id = r.Id w.WriteMsg(reply) return nil }
func (self *DnsResolver) lookupHost(host string, triesLeft int) ([]net.IP, error) { m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.Question = make([]dns.Question, 1) m1.Question[0] = dns.Question{dns.Fqdn(host), dns.TypeA, dns.ClassINET} in, err := dns.Exchange(m1, self.Servers[self.r.Intn(len(self.Servers))]) result := []net.IP{} if err != nil { if strings.HasSuffix(err.Error(), "i/o timeout") && triesLeft > 0 { triesLeft -= 1 return self.lookupHost(host, triesLeft) } else { return result, err } } if in != nil && in.Rcode != dns.RcodeSuccess { return result, errors.New(dns.RcodeToString[in.Rcode]) } for _, record := range in.Answer { if t, ok := record.(*dns.A); ok { result = append(result, t.A) } } return result, err }
// ServeDNSForward forwards a request to a nameservers and returns the response. func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { if s.config.NoRec { m := s.ServerFailure(req) w.WriteMsg(m) return m } if len(s.config.Nameservers) == 0 || dns.CountLabel(req.Question[0].Name) < s.config.Ndots { if s.config.Verbose { if len(s.config.Nameservers) == 0 { logf("can not forward, no nameservers defined") } else { logf("can not forward, name too short (less than %d labels): `%s'", s.config.Ndots, req.Question[0].Name) } } m := s.ServerFailure(req) m.RecursionAvailable = true // this is still true w.WriteMsg(m) return m } tcp := isTCP(w) var ( r *dns.Msg err error try int ) nsid := 0 if s.config.NSRotate { // Use request Id for "random" nameserver selection. nsid = int(req.Id) % len(s.config.Nameservers) } Redo: switch tcp { case false: r, _, err = s.dnsUDPclient.Exchange(req, s.config.Nameservers[nsid]) case true: r, _, err = s.dnsTCPclient.Exchange(req, s.config.Nameservers[nsid]) } if err == nil { r.Compress = true r.Id = req.Id w.WriteMsg(r) return r } // Seen an error, this can only mean, "server not reached", try again // but only if we have not exausted our nameservers. if try < len(s.config.Nameservers) { try++ nsid = (nsid + 1) % len(s.config.Nameservers) goto Redo } logf("failure to forward request %q", err) m := s.ServerFailure(req) return m }
func newMsg(host string, qClass uint16) *dns.Msg { m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.Question = make([]dns.Question, 1) m1.Question[0] = dns.Question{host, qClass, dns.ClassINET} return m1 }
// ServeDNSStubForward forwards a request to a nameservers and returns the response. func (s *server) ServeDNSStubForward(w dns.ResponseWriter, req *dns.Msg, ns []string) *dns.Msg { // Check EDNS0 Stub option, if set drop the packet. option := req.IsEdns0() if option != nil { for _, o := range option.Option { if o.Option() == ednsStubCode && len(o.(*dns.EDNS0_LOCAL).Data) == 1 && o.(*dns.EDNS0_LOCAL).Data[0] == 1 { // Maybe log source IP here? logf("not fowarding stub request to another stub") return nil } } } tcp := isTCP(w) // Add a custom EDNS0 option to the packet, so we can detect loops // when 2 stubs are forwarding to each other. if option != nil { option.Option = append(option.Option, &dns.EDNS0_LOCAL{ednsStubCode, []byte{1}}) } else { req.Extra = append(req.Extra, ednsStub) } var ( r *dns.Msg err error try int ) // Use request Id for "random" nameserver selection. nsid := int(req.Id) % len(ns) Redo: switch tcp { case false: r, _, err = s.dnsUDPclient.Exchange(req, ns[nsid]) case true: r, _, err = s.dnsTCPclient.Exchange(req, ns[nsid]) } if err == nil { r.Compress = true r.Id = req.Id w.WriteMsg(r) return r } // Seen an error, this can only mean, "server not reached", try again // but only if we have not exausted our nameservers. if try < len(ns) { try++ nsid = (nsid + 1) % len(ns) goto Redo } logf("failure to forward stub request %q", err) m := s.ServerFailure(req) w.WriteMsg(m) return m }
func localQuery(mychan chan DNSreply, qname string, qtype uint16) { var result DNSreply var trials uint result.qname = qname result.qtype = qtype result.r = nil result.err = errors.New("No name server to answer the question") localm := new(dns.Msg) localm.Id = dns.Id() localm.RecursionDesired = true localm.Question = make([]dns.Question, 1) localm.SetEdns0(EDNSBUFFERSIZE, false) // Even if no EDNS requested, see #9 May be we should retry without it if timeout? localc := new(dns.Client) localc.ReadTimeout = timeout localm.Question[0] = dns.Question{qname, qtype, dns.ClassINET} Tests: for trials = 0; trials < uint(*maxTrials); trials++ { Resolvers: for serverIndex := range conf.Servers { server := conf.Servers[serverIndex] result.nameserver = server // Brackets around the server address are necessary for IPv6 name servers r, rtt, err := localc.Exchange(localm, "["+server+"]:"+conf.Port) // Do not use net.JoinHostPort, see https://github.com/bortzmeyer/check-soa/commit/3e4edb13855d8c4016768796b2892aa83eda1933#commitcomment-2355543 if r == nil { result.r = nil result.err = err if strings.Contains(err.Error(), "timeout") { // Try another resolver break Resolvers } else { // We give in break Tests } } else { result.rtt = rtt if r.Rcode == dns.RcodeSuccess { // TODO: as a result, NODATA (NOERROR/ANSWER=0) are silently ignored (try "foo", for instance, the name exists but no IP address) // TODO: for rcodes like SERVFAIL, trying another resolver could make sense result.r = r result.err = nil break Tests } else { // All the other codes are errors. Yes, it may // happens that one resolver returns REFUSED // and the others work but we do not handle // this case. TODO: delete the resolver from // the list and try another one result.r = r result.err = errors.New(dns.RcodeToString[r.Rcode]) break Tests } } } } if *debug { fmt.Printf("DEBUG: end of DNS request \"%s\" / %d\n", qname, qtype) } mychan <- result }
func prepareFailureMsg(req *dns.Msg) *dns.Msg { failMsg := new(dns.Msg) failMsg.Id = req.Id failMsg.Response = true failMsg.Authoritative = true failMsg.Question = req.Question failMsg.Rcode = dns.RcodeNameError return failMsg }
func (ds *DNSServer) ServeDNS(rw dns.ResponseWriter, mes *dns.Msg) { resp := new(dns.Msg) for _, q := range mes.Question { log.Printf("DNS request from %s: %s", rw.RemoteAddr(), &q) switch q.Qtype { case dns.TypeA, dns.TypeAAAA: val, err := ds.HandleLookup(q.Name) if err != nil { log.Println(err) continue } if q.Qclass != dns.ClassINET { log.Printf("error: got invalid DNS question class %d\n", q.Qclass) continue } header := dns.RR_Header{ Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: DefaultResponseTTL, } var rr dns.RR // not really super sure why these have to be different types if q.Qtype == dns.TypeA { rr = &dns.A{ A: net.ParseIP(val), Hdr: header, } } else if q.Qtype == dns.TypeAAAA { rr = &dns.AAAA{ AAAA: net.ParseIP(val), Hdr: header, } } else { panic("unreachable") } resp.Answer = append(resp.Answer, rr) default: log.Printf("unhandled qtype: %d\n", q.Qtype) } } resp.Authoritative = true resp.Id = mes.Id resp.Response = true if err := rw.WriteMsg(resp); err != nil { log.Printf("error responding to DNS query: %s", err) } }
// DNS requests go to this function func dnsHandle(w dns.ResponseWriter, r *dns.Msg) { name := r.Question[0].Name if !namePattern.MatchString(name) { kilog.Debug("%v does not match pattern, forwarding", name) dnsForward(w, r) return } // otherwise kilog.Debug("%v matches pattern, handling", name) dnsLock.Lock() defer dnsLock.Unlock() // check in table first fakeIP, ok := nameToIP[name] if !ok { // place in table var nwIP string for { haha := ipAlloc().String() _, exists := ipToName[haha] if exists { continue } nwIP = haha break } fakeIP = nwIP nameToIP[name] = fakeIP ipToName[fakeIP] = name // remove in 30 minutes go func() { time.Sleep(time.Minute * 30) dnsLock.Lock() defer dnsLock.Unlock() delete(nameToIP, name) delete(ipToName, fakeIP) }() } // return the fake IP to the user resp := new(dns.A) resp.Hdr.Name = name resp.Hdr.Ttl = 1 // very short resp.Hdr.Class = dns.ClassINET resp.Hdr.Rrtype = dns.TypeA resp.A = net.ParseIP(fakeIP) towrite := new(dns.Msg) towrite.Id = r.Id towrite.RecursionAvailable = true towrite.RecursionDesired = true towrite.Response = true towrite.Question = r.Question towrite.Answer = make([]dns.RR, 1) towrite.Answer[0] = resp w.WriteMsg(towrite) kilog.Debug("returning mapping %v -> %v", name, fakeIP) }
func (d *DnsDomain) Test() bool { if !(*Domain)(d).Test() { return false } fqdn := d.Name if strings.HasPrefix(fqdn, "*.") { fqdn = "a" + fqdn[1:] } if !strings.HasSuffix(fqdn, ".") { fqdn = fqdn + "." } any_ok := false d.DNS = make([]*DnsRecords, 0, len(DNS_servers)) for name, addr := range DNS_servers { records := new(DnsRecords) records.Server = name records.NS = addr d.DNS = append(d.DNS, records) req := new(dns.Msg) req.Id = dns.Id() req.RecursionDesired = true req.Question = []dns.Question{ dns.Question{fqdn, dns.TypeA, dns.ClassINET}, } resp, err := dns_client.Exchange(req, addr) if err != nil { records.Status = 900 records.Message = err.Error() continue } records.IPs = make([]string, 0, len(resp.Answer)) for _, rr := range resp.Answer { switch a := rr.(type) { case *dns.RR_A: records.IPs = append(records.IPs, a.A.String()) } } if len(records.IPs) > 0 { any_ok = true } else { records.Status = 900 records.Message = "No records" } } return any_ok }
func DnsGetDoaminIP(domain string) (string, error) { m := new(dns.Msg) m.Id = dns.Id() m.SetQuestion(dns.Fqdn(domain), dns.TypeA) m.RecursionDesired = true res, err := dnsQuery(m) if nil != err { return "", err } return pickIP(res), nil }
func check(c *dns.Client, m *dns.Msg, addr string) bool { m.Id = dns.Id() in, _, err := c.Exchange(m, addr) if err != nil { return false } if in.Rcode != dns.RcodeSuccess { return false } return true }
func prepareAnswerMsg(req *dns.Msg, answers []dns.RR) *dns.Msg { answerMsg := new(dns.Msg) answerMsg.Id = req.Id answerMsg.Response = true answerMsg.Authoritative = true answerMsg.Question = req.Question answerMsg.Answer = answers answerMsg.Rcode = dns.RcodeSuccess answerMsg.Extra = []dns.RR{} return answerMsg }
// ServeDNSForward forwards a request to a nameservers and returns the response. func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { if s.config.NoRec { m := s.ServerFailure(req) w.WriteMsg(m) return m } if len(s.config.Nameservers) == 0 || dns.CountLabel(req.Question[0].Name) < s.config.Ndots { if s.config.Verbose { if len(s.config.Nameservers) == 0 { logf("can not forward, no nameservers defined") } else { logf("can not forward, name too short (less than %d labels): `%s'", s.config.Ndots, req.Question[0].Name) } } m := s.ServerFailure(req) m.RecursionAvailable = true // this is still true w.WriteMsg(m) return m } var ( r *dns.Msg err error ) nsid := s.randomNameserverID(req.Id) try := 0 Redo: if isTCP(w) { r, err = exchangeWithRetry(s.dnsTCPclient, req, s.config.Nameservers[nsid]) } else { r, err = exchangeWithRetry(s.dnsUDPclient, req, s.config.Nameservers[nsid]) } if err == nil { r.Compress = true r.Id = req.Id w.WriteMsg(r) return r } // Seen an error, this can only mean, "server not reached", try again // but only if we have not exausted our nameservers. if try < len(s.config.Nameservers) { try++ nsid = (nsid + 1) % len(s.config.Nameservers) goto Redo } logf("failure to forward request %q", err) m := s.ServerFailure(req) return m }
func serve(w dns.ResponseWriter, req *dns.Msg) { var resp dns.Msg var err error key := msgKey(req) cacheLock.Lock() cached, ok := cache[key] // cached value will not change until return because of SingleInflight cacheLock.Unlock() if !ok { log.Printf("%04X┐%s\n", req.Id, key) for attempt := 1; attempt <= queryAttempts; attempt++ { cached, _, err = dnsclient.Exchange(req, *flUpstream) if err != nil { cacheLock.Lock() _, ok = cache[key] cacheLock.Unlock() if ok { // concurrent exchange succeeded err = nil break } sep := "·" if attempt == queryAttempts { sep = "╳" } log.Printf("%04X%s%s: [%d/%d] %v\n", req.Id, sep, key, attempt, queryAttempts, err) } } if err != nil { dns.HandleFailed(w, req) return } cacheLock.Lock() cached2, ok := cache[key] if ok { // concurrent exchange has already updated the cache cached = cached2 log.Printf("%04X┴%04X\n", req.Id, cached.Id) } else { cache[key] = cached log.Printf("%04X└%s = %s\n", req.Id, key, answersSummary(cached)) } cacheLock.Unlock() } resp = *cached resp.Id = req.Id err = w.WriteMsg(&resp) eprint(err) }
func pinguer(domain string) (int, int) { // Every N steps, we will tell the stats module how many requests we sent maxRequestID := big.NewInt(65536) errors := 0 totalSent := 0 questionRecord := dns.TypeA message := new(dns.Msg).SetQuestion(domain, questionRecord) if iterative { message.RecursionDesired = false } for reqnumber := 0; count == 0 || reqnumber < count; reqnumber++ { // Try to resolve the domain if randomIds { // Regenerate message Id to avoid servers dropping (seemingly) duplicate messages newid, _ := rand.Int(rand.Reader, maxRequestID) message.Id = uint16(newid.Int64()) } start := time.Now() err := dnsExchange(resolver, message) elapsedMilliSeconds := float64(time.Since(start)) / float64(time.Millisecond) if err != nil { if verbose { fmt.Printf("%s error: % (%s)\n", domain, err, resolver) } errors++ } totalSent++ // Display results of the ping fmt.Printf( "ping %s with %s %s: %.3fms\n", resolver, dns.TypeToString[questionRecord], domain, elapsedMilliSeconds, ) time.Sleep(time.Duration(pingInterval) * time.Millisecond) } return totalSent, errors }
func (resolver ConsulDnsAddressResolver) Resolve(service string) (string, error) { m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.SetQuestion(service+".service.consul.", dns.TypeA) c := new(dns.Client) in, _, err := c.Exchange(m1, resolver.ServerAddress) if err != nil { log.Fatal(err) } if len(in.Answer) > 0 { log.Println(in.Answer) return in.Answer[0].(*dns.A).A.String(), nil } return "", errors.New("Could not resolve service address") }
func findSoaNs(domain string) (string, string, string) { var cname string var soa string var ns string add := func(c, s, n string) { cname += c soa += s ns += n return } cname += domain + "," m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.Question = make([]dns.Question, 1) m1.Question[0] = dns.Question{domain, dns.TypeSOA, dns.ClassINET} in, _ := dns.Exchange(m1, (cf.Servers[1] + ":53")) rrList := [...][]dns.RR{in.Answer, in.Ns, in.Extra} for _, rr := range rrList { for i := len(rr) - 1; i >= 0; i-- { switch rr[i].Header().Rrtype { case dns.TypeCNAME: temp_cname := rr[i].(*dns.CNAME) add(findSoaNs(temp_cname.Target)) // fmt.Println( "temp_cname:" , temp_cname ) return cname, soa, ns break case dns.TypeNS: temp_ns := rr[i].(*dns.NS) ns += temp_ns.Ns + "," // + "|" + fmt.Sprint( temp_ns.Hdr.Ttl ) + "," // fmt.Println( "temp_ns:" , temp_ns ) break case dns.TypeSOA: temp_soa := rr[i].(*dns.SOA) soa += temp_soa.Ns + "," // + "|" + fmt.Sprint( temp_soa.Hdr.Ttl ) + "," // fmt.Println( "temp_soa:" , temp_soa ) break } } } return cname, soa, ns }
func (this *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer { buffer := alloc.NewBuffer() msg := new(dns.Msg) msg.Id = id msg.RecursionDesired = true msg.Question = []dns.Question{ dns.Question{ Name: dns.Fqdn(domain), Qtype: dns.TypeA, Qclass: dns.ClassINET, }} writtenBuffer, _ := msg.PackBuffer(buffer.Value) buffer.Slice(0, len(writtenBuffer)) return buffer }
func route(w dns.ResponseWriter, req *dns.Msg) { if len(req.Question) != 1 { failWithRcode(w, req, dns.RcodeRefused) return } question := req.Question[0] qtype := question.Qtype if question.Qclass != dns.ClassINET { failWithRcode(w, req, dns.RcodeRefused) return } remoteIP := w.RemoteAddr().(*net.UDPAddr).IP m := new(dns.Msg) m.Id = req.Id switch qtype { case dns.TypeA: if remoteIP4 := remoteIP.To4(); remoteIP4 != nil { rr := new(dns.A) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.A = remoteIP4 m.Answer = []dns.RR{rr} } case dns.TypeAAAA: if remoteIP16 := remoteIP.To16(); remoteIP16 != nil { rr := new(dns.AAAA) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.AAAA = remoteIP16 m.Answer = []dns.RR{rr} } case dns.TypeTXT: rr := new(dns.TXT) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.Txt = []string{fmt.Sprintf("Resolver IP: %v", remoteIP.String())} m.Answer = []dns.RR{rr} } m.Question = req.Question m.Response = true m.Authoritative = true w.WriteMsg(m) }
func linearResolver(threadID int, domain string, sentCounterCh chan<- result) { // Resolve the domain as fast as possible if verbose { fmt.Printf("Starting thread #%d.\n", threadID) } // Every N steps, we will tell the stats module how many requests we sent displayStep := 5 maxRequestID := big.NewInt(65536) errors := 0 message := new(dns.Msg).SetQuestion(domain, dns.TypeA) if iterative { message.RecursionDesired = false } for { for i := 0; i < displayStep; i++ { // Try to resolve the domain if randomIds { // Regenerate message Id to avoid servers dropping (seemingly) duplicate messages newid, _ := rand.Int(rand.Reader, maxRequestID) message.Id = uint16(newid.Int64()) } if flood { go dnsExchange(resolver, message) } else { err := dnsExchange(resolver, message) if err != nil { if verbose { fmt.Printf("%s error: % (%s)\n", domain, err, resolver) } errors++ } } } // Update the counter of sent requests and requests sentCounterCh <- result{displayStep, errors} errors = 0 } }
/* * makeMessage() - construct DNS message structure */ func makeMessage(c *Context, qname, qtype, qclass string, ext Extension) *dns.Msg { m := new(dns.Msg) m.Id = dns.Id() if c.restype == RESOLUTION_STUB { m.RecursionDesired = true } else { m.RecursionDesired = false } if c.adflag { m.AuthenticatedData = true } if c.cdflag { m.CheckingDisabled = true } if ext["dnssec_return_status"] || ext["dnssec_return_only_secure"] || ext["dnssec_return_validation_chain"] { opt := new(dns.OPT) opt.Hdr.Name = "." opt.Hdr.Rrtype = dns.TypeOPT opt.SetDo() m.Extra = append(m.Extra, opt) } m.Question = make([]dns.Question, 1) qtype_int, ok := dns.StringToType[strings.ToUpper(qtype)] if !ok { fmt.Printf("%s: Unrecognized query type.\n", qtype) return nil } qclass_int, ok := dns.StringToClass[strings.ToUpper(qclass)] if !ok { fmt.Printf("%s: Unrecognized query class.\n", qclass) return nil } m.Question[0] = dns.Question{qname, qtype_int, qclass_int} return m }
// dnsLookup is used whenever we need to conduct a DNS query over a given TCP connection func DnsLookup(addr string, conn net.Conn) (*DnsResponse, error) { //log.Printf("Doing a DNS lookup on %s", addr) dnsResponse := &DnsResponse{ records: make([]DNSRecord, 0), } // create the connection to the DNS server dnsConn := &dns.Conn{Conn: conn} defer dnsConn.Close() m := new(dns.Msg) m.Id = dns.Id() // set the question section in the dns query // Fqdn returns the fully qualified domain name m.SetQuestion(dns.Fqdn(addr), dns.TypeA) m.RecursionDesired = true dnsConn.WriteMsg(m) response, err := dnsConn.ReadMsg() if err != nil { log.Printf("Could not process DNS response: %v", err) return nil, err } now := time.Now() // iterate over RRs containing the DNS answer for _, answer := range response.Answer { if a, ok := answer.(*dns.A); ok { // append the result to our list of records // the A records in the RDATA section of the DNS answer // contains the actual IP address dnsResponse.records = append(dnsResponse.records, DNSRecord{ IP: a.A, ExpireAt: now.Add(time.Duration(a.Hdr.Ttl) * time.Second), }) //log.Printf("###TTL:%d", a.Hdr.Ttl) } } return dnsResponse, nil }
func (v *UDPNameServer) BuildQueryA(domain string, id uint16) *buf.Buffer { msg := new(dns.Msg) msg.Id = id msg.RecursionDesired = true msg.Question = []dns.Question{ { Name: dns.Fqdn(domain), Qtype: dns.TypeA, Qclass: dns.ClassINET, }} buffer := buf.New() buffer.AppendSupplier(func(b []byte) (int, error) { writtenBuffer, err := msg.PackBuffer(b) return len(writtenBuffer), err }) return buffer }
// Get a single metric from dnsmasq. Returns the numeric value of the // metric. func (mc *metricsClient) getSingleMetric(name string) (int64, error) { msg := new(dns.Msg) msg.Id = dns.Id() msg.RecursionDesired = false msg.Question = make([]dns.Question, 1) msg.Question[0] = dns.Question{ Name: name, Qtype: dns.TypeTXT, Qclass: dns.ClassCHAOS, } in, _, err := mc.dnsClient.Exchange(msg, mc.addrPort) if err != nil { return 0, err } if len(in.Answer) != 1 { return 0, fmt.Errorf("Invalid number of Answer records for %s: %d", name, len(in.Answer)) } if t, ok := in.Answer[0].(*dns.TXT); ok { glog.V(4).Infof("Got valid TXT response %+v for %s", t, name) if len(t.Txt) != 1 { return 0, fmt.Errorf("Invalid number of TXT records for %s: %d", name, len(t.Txt)) } value, err := strconv.ParseInt(t.Txt[0], 10, 64) if err != nil { return 0, err } return value, nil } return 0, fmt.Errorf("missing txt record for %s", name) }
func (r Resolver) ResolveA(addr string) (net.IP, bool) { // log.Println("Looking up A for " + addr) m1 := new(dns.Msg) m1.Id = dns.Id() m1.RecursionDesired = true m1.Question = make([]dns.Question, 1) m1.Question[0] = dns.Question{addr, dns.TypeA, dns.ClassINET} c := new(dns.Client) in, _, err := c.Exchange(m1, "10.1.3.254:53") if err != nil { log.Println("Failed on c.Exchange call: " + err.Error()) return nil, false } if a, ok := in.Answer[0].(*dns.A); ok { // log.Println("I found an answer for " + addr) return a.A, true } // log.Println("Nothing found for " + addr) return nil, false }