checker: fix @ target resolving to apex via sdk.JoinRelative
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing

A CNAME (or MX/SRV/NS) whose target is "@" was being concatenated
literally as "@.<apex>" instead of resolving to the apex itself.
Replace the hand-rolled normaliseTarget logic with sdk.JoinRelative,
which correctly maps "" and "@" to the origin. Absolute FQDNs
(trailing dot, used for external targets) are still stripped before
the call so the external-target path is unaffected.
This commit is contained in:
nemunaire 2026-05-16 21:44:47 +08:00
commit c4abc1b861

View file

@ -155,7 +155,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
if err := json.Unmarshal(svc.Service, &b); err != nil { if err := json.Unmarshal(svc.Service, &b); err != nil {
return nil, fmt.Errorf("decode cname body: %w", err) return nil, fmt.Errorf("decode cname body: %w", err)
} }
target := normaliseTarget(b.Record.Target, owner, apex) target := normaliseTarget(b.Record.Target, apex)
if target == "" { if target == "" {
return nil, nil return nil, nil
} }
@ -175,7 +175,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
} }
out := make([]Pointer, 0, len(b.MXs)) out := make([]Pointer, 0, len(b.MXs))
for _, r := range b.MXs { for _, r := range b.MXs {
target := normaliseTarget(r.Mx, owner, apex) target := normaliseTarget(r.Mx, apex)
if target == "" { if target == "" {
continue continue
} }
@ -196,7 +196,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
} }
out := make([]Pointer, 0, len(b.Records)) out := make([]Pointer, 0, len(b.Records))
for _, r := range b.Records { for _, r := range b.Records {
target := normaliseTarget(r.Target, owner, apex) target := normaliseTarget(r.Target, apex)
if target == "" { if target == "" {
continue continue
} }
@ -218,7 +218,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
ptOwner := preferRRName(b.Record.Hdr.Name, owner, apex) ptOwner := preferRRName(b.Record.Hdr.Name, owner, apex)
switch b.Record.Hdr.Rrtype { switch b.Record.Hdr.Rrtype {
case dns.TypeNS: case dns.TypeNS:
target := normaliseTarget(b.Record.Ns, ptOwner, apex) target := normaliseTarget(b.Record.Ns, apex)
if target == "" { if target == "" {
return nil, nil return nil, nil
} }
@ -230,7 +230,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
ServiceType: svc.Type, ServiceType: svc.Type,
}}, nil }}, nil
case dns.TypeCNAME: case dns.TypeCNAME:
target := normaliseTarget(b.Record.Target, ptOwner, apex) target := normaliseTarget(b.Record.Target, apex)
if target == "" { if target == "" {
return nil, nil return nil, nil
} }
@ -242,7 +242,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) {
ServiceType: svc.Type, ServiceType: svc.Type,
}}, nil }}, nil
case dns.TypeMX: case dns.TypeMX:
target := normaliseTarget(b.Record.Mx, ptOwner, apex) target := normaliseTarget(b.Record.Mx, apex)
if target == "" { if target == "" {
return nil, nil return nil, nil
} }
@ -349,20 +349,14 @@ func preferRRName(rrName, fallback, apex string) string {
return rrName + "." + apex return rrName + "." + apex
} }
// normaliseTarget converts a target to FQDN form; happyDomain stores in-zone targets relative, external ones absolute. // normaliseTarget converts a target to FQDN form without trailing dot.
func normaliseTarget(target, owner, apex string) string { // Absolute FQDNs (trailing dot) are stripped; relative names and "@" are
t := strings.TrimSpace(target) // resolved against apex via sdk.JoinRelative.
if t == "" { func normaliseTarget(target, apex string) string {
return "" if t, ok := strings.CutSuffix(strings.TrimSpace(target), "."); ok {
return t
} }
if trimmed, ok := strings.CutSuffix(t, "."); ok { return sdk.JoinRelative(target, apex)
return trimmed
}
// Relative target: anchor under apex (empty apex only occurs in tests that omit domain_name).
if apex != "" {
return t + "." + apex
}
return t + "." + owner
} }
func displaySubdomain(s string) string { func displaySubdomain(s string) string {