plugin/file: run additional processing for wildcard answers (#8222)

* plugin/file: run additional processing for wildcard answers

The wildcard branch of Zone.Lookup returned a nil additional section, so a
wildcard-synthesized MX/SRV/SVCB/HTTPS answer with an in-bailiwick target
did not include the target's A/AAAA glue. The non-wildcard path already
does this, so call additionalProcessing in the wildcard branch as well.

Fixes #6629

Signed-off-by: Salih Muhammed <root@lr0.org>

* plugin/file: move wildcard additional test into wildcard_test.go

Requested in review: keep the wildcard tests in one file.

Signed-off-by: Salih Muhammed <root@lr0.org>

---------

Signed-off-by: Salih Muhammed <root@lr0.org>
This commit is contained in:
Saleh
2026-07-05 02:07:01 +03:00
committed by GitHub
parent bc4343b083
commit 7abc21bc49
3 changed files with 70 additions and 2 deletions

View File

@@ -226,6 +226,11 @@ func (z *Zone) Lookup(ctx context.Context, state request.Request, qname string)
return nil, ret, nil, NoData return nil, ret, nil, NoData
} }
// Additional section processing for MX, SRV, SVCB, HTTPS. Check response
// and see if any of the names are in bailiwick - if so add IP addresses
// to the additional section. This mirrors the non-wildcard path above.
additional := z.additionalProcessing(rrs, do)
auth := ap.ns(do) auth := ap.ns(do)
if do { if do {
// An NSEC is needed to say no longer name exists under this wildcard. // An NSEC is needed to say no longer name exists under this wildcard.
@@ -238,7 +243,7 @@ func (z *Zone) Lookup(ctx context.Context, state request.Request, qname string)
sigs = rrutil.SubTypeSignature(sigs, qtype) sigs = rrutil.SubTypeSignature(sigs, qtype)
rrs = append(rrs, sigs...) rrs = append(rrs, sigs...)
} }
return rrs, auth, nil, Success return rrs, auth, additional, Success
} }
rcode := NameError rcode := NameError

View File

@@ -53,12 +53,17 @@ var svcbTestCases = []test.Case{
}, },
}, },
{ {
// Wildcard SVCB expansion (no additional section — wildcards don't run additionalProcessing) // Wildcard SVCB expansion — glue for the in-bailiwick target is added to
// the additional section, same as for non-wildcard answers (issue #6629).
Qname: "_http._tcp.example.com.", Qtype: dns.TypeSVCB, Qname: "_http._tcp.example.com.", Qtype: dns.TypeSVCB,
Answer: []dns.RR{ Answer: []dns.RR{
test.SVCB("_http._tcp.example.com. 1800 IN SVCB 1 svc-target.example.com. port=\"443\""), test.SVCB("_http._tcp.example.com. 1800 IN SVCB 1 svc-target.example.com. port=\"443\""),
}, },
Ns: svcbAuth, Ns: svcbAuth,
Extra: []dns.RR{
test.A("svc-target.example.com. 1800 IN A 192.0.2.10"),
test.AAAA("svc-target.example.com. 1800 IN AAAA 2001:db8::10"),
},
}, },
{ {
// NoData: existing name, no SVCB record // NoData: existing name, no SVCB record

View File

@@ -296,3 +296,61 @@ example.org. IN NS b.iana-servers.net.
*.intern.example.org. IN A 127.0.1.52 *.intern.example.org. IN A 127.0.1.52
foo.example.org. IN A 127.0.0.54 foo.example.org. IN A 127.0.0.54
` `
// Wildcard-synthesized answers must run additional-section processing for
// MX/SRV/SVCB/HTTPS targets, just like non-wildcard answers do.
// See https://github.com/coredns/coredns/issues/6629.
const dbWildcardAdditional = `
$TTL 30M
$ORIGIN example.org.
@ IN SOA ns.example.org. admin.example.org. 2024010100 14400 3600 604800 14400
IN NS ns.example.org.
ns IN A 192.0.2.1
mail IN A 192.0.2.10
IN AAAA 2001:db8::10
*.wild IN MX 10 mail.example.org.
`
const testWildcardAdditionalOrigin = "example.org."
var wildcardAdditionalTestCases = []test.Case{
{
// Wildcard-synthesized MX answer includes glue (A/AAAA) for the
// in-bailiwick target in the additional section.
Qname: "foo.wild.example.org.", Qtype: dns.TypeMX,
Answer: []dns.RR{
test.MX("foo.wild.example.org. 1800 IN MX 10 mail.example.org."),
},
Ns: []dns.RR{
test.NS("example.org. 1800 IN NS ns.example.org."),
},
Extra: []dns.RR{
test.A("mail.example.org. 1800 IN A 192.0.2.10"),
test.AAAA("mail.example.org. 1800 IN AAAA 2001:db8::10"),
},
},
}
func TestLookupWildcardAdditional(t *testing.T) {
zone, err := Parse(strings.NewReader(dbWildcardAdditional), testWildcardAdditionalOrigin, "stdin", 0)
if err != nil {
t.Fatalf("Expected no error when reading zone, got %q", err)
}
fm := File{Next: test.ErrorHandler(), Zones: Zones{Z: map[string]*Zone{testWildcardAdditionalOrigin: zone}, Names: []string{testWildcardAdditionalOrigin}}}
ctx := context.TODO()
for _, tc := range wildcardAdditionalTestCases {
m := tc.Msg()
rec := dnstest.NewRecorder(&test.ResponseWriter{})
if _, err := fm.ServeDNS(ctx, rec, m); err != nil {
t.Errorf("Expected no error for %q/%d, got %v", tc.Qname, tc.Qtype, err)
continue
}
if err := test.SortAndCheck(rec.Msg, tc); err != nil {
t.Errorf("Test %q/%d: %v", tc.Qname, tc.Qtype, err)
}
}
}