aboutsummaryrefslogtreecommitdiff
path: root/middleware/file/xfr.go
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2016-03-28 12:08:05 +0100
committerGravatar Miek Gieben <miek@miek.nl> 2016-03-28 18:23:17 +0100
commite56d206542c901a48b28c4501fe5805e9e9e1a10 (patch)
tree77a644f6fe28f3de8eaf6f7c766cea73b438b487 /middleware/file/xfr.go
parent6324bb1fa7c0516ef3bebfb822a0cdc767764ad2 (diff)
downloadcoredns-e56d206542c901a48b28c4501fe5805e9e9e1a10.tar.gz
coredns-e56d206542c901a48b28c4501fe5805e9e9e1a10.tar.zst
coredns-e56d206542c901a48b28c4501fe5805e9e9e1a10.zip
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.
Diffstat (limited to 'middleware/file/xfr.go')
-rw-r--r--middleware/file/xfr.go61
1 files changed, 61 insertions, 0 deletions
diff --git a/middleware/file/xfr.go b/middleware/file/xfr.go
new file mode 100644
index 000000000..297de2fc5
--- /dev/null
+++ b/middleware/file/xfr.go
@@ -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.