qctx_destroy(&qctx);
}
+/*%
+ * Depending on the db lookup result, we can respond to the
+ * client this stale answer.
+ */
+static bool
+stale_client_answer(isc_result_t result) {
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_EMPTYNAME:
+ case DNS_R_NXRRSET:
+ case DNS_R_NCACHENXRRSET:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ return (true);
+ default:
+ return (false);
+ }
+
+ UNREACHABLE();
+}
+
/*%
* Perform a local database lookup, in either an authoritative or
* cache database. If unable to answer, call ns_query_done(); otherwise
{
/* Found non-stale usable rdataset. */
answer_found = true;
- goto gotanswer;
}
if (dbfind_stale || stale_refresh_window || stale_timeout) {
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
"%s resolver failure, stale answer %s", namebuf,
stale_found ? "used" : "unavailable");
- if (!stale_found) {
+ if (!stale_found && !answer_found) {
/*
* Resolver failure, no stale data, nothing more we
* can do, return SERVFAIL.
"answer %s",
namebuf, stale_found ? "used" : "unavailable");
- if (!stale_found) {
+ if (!stale_found && !answer_found) {
/*
* During the stale refresh window explicitly do not try
* to refresh the data, because a recent lookup failed.
}
} else if (stale_timeout) {
if ((qctx->options & DNS_GETDB_STALEFIRST) != 0) {
- if (!stale_found) {
+ if (!stale_found && !answer_found) {
/*
* We have nothing useful in cache to return
* immediately.
&qctx->client->query.fetch);
}
return (query_lookup(qctx));
- } else {
+ } else if (stale_client_answer(result)) {
/*
* Immediately return the stale answer, start a
* resolver fetch to refresh the data in cache.
"%s client timeout, stale answer %s",
namebuf,
stale_found ? "used" : "unavailable");
- if (!stale_found) {
+ if (!stale_found && !answer_found) {
+ return (result);
+ }
+
+ if (!stale_client_answer(result)) {
return (result);
}
}
}
-gotanswer:
if (stale_timeout && (answer_found || stale_found)) {
/*
* Mark RRsets that we are adding to the client message on a