From: Nick Rosbrook Date: Fri, 19 Jun 2026 19:01:01 +0000 (-0400) Subject: resolvectl: use varlink instead of dbus for ResolveAddress X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ff17fb750c0485469c73064cffcbbb0d29c6f0f;p=thirdparty%2Fsystemd.git resolvectl: use varlink instead of dbus for ResolveAddress --- diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 4baa2f38681..2cfd5855649 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -446,16 +446,9 @@ static int resolve_host(const char *name) { return 0; } -static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *pretty = NULL; - uint64_t flags; - unsigned c = 0; - usec_t ts; +static int resolve_address(int family, const union in_addr_union *address, int ifindex) { int r; - assert(bus); assert(IN_SET(family, AF_INET, AF_INET6)); assert(address); @@ -465,80 +458,64 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a if (ifindex <= 0) ifindex = arg_ifindex; + _cleanup_free_ char *pretty = NULL; r = in_addr_ifindex_to_string(family, address, ifindex, &pretty); if (r < 0) return log_oom(); log_debug("Resolving %s.", pretty); - r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveAddress"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(req, "ii", ifindex, family); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family)); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(req, "t", arg_flags); + _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL; + r = varlink_connect_with_query_timeout(&vl); if (r < 0) - return bus_log_create_error(r); + return r; - ts = now(CLOCK_MONOTONIC); + usec_t ts = now(CLOCK_MONOTONIC); - r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + const char *error_id = NULL; + sd_json_variant *v = NULL; + r = sd_varlink_callbo( + vl, + "io.systemd.Resolve.ResolveAddress", + &v, + &error_id, + SD_JSON_BUILD_PAIR_BYTE_ARRAY("address", &address->bytes, FAMILY_ADDRESS_SIZE_SAFE(family)), + SD_JSON_BUILD_PAIR_UNSIGNED("family", family), + JSON_BUILD_PAIR_CONDITION_UNSIGNED(ifindex > 0, "ifindex", ifindex), + JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("flags", arg_flags)); if (r < 0) - return log_error_errno(r, "%s: resolve call failed: %s", pretty, bus_error_message(&error, r)); + return log_error_errno(r, "Failed to issue varlink call: %m"); ts = now(CLOCK_MONOTONIC) - ts; - r = sd_bus_message_enter_container(reply, 'a', "(is)"); - if (r < 0) - return bus_log_create_error(r); - - while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) { - const char *n; - int k; - - assert_cc(sizeof(int) == sizeof(int32_t)); - - r = sd_bus_message_read(reply, "is", &ifindex, &n); - if (r < 0) - return r; + if (!isempty(error_id)) + return varlink_log_resolve_error(pretty, error_id, v); - r = sd_bus_message_exit_container(reply); - if (r < 0) - return r; + _cleanup_(resolve_address_reply_done) ResolveAddressReply reply = {}; + r = dispatch_resolve_address_reply(/* name = */ NULL, v, SD_JSON_LOG, &reply); + if (r < 0) + return r; - k = printf("%*s%s %s%s%s", - (int) strlen(pretty), c == 0 ? pretty : "", - c == 0 ? ":" : " ", - ansi_highlight(), n, ansi_normal()); + bool first = true; + FOREACH_ARRAY(name, reply.names, reply.n_names) { + int k = printf("%*s%s %s%s%s", + (int) strlen(pretty), + first ? pretty : "", + first ? ":" : " ", + ansi_highlight(), + name->name, + ansi_normal()); - print_ifindex_comment(k, ifindex); + print_ifindex_comment(k, name->ifindex); fputc('\n', stdout); - c++; + first = false; } - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_read(reply, "t", &flags); - if (r < 0) - return bus_log_parse_error(r); - if (c == 0) - return log_error_errno(SYNTHETIC_ERRNO(ESRCH), - "%s: no names found", pretty); + if (reply.n_names == 0) + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "%s: no names found", pretty); - print_source(flags, ts); + print_source(reply.flags, ts); return 0; } @@ -887,7 +864,7 @@ static int verb_query(int argc, char *argv[], uintptr_t _data, void *userdata) { r = in_addr_ifindex_from_string_auto(*p, &family, &a, &ifindex); if (r >= 0) - RET_GATHER(ret, resolve_address(bus, family, &a, ifindex)); + RET_GATHER(ret, resolve_address(family, &a, ifindex)); else RET_GATHER(ret, resolve_host(*p)); } diff --git a/src/shared/resolve-varlink-util.c b/src/shared/resolve-varlink-util.c index 3459cfc9d6e..877e298999a 100644 --- a/src/shared/resolve-varlink-util.c +++ b/src/shared/resolve-varlink-util.c @@ -105,3 +105,73 @@ int dispatch_resolve_hostname_reply(const char *name, sd_json_variant *variant, *ret = TAKE_STRUCT(reply); return 0; } + +static void resolved_name_done(ResolvedName *name) { + if (!name) + return; + + name->name = mfree(name->name); +} + +static int dispatch_resolved_name(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { + static const sd_json_dispatch_field resolved_name_dispatch_table[] = { + { "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_ifindex, offsetof(ResolvedName, ifindex), SD_JSON_RELAX }, + { "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(ResolvedName, name), SD_JSON_MANDATORY }, + {}, + }; + ResolvedName *ret = ASSERT_PTR(userdata); + int r; + + _cleanup_(resolved_name_done) ResolvedName resolved_name = {}; + r = sd_json_dispatch(variant, resolved_name_dispatch_table, flags & ~SD_JSON_MANDATORY, &resolved_name); + if (r < 0) + return r; + + *ret = TAKE_STRUCT(resolved_name); + return 0; +} + +static int dispatch_resolved_name_array(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { + ResolveAddressReply *reply = ASSERT_PTR(userdata); + int r; + + sd_json_variant *v; + JSON_VARIANT_ARRAY_FOREACH(v, variant) { + if (!GREEDY_REALLOC0(reply->names, reply->n_names + 1)) + return json_log_oom(variant, flags); + + r = dispatch_resolved_name(name, v, flags, &reply->names[reply->n_names++]); + if (r < 0) + return r; + } + + return 0; +} + +void resolve_address_reply_done(ResolveAddressReply *reply) { + if (!reply) + return; + + FOREACH_ARRAY(n, reply->names, reply->n_names) + resolved_name_done(n); + reply->names = mfree(reply->names); + reply->n_names = 0; +} + +int dispatch_resolve_address_reply(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { + static const sd_json_dispatch_field resolve_address_reply_dispatch_table[] = { + { "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(ResolveAddressReply, flags), SD_JSON_MANDATORY }, + { "names", SD_JSON_VARIANT_ARRAY, dispatch_resolved_name_array, 0, SD_JSON_MANDATORY }, + {}, + }; + ResolveAddressReply *ret = ASSERT_PTR(userdata); + int r; + + _cleanup_(resolve_address_reply_done) ResolveAddressReply reply = {}; + r = sd_json_dispatch(variant, resolve_address_reply_dispatch_table, flags | SD_JSON_ALLOW_EXTENSIONS, &reply); + if (r < 0) + return r; + + *ret = TAKE_STRUCT(reply); + return 0; +} diff --git a/src/shared/resolve-varlink-util.h b/src/shared/resolve-varlink-util.h index 4e94fbe8c64..9fbc8a1492b 100644 --- a/src/shared/resolve-varlink-util.h +++ b/src/shared/resolve-varlink-util.h @@ -32,3 +32,18 @@ typedef struct ResolveHostnameReply { void resolve_hostname_reply_done(ResolveHostnameReply *reply); int dispatch_resolve_hostname_reply(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); + +typedef struct ResolvedName { + int ifindex; + char *name; +} ResolvedName; + +typedef struct ResolveAddressReply { + uint64_t flags; + ResolvedName *names; + size_t n_names; +} ResolveAddressReply; + +void resolve_address_reply_done(ResolveAddressReply *reply); + +int dispatch_resolve_address_reply(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);