From: Lennart Poettering Date: Wed, 11 Sep 2024 14:12:04 +0000 (+0200) Subject: resolvectl: show delegate information, too X-Git-Tag: v258-rc1~563^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=45817e9245d48ad8807de2b1604bc64b9dd39a1d;p=thirdparty%2Fsystemd.git resolvectl: show delegate information, too --- diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 1715f0b7469..7dac8d741fc 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -1458,7 +1458,7 @@ static int read_dns_server_one(sd_bus_message *m, ReadDNSFlag flags, char **ret) return 1; } -static int map_link_dns_servers_internal(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, ReadDNSFlag flags, void *userdata) { +static int map_dns_servers_internal(sd_bus *bus, const char *member, sd_bus_message *m, ReadDNSFlag flags, sd_bus_error *error, void *userdata) { char ***l = ASSERT_PTR(userdata); int r; @@ -1497,11 +1497,11 @@ static int map_link_dns_servers_internal(sd_bus *bus, const char *member, sd_bus } static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { - return map_link_dns_servers_internal(bus, member, m, error, /* flags = */ 0, userdata); + return map_dns_servers_internal(bus, member, m, /* flags = */ 0, error, userdata); } static int map_link_dns_servers_ex(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { - return map_link_dns_servers_internal(bus, member, m, error, READ_DNS_EXTENDED, userdata); + return map_dns_servers_internal(bus, member, m, READ_DNS_EXTENDED, error, userdata); } static int map_link_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { @@ -1597,12 +1597,14 @@ static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m, return map_domains_internal(bus, member, m, /* with_ifindex= */ false, error, userdata); } -static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) { +static int status_print_strv_full(int ifindex, const char *ifname, const char *delegate_id, char **p) { const unsigned indent = strlen("Global: "); /* Use the same indentation everywhere to make things nice */ int pos1, pos2; if (ifname) printf("%s%nLink %i (%s)%n%s:", ansi_highlight(), &pos1, ifindex, ifname, &pos2, ansi_normal()); + else if (delegate_id) + printf("%s%nDelegate %s%n%s:", ansi_highlight(), &pos1, delegate_id, &pos2, ansi_normal()); else printf("%s%nGlobal%n%s:", ansi_highlight(), &pos1, &pos2, ansi_normal()); @@ -1626,8 +1628,16 @@ static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) return 0; } +static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) { + return status_print_strv_full(ifindex, ifname, NULL, p); +} + +static int status_print_strv_delegate(const char *delegate_id, char **p) { + return status_print_strv_full(0, NULL, delegate_id, p); +} + static int status_print_strv_global(char **p) { - return status_print_strv_ifindex(0, NULL, p); + return status_print_strv_full(0, NULL, NULL, p); } typedef struct LinkInfo { @@ -2144,18 +2154,13 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) { return 0; } -static int status_all(sd_bus *bus, StatusMode mode) { +static int status_links(sd_bus *bus, StatusMode mode, bool *empty_line) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - bool empty_line = false; int ret = 0, r; assert(bus); - r = status_global(bus, mode, &empty_line); - if (r < 0) - return r; - r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); @@ -2207,11 +2212,205 @@ static int status_all(sd_bus *bus, StatusMode mode) { typesafe_qsort(infos, n_infos, interface_info_compare); FOREACH_ARRAY(info, infos, n_infos) - RET_GATHER(ret, status_ifindex(bus, info->index, info->name, mode, &empty_line)); + RET_GATHER(ret, status_ifindex(bus, info->index, info->name, mode, empty_line)); return ret; } +typedef struct DelegateInfo { + char *current_dns; + char **dns; + char **domains; + bool default_route; +} DelegateInfo; + +static void delegate_info_done(DelegateInfo *p) { + assert(p); + + free(p->current_dns); + strv_free(p->dns); + strv_free(p->domains); +} + +static int map_delegate_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + return map_dns_servers_internal(bus, member, m, READ_DNS_WITH_IFINDEX|READ_DNS_EXTENDED, error, userdata); +} + +static int map_delegate_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_EXTENDED, userdata); +} + +static int map_delegate_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= */ false, error, userdata); +} + +static int status_delegate_one(sd_bus *bus, const char *id, StatusMode mode, bool *empty_line) { + + static const struct bus_properties_map property_map[] = { + { "DNS", "a(iiayqs)", map_delegate_dns_servers, offsetof(DelegateInfo, dns) }, + { "CurrentDNSServer", "(iiayqs)", map_delegate_current_dns_server, offsetof(DelegateInfo, current_dns) }, + { "Domains", "a(sb)", map_delegate_domains, offsetof(DelegateInfo, domains) }, + { "DefaultRoute", "b", NULL, offsetof(DelegateInfo, default_route) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(delegate_info_done) DelegateInfo delegate_info = {}; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(bus); + assert(id); + + r = sd_bus_path_encode("/org/freedesktop/resolve1/dns_delegate", id, &p); + if (r < 0) + return log_oom(); + + r = bus_map_all_properties( + bus, + "org.freedesktop.resolve1", + p, + property_map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &delegate_info); + if (r < 0) + return log_error_errno(r, "Failed to get delegate data for %s: %s", id, bus_error_message(&error, r)); + + pager_open(arg_pager_flags); + + switch (mode) { + + case STATUS_DNS: + return status_print_strv_delegate(id, delegate_info.dns); + + case STATUS_DOMAIN: + return status_print_strv_delegate(id, delegate_info.domains); + + case STATUS_DEFAULT_ROUTE: + printf("%sDelegate %s%s: %s\n", + ansi_highlight(), id, ansi_normal(), + yes_no(delegate_info.default_route)); + + return 0; + + case STATUS_ALL: + break; + + default: + return 0; + } + + if (empty_line && *empty_line) + fputc('\n', stdout); + + printf("%sDelegate %s%s\n", + ansi_highlight(), id, ansi_normal()); + + _cleanup_(table_unrefp) Table *table = table_new_vertical(); + if (!table) + return log_oom(); + + if (delegate_info.current_dns) { + r = table_add_many(table, + TABLE_FIELD, "Current DNS Server", + TABLE_STRING, delegate_info.current_dns); + if (r < 0) + return table_log_add_error(r); + } + + r = dump_list(table, "DNS Servers", delegate_info.dns); + if (r < 0) + return r; + + r = dump_list(table, "DNS Domain", delegate_info.domains); + if (r < 0) + return r; + + r = table_add_many(table, + TABLE_FIELD, "Default Route", + TABLE_SET_MINIMUM_WIDTH, 19, + TABLE_BOOLEAN, delegate_info.default_route); + + r = table_print(table, NULL); + if (r < 0) + return table_log_print_error(r); + + if (empty_line) + *empty_line = true; + + return 0; +} + +static int status_delegates(sd_bus *bus, StatusMode mode, bool *empty_line) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r, ret = 0; + + assert(bus); + + r = bus_call_method(bus, bus_resolve_mgr, "ListDelegates", &error, &reply, NULL); + if (r < 0) { + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) { + log_debug("Delegates not supported, skipping."); + return 0; + } + return log_error_errno(r, "Failed to list delegates: %s", bus_error_message(&error, r)); + } + + r = sd_bus_message_enter_container(reply, 'a', "(so)"); + if (r < 0) + return bus_log_parse_error(r); + + _cleanup_strv_free_ char **l = NULL; + for (;;) { + const char *id; + + r = sd_bus_message_read(reply, "(so)", &id, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (strv_extend(&l, id) < 0) + return log_oom(); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + strv_sort(l); + + STRV_FOREACH(i, l) + RET_GATHER(ret, status_delegate_one(bus, *i, mode, empty_line)); + + return ret; +} + +static int status_all(sd_bus *bus, StatusMode mode) { + bool empty_line = false; + int r; + + assert(bus); + + r = status_global(bus, mode, &empty_line); + if (r < 0) + return r; + + r = status_links(bus, mode, &empty_line); + if (r < 0) + return r; + + r = status_delegates(bus, mode, &empty_line); + if (r < 0) + return r; + + return 0; +} + static int verb_status(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;