"DNS_TRANSACTION=%" PRIu16, t->id,
"DNS_QUESTION=%s", key_str,
"DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result),
- "DNS_SERVER=%s", dns_server_string(t->server),
+ "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));
}
dns_transaction_gc(t);
}
+static void dns_transaction_complete_errno(DnsTransaction *t, int error) {
+ assert(t);
+ assert(error != 0);
+
+ t->answer_errno = abs(error);
+ dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+}
+
static int dns_transaction_pick_server(DnsTransaction *t) {
DnsServer *server;
t->n_picked_servers ++;
- log_debug("Using DNS server %s for transaction %u.", dns_server_string(t->server), t->id);
+ log_debug("Using DNS server %s for transaction %u.", strna(dns_server_string_full(t->server)), t->id);
return 1;
}
dns_scope_next_dns_server(t->scope);
r = dns_transaction_go(t);
- if (r < 0) {
- t->answer_errno = -r;
- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
- }
+ if (r < 0)
+ dns_transaction_complete_errno(t, r);
}
static int dns_transaction_maybe_restart(DnsTransaction *t) {
dns_transaction_retry(t, true);
return;
}
- if (error != 0) {
- t->answer_errno = error;
- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
- }
+ if (error != 0)
+ dns_transaction_complete_errno(t, error);
}
static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
return 0;
}
-static uint16_t dns_port_for_feature_level(DnsServerFeatureLevel level) {
- return DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? 853 : 53;
+static uint16_t dns_transaction_port(DnsTransaction *t) {
+ if (t->server->port > 0)
+ return t->server->port;
+ return DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53;
}
static int dns_transaction_emit_tcp(DnsTransaction *t) {
if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
s = dns_stream_ref(t->server->stream);
else
- fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_port_for_feature_level(t->current_feature_level), &sa);
+ fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_transaction_port(t), &sa);
type = DNS_STREAM_LOOKUP;
break;
static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
DnsTransaction *dt;
- Iterator i;
assert(t);
- SET_FOREACH(dt, t->dnssec_transactions, i)
+ SET_FOREACH(dt, t->dnssec_transactions)
if (DNS_TRANSACTION_IS_LIVE(dt->state))
return true;
static int dns_transaction_dnssec_ready(DnsTransaction *t) {
DnsTransaction *dt;
- Iterator i;
assert(t);
/* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still
* ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
switch (dt->state) {
return;
fail:
- t->answer_errno = -r;
- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+ dns_transaction_complete_errno(t, r);
}
static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
return;
fail:
- t->answer_errno = -r;
- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
+ dns_transaction_complete_errno(t, r);
}
static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
assert(t->scope);
r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
- if (ERRNO_IS_DISCONNECT(-r)) {
+ if (ERRNO_IS_DISCONNECT(r)) {
usec_t usec;
- /* UDP connection failure get reported via ICMP and then are possible delivered to us on the next
- * recvmsg(). Treat this like a lost packet. */
+ /* UDP connection failures get reported via ICMP and then are possibly delivered to us on the
+ * next recvmsg(). Treat this like a lost packet. */
log_debug_errno(r, "Connection failure for DNS UDP packet: %m");
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
return 0;
}
if (r < 0) {
- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
- t->answer_errno = -r;
+ dns_transaction_complete_errno(t, r);
return 0;
}
+ if (r == 0)
+ /* Spurious wakeup without any data */
+ return 0;
r = dns_packet_validate_reply(p);
if (r < 0) {
dns_transaction_close_connection(t);
- fd = dns_scope_socket_udp(t->scope, t->server, 53);
+ fd = dns_scope_socket_udp(t->scope, t->server);
if (fd < 0)
return fd;
}
if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
- dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
+ DnsTransactionState result;
+
+ if (t->scope->protocol == DNS_PROTOCOL_LLMNR)
+ /* If we didn't find anything on LLMNR, it's not an error, but a failure to resolve
+ * the name. */
+ result = DNS_TRANSACTION_NOT_FOUND;
+ else
+ result = DNS_TRANSACTION_ATTEMPTS_MAX_REACHED;
+
+ dns_transaction_complete(t, result);
return 0;
}
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
bool add_known_answers = false;
DnsTransaction *other;
- Iterator i;
DnsResourceKey *tkey;
_cleanup_set_free_ Set *keys = NULL;
unsigned qdcount;
add_known_answers = true;
if (t->key->type == DNS_TYPE_ANY) {
- r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(keys, t->key);
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, t->key);
if (r < 0)
return r;
}
add_known_answers = true;
if (other->key->type == DNS_TYPE_ANY) {
- r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(keys, other->key);
+ r = set_ensure_put(&keys, &dns_resource_key_hash_ops, other->key);
if (r < 0)
return r;
}
return r;
}
- SET_FOREACH(tkey, keys, i) {
+ SET_FOREACH(tkey, keys) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
bool tentative;
dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED);
return 0;
}
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(-r)) {
+ if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(r)) {
/* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot
* answer this request with this protocol. */
dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND);
static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
DnsTransaction *n;
- Iterator i;
int r;
assert(t);
if (t == aux)
return 1;
- SET_FOREACH(n, aux->dnssec_transactions, i) {
+ SET_FOREACH(n, aux->dnssec_transactions) {
r = dns_transaction_find_cyclic(t, n);
if (r != 0)
return r;
}
static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) {
- DnsTransaction *aux;
+ _cleanup_(dns_transaction_gcp) DnsTransaction *aux = NULL;
int r;
assert(t);
}
}
- r = set_ensure_allocated(&t->dnssec_transactions, NULL);
- if (r < 0)
- goto gc;
-
- r = set_ensure_allocated(&aux->notify_transactions, NULL);
- if (r < 0)
- goto gc;
-
r = set_ensure_allocated(&aux->notify_transactions_done, NULL);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(t->dnssec_transactions, aux);
+ r = set_ensure_put(&t->dnssec_transactions, NULL, aux);
if (r < 0)
- goto gc;
+ return r;
- r = set_put(aux->notify_transactions, t);
+ r = set_ensure_put(&aux->notify_transactions, NULL, t);
if (r < 0) {
(void) set_remove(t->dnssec_transactions, aux);
- goto gc;
+ return r;
}
- *ret = aux;
+ *ret = TAKE_PTR(aux);
return 1;
-
-gc:
- dns_transaction_gc(aux);
- return r;
}
static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) {
static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
DnsTransaction *dt;
- Iterator i;
assert(t);
if (!dns_transaction_dnssec_supported(t))
return false;
- SET_FOREACH(dt, t->dnssec_transactions, i)
+ SET_FOREACH(dt, t->dnssec_transactions)
if (!dns_transaction_dnssec_supported(dt))
return false;
case DNS_TYPE_SOA:
case DNS_TYPE_NS: {
DnsTransaction *dt;
- Iterator i;
/* For SOA or NS RRs we look for a matching DS transaction */
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != rr->key->class)
continue;
case DNS_TYPE_DNAME: {
const char *parent = NULL;
DnsTransaction *dt;
- Iterator i;
/*
* CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA.
* DS RRs are signed if the parent is signed, hence also look at the parent SOA
*/
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != rr->key->class)
continue;
default: {
DnsTransaction *dt;
- Iterator i;
/* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != rr->key->class)
continue;
static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) {
DnsTransaction *dt;
const char *tld;
- Iterator i;
int r;
/* If DNSSEC downgrade mode is on, checks whether the
if (!dns_name_is_single_label(tld))
return false;
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != key->class)
continue;
DnsTransaction *dt;
const char *name;
uint16_t type = 0;
- Iterator i;
int r;
assert(t);
/* For all other RRs we check the SOA on the same level to see
* if it's signed. */
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != t->key->class)
continue;
DNS_ANSWER_FOREACH(rrsig, t->answer) {
DnsTransaction *dt;
- Iterator i;
r = dnssec_key_match_rrsig(rr->key, rrsig);
if (r < 0)
if (r == 0)
continue;
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (dt->key->class != rr->key->class)
continue;
static int dns_transaction_copy_validated(DnsTransaction *t) {
DnsTransaction *dt;
- Iterator i;
int r;
assert(t);
/* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */
- SET_FOREACH(dt, t->dnssec_transactions, i) {
+ SET_FOREACH(dt, t->dnssec_transactions) {
if (DNS_TRANSACTION_IS_LIVE(dt->state))
continue;