/* Do not finish with bogus answer. */
if (qry->flags.DNSSEC_BOGUS) {
- return KR_STATE_FAIL;
+ if (qry->flags.FORWARD || qry->flags.STUB) {
+ return KR_STATE_FAIL;
+ }
+ /* Other servers might not have broken DNSSEC. */
+ qry->flags.DNSSEC_BOGUS = false;
+ return KR_STATE_PRODUCE;
}
return kr_rplan_empty(&request->rplan) ? KR_STATE_DONE : KR_STATE_PRODUCE;
* See `kr_server_selection::error` for more details.
*/
enum kr_selection_error {
+ KR_SELECTION_OK = 0,
+
// Network errors
KR_SELECTION_TIMEOUT,
KR_SELECTION_TLS_HANDSHAKE_FAILED,
trie_t *names;
trie_t *addresses;
unsigned int generation; // Used to distinguish old and valid records in tries
+ enum kr_selection_error last_error;
};
enum record_state {
*transport = choose_transport(choices, valid_addresses, unresolved_types, num_to_resolve, qry->server_selection.timeouts, mempool, tcp, NULL);
} else {
*transport = NULL;
+ if (local_state->last_error == KR_SELECTION_DNSSEC_ERROR) {
+ qry->flags.DNSSEC_BOGUS = true;
+ }
}
update_name_state(*transport, local_state->names);
}
struct iter_local_state *local_state = qry->server_selection.local_state;
struct address_state *addr_state = get_address_state(local_state, transport);
+ local_state->last_error = sel_error;
error(qry, addr_state, transport, sel_error);
}