func marshalCanonicalCAASet(set []*dns.CAA) ([]byte, error) { var err error offset, size := 0, 0 sortedSet := caaSet(set) sort.Sort(sortedSet) for _, rr := range sortedSet { size += dns.Len(rr) } tbh := make([]byte, size) for _, rr := range sortedSet { ttl := rr.Hdr.Ttl rr.Hdr.Ttl = 0 // only variable that should jitter offset, err = dns.PackRR(rr, tbh, offset, nil, false) if err != nil { return nil, err } rr.Hdr.Ttl = ttl } return tbh, nil }
// Serve an AXFR (and fallback of 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 && state.QType() != dns.TypeIXFR { return 0, 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 }