]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-query.c
Merge pull request #8025 from sourcejedi/pid1_journal_or2
[thirdparty/systemd.git] / src / resolve / resolved-dns-query.c
index c8af5579f02f17f67b40fbbd7cec11ee2c7aa085..5f51340743e44782d341445ff2b887878666c1cd 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -27,9 +28,6 @@
 #include "resolved-etc-hosts.h"
 #include "string-util.h"
 
-/* How long to wait for the query in total */
-#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
-
 #define CNAME_MAX 8
 #define QUERIES_MAX 2048
 #define AUXILIARY_QUERIES_MAX 64
@@ -83,9 +81,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
         if (c->scope)
                 LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
 
-        free(c);
-
-        return NULL;
+        return mfree(c);
 }
 
 static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
@@ -405,6 +401,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
         sd_bus_track_unref(q->bus_track);
 
         dns_packet_unref(q->request_dns_packet);
+        dns_packet_unref(q->reply_dns_packet);
 
         if (q->request_dns_stream) {
                 /* Detach the stream from our query, in case something else keeps a reference to it. */
@@ -421,9 +418,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
                 q->manager->n_dns_queries--;
         }
 
-        free(q);
-
-        return NULL;
+        return mfree(q);
 }
 
 int dns_query_new(
@@ -520,7 +515,7 @@ int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) {
         assert(q);
         assert(auxiliary_for);
 
-        /* Ensure that that the query is not auxiliary yet, and
+        /* Ensure that the query is not auxiliary yet, and
          * nothing else is auxiliary to it either */
         assert(!q->auxiliary_for);
         assert(!q->auxiliary_queries);
@@ -626,7 +621,18 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
                         q->question_utf8,
                         q->ifindex,
                         &answer);
+        if (r == -ENXIO) {
+                /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */
+
+                dns_query_reset_answer(q);
+                q->answer_rcode = DNS_RCODE_NXDOMAIN;
+                q->answer_protocol = dns_synthesize_protocol(q->flags);
+                q->answer_family = dns_synthesize_family(q->flags);
+                q->answer_authenticated = true;
+                *state = DNS_TRANSACTION_RCODE_FAILURE;
 
+                return 0;
+        }
         if (r <= 0)
                 return r;
 
@@ -760,8 +766,8 @@ int dns_query_go(DnsQuery *q) {
                         q->manager->event,
                         &q->timeout_event_source,
                         clock_boottime_or_monotonic(),
-                        now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
-                        on_query_timeout, q);
+                        now(clock_boottime_or_monotonic()) + SD_RESOLVED_QUERY_TIMEOUT_USEC,
+                        0, on_query_timeout, q);
         if (r < 0)
                 goto fail;
 
@@ -814,6 +820,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
                 q->answer = dns_answer_unref(q->answer);
                 q->answer_rcode = 0;
                 q->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
+                q->answer_authenticated = false;
                 q->answer_errno = c->error_code;
         }
 
@@ -850,15 +857,18 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
                         continue;
 
                 default:
-                        /* Any kind of failure? Store the data away,
-                         * if there's nothing stored yet. */
-
+                        /* Any kind of failure? Store the data away, if there's nothing stored yet. */
                         if (state == DNS_TRANSACTION_SUCCESS)
                                 continue;
 
+                        /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */
+                        if (q->answer_authenticated && !t->answer_authenticated)
+                                continue;
+
                         q->answer = dns_answer_unref(q->answer);
                         q->answer_rcode = t->answer_rcode;
                         q->answer_dnssec_result = t->answer_dnssec_result;
+                        q->answer_authenticated = t->answer_authenticated;
                         q->answer_errno = t->answer_errno;
 
                         state = t->state;
@@ -1032,6 +1042,9 @@ int dns_query_process_cname(DnsQuery *q) {
         if (q->flags & SD_RESOLVED_NO_CNAME)
                 return -ELOOP;
 
+        if (!q->answer_authenticated)
+                q->previous_redirect_unauthenticated = true;
+
         /* OK, let's actually follow the CNAME */
         r = dns_query_cname_redirect(q, cname);
         if (r < 0)
@@ -1119,3 +1132,9 @@ const char *dns_query_string(DnsQuery *q) {
 
         return dns_question_first_name(q->question_idna);
 }
+
+bool dns_query_fully_authenticated(DnsQuery *q) {
+        assert(q);
+
+        return q->answer_authenticated && !q->previous_redirect_unauthenticated;
+}