From: Wouter Wijngaards Date: Tue, 29 Apr 2014 08:47:33 +0000 (+0000) Subject: - Add unbound-control flush_negative that flushed nxdomains, nodata, X-Git-Tag: release-1.5.0rc1~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bc3fab7a41688bd497a244d7bbf3568e4a77f70;p=thirdparty%2Funbound.git - 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. git-svn-id: file:///svn/unbound/trunk@3125 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/remote.c b/daemon/remote.c index 224740af5..0c4ea73ad 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -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); } diff --git a/doc/Changelog b/doc/Changelog index c6545493f..7c2c84a31 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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 diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index a40895cb5..88297e9f9 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -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 diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 76de1b2d3..9b78cef94 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -95,6 +95,7 @@ usage() printf(" flush_zone 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");