| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | package dnsserver
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"fmt"
 | 
					
						
							|  |  |  | 	"net"
 | 
					
						
							|  |  |  | 	"time"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-24 18:14:41 +02:00
										 |  |  | 	"github.com/coredns/caddy"
 | 
					
						
							|  |  |  | 	"github.com/coredns/caddy/caddyfile"
 | 
					
						
							| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const serverType = "dns"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() {
 | 
					
						
							|  |  |  | 	caddy.RegisterServerType(serverType, caddy.ServerType{
 | 
					
						
							| 
									
										
										
										
											2017-12-15 01:26:36 -06:00
										 |  |  | 		Directives: func() []string { return Directives },
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		DefaultInput: func() caddy.Input {
 | 
					
						
							|  |  |  | 			return caddy.CaddyfileInput{
 | 
					
						
							|  |  |  | 				Filepath:       "Corefile",
 | 
					
						
							| 
									
										
										
										
											2019-09-09 14:41:50 +01:00
										 |  |  | 				Contents:       []byte(".:" + Port + " {\nwhoami\nlog\n}\n"),
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 				ServerTypeName: serverType,
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		},
 | 
					
						
							|  |  |  | 		NewContext: newContext,
 | 
					
						
							|  |  |  | 	})
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 07:15:57 +00:00
										 |  |  | func newContext(i *caddy.Instance) caddy.Context {
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	return &dnsContext{keysToConfigs: make(map[string]*Config)}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type dnsContext struct {
 | 
					
						
							|  |  |  | 	keysToConfigs map[string]*Config
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// configs is the master list of all site configs.
 | 
					
						
							|  |  |  | 	configs []*Config
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (h *dnsContext) saveConfig(key string, cfg *Config) {
 | 
					
						
							|  |  |  | 	h.configs = append(h.configs, cfg)
 | 
					
						
							|  |  |  | 	h.keysToConfigs[key] = cfg
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 16:25:07 +08:00
										 |  |  | // Compile-time check to ensure dnsContext implements the caddy.Context interface
 | 
					
						
							|  |  |  | var _ caddy.Context = &dnsContext{}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | // InspectServerBlocks make sure that everything checks out before
 | 
					
						
							|  |  |  | // executing directives and otherwise prepares the directives to
 | 
					
						
							|  |  |  | // be parsed and executed.
 | 
					
						
							|  |  |  | func (h *dnsContext) InspectServerBlocks(sourceFile string, serverBlocks []caddyfile.ServerBlock) ([]caddyfile.ServerBlock, error) {
 | 
					
						
							|  |  |  | 	// Normalize and check all the zone names and check for duplicates
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 	for ib, s := range serverBlocks {
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 		// Walk the s.Keys and expand any reverse address in their proper DNS in-addr zones. If the expansions leads for
 | 
					
						
							|  |  |  | 		// more than one reverse zone, replace the current value and add the rest to s.Keys.
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 		zoneAddrs := []zoneAddr{}
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 		for ik, k := range s.Keys {
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 			trans, k1 := parse.Transport(k) // get rid of any dns:// or other scheme.
 | 
					
						
							|  |  |  | 			hosts, port, err := plugin.SplitHostPort(k1)
 | 
					
						
							| 
									
										
										
										
											2021-05-19 19:38:37 +02:00
										 |  |  | 			// We need to make this a fully qualified domain name to catch all errors here and not later when
 | 
					
						
							|  |  |  | 			// plugin.Normalize is called again on these strings, with the prime difference being that the domain
 | 
					
						
							|  |  |  | 			// name is fully qualified. This was found by fuzzing where "ȶ" is deemed OK, but "ȶ." is not (might be a
 | 
					
						
							|  |  |  | 			// bug in miekg/dns actually). But here we were checking ȶ, which is OK, and later we barf in ȶ. leading to
 | 
					
						
							|  |  |  | 			// "index out of range".
 | 
					
						
							|  |  |  | 			for ih := range hosts {
 | 
					
						
							|  |  |  | 				_, _, err := plugin.SplitHostPort(dns.Fqdn(hosts[ih]))
 | 
					
						
							|  |  |  | 				if err != nil {
 | 
					
						
							|  |  |  | 					return nil, err
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if port == "" {
 | 
					
						
							|  |  |  | 				switch trans {
 | 
					
						
							|  |  |  | 				case transport.DNS:
 | 
					
						
							|  |  |  | 					port = Port
 | 
					
						
							|  |  |  | 				case transport.TLS:
 | 
					
						
							|  |  |  | 					port = transport.TLSPort
 | 
					
						
							|  |  |  | 				case transport.GRPC:
 | 
					
						
							|  |  |  | 					port = transport.GRPCPort
 | 
					
						
							|  |  |  | 				case transport.HTTPS:
 | 
					
						
							|  |  |  | 					port = transport.HTTPSPort
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if len(hosts) > 1 {
 | 
					
						
							|  |  |  | 				s.Keys[ik] = hosts[0] + ":" + port // replace for the first
 | 
					
						
							|  |  |  | 				for _, h := range hosts[1:] {      // add the rest
 | 
					
						
							|  |  |  | 					s.Keys = append(s.Keys, h+":"+port)
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 				}
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 			for i := range hosts {
 | 
					
						
							|  |  |  | 				zoneAddrs = append(zoneAddrs, zoneAddr{Zone: dns.Fqdn(hosts[i]), Port: port, Transport: trans})
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-05-11 09:50:18 +02:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		serverBlocks[ib].Keys = s.Keys // important to save back the new keys that are potentially created here.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:12:06 -04:00
										 |  |  | 		var firstConfigInBlock *Config
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 		for ik := range s.Keys {
 | 
					
						
							|  |  |  | 			za := zoneAddrs[ik]
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 			s.Keys[ik] = za.String()
 | 
					
						
							| 
									
										
										
										
											2017-10-24 10:16:03 +01:00
										 |  |  | 			// Save the config to our master list, and key it for lookups.
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 			cfg := &Config{
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:19:32 -05:00
										 |  |  | 				Zone:        za.Zone,
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 				ListenHosts: []string{""},
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:19:32 -05:00
										 |  |  | 				Port:        za.Port,
 | 
					
						
							|  |  |  | 				Transport:   za.Transport,
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:12:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Set reference to the first config in the current block.
 | 
					
						
							|  |  |  | 			// This is used later by MakeServers to share a single plugin list
 | 
					
						
							|  |  |  | 			// for all zones in a server block.
 | 
					
						
							|  |  |  | 			if ik == 0 {
 | 
					
						
							|  |  |  | 				firstConfigInBlock = cfg
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			cfg.firstConfigInBlock = firstConfigInBlock
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 			keyConfig := keyForConfig(ib, ik)
 | 
					
						
							|  |  |  | 			h.saveConfig(keyConfig, cfg)
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return serverBlocks, nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MakeServers uses the newly-created siteConfigs to create and return a list of server instances.
 | 
					
						
							|  |  |  | func (h *dnsContext) MakeServers() ([]caddy.Server, error) {
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:12:06 -04:00
										 |  |  | 	// Copy the Plugin, ListenHosts and Debug from first config in the block
 | 
					
						
							|  |  |  | 	// to all other config in the same block . Doing this results in zones
 | 
					
						
							|  |  |  | 	// sharing the same plugin instances and settings as other zones in
 | 
					
						
							|  |  |  | 	// the same block.
 | 
					
						
							|  |  |  | 	for _, c := range h.configs {
 | 
					
						
							|  |  |  | 		c.Plugin = c.firstConfigInBlock.Plugin
 | 
					
						
							|  |  |  | 		c.ListenHosts = c.firstConfigInBlock.ListenHosts
 | 
					
						
							|  |  |  | 		c.Debug = c.firstConfigInBlock.Debug
 | 
					
						
							| 
									
										
										
										
											2022-05-24 14:36:36 +02:00
										 |  |  | 		c.Stacktrace = c.firstConfigInBlock.Stacktrace
 | 
					
						
							| 
									
										
										
										
											2022-10-29 00:55:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Fork TLSConfig for each encrypted connection
 | 
					
						
							|  |  |  | 		c.TLSConfig = c.firstConfigInBlock.TLSConfig.Clone()
 | 
					
						
							| 
									
										
										
										
											2022-12-28 11:14:16 +00:00
										 |  |  | 		c.ReadTimeout = c.firstConfigInBlock.ReadTimeout
 | 
					
						
							|  |  |  | 		c.WriteTimeout = c.firstConfigInBlock.WriteTimeout
 | 
					
						
							|  |  |  | 		c.IdleTimeout = c.firstConfigInBlock.IdleTimeout
 | 
					
						
							| 
									
										
										
										
											2022-06-27 15:48:34 -04:00
										 |  |  | 		c.TsigSecret = c.firstConfigInBlock.TsigSecret
 | 
					
						
							| 
									
										
										
										
											2021-07-09 11:12:06 -04:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	// we must map (group) each config to a bind address
 | 
					
						
							|  |  |  | 	groups, err := groupConfigsByListenAddr(h.configs)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		return nil, err
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	// then we create a server for each group
 | 
					
						
							|  |  |  | 	var servers []caddy.Server
 | 
					
						
							|  |  |  | 	for addr, group := range groups {
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 		// switch on addr
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:16:04 +01:00
										 |  |  | 		switch tr, _ := parse.Transport(addr); tr {
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		case transport.DNS:
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 			s, err := NewServer(addr, group)
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			servers = append(servers, s)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		case transport.TLS:
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 			s, err := NewServerTLS(addr, group)
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			servers = append(servers, s)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		case transport.GRPC:
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 			s, err := NewServergRPC(addr, group)
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			servers = append(servers, s)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | 		case transport.HTTPS:
 | 
					
						
							| 
									
										
										
										
											2018-05-21 19:40:46 +01:00
										 |  |  | 			s, err := NewServerHTTPS(addr, group)
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			servers = append(servers, s)
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 14:56:27 -04:00
										 |  |  | 	// For each server config, check for View Filter plugins
 | 
					
						
							|  |  |  | 	for _, c := range h.configs {
 | 
					
						
							|  |  |  | 		// Add filters in the plugin.cfg order for consistent filter func evaluation order.
 | 
					
						
							|  |  |  | 		for _, d := range Directives {
 | 
					
						
							|  |  |  | 			if vf, ok := c.registry[d].(Viewer); ok {
 | 
					
						
							|  |  |  | 				if c.ViewName != "" {
 | 
					
						
							|  |  |  | 					return nil, fmt.Errorf("multiple views defined in server block")
 | 
					
						
							|  |  |  | 				}
 | 
					
						
							|  |  |  | 				c.ViewName = vf.ViewName()
 | 
					
						
							|  |  |  | 				c.FilterFuncs = append(c.FilterFuncs, vf.Filter)
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Verify that there is no overlap on the zones and listen addresses
 | 
					
						
							|  |  |  | 	// for unfiltered server configs
 | 
					
						
							|  |  |  | 	errValid := h.validateZonesAndListeningAddresses()
 | 
					
						
							|  |  |  | 	if errValid != nil {
 | 
					
						
							|  |  |  | 		return nil, errValid
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	return servers, nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // AddPlugin adds a plugin to a site's plugin stack.
 | 
					
						
							|  |  |  | func (c *Config) AddPlugin(m plugin.Plugin) {
 | 
					
						
							|  |  |  | 	c.Plugin = append(c.Plugin, m)
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 14:21:42 +01:00
										 |  |  | // registerHandler adds a handler to a site's handler registration. Handlers
 | 
					
						
							| 
									
										
										
										
											2022-12-28 11:14:16 +00:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	use this to announce that they exist to other plugin.
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | func (c *Config) registerHandler(h plugin.Handler) {
 | 
					
						
							| 
									
										
										
										
											2017-08-25 08:55:53 +01:00
										 |  |  | 	if c.registry == nil {
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 		c.registry = make(map[string]plugin.Handler)
 | 
					
						
							| 
									
										
										
										
											2017-08-10 21:31:36 +01:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Just overwrite...
 | 
					
						
							| 
									
										
										
										
											2017-08-25 08:55:53 +01:00
										 |  |  | 	c.registry[h.Name()] = h
 | 
					
						
							| 
									
										
										
										
											2017-08-10 21:31:36 +01:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // Handler returns the plugin handler that has been added to the config under its name.
 | 
					
						
							|  |  |  | // This is useful to inspect if a certain plugin is active in this server.
 | 
					
						
							|  |  |  | // Note that this is order dependent and the order is defined in directives.go, i.e. if your plugin
 | 
					
						
							|  |  |  | // comes before the plugin you are checking; it will not be there (yet).
 | 
					
						
							|  |  |  | func (c *Config) Handler(name string) plugin.Handler {
 | 
					
						
							| 
									
										
										
										
											2017-08-25 08:55:53 +01:00
										 |  |  | 	if c.registry == nil {
 | 
					
						
							| 
									
										
										
										
											2017-08-10 21:31:36 +01:00
										 |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2017-08-25 08:55:53 +01:00
										 |  |  | 	if h, ok := c.registry[name]; ok {
 | 
					
						
							| 
									
										
										
										
											2017-08-10 21:31:36 +01:00
										 |  |  | 		return h
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:40:30 -05:00
										 |  |  | // Handlers returns a slice of plugins that have been registered. This can be used to
 | 
					
						
							|  |  |  | // inspect and interact with registered plugins but cannot be used to remove or add plugins.
 | 
					
						
							|  |  |  | // Note that this is order dependent and the order is defined in directives.go, i.e. if your plugin
 | 
					
						
							|  |  |  | // comes before the plugin you are checking; it will not be there (yet).
 | 
					
						
							|  |  |  | func (c *Config) Handlers() []plugin.Handler {
 | 
					
						
							|  |  |  | 	if c.registry == nil {
 | 
					
						
							|  |  |  | 		return nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	hs := make([]plugin.Handler, 0, len(c.registry))
 | 
					
						
							|  |  |  | 	for k := range c.registry {
 | 
					
						
							|  |  |  | 		hs = append(hs, c.registry[k])
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return hs
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | func (h *dnsContext) validateZonesAndListeningAddresses() error {
 | 
					
						
							|  |  |  | 	//Validate Zone and addresses
 | 
					
						
							|  |  |  | 	checker := newOverlapZone()
 | 
					
						
							|  |  |  | 	for _, conf := range h.configs {
 | 
					
						
							|  |  |  | 		for _, h := range conf.ListenHosts {
 | 
					
						
							|  |  |  | 			// Validate the overlapping of ZoneAddr
 | 
					
						
							|  |  |  | 			akey := zoneAddr{Transport: conf.Transport, Zone: conf.Zone, Address: h, Port: conf.Port}
 | 
					
						
							| 
									
										
										
										
											2022-09-08 14:56:27 -04:00
										 |  |  | 			var existZone, overlapZone *zoneAddr
 | 
					
						
							|  |  |  | 			if len(conf.FilterFuncs) > 0 {
 | 
					
						
							|  |  |  | 				// This config has filters. Check for overlap with other (unfiltered) configs.
 | 
					
						
							|  |  |  | 				existZone, overlapZone = checker.check(akey)
 | 
					
						
							|  |  |  | 			} else {
 | 
					
						
							|  |  |  | 				// This config has no filters. Check for overlap with other (unfiltered) configs,
 | 
					
						
							|  |  |  | 				// and register the zone to prevent subsequent zones from overlapping with it.
 | 
					
						
							|  |  |  | 				existZone, overlapZone = checker.registerAndCheck(akey)
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 			if existZone != nil {
 | 
					
						
							|  |  |  | 				return fmt.Errorf("cannot serve %s - it is already defined", akey.String())
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			if overlapZone != nil {
 | 
					
						
							|  |  |  | 				return fmt.Errorf("cannot serve %s - zone overlap listener capacity with %v", akey.String(), overlapZone.String())
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | // groupSiteConfigsByListenAddr groups site configs by their listen
 | 
					
						
							|  |  |  | // (bind) address, so sites that use the same listener can be served
 | 
					
						
							|  |  |  | // on the same server instance. The return value maps the listen
 | 
					
						
							|  |  |  | // address (what you pass into net.Listen) to the list of site configs.
 | 
					
						
							|  |  |  | // This function does NOT vet the configs to ensure they are compatible.
 | 
					
						
							|  |  |  | func groupConfigsByListenAddr(configs []*Config) (map[string][]*Config, error) {
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 	groups := make(map[string][]*Config)
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	for _, conf := range configs {
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:19:32 -05:00
										 |  |  | 		for _, h := range conf.ListenHosts {
 | 
					
						
							|  |  |  | 			addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(h, conf.Port))
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							|  |  |  | 				return nil, err
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			addrstr := conf.Transport + "://" + addr.String()
 | 
					
						
							|  |  |  | 			groups[addrstr] = append(groups[addrstr], conf)
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-02-23 11:54:42 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	return groups, nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 07:29:37 +01:00
										 |  |  | // DefaultPort is the default port.
 | 
					
						
							| 
									
										
										
										
											2018-09-19 08:16:04 +01:00
										 |  |  | const DefaultPort = transport.Port
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // These "soft defaults" are configurable by
 | 
					
						
							|  |  |  | // command line flags, etc.
 | 
					
						
							|  |  |  | var (
 | 
					
						
							| 
									
										
										
										
											2016-10-07 10:14:23 +00:00
										 |  |  | 	// Port is the port we listen on by default.
 | 
					
						
							| 
									
										
										
										
											2016-08-19 17:14:17 -07:00
										 |  |  | 	Port = DefaultPort
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// GracefulTimeout is the maximum duration of a graceful shutdown.
 | 
					
						
							|  |  |  | 	GracefulTimeout time.Duration
 | 
					
						
							|  |  |  | )
 | 
					
						
							| 
									
										
										
										
											2017-02-10 19:50:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | var _ caddy.GracefulServer = new(Server)
 |