]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Add unbound-control flush_negative that flushed nxdomains, nodata,
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 29 Apr 2014 08:47:33 +0000 (08:47 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 29 Apr 2014 08:47:33 +0000 (08:47 +0000)
  and errors from the cache.  For dnssec-trigger and NetworkManager,
  fixes cases where network changes have localdata that was already
  negatively cached from the previous network.

git-svn-id: file:///svn/unbound/trunk@3125 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/remote.c
doc/Changelog
doc/unbound-control.8.in
smallapp/unbound-control.c

index 224740af564c1d0fe8d7379c4547bf5868aacf94..0c4ea73adcd4b32200574ae401d08d351f3b390d 100644 (file)
@@ -1332,7 +1332,7 @@ bogus_del_kcache(struct lruhash_entry* e, void* arg)
        }
 }
 
-/** remove all rrsets and keys from zone from cache */
+/** remove all bogus rrsets, msgs and keys from cache */
 static void
 do_flush_bogus(SSL* ssl, struct worker* worker)
 {
@@ -1361,6 +1361,82 @@ do_flush_bogus(SSL* ssl, struct worker* worker)
                (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys);
 }
 
+/** callback to delete negative and servfail rrsets */
+static void
+negative_del_rrset(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key;
+       struct packed_rrset_data* d = (struct packed_rrset_data*)e->data;
+       /* delete the parentside negative cache rrsets,
+        * these are namerserver rrsets that failed lookup, rdata empty */
+       if((k->rk.flags & PACKED_RRSET_PARENT_SIDE) && d->count == 1 &&
+               d->rrsig_count == 0 && d->rr_len[0] == 0) {
+               d->ttl = inf->expired;
+               inf->num_rrsets++;
+       }
+}
+
+/** callback to delete negative and servfail messages */
+static void
+negative_del_msg(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct reply_info* d = (struct reply_info*)e->data;
+       /* rcode not NOERROR: NXDOMAIN, SERVFAIL, ..: an nxdomain or error
+        * or NOERROR rcode with ANCOUNT==0: a NODATA answer */
+       if(FLAGS_GET_RCODE(d->flags) != 0 || d->an_numrrsets == 0) {
+               d->ttl = inf->expired;
+               inf->num_msgs++;
+       }
+}
+
+/** callback to delete negative key entries */
+static void
+negative_del_kcache(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct key_entry_data* d = (struct key_entry_data*)e->data;
+       /* could be bad because of lookup failure on the DS, DNSKEY, which
+        * was nxdomain or servfail, and thus a result of negative lookups */
+       if(d->isbad) {
+               d->ttl = inf->expired;
+               inf->num_keys++;
+       }
+}
+
+/** remove all negative(NODATA,NXDOMAIN), and servfail messages from cache */
+static void
+do_flush_negative(SSL* ssl, struct worker* worker)
+{
+       struct del_info inf;
+       /* what we do is to set them all expired */
+       inf.worker = worker;
+       inf.now = *worker->env.now;
+       inf.expired = *worker->env.now;
+       inf.expired -= 3; /* handle 3 seconds skew between threads */
+       inf.num_rrsets = 0;
+       inf.num_msgs = 0;
+       inf.num_keys = 0;
+       slabhash_traverse(&worker->env.rrset_cache->table, 1, 
+               &negative_del_rrset, &inf);
+
+       slabhash_traverse(worker->env.msg_cache, 1, &negative_del_msg, &inf);
+
+       /* and validator cache */
+       if(worker->env.key_cache) {
+               slabhash_traverse(worker->env.key_cache->slab, 1, 
+                       &negative_del_kcache, &inf);
+       }
+
+       (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages "
+               "and %lu key entries\n", (unsigned long)inf.num_rrsets, 
+               (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys);
+}
+
 /** remove name rrset from cache */
 static void
 do_flush_name(SSL* ssl, struct worker* w, char* arg)
@@ -2203,6 +2279,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
                do_get_option(ssl, worker, skipwhite(p+10));
        } else if(cmdcmp(p, "flush_bogus", 11)) {
                do_flush_bogus(ssl, worker);
+       } else if(cmdcmp(p, "flush_negative", 14)) {
+               do_flush_negative(ssl, worker);
        } else {
                (void)ssl_printf(ssl, "error unknown command '%s'\n", p);
        }
index c6545493fb7f81eeccd2a895ccc6db7a0589f6f2..7c2c84a314c3e78e07c01f6e594f9df5abee2b67 100644 (file)
@@ -1,5 +1,9 @@
 29 April 2014: Wouter
        - iana portlist updated.
+       - Add unbound-control flush_negative that flushed nxdomains, nodata,
+         and errors from the cache.  For dnssec-trigger and NetworkManager,
+         fixes cases where network changes have localdata that was already
+         negatively cached from the previous network.
 
 23 April 2014: Wouter
        - Patch from Jeremie Courreges-Anglas to use arc4random_uniform
index a40895cb510c20793e6c167d305f5a92208a3140..88297e9f934a3545644d071b2e6f7537018cb518 100644 (file)
@@ -133,6 +133,12 @@ This needs to walk and inspect the entire cache, and is a slow operation.
 .B flush_bogus
 Remove all bogus data from the cache.
 .TP
+.B flush_negative
+Remove all negative data from the cache.  This is nxdomain answers,
+nodata answers and servfail answers.  Also removes bad key entries
+(which could be due to failed lookups) from the dnssec key cache, and
+iterator last-resort lookup failures from the rrset cache.
+.TP
 .B flush_stats
 Reset statistics to zero.
 .TP
index 76de1b2d37e1054c6e7868d8b1f503327d0ce4ff..9b78cef940e1013cb3dabc78d1e832a64b79f221 100644 (file)
@@ -95,6 +95,7 @@ usage()
        printf("  flush_zone <name>             flush everything at or under name\n");
        printf("                                from rr and dnssec caches\n");
        printf("  flush_bogus                   flush all bogus data\n");
+       printf("  flush_negative                flush all negative data\n");
        printf("  flush_stats                   flush statistics, make zero\n");
        printf("  flush_requestlist             drop queries that are worked on\n");
        printf("  dump_requestlist              show what is worked on\n");