Support outgoing zone transfers

These can be enabled by adding "transfer out" to the Corefile. Without
it no AXFR is allowed.

For now only AXFR and no IXFR. No TSIG and no ACLs.
This commit is contained in:
Miek Gieben
2016-03-28 12:08:05 +01:00
parent 6324bb1fa7
commit e56d206542
10 changed files with 195 additions and 27 deletions

61
middleware/file/xfr.go Normal file
View File

@@ -0,0 +1,61 @@
package file
import (
"fmt"
"github.com/miekg/coredns/middleware"
"github.com/miekg/dns"
"golang.org/x/net/context"
)
type (
Xfr struct {
*Zone
}
)
// Serve an AXFR (or maybe later an IXFR) as well.
func (x Xfr) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := middleware.State{W: w, Req: r}
if !x.TransferAllowed(state) {
return dns.RcodeServerFailure, nil
}
if state.QType() != dns.TypeAXFR {
return 0, fmt.Errorf("file: xfr called with non xfr type: %d", state.QType())
}
if state.Proto() == "udp" {
return 0, fmt.Errorf("file: xfr called with udp")
}
records := x.All()
if len(records) == 0 {
return dns.RcodeServerFailure, nil
}
ch := make(chan *dns.Envelope)
defer close(ch)
tr := new(dns.Transfer)
go tr.Out(w, r, ch)
j, l := 0, 0
records = append(records, records[0])
for i, r := range records {
l += dns.Len(r)
if l > transferLength {
ch <- &dns.Envelope{RR: records[j:i]}
l = 0
j = i
}
}
if j < len(records) {
ch <- &dns.Envelope{RR: records[j:]}
}
w.Hijack()
// w.Close() // Client closes connection
return dns.RcodeSuccess, nil
}
//const transferLength = 10e3 // Start a new envelop after message reaches this size.
const transferLength = 100 // Start a new envelop after message reaches this size.