lookup delegation from cache and printout.

git-svn-id: file:///svn/unbound/trunk@1266 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-09-23 10:55:36 +00:00
parent de0f903d37
commit cfceb6487d
12 changed files with 136 additions and 19 deletions

View file

@ -48,6 +48,9 @@
#include "util/data/msgreply.h" #include "util/data/msgreply.h"
#include "util/regional.h" #include "util/regional.h"
#include "util/net_help.h" #include "util/net_help.h"
#include "util/data/dname.h"
#include "iterator/iter_delegpt.h"
#include "iterator/iter_utils.h"
/** convert to ldns rr */ /** convert to ldns rr */
static ldns_rr* static ldns_rr*
@ -776,3 +779,74 @@ load_cache(SSL* ssl, struct worker* worker)
return 0; return 0;
return read_fixed(ssl, worker->env.scratch_buffer, "EOF"); return read_fixed(ssl, worker->env.scratch_buffer, "EOF");
} }
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
size_t nmlen, int ATTR_UNUSED(nmlabs))
{
/* deep links into the iterator module */
struct delegpt* dp;
struct dns_msg* msg;
struct regional* region = worker->scratchpad;
char b[260];
struct query_info qinfo;
size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
regional_free_all(region);
qinfo.qname = nm;
qinfo.qname_len = nmlen;
qinfo.qtype = LDNS_RR_TYPE_A;
qinfo.qclass = LDNS_RR_CLASS_IN;
dname_str(nm, b);
if(!ssl_printf(ssl, "The following name servers are used for lookup "
"of %s\n", b))
return 0;
while(1) {
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
qinfo.qtype, qinfo.qclass, region, &msg,
*worker->env.now);
if(!dp) {
return ssl_printf(ssl, "no delegation from "
"cache; goes to configured roots\n");
}
/* print the dp */
for(i=0; i<msg->rep->rrset_count; i++) {
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
struct packed_rrset_data* d =
(struct packed_rrset_data*)k->entry.data;
if(!dump_rrset(ssl, k, d, 0))
return 0;
}
delegpt_count_ns(dp, &n_ns, &n_miss);
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
/* since dp has not been used by iterator, all are available*/
if(!ssl_printf(ssl, "Delegation with %d names, of which %d "
"have no addresses in cache.\n"
"It provides %d IP addresses.\n",
(int)n_ns, (int)n_miss, (int)n_addr))
return 0;
/* go up? */
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
if(!ssl_printf(ssl, "cache delegation was "
"useless (no IP addresses)\n"))
return 0;
if(dname_is_root(nm)) {
/* goes to root config */
return ssl_printf(ssl, "no delegation from "
"cache; goes to configured roots\n");
} else {
/* useless, goes up */
nm = dp->name;
nmlen = dp->namelen;
dname_remove_label(&nm, &nmlen);
dname_str(nm, b);
if(!ssl_printf(ssl, "going up, lookup %s\n", b))
return 0;
continue;
}
} else
break;
}
return 1;
}

View file

@ -91,4 +91,17 @@ int dump_cache(SSL* ssl, struct worker* worker);
*/ */
int load_cache(SSL* ssl, struct worker* worker); int load_cache(SSL* ssl, struct worker* worker);
/**
* Print the delegation used to lookup for this name.
* @param ssl: to read from
* @param worker: worker that is available (buffers, etc) and has
* ptrs to the caches.
* @param nm: name to lookup
* @param nmlen: length of name.
* @param nmlabs: labels in name.
* @return false on ssl error.
*/
int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
size_t nmlen, int nmlabs);
#endif /* DAEMON_DUMPCACHE_H */ #endif /* DAEMON_DUMPCACHE_H */

View file

@ -896,6 +896,7 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
return; return;
if(!local_zone_str2type(arg2, &t)) { if(!local_zone_str2type(arg2, &t)) {
ssl_printf(ssl, "error not a zone type. %s\n", arg2); ssl_printf(ssl, "error not a zone type. %s\n", arg2);
free(nm);
return; return;
} }
lock_quick_lock(&worker->daemon->local_zones->lock); lock_quick_lock(&worker->daemon->local_zones->lock);
@ -905,6 +906,7 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
lock_rw_wrlock(&z->lock); lock_rw_wrlock(&z->lock);
z->type = t; /* update type anyway */ z->type = t; /* update type anyway */
lock_rw_unlock(&z->lock); lock_rw_unlock(&z->lock);
free(nm);
lock_quick_unlock(&worker->daemon->local_zones->lock); lock_quick_unlock(&worker->daemon->local_zones->lock);
send_ok(ssl); send_ok(ssl);
return; return;
@ -934,6 +936,7 @@ do_zone_remove(SSL* ssl, struct worker* worker, char* arg)
nmlabs, LDNS_RR_CLASS_IN))) { nmlabs, LDNS_RR_CLASS_IN))) {
/* present in tree */ /* present in tree */
local_zones_del_zone(worker->daemon->local_zones, z); local_zones_del_zone(worker->daemon->local_zones, z);
free(nm);
} }
lock_quick_unlock(&worker->daemon->local_zones->lock); lock_quick_unlock(&worker->daemon->local_zones->lock);
send_ok(ssl); send_ok(ssl);
@ -962,9 +965,23 @@ do_data_remove(SSL* ssl, struct worker* worker, char* arg)
return; return;
local_zones_del_data(worker->daemon->local_zones, nm, local_zones_del_data(worker->daemon->local_zones, nm,
nmlen, nmlabs, LDNS_RR_CLASS_IN); nmlen, nmlabs, LDNS_RR_CLASS_IN);
free(nm);
send_ok(ssl); send_ok(ssl);
} }
/** cache lookup of nameservers */
static void
do_lookup(SSL* ssl, struct worker* worker, char* arg)
{
uint8_t* nm;
int nmlabs;
size_t nmlen;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
(void)print_deleg_lookup(ssl, worker, nm, nmlen, nmlabs);
free(nm);
}
/** execute a remote control command */ /** execute a remote control command */
static void static void
execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd) execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
@ -991,6 +1008,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
(void)dump_cache(ssl, rc->worker); (void)dump_cache(ssl, rc->worker);
} else if(strncmp(p, "load_cache", 10) == 0) { } else if(strncmp(p, "load_cache", 10) == 0) {
if(load_cache(ssl, rc->worker)) send_ok(ssl); if(load_cache(ssl, rc->worker)) send_ok(ssl);
} else if(strncmp(p, "lookup", 6) == 0) {
do_lookup(ssl, rc->worker, skipwhite(p+6));
} else { } else {
(void)ssl_printf(ssl, "error unknown command '%s'\n", p); (void)ssl_printf(ssl, "error unknown command '%s'\n", p);
} }

View file

@ -45,10 +45,8 @@ flush_type <name> <RR type>
flush_zone <name> flush_zone <name>
removes name and everything below that name from the cache. removes name and everything below that name from the cache.
has to search through the cache item by item, so this is slow. has to search through the cache item by item, so this is slow.
delegation <name> lookup <name>
see what servers would be queried for the given name. see what servers would be queried for a lookup of the given name.
info <name>
see data about the name. Slow, searches the cache item by item.
local_zone_remove <name of local-zone entry> local_zone_remove <name of local-zone entry>
the local-zone entry is removed. the local-zone entry is removed.
All data from the local zone is also deleted. All data from the local zone is also deleted.

View file

@ -54,7 +54,7 @@ like dnswall does. Allow certain subdomains to do it, config options.
addup stats over threads. addup stats over threads.
not stats on SIGUSR1. perhaps also see which slow auth servers cause >1sec values. not stats on SIGUSR1. perhaps also see which slow auth servers cause >1sec values.
+ remote control to add/remove localinfo, redirects. + remote control to add/remove localinfo, redirects.
* remote control to load/store cache contents + remote control to load/store cache contents
+ remote control to start, stop, reload. + remote control to start, stop, reload.
* remote control to flush names or domains (all under a name) from the * remote control to flush names or domains (all under a name) from the
cache. Include NSes. And the A, AAAA for its NSes. cache. Include NSes. And the A, AAAA for its NSes.

View file

@ -91,6 +91,10 @@ redirect it to a file to store the cache in a file.
The contents of the cache is loaded from stdin. Uses the same format as The contents of the cache is loaded from stdin. Uses the same format as
dump_cache uses. Loading the cache with old, or wrong data can result dump_cache uses. Loading the cache with old, or wrong data can result
in old or wrong data returned to clients. in old or wrong data returned to clients.
.TP
.B lookup \fIname
Print to stdout the name servers that would be used to look up the
name specified.
.SH "EXIT CODE" .SH "EXIT CODE"
The unbound-control program exits with status code 1 on error, 0 on success. The unbound-control program exits with status code 1 on error, 0 on success.
.SH "SET UP" .SH "SET UP"

View file

@ -157,8 +157,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
return 1; return 1;
} }
/** count NS and number missing */ void
static void
delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing) delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
{ {
struct delegpt_ns* ns; struct delegpt_ns* ns;
@ -171,8 +170,7 @@ delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
} }
} }
/** count addresses, and number in result and available lists */ void
static void
delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
size_t* numavail) size_t* numavail)
{ {

View file

@ -228,6 +228,13 @@ struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
*/ */
void delegpt_log(enum verbosity_value v, struct delegpt* dp); void delegpt_log(enum verbosity_value v, struct delegpt* dp);
/** count NS and number missing for logging */
void delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing);
/** count addresses, and number in result and available lists, for logging */
void delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
size_t* numavail);
/** /**
* Add all usable targets to the result list. * Add all usable targets to the result list.
* @param dp: delegation point. * @param dp: delegation point.

View file

@ -372,7 +372,8 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
} }
int int
iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp) iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp)
{ {
struct delegpt_ns* ns; struct delegpt_ns* ns;
/* check: /* check:
@ -385,18 +386,17 @@ iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp)
* o the query is for one of the nameservers in dp, * o the query is for one of the nameservers in dp,
* and that nameserver is a glue-name for this dp. * and that nameserver is a glue-name for this dp.
*/ */
if(!(qstate->query_flags&BIT_RD)) if(!(qflags&BIT_RD))
return 0; return 0;
/* either available or unused targets */ /* either available or unused targets */
if(dp->usable_list || dp->result_list) if(dp->usable_list || dp->result_list)
return 0; return 0;
/* see if query is for one of the nameservers, which is glue */ /* see if query is for one of the nameservers, which is glue */
if( (qstate->qinfo.qtype == LDNS_RR_TYPE_A || if( (qinfo->qtype == LDNS_RR_TYPE_A ||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) && qinfo->qtype == LDNS_RR_TYPE_AAAA) &&
dname_subdomain_c(qstate->qinfo.qname, dp->name) && dname_subdomain_c(qinfo->qname, dp->name) &&
delegpt_find_ns(dp, qstate->qinfo.qname, delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
qstate->qinfo.qname_len))
return 1; return 1;
for(ns = dp->nslist; ns; ns = ns->next) { for(ns = dp->nslist; ns; ns = ns->next) {

View file

@ -135,10 +135,12 @@ void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
/** /**
* See if delegation is useful or offers immediately no targets for * See if delegation is useful or offers immediately no targets for
* further recursion. * further recursion.
* @param qstate: query state with RD flag and query name. * @param qinfo: query name and type
* @param qflags: query flags with RD flag
* @param dp: delegpt to check. * @param dp: delegpt to check.
*/ */
int iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp); int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp);
/** /**
* See if delegation is expected to have DNSSEC information (RRSIGs) in * See if delegation is expected to have DNSSEC information (RRSIGs) in

View file

@ -842,7 +842,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* could be useless but lead to loops (bumping into the * could be useless but lead to loops (bumping into the
* same server reply) if useless-checked. * same server reply) if useless-checked.
*/ */
if(iter_dp_is_useless(qstate, iq->dp)) { if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp)) {
if(dname_is_root(iq->dp->name)) { if(dname_is_root(iq->dp->name)) {
/* use safety belt */ /* use safety belt */
verbose(VERB_QUERY, "Cache has root NS but " verbose(VERB_QUERY, "Cache has root NS but "

View file

@ -70,6 +70,7 @@ usage()
printf(" local_data_remove [name] remove local RR data from name\n"); printf(" local_data_remove [name] remove local RR data from name\n");
printf(" dump_cache print cache to stdout\n"); printf(" dump_cache print cache to stdout\n");
printf(" load_cache load cache from stdin\n"); printf(" load_cache load cache from stdin\n");
printf(" lookup [name] print nameservers for name\n");
printf("Version %s\n", PACKAGE_VERSION); printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n"); printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT); printf("Report bugs to %s\n", PACKAGE_BUGREPORT);