package main import ( "fmt" "github.com/miekg/dns" "strings" ) func (r *resolver) lookup(qname string) error { c := new(dns.Client) t := new(dns.Transfer) c.Net = "udp" if *four { c.Net = "udp4" } if *six { c.Net = "udp6" } if *tcp { c.Net = "tcp" if *four { c.Net = "tcp4" } if *six { c.Net = "tcp6" } } m := &dns.Msg{ MsgHdr: dns.MsgHdr{ Authoritative: false, AuthenticatedData: false, CheckingDisabled: false, RecursionDesired: true, Opcode: "query", }, Question: make([]dns.Question, 1), } if op, ok := dns.StringToOpcode[strings.ToUpper(*opcode)]; ok { m.Opcode = op } m.Rcode = dns.RcodeSuccess if rc, ok := dns.StringToRcode[strings.ToUpper(*rcode)]; ok { m.Rcode = rc } Query: for i, v := range qname { if i < len(qtype) { qt = qtype[i] } if i < len(qclass) { qc = qclass[i] } m.Question[0] = dns.Question{Name: dns.Fqdn(v), Qtype: qt, Qclass: qc} m.Id = dns.Id() if *query { fmt.Printf("%s", m.String()) fmt.Printf("\n;; size: %d bytes\n\n", m.Len()) } r, rtt, err := c.Exchange(m, nameserver) Redo: switch err { case nil: //do nothing case dns.ErrTruncated: if *fallback { if !*dnssec { fmt.Printf(";; Truncated, trying %d bytes bufsize\n", dns.DefaultMsgSize) o := new(dns.OPT) o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT o.SetUDPSize(dns.DefaultMsgSize) m.Extra = append(m.Extra, o) r, rtt, err = c.Exchange(m, nameserver) *dnssec = true goto Redo } else { // First EDNS, then TCP fmt.Printf(";; Truncated, trying TCP\n") c.Net = "tcp" r, rtt, err = c.Exchange(m, nameserver) *fallback = false goto Redo } } fmt.Printf(";; Truncated\n") default: fmt.Printf(";; %s\n", err.Error()) continue } if r.Id != m.Id { fmt.Fprintf(os.Stderr, "Id mismatch\n") return } if *short { // shortenMsg(r) } fmt.Printf("%v", r) fmt.Printf("\n;; query time: %.3d µs, server: %s(%s), size: %d bytes\n", rtt/1e3, nameserver, c.Net, r.Len()) } }