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) {
qry->server_selection.truncated = true;
}
+ if (UNRECOVERABLE_ERRORS[sel_error]) {
+ addr_state->unrecoverable_errors++;
+ }
+
addr_state->errors[sel_error]++;
addr_state->error_count++;
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 {
int forward_index;
int error_count;
+ int unrecoverable_errors;
int errors[KR_SELECTION_NUMBER_OF_ERRORS];
};
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,