Merge pull request #2640 from keszybz/dnssec-work-3

resolve: dumping of binary packets
This commit is contained in:
Lennart Poettering 2016-02-17 12:45:31 +01:00
commit 5031c4e21b
23 changed files with 778 additions and 619 deletions

View File

@ -65,7 +65,7 @@
<command>systemd-resolve</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<command> --type=<replaceable>TYPE</replaceable></command>
<arg choice="plain" rep="repeat"><replaceable>RRDOMAIN</replaceable></arg>
<arg choice="plain" rep="repeat"><replaceable>DOMAIN</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
@ -232,6 +232,16 @@
logic is disabled.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--raw</option><optional>=payload|packet</optional></term>
<listitem><para>Dump the answer as binary data. If there is no argument or if the argument is
<literal>payload</literal>, the payload of the packet is exported. If the argument is
<literal>packet</literal>, the whole packet is dumped in wire format, prefixed by
length specified as a little-endian 64-bit number. This format allows multiple packets
to be dumped and unambigously parsed.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--legend=</option><replaceable>BOOL</replaceable></term>
@ -263,27 +273,58 @@
<example>
<title>Retrieve the addresses of the <literal>www.0pointer.net</literal> domain</title>
<programlisting>$ systemd-resolve www.0pointer.net</programlisting>
<programlisting>$ systemd-resolve www.0pointer.net
www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
85.214.157.71
-- Information acquired via protocol DNS in 611.6ms.
-- Data is authenticated: no
</programlisting>
</example>
<example>
<title>Retrieve the domain of the <literal>85.214.157.71</literal> IP address</title>
<programlisting>$ systemd-resolve 85.214.157.71</programlisting>
<programlisting>$ systemd-resolve 85.214.157.71
85.214.157.71: gardel.0pointer.net
-- Information acquired via protocol DNS in 1.2997s.
-- Data is authenticated: no
</programlisting>
</example>
<example>
<title>Retrieve the MX record of the <literal>0pointer.net</literal> domain</title>
<programlisting>$ systemd-resolve -t MX 0pointer.net</programlisting>
<programlisting>$ systemd-resolve -t MX yahoo.com --legend=no
yahoo.com. IN MX 1 mta7.am0.yahoodns.net
yahoo.com. IN MX 1 mta6.am0.yahoodns.net
yahoo.com. IN MX 1 mta5.am0.yahoodns.net
</programlisting>
</example>
<example>
<title>Resolve an SRV service</title>
<programlisting>$ systemd-resolve --service _xmpp-server._tcp gmail.com</programlisting>
<programlisting>$ systemd-resolve --service _xmpp-server._tcp gmail.com
_xmpp-server._tcp/gmail.com: alt1.xmpp-server.l.google.com:5269 [priority=20, weight=0]
173.194.210.125
alt4.xmpp-server.l.google.com:5269 [priority=20, weight=0]
173.194.65.125
...
</programlisting>
</example>
<example>
<title>Retrieve a PGP key</title>
<programlisting>$ systemd-resolve --openpgp zbyszek@fedoraproject.org
d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org. IN OPENPGPKEY
mQINBFBHPMsBEACeInGYJCb+7TurKfb6wGyTottCDtiSJB310i37/6ZYoeIay/5soJjlMyf
MFQ9T2XNT/0LM6gTa0MpC1st9LnzYTMsT6tzRly1D1UbVI6xw0g0vE5y2Cjk3xUwAynCsSs
...
</programlisting>
</example>
</refsect1>
<refsect1>

View File

@ -19,7 +19,23 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "string-util.h"
const char *af_to_name(int id);
int af_from_name(const char *name);
static inline const char* af_to_name_short(int id) {
const char *f;
if (id == AF_UNSPEC)
return "*";
f = af_to_name(id);
if (!f)
return "unknown";
assert(startswith(f, "AF_"));
return f + 3;
}
int af_max(void);

View File

@ -124,6 +124,9 @@ enum {
_DNS_CLASS_INVALID = -1
};
#define _DNS_CLASS_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t))
#define _DNS_TYPE_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t))
bool dns_type_is_pseudo(uint16_t type);
bool dns_type_is_valid_query(uint16_t type);
bool dns_type_is_valid_rr(uint16_t type);
@ -133,7 +136,7 @@ bool dns_type_is_obsolete(uint16_t type);
bool dns_type_may_wildcard(uint16_t type);
bool dns_type_apex_only(uint16_t type);
bool dns_type_needs_authentication(uint16_t type);
int dns_type_to_af(uint16_t t);
int dns_type_to_af(uint16_t type);
bool dns_class_is_pseudo(uint16_t class);
bool dns_class_is_valid_rr(uint16_t class);
@ -142,7 +145,7 @@ bool dns_class_is_valid_rr(uint16_t class);
const char *dns_type_to_string(int type);
int dns_type_from_string(const char *s);
const char *dns_class_to_string(uint16_t type);
const char *dns_class_to_string(uint16_t class);
int dns_class_from_string(const char *name);
/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */

View File

@ -44,6 +44,14 @@ static uint16_t arg_class = 0;
static bool arg_legend = true;
static uint64_t arg_flags = 0;
typedef enum RawType {
RAW_NONE,
RAW_PAYLOAD,
RAW_PACKET,
} RawType;
static RawType arg_raw = RAW_NONE;
static enum {
MODE_RESOLVE_HOST,
MODE_RESOLVE_RECORD,
@ -331,6 +339,50 @@ static int parse_address(const char *s, int *family, union in_addr_union *addres
return 0;
}
static int output_rr_packet(const void *d, size_t l, int ifindex) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
int r;
char ifname[IF_NAMESIZE] = "";
r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
if (r < 0)
return log_oom();
p->refuse_compression = true;
r = dns_packet_append_blob(p, d, l, NULL);
if (r < 0)
return log_oom();
r = dns_packet_read_rr(p, &rr, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse RR: %m");
if (arg_raw == RAW_PAYLOAD) {
void *data;
ssize_t k;
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();
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);
}
return 0;
}
static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) {
_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;
@ -377,9 +429,6 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_
return bus_log_parse_error(r);
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;
@ -399,29 +448,16 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_
if (r < 0)
return bus_log_parse_error(r);
r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
if (r < 0)
return log_oom();
if (arg_raw == RAW_PACKET) {
uint64_t u64 = htole64(l);
p->refuse_compression = true;
r = dns_packet_append_blob(p, d, l, NULL);
if (r < 0)
return log_oom();
r = dns_packet_read_rr(p, &rr, NULL, NULL);
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();
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);
fwrite(&u64, sizeof(u64), 1, stdout);
fwrite(d, 1, l, stdout);
} else {
r = output_rr_packet(d, l, ifindex);
if (r < 0)
return r;
}
if (dns_type_needs_authentication(t))
needs_authentication = true;
@ -976,27 +1012,33 @@ static void help_dns_classes(void) {
}
static void help(void) {
printf("%s [OPTIONS...] NAME...\n"
"%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n"
printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
"%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
"%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
"%1$s [OPTIONS...] --statistics\n"
"%1$s [OPTIONS...] --reset-statistics\n"
"\n"
"Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" -4 Resolve IPv4 addresses\n"
" -6 Resolve IPv6 addresses\n"
" -i --interface=INTERFACE Look on interface\n"
" -p --protocol=PROTOCOL|help Look via protocol\n"
" -t --type=TYPE|help Query RR with DNS type\n"
" -c --class=CLASS|help Query RR with DNS class\n"
" --service Resolve service (SRV)\n"
" --service-address=BOOL Do [not] resolve address for services\n"
" --service-txt=BOOL Do [not] resolve TXT records for services\n"
" --openpgp Query OpenPGP public key\n"
" --cname=BOOL Do [not] follow CNAME redirects\n"
" --search=BOOL Do [not] use search domains\n"
" --legend=BOOL Do [not] print column headers and meta information\n"
" --statistics Show resolver statistics\n"
" --reset-statistics Reset resolver statistics\n"
, program_invocation_short_name, program_invocation_short_name);
" -h --help Show this help\n"
" --version Show package version\n"
" -4 Resolve IPv4 addresses\n"
" -6 Resolve IPv6 addresses\n"
" -i --interface=INTERFACE Look on interface\n"
" -p --protocol=PROTO|help Look via protocol\n"
" -t --type=TYPE|help Query RR with DNS type\n"
" -c --class=CLASS|help Query RR with DNS class\n"
" --service Resolve service (SRV)\n"
" --service-address=BOOL Resolve address for services (default: yes)\n"
" --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
" --openpgp Query OpenPGP public key\n"
" --cname=BOOL Follow CNAME redirects (default: yes)\n"
" --search=BOOL Use search domains for single-label names\n"
" (default: yes)\n"
" --raw[=payload|packet] Dump the answer as binary data\n"
" --legend=BOOL Print headers and additional info (default: yes)\n"
" --statistics Show resolver statistics\n"
" --reset-statistics Reset resolver statistics\n"
, program_invocation_short_name);
}
static int parse_argv(int argc, char *argv[]) {
@ -1008,6 +1050,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,
@ -1026,6 +1069,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", optional_argument, NULL, ARG_RAW },
{ "search", required_argument, NULL, ARG_SEARCH },
{ "statistics", no_argument, NULL, ARG_STATISTICS, },
{ "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
@ -1139,6 +1183,24 @@ 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;
}
if (optarg == NULL || streq(optarg, "payload"))
arg_raw = RAW_PAYLOAD;
else if (streq(optarg, "packet"))
arg_raw = RAW_PACKET;
else {
log_error("Unknown --raw specifier \"%s\".", optarg);
return -EINVAL;
}
arg_legend = false;
break;
case ARG_CNAME:
r = parse_boolean(optarg);
if (r < 0)

View File

@ -202,7 +202,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
/* The key names are not necessarily normalized, make sure that they are when we return them to our bus
* clients. */
r = dns_name_normalize(DNS_RESOURCE_KEY_NAME(canonical->key), &normalized);
r = dns_name_normalize(dns_resource_key_name(canonical->key), &normalized);
if (r < 0)
goto finish;
@ -797,7 +797,7 @@ static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr)
if (canonical) {
normalized = mfree(normalized);
r = dns_name_normalize(DNS_RESOURCE_KEY_NAME(canonical->key), &normalized);
r = dns_name_normalize(dns_resource_key_name(canonical->key), &normalized);
if (r < 0)
return r;
}
@ -959,7 +959,7 @@ static void resolve_service_all_complete(DnsQuery *q) {
goto finish;
assert(canonical);
r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain);
if (r < 0)
goto finish;

View File

@ -330,7 +330,7 @@ int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) {
if (rr->key->type != DNS_TYPE_NSEC3)
continue;
p = DNS_RESOURCE_KEY_NAME(rr->key);
p = dns_resource_key_name(rr->key);
r = dns_name_parent(&p);
if (r < 0)
return r;
@ -363,7 +363,7 @@ int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceReco
if (r > 0) {
if (soa) {
r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(soa->key));
r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key));
if (r < 0)
return r;
if (r > 0)
@ -840,13 +840,13 @@ bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) {
if (rr->key->class != cname->key->class)
continue;
r = dns_name_change_suffix(cname->cname.name, rr->dname.name, DNS_RESOURCE_KEY_NAME(rr->key), &n);
r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n);
if (r < 0)
return r;
if (r == 0)
continue;
r = dns_name_equal(n, DNS_RESOURCE_KEY_NAME(cname->key));
r = dns_name_equal(n, dns_resource_key_name(cname->key));
if (r < 0)
return r;
if (r > 0)

View File

@ -17,6 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <net/if.h>
#include "af-list.h"
#include "alloc-util.h"
#include "dns-domain.h"
#include "resolved-dns-answer.h"
@ -180,6 +183,7 @@ void dns_cache_prune(DnsCache *c) {
for (;;) {
DnsCacheItem *i;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
i = prioq_peek(c->by_expiry);
if (!i)
@ -192,8 +196,12 @@ void dns_cache_prune(DnsCache *c) {
break;
/* Depending whether this is an mDNS shared entry
* either remove only this one RR or the whole
* RRset */
* either remove only this one RR or the whole RRset */
log_debug("Removing %scache entry for %s (expired "USEC_FMT"s ago)",
i->shared_owner ? "shared " : "",
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
(t - i->until) / USEC_PER_SEC);
if (i->shared_owner)
dns_cache_item_unlink_and_free(c, i);
else {
@ -375,8 +383,8 @@ static int dns_cache_put_positive(
const union in_addr_union *owner_address) {
_cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
_cleanup_free_ char *key_str = NULL;
DnsCacheItem *existing;
char key_str[DNS_RESOURCE_KEY_STRING_MAX], ifname[IF_NAMESIZE];
int r, k;
assert(c);
@ -392,18 +400,9 @@ static int dns_cache_put_positive(
/* New TTL is 0? Delete this specific entry... */
if (rr->ttl <= 0) {
k = dns_cache_remove_by_rr(c, rr);
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(rr->key, &key_str);
if (r < 0)
return r;
if (k > 0)
log_debug("Removed zero TTL entry from cache: %s", key_str);
else
log_debug("Not caching zero TTL cache entry: %s", key_str);
}
log_debug("%s: %s",
k > 0 ? "Removed zero TTL entry from cache" : "Not caching zero TTL cache entry",
dns_resource_key_to_string(i->key, key_str, sizeof key_str));
return 0;
}
@ -450,11 +449,18 @@ static int dns_cache_put_positive(
return r;
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(i->key, &key_str);
if (r < 0)
return r;
_cleanup_free_ char *t = NULL;
log_debug("Added positive cache entry for %s", key_str);
(void) in_addr_to_string(i->owner_family, &i->owner_address, &t);
log_debug("Added positive %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
i->authenticated ? "authenticated" : "unauthenticated",
i->shared_owner ? " shared" : "",
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
(i->until - timestamp) / USEC_PER_SEC,
i->ifindex == 0 ? "*" : strna(if_indextoname(i->ifindex, ifname)),
af_to_name_short(i->owner_family),
strna(t));
}
i = NULL;
@ -473,7 +479,7 @@ static int dns_cache_put_negative(
const union in_addr_union *owner_address) {
_cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
_cleanup_free_ char *key_str = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
int r;
assert(c);
@ -490,14 +496,8 @@ static int dns_cache_put_negative(
return 0;
if (nsec_ttl <= 0 || soa->soa.minimum <= 0 || soa->ttl <= 0) {
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s", key_str);
}
log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s",
dns_resource_key_to_string(i->key, key_str, sizeof key_str));
return 0;
}
@ -524,7 +524,7 @@ static int dns_cache_put_negative(
if (i->type == DNS_CACHE_NXDOMAIN) {
/* NXDOMAIN entries should apply equally to all types, so we use ANY as
* a pseudo type for this purpose here. */
i->key = dns_resource_key_new(key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(key));
i->key = dns_resource_key_new(key->class, DNS_TYPE_ANY, dns_resource_key_name(key));
if (!i->key)
return -ENOMEM;
@ -542,13 +542,10 @@ static int dns_cache_put_negative(
if (r < 0)
return r;
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(i->key, &key_str);
if (r < 0)
return r;
log_debug("Added %s cache entry for %s", i->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", key_str);
}
log_debug("Added %s cache entry for %s "USEC_FMT"s",
i->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN",
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
(i->until - timestamp) / USEC_PER_SEC);
i = NULL;
return 0;
@ -628,16 +625,10 @@ int dns_cache_put(
dns_cache_remove_previous(c, key, answer);
if (dns_answer_size(answer) <= 0) {
if (log_get_max_level() >= LOG_DEBUG) {
_cleanup_free_ char *key_str = NULL;
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("Not caching negative entry without a SOA record: %s", key_str);
}
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
log_debug("Not caching negative entry without a SOA record: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
return 0;
}
@ -759,7 +750,7 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
if (i)
return i;
n = DNS_RESOURCE_KEY_NAME(k);
n = dns_resource_key_name(k);
/* Check if we have an NXDOMAIN cache item for the name, notice that we use
* the pseudo-type ANY for NXDOMAIN cache items. */
@ -801,10 +792,10 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **ret, bool *authenticated) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
unsigned n = 0;
int r;
bool nxdomain = false;
_cleanup_free_ char *key_str = NULL;
DnsCacheItem *j, *first, *nsec = NULL;
bool have_authenticated = false, have_non_authenticated = false;
@ -814,19 +805,12 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
assert(ret);
assert(authenticated);
if (key->type == DNS_TYPE_ANY ||
key->class == DNS_CLASS_ANY) {
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
/* If we have ANY lookups we don't use the cache, so
* that the caller refreshes via the network. */
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("Ignoring cache for ANY lookup: %s", key_str);
}
log_debug("Ignoring cache for ANY lookup: %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
c->n_miss++;
@ -839,13 +823,8 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
if (!first) {
/* If one question cannot be answered we need to refresh */
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("Cache miss for %s", key_str);
}
log_debug("Cache miss for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
c->n_miss++;
@ -873,13 +852,8 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
/* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from
* the lower-zone of a zone cut, but the DS RRs are on the upper zone. */
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("NSEC NODATA cache hit for %s", key_str);
}
log_debug("NSEC NODATA cache hit for %s",
dns_resource_key_to_string(key, key_str, sizeof key_str));
/* We only found an NSEC record that matches our name.
* If it says the type doesn't exist report
@ -900,16 +874,10 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
return 0;
}
if (log_get_max_level() >= LOG_DEBUG) {
r = dns_resource_key_to_string(key, &key_str);
if (r < 0)
return r;
log_debug("%s cache hit for %s",
n > 0 ? "Positive" :
nxdomain ? "NXDOMAIN" : "NODATA",
key_str);
}
log_debug("%s cache hit for %s",
n > 0 ? "Positive" :
nxdomain ? "NXDOMAIN" : "NODATA",
dns_resource_key_to_string(key, key_str, sizeof key_str));
if (n <= 0) {
c->n_hit++;
@ -1031,7 +999,6 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
void dns_cache_dump(DnsCache *cache, FILE *f) {
Iterator iterator;
DnsCacheItem *i;
int r;
if (!cache)
return;
@ -1057,14 +1024,9 @@ void dns_cache_dump(DnsCache *cache, FILE *f) {
fputs(t, f);
fputc('\n', f);
} else {
_cleanup_free_ char *z = NULL;
r = dns_resource_key_to_string(j->key, &z);
if (r < 0) {
log_oom();
continue;
}
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
fputs(z, f);
fputs(dns_resource_key_to_string(j->key, key_str, sizeof key_str), f);
fputs(" -- ", f);
fputs(j->type == DNS_CACHE_NODATA ? "NODATA" : "NXDOMAIN", f);
fputc('\n', f);

View File

@ -467,7 +467,7 @@ static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
return -EINVAL;
name = DNS_RESOURCE_KEY_NAME(rrsig->key);
name = dns_resource_key_name(rrsig->key);
n_key_labels = dns_name_count_labels(name);
if (n_key_labels < 0)
@ -651,7 +651,7 @@ int dnssec_verify_rrset(
return 0;
}
name = DNS_RESOURCE_KEY_NAME(key);
name = dns_resource_key_name(key);
/* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
@ -851,7 +851,7 @@ int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnske
if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
return 0;
return dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), rrsig->rrsig.signer);
return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer);
}
int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
@ -867,7 +867,7 @@ int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig)
if (rrsig->rrsig.type_covered != key->type)
return 0;
return dns_name_equal(DNS_RESOURCE_KEY_NAME(rrsig->key), DNS_RESOURCE_KEY_NAME(key));
return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key));
}
int dnssec_verify_rrset_search(
@ -1070,7 +1070,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
if (ds->ds.digest_size != hash_size)
return 0;
r = dnssec_canonicalize(DNS_RESOURCE_KEY_NAME(dnskey->key), owner_name, sizeof(owner_name));
r = dnssec_canonicalize(dns_resource_key_name(dnskey->key), owner_name, sizeof(owner_name));
if (r < 0)
return r;
@ -1120,7 +1120,7 @@ int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *vali
if (ds->key->class != dnskey->key->class)
continue;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(dnskey->key), DNS_RESOURCE_KEY_NAME(ds->key));
r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key));
if (r < 0)
return r;
if (r == 0)
@ -1272,14 +1272,14 @@ static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
return 0;
a = DNS_RESOURCE_KEY_NAME(rr->key);
a = dns_resource_key_name(rr->key);
r = dns_name_parent(&a); /* strip off hash */
if (r < 0)
return r;
if (r == 0)
return 0;
b = DNS_RESOURCE_KEY_NAME(nsec3->key);
b = dns_resource_key_name(nsec3->key);
r = dns_name_parent(&b); /* strip off hash */
if (r < 0)
return r;
@ -1353,7 +1353,7 @@ static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecR
* any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
* records from a given zone in a response must use the same
* parameters. */
zone = DNS_RESOURCE_KEY_NAME(key);
zone = dns_resource_key_name(key);
for (;;) {
DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
r = nsec3_is_good(zone_rr, NULL);
@ -1362,7 +1362,7 @@ static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecR
if (r == 0)
continue;
r = dns_name_equal_skip(DNS_RESOURCE_KEY_NAME(zone_rr->key), 1, zone);
r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone);
if (r < 0)
return r;
if (r > 0)
@ -1382,7 +1382,7 @@ static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecR
found_zone:
/* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
p = DNS_RESOURCE_KEY_NAME(key);
p = dns_resource_key_name(key);
for (;;) {
_cleanup_free_ char *hashed_domain = NULL;
@ -1405,7 +1405,7 @@ found_zone:
if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
continue;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(enclosure_rr->key), hashed_domain);
r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain);
if (r < 0)
return r;
if (r > 0) {
@ -1504,7 +1504,7 @@ found_closest_encloser:
if (r < 0)
return r;
r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), next_closer_domain, next_hashed_domain);
r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain);
if (r < 0)
return r;
if (r > 0) {
@ -1516,7 +1516,7 @@ found_closest_encloser:
no_closer = true;
}
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain);
r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain);
if (r < 0)
return r;
if (r > 0) {
@ -1525,7 +1525,7 @@ found_closest_encloser:
wildcard_rr = rr;
}
r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wildcard_domain, next_hashed_domain);
r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain);
if (r < 0)
return r;
if (r > 0) {
@ -1604,7 +1604,7 @@ static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
if (rr->n_skip_labels_source != 1)
return 0;
n = DNS_RESOURCE_KEY_NAME(rr->key);
n = dns_resource_key_name(rr->key);
r = dns_label_unescape(&n, label, sizeof(label));
if (r <= 0)
return r;
@ -1643,7 +1643,7 @@ static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
return r;
/* If the name we we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */
r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
if (r < 0)
return r;
@ -1662,7 +1662,7 @@ static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name)
if (r <= 0)
return r;
r = dns_name_equal(name, DNS_RESOURCE_KEY_NAME(rr->key));
r = dns_name_equal(name, dns_resource_key_name(rr->key));
if (r <= 0)
return r;
@ -1685,7 +1685,7 @@ static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
/* Checks whether the "Next Closer" is witin the space covered by the specified RR. */
r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
if (r < 0)
return r;
@ -1706,7 +1706,7 @@ static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
/* p is now the "Next Closer". */
return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), p, rr->nsec.next_domain_name);
return dns_name_between(dns_resource_key_name(rr->key), p, rr->nsec.next_domain_name);
}
static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) {
@ -1725,7 +1725,7 @@ static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name)
* NSEC yyy.zzz.xoo.bar bar: indicates that a number of wildcards don#t exist either...
*/
r = dns_name_common_suffix(DNS_RESOURCE_KEY_NAME(rr->key), rr->nsec.next_domain_name, &common_suffix);
r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
if (r < 0)
return r;
@ -1735,7 +1735,7 @@ static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name)
return r;
wc = strjoina("*.", common_suffix, NULL);
return dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), wc, rr->nsec.next_domain_name);
return dns_name_between(dns_resource_key_name(rr->key), wc, rr->nsec.next_domain_name);
}
int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
@ -1750,7 +1750,7 @@ int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
/* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
name = DNS_RESOURCE_KEY_NAME(key);
name = dns_resource_key_name(key);
DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
@ -1770,7 +1770,7 @@ int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r
continue;
/* Check if this is a direct match. If so, we have encountered a NODATA case */
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), name);
r = dns_name_equal(dns_resource_key_name(rr->key), name);
if (r < 0)
return r;
if (r == 0) {
@ -1900,7 +1900,7 @@ static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const cha
if (r == 0)
continue;
r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), name, rr->nsec.next_domain_name);
r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
if (r < 0)
return r;
@ -1943,7 +1943,7 @@ static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const cha
if (r < 0)
return r;
r = dns_name_between(DNS_RESOURCE_KEY_NAME(rr->key), hashed_domain, next_hashed_domain);
r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain);
if (r < 0)
return r;

View File

@ -577,7 +577,7 @@ int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start)
saved_size = p->size;
r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL);
r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL);
if (r < 0)
goto fail;
@ -2130,7 +2130,7 @@ int dns_packet_extract(DnsPacket *p) {
continue;
}
if (!dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key))) {
if (!dns_name_is_root(dns_resource_key_name(rr->key))) {
/* If the OPT RR is not owned by the root domain, then it is bad, let's ignore
* it. */
log_debug("OPT RR is not owned by root domain, ignoring.");

View File

@ -421,6 +421,7 @@ int dns_query_new(
DnsResourceKey *key;
bool good = false;
int r;
char key_str[DNS_RESOURCE_KEY_STRING_MAX];
assert(m);
@ -471,31 +472,20 @@ int dns_query_new(
q->answer_family = AF_UNSPEC;
/* First dump UTF8 question */
DNS_QUESTION_FOREACH(key, question_utf8) {
_cleanup_free_ char *p = NULL;
r = dns_resource_key_to_string(key, &p);
if (r < 0)
return r;
log_debug("Looking up RR for %s.", strstrip(p));
}
DNS_QUESTION_FOREACH(key, question_utf8)
log_debug("Looking up RR for %s.",
dns_resource_key_to_string(key, key_str, sizeof key_str));
/* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */
DNS_QUESTION_FOREACH(key, question_idna) {
_cleanup_free_ char *p = NULL;
r = dns_question_contains(question_utf8, key);
if (r < 0)
return r;
if (r > 0)
continue;
r = dns_resource_key_to_string(key, &p);
if (r < 0)
return r;
log_debug("Looking up IDNA RR for %s.", strstrip(p));
log_debug("Looking up IDNA RR for %s.",
dns_resource_key_to_string(key, key_str, sizeof key_str));
}
LIST_PREPEND(queries, m->dns_queries, q);

View File

@ -145,7 +145,7 @@ int dns_question_is_valid_for_query(DnsQuestion *q) {
if (q->n_keys > 65535)
return 0;
name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
name = dns_resource_key_name(q->keys[0]);
if (!name)
return 0;
@ -154,7 +154,7 @@ int dns_question_is_valid_for_query(DnsQuestion *q) {
assert(q->keys[i]);
if (i > 0) {
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
r = dns_name_equal(dns_resource_key_name(q->keys[i]), name);
if (r <= 0)
return r;
}
@ -235,7 +235,7 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
if (cname->key->type == DNS_TYPE_CNAME)
d = cname->cname.name;
else {
r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
if (r < 0)
return r;
if (r == 0)
@ -244,7 +244,7 @@ int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname,
d = destination;
}
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), d);
r = dns_name_equal(dns_resource_key_name(key), d);
if (r < 0)
return r;
@ -291,7 +291,7 @@ const char *dns_question_first_name(DnsQuestion *q) {
if (q->n_keys < 1)
return NULL;
return DNS_RESOURCE_KEY_NAME(q->keys[0]);
return dns_resource_key_name(q->keys[0]);
}
int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) {

View File

@ -66,7 +66,7 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D
DnsResourceKey *k;
char *destination = NULL;
r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
if (r < 0)
return NULL;
if (r == 0)
@ -96,7 +96,7 @@ int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key
return 0;
}
r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), name, &joined);
r = dns_name_concat(dns_resource_key_name(key), name, &joined);
if (r < 0)
return r;
@ -158,6 +158,23 @@ DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
return NULL;
}
const char* dns_resource_key_name(const DnsResourceKey *key) {
const char *name;
if (!key)
return NULL;
if (key->_name)
name = key->_name;
else
name = (char*) key + sizeof(DnsResourceKey);
if (dns_name_is_root(name))
return ".";
else
return name;
}
bool dns_resource_key_is_address(const DnsResourceKey *key) {
assert(key);
@ -172,7 +189,7 @@ int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
if (a == b)
return 1;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b));
if (r <= 0)
return r;
@ -204,18 +221,18 @@ int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr,
if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
return 0;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key));
if (r != 0)
return r;
if (search_domain) {
_cleanup_free_ char *joined = NULL;
r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined);
if (r < 0)
return r;
return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), joined);
return dns_name_equal(dns_resource_key_name(rr->key), joined);
}
return 0;
@ -231,9 +248,9 @@ int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsRe
return 0;
if (cname->type == DNS_TYPE_CNAME)
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname));
else if (cname->type == DNS_TYPE_DNAME)
r = dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname));
r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname));
else
return 0;
@ -243,14 +260,14 @@ int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsRe
if (search_domain) {
_cleanup_free_ char *joined = NULL;
r = dns_name_concat(DNS_RESOURCE_KEY_NAME(key), search_domain, &joined);
r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined);
if (r < 0)
return r;
if (cname->type == DNS_TYPE_CNAME)
return dns_name_equal(joined, DNS_RESOURCE_KEY_NAME(cname));
return dns_name_equal(joined, dns_resource_key_name(cname));
else if (cname->type == DNS_TYPE_DNAME)
return dns_name_endswith(joined, DNS_RESOURCE_KEY_NAME(cname));
return dns_name_endswith(joined, dns_resource_key_name(cname));
}
return 0;
@ -268,7 +285,7 @@ int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *
if (soa->type != DNS_TYPE_SOA)
return 0;
return dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(soa));
return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa));
}
static void dns_resource_key_hash_func(const void *i, struct siphash *state) {
@ -276,7 +293,7 @@ static void dns_resource_key_hash_func(const void *i, struct siphash *state) {
assert(k);
dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), state);
dns_name_hash_func(dns_resource_key_name(k), state);
siphash24_compress(&k->class, sizeof(k->class), state);
siphash24_compress(&k->type, sizeof(k->type), state);
}
@ -285,7 +302,7 @@ static int dns_resource_key_compare_func(const void *a, const void *b) {
const DnsResourceKey *x = a, *y = b;
int ret;
ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
if (ret != 0)
return ret;
@ -307,32 +324,22 @@ const struct hash_ops dns_resource_key_hash_ops = {
.compare = dns_resource_key_compare_func
};
int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
char cbuf[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)];
const char *c, *t, *n;
char *s;
char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) {
const char *c, *t;
char *ans = buf;
/* If we cannot convert the CLASS/TYPE into a known string,
use the format recommended by RFC 3597, Section 5. */
c = dns_class_to_string(key->class);
if (!c) {
sprintf(cbuf, "CLASS%u", key->class);
c = cbuf;
}
t = dns_type_to_string(key->type);
if (!t){
sprintf(tbuf, "TYPE%u", key->type);
t = tbuf;
}
n = DNS_RESOURCE_KEY_NAME(key);
if (asprintf(&s, "%s%s %s %-5s", n, endswith(n, ".") ? "" : ".", c, t) < 0)
return -ENOMEM;
snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u",
dns_resource_key_name(key),
c ?: "", c ? "" : "CLASS", c ? 0 : key->class,
t ?: "", t ? "" : "TYPE", t ? 0 : key->class);
*ret = s;
return 0;
return ans;
}
bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
@ -830,8 +837,8 @@ static char *format_txt(DnsTxtItem *first) {
}
const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
_cleanup_free_ char *k = NULL, *t = NULL;
char *s;
_cleanup_free_ char *t = NULL;
char *s, k[DNS_RESOURCE_KEY_STRING_MAX];
int r;
assert(rr);
@ -839,9 +846,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
if (rr->to_string)
return rr->to_string;
r = dns_resource_key_to_string(rr->key, &k);
if (r < 0)
return NULL;
dns_resource_key_to_string(rr->key, k, sizeof(k));
switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
@ -1204,6 +1209,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 = {
@ -1261,7 +1304,7 @@ int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
if (rr->n_skip_labels_signer == (unsigned) -1)
return -ENODATA;
n = DNS_RESOURCE_KEY_NAME(rr->key);
n = dns_resource_key_name(rr->key);
r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
if (r < 0)
return r;
@ -1284,7 +1327,7 @@ int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
if (rr->n_skip_labels_source == (unsigned) -1)
return -ENODATA;
n = DNS_RESOURCE_KEY_NAME(rr->key);
n = dns_resource_key_name(rr->key);
r = dns_name_skip(n, rr->n_skip_labels_source, &n);
if (r < 0)
return r;
@ -1324,7 +1367,7 @@ int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
if (rr->n_skip_labels_source > 1)
return 1;
r = dns_name_startswith(DNS_RESOURCE_KEY_NAME(rr->key), "*");
r = dns_name_startswith(dns_resource_key_name(rr->key), "*");
if (r < 0)
return r;

View File

@ -26,6 +26,7 @@
#include "hashmap.h"
#include "in-addr-util.h"
#include "list.h"
#include "string-util.h"
typedef struct DnsResourceKey DnsResourceKey;
typedef struct DnsResourceRecord DnsResourceRecord;
@ -81,7 +82,7 @@ enum {
struct DnsResourceKey {
unsigned n_ref; /* (unsigned -1) for const keys, see below */
uint16_t class, type;
char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */
char *_name; /* don't access directy, use dns_resource_key_name()! */
};
/* Creates a temporary resource key. This is only useful to quickly
@ -260,16 +261,6 @@ struct DnsResourceRecord {
};
};
static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) {
if (!key)
return NULL;
if (key->_name)
return key->_name;
return (char*) key + sizeof(DnsResourceKey);
}
static inline const void* DNS_RESOURCE_RECORD_RDATA(DnsResourceRecord *rr) {
if (!rr)
return NULL;
@ -297,12 +288,20 @@ int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key
DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
const char* dns_resource_key_name(const DnsResourceKey *key);
bool dns_resource_key_is_address(const DnsResourceKey *key);
int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain);
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);
/* _DNS_{CLASS,TYPE}_STRING_MAX include one byte for NUL, which we use for space instead below.
* DNS_HOSTNAME_MAX does not include the NUL byte, so we need to add 1. */
#define DNS_RESOURCE_KEY_STRING_MAX (_DNS_CLASS_STRING_MAX + _DNS_TYPE_STRING_MAX + DNS_HOSTNAME_MAX + 1)
char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size);
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) {

View File

@ -514,8 +514,8 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) {
* that those should be resolved via LLMNR or search
* path only, and should not be leaked onto the
* internet. */
return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) ||
dns_name_is_root(DNS_RESOURCE_KEY_NAME(key)));
return !(dns_name_is_single_label(dns_resource_key_name(key)) ||
dns_name_is_root(dns_resource_key_name(key)));
}
/* On mDNS and LLMNR, send A and AAAA queries only on the

View File

@ -86,7 +86,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, dns_resource_key_name(key));
if (!rr)
return -ENOMEM;
@ -100,7 +100,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if
if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, dns_resource_key_name(key));
if (!rr)
return -ENOMEM;
@ -140,7 +140,7 @@ static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int i
if (r < 0)
return r;
r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
r = answer_add_ptr(answer, dns_resource_key_name(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
if (r < 0)
return r;
}
@ -254,11 +254,11 @@ static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key,
.address.in6 = in6addr_loopback,
};
return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
return answer_add_addresses_rr(answer, dns_resource_key_name(key), buffer, n);
}
}
return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
return answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n);
}
static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
@ -319,7 +319,7 @@ static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifin
return n;
}
return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
return answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n);
}
static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
@ -360,7 +360,7 @@ int dns_synthesize_answer(
key->class != DNS_CLASS_ANY)
continue;
name = DNS_RESOURCE_KEY_NAME(key);
name = dns_resource_key_name(key);
if (is_localhost(name)) {

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,6 @@ struct DnsTransaction {
DnsScope *scope;
DnsResourceKey *key;
char *key_string;
DnsTransactionState state;
@ -153,8 +152,6 @@ void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
int dns_transaction_validate_dnssec(DnsTransaction *t);
int dns_transaction_request_dnssec_keys(DnsTransaction *t);
const char *dns_transaction_key_string(DnsTransaction *t);
const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;

View File

@ -651,7 +651,7 @@ static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceReco
}
}
a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, DNS_RESOURCE_KEY_NAME(revoked_dnskey->key)));
a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, dns_resource_key_name(revoked_dnskey->key)));
if (a) {
DnsResourceRecord *anchor;
@ -698,7 +698,7 @@ int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey,
/* Could this be interesting to us at all? If not,
* there's no point in looking for and verifying a
* self-signed RRSIG. */
if (!dns_trust_anchor_knows_domain_positive(d, DNS_RESOURCE_KEY_NAME(dnskey->key)))
if (!dns_trust_anchor_knows_domain_positive(d, dns_resource_key_name(dnskey->key)))
return 0;
/* Look for a self-signed RRSIG in the other rrs belonging to this DNSKEY */

View File

@ -68,12 +68,12 @@ static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {
else
hashmap_remove(z->by_key, i->rr->key);
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key));
LIST_REMOVE(by_name, first, i);
if (first)
assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0);
assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0);
else
hashmap_remove(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
hashmap_remove(z->by_name, dns_resource_key_name(i->rr->key));
dns_zone_item_free(i);
}
@ -147,12 +147,12 @@ static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) {
return r;
}
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key));
if (first) {
LIST_PREPEND(by_name, first, i);
assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0);
assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0);
} else {
r = hashmap_put(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key), i);
r = hashmap_put(z->by_name, dns_resource_key_name(i->rr->key), i);
if (r < 0)
return r;
}
@ -169,11 +169,11 @@ static int dns_zone_item_probe_start(DnsZoneItem *i) {
if (i->probe_transaction)
return 0;
t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key)), false);
t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)), false);
if (!t) {
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key));
key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key));
if (!key)
return -ENOMEM;
@ -303,7 +303,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
* go through the list by the name and look
* for everything manually */
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
first = hashmap_get(z->by_name, dns_resource_key_name(key));
LIST_FOREACH(by_name, j, first) {
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
continue;
@ -339,7 +339,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
}
if (!found) {
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
first = hashmap_get(z->by_name, dns_resource_key_name(key));
LIST_FOREACH(by_name, j, first) {
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
continue;
@ -370,7 +370,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
bool found = false, added = false;
int k;
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
first = hashmap_get(z->by_name, dns_resource_key_name(key));
LIST_FOREACH(by_name, j, first) {
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
continue;
@ -393,7 +393,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
}
if (found && !added) {
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL);
if (r < 0)
return r;
}
@ -418,7 +418,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
if (!found) {
bool add_soa = false;
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
first = hashmap_get(z->by_name, dns_resource_key_name(key));
LIST_FOREACH(by_name, j, first) {
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
continue;
@ -430,7 +430,7 @@ int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, Dns
}
if (add_soa) {
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL);
if (r < 0)
return r;
}
@ -482,7 +482,7 @@ void dns_zone_item_conflict(DnsZoneItem *i) {
i->state = DNS_ZONE_ITEM_WITHDRAWN;
/* Maybe change the hostname */
if (manager_is_own_hostname(i->scope->manager, DNS_RESOURCE_KEY_NAME(i->rr->key)) > 0)
if (manager_is_own_hostname(i->scope->manager, dns_resource_key_name(i->rr->key)) > 0)
manager_next_hostname(i->scope->manager);
}
@ -562,7 +562,7 @@ int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr) {
* so, we'll verify our RRs. */
/* No conflict if we don't have the name at all. */
first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(rr->key));
first = hashmap_get(zone->by_name, dns_resource_key_name(rr->key));
if (!first)
return 0;
@ -593,7 +593,7 @@ int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) {
/* Somebody else notified us about a possible conflict. Let's
* verify if that's true. */
first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(key));
first = hashmap_get(zone->by_name, dns_resource_key_name(key));
if (!first)
return 0;

View File

@ -363,7 +363,7 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
continue;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
r = dns_name_equal(dns_resource_key_name(t), name);
if (r < 0)
return r;
if (r > 0) {
@ -413,7 +413,7 @@ int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
continue;
r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
r = dns_name_equal(dns_resource_key_name(t), name);
if (r < 0)
return r;
if (r == 0)

View File

@ -1213,11 +1213,11 @@ void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResource
assert(verdict < _DNSSEC_VERDICT_MAX);
if (log_get_max_level() >= LOG_DEBUG) {
_cleanup_free_ char *s = NULL;
char s[DNS_RESOURCE_KEY_STRING_MAX];
(void) dns_resource_key_to_string(key, &s);
log_debug("Found verdict for lookup %s: %s", s ? strstrip(s) : "n/a", dnssec_verdict_to_string(verdict));
log_debug("Found verdict for lookup %s: %s",
dns_resource_key_to_string(key, s, sizeof s),
dnssec_verdict_to_string(verdict));
}
m->n_dnssec_verdict[verdict]++;

View File

@ -106,7 +106,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
dns_scope_check_conflicts(scope, p);
DNS_ANSWER_FOREACH(rr, p->answer) {
const char *name = DNS_RESOURCE_KEY_NAME(rr->key);
const char *name = dns_resource_key_name(rr->key);
DnsTransaction *t;
/* If the received reply packet contains ANY record that is not .local or .in-addr.arpa,

View File

@ -21,7 +21,44 @@
#include "test-tables.h"
int main(int argc, char **argv) {
uint16_t i;
test_table_sparse(dns_type, DNS_TYPE);
log_info("/* DNS_TYPE */");
for (i = 0; i < _DNS_TYPE_MAX; i++) {
const char *s;
s = dns_type_to_string(i);
assert_se(s == NULL || strlen(s) < _DNS_TYPE_STRING_MAX);
if (s)
log_info("%-*s %s%s%s%s%s%s%s%s%s",
(int) _DNS_TYPE_STRING_MAX - 1, s,
dns_type_is_pseudo(i) ? "pseudo " : "",
dns_type_is_valid_query(i) ? "valid_query " : "",
dns_type_is_valid_rr(i) ? "is_valid_rr " : "",
dns_type_may_redirect(i) ? "may_redirect " : "",
dns_type_is_dnssec(i) ? "dnssec " : "",
dns_type_is_obsolete(i) ? "obsolete " : "",
dns_type_may_wildcard(i) ? "wildcard " : "",
dns_type_apex_only(i) ? "apex_only " : "",
dns_type_needs_authentication(i) ? "needs_authentication" : "");
}
log_info("/* DNS_CLASS */");
for (i = 0; i < _DNS_CLASS_MAX; i++) {
const char *s;
s = dns_class_to_string(i);
assert_se(s == NULL || strlen(s) < _DNS_CLASS_STRING_MAX);
if (s)
log_info("%-*s %s%s",
(int) _DNS_CLASS_STRING_MAX - 1, s,
dns_class_is_pseudo(i) ? "is_pseudo " : "",
dns_class_is_valid_rr(i) ? "is_valid_rr " : "");
}
return EXIT_SUCCESS;
}