static void
fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
- isc_time_t *finish, isc_boolean_t no_response)
+ isc_time_t *finish, isc_boolean_t no_response,
+ isc_boolean_t age_untried)
{
fetchctx_t *fctx;
resquery_t *query;
* Age RTTs of servers not tried.
*/
isc_stdtime_get(&now);
- if (finish != NULL)
+ if (finish != NULL || age_untried)
for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
if (UNMARKED(addrinfo))
dns_adb_agesrtt(fctx->adb, addrinfo, now);
- if (finish != NULL && TRIEDFIND(fctx))
+ if ((finish != NULL || age_untried) && TRIEDFIND(fctx))
for (find = ISC_LIST_HEAD(fctx->finds);
find != NULL;
find = ISC_LIST_NEXT(find, publink))
dns_adb_agesrtt(fctx->adb, addrinfo,
now);
- if (finish != NULL && TRIEDALT(fctx)) {
+ if ((finish != NULL || age_untried) && TRIEDALT(fctx)) {
for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
addrinfo != NULL;
addrinfo = ISC_LIST_NEXT(addrinfo, publink))
}
static void
-fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
+fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response,
+ isc_boolean_t age_untried)
+{
resquery_t *query, *next_query;
FCTXTRACE("cancelqueries");
query != NULL;
query = next_query) {
next_query = ISC_LIST_NEXT(query, link);
- fctx_cancelquery(&query, NULL, NULL, no_response);
+ fctx_cancelquery(&query, NULL, NULL, no_response,
+ age_untried);
}
}
}
static inline void
-fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
+fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response,
+ isc_boolean_t age_untried)
+{
FCTXTRACE("stopeverything");
- fctx_cancelqueries(fctx, no_response);
+ fctx_cancelqueries(fctx, no_response, age_untried);
fctx_cleanupfinds(fctx);
fctx_cleanupaltfinds(fctx);
fctx_cleanupforwaddrs(fctx);
fctx_done(fetchctx_t *fctx, isc_result_t result, int line) {
dns_resolver_t *res;
isc_boolean_t no_response = ISC_FALSE;
+ isc_boolean_t age_untried = ISC_FALSE;
REQUIRE(line >= 0);
*/
log_edns(fctx);
no_response = ISC_TRUE;
- }
+ } else if (result == ISC_R_TIMEDOUT)
+ age_untried = ISC_TRUE;
fctx->reason = NULL;
- fctx_stopeverything(fctx, no_response);
+ fctx_stopeverything(fctx, no_response, age_untried);
LOCK(&res->buckets[fctx->bucketnum].lock);
*/
add_bad(fctx, query->addrinfo, sevent->result,
badns_unreachable);
- fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE,
+ ISC_FALSE);
retry = ISC_TRUE;
break;
"unexpected event result; responding",
sevent->result);
- fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE,
+ ISC_FALSE);
break;
}
}
FCTXTRACE("query canceled: idle timer failed; "
"responding");
- fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE,
+ ISC_FALSE);
fctx_done(fctx, result, __LINE__);
break;
}
FCTXTRACE("query canceled: "
"resquery_send() failed; responding");
- fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE);
fctx_done(fctx, result, __LINE__);
}
break;
* No route to remote.
*/
isc_socket_detach(&query->tcpsocket);
- fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE);
retry = ISC_TRUE;
break;
sevent->result);
isc_socket_detach(&query->tcpsocket);
- fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE);
break;
}
}
if (addrinfo == NULL) {
/* We have no more addresses. Start over. */
- fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
fctx_cleanupfinds(fctx);
fctx_cleanupaltfinds(fctx);
fctx_cleanupforwaddrs(fctx);
isc_time_compare(&tevent->due, &query->start) >= 0)
{
FCTXTRACE("query timed out; no response");
- fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE);
}
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
* fetch. To avoid deadlock with the ADB, we must do this
* before we lock the bucket lock.
*/
- fctx_stopeverything(fctx, ISC_FALSE);
+ fctx_stopeverything(fctx, ISC_FALSE, ISC_FALSE);
LOCK(&res->buckets[bucketnum].lock);
*
* XXXRTH Don't cancel the query if waiting for validation?
*/
- fctx_cancelquery(&query, &devent, finish, no_response);
+ fctx_cancelquery(&query, &devent, finish, no_response, ISC_FALSE);
if (keep_trying) {
if (result == DNS_R_FORMERR)
}
fctx->ns_ttl = fctx->nameservers.ttl;
fctx->ns_ttl_ok = ISC_TRUE;
- fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
fctx_cleanupfinds(fctx);
fctx_cleanupaltfinds(fctx);
fctx_cleanupforwaddrs(fctx);
* DNSSEC validator to validate the answer.
*/
FCTXTRACE("wait for validator");
- fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
/*
* We must not retransmit while the validator is working;
* it has references to the current rmessage.
} else if (result == DNS_R_CHASEDSSERVERS) {
unsigned int n;
add_bad(fctx, addrinfo, result, broken_type);
- fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE);
fctx_cleanupfinds(fctx);
fctx_cleanupforwaddrs(fctx);