I’ve implemented axfr in my Go DNS library in nice and Go-like way (at least that’s what I like to think). Starting an axfr results in a channel which can then be used with the range keyword to loop over it, until the entire axfr is received.

Using it

First the normal begin of a Go program:

package main
import (
    "fmt"
    "dns"           // DNS package
)

Then we start the main function in which we define a new resolver and a channel for receiving the axfr messages. The channels will send dns.xfr messages which is defined as:

type Xfr struct {
    Add bool // true is to be added, otherwise false
    RR
 }

This is facilitate IXFR handling, for an AXFR the bool is always set to true.

func main() {
    res := new(resolver.Resolver)
    res.FromFile("/etc/resolv.conf")

    ch := make(chan dns.xfr) 

Next we setup the server and the axfr query:

    res.Servers = []string{"127.0.0.1"}
    m := new(dns.Msg)
    m.Question = make([]dns.Question, 1)
    // We are asking for an AXFR of atoom.net in the IN class
    m.Question[0] = dns.Question{"atoom.net", dns.TypeAXFR, dns.ClassINET}

And now the fun part:

    // Ask the server to start the AXFR
    go res.Axfr(m, ch)

    // And then loop over the answers and print them
    for x := range ch {
        fmt.Printf("%v\n",x.RR)
    }
    // Done with axfr, note the channel is now closed
}

And that’s it.