resolved: when receiving a TTL=0 RR, only flush that specific RR
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Dec 2015 18:22:26 +0000 (19:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 18 Dec 2015 18:22:26 +0000 (19:22 +0100)
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

index 2e3090b..e8e3497 100644 (file)
@@ -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);