diff options
Diffstat (limited to 'iterator')
-rw-r--r-- | iterator/iter_delegpt.h | 2 | ||||
-rw-r--r-- | iterator/iter_hints.c | 2 | ||||
-rw-r--r-- | iterator/iter_scrub.c | 18 | ||||
-rw-r--r-- | iterator/iter_utils.c | 5 | ||||
-rw-r--r-- | iterator/iter_utils.h | 2 | ||||
-rw-r--r-- | iterator/iterator.c | 405 | ||||
-rw-r--r-- | iterator/iterator.h | 5 |
7 files changed, 329 insertions, 110 deletions
diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h index 4bd79c81af09f..24f0574901d9e 100644 --- a/iterator/iter_delegpt.h +++ b/iterator/iter_delegpt.h @@ -83,6 +83,8 @@ struct delegpt { uint8_t dp_type_mlc; /** use SSL for upstream query */ uint8_t ssl_upstream; + /** delegpt from authoritative zone that is locally hosted */ + uint8_t auth_dp; }; /** diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c index 47af96687fe6f..1d4c228fabc21 100644 --- a/iterator/iter_hints.c +++ b/iterator/iter_hints.c @@ -129,7 +129,7 @@ compile_time_root_prime(int do_ip4, int do_ip6) dp->has_parent_side_NS = 1; if(do_ip4) { if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed; - if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed; + if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed; if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed; if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed; if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed; diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c index 1bee85c0b991d..12580dcdb5395 100644 --- a/iterator/iter_scrub.c +++ b/iterator/iter_scrub.c @@ -503,6 +503,24 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, continue; } } + /* if this is type DS and we query for type DS we just got + * a referral answer for our type DS query, fix packet */ + if(rrset->type==LDNS_RR_TYPE_DS && + qinfo->qtype == LDNS_RR_TYPE_DS && + dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) { + rrset->section = LDNS_SECTION_ANSWER; + msg->ancount = rrset->rr_count + rrset->rrsig_count; + msg->nscount = 0; + msg->arcount = 0; + msg->an_rrsets = 1; + msg->ns_rrsets = 0; + msg->ar_rrsets = 0; + msg->rrset_count = 1; + msg->rrset_first = rrset; + msg->rrset_last = rrset; + rrset->rrset_all_next = NULL; + return 1; + } mark_additional_rrset(pkt, msg, rrset); prev = rrset; rrset = rrset->rrset_all_next; diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 0b1b456113f7a..70cab40faa801 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -656,6 +656,11 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, /* a trust anchor exists with this name, RRSIGs expected */ if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen, dclass))) { + if(a->numDS == 0 && a->numDNSKEY == 0) { + /* insecure trust point */ + lock_basic_unlock(&a->lock); + return 0; + } lock_basic_unlock(&a->lock); return 1; } diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index d0629a83e0df8..602fa6db3d0d5 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -193,7 +193,7 @@ int iter_indicates_dnssec_fwd(struct module_env* env, * @param dp: delegation point. * @param msg: delegation message, with DS if a secure referral. * @param dclass: class of query. - * @return 1 if dnssec is expected, 0 if not. + * @return 1 if dnssec is expected, 0 if not or insecure point above qname. */ int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, struct dns_msg* msg, uint16_t dclass); diff --git a/iterator/iterator.c b/iterator/iterator.c index 6c49709adea3d..7f3c65737d595 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -53,6 +53,7 @@ #include "validator/val_neg.h" #include "services/cache/dns.h" #include "services/cache/infra.h" +#include "services/authzone.h" #include "util/module.h" #include "util/netevent.h" #include "util/net_help.h" @@ -771,6 +772,11 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id, if(!stub) return 0; stub_dp = stub->dp; + /* if we have an auth_zone dp, and stub is equal, don't prime stub + * yet, unless we want to fallback and avoid the auth_zone */ + if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp && + query_dname_compare(iq->dp->name, stub_dp->name) == 0) + return 0; /* is it a noprime stub (always use) */ if(stub->noprime) { @@ -832,6 +838,96 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id, } /** + * Generate a delegation point for an auth zone (unless cached dp is better) + * false on alloc failure. + */ +static int +auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq, + uint8_t* delname, size_t delnamelen) +{ + struct auth_zone* z; + if(iq->auth_zone_avoid) + return 1; + if(!delname) { + delname = iq->qchase.qname; + delnamelen = iq->qchase.qname_len; + } + lock_rw_rdlock(&qstate->env->auth_zones->lock); + z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen, + qstate->qinfo.qclass); + if(!z) { + lock_rw_unlock(&qstate->env->auth_zones->lock); + return 1; + } + lock_rw_rdlock(&z->lock); + lock_rw_unlock(&qstate->env->auth_zones->lock); + if(z->for_upstream) { + if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0 + && iq->dp->auth_dp && qstate->blacklist && + z->fallback_enabled) { + /* cache is blacklisted and fallback, and we + * already have an auth_zone dp */ + if(verbosity>=VERB_ALGO) { + char buf[255+1]; + dname_str(z->name, buf); + verbose(VERB_ALGO, "auth_zone %s " + "fallback because cache blacklisted", + buf); + } + lock_rw_unlock(&z->lock); + iq->dp = NULL; + return 1; + } + if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) { + struct delegpt* dp; + if(qstate->blacklist && z->fallback_enabled) { + /* cache is blacklisted because of a DNSSEC + * validation failure, and the zone allows + * fallback to the internet, query there. */ + if(verbosity>=VERB_ALGO) { + char buf[255+1]; + dname_str(z->name, buf); + verbose(VERB_ALGO, "auth_zone %s " + "fallback because cache blacklisted", + buf); + } + lock_rw_unlock(&z->lock); + return 1; + } + dp = (struct delegpt*)regional_alloc_zero( + qstate->region, sizeof(*dp)); + if(!dp) { + log_err("alloc failure"); + if(z->fallback_enabled) { + lock_rw_unlock(&z->lock); + return 1; /* just fallback */ + } + lock_rw_unlock(&z->lock); + return 0; + } + dp->name = regional_alloc_init(qstate->region, + z->name, z->namelen); + if(!dp->name) { + log_err("alloc failure"); + if(z->fallback_enabled) { + lock_rw_unlock(&z->lock); + return 1; /* just fallback */ + } + lock_rw_unlock(&z->lock); + return 0; + } + dp->namelen = z->namelen; + dp->namelabs = z->namelabs; + dp->auth_dp = 1; + iq->dp = dp; + } + } + + lock_rw_unlock(&z->lock); + return 1; +} + +/** * Generate A and AAAA checks for glue that is in-zone for the referral * we just got to obtain authoritative information on the addresses. * @@ -914,6 +1010,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) generate_a_aaaa_check(qstate, iq, id); return; } + /* no need to get the NS record for DS, it is above the zonecut */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) + return; log_nametypeclass(VERB_ALGO, "schedule ns fetch", iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); @@ -1106,14 +1205,15 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, msg = dns_cache_lookup(qstate->env, iq->qchase.qname, iq->qchase.qname_len, iq->qchase.qtype, iq->qchase.qclass, qstate->query_flags, - qstate->region, qstate->env->scratch); + qstate->region, qstate->env->scratch, 0); if(!msg && qstate->env->neg_cache) { /* lookup in negative cache; may result in * NOERROR/NODATA or NXDOMAIN answers that need validation */ msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase, qstate->region, qstate->env->rrset_cache, qstate->env->scratch_buffer, - *qstate->env->now, 1/*add SOA*/, NULL); + *qstate->env->now, 1/*add SOA*/, NULL, + qstate->env->cfg); } /* item taken from cache does not match our query name, thus * security needs to be re-examined later */ @@ -1164,7 +1264,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, iq->response = msg; return final_state(iq); } - + /* attempt to forward the request */ if(forward_request(qstate, iq)) { @@ -1225,8 +1325,15 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, /* If the cache has returned nothing, then we have a * root priming situation. */ if(iq->dp == NULL) { + int r; + /* if under auth zone, no prime needed */ + if(!auth_zone_delegpt(qstate, iq, delname, delnamelen)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + if(iq->dp) /* use auth zone dp */ + return next_state(iq, INIT_REQUEST_2_STATE); /* if there is a stub, then no root prime needed */ - int r = prime_stub(qstate, iq, id, delname, + r = prime_stub(qstate, iq, id, delname, iq->qchase.qclass); if(r == 2) break; /* got noprime-stub-zone, continue */ @@ -1371,22 +1478,36 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq, log_query_info(VERB_QUERY, "resolving (init part 2): ", &qstate->qinfo); + delname = iq->qchase.qname; + delnamelen = iq->qchase.qname_len; if(iq->refetch_glue) { + struct iter_hints_stub* stub; if(!iq->dp) { log_err("internal or malloc fail: no dp for refetch"); return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } - delname = iq->dp->name; - delnamelen = iq->dp->namelen; - } else { - delname = iq->qchase.qname; - delnamelen = iq->qchase.qname_len; + /* Do not send queries above stub, do not set delname to dp if + * this is above stub without stub-first. */ + stub = hints_lookup_stub( + qstate->env->hints, iq->qchase.qname, iq->qchase.qclass, + iq->dp); + if(!stub || !stub->dp->has_parent_side_NS || + dname_subdomain_c(iq->dp->name, stub->dp->name)) { + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + } } if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) { if(!dname_is_root(delname)) dname_remove_label(&delname, &delnamelen); iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */ } + + /* see if we have an auth zone to answer from, improves dp from cache + * (if any dp from cache) with auth zone dp, if that is lower */ + if(!auth_zone_delegpt(qstate, iq, delname, delnamelen)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + /* Check to see if we need to prime a stub zone. */ if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) { /* A priming sub request was made */ @@ -1871,6 +1992,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, int tf_policy; struct delegpt_addr* target; struct outbound_entry* outq; + int auth_fallback = 0; /* NOTE: a request will encounter this state for each target it * needs to send a query to. That is, at least one per referral, @@ -1915,6 +2037,152 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, return 0; } + if(iq->minimisation_state == INIT_MINIMISE_STATE) { + /* (Re)set qinfo_out to (new) delegation point, except when + * qinfo_out is already a subdomain of dp. This happens when + * increasing by more than one label at once (QNAMEs with more + * than MAX_MINIMISE_COUNT labels). */ + if(!(iq->qinfo_out.qname_len + && dname_subdomain_c(iq->qchase.qname, + iq->qinfo_out.qname) + && dname_subdomain_c(iq->qinfo_out.qname, + iq->dp->name))) { + iq->qinfo_out.qname = iq->dp->name; + iq->qinfo_out.qname_len = iq->dp->namelen; + iq->qinfo_out.qtype = LDNS_RR_TYPE_A; + iq->qinfo_out.qclass = iq->qchase.qclass; + iq->qinfo_out.local_alias = NULL; + iq->minimise_count = 0; + } + + iq->minimisation_state = MINIMISE_STATE; + } + if(iq->minimisation_state == MINIMISE_STATE) { + int qchaselabs = dname_count_labels(iq->qchase.qname); + int labdiff = qchaselabs - + dname_count_labels(iq->qinfo_out.qname); + + iq->qinfo_out.qname = iq->qchase.qname; + iq->qinfo_out.qname_len = iq->qchase.qname_len; + iq->minimise_count++; + iq->minimise_timeout_count = 0; + + iter_dec_attempts(iq->dp, 1); + + /* Limit number of iterations for QNAMEs with more + * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB + * labels of QNAME always individually. + */ + if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 && + iq->minimise_count > MINIMISE_ONE_LAB) { + if(iq->minimise_count < MAX_MINIMISE_COUNT) { + int multilabs = qchaselabs - 1 - + MINIMISE_ONE_LAB; + int extralabs = multilabs / + MINIMISE_MULTIPLE_LABS; + + if (MAX_MINIMISE_COUNT - iq->minimise_count >= + multilabs % MINIMISE_MULTIPLE_LABS) + /* Default behaviour is to add 1 label + * every iteration. Therefore, decrement + * the extralabs by 1 */ + extralabs--; + if (extralabs < labdiff) + labdiff -= extralabs; + else + labdiff = 1; + } + /* Last minimised iteration, send all labels with + * QTYPE=NS */ + else + labdiff = 1; + } + + if(labdiff > 1) { + verbose(VERB_QUERY, "removing %d labels", labdiff-1); + dname_remove_labels(&iq->qinfo_out.qname, + &iq->qinfo_out.qname_len, + labdiff-1); + } + if(labdiff < 1 || (labdiff < 2 + && (iq->qchase.qtype == LDNS_RR_TYPE_DS + || iq->qchase.qtype == LDNS_RR_TYPE_A))) + /* Stop minimising this query, resolve "as usual" */ + iq->minimisation_state = DONOT_MINIMISE_STATE; + else if(!qstate->no_cache_lookup) { + struct dns_msg* msg = dns_cache_lookup(qstate->env, + iq->qinfo_out.qname, iq->qinfo_out.qname_len, + iq->qinfo_out.qtype, iq->qinfo_out.qclass, + qstate->query_flags, qstate->region, + qstate->env->scratch, 0); + if(msg && msg->rep->an_numrrsets == 0 + && FLAGS_GET_RCODE(msg->rep->flags) == + LDNS_RCODE_NOERROR) + /* no need to send query if it is already + * cached as NOERROR/NODATA */ + return 1; + } + } + if(iq->minimisation_state == SKIP_MINIMISE_STATE) { + if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT) + /* Do not increment qname, continue incrementing next + * iteration */ + iq->minimisation_state = MINIMISE_STATE; + else if(!qstate->env->cfg->qname_minimisation_strict) + /* Too many time-outs detected for this QNAME and QTYPE. + * We give up, disable QNAME minimisation. */ + iq->minimisation_state = DONOT_MINIMISE_STATE; + } + if(iq->minimisation_state == DONOT_MINIMISE_STATE) + iq->qinfo_out = iq->qchase; + + /* now find an answer to this query */ + /* see if authority zones have an answer */ + /* now we know the dp, we can check the auth zone for locally hosted + * contents */ + if(!iq->auth_zone_avoid && qstate->blacklist) { + if(auth_zones_can_fallback(qstate->env->auth_zones, + iq->dp->name, iq->dp->namelen, iq->qinfo_out.qclass)) { + /* if cache is blacklisted and this zone allows us + * to fallback to the internet, then do so, and + * fetch results from the internet servers */ + iq->auth_zone_avoid = 1; + } + } + if(iq->auth_zone_avoid) { + iq->auth_zone_avoid = 0; + auth_fallback = 1; + } else if(auth_zones_lookup(qstate->env->auth_zones, &iq->qinfo_out, + qstate->region, &iq->response, &auth_fallback, iq->dp->name, + iq->dp->namelen)) { + /* use this as a response to be processed by the iterator */ + if(verbosity >= VERB_ALGO) { + log_dns_msg("msg from auth zone", + &iq->response->qinfo, iq->response->rep); + } + iq->num_current_queries++; + iq->chase_to_rd = 0; + iq->dnssec_lame_query = 0; + iq->auth_zone_response = 1; + return next_state(iq, QUERY_RESP_STATE); + } + iq->auth_zone_response = 0; + if(auth_fallback == 0) { + /* like we got servfail from the auth zone lookup, and + * no internet fallback */ + verbose(VERB_ALGO, "auth zone lookup failed, no fallback," + " servfail"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + if(iq->dp && iq->dp->auth_dp) { + /* we wanted to fallback, but had no delegpt, only the + * auth zone generated delegpt, create an actual one */ + iq->auth_zone_avoid = 1; + return next_state(iq, INIT_REQUEST_STATE); + } + /* but mostly, fallback==1 (like, when no such auth zone exists) + * and we continue with lookups */ + tf_policy = 0; /* < not <=, because although the array is large enough for <=, the * generated query will immediately be discarded due to depth and @@ -2082,105 +2350,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, } } - if(iq->minimisation_state == INIT_MINIMISE_STATE) { - /* (Re)set qinfo_out to (new) delegation point, except when - * qinfo_out is already a subdomain of dp. This happens when - * increasing by more than one label at once (QNAMEs with more - * than MAX_MINIMISE_COUNT labels). */ - if(!(iq->qinfo_out.qname_len - && dname_subdomain_c(iq->qchase.qname, - iq->qinfo_out.qname) - && dname_subdomain_c(iq->qinfo_out.qname, - iq->dp->name))) { - iq->qinfo_out.qname = iq->dp->name; - iq->qinfo_out.qname_len = iq->dp->namelen; - iq->qinfo_out.qtype = LDNS_RR_TYPE_A; - iq->qinfo_out.qclass = iq->qchase.qclass; - iq->qinfo_out.local_alias = NULL; - iq->minimise_count = 0; - } - - iq->minimisation_state = MINIMISE_STATE; - } - if(iq->minimisation_state == MINIMISE_STATE) { - int qchaselabs = dname_count_labels(iq->qchase.qname); - int labdiff = qchaselabs - - dname_count_labels(iq->qinfo_out.qname); - - iq->qinfo_out.qname = iq->qchase.qname; - iq->qinfo_out.qname_len = iq->qchase.qname_len; - iq->minimise_count++; - iq->minimise_timeout_count = 0; - - iter_dec_attempts(iq->dp, 1); - - /* Limit number of iterations for QNAMEs with more - * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB - * labels of QNAME always individually. - */ - if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 && - iq->minimise_count > MINIMISE_ONE_LAB) { - if(iq->minimise_count < MAX_MINIMISE_COUNT) { - int multilabs = qchaselabs - 1 - - MINIMISE_ONE_LAB; - int extralabs = multilabs / - MINIMISE_MULTIPLE_LABS; - - if (MAX_MINIMISE_COUNT - iq->minimise_count >= - multilabs % MINIMISE_MULTIPLE_LABS) - /* Default behaviour is to add 1 label - * every iteration. Therefore, decrement - * the extralabs by 1 */ - extralabs--; - if (extralabs < labdiff) - labdiff -= extralabs; - else - labdiff = 1; - } - /* Last minimised iteration, send all labels with - * QTYPE=NS */ - else - labdiff = 1; - } - - if(labdiff > 1) { - verbose(VERB_QUERY, "removing %d labels", labdiff-1); - dname_remove_labels(&iq->qinfo_out.qname, - &iq->qinfo_out.qname_len, - labdiff-1); - } - if(labdiff < 1 || (labdiff < 2 - && (iq->qchase.qtype == LDNS_RR_TYPE_DS - || iq->qchase.qtype == LDNS_RR_TYPE_A))) - /* Stop minimising this query, resolve "as usual" */ - iq->minimisation_state = DONOT_MINIMISE_STATE; - else if(!qstate->no_cache_lookup) { - struct dns_msg* msg = dns_cache_lookup(qstate->env, - iq->qinfo_out.qname, iq->qinfo_out.qname_len, - iq->qinfo_out.qtype, iq->qinfo_out.qclass, - qstate->query_flags, qstate->region, - qstate->env->scratch); - if(msg && msg->rep->an_numrrsets == 0 - && FLAGS_GET_RCODE(msg->rep->flags) == - LDNS_RCODE_NOERROR) - /* no need to send query if it is already - * cached as NOERROR/NODATA */ - return 1; - } - } - if(iq->minimisation_state == SKIP_MINIMISE_STATE) { - if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT) - /* Do not increment qname, continue incrementing next - * iteration */ - iq->minimisation_state = MINIMISE_STATE; - else if(!qstate->env->cfg->qname_minimisation_strict) - /* Too many time-outs detected for this QNAME and QTYPE. - * We give up, disable QNAME minimisation. */ - iq->minimisation_state = DONOT_MINIMISE_STATE; - } - if(iq->minimisation_state == DONOT_MINIMISE_STATE) - iq->qinfo_out = iq->qchase; - /* We have a valid target. */ if(verbosity >= VERB_QUERY) { log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out); @@ -2573,6 +2742,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->deleg_msg = NULL; iq->dp = NULL; iq->dsns_point = NULL; + iq->auth_zone_response = 0; /* Note the query restart. */ iq->query_restart_count++; iq->sent_count = 0; @@ -2645,6 +2815,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, if (qstate->env->cfg->qname_minimisation && !qstate->env->cfg->qname_minimisation_strict) iq->minimisation_state = DONOT_MINIMISE_STATE; + if(iq->auth_zone_response) { + /* can we fallback? */ + iq->auth_zone_response = 0; + if(!auth_zones_can_fallback(qstate->env->auth_zones, + iq->dp->name, iq->dp->namelen, qstate->qinfo.qclass)) { + verbose(VERB_ALGO, "auth zone response bad, and no" + " fallback possible, servfail"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + verbose(VERB_ALGO, "auth zone response was bad, " + "fallback enabled"); + iq->auth_zone_avoid = 1; + if(iq->dp->auth_dp) { + /* we are using a dp for the auth zone, with no + * nameservers, get one first */ + iq->dp = NULL; + return next_state(iq, INIT_REQUEST_STATE); + } + } return next_state(iq, QUERYTARGETS_STATE); } diff --git a/iterator/iterator.h b/iterator/iterator.h index 841a3643669ca..67ffeb1476318 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -387,6 +387,11 @@ struct iter_qstate { * Count number of time-outs. Used to prevent resolving failures when * the QNAME minimisation QTYPE is blocked. */ int minimise_timeout_count; + + /** True if the current response is from auth_zone */ + int auth_zone_response; + /** True if the auth_zones should not be consulted for the query */ + int auth_zone_avoid; }; /** |