diff options
Diffstat (limited to 'iterator')
| -rw-r--r-- | iterator/iter_hints.c | 2 | ||||
| -rw-r--r-- | iterator/iterator.c | 106 | 
2 files changed, 77 insertions, 31 deletions
| diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c index 74869d355472..47af96687fe6 100644 --- a/iterator/iter_hints.c +++ b/iterator/iter_hints.c @@ -144,7 +144,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)        }        if(do_ip6) {  	if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed; -	if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed; +	if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;  	if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;  	if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;  	if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed; diff --git a/iterator/iterator.c b/iterator/iterator.c index 43b3d30c330b..205ab0d15407 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. */ | 
