mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-31 02:03:20 -04:00 
			
		
		
		
	* Add unit tests & cnames * more progress * fix * next mw dependent unit tests * add tests for OnNXDOMAIN * Add AAAA and ndots unit tests; fix request.NewWithQuestion * Correct default value in README * add CNAMEs to readme * review * fix autopath examples * fix and test CNAME response order
		
			
				
	
	
		
			79 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package kubernetes
 | |
| 
 | |
| import "github.com/miekg/dns"
 | |
| 
 | |
| // AutoPathWriter implements a ResponseWriter that also does the following:
 | |
| // * reverts question section of a packet to its original state.
 | |
| //   This is done to avoid the 'Question section mismatch:' error in client.
 | |
| // * Defers write to the client if the response code is NXDOMAIN.  This is needed
 | |
| //   to enable further search path probing if a search was not sucessful.
 | |
| // * Allow forced write to client regardless of response code.  This is needed to
 | |
| //   write the packet to the client if the final search in the path fails to
 | |
| //   produce results.
 | |
| // * Overwrites response code with AutoPathWriter.Rcode if the response code
 | |
| //   is NXDOMAIN (NameError).  This is needed to support the AutoPath.OnNXDOMAIN
 | |
| //   function, which returns a NOERROR to client instead of NXDOMAIN if the final
 | |
| //   search in the path fails to produce results.
 | |
| 
 | |
| type AutoPathWriter struct {
 | |
| 	dns.ResponseWriter
 | |
| 	original dns.Question
 | |
| 	Rcode    int
 | |
| 	Sent     bool
 | |
| }
 | |
| 
 | |
| // NewAutoPathWriter returns a pointer to a new AutoPathWriter
 | |
| func NewAutoPathWriter(w dns.ResponseWriter, r *dns.Msg) *AutoPathWriter {
 | |
| 	return &AutoPathWriter{
 | |
| 		ResponseWriter: w,
 | |
| 		original:       r.Question[0],
 | |
| 		Rcode:          dns.RcodeSuccess,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WriteMsg writes to client, unless response will be NXDOMAIN
 | |
| func (apw *AutoPathWriter) WriteMsg(res *dns.Msg) error {
 | |
| 	return apw.overrideMsg(res, false)
 | |
| }
 | |
| 
 | |
| // ForceWriteMsg forces the write to client regardless of response code
 | |
| func (apw *AutoPathWriter) ForceWriteMsg(res *dns.Msg) error {
 | |
| 	return apw.overrideMsg(res, true)
 | |
| }
 | |
| 
 | |
| // overrideMsg overrides rcode, reverts question, adds CNAME, and calls the
 | |
| // underlying ResponseWriter's WriteMsg method unless the write is deferred,
 | |
| // or force = true.
 | |
| func (apw *AutoPathWriter) overrideMsg(res *dns.Msg, force bool) error {
 | |
| 	if res.Rcode == dns.RcodeNameError {
 | |
| 		res.Rcode = apw.Rcode
 | |
| 	}
 | |
| 	if res.Rcode != dns.RcodeSuccess && !force {
 | |
| 		return nil
 | |
| 	}
 | |
| 	for _, a := range res.Answer {
 | |
| 		if apw.original.Name == a.Header().Name {
 | |
| 			continue
 | |
| 		}
 | |
| 		res.Answer = append(res.Answer, nil)
 | |
| 		copy(res.Answer[1:], res.Answer)
 | |
| 		res.Answer[0] = newCNAME(apw.original.Name, dns.Fqdn(a.Header().Name), a.Header().Ttl)
 | |
| 	}
 | |
| 	res.Question[0] = apw.original
 | |
| 	apw.Sent = true
 | |
| 	return apw.ResponseWriter.WriteMsg(res)
 | |
| }
 | |
| 
 | |
| // Write is a wrapper that records the size of the message that gets written.
 | |
| func (apw *AutoPathWriter) Write(buf []byte) (int, error) {
 | |
| 	n, err := apw.ResponseWriter.Write(buf)
 | |
| 	return n, err
 | |
| }
 | |
| 
 | |
| // Hijack implements dns.Hijacker. It simply wraps the underlying
 | |
| // ResponseWriter's Hijack method if there is one, or returns an error.
 | |
| func (apw *AutoPathWriter) Hijack() {
 | |
| 	apw.ResponseWriter.Hijack()
 | |
| 	return
 | |
| }
 |