summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-21 01:24:30 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-25 17:19:19 +0100
commitf6618dcd96d437f2b8abeefd32a6a6790c04d026 (patch)
treeb8253c404641fc21278a69a410a8825f5e8f4274
parentfcfaff123506b8c2300038934eef46892576d2d2 (diff)
resolved: never store NSEC/NSEC3 RRs from the upper zone of a zone cut in cache
When using NSEC/NSEC3 RRs from the cache to derive existance of arbitrary RRs, we should not get confused by the fact that NSEC/NSEC3 RRs exist twice at zone cuts: once in the parent zone, and once in the child zone. For most RR types we should only consult the latter since that's where the beef is. However, for DS lookups we have to check the former. This change makes sure we never cache NSEC/NSEC3 RRs from any parent zone of a zone-cut. It also makes sure that when we look for a DS RR in the cache we never consider any cached NSEC RR, as those are now always from the child zone.
-rw-r--r--src/resolve/resolved-dns-cache.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index fdb34d11df..9267b67f79 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -579,6 +579,28 @@ static void dns_cache_remove_previous(
}
}
+static bool rr_eligible(DnsResourceRecord *rr) {
+ assert(rr);
+
+ /* When we see an NSEC/NSEC3 RR, we'll only cache it if it is from the lower zone, not the upper zone, since
+ * that's where the interesting bits are (with exception of DS RRs). Of course, this way we cannot derive DS
+ * existence from any cached NSEC/NSEC3, but that should be fine. */
+
+ switch (rr->key->type) {
+
+ case DNS_TYPE_NSEC:
+ return !bitmap_isset(rr->nsec.types, DNS_TYPE_NS) ||
+ bitmap_isset(rr->nsec.types, DNS_TYPE_SOA);
+
+ case DNS_TYPE_NSEC3:
+ return !bitmap_isset(rr->nsec3.types, DNS_TYPE_NS) ||
+ bitmap_isset(rr->nsec3.types, DNS_TYPE_SOA);
+
+ default:
+ return true;
+ }
+}
+
int dns_cache_put(
DnsCache *c,
DnsResourceKey *key,
@@ -635,6 +657,12 @@ int dns_cache_put(
if ((flags & DNS_ANSWER_CACHEABLE) == 0)
continue;
+ r = rr_eligible(rr);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
+
r = dns_cache_put_positive(
c,
rr,
@@ -835,7 +863,10 @@ int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, int *rcode, DnsAnswer **r
have_non_authenticated = true;
}
- if (nsec && key->type != DNS_TYPE_NSEC) {
+ if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) {
+ /* 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)