summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/miekg/dns/xfr.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/miekg/dns/xfr.go')
-rw-r--r--vendor/github.com/miekg/dns/xfr.go59
1 files changed, 32 insertions, 27 deletions
diff --git a/vendor/github.com/miekg/dns/xfr.go b/vendor/github.com/miekg/dns/xfr.go
index 576c5590a..2e892ea38 100644
--- a/vendor/github.com/miekg/dns/xfr.go
+++ b/vendor/github.com/miekg/dns/xfr.go
@@ -51,18 +51,18 @@ func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
env = make(chan *Envelope)
go func() {
if q.Question[0].Qtype == TypeAXFR {
- go t.inAxfr(q.Id, env)
+ go t.inAxfr(q, env)
return
}
if q.Question[0].Qtype == TypeIXFR {
- go t.inIxfr(q.Id, env)
+ go t.inIxfr(q, env)
return
}
}()
return env, nil
}
-func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
+func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
first := true
defer t.Close()
defer close(c)
@@ -77,7 +77,7 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
c <- &Envelope{nil, err}
return
}
- if id != in.Id {
+ if q.Id != in.Id {
c <- &Envelope{in.Answer, ErrId}
return
}
@@ -110,9 +110,11 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
}
}
-func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
+func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
serial := uint32(0) // The first serial seen is the current server serial
- first := true
+ axfr := true
+ n := 0
+ qser := q.Ns[0].(*SOA).Serial
defer t.Close()
defer close(c)
timeout := dnsTimeout
@@ -126,21 +128,15 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
c <- &Envelope{nil, err}
return
}
- if id != in.Id {
+ if q.Id != in.Id {
c <- &Envelope{in.Answer, ErrId}
return
}
- if first {
- if in.Rcode != RcodeSuccess {
- c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
- return
- }
- // A single SOA RR signals "no changes"
- if len(in.Answer) == 1 && isSOAFirst(in) {
- c <- &Envelope{in.Answer, nil}
- return
- }
-
+ if in.Rcode != RcodeSuccess {
+ c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
+ return
+ }
+ if n == 0 {
// Check if the returned answer is ok
if !isSOAFirst(in) {
c <- &Envelope{in.Answer, ErrSoa}
@@ -148,21 +144,30 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
}
// This serial is important
serial = in.Answer[0].(*SOA).Serial
- first = !first
+ // Check if there are no changes in zone
+ if qser >= serial {
+ c <- &Envelope{in.Answer, nil}
+ return
+ }
}
-
// Now we need to check each message for SOA records, to see what we need to do
- if !first {
- t.tsigTimersOnly = true
- // If the last record in the IXFR contains the servers' SOA, we should quit
- if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
+ t.tsigTimersOnly = true
+ for _, rr := range in.Answer {
+ if v, ok := rr.(*SOA); ok {
if v.Serial == serial {
- c <- &Envelope{in.Answer, nil}
- return
+ n++
+ // quit if it's a full axfr or the the servers' SOA is repeated the third time
+ if axfr && n == 2 || n == 3 {
+ c <- &Envelope{in.Answer, nil}
+ return
+ }
+ } else if axfr {
+ // it's an ixfr
+ axfr = false
}
}
- c <- &Envelope{in.Answer, nil}
}
+ c <- &Envelope{in.Answer, nil}
}
}