diff --git a/checker/collect.go b/checker/collect.go index e8bb96c..ee326e3 100644 --- a/checker/collect.go +++ b/checker/collect.go @@ -159,7 +159,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) { if target == "" { return nil, nil } - ptOwner := preferRRName(b.Record.Hdr.Name, owner) + ptOwner := preferRRName(b.Record.Hdr.Name, owner, apex) return []Pointer{{ Owner: ptOwner, Subdomain: sub, @@ -180,7 +180,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) { continue } out = append(out, Pointer{ - Owner: preferRRName(r.Hdr.Name, owner), + Owner: preferRRName(r.Hdr.Name, owner, apex), Subdomain: sub, Rrtype: "MX", Target: target, @@ -201,7 +201,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) { continue } out = append(out, Pointer{ - Owner: preferRRName(r.Hdr.Name, owner), + Owner: preferRRName(r.Hdr.Name, owner, apex), Subdomain: sub, Rrtype: "SRV", Target: target, @@ -215,7 +215,7 @@ func extractPointers(sub, apex string, svc rawService) ([]Pointer, error) { if err := json.Unmarshal(svc.Service, &b); err != nil { return nil, fmt.Errorf("decode orphan body: %w", err) } - ptOwner := preferRRName(b.Record.Hdr.Name, owner) + ptOwner := preferRRName(b.Record.Hdr.Name, owner, apex) switch b.Record.Hdr.Rrtype { case dns.TypeNS: target := normaliseTarget(b.Record.Ns, ptOwner, apex) @@ -330,13 +330,20 @@ func ownerFQDN(svcDomain, sub, apex string) string { return sub + "." + apex } -// preferRRName returns the RR header Name when present, as it is authoritative over the service-derived owner. -func preferRRName(rrName, fallback string) string { +// preferRRName returns the RR header Name as an FQDN when present. +// happyDomain encodes service-embedded record owners relative to the zone +// apex, so the rrName must be joined with apex unless it already contains +// the apex suffix (services published with absolute owners). +func preferRRName(rrName, fallback, apex string) string { rrName = strings.TrimSuffix(rrName, ".") - if rrName != "" { + if rrName == "" { + return fallback + } + apex = strings.TrimSuffix(apex, ".") + if apex == "" || rrName == apex || strings.HasSuffix(rrName, "."+apex) { return rrName } - return fallback + return rrName + "." + apex } // normaliseTarget converts a target to FQDN form; happyDomain stores in-zone targets relative, external ones absolute.