Printing MX records with Go DNS, take 3
I’m starting to get really happy about the Go DNS API, so invasive API changes are less and less likely.
We want to create a little program that prints out the MX records of domains, like so:
% mx miek.nl
miek.nl. 86400 IN MX 10 elektron.atoom.net.
Or
% mx microsoft.com
microsoft.com. 3600 IN MX 10 mail.messaging.microsoft.com.
We are using my Go DNS package.
First the normal header of a Go program, with a bunch of imports. We
need the dns
package:
package main
import (
"github.com/miekg/dns"
"os"
"net"
"fmt"
"log"
)
Next we need to get the local nameserver to use:
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
Then we create a dns.Client
to perform the queries for us. In Go:
c := new(dns.Client)
We skip some error handling and assume a zone name is given. So we prepare our question. For that to work, we need:
- a new packet (
dns.Msg
); - setting some header bits;
- define a question section;
- fill out the question section:
os.Args[1]
contains the zone name.
Which translates into:
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
m.RecursionDesired = true
Then we need to finally ‘ask’ the question. We
do this by calling the Exchange()
function. The unused return value
is the rtt
(round trip time).
r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
Check if we got something sane. The following code snippet prints the answer section of the received packet:
Bail out on an error:
if r == nil {
log.Fatalf("*** error: %s\n", err.Error())
}
if r.Rcode != dns.RcodeSuccess {
log.Fatalf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
}
// Stuff must be in the answer section
for _, a := range r.Answer {
fmt.Printf("%v\n", a)
}
And we are done.
Full Source⌗
package main
import (
"github.com/miekg/dns"
"net"
"os"
"log"
"fmt"
)
func main() {
config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
m.RecursionDesired = true
r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
if r == nil {
log.Fatalf("*** error: %s\n", err.Error())
}
if r.Rcode != dns.RcodeSuccess {
log.Fatalf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
}
// Stuff must be in the answer section
for _, a := range r.Answer {
fmt.Printf("%v\n", a)
}
}