diff --git a/core/dnsserver/config.go b/core/dnsserver/config.go index d0a432a85..e5200d67c 100644 --- a/core/dnsserver/config.go +++ b/core/dnsserver/config.go @@ -50,6 +50,10 @@ type Config struct { // on them should register themselves here. The name should be the name as return by the // Handler's Name method. registry map[string]plugin.Handler + + // firstConfigInBlock is used to reference the first config in a server block, for the + // purpose of sharing single instance of each plugin among all zones in a server block. + firstConfigInBlock *Config } // keyForConfig builds a key for identifying the configs during setup time diff --git a/core/dnsserver/register.go b/core/dnsserver/register.go index 15772a248..ec254085e 100644 --- a/core/dnsserver/register.go +++ b/core/dnsserver/register.go @@ -108,6 +108,8 @@ func (h *dnsContext) InspectServerBlocks(sourceFile string, serverBlocks []caddy serverBlocks[ib].Keys = s.Keys // important to save back the new keys that are potentially created here. + var firstConfigInBlock *Config + for ik := range s.Keys { za := zoneAddrs[ik] s.Keys[ik] = za.String() @@ -118,6 +120,15 @@ func (h *dnsContext) InspectServerBlocks(sourceFile string, serverBlocks []caddy Port: za.Port, Transport: za.Transport, } + + // 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 + keyConfig := keyForConfig(ib, ik) h.saveConfig(keyConfig, cfg) } @@ -135,6 +146,17 @@ func (h *dnsContext) MakeServers() ([]caddy.Server, error) { return nil, errValid } + // 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 + c.TLSConfig = c.firstConfigInBlock.TLSConfig + } + // we must map (group) each config to a bind address groups, err := groupConfigsByListenAddr(h.configs) if err != nil { diff --git a/go.mod b/go.mod index c06b644a7..574fb5b4d 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/Microsoft/go-winio v0.5.0 // indirect github.com/apparentlymart/go-cidr v1.1.0 github.com/aws/aws-sdk-go v1.39.0 - github.com/coredns/caddy v1.1.0 + github.com/coredns/caddy v1.1.1 github.com/dnstap/golang-dnstap v0.4.0 github.com/farsightsec/golang-framestream v0.3.0 github.com/golang/protobuf v1.5.2 diff --git a/go.sum b/go.sum index b314174b1..81f5f2461 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= -github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= +github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= +github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= diff --git a/test/server_test.go b/test/server_test.go index c58915ee7..54e44722d 100644 --- a/test/server_test.go +++ b/test/server_test.go @@ -1,7 +1,11 @@ package test import ( + "reflect" "testing" + "unsafe" + + "github.com/coredns/coredns/core/dnsserver" "github.com/miekg/dns" ) @@ -107,3 +111,30 @@ func TestReverseExpansion(t *testing.T) { t.Errorf("Expected 0 RRs in additional section, got %d", len(r.Extra)) } } + +func TestMultiZoneBlockConfigs(t *testing.T) { + corefile := `.:40000 .:40001 .:40002 { + debug + }` + + server, err := CoreDNSServer(corefile) + defer server.Stop() + + if err != nil { + t.Fatalf("Could not get CoreDNS serving instance: %s", err) + } + + // unsafe reflection to read unexported fields "context" and "configs" within context + ctxVal := reflect.ValueOf(server).Elem().FieldByName("context") + ctxVal2 := reflect.NewAt(ctxVal.Type(), unsafe.Pointer(ctxVal.UnsafeAddr())).Elem() + configs := reflect.ValueOf(ctxVal2.Interface()).Elem().FieldByName("configs") + configs2 := reflect.NewAt(configs.Type(), unsafe.Pointer(configs.UnsafeAddr())).Elem() + + for i := 0; i < 3; i++ { + v := configs2.Index(i) + config := v.Interface().(*dnsserver.Config) + if !config.Debug { + t.Fatalf("Debug was not set for %s://%s:%s", config.Transport, config.Zone, config.Port) + } + } +}