From: Štěpán Balážik Date: Fri, 9 Oct 2020 14:54:01 +0000 (+0200) Subject: selection: support serve_stale module X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a59ab5cef466de90fcfdf1bc5c577f389b95faea;p=thirdparty%2Fknot-resolver.git selection: support serve_stale module --- diff --git a/lib/resolve.c b/lib/resolve.c index 2239735ea..5dfeb88ae 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -1323,8 +1323,14 @@ int kr_resolve_produce(struct kr_request *request, struct kr_transport **transpo qry->server_selection.choose_transport(qry, transport); if (*transport == NULL) { - // There is no point in continuing. - return KR_STATE_FAIL; + /* Properly signal to serve_stale module. */ + if (qry->flags.NO_NS_FOUND) { + ITERATE_LAYERS(request, qry, reset); + kr_rplan_pop(rplan, qry); + } else { + qry->flags.NO_NS_FOUND = true; + } + return KR_STATE_PRODUCE; } if ((*transport)->protocol == KR_TRANSPORT_NOADDR) { diff --git a/lib/selection.c b/lib/selection.c index 52f39c186..60696454c 100644 --- a/lib/selection.c +++ b/lib/selection.c @@ -359,6 +359,10 @@ void error(struct kr_query *qry, struct address_state *addr_state, const struct qry->server_selection.truncated = true; } + if (UNRECOVERABLE_ERRORS[sel_error]) { + addr_state->unrecoverable_errors++; + } + addr_state->errors[sel_error]++; addr_state->error_count++; diff --git a/lib/selection.h b/lib/selection.h index 743e0c532..a102ca085 100644 --- a/lib/selection.h +++ b/lib/selection.h @@ -34,7 +34,22 @@ enum kr_selection_error { KR_SELECTION_DNSSEC_ERROR, KR_SELECTION_LAME_DELEGATION, - KR_SELECTION_NUMBER_OF_ERRORS /**< Leave this last, as it is use as array size. */ + KR_SELECTION_NUMBER_OF_ERRORS /**< Leave this last, as it is used as array size. */ +}; + +static const bool UNRECOVERABLE_ERRORS[] = { + [KR_SELECTION_TIMEOUT] = false, + [KR_SELECTION_TLS_HANDSHAKE_FAILED] = false, + [KR_SELECTION_TCP_CONNECT_FAILED] = false, + [KR_SELECTION_TCP_CONNECT_TIMEOUT] = false, + [KR_SELECTION_REFUSED] = true, + [KR_SELECTION_SERVFAIL] = true, + [KR_SELECTION_FORMERROR] = true, + [KR_SELECTION_NOTIMPL] = true, + [KR_SELECTION_OTHER_RCODE] = true, + [KR_SELECTION_TRUNCATED] = false, + [KR_SELECTION_DNSSEC_ERROR] = true, + [KR_SELECTION_LAME_DELEGATION] = true, }; enum kr_transport_protocol { @@ -128,6 +143,7 @@ struct address_state { int forward_index; int error_count; + int unrecoverable_errors; int errors[KR_SELECTION_NUMBER_OF_ERRORS]; }; diff --git a/lib/selection_iter.c b/lib/selection_iter.c index 9ec0f8e7d..09bbfc185 100644 --- a/lib/selection_iter.c +++ b/lib/selection_iter.c @@ -163,7 +163,7 @@ void iter_choose_transport(struct kr_query *qry, struct kr_transport **transport size_t address_len; uint8_t* address = (uint8_t *)trie_it_key(it, &address_len); struct address_state *address_state = (struct address_state *)*trie_it_val(it); - if (address_state->generation == local_state->generation) { + if (address_state->generation == local_state->generation && !address_state->unrecoverable_errors) { choices[valid_addresses] = (struct choice){ .address = address, .address_len = address_len,