]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-transaction.c
tree-wide: define iterator inside of the macro
[thirdparty/systemd.git] / src / resolve / resolved-dns-transaction.c
index 9cac91f53603fc178741972f927aeebcc95fbbd5..36f57eae629e27a02188000d02a2cdcca0148ce1 100644 (file)
 #include "random-util.h"
 #include "resolved-dns-cache.h"
 #include "resolved-dns-transaction.h"
-#include "resolved-llmnr.h"
-#if ENABLE_DNS_OVER_TLS
 #include "resolved-dnstls.h"
-#endif
+#include "resolved-llmnr.h"
 #include "string-table.h"
 
 #define TRANSACTIONS_MAX 4096
@@ -268,7 +266,7 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
                   t->id,
                   dns_resource_key_to_string(t->key, key_str, sizeof key_str),
                   dns_protocol_to_string(t->scope->protocol),
-                  t->scope->link ? t->scope->link->name : "*",
+                  t->scope->link ? t->scope->link->ifname : "*",
                   af_to_name_short(t->scope->family),
                   strnull(pretty));
 
@@ -316,7 +314,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
                            "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));
         }
 
@@ -333,7 +331,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
                   t->id,
                   dns_resource_key_to_string(t->key, key_str, sizeof key_str),
                   dns_protocol_to_string(t->scope->protocol),
-                  t->scope->link ? t->scope->link->name : "*",
+                  t->scope->link ? t->scope->link->ifname : "*",
                   af_to_name_short(t->scope->family),
                   st,
                   t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
@@ -366,6 +364,14 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
         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;
 
@@ -400,7 +406,7 @@ static int dns_transaction_pick_server(DnsTransaction *t) {
 
         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;
 }
@@ -417,10 +423,8 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
                 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) {
@@ -468,10 +472,8 @@ static void on_transaction_stream_error(DnsTransaction *t, int error) {
                 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) {
@@ -546,8 +548,10 @@ static int on_stream_packet(DnsStream *s) {
         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) {
@@ -578,7 +582,7 @@ 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;
@@ -674,7 +678,7 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
                 return;
 
         /* Caching disabled? */
-        if (!t->scope->manager->enable_cache)
+        if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO)
                 return;
 
         /* We never cache if this packet is from the local host, under
@@ -685,6 +689,7 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
                 return;
 
         dns_cache_put(&t->scope->cache,
+                      t->scope->manager->enable_cache,
                       t->key,
                       t->answer_rcode,
                       t->answer,
@@ -697,11 +702,10 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
 
 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;
 
@@ -710,14 +714,13 @@ static bool dns_transaction_dnssec_is_live(DnsTransaction *t) {
 
 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) {
 
@@ -734,7 +737,7 @@ static int dns_transaction_dnssec_ready(DnsTransaction *t) {
                         }
 
                         /* Fall-through: NXDOMAIN/SERVFAIL is good enough for us. This is because some DNS servers
-                         * erronously return NXDOMAIN/SERVFAIL for empty non-terminals (Akamai...) or missing DS
+                         * erroneously return NXDOMAIN/SERVFAIL for empty non-terminals (Akamai...) or missing DS
                          * records (Facebook), and we need to handle that nicely, when asking for parent SOA or similar
                          * RRs to make unsigned proofs. */
 
@@ -835,8 +838,7 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) {
         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) {
@@ -1168,8 +1170,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
         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) {
@@ -1181,11 +1182,11 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
         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);
@@ -1195,10 +1196,12 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
                 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) {
@@ -1241,7 +1244,7 @@ static int dns_transaction_emit_udp(DnsTransaction *t) {
 
                         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;
 
@@ -1348,7 +1351,16 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
         }
 
         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;
         }
 
@@ -1462,7 +1474,6 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
         _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;
@@ -1490,11 +1501,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
                 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;
         }
@@ -1502,7 +1509,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
         /*
          * For mDNS, we want to coalesce as many open queries in pending transactions into one single
          * query packet on the wire as possible. To achieve that, we iterate through all pending transactions
-         * in our current scope, and see whether their timing contraints allow them to be sent.
+         * in our current scope, and see whether their timing constraints allow them to be sent.
          */
 
         assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
@@ -1560,11 +1567,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
                         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;
                 }
@@ -1579,7 +1582,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
                         return r;
         }
 
-        SET_FOREACH(tkey, keys, i) {
+        SET_FOREACH(tkey, keys) {
                 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
                 bool tentative;
 
@@ -1648,7 +1651,7 @@ int dns_transaction_go(DnsTransaction *t) {
                   t->id,
                   dns_resource_key_to_string(t->key, key_str, sizeof key_str),
                   dns_protocol_to_string(t->scope->protocol),
-                  t->scope->link ? t->scope->link->name : "*",
+                  t->scope->link ? t->scope->link->ifname : "*",
                   af_to_name_short(t->scope->family));
 
         if (!t->initial_jitter_scheduled &&
@@ -1731,7 +1734,7 @@ int dns_transaction_go(DnsTransaction *t) {
                 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);
@@ -1768,7 +1771,6 @@ int dns_transaction_go(DnsTransaction *t) {
 
 static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
         DnsTransaction *n;
-        Iterator i;
         int r;
 
         assert(t);
@@ -1779,7 +1781,7 @@ static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
         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;
@@ -1789,7 +1791,7 @@ static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) {
 }
 
 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);
@@ -1822,34 +1824,22 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource
                 }
         }
 
-        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) {
@@ -1983,7 +1973,6 @@ static bool dns_transaction_dnssec_supported(DnsTransaction *t) {
 
 static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) {
         DnsTransaction *dt;
-        Iterator i;
 
         assert(t);
 
@@ -1992,7 +1981,7 @@ static bool dns_transaction_dnssec_supported_full(DnsTransaction *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;
 
@@ -2026,7 +2015,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
         if (t->answer_source != DNS_TRANSACTION_NETWORK)
                 return 0; /* We only need to validate stuff from the network */
         if (!dns_transaction_dnssec_supported(t))
-                return 0; /* If we can't do DNSSEC anyway there's no point in geting the auxiliary RRs */
+                return 0; /* If we can't do DNSSEC anyway there's no point in getting the auxiliary RRs */
 
         DNS_ANSWER_FOREACH(rr, t->answer) {
 
@@ -2066,7 +2055,7 @@ int dns_transaction_request_dnssec_keys(DnsTransaction *t) {
                          * RRs for stuff we didn't really ask for, and
                          * also to avoid request loops, where
                          * additional RRs from one transaction result
-                         * in another transaction whose additonal RRs
+                         * in another transaction whose additional RRs
                          * point back to the original transaction, and
                          * we deadlock. */
                         r = dns_name_endswith(dns_resource_key_name(t->key), rr->rrsig.signer);
@@ -2386,11 +2375,10 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
         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;
@@ -2424,7 +2412,6 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
         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.
@@ -2432,7 +2419,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
                  * 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;
@@ -2468,11 +2455,10 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
 
         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;
@@ -2500,7 +2486,6 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *
 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
@@ -2536,7 +2521,7 @@ static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKe
         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;
@@ -2562,7 +2547,6 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) {
         DnsTransaction *dt;
         const char *name;
         uint16_t type = 0;
-        Iterator i;
         int r;
 
         assert(t);
@@ -2620,7 +2604,7 @@ static int dns_transaction_requires_nsec(DnsTransaction *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;
@@ -2657,7 +2641,6 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
 
         DNS_ANSWER_FOREACH(rrsig, t->answer) {
                 DnsTransaction *dt;
-                Iterator i;
 
                 r = dnssec_key_match_rrsig(rr->key, rrsig);
                 if (r < 0)
@@ -2665,7 +2648,7 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe
                 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;
@@ -2777,14 +2760,13 @@ static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) {
 
 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;