| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | package autopath
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 14:45:30 -07:00
										 |  |  | import (
 | 
					
						
							|  |  |  | 	"strings"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | // Writer implements a ResponseWriter that also does the following:
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | // * 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
 | 
					
						
							| 
									
										
										
										
											2017-08-04 09:06:06 -07:00
										 |  |  | //   to enable further search path probing if a search was not successful.
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | // * 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.
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | // * Overwrites response code with Writer.Rcode if the response code
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | //   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.
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | type Writer struct {
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	dns.ResponseWriter
 | 
					
						
							|  |  |  | 	original dns.Question
 | 
					
						
							|  |  |  | 	Rcode    int
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | // AutoPath enables server side search path lookups for pods.
 | 
					
						
							|  |  |  | type AutoPath struct {
 | 
					
						
							|  |  |  | 	NDots          int
 | 
					
						
							|  |  |  | 	ResolvConfFile string
 | 
					
						
							|  |  |  | 	HostSearchPath []string
 | 
					
						
							|  |  |  | 	OnNXDOMAIN     int
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewWriter returns a pointer to a new Writer
 | 
					
						
							|  |  |  | func NewWriter(w dns.ResponseWriter, r *dns.Msg) *Writer {
 | 
					
						
							|  |  |  | 	return &Writer{
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 		ResponseWriter: w,
 | 
					
						
							|  |  |  | 		original:       r.Question[0],
 | 
					
						
							|  |  |  | 		Rcode:          dns.RcodeSuccess,
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | // WriteMsg writes to client, unless response will be NXDOMAIN.
 | 
					
						
							|  |  |  | func (apw *Writer) WriteMsg(res *dns.Msg) error {
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	if res.Rcode == dns.RcodeNameError {
 | 
					
						
							|  |  |  | 		res.Rcode = apw.Rcode
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2017-08-07 14:45:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	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)
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | 		res.Answer[0] = CNAME(apw.original.Name, a.Header().Name, a.Header().Ttl)
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 	res.Question[0] = apw.original
 | 
					
						
							| 
									
										
										
										
											2017-08-07 14:45:30 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	return apw.ResponseWriter.WriteMsg(res)
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Write is a wrapper that records the size of the message that gets written.
 | 
					
						
							| 
									
										
										
										
											2017-08-07 07:09:32 -07:00
										 |  |  | func (apw *Writer) Write(buf []byte) (int, error) {
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | 	n, err := apw.ResponseWriter.Write(buf)
 | 
					
						
							|  |  |  | 	return n, err
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-07 14:45:30 -07:00
										 |  |  | func SplitSearch(zone, question, namespace string) (name, search string, ok bool) {
 | 
					
						
							|  |  |  | 	search = strings.Join([]string{namespace, "svc", zone}, ".")
 | 
					
						
							|  |  |  | 	if dns.IsSubDomain(search, question) {
 | 
					
						
							|  |  |  | 		return question[:len(question)-len(search)-1], search, true
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return "", "", false
 | 
					
						
							| 
									
										
										
										
											2017-07-11 18:05:32 -04:00
										 |  |  | }
 |