]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolvectl: use varlink to report global status
authorNick Rosbrook <enr0n@ubuntu.com>
Fri, 30 Jan 2026 19:34:38 +0000 (14:34 -0500)
committerNick Rosbrook <enr0n@ubuntu.com>
Tue, 3 Feb 2026 20:07:41 +0000 (15:07 -0500)
This is an incremental commit to replacing dbus usage with varlink for
all status output.

Re-implement regular global status output using the DumpDNSConfiguration
varlink method. And, remove the GlobalInfo type and associated functions
which were used to map dbus properties.

src/resolve/resolvectl.c

index d6609fe2edc09b700be0203bfdcdb9425b43f465..d9f93b5cbc72f3631b6f505f6299649af67b59f5 100644 (file)
@@ -21,6 +21,7 @@
 #include "bus-map-properties.h"
 #include "bus-message-util.h"
 #include "bus-util.h"
+#include "dns-configuration.h"
 #include "dns-domain.h"
 #include "dns-packet.h"
 #include "dns-rr.h"
@@ -35,6 +36,7 @@
 #include "missing-network.h"
 #include "netlink-util.h"
 #include "openssl-util.h"
+#include "ordered-set.h"
 #include "pager.h"
 #include "parse-argument.h"
 #include "parse-util.h"
@@ -1699,23 +1701,6 @@ typedef struct LinkInfo {
         bool default_route;
 } LinkInfo;
 
-typedef struct GlobalInfo {
-        char *current_dns;
-        char *current_dns_ex;
-        char **dns;
-        char **dns_ex;
-        char **fallback_dns;
-        char **fallback_dns_ex;
-        char **domains;
-        char **ntas;
-        const char *llmnr;
-        const char *mdns;
-        const char *dns_over_tls;
-        const char *dnssec;
-        const char *resolv_conf_mode;
-        bool dnssec_supported;
-} GlobalInfo;
-
 static void link_info_done(LinkInfo *p) {
         assert(p);
 
@@ -1727,19 +1712,6 @@ static void link_info_done(LinkInfo *p) {
         strv_free(p->ntas);
 }
 
-static void global_info_done(GlobalInfo *p) {
-        assert(p);
-
-        free(p->current_dns);
-        free(p->current_dns_ex);
-        strv_free(p->dns);
-        strv_free(p->dns_ex);
-        strv_free(p->fallback_dns);
-        strv_free(p->fallback_dns_ex);
-        strv_free(p->domains);
-        strv_free(p->ntas);
-}
-
 static int dump_list(Table *table, const char *field, char * const *l) {
         int r;
 
@@ -1790,26 +1762,6 @@ static char** link_protocol_status(const LinkInfo *info) {
         return TAKE_PTR(s);
 }
 
-static char** global_protocol_status(const GlobalInfo *info) {
-        _cleanup_strv_free_ char **s = NULL;
-
-        if (strv_extend_extended_bool(&s, "LLMNR", info->llmnr) < 0)
-                return NULL;
-
-        if (strv_extend_extended_bool(&s, "mDNS", info->mdns) < 0)
-                return NULL;
-
-        if (strv_extend_extended_bool(&s, "DNSOverTLS", info->dns_over_tls) < 0)
-                return NULL;
-
-        if (strv_extendf(&s, "DNSSEC=%s/%s",
-                         info->dnssec ?: "???",
-                         info->dnssec_supported ? "supported" : "unsupported") < 0)
-                return NULL;
-
-        return TAKE_PTR(s);
-}
-
 static int status_json_filter_fields(sd_json_variant **configuration, StatusMode mode) {
         _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
         sd_json_variant *w;
@@ -1929,6 +1881,112 @@ static int status_json(StatusMode mode, char **links) {
         return sd_json_variant_dump(configuration, arg_json_format_flags, /* f= */ NULL, /* prefix= */ NULL);
 }
 
+static int format_dns_server_one(DNSServer *s, bool with_ifindex, bool only_global, char **ret) {
+        int r;
+
+        assert(s);
+        assert(ret);
+
+        if (only_global && s->ifindex > 0 && s->ifindex != LOOPBACK_IFINDEX) {
+                /* This one has an (non-loopback) ifindex set, and we were told to suppress those. Hence do so. */
+                *ret = NULL;
+                return 0;
+        }
+
+        r = in_addr_port_ifindex_name_to_string(
+                        s->family,
+                        &s->in_addr,
+                        s->port != 53 ? s->port : 0,
+                        with_ifindex ? s->ifindex : 0,
+                        s->server_name,
+                        ret);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int format_dns_servers(OrderedSet *servers, bool with_ifindex, bool only_global, char ***ret) {
+        int r;
+
+        assert(ret);
+
+        _cleanup_strv_free_ char **l = NULL;
+        DNSServer *s;
+        ORDERED_SET_FOREACH(s, servers) {
+                _cleanup_free_ char *str = NULL;
+                r = format_dns_server_one(s, with_ifindex, only_global, &str);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        r = strv_consume(&l, TAKE_PTR(str));
+                        if (r < 0)
+                                return log_oom();
+                }
+        }
+
+        *ret = TAKE_PTR(l);
+        return 0;
+}
+
+static int format_search_domains(OrderedSet *domains, bool only_global, char ***ret) {
+        int r;
+
+        assert(ret);
+
+        _cleanup_strv_free_ char **l = NULL;
+        SearchDomain *d;
+        ORDERED_SET_FOREACH(d, domains) {
+                if (only_global && d->ifindex > 0)
+                        /* Only show the global ones here */
+                        continue;
+
+                _cleanup_free_ char *str = NULL;
+                if (d->route_only)
+                        str = strjoin("~", d->name);
+                else
+                        str = strdup(d->name);
+                if (!str)
+                        return log_oom();
+
+                r = strv_consume(&l, TAKE_PTR(str));
+                if (r < 0)
+                        return log_oom();
+        }
+
+        *ret = TAKE_PTR(l);
+        return 0;
+}
+
+static int format_protocol_status(DNSConfiguration *configuration, char ***ret) {
+        _cleanup_strv_free_ char **s = NULL;
+        int r;
+
+        assert(configuration);
+        assert(ret);
+
+        r = strv_extend_extended_bool(&s, "LLMNR", configuration->llmnr_mode_str);
+        if (r < 0)
+                return r;
+
+        r = strv_extend_extended_bool(&s, "mDNS", configuration->mdns_mode_str);
+        if (r < 0)
+                return r;
+
+        r = strv_extend_extended_bool(&s, "DNSOverTLS", configuration->dns_over_tls_mode_str);
+        if (r < 0)
+                return r;
+
+        r = strv_extendf(&s, "DNSSEC=%s/%s",
+                         configuration->dnssec_mode_str ?: "???",
+                         configuration->dnssec_supported ? "supported" : "unsupported");
+        if (r < 0)
+                return r;
+
+        *ret = TAKE_PTR(s);
+        return 0;
+}
+
 static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) {
         static const struct bus_properties_map property_map[] = {
                 { "ScopesMask",                 "t",        NULL,                           offsetof(LinkInfo, scopes_mask)      },
@@ -2120,141 +2178,66 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode
         return 0;
 }
 
-static int map_global_dns_servers_internal(
-                sd_bus *bus,
-                const char *member,
-                sd_bus_message *m,
-                sd_bus_error *error,
-                void *userdata,
-                ReadDNSFlag flags) {
-
-        char ***l = ASSERT_PTR(userdata);
+static int status_global(DNSConfiguration *configuration, StatusMode mode, bool *empty_line) {
+        _cleanup_(table_unrefp) Table *table = NULL;
         int r;
 
-        assert(bus);
-        assert(member);
-        assert(m);
+        assert(configuration);
+        assert(configuration->ifindex == 0);
+        assert(!configuration->delegate);
+        assert(empty_line);
 
-        r = sd_bus_message_enter_container(m, 'a', FLAGS_SET(flags, READ_DNS_EXTENDED) ? "(iiayqs)" : "(iiay)");
-        if (r < 0)
-                return r;
+        pager_open(arg_pager_flags);
 
-        for (;;) {
-                _cleanup_free_ char *pretty = NULL;
+        switch (mode) {
 
-                r = read_dns_server_one(m, flags, &pretty);
+        case STATUS_DNS: {
+                _cleanup_strv_free_ char **dns_servers = NULL;
+                r = format_dns_servers(configuration->dns_servers,
+                                       /* with_ifindex= */ true,
+                                       /* only_global= */ true,
+                                       &dns_servers);
                 if (r < 0)
                         return r;
-                if (r == 0)
-                        break;
 
-                if (isempty(pretty))
-                        continue;
+                return status_print_strv_global(dns_servers);
+        }
 
-                r = strv_consume(l, TAKE_PTR(pretty));
+        case STATUS_DOMAIN: {
+                _cleanup_strv_free_ char **search_domains = NULL;
+                r = format_search_domains(configuration->search_domains,
+                                          /* only_global= */ true,
+                                          &search_domains);
                 if (r < 0)
                         return r;
-        }
-
-        r = sd_bus_message_exit_container(m);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
-static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
-        return map_global_dns_servers_internal(bus, member, m, error, userdata, READ_DNS_WITH_IFINDEX | READ_DNS_ONLY_GLOBAL);
-}
-
-static int map_global_dns_servers_ex(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
-        return map_global_dns_servers_internal(bus, member, m, error, userdata, READ_DNS_WITH_IFINDEX | READ_DNS_ONLY_GLOBAL | READ_DNS_EXTENDED);
-}
-
-static int map_global_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
-        return read_dns_server_one(m, READ_DNS_WITH_IFINDEX | READ_DNS_ONLY_GLOBAL, userdata);
-}
-
-static int map_global_current_dns_server_ex(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
-        return read_dns_server_one(m, READ_DNS_WITH_IFINDEX | READ_DNS_ONLY_GLOBAL | READ_DNS_EXTENDED, userdata);
-}
-
-static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
-        return map_domains_internal(bus, member, m, /* with_ifindex= */ true, error, userdata);
-}
-
-static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
-        static const struct bus_properties_map property_map[] = {
-                { "DNS",                        "a(iiay)",   map_global_dns_servers,           offsetof(GlobalInfo, dns)              },
-                { "DNSEx",                      "a(iiayqs)", map_global_dns_servers_ex,        offsetof(GlobalInfo, dns_ex)           },
-                { "FallbackDNS",                "a(iiay)",   map_global_dns_servers,           offsetof(GlobalInfo, fallback_dns)     },
-                { "FallbackDNSEx",              "a(iiayqs)", map_global_dns_servers_ex,        offsetof(GlobalInfo, fallback_dns_ex)  },
-                { "CurrentDNSServer",           "(iiay)",    map_global_current_dns_server,    offsetof(GlobalInfo, current_dns)      },
-                { "CurrentDNSServerEx",         "(iiayqs)",  map_global_current_dns_server_ex, offsetof(GlobalInfo, current_dns_ex)   },
-                { "Domains",                    "a(isb)",    map_global_domains,               offsetof(GlobalInfo, domains)          },
-                { "DNSSECNegativeTrustAnchors", "as",        bus_map_strv_sort,                offsetof(GlobalInfo, ntas)             },
-                { "LLMNR",                      "s",         NULL,                             offsetof(GlobalInfo, llmnr)            },
-                { "MulticastDNS",               "s",         NULL,                             offsetof(GlobalInfo, mdns)             },
-                { "DNSOverTLS",                 "s",         NULL,                             offsetof(GlobalInfo, dns_over_tls)     },
-                { "DNSSEC",                     "s",         NULL,                             offsetof(GlobalInfo, dnssec)           },
-                { "DNSSECSupported",            "b",         NULL,                             offsetof(GlobalInfo, dnssec_supported) },
-                { "ResolvConfMode",             "s",         NULL,                             offsetof(GlobalInfo, resolv_conf_mode) },
-                {}
-        };
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-        _cleanup_(global_info_done) GlobalInfo global_info = {};
-        _cleanup_(table_unrefp) Table *table = NULL;
-        int r;
-
-        assert(bus);
-        assert(empty_line);
-
-        r = bus_map_all_properties(bus,
-                                   "org.freedesktop.resolve1",
-                                   "/org/freedesktop/resolve1",
-                                   property_map,
-                                   BUS_MAP_BOOLEAN_AS_BOOL,
-                                   &error,
-                                   &m,
-                                   &global_info);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r));
 
-        pager_open(arg_pager_flags);
-
-        switch (mode) {
-
-        case STATUS_DNS:
-                return status_print_strv_global(global_info.dns_ex ?: global_info.dns);
-
-        case STATUS_DOMAIN:
-                return status_print_strv_global(global_info.domains);
+                return status_print_strv_global(search_domains);
+        }
 
         case STATUS_NTA:
-                return status_print_strv_global(global_info.ntas);
+                return status_print_strv_global(configuration->negative_trust_anchors);
 
         case STATUS_LLMNR:
                 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
-                       strna(global_info.llmnr));
+                       strna(configuration->llmnr_mode_str));
 
                 return 0;
 
         case STATUS_MDNS:
                 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
-                       strna(global_info.mdns));
+                       strna(configuration->mdns_mode_str));
 
                 return 0;
 
         case STATUS_DNS_OVER_TLS:
                 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
-                       strna(global_info.dns_over_tls));
+                       strna(configuration->dns_over_tls_mode_str));
 
                 return 0;
 
         case STATUS_DNSSEC:
                 printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(),
-                       strna(global_info.dnssec));
+                       strna(configuration->dnssec_mode_str));
 
                 return 0;
 
@@ -2271,9 +2254,10 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
         if (!table)
                 return log_oom();
 
-        _cleanup_strv_free_ char **pstatus = global_protocol_status(&global_info);
-        if (!pstatus)
-                return log_oom();
+        _cleanup_strv_free_ char **pstatus = NULL;
+        r = format_protocol_status(configuration, &pstatus);
+        if (r < 0)
+                return r;
 
         r = table_add_many(table,
                            TABLE_FIELD,            "Protocols",
@@ -2282,31 +2266,63 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
         if (r < 0)
                 return table_log_add_error(r);
 
-        if (global_info.resolv_conf_mode) {
+        if (configuration->resolv_conf_mode_str) {
                 r = table_add_many(table,
                                    TABLE_FIELD, "resolv.conf mode",
-                                   TABLE_STRING, global_info.resolv_conf_mode);
+                                   TABLE_STRING, configuration->resolv_conf_mode_str);
                 if (r < 0)
                         return table_log_add_error(r);
         }
 
-        if (global_info.current_dns) {
-                r = table_add_many(table,
-                                   TABLE_FIELD, "Current DNS Server",
-                                   TABLE_STRING, global_info.current_dns_ex ?: global_info.current_dns);
+        if (configuration->current_dns_server) {
+                _cleanup_free_ char *current_dns = NULL;
+                r = format_dns_server_one(configuration->current_dns_server,
+                                          /* with_ifindex= */ true,
+                                          /* only_global= */ true,
+                                          &current_dns);
                 if (r < 0)
-                        return table_log_add_error(r);
+                        return r;
+                if (r > 0) {
+                        r = table_add_many(table,
+                                           TABLE_FIELD, "Current DNS Server",
+                                           TABLE_STRING, current_dns);
+                        if (r < 0)
+                                return table_log_add_error(r);
+                }
         }
 
-        r = dump_list(table, "DNS Servers", global_info.dns_ex ?: global_info.dns);
+        _cleanup_strv_free_ char **dns_servers = NULL;
+        r = format_dns_servers(configuration->dns_servers,
+                               /* with_ifindex= */ true,
+                               /* only_global= */ true,
+                               &dns_servers);
+        if (r < 0)
+                return r;
+
+        r = dump_list(table, "DNS Servers", dns_servers);
+        if (r < 0)
+                return r;
+
+        _cleanup_strv_free_ char **fallback_dns_servers = NULL;
+        r = format_dns_servers(configuration->fallback_dns_servers,
+                               /* with_ifindex= */ true,
+                               /* only_global= */ true,
+                               &fallback_dns_servers);
+        if (r < 0)
+                return r;
+
+        r = dump_list(table, "Fallback DNS Servers", fallback_dns_servers);
         if (r < 0)
                 return r;
 
-        r = dump_list(table, "Fallback DNS Servers", global_info.fallback_dns_ex ?: global_info.fallback_dns);
+        _cleanup_strv_free_ char **search_domains = NULL;
+        r = format_search_domains(configuration->search_domains,
+                                  /* only_global= */ true,
+                                  &search_domains);
         if (r < 0)
                 return r;
 
-        r = dump_list(table, "DNS Domain", global_info.domains);
+        r = dump_list(table, "DNS Domain", search_domains);
         if (r < 0)
                 return r;
 
@@ -2566,10 +2582,33 @@ static int status_all(sd_bus *bus, StatusMode mode) {
         if (sd_json_format_enabled(arg_json_format_flags))
                 return status_json(mode, /* links= */ NULL);
 
-        r = status_global(bus, mode, &empty_line);
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+        r = varlink_dump_dns_configuration(&v);
         if (r < 0)
                 return r;
 
+        _cleanup_(dns_configuration_freep) DNSConfiguration *global_config = NULL;
+        sd_json_variant *w;
+        JSON_VARIANT_ARRAY_FOREACH(w, v) {
+                _cleanup_(dns_configuration_freep) DNSConfiguration *c = NULL;
+                r = dns_configuration_from_json(w, &c);
+                if (r < 0)
+                        return r;
+
+                if (c->ifindex > 0 || c->delegate)
+                        continue;
+                else {
+                        assert(!global_config);
+                        global_config = TAKE_PTR(c);
+                }
+        }
+
+        if (global_config) {
+                r = status_global(global_config, mode, &empty_line);
+                if (r < 0)
+                        return r;
+        }
+
         r = status_links(bus, mode, &empty_line);
         if (r < 0)
                 return r;