83 строки
2.0 KiB
Go
83 строки
2.0 KiB
Go
package cdns
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
func soaQuery(mychan chan SOAreply, zone string, name string, server string) {
|
|
var result SOAreply
|
|
var trials uint
|
|
result.retrieved = false
|
|
result.name = name
|
|
result.address = server
|
|
result.msg = "UNKNOWN"
|
|
m := new(dns.Msg)
|
|
if !noedns {
|
|
m.SetEdns0(bufsize, !nodnssec)
|
|
}
|
|
m.Id = dns.Id()
|
|
if recursion {
|
|
m.RecursionDesired = true
|
|
} else {
|
|
m.RecursionDesired = false
|
|
}
|
|
m.Question = make([]dns.Question, 1)
|
|
c := new(dns.Client)
|
|
c.ReadTimeout = timeout // Seems ignored for TCP?
|
|
if tcp {
|
|
c.Net = "tcp"
|
|
}
|
|
m.Question[0] = dns.Question{Name: zone, Qtype: dns.TypeSOA, Qclass: dns.ClassINET}
|
|
nsAddressPort := net.JoinHostPort(server, "53")
|
|
if debug {
|
|
fmt.Printf("DEBUG Querying SOA from %s\n", nsAddressPort)
|
|
}
|
|
for trials = 0; trials < uint(maxTrials); trials++ {
|
|
soa, rtt, err := c.Exchange(m, nsAddressPort)
|
|
if soa == nil {
|
|
result.rtt = 0
|
|
result.msg = err.Error()
|
|
} else {
|
|
result.rtt = rtt
|
|
if soa.Rcode != dns.RcodeSuccess {
|
|
result.msg = dns.RcodeToString[soa.Rcode]
|
|
break
|
|
}
|
|
if len(soa.Answer) == 0 { /* May happen if the server is a recursor, not authoritative, since we query with RD=0 */
|
|
result.msg = "0 answer"
|
|
break
|
|
} else { //nolint:revive // complex nested structure
|
|
gotSoa := false
|
|
for _, rsoa := range soa.Answer {
|
|
switch r := rsoa.(type) {
|
|
case *dns.SOA:
|
|
if noauthrequired || soa.Authoritative {
|
|
result.retrieved = true
|
|
result.serial = r.Serial
|
|
result.msg = "OK"
|
|
} else {
|
|
result.msg = "Not authoritative"
|
|
}
|
|
gotSoa = true
|
|
case *dns.CNAME: /* Bad practice but common */
|
|
result.msg = "Apparently not a zone but an alias"
|
|
case *dns.RRSIG:
|
|
/* Ignore them. See bug #8 */
|
|
default:
|
|
// TODO: a name server can send us other RR types.
|
|
result.msg = fmt.Sprintf("Internal error when processing %s, unexpected record type\n", rsoa)
|
|
}
|
|
}
|
|
if !gotSoa {
|
|
result.msg = "No SOA record in reply"
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
mychan <- result
|
|
}
|