mirror of
https://github.com/systemd/systemd.git
synced 2025-08-25 13:49:55 +03:00
resolved: add transaction result for upstream failures
This new transaction result is emitted when the upstream server indicates a fatal error that we will not try to recover from. Currently, it is emitted when a validating recursive resolver reports an error validating dnssec records for a domain. The extended error message should help give context to the admin.
This commit is contained in:
@ -189,6 +189,11 @@ static int reply_query_state(DnsQuery *q) {
|
|||||||
return sd_bus_reply_method_error(req, &error);
|
return sd_bus_reply_method_error(req, &error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DNS_TRANSACTION_UPSTREAM_DNSSEC_FAILURE:
|
||||||
|
return reply_method_errorf(q, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed upstream: %s%s%s",
|
||||||
|
dns_ede_rcode_to_string(q->answer_ede_rcode),
|
||||||
|
isempty(q->answer_ede_msg) ? "" : ": ", q->answer_ede_msg);
|
||||||
|
|
||||||
case DNS_TRANSACTION_NULL:
|
case DNS_TRANSACTION_NULL:
|
||||||
case DNS_TRANSACTION_PENDING:
|
case DNS_TRANSACTION_PENDING:
|
||||||
case DNS_TRANSACTION_VALIDATING:
|
case DNS_TRANSACTION_VALIDATING:
|
||||||
|
@ -421,6 +421,8 @@ DnsQuery *dns_query_free(DnsQuery *q) {
|
|||||||
dns_answer_unref(q->reply_authoritative);
|
dns_answer_unref(q->reply_authoritative);
|
||||||
dns_answer_unref(q->reply_additional);
|
dns_answer_unref(q->reply_additional);
|
||||||
|
|
||||||
|
free(q->answer_ede_msg);
|
||||||
|
|
||||||
if (q->request_stream) {
|
if (q->request_stream) {
|
||||||
/* Detach the stream from our query, in case something else keeps a reference to it. */
|
/* Detach the stream from our query, in case something else keeps a reference to it. */
|
||||||
(void) set_remove(q->request_stream->queries, q);
|
(void) set_remove(q->request_stream->queries, q);
|
||||||
@ -896,9 +898,20 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
|
|||||||
!FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
!FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
char *answer_ede_msg = NULL;
|
||||||
|
if (t->answer_ede_msg) {
|
||||||
|
answer_ede_msg = strdup(t->answer_ede_msg);
|
||||||
|
if (!answer_ede_msg) {
|
||||||
|
log_oom();
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DNS_ANSWER_REPLACE(q->answer, dns_answer_ref(t->answer));
|
DNS_ANSWER_REPLACE(q->answer, dns_answer_ref(t->answer));
|
||||||
q->answer_rcode = t->answer_rcode;
|
q->answer_rcode = t->answer_rcode;
|
||||||
q->answer_dnssec_result = t->answer_dnssec_result;
|
q->answer_dnssec_result = t->answer_dnssec_result;
|
||||||
|
q->answer_ede_rcode = t->answer_ede_rcode;
|
||||||
|
q->answer_ede_msg = answer_ede_msg;
|
||||||
q->answer_query_flags = t->answer_query_flags | dns_transaction_source_to_query_flags(t->answer_source);
|
q->answer_query_flags = t->answer_query_flags | dns_transaction_source_to_query_flags(t->answer_source);
|
||||||
q->answer_errno = t->answer_errno;
|
q->answer_errno = t->answer_errno;
|
||||||
DNS_PACKET_REPLACE(q->answer_full_packet, dns_packet_ref(t->received));
|
DNS_PACKET_REPLACE(q->answer_full_packet, dns_packet_ref(t->received));
|
||||||
|
@ -74,6 +74,8 @@ struct DnsQuery {
|
|||||||
DnsAnswer *answer;
|
DnsAnswer *answer;
|
||||||
int answer_rcode;
|
int answer_rcode;
|
||||||
DnssecResult answer_dnssec_result;
|
DnssecResult answer_dnssec_result;
|
||||||
|
int answer_ede_rcode;
|
||||||
|
char *answer_ede_msg;
|
||||||
uint64_t answer_query_flags;
|
uint64_t answer_query_flags;
|
||||||
DnsProtocol answer_protocol;
|
DnsProtocol answer_protocol;
|
||||||
int answer_family;
|
int answer_family;
|
||||||
|
@ -162,6 +162,8 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
|
|||||||
dns_resource_key_unref(t->key);
|
dns_resource_key_unref(t->key);
|
||||||
dns_packet_unref(t->bypass);
|
dns_packet_unref(t->bypass);
|
||||||
|
|
||||||
|
free(t->answer_ede_msg);
|
||||||
|
|
||||||
return mfree(t);
|
return mfree(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,6 +282,7 @@ int dns_transaction_new(
|
|||||||
.dns_udp_fd = -EBADF,
|
.dns_udp_fd = -EBADF,
|
||||||
.answer_source = _DNS_TRANSACTION_SOURCE_INVALID,
|
.answer_source = _DNS_TRANSACTION_SOURCE_INVALID,
|
||||||
.answer_dnssec_result = _DNSSEC_RESULT_INVALID,
|
.answer_dnssec_result = _DNSSEC_RESULT_INVALID,
|
||||||
|
.answer_ede_rcode = _DNS_EDE_RCODE_INVALID,
|
||||||
.answer_nsec_ttl = UINT32_MAX,
|
.answer_nsec_ttl = UINT32_MAX,
|
||||||
.key = dns_resource_key_ref(key),
|
.key = dns_resource_key_ref(key),
|
||||||
.query_flags = query_flags,
|
.query_flags = query_flags,
|
||||||
@ -404,6 +407,21 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
|
|||||||
"DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
|
"DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state == DNS_TRANSACTION_UPSTREAM_DNSSEC_FAILURE) {
|
||||||
|
dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str);
|
||||||
|
|
||||||
|
log_struct(LOG_NOTICE,
|
||||||
|
"MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR,
|
||||||
|
LOG_MESSAGE("Upstream resolver reported failure for question %s: %s%s%s",
|
||||||
|
key_str, dns_ede_rcode_to_string(t->answer_ede_rcode),
|
||||||
|
isempty(t->answer_ede_msg) ? "" : ": ", t->answer_ede_msg),
|
||||||
|
"DNS_TRANSACTION=%" PRIu16, t->id,
|
||||||
|
"DNS_QUESTION=%s", key_str,
|
||||||
|
"DNS_EDE_RCODE=%s", dns_ede_rcode_to_string(t->answer_ede_rcode),
|
||||||
|
"DNS_SERVER=%s", strna(dns_server_string_full(t->server)),
|
||||||
|
"DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level));
|
||||||
|
}
|
||||||
|
|
||||||
/* Note that this call might invalidate the query. Callers
|
/* Note that this call might invalidate the query. Callers
|
||||||
* should hence not attempt to access the query or transaction
|
* should hence not attempt to access the query or transaction
|
||||||
* after calling this function. */
|
* after calling this function. */
|
||||||
@ -1209,6 +1227,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
|||||||
ede_rcode = dns_packet_ede_rcode(p, &ede_msg);
|
ede_rcode = dns_packet_ede_rcode(p, &ede_msg);
|
||||||
if (ede_rcode < 0 && ede_rcode != -EINVAL)
|
if (ede_rcode < 0 && ede_rcode != -EINVAL)
|
||||||
log_debug_errno(ede_rcode, "Unable to extract EDE error code from packet, ignoring: %m");
|
log_debug_errno(ede_rcode, "Unable to extract EDE error code from packet, ignoring: %m");
|
||||||
|
else {
|
||||||
|
t->answer_ede_rcode = ede_rcode;
|
||||||
|
t->answer_ede_msg = TAKE_PTR(ede_msg);
|
||||||
|
}
|
||||||
|
|
||||||
if (!t->bypass &&
|
if (!t->bypass &&
|
||||||
IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
|
IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) {
|
||||||
@ -1222,8 +1244,9 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
|||||||
log_debug("Server returned error: %s (%s%s%s). Lookup failed.",
|
log_debug("Server returned error: %s (%s%s%s). Lookup failed.",
|
||||||
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
||||||
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
||||||
isempty(ede_msg) ? "" : ": ", ede_msg);
|
isempty(t->answer_ede_msg) ? "" : ": ",
|
||||||
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
|
t->answer_ede_msg);
|
||||||
|
dns_transaction_complete(t, DNS_TRANSACTION_UPSTREAM_DNSSEC_FAILURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,7 +1255,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
|||||||
log_debug("Server returned error: %s (%s%s%s), retrying transaction.",
|
log_debug("Server returned error: %s (%s%s%s), retrying transaction.",
|
||||||
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
||||||
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
||||||
isempty(ede_msg) ? "" : ": ", ede_msg);
|
isempty(t->answer_ede_msg) ? "" : ": ",
|
||||||
|
t->answer_ede_msg);
|
||||||
dns_transaction_retry(t, false);
|
dns_transaction_retry(t, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1242,7 +1266,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
|
|||||||
log_debug("Server returned error: %s (%s%s%s)",
|
log_debug("Server returned error: %s (%s%s%s)",
|
||||||
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
FORMAT_DNS_RCODE(DNS_PACKET_RCODE(p)),
|
||||||
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
FORMAT_DNS_EDE_RCODE(ede_rcode),
|
||||||
isempty(ede_msg) ? "" : ": ", ede_msg);
|
isempty(t->answer_ede_msg) ? "" : ": ", t->answer_ede_msg);
|
||||||
break;
|
break;
|
||||||
} /* No EDE rcode, or EDE rcode we don't understand */
|
} /* No EDE rcode, or EDE rcode we don't understand */
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ enum DnsTransactionState {
|
|||||||
DNS_TRANSACTION_PENDING,
|
DNS_TRANSACTION_PENDING,
|
||||||
DNS_TRANSACTION_VALIDATING,
|
DNS_TRANSACTION_VALIDATING,
|
||||||
DNS_TRANSACTION_RCODE_FAILURE,
|
DNS_TRANSACTION_RCODE_FAILURE,
|
||||||
|
DNS_TRANSACTION_UPSTREAM_DNSSEC_FAILURE,
|
||||||
DNS_TRANSACTION_SUCCESS,
|
DNS_TRANSACTION_SUCCESS,
|
||||||
DNS_TRANSACTION_NO_SERVERS,
|
DNS_TRANSACTION_NO_SERVERS,
|
||||||
DNS_TRANSACTION_TIMEOUT,
|
DNS_TRANSACTION_TIMEOUT,
|
||||||
@ -61,6 +62,8 @@ struct DnsTransaction {
|
|||||||
|
|
||||||
DnsAnswer *answer;
|
DnsAnswer *answer;
|
||||||
int answer_rcode;
|
int answer_rcode;
|
||||||
|
int answer_ede_rcode;
|
||||||
|
char *answer_ede_msg;
|
||||||
DnssecResult answer_dnssec_result;
|
DnssecResult answer_dnssec_result;
|
||||||
DnsTransactionSource answer_source;
|
DnsTransactionSource answer_source;
|
||||||
uint32_t answer_nsec_ttl;
|
uint32_t answer_nsec_ttl;
|
||||||
|
Reference in New Issue
Block a user