From: Lennart Poettering Date: Wed, 31 Jan 2024 10:28:12 +0000 (+0100) Subject: resolvectl: add JSON output support for "resolvectl query" X-Git-Tag: v256-rc1~1000^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3557f1a62a487c0be080f2de866637a7895698c2;p=thirdparty%2Fsystemd.git 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 --- diff --git a/man/resolvectl.xml b/man/resolvectl.xml index 3babb8afc21..dada3f51d72 100644 --- a/man/resolvectl.xml +++ b/man/resolvectl.xml @@ -69,6 +69,9 @@ / is used IDNA translation is turned off and domain names are processed as specified. + If combined with (only supported in combination with + ) will output the resource record data in a JSON object. + @@ -478,15 +481,7 @@ - - - - - Short for - - - - + diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index fcc8eb7bdc9..56ba992c4f9 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -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++; diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index 92f6b8e030d..818a23736d5 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -821,6 +821,9 @@ run resolvectl reset-statistics --json=pretty run resolvectl reset-statistics --json=short +test "$(resolvectl --json=short query -t AAAA localhost)" == '{"key":{"class":1,"type":28,"name":"localhost"},"address":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]}' +test "$(resolvectl --json=short query -t A localhost)" == '{"key":{"class":1,"type":1,"name":"localhost"},"address":[127,0,0,1]}' + # Check if resolved exits cleanly. restart_resolved