]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-bus.c
Merge pull request #18990 from yuwata/network-dhcpv6-use-domains
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
index 724c3d4a6a10dbe25d7da09a613bfb94024ebc6e..c3624669ce18b954fb29890bce42c936ce4005cd 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "alloc-util.h"
 #include "bus-common-errors.h"
@@ -7,6 +7,7 @@
 #include "bus-message-util.h"
 #include "bus-polkit.h"
 #include "dns-domain.h"
+#include "format-util.h"
 #include "memory-util.h"
 #include "missing_capability.h"
 #include "resolved-bus.h"
@@ -101,6 +102,12 @@ static int reply_query_state(DnsQuery *q) {
                  * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
                 return sd_bus_reply_method_errorf(q->bus_request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
 
+        case DNS_TRANSACTION_NO_SOURCE:
+                return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
+
+        case DNS_TRANSACTION_STUB_LOOP:
+                return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_STUB_LOOP, "Configured DNS server loops back to us");
+
         case DNS_TRANSACTION_RCODE_FAILURE: {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 
@@ -188,14 +195,14 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
                 goto finish;
         }
 
-        r = dns_query_process_cname(q);
+        r = dns_query_process_cname_many(q);
         if (r == -ELOOP) {
                 r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
                 goto finish;
         }
         if (r < 0)
                 goto finish;
-        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
                 return;
 
         r = sd_bus_message_new_method_return(q->bus_request, &reply);
@@ -246,7 +253,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
         r = sd_bus_message_append(
                         reply, "st",
                         normalized,
-                        SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+                        dns_query_reply_flags_make(q));
         if (r < 0)
                 goto finish;
 
@@ -274,8 +281,8 @@ static int validate_and_mangle_flags(
          *
          * 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive
          *
-         * 2. Only the protocols flags and the NO_CNAME flag are set, at most. Plus additional flags specific
-         *    to our method, passed in the "ok" parameter.
+         * 2. Only the protocols flags and a bunch of NO_XYZ flags are set, at most. Plus additional flags
+         *    specific to our method, passed in the "ok" parameter.
          *
          * 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way
          *    clients can simply pass 0 as flags and all will work as it should. They can also use this so
@@ -283,7 +290,15 @@ static int validate_and_mangle_flags(
          *    to mean "all supported protocols".
          */
 
-        if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
+        if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|
+                       SD_RESOLVED_NO_CNAME|
+                       SD_RESOLVED_NO_VALIDATE|
+                       SD_RESOLVED_NO_SYNTHESIZE|
+                       SD_RESOLVED_NO_CACHE|
+                       SD_RESOLVED_NO_ZONE|
+                       SD_RESOLVED_NO_TRUST_ANCHOR|
+                       SD_RESOLVED_NO_NETWORK|
+                       ok))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
 
         if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
@@ -353,13 +368,39 @@ static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname
                 return r;
 
         r = sd_bus_message_append(reply, "st", canonical,
-                                  SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
+                                  SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true) |
+                                  SD_RESOLVED_SYNTHETIC);
         if (r < 0)
                 return r;
 
         return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
 }
 
+void bus_client_log(sd_bus_message *m, const char *what) {
+        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+        const char *comm = NULL;
+        uid_t uid = UID_INVALID;
+        pid_t pid = 0;
+        int r;
+
+        assert(m);
+        assert(what);
+
+        if (!DEBUG_LOGGING)
+                return;
+
+        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
+        if (r < 0)
+                return (void) log_debug_errno(r, "Failed to query client credentials, ignoring: %m");
+
+        (void) sd_bus_creds_get_uid(creds, &uid);
+        (void) sd_bus_creds_get_pid(creds, &pid);
+        (void) sd_bus_creds_get_comm(creds, &comm);
+
+        log_debug("D-Bus %s request from client PID " PID_FMT " (%s) with UID " UID_FMT,
+                  what, pid, strna(comm), uid);
+}
+
 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
         Manager *m = userdata;
@@ -406,7 +447,9 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
         if (r < 0 && r != -EALREADY)
                 return r;
 
-        r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
+        bus_client_log(message, "hostname resolution");
+
+        r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, ifindex, flags);
         if (r < 0)
                 return r;
 
@@ -443,14 +486,14 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
                 goto finish;
         }
 
-        r = dns_query_process_cname(q);
+        r = dns_query_process_cname_many(q);
         if (r == -ELOOP) {
                 r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
                 goto finish;
         }
         if (r < 0)
                 goto finish;
-        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
                 return;
 
         r = sd_bus_message_new_method_return(q->bus_request, &reply);
@@ -496,7 +539,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+        r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
         if (r < 0)
                 goto finish;
 
@@ -548,7 +591,9 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+        bus_client_log(message, "address resolution");
+
+        r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
         if (r < 0)
                 return r;
 
@@ -615,14 +660,14 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
                 goto finish;
         }
 
-        r = dns_query_process_cname(q);
+        r = dns_query_process_cname_many(q);
         if (r == -ELOOP) {
                 r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
                 goto finish;
         }
         if (r < 0)
                 goto finish;
-        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
                 return;
 
         r = sd_bus_message_new_method_return(q->bus_request, &reply);
@@ -658,7 +703,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
         if (r < 0)
                 goto finish;
 
-        r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+        r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
         if (r < 0)
                 goto finish;
 
@@ -724,14 +769,14 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+        bus_client_log(message, "resource record resolution");
+
+        /* Setting SD_RESOLVED_CLAMP_TTL: let's request that the TTL is fixed up for locally cached entries,
+         * after all we return it in the wire format blob. */
+        r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH|SD_RESOLVED_CLAMP_TTL);
         if (r < 0)
                 return r;
 
-        /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
-         * blob */
-        q->clamp_ttl = true;
-
         q->bus_request = sd_bus_message_ref(message);
         q->complete = bus_method_resolve_record_complete;
 
@@ -1036,7 +1081,7 @@ static void resolve_service_all_complete(DnsQuery *q) {
                         reply,
                         "ssst",
                         name, type, domain,
-                        SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
+                        dns_query_reply_flags_make(q));
         if (r < 0)
                 goto finish;
 
@@ -1062,8 +1107,8 @@ static void resolve_service_hostname_complete(DnsQuery *q) {
                 return;
         }
 
-        r = dns_query_process_cname(q);
-        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+        r = dns_query_process_cname_many(q);
+        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
                 return;
 
         /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
@@ -1088,7 +1133,7 @@ static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifin
         if (r < 0)
                 return r;
 
-        r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
+        r = dns_query_new(q->manager, &aux, question, question, NULL, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
         if (r < 0)
                 return r;
 
@@ -1135,14 +1180,14 @@ static void bus_method_resolve_service_complete(DnsQuery *q) {
                 goto finish;
         }
 
-        r = dns_query_process_cname(q);
+        r = dns_query_process_cname_many(q);
         if (r == -ELOOP) {
                 r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
                 goto finish;
         }
         if (r < 0)
                 goto finish;
-        if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
+        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
                 return;
 
         question = dns_query_question_for_protocol(q, q->answer_protocol);
@@ -1258,7 +1303,9 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s
         if (r < 0)
                 return r;
 
-        r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
+        bus_client_log(message, "service resolution");
+
+        r = dns_query_new(m, &q, question_utf8, question_idna, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
         if (r < 0)
                 return r;
 
@@ -1650,6 +1697,8 @@ static int bus_method_reset_statistics(sd_bus_message *message, void *userdata,
         assert(message);
         assert(m);
 
+        bus_client_log(message, "statistics reset");
+
         LIST_FOREACH(scopes, s, m->dns_scopes)
                 s->cache.n_hit = s->cache.n_miss = 0;
 
@@ -1762,7 +1811,9 @@ static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_b
         assert(message);
         assert(m);
 
-        manager_flush_caches(m);
+        bus_client_log(message, "cache flush");
+
+        manager_flush_caches(m, LOG_INFO);
 
         return sd_bus_reply_method_return(message, NULL);
 }
@@ -1773,6 +1824,8 @@ static int bus_method_reset_server_features(sd_bus_message *message, void *userd
         assert(message);
         assert(m);
 
+        bus_client_log(message, "server feature reset");
+
         manager_reset_server_features(m);
 
         return sd_bus_reply_method_return(message, NULL);
@@ -1795,6 +1848,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
         _cleanup_(dnssd_service_freep) DnssdService *service = NULL;
         _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
         _cleanup_free_ char *path = NULL;
+        _cleanup_free_ char *instance_name = NULL;
         Manager *m = userdata;
         DnssdService *s = NULL;
         const char *name;
@@ -1835,10 +1889,6 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
         if (!dnssd_srv_type_is_valid(type))
                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type);
 
-        r = dnssd_render_instance_name(name_template, NULL);
-        if (r < 0)
-                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service name '%s' is invalid", name_template);
-
         service->name = strdup(name);
         if (!service->name)
                 return log_oom();
@@ -1851,6 +1901,10 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
         if (!service->type)
                 return log_oom();
 
+        r = dnssd_render_instance_name(service, &instance_name);
+        if (r < 0)
+                return r;
+
         r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}");
         if (r < 0)
                 return r;
@@ -1942,11 +1996,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
         if (r == 0)
                 return 1; /* Polkit will call us back */
 
-        r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops);
-        if (r < 0)
-                return r;
-
-        r = hashmap_put(m->dnssd_services, service->name, service);
+        r = hashmap_ensure_put(&m->dnssd_services, &string_hash_ops, service->name, service);
         if (r < 0)
                 return r;