resolvectl: add JSON output support for "resolvectl query"

It's easy to add. Let's do so.

This only covers record lookups, i.e. with the --type= switch.

The higher level lookups are not covered, I opted instead to print a
message there to use --type= instead.

I am a bit reluctant to defining a new JSON format for the high-level
lookups, hence I figured for now a helpful error is good enough, that
points people to the right use.

Fixes: #29755
This commit is contained in:
Lennart Poettering
2024-01-31 16:13:16 +01:00
parent 1d556e9e2a
commit 3557f1a62a
3 changed files with 38 additions and 10 deletions
+31 -1
View File
@@ -184,6 +184,9 @@ static void print_source(uint64_t flags, usec_t rtt) {
if (!arg_legend)
return;
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return;
if (flags == 0)
return;
@@ -250,6 +253,9 @@ static int resolve_host(sd_bus *bus, const char *name) {
assert(name);
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type=A or --type=AAAA to acquire address record information in JSON format.");
log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname);
r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname");
@@ -348,6 +354,9 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
assert(IN_SET(family, AF_INET, AF_INET6));
assert(address);
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
if (ifindex <= 0)
ifindex = arg_ifindex;
@@ -433,11 +442,23 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
int r;
assert(d || l == 0);
r = dns_resource_record_new_from_raw(&rr, d, l);
if (r < 0)
return log_error_errno(r, "Failed to parse RR: %m");
if (arg_raw == RAW_PAYLOAD) {
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) {
_cleanup_(json_variant_unrefp) JsonVariant *j = NULL;
r = dns_resource_record_to_json(rr, &j);
if (r < 0)
return log_error_errno(r, "Failed to convert RR to JSON: %m");
r = json_variant_dump(j, arg_json_format_flags, NULL, NULL);
if (r < 0)
return r;
} else if (arg_raw == RAW_PAYLOAD) {
void *data;
ssize_t k;
@@ -946,6 +967,9 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons
static int verb_service(int argc, char **argv, void *userdata) {
sd_bus *bus = userdata;
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
if (argc == 2)
return resolve_service(bus, NULL, NULL, argv[1]);
else if (argc == 3)
@@ -1005,6 +1029,9 @@ static int verb_openpgp(int argc, char **argv, void *userdata) {
sd_bus *bus = userdata;
int q, r = 0;
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
STRV_FOREACH(p, argv + 1) {
q = resolve_openpgp(bus, *p);
if (q < 0)
@@ -1056,6 +1083,9 @@ static int verb_tlsa(int argc, char **argv, void *userdata) {
const char *family = "tcp";
int q, r = 0;
if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Use --json=pretty with --type= to acquire resource record information in JSON format.");
if (service_family_is_valid(argv[1])) {
family = argv[1];
args++;