]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-query.c
tree-wide: use mfree more
[thirdparty/systemd.git] / src / resolve / resolved-dns-query.c
index 06d30d78638e75c241af148a0720ed6db7c421e2..e03db4d003ee3630ec9a6d1fbd9a96a7ef27c5cb 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
@@ -64,6 +62,7 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
 
         while ((t = set_steal_first(c->transactions))) {
                 set_remove(t->notify_query_candidates, c);
+                set_remove(t->notify_query_candidates_done, c);
                 dns_transaction_gc(t);
         }
 }
@@ -84,9 +83,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) {
@@ -141,6 +138,10 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
         if (r < 0)
                 goto gc;
 
+        r = set_ensure_allocated(&t->notify_query_candidates_done, NULL);
+        if (r < 0)
+                goto gc;
+
         r = set_put(t->notify_query_candidates, c);
         if (r < 0)
                 goto gc;
@@ -151,6 +152,7 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
                 goto gc;
         }
 
+        t->clamp_ttl = c->query->clamp_ttl;
         return 1;
 
 gc:
@@ -400,6 +402,16 @@ DnsQuery *dns_query_free(DnsQuery *q) {
         sd_bus_message_unref(q->request);
         sd_bus_track_unref(q->bus_track);
 
+        dns_packet_unref(q->request_dns_packet);
+
+        if (q->request_dns_stream) {
+                /* Detach the stream from our query, in case something else keeps a reference to it. */
+                q->request_dns_stream->complete = NULL;
+                q->request_dns_stream->on_packet = NULL;
+                q->request_dns_stream->query = NULL;
+                dns_stream_unref(q->request_dns_stream);
+        }
+
         free(q->request_address_string);
 
         if (q->manager) {
@@ -407,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
                 q->manager->n_dns_queries--;
         }
 
-        free(q);
-
-        return NULL;
+        return mfree(q);
 }
 
 int dns_query_new(
@@ -417,12 +427,14 @@ int dns_query_new(
                 DnsQuery **ret,
                 DnsQuestion *question_utf8,
                 DnsQuestion *question_idna,
-                int ifindex, uint64_t flags) {
+                int ifindex,
+                uint64_t flags) {
 
         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
         DnsResourceKey *key;
         bool good = false;
         int r;
+        char key_str[DNS_RESOURCE_KEY_STRING_MAX];
 
         assert(m);
 
@@ -473,31 +485,20 @@ int dns_query_new(
         q->answer_family = AF_UNSPEC;
 
         /* First dump UTF8  question */
-        DNS_QUESTION_FOREACH(key, question_utf8) {
-                _cleanup_free_ char *p = NULL;
-
-                r = dns_resource_key_to_string(key, &p);
-                if (r < 0)
-                        return r;
-
-                log_debug("Looking up RR for %s.", strstrip(p));
-        }
+        DNS_QUESTION_FOREACH(key, question_utf8)
+                log_debug("Looking up RR for %s.",
+                          dns_resource_key_to_string(key, key_str, sizeof key_str));
 
         /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
         DNS_QUESTION_FOREACH(key, question_idna) {
-                _cleanup_free_ char *p = NULL;
-
                 r = dns_question_contains(question_utf8, key);
                 if (r < 0)
                         return r;
                 if (r > 0)
                         continue;
 
-                r = dns_resource_key_to_string(key, &p);
-                if (r < 0)
-                        return r;
-
-                log_debug("Looking up IDNA RR for %s.", strstrip(p));
+                log_debug("Looking up IDNA RR for %s.",
+                          dns_resource_key_to_string(key, key_str, sizeof key_str));
         }
 
         LIST_PREPEND(queries, m->dns_queries, q);
@@ -515,7 +516,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);
@@ -817,7 +818,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
                 switch (t->state) {
 
                 case DNS_TRANSACTION_SUCCESS: {
-                        /* We found a successfuly reply, merge it into the answer */
+                        /* We found a successfully reply, merge it into the answer */
                         r = dns_answer_extend(&q->answer, t->answer);
                         if (r < 0)
                                 goto fail;
@@ -939,7 +940,7 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
 
         assert(q);
 
-        q->n_cname_redirects ++;
+        q->n_cname_redirects++;
         if (q->n_cname_redirects > CNAME_MAX)
                 return -ELOOP;
 
@@ -967,6 +968,17 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
         if (r == 0 && k == 0) /* No actual cname happened? */
                 return -ELOOP;
 
+        if (q->answer_protocol == DNS_PROTOCOL_DNS) {
+                /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources
+                 * cannot invade the local namespace. The opposite way we permit: local names may redirect to global
+                 * ones. */
+
+                q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */
+        }
+
+        /* Turn off searching for the new name */
+        q->flags |= SD_RESOLVED_NO_SEARCH;
+
         dns_question_unref(q->question_idna);
         q->question_idna = nq_idna;
         nq_idna = NULL;
@@ -977,10 +989,8 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
 
         dns_query_free_candidates(q);
         dns_query_reset_answer(q);
-        q->state = DNS_TRANSACTION_NULL;
 
-        /* Turn off searching for the new name */
-        q->flags |= SD_RESOLVED_NO_SEARCH;
+        q->state = DNS_TRANSACTION_NULL;
 
         return 0;
 }