package main import ( "errors" "fmt" "log" "net" "strings" "sync" "time" "github.com/miekg/dns" ) var ( dnsStringToType sync.Map ) func dnsQtypeStringToValue(qtype string) uint16 { x, found_qtype := dnsStringToType.Load(qtype) if found_qtype { return x.(uint16) } for k, v := range dns.TypeToString { if v == qtype { dnsStringToType.Store(qtype, k) return k } } log.Printf("qtype %#v is not known or found", qtype) return dns.TypeNone } func dnsCustomResolve(qname string, qtype uint16) (*dns.Msg, error) { qtype_s, qtype_known := dns.TypeToString[qtype] if !qtype_known { log.Printf("qtype is not known (%v) for %v", qtype, qname) return nil, fmt.Errorf("qtype is not known: %v", qtype) } c := new(dns.Client) c.Net = cfgResolverProto c.Dialer = &net.Dialer{ Timeout: cfgResolverTimeout, } req := new(dns.Msg) req.Id = dns.Id() req.RecursionDesired = true req.Question = make([]dns.Question, 1) req.Question[0] = dns.Question{Name: qname, Qtype: qtype, Qclass: dns.ClassINET} var resp *dns.Msg var rtt time.Duration var err error for i := 0; i < 2; i++ { resp, rtt, err = c.Exchange(req, cfgResolverEndpoint) if err == nil { break } } if err != nil { log.Printf("resolving %v/%v (rtt %v) with error: %v", qname, qtype_s, rtt, err) return nil, err } log.Printf("resolved %v/%v (rtt %v)", qname, qtype_s, rtt) return resp, nil } func dnsClipTtl(ttl uint32) uint32 { if ttl < cfgTtlMin { return cfgTtlMin } if ttl > cfgTtlMax { return cfgTtlMax } return ttl } type PowerDnsAnswer struct { Qname string `json:"qname"` Qtype string `json:"qtype"` Ttl uint32 `json:"ttl"` Content string `json:"content"` } func dnsToPowerDnsAnswer(response *dns.Msg) ([]PowerDnsAnswer, error) { if response == nil { return nil, errors.New("response is nil") } result := make([]PowerDnsAnswer, 0, len(response.Answer)) for i := range response.Answer { cont, ok := strings.CutPrefix(response.Answer[i].String(), response.Answer[i].Header().String()) if !ok { continue } qtype, ok := dns.TypeToString[response.Answer[i].Header().Rrtype] if !ok { continue } rec := PowerDnsAnswer{ Qname: response.Answer[i].Header().Name, Qtype: qtype, Ttl: dnsClipTtl(response.Answer[i].Header().Ttl), Content: cont, } result = append(result, rec) } return result, nil }