Fixes for axfr,ixfr
This commit is contained in:
parent
2b5a97570a
commit
c1297a4f9c
|
@ -9,7 +9,7 @@ func main() {
|
|||
res := new(dns.Resolver)
|
||||
res.FromFile("/etc/resolv.conf")
|
||||
|
||||
ch := make(chan *dns.Msg)
|
||||
ch := make(chan dns.RR)
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.Question = make([]dns.Question, 1)
|
||||
|
|
197
resolver.go
197
resolver.go
|
@ -94,94 +94,11 @@ func (res *Resolver) Query(q *Msg) (d *Msg, err os.Error) {
|
|||
return in, nil
|
||||
}
|
||||
|
||||
// Start an AXFR, q should contain a message with the question
|
||||
// for an AXFR: "miek.nl" ANY AXFR. All incoming axfr snippets
|
||||
// are returned on the channel m. The function closes the
|
||||
// channel to signal the end of the AXFR.
|
||||
func (res *Resolver) Ixfr(q *Msg, m chan *Msg) {
|
||||
var port string
|
||||
var err os.Error
|
||||
var in *Msg
|
||||
if res.Port == "" {
|
||||
port = "53"
|
||||
} else {
|
||||
port = res.Port
|
||||
}
|
||||
|
||||
var _ = err // TODO(mg)
|
||||
|
||||
if q.Id == 0 {
|
||||
q.SetId()
|
||||
}
|
||||
|
||||
sending, ok := q.Pack()
|
||||
if !ok {
|
||||
m <- nil
|
||||
return
|
||||
}
|
||||
|
||||
Server:
|
||||
for i := 0; i < len(res.Servers); i++ {
|
||||
server := res.Servers[i] + ":" + port
|
||||
c, cerr := net.Dial("tcp", "", server)
|
||||
if cerr != nil {
|
||||
err = cerr
|
||||
continue Server
|
||||
}
|
||||
first := true
|
||||
// Start the AXFR
|
||||
for {
|
||||
if first {
|
||||
in, cerr = exchangeTCP(c, sending, res, true)
|
||||
} else {
|
||||
in, err = exchangeTCP(c, sending, res, false)
|
||||
}
|
||||
|
||||
if cerr != nil {
|
||||
// Failed to send, try the next
|
||||
err = cerr
|
||||
c.Close()
|
||||
continue Server
|
||||
}
|
||||
if in.Id != q.Id {
|
||||
m <- nil
|
||||
return
|
||||
}
|
||||
|
||||
if first {
|
||||
if !checkSOA(in, true) {
|
||||
c.Close()
|
||||
continue Server
|
||||
}
|
||||
m <- in
|
||||
first = !first
|
||||
}
|
||||
|
||||
if !first {
|
||||
if !checkSOA(in, false) {
|
||||
// Soa record not the last one
|
||||
m <- in
|
||||
continue
|
||||
} else {
|
||||
c.Close()
|
||||
m <- in
|
||||
close(m)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("not reached")
|
||||
return
|
||||
}
|
||||
close(m)
|
||||
return
|
||||
}
|
||||
|
||||
// Start an IXFR, q should contain a message with the question
|
||||
// for an IXFR: "miek.nl" ANY IXFR. All incoming ixfr snippets
|
||||
// are returned on the channel m. The function closes the
|
||||
// channel to signal the end of the IXFR.
|
||||
func (res *Resolver) Axfr(q *Msg, m chan *Msg) {
|
||||
func (res *Resolver) Ixfr(q *Msg, m chan RR) {
|
||||
var port string
|
||||
var err os.Error
|
||||
var in *Msg
|
||||
|
@ -203,6 +120,7 @@ func (res *Resolver) Axfr(q *Msg, m chan *Msg) {
|
|||
return
|
||||
}
|
||||
|
||||
defer close(m)
|
||||
Server:
|
||||
for i := 0; i < len(res.Servers); i++ {
|
||||
server := res.Servers[i] + ":" + port
|
||||
|
@ -212,7 +130,10 @@ Server:
|
|||
continue Server
|
||||
}
|
||||
first := true
|
||||
// Start the AXFR
|
||||
var serial int // The first serial seen is the current server serial
|
||||
var _ = serial
|
||||
|
||||
defer c.Close()
|
||||
for {
|
||||
if first {
|
||||
in, cerr = exchangeTCP(c, sending, res, true)
|
||||
|
@ -227,28 +148,112 @@ Server:
|
|||
continue Server
|
||||
}
|
||||
if in.Id != q.Id {
|
||||
m <- nil
|
||||
// Query ID mismatch
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if first {
|
||||
// A single SOA RR signals "no changes"
|
||||
if len(in.Answer) == 1 && checkSOA(in, true) {
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// But still check if the returned answer is ok
|
||||
if !checkSOA(in, true) {
|
||||
c.Close()
|
||||
continue Server
|
||||
}
|
||||
// This serial is important
|
||||
serial = int(in.Answer[0].(*RR_SOA).Serial)
|
||||
sendFromMsg(in, m)
|
||||
first = !first
|
||||
}
|
||||
|
||||
// Now we need to check each message for SOA records, to see what we need to do
|
||||
if !first {
|
||||
|
||||
}
|
||||
}
|
||||
panic("not reached")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Start an AXFR, q should contain a message with the question
|
||||
// for an AXFR: "miek.nl" ANY AXFR. All incoming axfr snippets
|
||||
// are returned on the channel m. The function closes the
|
||||
// channel to signal the end of the AXFR.
|
||||
func (res *Resolver) Axfr(q *Msg, m chan RR) {
|
||||
var port string
|
||||
var err os.Error
|
||||
var in *Msg
|
||||
if res.Port == "" {
|
||||
port = "53"
|
||||
} else {
|
||||
port = res.Port
|
||||
}
|
||||
|
||||
var _ = err // TODO(mg)
|
||||
|
||||
if q.Id == 0 {
|
||||
q.SetId()
|
||||
}
|
||||
|
||||
sending, ok := q.Pack()
|
||||
if !ok {
|
||||
m <- nil
|
||||
return
|
||||
}
|
||||
|
||||
defer close(m)
|
||||
Server:
|
||||
for i := 0; i < len(res.Servers); i++ {
|
||||
server := res.Servers[i] + ":" + port
|
||||
c, cerr := net.Dial("tcp", "", server)
|
||||
if cerr != nil {
|
||||
err = cerr
|
||||
continue Server
|
||||
}
|
||||
first := true
|
||||
defer c.Close() // TODO(mg): if not open?
|
||||
for {
|
||||
if first {
|
||||
in, cerr = exchangeTCP(c, sending, res, true)
|
||||
} else {
|
||||
in, err = exchangeTCP(c, sending, res, false)
|
||||
}
|
||||
|
||||
if cerr != nil {
|
||||
// Failed to send, try the next
|
||||
err = cerr
|
||||
c.Close()
|
||||
continue Server
|
||||
}
|
||||
if in.Id != q.Id {
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if first {
|
||||
if !checkSOA(in, true) {
|
||||
c.Close()
|
||||
c.Close()
|
||||
continue Server
|
||||
}
|
||||
m <- in
|
||||
sendFromMsg(in, m)
|
||||
first = !first
|
||||
}
|
||||
|
||||
if !first {
|
||||
if !checkSOA(in, false) {
|
||||
// Soa record not the last one
|
||||
m <- in
|
||||
sendFromMsg(in, m)
|
||||
continue
|
||||
} else {
|
||||
c.Close()
|
||||
m <- in
|
||||
close(m)
|
||||
c.Close()
|
||||
sendFromMsg(in, m)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +261,6 @@ Server:
|
|||
panic("not reached")
|
||||
return
|
||||
}
|
||||
close(m)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -431,3 +435,10 @@ func checkSOA(in *Msg, first bool) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Send the answer section to the channel
|
||||
func sendFromMsg(in *Msg, c chan RR) {
|
||||
for _, r := range in.Answer {
|
||||
c <- r
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue