]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolvectl: use varlink instead of dbus for ResolveAddress
authorNick Rosbrook <enr0n@ubuntu.com>
Fri, 19 Jun 2026 19:01:01 +0000 (15:01 -0400)
committerNick Rosbrook <enr0n@ubuntu.com>
Fri, 26 Jun 2026 20:03:18 +0000 (16:03 -0400)
src/resolve/resolvectl.c
src/shared/resolve-varlink-util.c
src/shared/resolve-varlink-util.h

index 4baa2f38681447e940f0163489c99f19af65a099..2cfd5855649ddd01d2240f43b0f337a78ce97e9e 100644 (file)
@@ -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));
                         }
index 3459cfc9d6e3e030e01093d5b8c4904c15dfafa4..877e298999a05d4d279e8f6c7735ba415afce6d6 100644 (file)
@@ -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;
+}
index 4e94fbe8c6450c1b7797686498364b930e6330d3..9fbc8a1492bbfb479c7cc08467fb26ee8ad99560 100644 (file)
@@ -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);