Fix make IXFR work with single line answers (#507)
This commit is contained in:
parent
5f64fb22f9
commit
be519e51ff
59
xfr.go
59
xfr.go
|
@ -51,18 +51,18 @@ func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
||||||
env = make(chan *Envelope)
|
env = make(chan *Envelope)
|
||||||
go func() {
|
go func() {
|
||||||
if q.Question[0].Qtype == TypeAXFR {
|
if q.Question[0].Qtype == TypeAXFR {
|
||||||
go t.inAxfr(q.Id, env)
|
go t.inAxfr(q, env)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if q.Question[0].Qtype == TypeIXFR {
|
if q.Question[0].Qtype == TypeIXFR {
|
||||||
go t.inIxfr(q.Id, env)
|
go t.inIxfr(q, env)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
|
||||||
first := true
|
first := true
|
||||||
defer t.Close()
|
defer t.Close()
|
||||||
defer close(c)
|
defer close(c)
|
||||||
|
@ -77,7 +77,7 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
||||||
c <- &Envelope{nil, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != in.Id {
|
if q.Id != in.Id {
|
||||||
c <- &Envelope{in.Answer, ErrId}
|
c <- &Envelope{in.Answer, ErrId}
|
||||||
return
|
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
|
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 t.Close()
|
||||||
defer close(c)
|
defer close(c)
|
||||||
timeout := dnsTimeout
|
timeout := dnsTimeout
|
||||||
|
@ -126,21 +128,15 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||||
c <- &Envelope{nil, err}
|
c <- &Envelope{nil, err}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if id != in.Id {
|
if q.Id != in.Id {
|
||||||
c <- &Envelope{in.Answer, ErrId}
|
c <- &Envelope{in.Answer, ErrId}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if first {
|
if in.Rcode != RcodeSuccess {
|
||||||
if in.Rcode != RcodeSuccess {
|
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||||
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
return
|
||||||
return
|
}
|
||||||
}
|
if n == 0 {
|
||||||
// A single SOA RR signals "no changes"
|
|
||||||
if len(in.Answer) == 1 && isSOAFirst(in) {
|
|
||||||
c <- &Envelope{in.Answer, nil}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the returned answer is ok
|
// Check if the returned answer is ok
|
||||||
if !isSOAFirst(in) {
|
if !isSOAFirst(in) {
|
||||||
c <- &Envelope{in.Answer, ErrSoa}
|
c <- &Envelope{in.Answer, ErrSoa}
|
||||||
|
@ -148,21 +144,30 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||||
}
|
}
|
||||||
// This serial is important
|
// This serial is important
|
||||||
serial = in.Answer[0].(*SOA).Serial
|
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
|
// Now we need to check each message for SOA records, to see what we need to do
|
||||||
if !first {
|
t.tsigTimersOnly = true
|
||||||
t.tsigTimersOnly = true
|
for _, rr := range in.Answer {
|
||||||
// If the last record in the IXFR contains the servers' SOA, we should quit
|
if v, ok := rr.(*SOA); ok {
|
||||||
if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
|
|
||||||
if v.Serial == serial {
|
if v.Serial == serial {
|
||||||
c <- &Envelope{in.Answer, nil}
|
n++
|
||||||
return
|
// 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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue