resolvectl: use varlink instead of dbus for ResolveAddress
This commit is contained in:
+40
-63
@@ -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");
|
||||
_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;
|
||||
|
||||
r = sd_bus_message_append(req, "ii", ifindex, family);
|
||||
usec_t ts = now(CLOCK_MONOTONIC);
|
||||
|
||||
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 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);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
ts = now(CLOCK_MONOTONIC);
|
||||
|
||||
r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
|
||||
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 (!isempty(error_id))
|
||||
return varlink_log_resolve_error(pretty, error_id, v);
|
||||
|
||||
_cleanup_(resolve_address_reply_done) ResolveAddressReply reply = {};
|
||||
r = dispatch_resolve_address_reply(/* name = */ NULL, v, SD_JSON_LOG, &reply);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
|
||||
const char *n;
|
||||
int k;
|
||||
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());
|
||||
|
||||
assert_cc(sizeof(int) == sizeof(int32_t));
|
||||
|
||||
r = sd_bus_message_read(reply, "is", &ifindex, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(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());
|
||||
|
||||
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);
|
||||
if (reply.n_names == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "%s: no names found", pretty);
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user