aboutsummaryrefslogtreecommitdiff
path: root/middleware/file/xfr.go
diff options
context:
space:
mode:
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.