plugin/secondary: serve catalog member zones (#8230)

Signed-off-by: houyuwushang <liuluoqianqiu@outlook.com>
This commit is contained in:
houyuwushang
2026-07-10 08:42:30 +08:00
committed by GitHub
parent e4990abfa3
commit 1e01c0ad7c
9 changed files with 368 additions and 67 deletions

View File

@@ -24,11 +24,15 @@ type (
Next plugin.Handler
Zones
Xfer *transfer.Transfer
ZoneLookupFunc
TransferInFunc
Fall fall.F
}
// ZoneLookupFunc looks up the authoritative zone for qname.
ZoneLookupFunc func(qname string) (zone string, z *Zone, ok bool)
// Zones maps zone names to a *Zone.
Zones struct {
Z map[string]*Zone // A map mapping zone (origin) to the Zone's data
@@ -41,9 +45,8 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
state := request.Request{W: w, Req: r}
qname := state.Name()
// TODO(miek): match the qname better in the map
zone := plugin.Zones(f.Zones.Names).Matches(qname)
if zone == "" {
zone, z, ok := f.lookupZone(qname)
if !ok {
// If no next plugin is configured, it's more correct to return REFUSED as file acts as an authoritative server
if f.Next == nil {
return dns.RcodeRefused, nil
@@ -51,8 +54,7 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
}
z, ok := f.Z[zone]
if !ok || z == nil {
if z == nil {
return dns.RcodeServerFailure, nil
}
@@ -134,6 +136,22 @@ func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
// Name implements the Handler interface.
func (f File) Name() string { return "file" }
func (f File) lookupZone(qname string) (string, *Zone, bool) {
if f.ZoneLookupFunc != nil {
return f.ZoneLookupFunc(qname)
}
// TODO(miek): match the qname better in the map
zone := plugin.Zones(f.Zones.Names).Matches(qname)
if zone == "" {
return "", nil, false
}
z, ok := f.Z[zone]
if !ok {
return zone, nil, true
}
return zone, z, true
}
func (f File) transferIn(z *Zone, t *transfer.Transfer) error {
if f.TransferInFunc != nil {
return f.TransferInFunc(z, t)

View File

@@ -9,8 +9,8 @@ import (
// Transfer implements the transfer.Transfer interface.
func (f File) Transfer(zone string, serial uint32) (<-chan []dns.RR, error) {
z, ok := f.Z[zone]
if !ok || z == nil {
matched, z, ok := f.lookupZone(zone)
if !ok || matched != zone || z == nil {
return nil, transfer.ErrNotAuthoritative
}
return z.Transfer(serial)

View File

@@ -8,6 +8,7 @@ import (
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/test"
"github.com/coredns/coredns/plugin/transfer"
"github.com/miekg/dns"
)
@@ -70,3 +71,15 @@ func TestAXFRWithOutTransferPlugin(t *testing.T) {
t.Errorf("Expecting REFUSED, got %d", code)
}
}
func TestTransferRequiresExactZone(t *testing.T) {
zone, err := Parse(strings.NewReader(dbMiekNL), testzone, "stdin", 0)
if err != nil {
t.Fatalf("Expected no error when reading zone, got %q", err)
}
fm := File{Zones: Zones{Z: map[string]*Zone{testzone: zone}, Names: []string{testzone}}}
if _, err := fm.Transfer("www."+testzone, 0); err != transfer.ErrNotAuthoritative {
t.Fatalf("expected ErrNotAuthoritative for subdomain transfer, got %v", err)
}
}