summaryrefslogtreecommitdiff
path: root/iterator
diff options
context:
space:
mode:
Diffstat (limited to 'iterator')
-rw-r--r--iterator/iter_hints.c2
-rw-r--r--iterator/iter_resptype.c6
-rw-r--r--iterator/iterator.c105
-rw-r--r--iterator/iterator.h2
4 files changed, 79 insertions, 36 deletions
diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c
index 9b1a200bbb17..a60d9a6b1cf2 100644
--- a/iterator/iter_hints.c
+++ b/iterator/iter_hints.c
@@ -100,7 +100,7 @@ ah(struct delegpt* dp, const char* sv, const char* ip)
return 0;
}
if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) ||
- !extstrtoaddr(ip, &addr, &addrlen) ||
+ !extstrtoaddr(ip, &addr, &addrlen, UNBOUND_DNS_PORT) ||
!delegpt_add_target_mlc(dp, dname, dname_len,
&addr, addrlen, 0, 0)) {
free(dname);
diff --git a/iterator/iter_resptype.c b/iterator/iter_resptype.c
index f146a2b6bfe8..c2b824a0f9b8 100644
--- a/iterator/iter_resptype.c
+++ b/iterator/iter_resptype.c
@@ -113,7 +113,11 @@ response_type_from_server(int rdset,
if(!msg || !request)
return RESPONSE_TYPE_THROWAWAY;
-
+ /* If the TC flag is set, the response is incomplete. Too large to
+ * fit even in TCP or so. Discard it, it cannot be retrieved here. */
+ if((msg->rep->flags & BIT_TC))
+ return RESPONSE_TYPE_THROWAWAY;
+
/* If the message is NXDOMAIN, then it answers the question. */
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
/* make sure its not recursive when we don't want it to */
diff --git a/iterator/iterator.c b/iterator/iterator.c
index da9b7990c506..2f3ad06fe6ea 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -255,9 +255,9 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
- dpns->resolved = 1; /* mark as failed */
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
+ dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super_iq, 1);
}
}
@@ -596,15 +596,17 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
{
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
- if((qstate->reply && qstate->reply->addrlen != 0) ||
- (iq->fail_reply && iq->fail_reply->addrlen != 0)) {
+ if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
+ (iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
char from[256], frm[512];
- if(qstate->reply && qstate->reply->addrlen != 0)
- addr_to_str(&qstate->reply->addr, qstate->reply->addrlen,
- from, sizeof(from));
+ if(qstate->reply && qstate->reply->remote_addrlen != 0)
+ addr_to_str(&qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen, from,
+ sizeof(from));
else
- addr_to_str(&iq->fail_reply->addr, iq->fail_reply->addrlen,
- from, sizeof(from));
+ addr_to_str(&iq->fail_reply->remote_addr,
+ iq->fail_reply->remote_addrlen, from,
+ sizeof(from));
snprintf(frm, sizeof(frm), "from %s", from);
errinf(qstate, frm);
}
@@ -2262,6 +2264,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
size_t qout_orig_len = 0;
int sq_check_ratelimit = 1;
int sq_was_ratelimited = 0;
+ int can_do_promisc = 0;
/* NOTE: a request will encounter this state for each target it
* needs to send a query to. That is, at least one per referral,
@@ -2589,12 +2592,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->depth < ie->max_dependency_depth
&& iq->num_target_queries == 0
&& (!iq->target_count || iq->target_count[TARGET_COUNT_NX]==0)
- && iq->sent_count < TARGET_FETCH_STOP
- /* if the mesh query list is full, then do not waste cpu
- * and sockets to fetch promiscuous targets. They can be
- * looked up when needed. */
- && !mesh_jostle_exceeded(qstate->env->mesh)
- ) {
+ && iq->sent_count < TARGET_FETCH_STOP) {
+ can_do_promisc = 1;
+ }
+ /* if the mesh query list is full, then do not waste cpu and sockets to
+ * fetch promiscuous targets. They can be looked up when needed. */
+ if(can_do_promisc && !mesh_jostle_exceeded(qstate->env->mesh)) {
tf_policy = ie->target_fetch_policy[iq->depth];
}
@@ -2766,6 +2769,37 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
+ /* We have a target. We could have created promiscuous target
+ * queries but we are currently under pressure (mesh_jostle_exceeded).
+ * If we are configured to allow promiscuous target queries and haven't
+ * gone out to the network for a target query for this delegation, then
+ * it is possible to slip in a promiscuous one with a 1/10 chance. */
+ if(can_do_promisc && tf_policy == 0 && iq->depth == 0
+ && iq->depth < ie->max_dependency_depth
+ && ie->target_fetch_policy[iq->depth] != 0
+ && iq->dp_target_count == 0
+ && !ub_random_max(qstate->env->rnd, 10)) {
+ int extra = 0;
+ verbose(VERB_ALGO, "available target exists in cache but "
+ "attempt to get extra 1 target");
+ (void)query_for_targets(qstate, iq, ie, id, 1, &extra);
+ /* errors ignored, these targets are not strictly necessary for
+ * this result, we do not have to reply with SERVFAIL */
+ if(extra > 0) {
+ iq->num_target_queries += extra;
+ target_count_increase(iq, extra);
+ check_waiting_queries(iq, qstate, id);
+ /* undo qname minimise step because we'll get back here
+ * to do it again */
+ if(qout_orig && iq->minimise_count > 0) {
+ iq->minimise_count--;
+ iq->qinfo_out.qname = qout_orig;
+ iq->qinfo_out.qname_len = qout_orig_len;
+ }
+ return 0;
+ }
+ }
+
/* Do not check ratelimit for forwarding queries or if we already got a
* pass. */
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
@@ -2873,6 +2907,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
iq->response, &iq->qinfo_out, iq->dp);
iq->chase_to_rd = 0;
+ /* remove TC flag, if this is erroneously set by TCP upstream */
+ iq->response->rep->flags &= ~BIT_TC;
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
!iq->auth_zone_response) {
/* When forwarding (RD bit is set), we handle referrals
@@ -2896,8 +2932,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* 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);
+ iq->dp, &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen);
if(a) a->dnsseclame = 1;
}
/* test the answer is from the zone we expected,
@@ -2993,9 +3029,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
- sock_list_insert(&qstate->reply_origin,
- &qstate->reply->addr, qstate->reply->addrlen,
- qstate->region);
+ sock_list_insert(&qstate->reply_origin,
+ &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen, qstate->region);
if(iq->minimisation_state != DONOT_MINIMISE_STATE
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
@@ -3250,9 +3286,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
if(qstate->reply)
- sock_list_insert(&qstate->reply_origin,
- &qstate->reply->addr, qstate->reply->addrlen,
- qstate->region);
+ sock_list_insert(&qstate->reply_origin,
+ &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen, qstate->region);
verbose(VERB_ALGO, "cleared outbound list for query restart");
/* go to INIT_REQUEST_STATE for new qname. */
return next_state(iq, INIT_REQUEST_STATE);
@@ -3266,9 +3302,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
} else if(qstate->reply) {
/* need addr for lameness cache, but we may have
* gotten this from cache, so test to be sure */
- if(!infra_set_lame(qstate->env->infra_cache,
- &qstate->reply->addr, qstate->reply->addrlen,
- iq->dp->name, iq->dp->namelen,
+ if(!infra_set_lame(qstate->env->infra_cache,
+ &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen,
+ iq->dp->name, iq->dp->namelen,
*qstate->env->now, dnsseclame, 0,
iq->qchase.qtype))
log_err("mark host lame: out of memory");
@@ -3285,8 +3322,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* gotten this from cache, so test to be sure */
verbose(VERB_DETAIL, "mark as REC_LAME");
if(!infra_set_lame(qstate->env->infra_cache,
- &qstate->reply->addr, qstate->reply->addrlen,
- iq->dp->name, iq->dp->namelen,
+ &qstate->reply->remote_addr,
+ qstate->reply->remote_addrlen,
+ iq->dp->name, iq->dp->namelen,
*qstate->env->now, 0, 1, iq->qchase.qtype))
log_err("mark host lame: out of memory");
}
@@ -3527,12 +3565,13 @@ processTargetResponse(struct module_qstate* qstate, int id,
} else {
verbose(VERB_ALGO, "iterator TargetResponse failed");
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
- dpns->resolved = 1; /* fail the target */
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
- (dpns->got6 == 2 || !ie->supports_ipv6) &&
+ (dpns->got6 == 2 || !ie->supports_ipv6)) {
+ dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
- (qstate->reply_origin && qstate->reply_origin->len != 0)) {
- target_count_increase_nx(foriq, 1);
+ if(qstate->reply_origin && qstate->reply_origin->len != 0) {
+ target_count_increase_nx(foriq, 1);
+ }
}
}
}
@@ -4014,8 +4053,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(!iq->response)
goto handle_it;
log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
- log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
- &qstate->reply->addr, qstate->reply->addrlen);
+ log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
+ &qstate->reply->remote_addr, qstate->reply->remote_addrlen);
if(verbosity >= VERB_ALGO)
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
iq->response->rep);
diff --git a/iterator/iterator.h b/iterator/iterator.h
index b71b7fe9945f..e35718cf33bd 100644
--- a/iterator/iterator.h
+++ b/iterator/iterator.h
@@ -324,7 +324,7 @@ struct iter_qstate {
/** the number of times this query has been restarted. */
int query_restart_count;
- /** the number of times this query as followed a referral. */
+ /** the number of times this query has followed a referral. */
int referral_count;
/** number of queries fired off */