diff options
Diffstat (limited to 'iterator/iterator.c')
-rw-r--r-- | iterator/iterator.c | 106 |
1 files changed, 76 insertions, 30 deletions
diff --git a/iterator/iterator.c b/iterator/iterator.c index 43b3d30c330bf..205ab0d154072 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -288,6 +288,22 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode) return error_response(qstate, id, rcode); /* if that fails (not in cache), fall through to store err */ } + if(qstate->env->cfg->serve_expired) { + /* if serving expired contents, and such content is + * already available, don't overwrite this servfail */ + struct msgreply_entry* msg; + if((msg=msg_cache_lookup(qstate->env, + qstate->qinfo.qname, qstate->qinfo.qname_len, + qstate->qinfo.qtype, qstate->qinfo.qclass, + qstate->query_flags, 0, 0)) + != NULL) { + lock_rw_unlock(&msg->entry.lock); + return error_response(qstate, id, rcode); + } + /* serving expired contents, but nothing is cached + * at all, so the servfail cache entry is useful + * (stops waste of time on this servfail NORR_TTL) */ + } memset(&err, 0, sizeof(err)); err.flags = (uint16_t)(BIT_QR | BIT_RA); FLAGS_SET_RCODE(err.flags, rcode); @@ -509,6 +525,33 @@ handle_cname_response(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, uint8_t* nm, size_t nmlen, + uint16_t qclass) +{ + struct delegpt* fwddp; + struct iter_hints_stub* stub; + int labs = dname_count_labels(nm); + /* 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(nm) && (stub = (struct iter_hints_stub*) + name_tree_find(&env->hints->tree, nm, nmlen, labs, 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) { + return 0; + } + if((fwddp = forwards_find(env->fwds, nm, qclass)) && + /* has_parent_side is turned off for forward_first, where + * we are allowed to go to the parent */ + fwddp->has_parent_side_NS) { + return 0; + } + return 1; +} + /** see if target name is caps-for-id whitelisted */ static int is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq) @@ -853,6 +896,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) if(iq->depth == ie->max_dependency_depth) return; + if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, + iq->qchase.qclass)) + return; /* is this query the same as the nscheck? */ if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS && query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 && @@ -1025,6 +1071,20 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, return next_state(iq, COLLECT_CLASS_STATE); } + /* + * If we are restricted by a forward-zone or a stub-zone, we + * can't re-fetch glue for this delegation point. + * we won’t try to re-fetch glue if the iq->dp is null. + */ + if (iq->refetch_glue && + iq->dp && + !can_have_last_resort(qstate->env, + iq->dp->name, + iq->dp->namelen, + iq->qchase.qclass)) { + iq->refetch_glue = 0; + } + /* Resolver Algorithm Step 1 -- Look for the answer in local data. */ /* This either results in a query restart (CNAME cache response), a @@ -1558,35 +1618,6 @@ 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 @@ -1608,9 +1639,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)) { + if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, + iq->qchase.qclass)) { /* fail -- no more targets, no more hope of targets, no hope * of a response. */ + verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL"); return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); } if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) { @@ -1695,6 +1728,19 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, /* see if we can issue queries to get nameserver addresses */ /* this lookup is not randomized, but sequential. */ for(ns = iq->dp->nslist; ns; ns = ns->next) { + /* if this nameserver is at a delegation point, but that + * delegation point is a stub and we cannot go higher, skip*/ + if( ((ie->supports_ipv6 && !ns->done_pside6) || + (ie->supports_ipv4 && !ns->done_pside4)) && + !can_have_last_resort(qstate->env, ns->name, ns->namelen, + iq->qchase.qclass)) { + log_nametypeclass(VERB_ALGO, "cannot pside lookup ns " + "because it is also a stub/forward,", + ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); + if(ie->supports_ipv6) ns->done_pside6 = 1; + if(ie->supports_ipv4) ns->done_pside4 = 1; + continue; + } /* query for parent-side A and AAAA for nameservers */ if(ie->supports_ipv6 && !ns->done_pside6) { /* Send the AAAA request. */ |