}
/**
- * Closest NONEMPTY encloser.
- * Thus, no empty nonterminals are returned.
- * @param qname: query name
- * @param nsec: nsec record.
- * @return the name (part of qname).
+ * Find shared topdomain that exists
*/
-static uint8_t*
-nsec_closest_nonempty(uint8_t* qname, struct ub_packed_rrset_key* nsec)
+static void
+dlv_topdomain(struct ub_packed_rrset_key* nsec, uint8_t* qname,
+ uint8_t** nm, size_t* nm_len)
{
- uint8_t* next;
- size_t nlen;
- uint8_t* common1, *common2;
- if(!nsec_get_next(nsec, &next, &nlen))
- return NULL;
- /* shortest common with owner or next name */
- common1 = dname_get_shared_topdomain(qname, nsec->rk.dname);
- common2 = dname_get_shared_topdomain(qname, next);
- if(dname_count_labels(common1) < dname_count_labels(common2))
- return common1;
- return common2;
+ /* make sure reply is part of nm */
+ /* take shared topdomain with left of NSEC. */
+
+ /* because, if empty nonterminal, then right is subdomain of qname.
+ * and any shared topdomain would be empty nonterminals.
+ *
+ * If nxdomain, then the right is bigger, and could have an
+ * interesting shared topdomain, but if it does have one, it is
+ * an empty nonterminal. An empty nonterminal shared with the left
+ * one. */
+ int n;
+ uint8_t* common = dname_get_shared_topdomain(qname, nsec->rk.dname);
+ n = dname_count_labels(*nm) - dname_count_labels(common);
+ dname_remove_labels(nm, nm_len, n);
}
int val_nsec_check_dlv(struct query_info* qinfo,
rep->rrsets[i]->rk.dname, qinfo->qname);
if(c == 0) {
/* plain match */
+ if(nsec_has_type(rep->rrsets[i],
+ LDNS_RR_TYPE_DLV))
+ return 0;
dname_remove_label(nm, nm_len);
return 1;
} else if(c < 0 &&
dname_strict_subdomain_c(next, qinfo->qname)) {
/* ENT */
- *nm = nsec_closest_nonempty(
- *nm, rep->rrsets[i]);
- if(!*nm) return 0;
+ dlv_topdomain(rep->rrsets[i], qinfo->qname,
+ nm, nm_len);
return 1;
}
}
for(i=0; i<rep->ns_numrrsets; i++) {
if(val_nsec_proves_name_error(rep->rrsets[i],
qinfo->qname)) {
- *nm = nsec_closest_nonempty(
- *nm, rep->rrsets[i]);
- if(!*nm) return 0;
+ dlv_topdomain(rep->rrsets[i], qinfo->qname,
+ nm, nm_len);
return 1;
}
}
vq->ds_rrset = 0;
vq->trust_anchor = anchors_lookup(qstate->env->anchors,
lookup_name, lookup_len, vq->qchase.qclass);
- if(vq->trust_anchor == NULL) {
- /*response isn't under a trust anchor, so we cannot validate.*/
- vq->chase_reply->security = sec_status_indeterminate;
- /* go to finished state to cache this result */
- vq->state = VAL_FINISHED_STATE;
- return 1;
- }
/* Determine the signer/lookup name */
val_find_signer(subtype, &vq->qchase, vq->orig_msg->rep,
/* for NXDOMAIN it could be signed by a parent of the trust anchor */
if(subtype == VAL_CLASS_NAMEERROR && vq->signer_name &&
+ vq->trust_anchor &&
dname_strict_subdomain_c(vq->trust_anchor->name, lookup_name)){
while(vq->trust_anchor && dname_strict_subdomain_c(
vq->trust_anchor->name, lookup_name)) {
vq->key_entry = key_cache_obtain(ve->kcache, lookup_name, lookup_len,
vq->qchase.qclass, qstate->region, *qstate->env->now);
-
+
+ /* there is no key(from DLV) and no trust anchor */
+ if(vq->key_entry == NULL && vq->trust_anchor == NULL) {
+ /*response isn't under a trust anchor, so we cannot validate.*/
+ vq->chase_reply->security = sec_status_indeterminate;
+ /* go to finished state to cache this result */
+ vq->state = VAL_FINISHED_STATE;
+ return 1;
+ }
/* if not key, or if keyentry is *above* the trustanchor, i.e.
* the keyentry is based on another (higher) trustanchor */
- if(vq->key_entry == NULL || dname_strict_subdomain_c(
+ else if(vq->key_entry == NULL || dname_strict_subdomain_c(
vq->trust_anchor->name, vq->key_entry->name)) {
/* fire off a trust anchor priming query. */
verbose(VERB_DETAIL, "prime trust anchor");
else if(vq->dlv_status==dlv_there_is_no_dlv)
verbose(VERB_ALGO, "DLV woke up with status dlv_there_is_no_dlv");
else verbose(VERB_ALGO, "DLV woke up with status unknown");
- log_nametypeclass(VERB_ALGO, "next look", vq->dlv_lookup_name,
- LDNS_RR_TYPE_DLV, vq->qchase.qclass);
if(vq->dlv_status == dlv_error) {
verbose(VERB_QUERY, "failed DLV lookup");
return val_error(qstate, id);
} else if(vq->dlv_status == dlv_success) {
+ uint8_t* nm;
+ size_t nmlen;
/* chain continues with DNSKEY, continue in FINDKEY */
vq->state = VAL_FINDKEY_STATE;
+
+ /* strip off the DLV suffix from the name; could result in . */
+ log_assert(dname_subdomain_c(vq->ds_rrset->rk.dname,
+ qstate->env->anchors->dlv_anchor->name));
+ nmlen = vq->ds_rrset->rk.dname_len -
+ qstate->env->anchors->dlv_anchor->namelen + 1;
+ nm = regional_alloc_init(qstate->region,
+ vq->ds_rrset->rk.dname, nmlen);
+ if(!nm) {
+ log_err("Out of memory in DLVLook");
+ return val_error(qstate, id);
+ }
+ nm[nmlen-1] = 0;
+
+ vq->ds_rrset->rk.dname = nm;
+ vq->ds_rrset->rk.dname_len = nmlen;
+
if(!generate_request(qstate, id, vq->ds_rrset->rk.dname,
vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY,
vq->qchase.qclass, BIT_CD)) {
return 1;
}
- if(!generate_request(qstate, id, vq->dlv_lookup_name,
- vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
+ if(!generate_request(qstate, id, vq->dlv_lookup_name,
+ vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
vq->qchase.qclass, 0)) {
return val_error(qstate, id);
}