mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 07:35:26 +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 412aa881f2
)
This commit is contained in:
committed by
Arаm Sаrgsyаn
parent
8f7f97666a
commit
7d652d9994
@@ -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);
|
||||
|
Reference in New Issue
Block a user