2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

Fix a serve-stale issue with a delegated zone

When 'stale-answer-client-timeout' is 0, named is allowed to return
a stale answer immediately, while also initiating a new query to get
the real answer. This mode is activated in ns__query_start() by setting
the 'qctx->options.stalefirst' optoin to 'true' before calling the
query_lookup() function, but not when the zone is known to be
authoritative to the server. When the zone is authoritative, and
query_looup() finds out that the requested name is a delegation,
then before proceeding with the query, named tries to look it up
in the cache first. Here comes the issue that it doesn't consider
enabling 'qctx->options.stalefirst' in this case, and so the
'stale-answer-client-timeout 0' setting doesn't work for those
delegated zones - instead of immediately returning the stale answer
(if it exists), named tries to resolve it.

Fix this issue by enabling 'qctx->options.stalefirst' in the
query_zone_delegation() function just before named looks up the name
in the cache using a new query_lookup() call. Also, if nothing was
found in the cache, don't initiate another query_lookup() from inside
query_notfound(), and let query_notfound() do its work, i.e. it will
call query_delegation() for further processing.

(cherry picked from commit 412aa881f2ce0e9d07b9ab46d2d4863ba388b898)
This commit is contained in:
Aram Sargsyan 2025-04-10 18:15:49 +00:00 committed by Arаm Sаrgsyаn
parent 8f7f97666a
commit 7d652d9994

View File

@ -6206,11 +6206,18 @@ query_lookup(query_ctx_t *qctx) {
}
} else if (stale_timeout) {
if (qctx->options.stalefirst) {
if (!stale_found && !answer_found) {
/*
* We have nothing useful in cache to return
* immediately.
*/
/*
* If 'qctx->zdb' is set, this was a cache lookup after
* an authoritative lookup returned a delegation (in
* order to find a better answer). But we still can
* return without getting any usable answer here, as
* query_notfound() should handle it from here.
* Otherwise, if nothing useful was found in cache then
* recursively call query_lookup() again without the
* 'stalefirst' option set.
*/
if (!stale_found && !answer_found && qctx->zdb == NULL)
{
qctx_clean(qctx);
qctx_freedata(qctx);
dns_db_attach(qctx->client->view->cachedb,
@ -8936,7 +8943,25 @@ query_zone_delegation(query_ctx_t *qctx) {
dns_db_attach(qctx->view->cachedb, &qctx->db);
qctx->is_zone = false;
return query_lookup(qctx);
/*
* Since 'qctx->is_zone' is now false, we should reconsider
* setting the 'stalefirst' option, which is usually set in
* the beginning in ns__query_start().
*/
if (qctx->view->staleanswerclienttimeout == 0 &&
dns_view_staleanswerenabled(qctx->view))
{
qctx->options.stalefirst = true;
}
result = query_lookup(qctx);
/*
* After fetch completes, this option is not expected to be set.
*/
qctx->options.stalefirst = false;
return result;
}
return query_prepare_delegation_response(qctx);