diff options
Diffstat (limited to 'core/config.go')
-rw-r--r-- | core/config.go | 340 |
1 files changed, 0 insertions, 340 deletions
diff --git a/core/config.go b/core/config.go deleted file mode 100644 index eea099a70..000000000 --- a/core/config.go +++ /dev/null @@ -1,340 +0,0 @@ -package core - -import ( - "bytes" - "fmt" - "io" - "log" - "net" - "sync" - - "github.com/miekg/coredns/core/parse" - "github.com/miekg/coredns/core/setup" - "github.com/miekg/coredns/server" -) - -const ( - // DefaultConfigFile is the name of the configuration file that is loaded - // by default if no other file is specified. - DefaultConfigFile = "Corefile" -) - -func loadConfigsUpToIncludingTLS(filename string, input io.Reader) ([]server.Config, []parse.ServerBlock, int, error) { - var configs []server.Config - - // Each server block represents similar hosts/addresses, since they - // were grouped together in the Corefile. - serverBlocks, err := parse.ServerBlocks(filename, input, true) - if err != nil { - return nil, nil, 0, err - } - if len(serverBlocks) == 0 { - newInput := DefaultInput() - serverBlocks, err = parse.ServerBlocks(newInput.Path(), bytes.NewReader(newInput.Body()), true) - if err != nil { - return nil, nil, 0, err - } - } - - var lastDirectiveIndex int // we set up directives in two parts; this stores where we left off - - // Iterate each server block and make a config for each one, - // executing the directives that were parsed in order up to the tls - // directive; this is because we must activate Let's Encrypt. - for i, sb := range serverBlocks { - onces := makeOnces() - storages := makeStorages() - - for j, addr := range sb.Addresses { - config := server.Config{ - Host: addr.Host, - Port: addr.Port, - Root: Root, - ConfigFile: filename, - AppName: AppName, - AppVersion: AppVersion, - } - - // It is crucial that directives are executed in the proper order. - for k, dir := range directiveOrder { - // Execute directive if it is in the server block - if tokens, ok := sb.Tokens[dir.name]; ok { - // Each setup function gets a controller, from which setup functions - // get access to the config, tokens, and other state information useful - // to set up its own host only. - controller := &setup.Controller{ - Config: &config, - Dispenser: parse.NewDispenserTokens(filename, tokens), - OncePerServerBlock: func(f func() error) error { - var err error - onces[dir.name].Do(func() { - err = f() - }) - return err - }, - ServerBlockIndex: i, - ServerBlockHostIndex: j, - ServerBlockHosts: sb.HostList(), - ServerBlockStorage: storages[dir.name], - } - // execute setup function and append middleware handler, if any - midware, err := dir.setup(controller) - if err != nil { - return nil, nil, lastDirectiveIndex, err - } - if midware != nil { - config.Middleware = append(config.Middleware, midware) - } - storages[dir.name] = controller.ServerBlockStorage // persist for this server block - } - - // Stop after TLS setup, since we need to activate Let's Encrypt before continuing; - // it makes some changes to the configs that middlewares might want to know about. - if dir.name == "tls" { - lastDirectiveIndex = k - break - } - } - - configs = append(configs, config) - } - } - return configs, serverBlocks, lastDirectiveIndex, nil -} - -// loadConfigs reads input (named filename) and parses it, returning the -// server configurations in the order they appeared in the input. As part -// of this, it activates Let's Encrypt for the configs that are produced. -// Thus, the returned configs are already optimally configured for HTTPS. -func loadConfigs(filename string, input io.Reader) ([]server.Config, error) { - configs, serverBlocks, lastDirectiveIndex, err := loadConfigsUpToIncludingTLS(filename, input) - if err != nil { - return nil, err - } - - // Now we have all the configs, but they have only been set up to the - // point of tls. We need to activate Let's Encrypt before setting up - // the rest of the middlewares so they have correct information regarding - // TLS configuration, if necessary. (this only appends, so our iterations - // over server blocks below shouldn't be affected) - if !IsRestart() && !Quiet { - fmt.Println("Activating privacy features...") - } - /* TODO(miek): stopped for now - configs, err = https.Activate(configs) - if err != nil { - return nil, err - } else if !IsRestart() && !Quiet { - fmt.Println(" done.") - } - */ - - // Finish setting up the rest of the directives, now that TLS is - // optimally configured. These loops are similar to above except - // we don't iterate all the directives from the beginning and we - // don't create new configs. - configIndex := -1 - for i, sb := range serverBlocks { - onces := makeOnces() - storages := makeStorages() - - for j := range sb.Addresses { - configIndex++ - - for k := lastDirectiveIndex + 1; k < len(directiveOrder); k++ { - dir := directiveOrder[k] - - if tokens, ok := sb.Tokens[dir.name]; ok { - controller := &setup.Controller{ - Config: &configs[configIndex], - Dispenser: parse.NewDispenserTokens(filename, tokens), - OncePerServerBlock: func(f func() error) error { - var err error - onces[dir.name].Do(func() { - err = f() - }) - return err - }, - ServerBlockIndex: i, - ServerBlockHostIndex: j, - ServerBlockHosts: sb.HostList(), - ServerBlockStorage: storages[dir.name], - } - midware, err := dir.setup(controller) - if err != nil { - return nil, err - } - if midware != nil { - configs[configIndex].Middleware = append(configs[configIndex].Middleware, midware) - } - storages[dir.name] = controller.ServerBlockStorage // persist for this server block - } - } - } - } - - return configs, nil -} - -// makeOnces makes a map of directive name to sync.Once -// instance. This is intended to be called once per server -// block when setting up configs so that Setup functions -// for each directive can perform a task just once per -// server block, even if there are multiple hosts on the block. -// -// We need one Once per directive, otherwise the first -// directive to use it would exclude other directives from -// using it at all, which would be a bug. -func makeOnces() map[string]*sync.Once { - onces := make(map[string]*sync.Once) - for _, dir := range directiveOrder { - onces[dir.name] = new(sync.Once) - } - return onces -} - -// makeStorages makes a map of directive name to interface{} -// so that directives' setup functions can persist state -// between different hosts on the same server block during the -// setup phase. -func makeStorages() map[string]interface{} { - storages := make(map[string]interface{}) - for _, dir := range directiveOrder { - storages[dir.name] = nil - } - return storages -} - -// arrangeBindings groups configurations by their bind address. For example, -// a server that should listen on localhost and another on 127.0.0.1 will -// be grouped into the same address: 127.0.0.1. It will return an error -// if an address is malformed or a TLS listener is configured on the -// same address as a plaintext HTTP listener. The return value is a map of -// bind address to list of configs that would become VirtualHosts on that -// server. Use the keys of the returned map to create listeners, and use -// the associated values to set up the virtualhosts. -func arrangeBindings(allConfigs []server.Config) (bindingGroup, error) { - var groupings bindingGroup - - // Group configs by bind address - for _, conf := range allConfigs { - // use default port if none is specified - if conf.Port == "" { - conf.Port = Port - } - - bindAddr, warnErr, fatalErr := resolveAddr(conf) - if fatalErr != nil { - return groupings, fatalErr - } - if warnErr != nil { - log.Printf("[WARNING] Resolving bind address for %s: %v", conf.Address(), warnErr) - } - - // Make sure to compare the string representation of the address, - // not the pointer, since a new *TCPAddr is created each time. - var existing bool - for i := 0; i < len(groupings); i++ { - if groupings[i].BindAddr.String() == bindAddr.String() { - groupings[i].Configs = append(groupings[i].Configs, conf) - existing = true - break - } - } - if !existing { - groupings = append(groupings, bindingMapping{ - BindAddr: bindAddr, - Configs: []server.Config{conf}, - }) - } - } - - // Don't allow HTTP and HTTPS to be served on the same address - for _, group := range groupings { - isTLS := group.Configs[0].TLS.Enabled - for _, config := range group.Configs { - if config.TLS.Enabled != isTLS { - thisConfigProto, otherConfigProto := "HTTP", "HTTP" - if config.TLS.Enabled { - thisConfigProto = "HTTPS" - } - if group.Configs[0].TLS.Enabled { - otherConfigProto = "HTTPS" - } - return groupings, fmt.Errorf("configuration error: Cannot multiplex %s (%s) and %s (%s) on same address", - group.Configs[0].Address(), otherConfigProto, config.Address(), thisConfigProto) - } - } - } - - return groupings, nil -} - -// resolveAddr determines the address (host and port) that a config will -// bind to. The returned address, resolvAddr, should be used to bind the -// listener or group the config with other configs using the same address. -// The first error, if not nil, is just a warning and should be reported -// but execution may continue. The second error, if not nil, is a real -// problem and the server should not be started. -// -// This function does not handle edge cases like port "http" or "https" if -// they are not known to the system. It does, however, serve on the wildcard -// host if resolving the address of the specific hostname fails. -func resolveAddr(conf server.Config) (resolvAddr *net.TCPAddr, warnErr, fatalErr error) { - resolvAddr, warnErr = net.ResolveTCPAddr("tcp", net.JoinHostPort(conf.BindHost, conf.Port)) - if warnErr != nil { - // the hostname probably couldn't be resolved, just bind to wildcard then - resolvAddr, fatalErr = net.ResolveTCPAddr("tcp", net.JoinHostPort("", conf.Port)) - if fatalErr != nil { - return - } - } - - return -} - -// validDirective returns true if d is a valid -// directive; false otherwise. -func validDirective(d string) bool { - for _, dir := range directiveOrder { - if dir.name == d { - return true - } - } - return false -} - -// DefaultInput returns the default Corefile input -// to use when it is otherwise empty or missing. -// It uses the default host and port and root. -func DefaultInput() CorefileInput { - port := Port - return CorefileInput{ - Contents: []byte(fmt.Sprintf("%s:%s\nroot %s", Host, port, Root)), - } -} - -// These defaults are configurable through the command line -var ( - // Root is the site root - Root = DefaultRoot - - // Host is the site host - Host = DefaultHost - - // Port is the site port - Port = DefaultPort -) - -// bindingMapping maps a network address to configurations -// that will bind to it. The order of the configs is important. -type bindingMapping struct { - BindAddr *net.TCPAddr - Configs []server.Config -} - -// bindingGroup maps network addresses to their configurations. -// Preserving the order of the groupings is important -// (related to graceful shutdown and restart) -// so this is a slice, not a literal map. -type bindingGroup []bindingMapping |