diff options
| author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2015-01-02 17:35:29 +0000 | 
|---|---|---|
| committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2015-01-02 17:35:29 +0000 | 
| commit | 7954be7fa5ea70de36aacebb8bcca2a70af709f4 (patch) | |
| tree | b839bbb75392ad4c301a0393b3ca49fe155c5740 /iterator | |
| parent | 7f563e614fb9a8ce7c8904a3ad346b7e38238339 (diff) | |
Diffstat (limited to 'iterator')
| -rw-r--r-- | iterator/iter_utils.c | 7 | ||||
| -rw-r--r-- | iterator/iter_utils.h | 3 | ||||
| -rw-r--r-- | iterator/iterator.c | 71 | ||||
| -rw-r--r-- | iterator/iterator.h | 6 | 
4 files changed, 73 insertions, 14 deletions
| diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 4148c1268f78..9d0aa698f996 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -425,10 +425,10 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)  void   iter_dns_store(struct module_env* env, struct query_info* msgqinf,  	struct reply_info* msgrep, int is_referral, time_t leeway, int pside, -	struct regional* region) +	struct regional* region, uint16_t flags)  {  	if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, -		pside, region)) +		pside, region, flags))  		log_err("out of memory: cannot store data in cache");  } @@ -457,7 +457,8 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,  	fptr_ok(fptr_whitelist_modenv_detect_cycle(  		qstate->env->detect_cycle));  	return (*qstate->env->detect_cycle)(qstate, &qinf,  -		(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming); +		(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming, +		qstate->is_valrec);  }  void  diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index abdc68f3cd44..d7c2b68afa2d 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -124,6 +124,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);   * @param pside: true if dp is parentside, thus message is 'fresh' and NS   * 	can be prefetch-updates.   * @param region: to copy modified (cache is better) rrs back to. + * @param flags: with BIT_CD for dns64 AAAA translated queries.   * @return void, because we are not interested in alloc errors,   * 	the iterator and validator can operate on the results in their   * 	scratch space (the qstate.region) and are not dependent on the cache. @@ -132,7 +133,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);   */  void iter_dns_store(struct module_env* env, struct query_info* qinf,  	struct reply_info* rep, int is_referral, time_t leeway, int pside, -	struct regional* region); +	struct regional* region, uint16_t flags);  /**   * Select randomly with n/m probability. diff --git a/iterator/iterator.c b/iterator/iterator.c index df5f645cc28c..6e05c99a0e95 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -120,6 +120,7 @@ iter_new(struct module_qstate* qstate, int id)  	iq->query_restart_count = 0;  	iq->referral_count = 0;  	iq->sent_count = 0; +	iq->target_count = NULL;  	iq->wait_priming_stub = 0;  	iq->refetch_glue = 0;  	iq->dnssec_expected = 0; @@ -257,7 +258,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)  		verbose(VERB_ALGO, "error response for prefetch in cache");  		/* attempt to adjust the cache entry prefetch */  		if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo, -			NORR_TTL)) +			NORR_TTL, qstate->query_flags))  			return error_response(qstate, id, rcode);  		/* if that fails (not in cache), fall through to store err */  	} @@ -270,7 +271,8 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)  	/* do not waste time trying to validate this servfail */  	err.security = sec_status_indeterminate;  	verbose(VERB_ALGO, "store error response in message cache"); -	iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL); +	iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL, +		qstate->query_flags);  	return error_response(qstate, id, rcode);  } @@ -453,6 +455,26 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,  	return 1;  } +/** create target count structure for this query */ +static void +target_count_create(struct iter_qstate* iq) +{ +	if(!iq->target_count) { +		iq->target_count = (int*)calloc(2, sizeof(int)); +		/* if calloc fails we simply do not track this number */ +		if(iq->target_count) +			iq->target_count[0] = 1; +	} +} + +static void +target_count_increase(struct iter_qstate* iq, int num) +{ +	target_count_create(iq); +	if(iq->target_count) +		iq->target_count[1] += num; +} +  /**   * Generate a subrequest.   * Generate a local request event. Local events are tied to this module, and @@ -486,6 +508,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,  	uint16_t qflags = 0; /* OPCODE QUERY, no flags */  	struct query_info qinf;  	int prime = (finalstate == PRIME_RESP_STATE)?1:0; +	int valrec = 0;  	qinf.qname = qname;  	qinf.qname_len = qnamelen;  	qinf.qtype = qtype; @@ -499,12 +522,15 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,  	 * the resolution chain, which might have a validator. We are   	 * uninterested in validating things not on the direct resolution   	 * path.  */ -	if(!v) +	if(!v) {  		qflags |= BIT_CD; +		valrec = 1; +	}  	/* attach subquery, lookup existing or make a new one */  	fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); -	if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, &subq)) { +	if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec, +		&subq)) {  		return 0;  	}  	*subq_ret = subq; @@ -524,6 +550,10 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,  		subiq = (struct iter_qstate*)subq->minfo[id];  		memset(subiq, 0, sizeof(*subiq));  		subiq->num_target_queries = 0; +		target_count_create(iq); +		subiq->target_count = iq->target_count; +		if(iq->target_count) +			iq->target_count[0] ++; /* extra reference */  		subiq->num_current_queries = 0;  		subiq->depth = iq->depth+1;  		outbound_list_init(&subiq->outlist); @@ -938,7 +968,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,  	} else {  		msg = dns_cache_lookup(qstate->env, iq->qchase.qname,   			iq->qchase.qname_len, iq->qchase.qtype,  -			iq->qchase.qclass, qstate->region, qstate->env->scratch); +			iq->qchase.qclass, qstate->query_flags, +			qstate->region, qstate->env->scratch);  		if(!msg && qstate->env->neg_cache) {  			/* lookup in negative cache; may result in   			 * NOERROR/NODATA or NXDOMAIN answers that need validation */ @@ -1350,6 +1381,12 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,  	if(iq->depth == ie->max_dependency_depth)  		return 0; +	if(iq->depth > 0 && iq->target_count && +		iq->target_count[1] > MAX_TARGET_COUNT) { +		verbose(VERB_QUERY, "request has exceeded the maximum " +			"number of glue fetches %d", iq->target_count[1]); +		return 0; +	}  	iter_mark_cycle_targets(qstate, iq->dp);  	missing = (int)delegpt_count_missing_targets(iq->dp); @@ -1532,6 +1569,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,  			return error_response(qstate, id, LDNS_RCODE_SERVFAIL);  		}  		iq->num_target_queries += qs; +		target_count_increase(iq, qs);  		if(qs != 0) {  			qstate->ext_state[id] = module_wait_subquery;  			return 0; /* and wait for them */ @@ -1541,6 +1579,12 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,  		verbose(VERB_QUERY, "maxdepth and need more nameservers, fail");  		return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);  	} +	if(iq->depth > 0 && iq->target_count && +		iq->target_count[1] > MAX_TARGET_COUNT) { +		verbose(VERB_QUERY, "request has exceeded the maximum " +			"number of glue fetches %d", iq->target_count[1]); +		return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); +	}  	/* mark cycle targets for parent-side lookups */  	iter_mark_pside_cycle_targets(qstate, iq->dp);  	/* see if we can issue queries to get nameserver addresses */ @@ -1570,6 +1614,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,  		if(query_count != 0) { /* suspend to await results */  			verbose(VERB_ALGO, "try parent-side glue lookup");  			iq->num_target_queries += query_count; +			target_count_increase(iq, query_count);  			qstate->ext_state[id] = module_wait_subquery;  			return 0;  		} @@ -1725,6 +1770,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,  			return error_response(qstate, id, LDNS_RCODE_SERVFAIL);  		}  		iq->num_target_queries += extra; +		target_count_increase(iq, extra);  		if(iq->num_target_queries > 0) {  			/* wait to get all targets, we want to try em */  			verbose(VERB_ALGO, "wait for all targets for fallback"); @@ -1765,6 +1811,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,  		/* errors ignored, these targets are not strictly necessary for  		 * this result, we do not have to reply with SERVFAIL */  		iq->num_target_queries += extra; +		target_count_increase(iq, extra);  	}  	/* Add the current set of unused targets to our queue. */ @@ -1810,6 +1857,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,  					return 1;  				}  				iq->num_target_queries += qs; +				target_count_increase(iq, qs);  			}  			/* Since a target query might have been made, we   			 * need to check again. */ @@ -1991,7 +2039,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,  		iter_dns_store(qstate->env, &iq->response->qinfo,  			iq->response->rep, 0, qstate->prefetch_leeway,  			iq->dp&&iq->dp->has_parent_side_NS, -			qstate->region); +			qstate->region, qstate->query_flags);  		/* close down outstanding requests to be discarded */  		outbound_list_clear(&iq->outlist);  		iq->num_current_queries = 0; @@ -2029,7 +2077,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,  			/* Store the referral under the current query */  			/* no prefetch-leeway, since its not the answer */  			iter_dns_store(qstate->env, &iq->response->qinfo, -				iq->response->rep, 1, 0, 0, NULL); +				iq->response->rep, 1, 0, 0, NULL, 0);  			if(iq->store_parent_NS)  				iter_store_parentside_NS(qstate->env,   					iq->response->rep); @@ -2128,7 +2176,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,  		/* prefetchleeway applied because this updates answer parts */  		iter_dns_store(qstate->env, &iq->response->qinfo,  			iq->response->rep, 1, qstate->prefetch_leeway, -			iq->dp&&iq->dp->has_parent_side_NS, NULL); +			iq->dp&&iq->dp->has_parent_side_NS, NULL, +			qstate->query_flags);  		/* set the current request's qname to the new value. */  		iq->qchase.qname = sname;  		iq->qchase.qname_len = snamelen; @@ -2209,7 +2258,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,  }  /** - * Return priming query results to interestes super querystates. + * Return priming query results to interested super querystates.   *    * Sets the delegation point and delegation message (not nonRD queries).   * This is a callback from walk_supers. @@ -2640,7 +2689,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,  			iter_dns_store(qstate->env, &qstate->qinfo,   				iq->response->rep, 0, qstate->prefetch_leeway,  				iq->dp&&iq->dp->has_parent_side_NS, -				qstate->region); +				qstate->region, qstate->query_flags);  		}  	}  	qstate->return_rcode = LDNS_RCODE_NOERROR; @@ -2921,6 +2970,8 @@ iter_clear(struct module_qstate* qstate, int id)  	iq = (struct iter_qstate*)qstate->minfo[id];  	if(iq) {  		outbound_list_clear(&iq->outlist); +		if(iq->target_count && --iq->target_count[0] == 0) +			free(iq->target_count);  		iq->num_current_queries = 0;  	}  	qstate->minfo[id] = NULL; diff --git a/iterator/iterator.h b/iterator/iterator.h index 0b91760d4a49..1364b86d722b 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -52,6 +52,8 @@ struct iter_donotq;  struct iter_prep_list;  struct iter_priv; +/** max number of targets spawned for a query and its subqueries */ +#define MAX_TARGET_COUNT	32  /** max number of query restarts. Determines max number of CNAME chain. */  #define MAX_RESTART_COUNT       8  /** max number of referrals. Makes sure resolver does not run away */ @@ -251,6 +253,10 @@ struct iter_qstate {  	/** number of queries fired off */  	int sent_count; +	 +	/** number of target queries spawned in [1], for this query and its +	 * subqueries, the malloced-array is shared, [0] refcount. */ +	int* target_count;  	/**  	 * The query must store NS records from referrals as parentside RRs | 
