From: Wouter Wijngaards Date: Tue, 26 Oct 2010 09:08:33 +0000 (+0000) Subject: dump_infra and flush_infra commands for unbound-control. X-Git-Tag: release-1.4.7rc1~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2ae3e8167754fcb7419571553a6d6ba280f8c99;p=thirdparty%2Funbound.git dump_infra and flush_infra commands for unbound-control. git-svn-id: file:///svn/unbound/trunk@2306 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/remote.c b/daemon/remote.c index 3a1c32fa7..3e14bc709 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -59,6 +59,7 @@ #include "util/module.h" #include "services/listen_dnsport.h" #include "services/cache/rrset.h" +#include "services/cache/infra.h" #include "services/mesh.h" #include "services/localzone.h" #include "util/storage/slabhash.h" @@ -1097,6 +1098,25 @@ do_flush_stats(SSL* ssl, struct worker* worker) send_ok(ssl); } +/** flush infra cache */ +static void +do_flush_infra(SSL* ssl, struct worker* worker, char* arg) +{ + struct sockaddr_storage addr; + socklen_t len; + if(strcmp(arg, "all") == 0) { + slabhash_clear(worker->env.infra_cache->hosts); + send_ok(ssl); + return; + } + if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) { + (void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg); + return; + } + infra_remove_host(worker->env.infra_cache, &addr, len); + send_ok(ssl); +} + /** flush requestlist */ static void do_flush_requestlist(SSL* ssl, struct worker* worker) @@ -1494,6 +1514,90 @@ do_dump_requestlist(SSL* ssl, struct worker* worker) } } +/** structure for argument data for dump infra host */ +struct infra_arg { + /** the infra cache */ + struct infra_cache* infra; + /** the SSL connection */ + SSL* ssl; + /** the time now */ + uint32_t now; + /** ipstr */ + char* ipstr; +}; + +/** callback for every lame element in the infra cache */ +static void +dump_infra_lame(struct lruhash_entry* e, void* arg) +{ + struct infra_arg* a = (struct infra_arg*)arg; + struct infra_lame_key* k = (struct infra_lame_key*)e->key; + struct infra_lame_data* d = (struct infra_lame_data*)e->data; + ldns_rdf* rdf; + size_t pos; + char* nm; + /* skip expired */ + if(d->ttl < a->now) { + return; + } + /* use ldns print for domain name */ + if(ldns_wire2dname(&rdf, k->zonename, k->namelen, &pos) + != LDNS_STATUS_OK) + return; + nm = ldns_rdf2str(rdf); + ldns_rdf_deep_free(rdf); + if(!ssl_printf(a->ssl, "%s lame %s ttl %d dnssec %d rec %d " + "A %d other %d\n", a->ipstr, nm, (int)(d->ttl - a->now), + d->isdnsseclame, d->rec_lame, d->lame_type_A, d->lame_other)) { + free(nm); + return; + } + free(nm); +} + +/** callback for every host element in the infra cache */ +static void +dump_infra_host(struct lruhash_entry* e, void* arg) +{ + struct infra_arg* a = (struct infra_arg*)arg; + struct infra_host_key* k = (struct infra_host_key*)e->key; + struct infra_host_data* d = (struct infra_host_data*)e->data; + char ip_str[1024]; + addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str)); + a->ipstr = ip_str; + /* skip expired stuff (only backed off) */ + if(d->ttl < a->now) { + if(d->backoff != INFRA_BACKOFF_INITIAL) { + if(!ssl_printf(a->ssl, "%s expired, backoff is %d\n", + ip_str, (int)d->backoff)) + return; + } + if(d->lameness) + lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg); + return; + } + if(!ssl_printf(a->ssl, "%s ttl %d ping %d var %d rtt %d rto %d " + "backoff %d ednsknown %d edns %d\n", + ip_str, (int)(d->ttl - a->now), + d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, + (int)d->backoff, (int)d->edns_lame_known, (int)d->edns_version + )) + return; + if(d->lameness) + lruhash_traverse(d->lameness, 0, &dump_infra_lame, arg); +} + +/** do the dump_infra command */ +static void +do_dump_infra(SSL* ssl, struct worker* worker) +{ + struct infra_arg arg; + arg.infra = worker->env.infra_cache; + arg.ssl = ssl; + arg.now = *worker->env.now; + slabhash_traverse(arg.infra->hosts, 0, &dump_infra_host, (void*)&arg); +} + /** do the log_reopen command */ static void do_log_reopen(SSL* ssl, struct worker* worker) @@ -1725,10 +1829,14 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, do_flush_zone(ssl, worker, skipwhite(p+10)); } else if(cmdcmp(p, "flush_type", 10)) { do_flush_type(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "flush_infra", 11)) { + do_flush_infra(ssl, worker, skipwhite(p+11)); } else if(cmdcmp(p, "flush", 5)) { do_flush_name(ssl, worker, skipwhite(p+5)); } else if(cmdcmp(p, "dump_requestlist", 16)) { do_dump_requestlist(ssl, worker); + } else if(cmdcmp(p, "dump_infra", 10)) { + do_dump_infra(ssl, worker); } else if(cmdcmp(p, "log_reopen", 10)) { do_log_reopen(ssl, worker); } else if(cmdcmp(p, "set_option", 10)) { diff --git a/doc/Changelog b/doc/Changelog index 1c52aa835..3b37ad762 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +26 October 2010: Wouter + - dump_infra and flush_infra commands for unbound-control. + 25 October 2010: Wouter - Configure errors if ldns is not found. diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 5c6cb2c1b..29a4502bc 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -142,6 +142,14 @@ Show what is worked on. Prints all queries that the server is currently working on. Prints the time that users have been waiting. For internal requests, no time is printed. And then prints out the module status. .TP +.B flush_infra \fIall|IP +If all then entire infra cache is emptied. If a specific IP address, the +entry for that address is removed from the cache. It contains EDNS, ping +and lameness data. +.TP +.B dump_infra +Show the contents of the infra cache. +.TP .B set_option \fIopt: val Set the option to the given value without a reload. The cache is therefore not flushed. The option must end with a ':' and whitespace must be between the diff --git a/services/cache/infra.c b/services/cache/infra.c index a2cd5996f..6f28283c1 100644 --- a/services/cache/infra.c +++ b/services/cache/infra.c @@ -155,6 +155,19 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen) return h; } +void +infra_remove_host(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen) +{ + struct infra_host_key k; + k.addrlen = addrlen; + memcpy(&k.addr, addr, addrlen); + k.entry.hash = hash_addr(addr, addrlen); + k.entry.key = (void*)&k; + k.entry.data = NULL; + slabhash_remove(infra->hosts, k.entry.hash, &k); +} + /** lookup version that does not check host ttl (you check it) */ static struct lruhash_entry* infra_lookup_host_nottl(struct infra_cache* infra, diff --git a/services/cache/infra.h b/services/cache/infra.h index 956edd23f..58ea7190c 100644 --- a/services/cache/infra.h +++ b/services/cache/infra.h @@ -144,6 +144,10 @@ struct infra_cache* infra_create(struct config_file* cfg); */ void infra_delete(struct infra_cache* infra); +/** explicitly delete an infra host element */ +void infra_remove_host(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen); + /** * Adjust infra cache to use updated configuration settings. * This may clean the cache. Operates a bit like realloc. diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index 57741dd2e..6b719f84e 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -96,6 +96,8 @@ usage() 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"); + printf(" flush_infra [all | ip] remove ping, edns for one IP or all\n"); + printf(" dump_infra show ping and edns entries\n"); printf(" set_option opt: val set option to value, no reload\n"); printf(" get_option opt get option value\n"); printf(" list_stubs list stub-zones and root hints in use\n");