summaryrefslogtreecommitdiff
path: root/iterator/iterator.c
diff options
context:
space:
mode:
Diffstat (limited to 'iterator/iterator.c')
-rw-r--r--iterator/iterator.c106
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. */