Fix transferring the zone from a master and the matching of notifies to source and dst IP addresses. Add `upstream` keyword as well, because it is needed for the same reasons as in the *file* middlware. Add some dire warning about upstream in the readme of both middlewares. Out of band testing, hidden by net build tag was added. Integration testing still needs to be setup.
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package file
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/coredns/coredns/middleware"
|
|
"github.com/coredns/coredns/request"
|
|
|
|
"github.com/miekg/dns"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// Xfr serves up an AXFR.
|
|
type Xfr struct {
|
|
*Zone
|
|
}
|
|
|
|
// ServeDNS implements the middleware.Handler interface.
|
|
func (x Xfr) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
state := request.Request{W: w, Req: r}
|
|
if !x.TransferAllowed(state) {
|
|
return dns.RcodeServerFailure, nil
|
|
}
|
|
if state.QType() != dns.TypeAXFR && state.QType() != dns.TypeIXFR {
|
|
return 0, middleware.Error(x.Name(), fmt.Errorf("xfr called with non transfer type: %d", state.QType()))
|
|
}
|
|
|
|
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]) // add closing SOA to the end
|
|
log.Printf("[INFO] Outgoing transfer of %d records of zone %s to %s started", len(records), x.origin, state.IP())
|
|
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
|
|
}
|
|
|
|
// Name implements the middleware.Hander interface.
|
|
func (x Xfr) Name() string { return "xfr" }
|
|
|
|
const transferLength = 1000 // Start a new envelop after message reaches this size in bytes. Intentionally small to test multi envelope parsing.
|