| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | package file | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-06-21 23:46:20 -07:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2018-10-21 15:59:37 +02:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-04-13 20:14:03 +01:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2018-09-29 17:50:49 +02:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2016-04-13 20:14:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/file/tree" | 
					
						
							| 
									
										
										
										
											2018-02-16 03:44:50 -05:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/upstream" | 
					
						
							| 
									
										
										
										
											2017-02-21 22:51:47 -08:00
										 |  |  | 	"github.com/coredns/coredns/request" | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | // Zone is a structure that contains all data related to a DNS zone. | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | type Zone struct { | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	origin  string | 
					
						
							|  |  |  | 	origLen int | 
					
						
							|  |  |  | 	file    string | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 	*tree.Tree | 
					
						
							| 
									
										
										
										
											2019-06-29 22:22:34 +01:00
										 |  |  | 	Apex | 
					
						
							| 
									
										
										
										
											2019-08-01 12:51:37 +00:00
										 |  |  | 	Expired bool | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sync.RWMutex | 
					
						
							| 
									
										
										
										
											2016-04-03 09:02:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	TransferTo   []string | 
					
						
							| 
									
										
										
										
											2016-04-13 20:14:03 +01:00
										 |  |  | 	StartupOnce  sync.Once | 
					
						
							| 
									
										
										
										
											2016-04-03 09:02:34 +01:00
										 |  |  | 	TransferFrom []string | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-29 17:50:49 +02:00
										 |  |  | 	ReloadInterval time.Duration | 
					
						
							| 
									
										
										
										
											2018-02-28 18:19:37 -08:00
										 |  |  | 	reloadShutdown chan bool | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Upstream *upstream.Upstream // Upstream for looking up external names during the resolution process. | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | // Apex contains the apex records of a zone: SOA, NS and their potential signatures. | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | type Apex struct { | 
					
						
							|  |  |  | 	SOA    *dns.SOA | 
					
						
							|  |  |  | 	NS     []dns.RR | 
					
						
							|  |  |  | 	SIGSOA []dns.RR | 
					
						
							|  |  |  | 	SIGNS  []dns.RR | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 16:56:16 +01:00
										 |  |  | // NewZone returns a new zone. | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | func NewZone(name, file string) *Zone { | 
					
						
							| 
									
										
										
										
											2019-08-01 12:51:37 +00:00
										 |  |  | 	return &Zone{ | 
					
						
							| 
									
										
										
										
											2016-10-17 18:37:56 +01:00
										 |  |  | 		origin:         dns.Fqdn(name), | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 		origLen:        dns.CountLabel(dns.Fqdn(name)), | 
					
						
							| 
									
										
										
										
											2018-10-21 15:59:37 +02:00
										 |  |  | 		file:           filepath.Clean(file), | 
					
						
							| 
									
										
										
										
											2016-10-17 18:37:56 +01:00
										 |  |  | 		Tree:           &tree.Tree{}, | 
					
						
							| 
									
										
										
										
											2018-02-28 18:19:37 -08:00
										 |  |  | 		reloadShutdown: make(chan bool), | 
					
						
							| 
									
										
										
										
											2016-10-17 18:37:56 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 09:46:40 -07:00
										 |  |  | // Copy copies a zone. | 
					
						
							| 
									
										
										
										
											2016-04-05 10:53:23 +01:00
										 |  |  | func (z *Zone) Copy() *Zone { | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	z1 := NewZone(z.origin, z.file) | 
					
						
							| 
									
										
										
										
											2016-04-05 10:53:23 +01:00
										 |  |  | 	z1.TransferTo = z.TransferTo | 
					
						
							|  |  |  | 	z1.TransferFrom = z.TransferFrom | 
					
						
							|  |  |  | 	z1.Expired = z.Expired | 
					
						
							| 
									
										
										
										
											2017-06-21 23:46:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	z1.Apex = z.Apex | 
					
						
							| 
									
										
										
										
											2016-04-05 10:53:23 +01:00
										 |  |  | 	return z1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-23 10:35:31 +00:00
										 |  |  | // CopyWithoutApex copies zone z without the Apex records. | 
					
						
							|  |  |  | func (z *Zone) CopyWithoutApex() *Zone { | 
					
						
							|  |  |  | 	z1 := NewZone(z.origin, z.file) | 
					
						
							|  |  |  | 	z1.TransferTo = z.TransferTo | 
					
						
							|  |  |  | 	z1.TransferFrom = z.TransferFrom | 
					
						
							|  |  |  | 	z1.Expired = z.Expired | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return z1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 16:56:16 +01:00
										 |  |  | // Insert inserts r into z. | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | func (z *Zone) Insert(r dns.RR) error { | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	r.Header().Name = strings.ToLower(r.Header().Name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	switch h := r.Header().Rrtype; h { | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	case dns.TypeNS: | 
					
						
							|  |  |  | 		r.(*dns.NS).Ns = strings.ToLower(r.(*dns.NS).Ns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if r.Header().Name == z.origin { | 
					
						
							|  |  |  | 			z.Apex.NS = append(z.Apex.NS, r) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	case dns.TypeSOA: | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 		r.(*dns.SOA).Ns = strings.ToLower(r.(*dns.SOA).Ns) | 
					
						
							|  |  |  | 		r.(*dns.SOA).Mbox = strings.ToLower(r.(*dns.SOA).Mbox) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		z.Apex.SOA = r.(*dns.SOA) | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	case dns.TypeNSEC3, dns.TypeNSEC3PARAM: | 
					
						
							| 
									
										
										
										
											2016-09-03 09:37:36 +01:00
										 |  |  | 		return fmt.Errorf("NSEC3 zone is not supported, dropping RR: %s for zone: %s", r.Header().Name, z.origin) | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	case dns.TypeRRSIG: | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 		x := r.(*dns.RRSIG) | 
					
						
							|  |  |  | 		switch x.TypeCovered { | 
					
						
							|  |  |  | 		case dns.TypeSOA: | 
					
						
							|  |  |  | 			z.Apex.SIGSOA = append(z.Apex.SIGSOA, x) | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 			return nil | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 		case dns.TypeNS: | 
					
						
							|  |  |  | 			if r.Header().Name == z.origin { | 
					
						
							|  |  |  | 				z.Apex.SIGNS = append(z.Apex.SIGNS, x) | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	case dns.TypeCNAME: | 
					
						
							|  |  |  | 		r.(*dns.CNAME).Target = strings.ToLower(r.(*dns.CNAME).Target) | 
					
						
							|  |  |  | 	case dns.TypeMX: | 
					
						
							|  |  |  | 		r.(*dns.MX).Mx = strings.ToLower(r.(*dns.MX).Mx) | 
					
						
							|  |  |  | 	case dns.TypeSRV: | 
					
						
							|  |  |  | 		r.(*dns.SRV).Target = strings.ToLower(r.(*dns.SRV).Target) | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	z.Tree.Insert(r) | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-03-27 07:37:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | // File retrieves the file path in a safe way. | 
					
						
							| 
									
										
										
										
											2018-07-03 06:20:39 -04:00
										 |  |  | func (z *Zone) File() string { | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 	z.RLock() | 
					
						
							|  |  |  | 	defer z.RUnlock() | 
					
						
							| 
									
										
										
										
											2018-07-03 06:20:39 -04:00
										 |  |  | 	return z.file | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | // SetFile updates the file path in a safe way. | 
					
						
							| 
									
										
										
										
											2018-07-03 06:20:39 -04:00
										 |  |  | func (z *Zone) SetFile(path string) { | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 	z.Lock() | 
					
						
							| 
									
										
										
										
											2018-07-03 06:20:39 -04:00
										 |  |  | 	z.file = path | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 	z.Unlock() | 
					
						
							| 
									
										
										
										
											2018-07-03 06:20:39 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-03 09:02:34 +01:00
										 |  |  | // TransferAllowed checks if incoming request for transferring the zone is allowed according to the ACLs. | 
					
						
							| 
									
										
										
										
											2017-06-21 23:46:20 -07:00
										 |  |  | func (z *Zone) TransferAllowed(state request.Request) bool { | 
					
						
							| 
									
										
										
										
											2016-04-03 09:02:34 +01:00
										 |  |  | 	for _, t := range z.TransferTo { | 
					
						
							|  |  |  | 		if t == "*" { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-06-21 23:46:20 -07:00
										 |  |  | 		// If remote IP matches we accept. | 
					
						
							|  |  |  | 		remote := state.IP() | 
					
						
							|  |  |  | 		to, _, err := net.SplitHostPort(t) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if to == remote { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-28 12:08:05 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-05 07:37:05 +01:00
										 |  |  | 	// TODO(miek): future matching against IP/CIDR notations | 
					
						
							| 
									
										
										
										
											2016-04-03 09:02:34 +01:00
										 |  |  | 	return false | 
					
						
							| 
									
										
										
										
											2016-03-28 12:08:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | // ApexIfDefined returns the apex nodes from z. The SOA record is the first record, if it does not exist, an error is returned. | 
					
						
							|  |  |  | func (z *Zone) ApexIfDefined() ([]dns.RR, error) { | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 	z.RLock() | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | 	defer z.RUnlock() | 
					
						
							|  |  |  | 	if z.Apex.SOA == nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("no SOA") | 
					
						
							| 
									
										
										
										
											2016-03-28 12:08:05 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | 	rrs := []dns.RR{z.Apex.SOA} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(z.Apex.SIGSOA) > 0 { | 
					
						
							|  |  |  | 		rrs = append(rrs, z.Apex.SIGSOA...) | 
					
						
							| 
									
										
										
										
											2016-04-16 16:16:52 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-20 18:13:43 +00:00
										 |  |  | 	if len(z.Apex.NS) > 0 { | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | 		rrs = append(rrs, z.Apex.NS...) | 
					
						
							| 
									
										
										
										
											2019-07-20 18:13:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | 	if len(z.Apex.SIGNS) > 0 { | 
					
						
							|  |  |  | 		rrs = append(rrs, z.Apex.SIGNS...) | 
					
						
							| 
									
										
										
										
											2016-03-28 12:08:05 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-23 18:32:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-30 13:47:27 +01:00
										 |  |  | 	return rrs, nil | 
					
						
							| 
									
										
										
										
											2016-03-28 12:08:05 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-15 14:26:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | // NameFromRight returns the labels from the right, staring with the | 
					
						
							|  |  |  | // origin and then i labels extra. When we are overshooting the name | 
					
						
							|  |  |  | // the returned boolean is set to true. | 
					
						
							|  |  |  | func (z *Zone) nameFromRight(qname string, i int) (string, bool) { | 
					
						
							|  |  |  | 	if i <= 0 { | 
					
						
							|  |  |  | 		return z.origin, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for j := 1; j <= z.origLen; j++ { | 
					
						
							|  |  |  | 		if _, shot := dns.PrevLabel(qname, j); shot { | 
					
						
							|  |  |  | 			return qname, shot | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	k := 0 | 
					
						
							| 
									
										
										
										
											2018-07-28 17:32:13 +08:00
										 |  |  | 	var shot bool | 
					
						
							| 
									
										
										
										
											2016-11-05 14:39:49 +00:00
										 |  |  | 	for j := 1; j <= i; j++ { | 
					
						
							|  |  |  | 		k, shot = dns.PrevLabel(qname, j+z.origLen) | 
					
						
							|  |  |  | 		if shot { | 
					
						
							|  |  |  | 			return qname, shot | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return qname[k:], false | 
					
						
							|  |  |  | } |