]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
selection: support serve_stale module
authorŠtěpán Balážik <stepan.balazik@nic.cz>
Fri, 9 Oct 2020 14:54:01 +0000 (16:54 +0200)
committerŠtěpán Balážik <stepan.balazik@nic.cz>
Thu, 15 Oct 2020 11:22:22 +0000 (13:22 +0200)
lib/resolve.c
lib/selection.c
lib/selection.h
lib/selection_iter.c

index 2239735ea24c5229039d69503b146290b32dfacd..5dfeb88ae773fa5c806955af7c997fbf6cfcbc97 100644 (file)
@@ -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) {
index 52f39c186b2cb809ad3cfff4731ac64071b79676..60696454c46e97c4cdf0b8520072f723b4114ab4 100644 (file)
@@ -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++;
 
index 743e0c5321bd81b1bf2a9856918215ee2a879ae0..a102ca085bc7098bd77faa680b698ebd637de0c6 100644 (file)
@@ -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];
 };
 
index 9ec0f8e7dbed315da41c452b087bc0aa1064ad73..09bbfc185a2456a1945453fd5e7b8e8afcdf8879 100644 (file)
@@ -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,