Implementing IXFR

This commit is contained in:
Miek Gieben 2011-02-25 21:17:17 +01:00
parent c1297a4f9c
commit fef5d323bb
2 changed files with 40 additions and 9 deletions

View File

@ -3,20 +3,37 @@ package main
import (
"fmt"
"dns"
"flag"
)
func main() {
var serial *int = flag.Int("serial", 0, "Perform an IXFR with the given serial")
flag.Parse()
res := new(dns.Resolver)
res.FromFile("/etc/resolv.conf")
res.Servers[0] = "213.154.224.1"
ch := make(chan dns.RR)
m := new(dns.Msg)
m.Question = make([]dns.Question, 1)
m.Question[0] = dns.Question{"atoom.net", dns.TypeAXFR, dns.ClassINET}
if *serial > 0 {
m.Question[0] = dns.Question{"tjeb.nl.", dns.TypeIXFR, dns.ClassINET}
soa := new(dns.RR_SOA)
soa.Hdr = dns.RR_Header{"tjeb.nl.", dns.TypeSOA, dns.ClassINET, 14400, 0}
soa.Serial = uint32(*serial)
m.Ns = make([]dns.RR, 1)
m.Ns[0] = soa
go res.Ixfr(m, ch)
} else {
m.Question[0] = dns.Question{"tjeb.nl.", dns.TypeAXFR, dns.ClassINET}
go res.Axfr(m, ch)
}
go res.Axfr(m, ch)
for x := range ch {
for x := range ch {
fmt.Printf("%v\n",x)
}
}

View File

@ -120,6 +120,12 @@ func (res *Resolver) Ixfr(q *Msg, m chan RR) {
return
}
const (
FIRST = iota
SECOND
LAST
)
defer close(m)
Server:
for i := 0; i < len(res.Servers); i++ {
@ -129,13 +135,13 @@ Server:
err = cerr
continue Server
}
first := true
state := FIRST
var serial int // The first serial seen is the current server serial
var _ = serial
defer c.Close()
for {
if first {
if state == FIRST {
in, cerr = exchangeTCP(c, sending, res, true)
} else {
in, err = exchangeTCP(c, sending, res, false)
@ -153,7 +159,7 @@ Server:
return
}
if first {
if state == FIRST {
// A single SOA RR signals "no changes"
if len(in.Answer) == 1 && checkSOA(in, true) {
c.Close()
@ -168,12 +174,20 @@ Server:
// This serial is important
serial = int(in.Answer[0].(*RR_SOA).Serial)
sendFromMsg(in, m)
first = !first
state = SECOND
}
// Now we need to check each message for SOA records, to see what we need to do
if !first {
if state != FIRST {
if !checkSOA(in, false) {
// Soa record not the last one
sendFromMsg(in, m)
continue
} else{
c.Close()
sendFromMsg(in, m)
return
}
}
}
panic("not reached")