Now that the API seems to stabilize it is time to update these items.

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 (
    "dns"
    "os"
    "fmt"
)

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:

  1. a new packet (dns.Msg);
  2. setting some header bits (dns.Msg.MsgHdr);
  3. define a question section;
  4. 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.MsgHdr.RecursionDesired = true

Then we need to finally ‘ask’ the question. We do this by calling the Exchange() function.

r, err := c.Exchange(m, config.Servers[0]+":"+config.Port)

Check if we got something sane. The following code snippet prints the answer section of the received packet:

if r != nil {
        if r.Rcode != dns.RcodeSuccess {
                fmt.Printf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
                os.Exit(1)
        }
        // Stuff must be in the answer section
        for _, a := range r.Answer {
                fmt.Printf("%v\n", a)
        }
} else {
        fmt.Printf("*** error: %s\n", err.String())
}

And we are done.

Full source

The full source of mx.go can be found over at github. Compiling works with go build.