Merge branch 'master' of github.com:miekg/dns
This commit is contained in:
commit
fbe3e80256
3
dns.go
3
dns.go
|
@ -61,7 +61,8 @@
|
||||||
// c := new(Client)
|
// c := new(Client)
|
||||||
// in, err := c.Exchange(m1, "127.0.0.1:53")
|
// in, err := c.Exchange(m1, "127.0.0.1:53")
|
||||||
//
|
//
|
||||||
// An asynchronous query is also possible, see client.Do and client.DoRtt.
|
// An asynchronous query is also possible, see client.Do or client.DoRtt, when
|
||||||
|
// you are interested in the round trip time of the exchange.
|
||||||
//
|
//
|
||||||
// From a birds eye view a dns message consists out of four sections.
|
// From a birds eye view a dns message consists out of four sections.
|
||||||
// The question section: in.Question, the answer section: in.Answer,
|
// The question section: in.Question, the answer section: in.Answer,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Go equivalent of the "DNS & BIND" book check-soa program.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -19,18 +20,12 @@ var (
|
||||||
conf *dns.ClientConfig
|
conf *dns.ClientConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
func localQuery(qname string, qtype uint16) (r *dns.Msg, err error) {
|
func localQuery(qname string, qtype uint16) (*dns.Msg, error) {
|
||||||
localm.Question[0] = dns.Question{qname, qtype, dns.ClassINET}
|
localm.SetQuestion(qname, qtype)
|
||||||
for serverIndex := range conf.Servers {
|
for i := range conf.Servers {
|
||||||
server := conf.Servers[serverIndex]
|
server := conf.Servers[i]
|
||||||
r, err := localc.Exchange(localm, server+":"+conf.Port)
|
r, err := localc.Exchange(localm, server+":"+conf.Port)
|
||||||
if r == nil {
|
if r == nil || r.Rcode == dns.RcodeNameError || r.Rcode == dns.RcodeSuccess {
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if r.Rcode == dns.RcodeNameError {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
if r.Rcode == dns.RcodeSuccess {
|
|
||||||
return r, err
|
return r, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,17 +33,11 @@ func localQuery(qname string, qtype uint16) (r *dns.Msg, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var err error
|
||||||
err error
|
|
||||||
)
|
|
||||||
if len(os.Args) != 2 {
|
if len(os.Args) != 2 {
|
||||||
fmt.Printf("%s ZONE\n", os.Args[0])
|
fmt.Printf("%s ZONE\n", os.Args[0])
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
zone := os.Args[1]
|
|
||||||
if zone[len(zone)-1] != '.' {
|
|
||||||
zone += "."
|
|
||||||
}
|
|
||||||
conf, err = dns.ClientConfigFromFile("/etc/resolv.conf")
|
conf, err = dns.ClientConfigFromFile("/etc/resolv.conf")
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
fmt.Printf("Cannot initialize the local resolver: %s\n", err)
|
fmt.Printf("Cannot initialize the local resolver: %s\n", err)
|
||||||
|
@ -59,13 +48,13 @@ func main() {
|
||||||
localm.Question = make([]dns.Question, 1)
|
localm.Question = make([]dns.Question, 1)
|
||||||
localc = new(dns.Client)
|
localc = new(dns.Client)
|
||||||
localc.ReadTimeout = TIMEOUT * 1e9
|
localc.ReadTimeout = TIMEOUT * 1e9
|
||||||
r, err := localQuery(zone, dns.TypeNS)
|
r, err := localQuery(dns.Fqdn(os.Args[1]), dns.TypeNS)
|
||||||
if r == nil {
|
if r == nil {
|
||||||
fmt.Printf("Cannot retrieve the list of name servers for %s: %s\n", zone, err)
|
fmt.Printf("Cannot retrieve the list of name servers for %s: %s\n", dns.Fqdn(os.Args[1]), err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if r.Rcode == dns.RcodeNameError {
|
if r.Rcode == dns.RcodeNameError {
|
||||||
fmt.Printf("No such domain %s\n", zone)
|
fmt.Printf("No such domain %s\n", dns.Fqdn(os.Args[1]))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
|
@ -75,8 +64,7 @@ func main() {
|
||||||
c.ReadTimeout = TIMEOUT * 1e9
|
c.ReadTimeout = TIMEOUT * 1e9
|
||||||
success := true
|
success := true
|
||||||
numNS := 0
|
numNS := 0
|
||||||
for i := range r.Answer {
|
for _, ans := range r.Answer {
|
||||||
ans := r.Answer[i]
|
|
||||||
switch ans.(type) {
|
switch ans.(type) {
|
||||||
case *dns.RR_NS:
|
case *dns.RR_NS:
|
||||||
nameserver := ans.(*dns.RR_NS).Ns
|
nameserver := ans.(*dns.RR_NS).Ns
|
||||||
|
@ -92,8 +80,7 @@ func main() {
|
||||||
fmt.Printf("Error getting the IPv4 address of %s: %s\n", nameserver, dns.Rcode_str[ra.Rcode])
|
fmt.Printf("Error getting the IPv4 address of %s: %s\n", nameserver, dns.Rcode_str[ra.Rcode])
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
for j := range ra.Answer {
|
for _, ansa := range ra.Answer {
|
||||||
ansa := ra.Answer[j]
|
|
||||||
switch ansa.(type) {
|
switch ansa.(type) {
|
||||||
case *dns.RR_A:
|
case *dns.RR_A:
|
||||||
ips = append(ips, ansa.(*dns.RR_A).A.String())
|
ips = append(ips, ansa.(*dns.RR_A).A.String())
|
||||||
|
@ -108,8 +95,7 @@ func main() {
|
||||||
fmt.Printf("Error getting the IPv6 address of %s: %s\n", nameserver, dns.Rcode_str[raaaa.Rcode])
|
fmt.Printf("Error getting the IPv6 address of %s: %s\n", nameserver, dns.Rcode_str[raaaa.Rcode])
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
for j := range raaaa.Answer {
|
for _, ansaaaa := range raaaa.Answer {
|
||||||
ansaaaa := raaaa.Answer[j]
|
|
||||||
switch ansaaaa.(type) {
|
switch ansaaaa.(type) {
|
||||||
case *dns.RR_AAAA:
|
case *dns.RR_AAAA:
|
||||||
ips = append(ips, ansaaaa.(*dns.RR_AAAA).AAAA.String())
|
ips = append(ips, ansaaaa.(*dns.RR_AAAA).AAAA.String())
|
||||||
|
@ -119,54 +105,54 @@ func main() {
|
||||||
success = false
|
success = false
|
||||||
fmt.Printf("No IP address for this server")
|
fmt.Printf("No IP address for this server")
|
||||||
}
|
}
|
||||||
for j := range ips {
|
for _, ip := range ips {
|
||||||
m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET}
|
m.Question[0] = dns.Question{dns.Fqdn(os.Args[1]), dns.TypeSOA, dns.ClassINET}
|
||||||
nsAddressPort := ""
|
nsAddressPort := ""
|
||||||
if strings.ContainsAny(":", ips[j]) {
|
if strings.ContainsAny(":", ip) {
|
||||||
/* IPv6 address */
|
// IPv6 address
|
||||||
nsAddressPort = "[" + ips[j] + "]:53"
|
nsAddressPort = "[" + ip + "]:53"
|
||||||
} else {
|
} else {
|
||||||
nsAddressPort = ips[j] + ":53"
|
nsAddressPort = ip + ":53"
|
||||||
}
|
}
|
||||||
soa, err := c.Exchange(m, nsAddressPort)
|
soa, err := c.Exchange(m, nsAddressPort)
|
||||||
/* TODO: retry if timeout? Otherwise, one lost UDP packet and it is the end ... */
|
// TODO: retry if timeout? Otherwise, one lost UDP packet and it is the end
|
||||||
if soa == nil {
|
if soa == nil {
|
||||||
success = false
|
success = false
|
||||||
fmt.Printf("%s (%s) ", ips[j], err)
|
fmt.Printf("%s (%s) ", ip, err)
|
||||||
} else {
|
goto Next
|
||||||
if soa.Rcode != dns.RcodeSuccess {
|
}
|
||||||
success = false
|
if soa.Rcode != dns.RcodeSuccess {
|
||||||
fmt.Printf("%s (%s) ", ips[j], dns.Rcode_str[soa.Rcode])
|
success = false
|
||||||
|
fmt.Printf("%s (%s) ", ips, dns.Rcode_str[soa.Rcode])
|
||||||
|
goto Next
|
||||||
|
}
|
||||||
|
if len(soa.Answer) == 0 { // May happen if the server is a recursor, not authoritative, since we query with RD=0
|
||||||
|
success = false
|
||||||
|
fmt.Printf("%s (0 answer) ", ip)
|
||||||
|
goto Next
|
||||||
|
}
|
||||||
|
rsoa := soa.Answer[0]
|
||||||
|
switch rsoa.(type) {
|
||||||
|
case *dns.RR_SOA:
|
||||||
|
if soa.MsgHdr.Authoritative {
|
||||||
|
// TODO: test if all name servers have the same serial ?
|
||||||
|
fmt.Printf("%s (%d) ", ips, rsoa.(*dns.RR_SOA).Serial)
|
||||||
} else {
|
} else {
|
||||||
if len(soa.Answer) == 0 { /* May happen if the server is a recursor, not authoritative, since we query with RD=0 */
|
success = false
|
||||||
success = false
|
fmt.Printf("%s (not authoritative) ", ips)
|
||||||
fmt.Printf("%s (0 answer) ", ips[j])
|
|
||||||
} else {
|
|
||||||
rsoa := soa.Answer[0]
|
|
||||||
switch rsoa.(type) {
|
|
||||||
case *dns.RR_SOA:
|
|
||||||
if soa.MsgHdr.Authoritative {
|
|
||||||
/* TODO: test if all name servers have the same serial ? */
|
|
||||||
fmt.Printf("%s (%d) ", ips[j], rsoa.(*dns.RR_SOA).Serial)
|
|
||||||
} else {
|
|
||||||
success = false
|
|
||||||
fmt.Printf("%s (not authoritative) ", ips[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Next:
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if numNS == 0 {
|
if numNS == 0 {
|
||||||
fmt.Printf("No NS records for \"%s\". It is probably a CNAME to a domain but not a zone\n", zone)
|
fmt.Printf("No NS records for \"%s\". It is probably a CNAME to a domain but not a zone\n", dns.Fqdn(os.Args[1]))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if success {
|
if success {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
} else {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue