mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-28 21:17:54 +00:00
Fix serve-stale bug when cache has no data
We recently fixed a bug where in some cases (when following an expired CNAME for example), named could return SERVFAIL if the target record is still valid (see isc-projects/bind9#3678, and isc-projects/bind9!7096). We fixed this by considering non-stale RRsets as well during the stale lookup. However, this triggered a new bug because despite the answer from cache not being stale, the lookup may be triggered by serve-stale. If the answer from database is not stale, the fix in isc-projects/bind9!7096 erroneously skips the serve-stale logic. Add 'answer_found' checks to the serve-stale logic to fix this issue. (cherry picked from commit bbd163acf67843c76099921e467dd0ef90f3f670)
This commit is contained in:
parent
ad5d447348
commit
b90bad93cb
@ -5852,6 +5852,27 @@ query_refresh_rrset(query_ctx_t *orig_qctx) {
|
|||||||
qctx_destroy(&qctx);
|
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
|
* Perform a local database lookup, in either an authoritative or
|
||||||
* cache database. If unable to answer, call ns_query_done(); otherwise
|
* cache database. If unable to answer, call ns_query_done(); otherwise
|
||||||
@ -5983,7 +6004,6 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
{
|
{
|
||||||
/* Found non-stale usable rdataset. */
|
/* Found non-stale usable rdataset. */
|
||||||
answer_found = true;
|
answer_found = true;
|
||||||
goto gotanswer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbfind_stale || stale_refresh_window || stale_timeout) {
|
if (dbfind_stale || stale_refresh_window || stale_timeout) {
|
||||||
@ -6019,7 +6039,7 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
if (stale_found) {
|
if (stale_found) {
|
||||||
ns_client_extendederror(qctx->client, ede,
|
ns_client_extendederror(qctx->client, ede,
|
||||||
"resolver failure");
|
"resolver failure");
|
||||||
} else {
|
} else if (!answer_found) {
|
||||||
/*
|
/*
|
||||||
* Resolver failure, no stale data, nothing more we
|
* Resolver failure, no stale data, nothing more we
|
||||||
* can do, return SERVFAIL.
|
* can do, return SERVFAIL.
|
||||||
@ -6042,7 +6062,7 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
ns_client_extendederror(
|
ns_client_extendederror(
|
||||||
qctx->client, ede,
|
qctx->client, ede,
|
||||||
"query within stale refresh time window");
|
"query within stale refresh time window");
|
||||||
} else {
|
} else if (!answer_found) {
|
||||||
/*
|
/*
|
||||||
* During the stale refresh window explicitly do not try
|
* During the stale refresh window explicitly do not try
|
||||||
* to refresh the data, because a recent lookup failed.
|
* to refresh the data, because a recent lookup failed.
|
||||||
@ -6052,7 +6072,7 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
}
|
}
|
||||||
} else if (stale_timeout) {
|
} else if (stale_timeout) {
|
||||||
if ((qctx->options & DNS_GETDB_STALEFIRST) != 0) {
|
if ((qctx->options & DNS_GETDB_STALEFIRST) != 0) {
|
||||||
if (!stale_found) {
|
if (!stale_found && !answer_found) {
|
||||||
/*
|
/*
|
||||||
* We have nothing useful in cache to return
|
* We have nothing useful in cache to return
|
||||||
* immediately.
|
* immediately.
|
||||||
@ -6069,7 +6089,7 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
&qctx->client->query.fetch);
|
&qctx->client->query.fetch);
|
||||||
}
|
}
|
||||||
return (query_lookup(qctx));
|
return (query_lookup(qctx));
|
||||||
} else {
|
} else if (stale_client_answer(result)) {
|
||||||
/*
|
/*
|
||||||
* Immediately return the stale answer, start a
|
* Immediately return the stale answer, start a
|
||||||
* resolver fetch to refresh the data in cache.
|
* resolver fetch to refresh the data in cache.
|
||||||
@ -6081,9 +6101,12 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
"refresh the RRset will still be made",
|
"refresh the RRset will still be made",
|
||||||
namebuf);
|
namebuf);
|
||||||
qctx->refresh_rrset = STALE(qctx->rdataset);
|
qctx->refresh_rrset = STALE(qctx->rdataset);
|
||||||
ns_client_extendederror(
|
if (stale_found) {
|
||||||
qctx->client, ede,
|
ns_client_extendederror(
|
||||||
"stale data prioritized over lookup");
|
qctx->client, ede,
|
||||||
|
"stale data prioritized over "
|
||||||
|
"lookup");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@ -6099,7 +6122,11 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
if (stale_found) {
|
if (stale_found) {
|
||||||
ns_client_extendederror(qctx->client, ede,
|
ns_client_extendederror(qctx->client, ede,
|
||||||
"client timeout");
|
"client timeout");
|
||||||
} else {
|
} else if (!answer_found) {
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stale_client_answer(result)) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6112,7 +6139,6 @@ query_lookup(query_ctx_t *qctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gotanswer:
|
|
||||||
if (stale_timeout && (answer_found || stale_found)) {
|
if (stale_timeout && (answer_found || stale_found)) {
|
||||||
/*
|
/*
|
||||||
* Mark RRsets that we are adding to the client message on a
|
* Mark RRsets that we are adding to the client message on a
|
||||||
|
Loading…
x
Reference in New Issue
Block a user