| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | package dnsserver
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:19:32 -05:00
										 |  |  | 	"fmt"
 | 
					
						
							| 
									
										
										
										
											2017-10-24 10:16:03 +01:00
										 |  |  | 	"net"
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	"strings"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin"
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:16:04 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/parse"
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/transport"
 | 
					
						
							| 
									
										
										
										
											2017-08-07 13:24:09 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type zoneAddr struct {
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 	Zone      string
 | 
					
						
							|  |  |  | 	Port      string
 | 
					
						
							| 
									
										
										
										
											2017-10-24 10:16:03 +01:00
										 |  |  | 	Transport string     // dns, tls or grpc
 | 
					
						
							|  |  |  | 	IPNet     *net.IPNet // if reverse zone this hold the IPNet
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 	Address   string     // used for bound zoneAddr - validation of overlapping
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-17 02:24:59 -08:00
										 |  |  | // String returns the string representation of z.
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | func (z zoneAddr) String() string {
 | 
					
						
							|  |  |  | 	s := z.Transport + "://" + z.Zone + ":" + z.Port
 | 
					
						
							|  |  |  | 	if z.Address != "" {
 | 
					
						
							|  |  |  | 		s += " on " + z.Address
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return s
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-17 02:24:59 -08:00
										 |  |  | // normalizeZone parses a zone string into a structured format with separate
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | // host, and port portions, as well as the original input string.
 | 
					
						
							|  |  |  | func normalizeZone(str string) (zoneAddr, error) {
 | 
					
						
							| 
									
										
										
										
											2018-12-17 02:24:59 -08:00
										 |  |  | 	trans, str := parse.Transport(str)
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-24 10:16:03 +01:00
										 |  |  | 	host, port, ipnet, err := plugin.SplitHostPort(str)
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	if err != nil {
 | 
					
						
							| 
									
										
										
										
											2017-08-07 13:24:09 -07:00
										 |  |  | 		return zoneAddr{}, err
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if port == "" {
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		switch trans {
 | 
					
						
							|  |  |  | 		case transport.DNS:
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 			port = Port
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		case transport.TLS:
 | 
					
						
							|  |  |  | 			port = transport.TLSPort
 | 
					
						
							|  |  |  | 		case transport.GRPC:
 | 
					
						
							|  |  |  | 			port = transport.GRPCPort
 | 
					
						
							|  |  |  | 		case transport.HTTPS:
 | 
					
						
							|  |  |  | 			port = transport.HTTPSPort
 | 
					
						
							| 
									
										
										
										
											2018-05-21 19:40:46 +01:00
										 |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 08:01:45 -07:00
										 |  |  | 	return zoneAddr{Zone: dns.Fqdn(host), Port: port, Transport: trans, IPNet: ipnet}, nil
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 15:02:05 +00:00
										 |  |  | // SplitProtocolHostPort splits a full formed address like "dns://[::1]:53" into parts.
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:19:32 -05:00
										 |  |  | func SplitProtocolHostPort(address string) (protocol string, ip string, port string, err error) {
 | 
					
						
							|  |  |  | 	parts := strings.Split(address, "://")
 | 
					
						
							|  |  |  | 	switch len(parts) {
 | 
					
						
							|  |  |  | 	case 1:
 | 
					
						
							|  |  |  | 		ip, port, err := net.SplitHostPort(parts[0])
 | 
					
						
							|  |  |  | 		return "", ip, port, err
 | 
					
						
							|  |  |  | 	case 2:
 | 
					
						
							|  |  |  | 		ip, port, err := net.SplitHostPort(parts[1])
 | 
					
						
							|  |  |  | 		return parts[0], ip, port, err
 | 
					
						
							|  |  |  | 	default:
 | 
					
						
							|  |  |  | 		return "", "", "", fmt.Errorf("provided value is not in an address format : %s", address)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | type zoneOverlap struct {
 | 
					
						
							|  |  |  | 	registeredAddr map[zoneAddr]zoneAddr // each zoneAddr is registered once by its key
 | 
					
						
							| 
									
										
										
										
											2019-02-01 19:22:43 +08:00
										 |  |  | 	unboundOverlap map[zoneAddr]zoneAddr // the "no bind" equiv ZoneAddr is registered by its original key
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newOverlapZone() *zoneOverlap {
 | 
					
						
							|  |  |  | 	return &zoneOverlap{registeredAddr: make(map[zoneAddr]zoneAddr), unboundOverlap: make(map[zoneAddr]zoneAddr)}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // registerAndCheck adds a new zoneAddr for validation, it returns information about existing or overlapping with already registered
 | 
					
						
							|  |  |  | // we consider that an unbound address is overlapping all bound addresses for same zone, same port
 | 
					
						
							|  |  |  | func (zo *zoneOverlap) registerAndCheck(z zoneAddr) (existingZone *zoneAddr, overlappingZone *zoneAddr) {
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if exist, ok := zo.registeredAddr[z]; ok {
 | 
					
						
							|  |  |  | 		// exact same zone already registered
 | 
					
						
							|  |  |  | 		return &exist, nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	uz := zoneAddr{Zone: z.Zone, Address: "", Port: z.Port, Transport: z.Transport}
 | 
					
						
							|  |  |  | 	if already, ok := zo.unboundOverlap[uz]; ok {
 | 
					
						
							|  |  |  | 		if z.Address == "" {
 | 
					
						
							|  |  |  | 			// current is not bound to an address, but there is already another zone with a bind address registered
 | 
					
						
							|  |  |  | 			return nil, &already
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if _, ok := zo.registeredAddr[uz]; ok {
 | 
					
						
							|  |  |  | 			// current zone is bound to an address, but there is already an overlapping zone+port with no bind address
 | 
					
						
							|  |  |  | 			return nil, &uz
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	// there is no overlap, keep the current zoneAddr for future checks
 | 
					
						
							|  |  |  | 	zo.registeredAddr[z] = z
 | 
					
						
							|  |  |  | 	zo.unboundOverlap[uz] = z
 | 
					
						
							|  |  |  | 	return nil, nil
 | 
					
						
							|  |  |  | }
 |