diff options
Diffstat (limited to 'iterator/iterator.c')
-rw-r--r-- | iterator/iterator.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/iterator/iterator.c b/iterator/iterator.c index e3f058fe51229..1604893317038 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1409,6 +1409,35 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, return 1; } +/** see if last resort is possible - does config allow queries to parent */ +static int +can_have_last_resort(struct module_env* env, struct delegpt* dp, + struct iter_qstate* iq) +{ + struct delegpt* fwddp; + struct iter_hints_stub* stub; + /* do not process a last resort (the parent side) if a stub + * or forward is configured, because we do not want to go 'above' + * the configured servers */ + if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*) + name_tree_find(&env->hints->tree, dp->name, dp->namelen, + dp->namelabs, iq->qchase.qclass)) && + /* has_parent side is turned off for stub_first, where we + * are allowed to go to the parent */ + stub->dp->has_parent_side_NS) { + verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL"); + return 0; + } + if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) && + /* has_parent_side is turned off for forward_first, where + * we are allowed to go to the parent */ + fwddp->has_parent_side_NS) { + verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL"); + return 0; + } + return 1; +} + /** * Called by processQueryTargets when it would like extra targets to query * but it seems to be out of options. At last resort some less appealing @@ -1430,6 +1459,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_ALGO, "No more query targets, attempting last resort"); log_assert(iq->dp); + if(!can_have_last_resort(qstate->env, iq->dp, iq)) { + /* fail -- no more targets, no more hope of targets, no hope + * of a response. */ + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) { struct delegpt* p = hints_lookup_root(qstate->env->hints, iq->qchase.qclass); @@ -1439,7 +1473,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, iq->chase_flags &= ~BIT_RD; /* go to authorities */ for(ns = p->nslist; ns; ns=ns->next) { (void)delegpt_add_ns(iq->dp, qstate->region, - ns->name, (int)ns->lame); + ns->name, ns->lame); } for(a = p->target_list; a; a=a->next_target) { (void)delegpt_add_addr(iq->dp, qstate->region, @@ -1880,12 +1914,23 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, && type != RESPONSE_TYPE_UNTYPED) { /* a possible answer, see if it is missing DNSSEC */ /* but not when forwarding, so we dont mark fwder lame */ - /* also make sure the answer is from the zone we expected, - * otherwise, (due to parent,child on same server), we - * might mark the server,zone lame inappropriately */ - if(!iter_msg_has_dnssec(iq->response) && - iter_msg_from_zone(iq->response, iq->dp, type, - iq->qchase.qclass)) { + if(!iter_msg_has_dnssec(iq->response)) { + /* Mark this address as dnsseclame in this dp, + * because that will make serverselection disprefer + * it, but also, once it is the only final option, + * use dnssec-lame-bypass if it needs to query there.*/ + if(qstate->reply) { + struct delegpt_addr* a = delegpt_find_addr( + iq->dp, &qstate->reply->addr, + qstate->reply->addrlen); + if(a) a->dnsseclame = 1; + } + /* test the answer is from the zone we expected, + * otherwise, (due to parent,child on same server), we + * might mark the server,zone lame inappropriately */ + if(!iter_msg_from_zone(iq->response, iq->dp, type, + iq->qchase.qclass)) + qstate->reply = NULL; type = RESPONSE_TYPE_LAME; dnsseclame = 1; } @@ -2117,8 +2162,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, *qstate->env->now, dnsseclame, 0, iq->qchase.qtype)) log_err("mark host lame: out of memory"); - } else log_err("%slame response from cache", - dnsseclame?"DNSSEC ":""); + } } else if(type == RESPONSE_TYPE_REC_LAME) { /* Cache the LAMEness. */ verbose(VERB_DETAIL, "query response REC_LAME: " @@ -2326,12 +2370,12 @@ processTargetResponse(struct module_qstate* qstate, int id, rrset->rk.dname_len)) { /* if dpns->lame then set newcname ns lame too */ if(!delegpt_add_ns(foriq->dp, forq->region, - rrset->rk.dname, (int)dpns->lame)) + rrset->rk.dname, dpns->lame)) log_err("out of memory adding cnamed-ns"); } /* if dpns->lame then set the address(es) lame too */ if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, - (int)dpns->lame)) + dpns->lame)) log_err("out of memory adding targets"); verbose(VERB_ALGO, "added target response"); delegpt_log(VERB_ALGO, foriq->dp); |