From 105e151299dc1208855380be2b22d0db2d66ebc6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 14:37:06 +0100 Subject: resolved: add support NSEC3 proofs, as well as proofs for domains that are OK to be unsigned This large patch adds a couple of mechanisms to ensure we get NSEC3 and proof-of-unsigned support into place. Specifically: - Each item in an DnsAnswer gets two bit flags now: DNS_ANSWER_AUTHENTICATED and DNS_ANSWER_CACHEABLE. The former is necessary since DNS responses might contain signed as well as unsigned RRsets in one, and we need to remember which ones are signed and which ones aren't. The latter is necessary, since not we need to keep track which RRsets may be cached and which ones may not be, even while manipulating DnsAnswer objects. - The .n_answer_cachable of DnsTransaction is dropped now (it used to store how many of the first DnsAnswer entries are cachable), and replaced by the DNS_ANSWER_CACHABLE flag instead. - NSEC3 proofs are implemented now (lacking support for the wildcard part, to be added in a later commit). - Support for the "AD" bit has been dropped. It's unsafe, and now that we have end-to-end authentication we don't need it anymore. - An auxiliary DnsTransaction of a DnsTransactions is now kept around as least as long as the latter stays around. We no longer remove the auxiliary DnsTransaction as soon as it completed. THis is necessary, as we now are interested not only in the RRsets it acquired but also in its authentication status. --- src/resolve/resolved-dns-cache.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 62713b5a6a..a8d612794c 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -436,14 +436,14 @@ int dns_cache_put( DnsResourceKey *key, int rcode, DnsAnswer *answer, - unsigned max_rrs, bool authenticated, usec_t timestamp, int owner_family, const union in_addr_union *owner_address) { DnsResourceRecord *soa = NULL, *rr; - unsigned cache_keys, i; + DnsAnswerFlags flags; + unsigned cache_keys; int r; assert(c); @@ -468,9 +468,13 @@ int dns_cache_put( return 0; } - DNS_ANSWER_FOREACH(rr, answer) + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + if (rr->key->cache_flush) dns_cache_remove(c, rr->key); + } /* We only care for positive replies and NXDOMAINs, on all * other replies we will simply flush the respective entries, @@ -480,7 +484,6 @@ int dns_cache_put( return 0; cache_keys = answer->n_rrs; - if (key) cache_keys ++; @@ -491,10 +494,12 @@ int dns_cache_put( timestamp = now(clock_boottime_or_monotonic()); /* Second, add in positive entries for all contained RRs */ - for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) { - rr = answer->items[i].rr; - r = dns_cache_put_positive(c, rr, authenticated, timestamp, owner_family, owner_address); + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + + r = dns_cache_put_positive(c, rr, flags & DNS_ANSWER_AUTHENTICATED, timestamp, owner_family, owner_address); if (r < 0) goto fail; } @@ -503,7 +508,7 @@ int dns_cache_put( return 0; /* Third, add in negative entries if the key has no RR */ - r = dns_answer_match_key(answer, key); + r = dns_answer_match_key(answer, key, NULL); if (r < 0) goto fail; if (r > 0) @@ -512,7 +517,7 @@ int dns_cache_put( /* But not if it has a matching CNAME/DNAME (the negative * caching will be done on the canonical name, not on the * alias) */ - r = dns_answer_find_cname_or_dname(answer, key, NULL); + r = dns_answer_find_cname_or_dname(answer, key, NULL, NULL); if (r < 0) goto fail; if (r > 0) @@ -541,8 +546,12 @@ fail: if (key) dns_cache_remove(c, key); - for (i = 0; i < answer->n_rrs; i++) - dns_cache_remove(c, answer->items[i].rr->key); + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + + dns_cache_remove(c, rr->key); + } return r; } @@ -722,7 +731,7 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r if (!j->rr) continue; - r = dns_answer_add(answer, j->rr, 0); + r = dns_answer_add(answer, j->rr, 0, have_authenticated && !have_non_authenticated ? DNS_ANSWER_AUTHENTICATED : 0); if (r < 0) return r; } -- cgit v1.2.3-54-g00ecf From 222148b66d1abf5b05c9d803472a9368331dae53 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:06:23 +0100 Subject: resolved: make use of dns_{class|type}_is_{pseudo|valid_rr}() everywhere --- src/resolve/dns-type.h | 15 ++++++++------- src/resolve/resolved-dns-cache.c | 20 ++++++++++++-------- src/resolve/resolved-dns-packet.c | 2 +- src/resolve/resolved-dns-zone.c | 4 ++-- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h index deb89e9b7e..bea0adaa16 100644 --- a/src/resolve/dns-type.h +++ b/src/resolve/dns-type.h @@ -23,13 +23,6 @@ #include "macro.h" -const char *dns_type_to_string(int type); -int dns_type_from_string(const char *s); - -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); - /* DNS record types, taken from * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml. */ @@ -127,12 +120,20 @@ assert_cc(DNS_TYPE_ANY == 255); enum { DNS_CLASS_IN = 0x01, DNS_CLASS_ANY = 0xFF, + _DNS_CLASS_MAX, _DNS_CLASS_INVALID = -1 }; +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); + bool dns_class_is_pseudo(uint16_t class); 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); int dns_class_from_string(const char *name); diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index a8d612794c..9ad3c0e82b 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -282,6 +282,12 @@ static int dns_cache_put_positive( assert(rr); assert(owner_address); + /* Never cache pseudo RRs */ + if (dns_class_is_pseudo(rr->key->class)) + return 0; + if (dns_type_is_pseudo(rr->key->type)) + return 0; + /* New TTL is 0? Delete the entry... */ if (rr->ttl <= 0) { k = dns_cache_remove(c, rr->key); @@ -300,11 +306,6 @@ static int dns_cache_put_positive( return 0; } - if (rr->key->class == DNS_CLASS_ANY) - return 0; - if (dns_type_is_pseudo(rr->key->type)) - return 0; - /* Entry exists already? Update TTL and timestamp */ existing = dns_cache_get(c, rr); if (existing) { @@ -368,12 +369,15 @@ static int dns_cache_put_negative( dns_cache_remove(c, key); - if (key->class == DNS_CLASS_ANY) + /* Never cache pseudo RR keys */ + if (dns_class_is_pseudo(key->class)) return 0; if (dns_type_is_pseudo(key->type)) - /* ANY is particularly important to filter out as we - * use this as a pseudo-type for NXDOMAIN entries */ + /* DNS_TYPE_ANY is particularly important to filter + * out as we use this as a pseudo-type for NXDOMAIN + * entries */ return 0; + if (soa_ttl <= 0) { if (log_get_max_level() >= LOG_DEBUG) { r = dns_resource_key_to_string(key, &key_str); diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index e8f570555b..bb299462a7 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -1531,7 +1531,7 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { if (r < 0) goto fail; - if (key->class == DNS_CLASS_ANY || + if (!dns_class_is_valid_rr(key->class)|| !dns_type_is_valid_rr(key->type)) { r = -EBADMSG; goto fail; diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index 0ddf2be8b3..20c8a4da90 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -223,9 +223,9 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) { assert(s); assert(rr); - if (rr->key->class == DNS_CLASS_ANY) + if (dns_class_is_pseudo(rr->key->class)) return -EINVAL; - if (rr->key->type == DNS_TYPE_ANY) + if (dns_type_is_pseudo(rr->key->type)) return -EINVAL; existing = dns_zone_get(z, rr); -- cgit v1.2.3-54-g00ecf From d98e5504208e5435584d3ee44fd1ab1629920e7a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:07:31 +0100 Subject: resolved: bump cache size a bit Let's keep entries for longer and more of them. After all, due to the DNSSEC hookup the amount of RRs we need to store is much higher now. --- src/resolve/resolved-dns-cache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 9ad3c0e82b..fe74f0f83f 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -26,11 +26,11 @@ #include "resolved-dns-packet.h" #include "string-util.h" -/* Never cache more than 1K entries */ -#define CACHE_MAX 1024 +/* Never cache more than 4K entries */ +#define CACHE_MAX 4096 -/* We never keep any item longer than 10min in our cache */ -#define CACHE_TTL_MAX_USEC (10 * USEC_PER_MINUTE) +/* We never keep any item longer than 2h in our cache */ +#define CACHE_TTL_MAX_USEC (2 * USEC_PER_HOUR) typedef enum DnsCacheItemType DnsCacheItemType; typedef struct DnsCacheItem DnsCacheItem; -- cgit v1.2.3-54-g00ecf From 1069048089d12462ccc1ce273802ef517433aff5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:09:27 +0100 Subject: resolved: don't call dns_cache_remove() from dns_cache_put_negative() We call it anyway as one of the first calls in dns_cache_put(), hence there's no reason to do this multiple times. --- src/resolve/resolved-dns-cache.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index fe74f0f83f..31325ecc88 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -367,8 +367,6 @@ static int dns_cache_put_negative( assert(key); assert(owner_address); - dns_cache_remove(c, key); - /* Never cache pseudo RR keys */ if (dns_class_is_pseudo(key->class)) return 0; -- cgit v1.2.3-54-g00ecf From fd009cd80e511587c6afae59da8aff14e5e18fa3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:12:48 +0100 Subject: resolved: check SOA authentication state when negative caching We should never use the TTL of an unauthenticated SOA to cache an authenticated RR. --- src/resolve/resolved-dns-answer.c | 7 +++++-- src/resolve/resolved-dns-answer.h | 2 +- src/resolve/resolved-dns-cache.c | 7 ++++++- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index cb0be7d18c..fa0e026ea7 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -302,8 +302,9 @@ int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { return false; } -int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret) { +int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { DnsResourceRecord *rr; + DnsAnswerFlags rr_flags; int r; assert(key); @@ -312,13 +313,15 @@ int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceReco if (key->type == DNS_TYPE_SOA) return 0; - DNS_ANSWER_FOREACH(rr, a) { + DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { r = dns_resource_key_match_soa(key, rr->key); if (r < 0) return r; if (r > 0) { if (ret) *ret = rr; + if (flags) + *flags = rr_flags; return 1; } } diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h index 569f283d03..c946f09f8a 100644 --- a/src/resolve/resolved-dns-answer.h +++ b/src/resolve/resolved-dns-answer.h @@ -64,7 +64,7 @@ int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags * int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags); int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a); -int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret); +int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret); diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 31325ecc88..df397e1ddd 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -529,12 +529,17 @@ int dns_cache_put( * matching SOA record in the packet is used to to enable * negative caching. */ - r = dns_answer_find_soa(answer, key, &soa); + r = dns_answer_find_soa(answer, key, &soa, &flags); if (r < 0) goto fail; if (r == 0) return 0; + /* Refuse using the SOA data if it is unsigned, but the key is + * signed */ + if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0) + return 0; + r = dns_cache_put_negative(c, key, rcode, authenticated, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From 950b692bfbabf01e92f912450b0c76265c99ae43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:15:34 +0100 Subject: resolved: use dns_name_parent() where appropriate --- src/resolve/resolved-dns-cache.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index df397e1ddd..65eff7fda6 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -598,8 +598,6 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D /* OK, let's look for cached DNAME records. */ for (;;) { - char label[DNS_LABEL_MAX]; - if (isempty(n)) return NULL; @@ -608,13 +606,13 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D return i; /* Jump one label ahead */ - r = dns_label_unescape(&n, label, sizeof(label)); + r = dns_name_parent(&n); if (r <= 0) return NULL; } } - if (k-> type != DNS_TYPE_NSEC) { + if (k->type != DNS_TYPE_NSEC) { /* Check if we have an NSEC record instead for the name. */ i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n)); if (i) -- cgit v1.2.3-54-g00ecf From 1f97052fe0e90781b6e4caac0ecd104bd2bf54e6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:19:56 +0100 Subject: resolved: optimize dns_cache_remove() a bit --- src/resolve/resolved-dns-cache.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 65eff7fda6..2e3090b32a 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -101,18 +101,21 @@ void dns_cache_flush(DnsCache *c) { } static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) { - DnsCacheItem *i; - bool exist = false; + DnsCacheItem *first, *i, *n; assert(c); assert(key); - while ((i = hashmap_get(c->by_key, key))) { - dns_cache_item_remove_and_free(c, i); - exist = true; + first = hashmap_remove(c->by_key, key); + if (!first) + return false; + + LIST_FOREACH_SAFE(by_key, i, n, first) { + prioq_remove(c->by_expiry, i, &i->prioq_idx); + dns_cache_item_free(i); } - return exist; + return true; } static void dns_cache_make_space(DnsCache *c, unsigned add) { -- cgit v1.2.3-54-g00ecf From f5bdeb01e4c9f479aaa31cebfa6cfa85ae8a7336 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:22:26 +0100 Subject: resolved: when receiving a TTL=0 RR, only flush that specific RR When we receieve a TTL=0 RR, then let's only flush that specific RR and not the whole RRset. On mDNS with RRsets that a shared-owner this is how specific RRs are removed from the set, hence support this. And on non-mDNS the whole RRset will already be removed much earlier in dns_cache_put() hence there's no reason remove it again. --- src/resolve/resolved-dns-cache.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 2e3090b32a..e8e349748a 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -100,6 +100,24 @@ void dns_cache_flush(DnsCache *c) { c->by_expiry = prioq_free(c->by_expiry); } +static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { + DnsCacheItem *first, *i; + int r; + + first = hashmap_get(c->by_key, rr->key); + LIST_FOREACH(by_key, i, first) { + r = dns_resource_record_equal(i->rr, rr); + if (r < 0) + return r; + if (r > 0) { + dns_cache_item_remove_and_free(c, i); + return true; + } + } + + return false; +} + static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) { DnsCacheItem *first, *i, *n; @@ -291,9 +309,9 @@ static int dns_cache_put_positive( if (dns_type_is_pseudo(rr->key->type)) return 0; - /* New TTL is 0? Delete the entry... */ + /* New TTL is 0? Delete this specific entry... */ if (rr->ttl <= 0) { - k = dns_cache_remove(c, rr->key); + 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); -- cgit v1.2.3-54-g00ecf From ef9a3e3c28095e52f8ffe96acf3c70b2babfacb5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:25:04 +0100 Subject: resolve: optimize dns_cache_flush() a bit Let's use dns_cache_remove() rather than dns_cache_item_remove_and_free() to destroy the cache, since the former requires far fewer hash table lookups. --- src/resolve/resolved-dns-cache.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index e8e349748a..a4fc185514 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -85,21 +85,6 @@ static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) { dns_cache_item_free(i); } -void dns_cache_flush(DnsCache *c) { - DnsCacheItem *i; - - assert(c); - - while ((i = hashmap_first(c->by_key))) - dns_cache_item_remove_and_free(c, i); - - assert(hashmap_size(c->by_key) == 0); - assert(prioq_size(c->by_expiry) == 0); - - c->by_key = hashmap_free(c->by_key); - c->by_expiry = prioq_free(c->by_expiry); -} - static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { DnsCacheItem *first, *i; int r; @@ -136,6 +121,21 @@ static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) { return true; } +void dns_cache_flush(DnsCache *c) { + DnsResourceKey *key; + + assert(c); + + while ((key = hashmap_first_key(c->by_key))) + dns_cache_remove(c, key); + + assert(hashmap_size(c->by_key) == 0); + assert(prioq_size(c->by_expiry) == 0); + + c->by_key = hashmap_free(c->by_key); + c->by_expiry = prioq_free(c->by_expiry); +} + static void dns_cache_make_space(DnsCache *c, unsigned add) { assert(c); -- cgit v1.2.3-54-g00ecf From eed749cca62983df3290dd46b423e59c7b039f42 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:29:47 +0100 Subject: resolved: pass out precise authenticated bit we got passed in Make sure the cache never altes the authenticated bit of RRs stored in it, and drops it for RRs when passing it out again. --- src/resolve/resolved-dns-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index a4fc185514..451875ece0 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -757,7 +757,7 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r if (!j->rr) continue; - r = dns_answer_add(answer, j->rr, 0, have_authenticated && !have_non_authenticated ? DNS_ANSWER_AUTHENTICATED : 0); + r = dns_answer_add(answer, j->rr, 0, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0); if (r < 0) return r; } -- cgit v1.2.3-54-g00ecf From ea207b639a379b2a0bb8f2cafb0893e406c6152e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:31:21 +0100 Subject: resolved: properly determine size of DnsAnswer object After all we want to allow NULL DnsAnswer objects as equivalent to empty ones, hence we should use the right checks everywhere. --- src/resolve/resolved-dns-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 451875ece0..84ae8b59f9 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -477,7 +477,7 @@ int dns_cache_put( dns_cache_remove(c, key); } - if (!answer) { + if (dns_answer_size(answer) <= 0) { if (log_get_max_level() >= LOG_DEBUG) { _cleanup_free_ char *key_str = NULL; @@ -506,7 +506,7 @@ int dns_cache_put( if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) return 0; - cache_keys = answer->n_rrs; + cache_keys = dns_answer_size(answer); if (key) cache_keys ++; -- cgit v1.2.3-54-g00ecf From d2579eec5e1b845b2cf29caddc951dc22f2abb91 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:32:46 +0100 Subject: resolved: rework mDNS cache-flush bit handling This adds a new DnsAnswer item flag "DNS_ANSWER_SHARED_OWNER" which is set for mDNS RRs that lack the cache-flush bit. The cache-flush bit is removed from the DnsResourceRecord object in favour of this. This also splits out the code that removes previous entries when adding new positive ones into a new separate call dns_cache_remove_previous(). --- src/resolve-host/resolve-host.c | 2 +- src/resolve/resolved-dns-answer.h | 5 +- src/resolve/resolved-dns-cache.c | 138 ++++++++++++++++++++++++++++---------- src/resolve/resolved-dns-packet.c | 32 ++++++--- src/resolve/resolved-dns-packet.h | 4 +- src/resolve/resolved-dns-rr.h | 1 - 6 files changed, 129 insertions(+), 53 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c index bcacb2595c..3e4b52a3a9 100644 --- a/src/resolve-host/resolve-host.c +++ b/src/resolve-host/resolve-host.c @@ -398,7 +398,7 @@ static int resolve_record(sd_bus *bus, const char *name) { if (r < 0) return log_oom(); - r = dns_packet_read_rr(p, &rr, NULL); + r = dns_packet_read_rr(p, &rr, NULL, NULL); if (r < 0) { log_error("Failed to parse RR."); return r; diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h index c946f09f8a..29d6636e68 100644 --- a/src/resolve/resolved-dns-answer.h +++ b/src/resolve/resolved-dns-answer.h @@ -35,8 +35,9 @@ typedef struct DnsAnswerItem DnsAnswerItem; * Note that we usually encode the the empty DnsAnswer object as a simple NULL. */ typedef enum DnsAnswerFlags { - DNS_ANSWER_AUTHENTICATED = 1, - DNS_ANSWER_CACHEABLE = 2, + DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */ + DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */ + DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */ } DnsAnswerFlags; struct DnsAnswerItem { diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 84ae8b59f9..a6b9fb8f2d 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -42,14 +42,18 @@ enum DnsCacheItemType { }; struct DnsCacheItem { + DnsCacheItemType type; DnsResourceKey *key; DnsResourceRecord *rr; + usec_t until; - DnsCacheItemType type; - unsigned prioq_idx; - bool authenticated; + bool authenticated:1; + bool shared_owner:1; + int owner_family; union in_addr_union owner_address; + + unsigned prioq_idx; LIST_FIELDS(DnsCacheItem, by_key); }; @@ -175,7 +179,6 @@ void dns_cache_prune(DnsCache *c) { /* Remove all entries that are past their TTL */ for (;;) { - _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; DnsCacheItem *i; i = prioq_peek(c->by_expiry); @@ -188,10 +191,19 @@ void dns_cache_prune(DnsCache *c) { if (i->until > t) break; - /* Take an extra reference to the key so that it - * doesn't go away in the middle of the remove call */ - key = dns_resource_key_ref(i->key); - dns_cache_remove(c, key); + /* Depending whether this is an mDNS shared entry + * either remove only this one RR or the whole + * RRset */ + if (i->shared_owner) + dns_cache_item_remove_and_free(c, i); + else { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + /* Take an extra reference to the key so that it + * doesn't go away in the middle of the remove call */ + key = dns_resource_key_ref(i->key); + dns_cache_remove(c, key); + } } } @@ -260,10 +272,20 @@ static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) { return NULL; } -static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, bool authenticated, usec_t timestamp) { +static void dns_cache_item_update_positive( + DnsCache *c, + DnsCacheItem *i, + DnsResourceRecord *rr, + bool authenticated, + bool shared_owner, + usec_t timestamp, + int owner_family, + const union in_addr_union *owner_address) { + assert(c); assert(i); assert(rr); + assert(owner_address); i->type = DNS_CACHE_POSITIVE; @@ -280,8 +302,12 @@ static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsReso dns_resource_key_unref(i->key); i->key = dns_resource_key_ref(rr->key); - i->authenticated = authenticated; i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC); + i->authenticated = authenticated; + i->shared_owner = shared_owner; + + i->owner_family = owner_family; + i->owner_address = *owner_address; prioq_reshuffle(c->by_expiry, i, &i->prioq_idx); } @@ -290,6 +316,7 @@ static int dns_cache_put_positive( DnsCache *c, DnsResourceRecord *rr, bool authenticated, + bool shared_owner, usec_t timestamp, int owner_family, const union in_addr_union *owner_address) { @@ -327,10 +354,18 @@ static int dns_cache_put_positive( return 0; } - /* Entry exists already? Update TTL and timestamp */ + /* Entry exists already? Update TTL, timestamp and owner*/ existing = dns_cache_get(c, rr); if (existing) { - dns_cache_item_update_positive(c, existing, rr, authenticated, timestamp); + dns_cache_item_update_positive( + c, + existing, + rr, + authenticated, + shared_owner, + timestamp, + owner_family, + owner_address); return 0; } @@ -349,10 +384,11 @@ static int dns_cache_put_positive( i->key = dns_resource_key_ref(rr->key); i->rr = dns_resource_record_ref(rr); i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC); - i->prioq_idx = PRIOQ_IDX_NULL; + i->authenticated = authenticated; + i->shared_owner = shared_owner; i->owner_family = owner_family; i->owner_address = *owner_address; - i->authenticated = authenticated; + i->prioq_idx = PRIOQ_IDX_NULL; r = dns_cache_link_item(c, i); if (r < 0) @@ -363,7 +399,7 @@ static int dns_cache_put_positive( if (r < 0) return r; - log_debug("Added cache entry for %s", key_str); + log_debug("Added positive cache entry for %s", key_str); } i = NULL; @@ -424,10 +460,10 @@ static int dns_cache_put_negative( i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN; i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC); - i->prioq_idx = PRIOQ_IDX_NULL; + i->authenticated = authenticated; i->owner_family = owner_family; i->owner_address = *owner_address; - i->authenticated = authenticated; + i->prioq_idx = PRIOQ_IDX_NULL; if (i->type == DNS_CACHE_NXDOMAIN) { /* NXDOMAIN entries should apply equally to all types, so we use ANY as @@ -454,6 +490,36 @@ static int dns_cache_put_negative( return 0; } +static void dns_cache_remove_previous( + DnsCache *c, + DnsResourceKey *key, + DnsAnswer *answer) { + + DnsResourceRecord *rr; + DnsAnswerFlags flags; + + assert(c); + + /* First, if we were passed a key (i.e. on LLMNR/DNS, but + * not on mDNS), delete all matching old RRs, so that we only + * keep complete by_key in place. */ + if (key) + dns_cache_remove(c, key); + + /* Second, flush all entries matching the answer, unless this + * is an RR that is explicitly marked to be "shared" between + * peers (i.e. mDNS RRs without the flush-cache bit set). */ + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + + if (flags & DNS_ANSWER_SHARED_OWNER) + continue; + + dns_cache_remove(c, rr->key); + } +} + int dns_cache_put( DnsCache *c, DnsResourceKey *key, @@ -470,12 +536,9 @@ int dns_cache_put( int r; assert(c); + assert(owner_address); - if (key) { - /* First, if we were passed a key, delete all matching old RRs, - * so that we only keep complete by_key in place. */ - dns_cache_remove(c, key); - } + dns_cache_remove_previous(c, key, answer); if (dns_answer_size(answer) <= 0) { if (log_get_max_level() >= LOG_DEBUG) { @@ -491,18 +554,9 @@ int dns_cache_put( return 0; } - DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { - if ((flags & DNS_ANSWER_CACHEABLE) == 0) - continue; - - if (rr->key->cache_flush) - dns_cache_remove(c, rr->key); - } - /* We only care for positive replies and NXDOMAINs, on all * other replies we will simply flush the respective entries, * and that's it */ - if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) return 0; @@ -517,17 +571,22 @@ int dns_cache_put( timestamp = now(clock_boottime_or_monotonic()); /* Second, add in positive entries for all contained RRs */ - DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { if ((flags & DNS_ANSWER_CACHEABLE) == 0) continue; - r = dns_cache_put_positive(c, rr, flags & DNS_ANSWER_AUTHENTICATED, timestamp, owner_family, owner_address); + r = dns_cache_put_positive( + c, + rr, + flags & DNS_ANSWER_AUTHENTICATED, + flags & DNS_ANSWER_SHARED_OWNER, + timestamp, + owner_family, owner_address); if (r < 0) goto fail; } - if (!key) + if (!key) /* mDNS doesn't know negative caching, really */ return 0; /* Third, add in negative entries if the key has no RR */ @@ -561,7 +620,14 @@ int dns_cache_put( if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0) return 0; - r = dns_cache_put_negative(c, key, rcode, authenticated, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address); + r = dns_cache_put_negative( + c, + key, + rcode, + authenticated, + timestamp, + MIN(soa->soa.minimum, soa->ttl), + owner_family, owner_address); if (r < 0) goto fail; @@ -822,7 +888,7 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { if (!j->rr) continue; - if (!dns_key_is_shared(j->rr->key)) + if (!j->shared_owner) continue; r = dns_packet_append_rr(p, j->rr, NULL, NULL); diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 2b7d634a51..14faf9e4ab 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -1455,9 +1455,9 @@ fail: return r; } -int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) { +int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) { _cleanup_free_ char *name = NULL; - bool cache_flush = true; + bool cache_flush = false; uint16_t class, type; DnsResourceKey *key; size_t saved_rindex; @@ -1483,10 +1483,10 @@ int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) { if (p->protocol == DNS_PROTOCOL_MDNS) { /* See RFC6762, Section 10.2 */ - if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) + if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) { class &= ~MDNS_RR_CACHE_FLUSH; - else - cache_flush = false; + cache_flush = true; + } } key = dns_resource_key_new_consume(class, type, name); @@ -1495,11 +1495,11 @@ int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) { goto fail; } - key->cache_flush = cache_flush; - name = NULL; *ret = key; + if (ret_cache_flush) + *ret_cache_flush = cache_flush; if (start) *start = saved_rindex; @@ -1515,11 +1515,12 @@ static bool loc_size_ok(uint8_t size) { return m <= 9 && e <= 9 && (m > 0 || e == 0); } -int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { +int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; size_t saved_rindex, offset; uint16_t rdlength; + bool cache_flush; int r; assert(p); @@ -1527,7 +1528,7 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { saved_rindex = p->rindex; - r = dns_packet_read_key(p, &key, NULL); + r = dns_packet_read_key(p, &key, &cache_flush, NULL); if (r < 0) goto fail; @@ -1939,6 +1940,8 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) { *ret = rr; rr = NULL; + if (ret_cache_flush) + *ret_cache_flush = cache_flush; if (start) *start = saved_rindex; @@ -1971,11 +1974,17 @@ int dns_packet_extract(DnsPacket *p) { for (i = 0; i < n; i++) { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + bool cache_flush; - r = dns_packet_read_key(p, &key, NULL); + r = dns_packet_read_key(p, &key, &cache_flush, NULL); if (r < 0) goto finish; + if (cache_flush) { + r = -EBADMSG; + goto finish; + } + if (!dns_type_is_valid_query(key->type)) { r = -EBADMSG; goto finish; @@ -2034,7 +2043,8 @@ int dns_packet_extract(DnsPacket *p) { * sections. */ r = dns_answer_add(answer, rr, p->ifindex, - i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0); + (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) | + (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0)); if (r < 0) goto finish; } diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 082e92833c..36da86dee5 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -185,8 +185,8 @@ int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start); int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start); int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start); int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start); -int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start); -int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start); +int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start); +int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start); void dns_packet_rewind(DnsPacket *p, size_t idx); diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h index bb50cf6a34..a35f01ce10 100644 --- a/src/resolve/resolved-dns-rr.h +++ b/src/resolve/resolved-dns-rr.h @@ -71,7 +71,6 @@ struct DnsResourceKey { unsigned n_ref; uint16_t class, type; char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */ - bool cache_flush:1; }; /* Creates a temporary resource key. This is only useful to quickly -- cgit v1.2.3-54-g00ecf From 2dda578f1e729ff906820936b65474967683aeda Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:43:10 +0100 Subject: resolved: rename dns_cache_remove() → dns_cache_remove_by_key() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that we already have dns_cache_remove_by_rr() this makes clearer what the operation actually does. --- src/resolve/resolved-dns-cache.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index a6b9fb8f2d..c0bfcce7cd 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -107,7 +107,7 @@ static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { return false; } -static bool dns_cache_remove(DnsCache *c, DnsResourceKey *key) { +static bool dns_cache_remove_by_key(DnsCache *c, DnsResourceKey *key) { DnsCacheItem *first, *i, *n; assert(c); @@ -131,7 +131,7 @@ void dns_cache_flush(DnsCache *c) { assert(c); while ((key = hashmap_first_key(c->by_key))) - dns_cache_remove(c, key); + dns_cache_remove_by_key(c, key); assert(hashmap_size(c->by_key) == 0); assert(prioq_size(c->by_expiry) == 0); @@ -167,7 +167,7 @@ static void dns_cache_make_space(DnsCache *c, unsigned add) { /* Take an extra reference to the key so that it * doesn't go away in the middle of the remove call */ key = dns_resource_key_ref(i->key); - dns_cache_remove(c, key); + dns_cache_remove_by_key(c, key); } } @@ -202,7 +202,7 @@ void dns_cache_prune(DnsCache *c) { /* Take an extra reference to the key so that it * doesn't go away in the middle of the remove call */ key = dns_resource_key_ref(i->key); - dns_cache_remove(c, key); + dns_cache_remove_by_key(c, key); } } } @@ -504,7 +504,7 @@ static void dns_cache_remove_previous( * not on mDNS), delete all matching old RRs, so that we only * keep complete by_key in place. */ if (key) - dns_cache_remove(c, key); + dns_cache_remove_by_key(c, key); /* Second, flush all entries matching the answer, unless this * is an RR that is explicitly marked to be "shared" between @@ -516,7 +516,7 @@ static void dns_cache_remove_previous( if (flags & DNS_ANSWER_SHARED_OWNER) continue; - dns_cache_remove(c, rr->key); + dns_cache_remove_by_key(c, rr->key); } } @@ -638,13 +638,13 @@ fail: * added, just in case */ if (key) - dns_cache_remove(c, key); + dns_cache_remove_by_key(c, key); DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { if ((flags & DNS_ANSWER_CACHEABLE) == 0) continue; - dns_cache_remove(c, rr->key); + dns_cache_remove_by_key(c, rr->key); } return r; -- cgit v1.2.3-54-g00ecf From 39963f1123b3c192dd72e88d5403e4d39deabcba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:44:15 +0100 Subject: resolved: rename dns_cache_item_remove_and_free() → _unlink_and_free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In most of the other call, we called similar functions that remove the data structure link-ups to other objects "unlink", hence we should here, too. --- src/resolve/resolved-dns-cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index c0bfcce7cd..0aacc74e5e 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -68,7 +68,7 @@ static void dns_cache_item_free(DnsCacheItem *i) { DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free); -static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) { +static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) { DnsCacheItem *first; assert(c); @@ -99,7 +99,7 @@ static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { if (r < 0) return r; if (r > 0) { - dns_cache_item_remove_and_free(c, i); + dns_cache_item_unlink_and_free(c, i); return true; } } @@ -195,7 +195,7 @@ void dns_cache_prune(DnsCache *c) { * either remove only this one RR or the whole * RRset */ if (i->shared_owner) - dns_cache_item_remove_and_free(c, i); + dns_cache_item_unlink_and_free(c, i); else { _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; -- cgit v1.2.3-54-g00ecf From 98b6be778400636bb2f8c155d3079d9396d90974 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Dec 2015 19:46:27 +0100 Subject: resolved: merge two comments --- src/resolve/resolved-dns-cache.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/resolve/resolved-dns-cache.c') diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c index 0aacc74e5e..f50d780ebb 100644 --- a/src/resolve/resolved-dns-cache.c +++ b/src/resolve/resolved-dns-cache.c @@ -424,13 +424,12 @@ static int dns_cache_put_negative( assert(key); assert(owner_address); - /* Never cache pseudo RR keys */ + /* Never cache pseudo RR keys. DNS_TYPE_ANY is particularly + * important to filter out as we use this as a pseudo-type for + * NXDOMAIN entries */ if (dns_class_is_pseudo(key->class)) return 0; if (dns_type_is_pseudo(key->type)) - /* DNS_TYPE_ANY is particularly important to filter - * out as we use this as a pseudo-type for NXDOMAIN - * entries */ return 0; if (soa_ttl <= 0) { -- cgit v1.2.3-54-g00ecf