/* TODO: uncomment these once we actually use the information it collects. */
/**
* Check if there is a existing TCP connection to this address.
- *
+ *
* @p req has to have the selection_context properly initiazed.
*/
void check_tcp_connections(struct address_state *address_state, struct kr_request *req, struct sockaddr *address) {
qry->flags.NO_MINIMIZE = true;
}
break;
+ case KR_SELECTION_TCP_CONNECT_FAILED:
+ case KR_SELECTION_TCP_CONNECT_TIMEOUT:
+ qry->server_selection.local_state->force_udp = true;
+ qry->flags.NO_0X20 = false;
+ break;
case KR_SELECTION_NOTIMPL:
case KR_SELECTION_OTHER_RCODE:
case KR_SELECTION_DNSSEC_ERROR:
addr_state->broken = true;
break;
case KR_SELECTION_TLS_HANDSHAKE_FAILED:
- case KR_SELECTION_TCP_CONNECT_FAILED:
- case KR_SELECTION_TCP_CONNECT_TIMEOUT:
/* These might get resolved by retrying. */
break;
default:
addr_state->error_count++;
addr_state->errors[sel_error]++;
-
+
WITH_VERBOSE(qry)
{
KR_DNAME_GET_STR(ns_name, transport->ns_name);
/** Force resolution of a new NS name (if possible)
* Done by selection.c:error in some cases. */
bool force_resolve;
+ /** Used to work around auths with broken TCP. */
+ bool force_udp;
void *private; /**< Inner state of the implementation.*/
};
name_state->a_state = RECORD_UNKNOWN;
name_state->aaaa_state = RECORD_UNKNOWN;
}
-
+
/* Iterate over all addresses of this NS (if any). */
for (uint8_t *obj = pack_head(*addresses); obj != pack_tail(*addresses);
obj = pack_obj_next(obj)) {
assert(0);
break;
}
+
+ if (*transport &&
+ (*transport)->protocol==KR_TRANSPORT_TCP &&
+ !qry->server_selection.local_state->truncated &&
+ qry->server_selection.local_state->force_udp) {
+ // Last chance on broken TCP.
+ (*transport)->protocol = KR_TRANSPORT_UDP;
+ }
}
if (*transport == NULL && local_state->last_error == KR_SELECTION_DNSSEC_ERROR) {