ret = kr_nsec_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner);
} else {
ret = kr_nsec3_wildcard_answer_response_check(pkt, KNOT_AUTHORITY, covered->owner, trim_labels - 1);
+ if (ret == kr_error(DNSSEC_OUT_OF_RANGE)) {
+ ret = 0;
+ vctx->flags |= KR_DNSSEC_VFLG_OPTOUT;
+ }
}
if (ret != 0) {
continue;
struct dseckey;
#define KR_DNSSEC_VFLG_WEXPAND 0x01
+#define KR_DNSSEC_VFLG_OPTOUT 0x02
/** DNSSEC validation context. */
struct kr_rrset_validation_ctx {
return ret;
}
if (flags & FLG_NAME_COVERED) {
- return kr_ok();
+ return has_optout(rrset) ?
+ kr_error(DNSSEC_OUT_OF_RANGE) : kr_ok();
}
}
* @param section_id Packet section to be processed.
* @param sname Name to be checked.
* @param trim_to_next Number of labels to remove to obtain next closer name.
- * @return 0 or error code.
+ * @return 0 or error code:
+ * DNSSEC_OUT_OF_RANGE - NSEC3 RR that covers a wildcard
+ * has been found, but has opt-out flag set;
+ * otherwise - error.
*/
int kr_nsec3_wildcard_answer_response_check(const knot_pkt_t *pkt, knot_section_t section_id,
const knot_dname_t *sname, int trim_to_next);
}
/* Records were validated.
- * If there is wildcard expansion in answer, flag the query.
+ * If there is wildcard expansion in answer,
+ * or optout - flag the query.
*/
if (an_flags & KR_DNSSEC_VFLG_WEXPAND) {
qry->flags |= QUERY_DNSSEC_WEXPAND;
}
+ if (an_flags & KR_DNSSEC_VFLG_OPTOUT) {
+ qry->flags |= QUERY_DNSSEC_OPTOUT;
+ }
return ret;
}
return ret;
}
- if (vctx.flags & KR_DNSSEC_VFLG_WEXPAND)
- {
+ if (vctx.flags & KR_DNSSEC_VFLG_WEXPAND) {
qry->flags |= QUERY_DNSSEC_WEXPAND;
}
+ if (vctx.flags & KR_DNSSEC_VFLG_OPTOUT) {
+ qry->flags |= QUERY_DNSSEC_OPTOUT;
+ }
}
return kr_ok();