]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-cache.c
resolved: cache - don't cache NXDOMAIN by TYPE
[thirdparty/systemd.git] / src / resolve / resolved-dns-cache.c
index 4aacc268e20f4337ceb92e3fdea99b0a04e43a3b..9ffbf1d1a613dcd4dec3f0fd319e1d28790c4f38 100644 (file)
@@ -364,6 +364,8 @@ static int dns_cache_put_negative(
         if (key->class == DNS_CLASS_ANY)
                 return 0;
         if (key->type == DNS_TYPE_ANY)
+                /* This is particularly important to filter out as we use this as a
+                 * pseudo-type for NXDOMAIN entries */
                 return 0;
         if (soa_ttl <= 0) {
                 r = dns_resource_key_to_string(key, &key_str);
@@ -389,13 +391,21 @@ static int dns_cache_put_negative(
                 return -ENOMEM;
 
         i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN;
-        i->key = dns_resource_key_ref(key);
         i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
         i->prioq_idx = PRIOQ_IDX_NULL;
         i->owner_family = owner_family;
         i->owner_address = *owner_address;
         i->authenticated = authenticated;
 
+        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));
+                if (!i->key)
+                        return -ENOMEM;
+        } else
+                i->key = dns_resource_key_ref(key);
+
         r = dns_cache_link_item(c, i);
         if (r < 0)
                 return r;
@@ -479,6 +489,15 @@ int dns_cache_put(
         if (r > 0)
                 return 0;
 
+        /* 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);
+        if (r < 0)
+                goto fail;
+        if (r > 0)
+                return 0;
+
         /* See https://tools.ietf.org/html/rfc2308, which say that a
          * matching SOA record in the packet is used to to enable
          * negative caching. */
@@ -525,6 +544,12 @@ static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, D
 
         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. */
+        i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_ANY, n));
+        if (i && i->type == DNS_CACHE_NXDOMAIN)
+                return i;
+
         /* 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)