diff --git a/daemon/remote.c b/daemon/remote.c index f2e8f3ff9..5dc05c5fa 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1286,6 +1286,74 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg) (unsigned)inf.num_msgs, (unsigned)inf.num_keys); } +/** callback to delete bogus rrsets */ +static void +bogus_del_rrset(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct packed_rrset_data* d = (struct packed_rrset_data*)e->data; + if(d->security == sec_status_bogus) { + d->ttl = inf->expired; + inf->num_rrsets++; + } +} + +/** callback to delete bogus messages */ +static void +bogus_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; + if(d->security == sec_status_bogus) { + d->ttl = inf->expired; + inf->num_msgs++; + } +} + +/** callback to delete bogus keys */ +static void +bogus_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; + if(d->isbad) { + d->ttl = inf->expired; + inf->num_keys++; + } +} + +/** remove all rrsets and keys from zone from cache */ +static void +do_flush_bogus(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, + &bogus_del_rrset, &inf); + + slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf); + + /* and validator cache */ + if(worker->env.key_cache) { + slabhash_traverse(worker->env.key_cache->slab, 1, + &bogus_del_kcache, &inf); + } + + (void)ssl_printf(ssl, "ok removed %u rrsets, %u messages " + "and %u key entries\n", (unsigned)inf.num_rrsets, + (unsigned)inf.num_msgs, (unsigned)inf.num_keys); +} + /** remove name rrset from cache */ static void do_flush_name(SSL* ssl, struct worker* w, char* arg) @@ -2038,6 +2106,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, do_set_option(ssl, worker, skipwhite(p+10)); } else if(cmdcmp(p, "get_option", 10)) { do_get_option(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "flush_bogus", 11)) { + do_flush_bogus(ssl, worker); } else { (void)ssl_printf(ssl, "error unknown command '%s'\n", p); } diff --git a/doc/Changelog b/doc/Changelog index ebd85e350..6b516c5e9 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +9 July 2012: Willem + - Add flush_bogus option for unbound-control + 6 July 2012: Wouter - Fix validation of qtype DS queries that result in no data for non-optout NSEC3 zones. diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index a095eb7a6..f458338c1 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -127,6 +127,9 @@ Remove all information at or below the name from the cache. The rrsets and key entries are removed so that new lookups will be performed. This needs to walk and inspect the entire cache, and is a slow operation. .TP +.B flush_bogus +Remove all bogus data from the cache. +.TP .B flush_stats Reset statistics to zero. .TP diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index a5aa92bf9..e438b3d20 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -93,6 +93,7 @@ usage() printf(" flush_type flush name, type from cache\n"); 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_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");