resolve-tool.c revision ba82da3bb547bb2db1b8637a4a9c4a8c69f7fb6d
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek This file is part of systemd.
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek Copyright 2014 Zbigniew Jędrzejewski-Szmek
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek systemd is free software; you can redistribute it and/or modify it
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek under the terms of the GNU Lesser General Public License as published by
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek the Free Software Foundation; either version 2.1 of the License, or
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek (at your option) any later version.
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek systemd is distributed in the hope that it will be useful, but
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek WITHOUT ANY WARRANTY; without even the implied warranty of
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek Lesser General Public License for more details.
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek You should have received a copy of the GNU Lesser General Public License
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek along with systemd; If not, see <http://www.gnu.org/licenses/>.
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic int arg_ifindex = 0;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic bool arg_legend = true;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic enum {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic void print_source(uint64_t flags, usec_t rtt) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek fputs("\n-- Information acquired via", stdout);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek flags & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4" : "",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek flags & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6" : "");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozekstatic int resolve_host(sd_bus *bus, const char *name) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek unsigned c = 0;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
a171d77f40aa92e240e91aa4bafe5a392a98b5a2Michal Zidek log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "org.freedesktop.resolve1",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "org.freedesktop.resolve1.Manager",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "ResolveHostname");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const void *a;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_read(reply, "ii", &ifindex, &family);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_read_array(reply, 'y', &a, &sz);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (ifindex > 0 && !if_indextoname(ifindex, ifname))
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return log_error_errno(r, "Failed to print address for %s: %m", name);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_read(reply, "st", &canonical, &flags);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (c == 0) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozekstatic int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek unsigned c = 0;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = in_addr_to_string(family, address, &pretty);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (ifindex > 0 && !if_indextoname(ifindex, ifname))
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "org.freedesktop.resolve1",
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek "org.freedesktop.resolve1.Manager",
1c383994ae898fa862f93c43501395bae6304f28Jakub Hrozek "ResolveAddress");
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_append(req, "ii", ifindex, family);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = sd_bus_message_append(req, "t", arg_flags);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (r < 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_enter_container(reply, 'a', "(is)");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *n;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_read(reply, "is", &ifindex, &n);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (ifindex > 0 && !if_indextoname(ifindex, ifname))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
1cde5866227feccf482f82c112c352c103afbc59Jakub Hrozek if (c == 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozekstatic int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *percent, *a;
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek r = in_addr_from_string_auto(a, family, address);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozekstatic int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek unsigned n = 0;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "org.freedesktop.resolve1",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "org.freedesktop.resolve1.Manager",
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek "ResolveRecord");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (r < 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
0a78bac242d0172a858d6b65402276aa734a4671Jakub Hrozek _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *s;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const void *d;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek r = sd_bus_message_read_array(reply, 'y', &d, &l);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek return log_error_errno(r, "Failed to parse RR: %m");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (ifindex > 0 && !if_indextoname(ifindex, ifname))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (n == 0) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozekstatic int resolve_rfc4501(sd_bus *bus, const char *name) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *p, *q, *n;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek /* Parse RFC 4501 dns: URIs */
c83ebdbc0629313ef6594215ed1674b9a783cfddJakub Hrozek if (p[0] == '/') {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek const char *e;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (e != p + 2)
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek log_warning("DNS authority specification not supported; ignoring specified authority.");
n = strndupa(p, q - p);
if (class != 0) {
return -EINVAL;
t = strndup(f, e - f);
return log_oom();
r = dns_class_from_string(t);
return -EINVAL;
class = r;
if (type != 0) {
return -EINVAL;
t = strndup(f, e - f);
return log_oom();
r = dns_type_from_string(t);
return -EINVAL;
type = r;
goto invalid;
if (type == 0)
if (type == 0)
if (class == 0)
if (class == 0)
return -EINVAL;
if (name)
log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
else if (type)
log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
bus,
&req,
"/org/freedesktop/resolve1",
return bus_log_create_error(r);
return bus_log_create_error(r);
return bus_log_parse_error(r);
indent =
return bus_log_parse_error(r);
if (name)
if (type)
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
return -EINVAL;
ifname[0] = 0;
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
return bus_log_parse_error(r);
if (!escaped)
return log_oom();
return bus_log_parse_error(r);
return bus_log_parse_error(r);
r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
return bus_log_parse_error(r);
if (canonical_name)
if (canonical_type)
int r, dnssec_supported;
"/org/freedesktop/resolve1",
&error,
return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
ansi_normal());
"/org/freedesktop/resolve1",
&error,
&reply,
return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
return bus_log_parse_error(r);
ansi_normal(),
"/org/freedesktop/resolve1",
&error,
&reply,
&n_cache_miss);
return bus_log_parse_error(r);
ansi_normal(),
"/org/freedesktop/resolve1",
&error,
&reply,
return bus_log_parse_error(r);
ansi_normal(),
"/org/freedesktop/resolve1",
&error,
NULL,
NULL);
static void help_protocol_types(void) {
if (arg_legend)
static void help_dns_types(void) {
if (arg_legend)
for (i = 0; i < _DNS_TYPE_MAX; i++) {
t = dns_type_to_string(i);
puts(t);
static void help_dns_classes(void) {
if (arg_legend)
for (i = 0; i < _DNS_CLASS_MAX; i++) {
t = dns_class_to_string(i);
puts(t);
static void help(void) {
help();
case ARG_VERSION:
return version();
int ifi;
if (ifi <= 0)
case ARG_LEGEND:
arg_legend = r;
return -EINVAL;
case ARG_SERVICE:
case ARG_CNAME:
case ARG_SERVICE_ADDRESS:
case ARG_SERVICE_TXT:
case ARG_SEARCH:
case ARG_STATISTICS:
case ARG_RESET_STATISTICS:
return -EINVAL;
return -EINVAL;
return -EINVAL;
log_open();
goto finish;
goto finish;
switch (arg_mode) {
case MODE_RESOLVE_HOST:
r = -EINVAL;
goto finish;
union in_addr_union a;
optind++;
case MODE_RESOLVE_RECORD:
r = -EINVAL;
goto finish;
optind++;
case MODE_RESOLVE_SERVICE:
r = -EINVAL;
goto finish;
r = -EINVAL;
goto finish;
case MODE_STATISTICS:
r = -EINVAL;
goto finish;
case MODE_RESET_STATISTICS:
r = -EINVAL;
goto finish;