package checker import ( "context" "fmt" sdk "git.happydns.org/checker-sdk-go/checker" ) type cnameCoexistenceRule struct{} func (cnameCoexistenceRule) Name() string { return "cname_coexistence" } func (cnameCoexistenceRule) Description() string { return "Flags other RRsets that sit at the same owner as a CNAME (RFC 1034 §3.6.2 / RFC 2181 §10.1). Honours allowApexCNAME and recognizeApexFlattening." } func (cnameCoexistenceRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState { data, errState := loadAlias(ctx, obs) if errState != nil { return errState } if !apexKnown(data) { return skipped("apex lookup failed") } if !data.OwnerHasCNAME { return skipped("owner has no CNAME") } if len(data.Coexisting) == 0 { return okState(data.Owner, "CNAME is the only RRset at its owner") } isApex := data.OwnerIsApex recognize := recognizeApexFlattening(opts) allow := allowApexCNAME(opts) var out []sdk.CheckState for _, rr := range data.Coexisting { // Provider-side flattening serves apex A/AAAA on a synthetic owner, // so the wire-level coexistence is intentional, not a zone bug. if isApex && recognize && data.ApexFlattening && (rr.Type == "A" || rr.Type == "AAAA") { continue } status := sdk.StatusCrit if isApex && allow { status = sdk.StatusWarn } out = append(out, withHint(sdk.CheckState{ Status: status, Subject: data.Owner, Message: fmt.Sprintf("%s and CNAME both exist at %s (RFC 1034 §3.6.2 / RFC 2181 §10.1)", rr.Type, data.Owner), Code: rr.Type, }, "Remove the sibling record or move it under a different label; a name cannot simultaneously carry a CNAME and other data.")) } if len(out) == 0 { return okState(data.Owner, "CNAME coexistence exempted by ALIAS/ANAME flattening") } return out }