diff --git a/doc/Changelog b/doc/Changelog index 00682e24a..92ad04c04 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +14 August 2008: Wouter + - synthesize DLV messages from the rrset cache, like done for DS. + 13 August 2008: Wouter - bug #203: nicer do-auto log message when user sets incompatible options. diff --git a/services/cache/dns.c b/services/cache/dns.c index e1dcf325e..bea8182dc 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -595,8 +595,9 @@ dns_cache_lookup(struct module_env* env, lock_rw_unlock(&rrset->entry.lock); } - /* construct DS, DNSKEY messages from rrset cache. */ - if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY) && + /* construct DS, DNSKEY, DLV messages from rrset cache. */ + if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY || + qtype == LDNS_RR_TYPE_DLV) && (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, qtype, qclass, 0, now, 0))) { /* if the rrset is from the additional section, and the diff --git a/validator/val_nsec.c b/validator/val_nsec.c index f984a0dab..009aa814c 100644 --- a/validator/val_nsec.c +++ b/validator/val_nsec.c @@ -45,6 +45,7 @@ #include "validator/val_utils.h" #include "util/data/msgreply.h" #include "util/data/dname.h" +#include "util/net_help.h" /** get ttl of rrset */ static uint32_t @@ -479,3 +480,79 @@ val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, } return 0; } + +/** + * Closest NONEMPTY encloser. + * Thus, no empty nonterminals are returned. + * @param qname: query name + * @param nsec: nsec record. + * @return the name (part of qname). + */ +static uint8_t* +nsec_closest_nonempty(uint8_t* qname, struct ub_packed_rrset_key* nsec) +{ + 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; +} + +int val_nsec_check_dlv(struct query_info* qinfo, + struct reply_info* rep, uint8_t** nm, size_t* nm_len) +{ + uint8_t* next; + size_t i, nlen; + int c; + /* we should now have a NOERROR/NODATA or NXDOMAIN message */ + if(rep->an_numrrsets != 0) { + return 0; + } + /* is this NOERROR ? */ + if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) { + /* it can be a plain NSEC match - go up one more level. */ + /* or its an empty nonterminal - go up to nonempty level */ + for(i=0; ins_numrrsets; i++) { + if(!nsec_get_next(rep->rrsets[i], &next, &nlen)) + continue; + c = dname_canonical_compare( + rep->rrsets[i]->rk.dname, qinfo->qname); + if(c == 0) { + /* plain match */ + 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; + return 1; + } + } + return 0; + } + + /* is this NXDOMAIN ? */ + if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN) { + /* find the qname denial NSEC record. It can tell us + * a closest encloser name; or that we not need bother */ + for(i=0; ins_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; + return 1; + } + } + return 0; + } + return 0; +} diff --git a/validator/val_nsec.h b/validator/val_nsec.h index 68ab91a83..c7e4b0bcd 100644 --- a/validator/val_nsec.h +++ b/validator/val_nsec.h @@ -145,4 +145,17 @@ uint8_t* nsec_closest_encloser(uint8_t* qname, int val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, size_t qnamelen); +/** + * Determine the DLV result, what to do with NSEC DLV reply. + * @param qinfo: what was queried for. + * @param rep: the nonpositive reply. + * @param nm: dlv lookup name, to adjust for new lookup name (if needed). + * @param nm_len: length of lookup name. + * @return 0 on error, 1 if a higher point is found. + * If the higher point is above the dlv repo anchor, the qname does + * not exist. + */ +int val_nsec_check_dlv(struct query_info* qinfo, + struct reply_info* rep, uint8_t** nm, size_t* nm_len); + #endif /* VALIDATOR_VAL_NSEC_H */ diff --git a/validator/validator.c b/validator/validator.c index a1e1a8cee..c05920be1 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -287,11 +287,12 @@ needs_validation(struct module_qstate* qstate, int ret_rc, * @param namelen: length of name. * @param qtype: query type. * @param qclass: query class. + * @param flags: additional flags, such as the CD bit (BIT_CD), or 0. * @return false on alloc failure. */ static int generate_request(struct module_qstate* qstate, int id, uint8_t* name, - size_t namelen, uint16_t qtype, uint16_t qclass) + size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags) { struct module_qstate* newq; struct query_info ask; @@ -302,7 +303,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name, log_query_info(VERB_ALGO, "generate request", &ask); fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); if(!(*qstate->env->attach_sub)(qstate, &ask, - (uint16_t)(BIT_RD|BIT_CD), 0, &newq)){ + (uint16_t)(BIT_RD|flags), 0, &newq)){ log_err("Could not generate request: out of memory"); return 0; } @@ -328,7 +329,7 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq, int id, struct trust_anchor* toprime) { int ret = generate_request(qstate, id, toprime->name, toprime->namelen, - LDNS_RR_TYPE_DNSKEY, toprime->dclass); + LDNS_RR_TYPE_DNSKEY, toprime->dclass, BIT_CD); if(!ret) { log_err("Could not prime trust anchor: out of memory"); return 0; @@ -1303,7 +1304,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) vq->key_entry->name) != 0) { if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, - vq->qchase.qclass)) { + vq->qchase.qclass, BIT_CD)) { log_err("mem error generating DNSKEY request"); return val_error(qstate, id); } @@ -1313,7 +1314,8 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) if(!vq->ds_rrset || query_dname_compare(vq->ds_rrset->rk.dname, target_key_name) != 0) { if(!generate_request(qstate, id, target_key_name, - target_key_len, LDNS_RR_TYPE_DS, vq->qchase.qclass)) { + target_key_len, LDNS_RR_TYPE_DS, vq->qchase.qclass, + BIT_CD)) { log_err("mem error generating DS request"); return val_error(qstate, id); } @@ -1323,7 +1325,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) /* Otherwise, it is time to query for the DNSKEY */ if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, - vq->qchase.qclass)) { + vq->qchase.qclass, BIT_CD)) { log_err("mem error generating DNSKEY request"); return val_error(qstate, id); } @@ -1472,6 +1474,130 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq, return 1; } +/** + * Init DLV check. + * Called when a query is determined by other trust anchors to be insecure + * (or indeterminate). Then we look if there is a key in the DLV. + * Performs aggressive negative cache check to see if there is no key. + * Otherwise, spawns a DLV query, and changes to the DLV wait state. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if there is no DLV. + * false: processing is finished for the validator operate(). + * This function may exit in three ways: + * o no DLV (agressive cache), so insecure. (true) + * o error - stop processing (false) + * o DLV lookup was started, stop processing (false) + */ +static int +val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + uint8_t* nm; + size_t nm_len; + /* there must be a DLV configured */ + log_assert(qstate->env->anchors->dlv_anchor); + /* this bool is true to avoid looping in the DLV checks */ + log_assert(vq->dlv_checked); + + /* init the DLV lookup variables */ + vq->dlv_lookup_name = NULL; + vq->dlv_lookup_name_len = 0; + vq->dlv_insecure_at = NULL; + vq->dlv_insecure_at_len = 0; + + /* Determine the name for which we want to lookup DLV. + * This name is for the current message, or + * for the current RRset for CNAME, referral subtypes. + * If there is a signer, use that, otherwise the domain name */ + if(vq->signer_name) { + nm = vq->signer_name; + nm_len = vq->signer_len; + } else { + /* use qchase */ + nm = vq->qchase.qname; + nm_len = vq->qchase.qname_len; + } + log_nametypeclass(VERB_ALGO, "DLV init look", nm, LDNS_RR_TYPE_DS, + vq->qchase.qclass); + log_assert(nm && nm_len) + /* sanity check: no DLV lookups below the DLV anchor itself. + * Like, an securely insecure delegation there makes no sense. */ + if(dname_subdomain_c(nm, qstate->env->anchors->dlv_anchor->name)) { + verbose(VERB_ALGO, "DLV lookup within DLV repository denied"); + return 1; + } + /* concat name (minus root label) + dlv name */ + vq->dlv_lookup_name_len = nm_len - 1 + + qstate->env->anchors->dlv_anchor->namelen; + vq->dlv_lookup_name = regional_alloc(qstate->region, + vq->dlv_lookup_name_len); + if(!vq->dlv_lookup_name) { + log_err("Out of memory preparing DLV lookup"); + return val_error(qstate, id); + } + memmove(vq->dlv_lookup_name, nm, nm_len-1); + memmove(vq->dlv_lookup_name+nm_len-1, + qstate->env->anchors->dlv_anchor->name, + qstate->env->anchors->dlv_anchor->namelen); + log_nametypeclass(VERB_ALGO, "DLV name", vq->dlv_lookup_name, + LDNS_RR_TYPE_DLV, vq->qchase.qclass); + + /* determine where the insecure point was determined, the DLV must + * be equal or below that to continue building the trust chain + * down. May be NULL if no trust chain was built yet */ + nm = NULL; + if(vq->key_entry && key_entry_isnull(vq->key_entry)) { + nm = vq->key_entry->name; + nm_len = vq->key_entry->namelen; + } + if(nm) { + vq->dlv_insecure_at_len = nm_len - 1 + + qstate->env->anchors->dlv_anchor->namelen; + vq->dlv_insecure_at = regional_alloc(qstate->region, + vq->dlv_insecure_at_len); + if(!vq->dlv_insecure_at) { + log_err("Out of memory preparing DLV lookup"); + return val_error(qstate, id); + } + memmove(vq->dlv_insecure_at, nm, nm_len-1); + memmove(vq->dlv_insecure_at+nm_len-1, + qstate->env->anchors->dlv_anchor->name, + qstate->env->anchors->dlv_anchor->namelen); + log_nametypeclass(VERB_ALGO, "insecure_at", + vq->dlv_insecure_at, 0, vq->qchase.qclass); + } + + /* If we can find the name in the aggressive negative cache, + * give up; insecure is the answer */ + /* lookup, several places in the tree may qualify + * between insecure_at and the lookup_name + * Check proof thoroughly + * TODO + * return 1; + */ + + /* perform a lookup for the DLV; with validation */ + vq->state = VAL_DLVLOOKUP_STATE; + 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); + } + + /* Find the closest encloser DLV from the repository. + * then that is used to build another chain of trust + * This may first require a query 'too low' that has NSECs in + * the answer, from which we determine the closest encloser DLV. + * When determine the closest encloser, skip empty nonterminals, + * since we want a nonempty node in the DLV repository. */ + + return 0; +} + /** * The Finished state. The validation status (good or bad) has been determined. * @@ -1490,6 +1616,18 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, qstate->query_flags, &qstate->qinfo, &vq->qchase, vq->orig_msg->rep, vq->rrset_skip); + /* if the result is insecure or indeterminate and we have not + * checked the DLV yet, check the DLV */ + verbose(VERB_ALGO, "check for DLV"); + verbose(VERB_ALGO, "sec %s", sec_status_to_string(vq->chase_reply->security)); + if((vq->chase_reply->security == sec_status_insecure || + vq->chase_reply->security == sec_status_indeterminate) && + qstate->env->anchors->dlv_anchor && !vq->dlv_checked) { + vq->dlv_checked = 1; + if(!val_dlv_init(qstate, vq, ve, id)) + return 0; + } + /* store overall validation result in orig_msg */ if(vq->rrset_skip == 0) vq->orig_msg->rep->security = vq->chase_reply->security; @@ -1511,6 +1649,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, /* and restart for this rrset */ verbose(VERB_ALGO, "validator: go to next rrset"); vq->chase_reply->security = sec_status_unchecked; + vq->dlv_checked = 0; /* can do DLV for this RR */ vq->state = VAL_INIT_STATE; return 1; } @@ -1528,6 +1667,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, log_query_info(VERB_ALGO, "validator: chased to", &vq->qchase); vq->chase_reply->security = sec_status_unchecked; + vq->dlv_checked = 0; /* can do DLV for this RR */ vq->state = VAL_INIT_STATE; return 1; } @@ -1540,8 +1680,10 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, * that are not secure (if clean-additional option is set) */ /* this may cause the msg to be marked bogus */ val_check_nonsecure(ve, vq->orig_msg->rep); - log_query_info(VERB_DETAIL, "validation success", - &qstate->qinfo); + if(vq->orig_msg->rep->security == sec_status_secure) { + log_query_info(VERB_DETAIL, "validation success", + &qstate->qinfo); + } } /* if the result is bogus - set message ttl to bogus ttl to avoid @@ -1572,6 +1714,80 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, return 0; } +/** + * The DLVLookup state. Process DLV lookups. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + /* see if this we are ready to continue normal resolution */ + /* we may need more DLV lookups */ + if(vq->dlv_status==dlv_error) + verbose(VERB_ALGO, "DLV woke up with status dlv_error"); + else if(vq->dlv_status==dlv_success) + verbose(VERB_ALGO, "DLV woke up with status dlv_success"); + else if(vq->dlv_status==dlv_ask_higher) + verbose(VERB_ALGO, "DLV woke up with status dlv_ask_higher"); + 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) { + /* chain continues with DNSKEY, continue in FINDKEY */ + vq->state = VAL_FINDKEY_STATE; + 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)) { + log_err("mem error generating DNSKEY request"); + return val_error(qstate, id); + } + return 0; + } else if(vq->dlv_status == dlv_there_is_no_dlv) { + /* continue with the insecure result we got */ + vq->state = VAL_FINISHED_STATE; + return 1; + } + log_assert(vq->dlv_status == dlv_ask_higher); + + /* ask higher, make sure we stay in DLV repo, below dlv_at */ + if(!dname_subdomain_c(vq->dlv_lookup_name, + qstate->env->anchors->dlv_anchor->name)) { + /* just like, there is no DLV */ + verbose(VERB_ALGO, "ask above dlv repo"); + vq->state = VAL_FINISHED_STATE; + return 1; + } + if(vq->dlv_insecure_at && !dname_subdomain_c(vq->dlv_lookup_name, + vq->dlv_insecure_at)) { + /* already checked a chain lower than dlv_lookup_name */ + verbose(VERB_ALGO, "ask above insecure endpoint"); + log_nametypeclass(0, "enpt", vq->dlv_insecure_at, 0, 0); + vq->state = VAL_FINISHED_STATE; + return 1; + } + + 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); + } + + return 0; +} + /** * Handle validator state. * If a method returns true, the next state is started. If false, then @@ -1602,6 +1818,9 @@ val_handle(struct module_qstate* qstate, struct val_qstate* vq, case VAL_FINISHED_STATE: cont = processFinished(qstate, vq, ve, id); break; + case VAL_DLVLOOKUP_STATE: + cont = processDLVLookup(qstate, vq, ve, id); + break; default: log_warn("validator: invalid state %d", vq->state); @@ -2047,7 +2266,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, /* If good, we stay in the FINDKEY state. */ log_query_info(VERB_DETAIL, "validated DNSKEY", qinfo); } - + /** * Process prime response * Sets the key entry in the state. @@ -2075,6 +2294,96 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, /* the qstate will be reactivated after inform_super is done */ } +/** + * Process DLV response. Called from inform_supers. + * Because it is in inform_supers, the mesh itself is busy doing callbacks + * for a state that is to be deleted soon; don't touch the mesh; instead + * set a state in the super, as the super will be reactivated soon. + * Perform processing to determine what state to set in the super. + * + * @param qstate: query state that is validating and asked for a DLV. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param qinfo: from the sub query state, query info. + */ +static void +process_dlv_response(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct query_info* qinfo) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + + verbose(VERB_ALGO, "process dlv response to super"); + if(rcode != LDNS_RCODE_NOERROR) { + /* lookup failed, set in vq to give up */ + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "response is error"); + return; + } + if(msg->rep->security != sec_status_secure) { + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "response is not secure"); + return; + } + /* was the lookup a success? validated DLV? */ + if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NOERROR && + msg->rep->an_numrrsets == 1 && + msg->rep->security == sec_status_secure && + ntohs(msg->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DLV && + ntohs(msg->rep->rrsets[0]->rk.rrset_class) == qinfo->qclass && + query_dname_compare(msg->rep->rrsets[0]->rk.dname, + vq->dlv_lookup_name) == 0) { + /* yay! it is just like a DS */ + vq->ds_rrset = (struct ub_packed_rrset_key*) + regional_alloc_init(qstate->region, + msg->rep->rrsets[0], sizeof(*vq->ds_rrset)); + if(!vq->ds_rrset) { + log_err("out of memory in process_dlv"); + return; + } + vq->ds_rrset->entry.key = vq->ds_rrset; + vq->ds_rrset->rk.dname = (uint8_t*)regional_alloc_init( + qstate->region, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len); + if(!vq->ds_rrset->rk.dname) { + log_err("out of memory in process_dlv"); + vq->dlv_status = dlv_error; + return; + } + vq->ds_rrset->entry.data = regional_alloc_init(qstate->region, + vq->ds_rrset->entry.data, + packed_rrset_sizeof(vq->ds_rrset->entry.data)); + if(!vq->ds_rrset->entry.data) { + log_err("out of memory in process_dlv"); + vq->dlv_status = dlv_error; + return; + } + packed_rrset_ptr_fixup(vq->ds_rrset->entry.data); + /* make vq do a DNSKEY query next up */ + vq->dlv_status = dlv_success; + return; + } + + /* was the lookup a failure? + * if we have to go up into the DLV for a higher DLV anchor + * then set this in the vq, so it can make queries when activated. + * See if the NSECs indicate that we should look for higher DLV + * or, that there is no DLV securely */ + if(!val_nsec_check_dlv(qinfo, msg->rep, &vq->dlv_lookup_name, + &vq->dlv_lookup_name_len)) { + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "nsec error"); + return; + } + if(!dname_subdomain_c(vq->dlv_lookup_name, + qstate->env->anchors->dlv_anchor->name)) { + vq->dlv_status = dlv_there_is_no_dlv; + return; + } + vq->dlv_status = dlv_ask_higher; +} + /* * inform validator super. * @@ -2108,6 +2417,10 @@ val_inform_super(struct module_qstate* qstate, int id, process_dnskey_response(super, vq, id, qstate->return_rcode, qstate->return_msg, &qstate->qinfo); return; + } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DLV) { + process_dlv_response(super, vq, id, qstate->return_rcode, + qstate->return_msg, &qstate->qinfo); + return; } log_err("internal error in validator: no inform_supers possible"); } @@ -2155,6 +2468,7 @@ val_state_to_string(enum val_state state) case VAL_FINDKEY_STATE: return "VAL_FINDKEY_STATE"; case VAL_VALIDATE_STATE: return "VAL_VALIDATE_STATE"; case VAL_FINISHED_STATE: return "VAL_FINISHED_STATE"; + case VAL_DLVLOOKUP_STATE: return "VAL_DLVLOOKUP_STATE"; } return "UNKNOWN VALIDATOR STATE"; } diff --git a/validator/validator.h b/validator/validator.h index 8369aa76a..daf65c34f 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -116,7 +116,9 @@ enum val_state { /** validate the answer, using found key entry */ VAL_VALIDATE_STATE, /** finish up */ - VAL_FINISHED_STATE + VAL_FINISHED_STATE, + /** DLV lookup state, processing DLV queries */ + VAL_DLVLOOKUP_STATE }; /** @@ -184,6 +186,27 @@ struct val_qstate { /** true if this state is waiting to prime a trust anchor */ int wait_prime_ta; + + /** have we already checked the DLV? */ + int dlv_checked; + /** The name for which the DLV is looked up. For the current message + * or for the current RRset (for CNAME, REFERRAL types). + * If there is signer name, that may be it, else a domain name */ + uint8_t* dlv_lookup_name; + /** length of dlv lookup name */ + size_t dlv_lookup_name_len; + /** Name at which chain of trust stopped with insecure, starting DLV + * DLV must result in chain going further down */ + uint8_t* dlv_insecure_at; + /** length of dlv insecure point name */ + size_t dlv_insecure_at_len; + /** status of DLV lookup. Indication to VAL_DLV_STATE what to do */ + enum dlv_status { + dlv_error, /* server failure */ + dlv_success, /* got a DLV */ + dlv_ask_higher, /* ask again */ + dlv_there_is_no_dlv /* got no DLV, sure of it */ + } dlv_status; }; /**