From 2e74028a5cf636760191656d7fabfa9f43db96e2 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 28 Jan 2016 18:24:28 -0500 Subject: systemd-resolve: allow keys to be dumped in binary form $ systemd-resolve --raw --openpgp zbyszek@fedoraproject.org | pgpdump /dev/stdin --- src/resolve/resolve-tool.c | 40 +++++++++++++++++++++++++++++++++------- src/resolve/resolved-dns-rr.c | 38 ++++++++++++++++++++++++++++++++++++++ src/resolve/resolved-dns-rr.h | 2 ++ 3 files changed, 73 insertions(+), 7 deletions(-) (limited to 'src/resolve') diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index ed9b0353cc..a24bb546d4 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -43,6 +43,7 @@ static uint16_t arg_type = 0; static uint16_t arg_class = 0; static bool arg_legend = true; static uint64_t arg_flags = 0; +static bool arg_raw = false; static enum { MODE_RESOLVE_HOST, @@ -379,7 +380,6 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; - const char *s; uint16_t c, t; int ifindex; const void *d; @@ -413,13 +413,27 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ if (r < 0) return log_error_errno(r, "Failed to parse RR: %m"); - s = dns_resource_record_to_string(rr); - if (!s) - return log_oom(); + if (arg_raw) { + void *data; + ssize_t k; - ifname[0] = 0; - if (ifindex > 0 && !if_indextoname(ifindex, ifname)) - log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); + k = dns_resource_record_payload(rr, &data); + if (k < 0) + return log_error_errno(k, "Cannot dump RR: %m"); + fwrite(data, 1, k, stdout); + } else { + const char *s; + + s = dns_resource_record_to_string(rr); + if (!s) + return log_oom(); + + ifname[0] = 0; + if (ifindex > 0 && !if_indextoname(ifindex, ifname)) + log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex); + + printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname); + } printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname); @@ -1013,6 +1027,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SERVICE_ADDRESS, ARG_SERVICE_TXT, ARG_OPENPGP, + ARG_RAW, ARG_SEARCH, ARG_STATISTICS, ARG_RESET_STATISTICS, @@ -1031,6 +1046,7 @@ static int parse_argv(int argc, char *argv[]) { { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS }, { "service-txt", required_argument, NULL, ARG_SERVICE_TXT }, { "openpgp", no_argument, NULL, ARG_OPENPGP }, + { "raw", no_argument, NULL, ARG_RAW }, { "search", required_argument, NULL, ARG_SEARCH }, { "statistics", no_argument, NULL, ARG_STATISTICS, }, { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS }, @@ -1144,6 +1160,16 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = MODE_RESOLVE_OPENPGP; break; + case ARG_RAW: + if (on_tty()) { + log_error("Refusing to write binary data to tty."); + return -ENOTTY; + } + + arg_raw = true; + arg_legend = false; + break; + case ARG_CNAME: r = parse_boolean(optarg); if (r < 0) diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 6397005a68..919a0d3c2c 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1204,6 +1204,44 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) { return s; } +ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) { + assert(rr); + assert(out); + + switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + case DNS_TYPE_SRV: + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + case DNS_TYPE_HINFO: + case DNS_TYPE_SPF: + case DNS_TYPE_TXT: + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_SOA: + case DNS_TYPE_MX: + case DNS_TYPE_LOC: + case DNS_TYPE_DS: + case DNS_TYPE_SSHFP: + case DNS_TYPE_DNSKEY: + case DNS_TYPE_RRSIG: + case DNS_TYPE_NSEC: + case DNS_TYPE_NSEC3: + return -EINVAL; + + case DNS_TYPE_TLSA: + *out = rr->tlsa.data; + return rr->tlsa.data_size; + + + case DNS_TYPE_OPENPGPKEY: + default: + *out = rr->generic.data; + return rr->generic.data_size; + } +} + int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) { DnsPacket packet = { diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index 23749790b4..964bf7e77a 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -303,6 +303,8 @@ int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain); int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa); int dns_resource_key_to_string(const DnsResourceKey *key, char **ret); +ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out); + DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref); static inline bool dns_key_is_shared(const DnsResourceKey *key) { -- cgit v1.2.3-54-g00ecf