From: Nick Rosbrook Date: Fri, 30 Jan 2026 19:34:38 +0000 (-0500) Subject: resolvectl: use varlink to report global status X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a56366182ee353f8d777d0384a37580a309ed4b6;p=thirdparty%2Fsystemd.git resolvectl: use varlink to report global status 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. --- diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index d6609fe2edc..d9f93b5cbc7 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -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, + ¤t_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;