]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
lookup delegation from cache and printout.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 23 Sep 2008 10:55:36 +0000 (10:55 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 23 Sep 2008 10:55:36 +0000 (10:55 +0000)
git-svn-id: file:///svn/unbound/trunk@1266 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
daemon/cachedump.c
daemon/cachedump.h
daemon/remote.c
doc/control_proto_spec.txt
doc/plan
doc/unbound-control.8.in
iterator/iter_delegpt.c
iterator/iter_delegpt.h
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
smallapp/unbound-control.c

index 6b04f10d6eca502a0aa6e0d85cd227e29fa3042e..2d800e5c34ab3f1f4e6461fe0b015dc71e54606e 100644 (file)
@@ -48,6 +48,9 @@
 #include "util/data/msgreply.h"
 #include "util/regional.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 */
 static ldns_rr*
@@ -776,3 +779,74 @@ load_cache(SSL* ssl, struct worker* worker)
                return 0;
        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;
+}
index 61cc2a409a6f7e50a6cedeae9e2fca014f675090..da9804ff1e09641ae21c4d7b9373026bcaafbbcf 100644 (file)
@@ -91,4 +91,17 @@ int dump_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 */
index 845527ae9cbebcdb42938ff183cd318a0fb93928..16ca5c2c13812947be9b6334e20c9b42de41067b 100644 (file)
@@ -896,6 +896,7 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
                return;
        if(!local_zone_str2type(arg2, &t)) {
                ssl_printf(ssl, "error not a zone type. %s\n", arg2);
+               free(nm);
                return;
        }
        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);
                z->type = t; /* update type anyway */
                lock_rw_unlock(&z->lock);
+               free(nm);
                lock_quick_unlock(&worker->daemon->local_zones->lock);
                send_ok(ssl);
                return;
@@ -934,6 +936,7 @@ do_zone_remove(SSL* ssl, struct worker* worker, char* arg)
                nmlabs, LDNS_RR_CLASS_IN))) {
                /* present in tree */
                local_zones_del_zone(worker->daemon->local_zones, z);
+               free(nm);
        }
        lock_quick_unlock(&worker->daemon->local_zones->lock);
        send_ok(ssl);
@@ -962,9 +965,23 @@ do_data_remove(SSL* ssl, struct worker* worker, char* arg)
                return;
        local_zones_del_data(worker->daemon->local_zones, nm,
                nmlen, nmlabs, LDNS_RR_CLASS_IN);
+       free(nm);
        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 */
 static void
 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);
        } else if(strncmp(p, "load_cache", 10) == 0) {
                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 {
                (void)ssl_printf(ssl, "error unknown command '%s'\n", p);
        }
index 1ad8d1cf999ca0daa0cee89811ba714c2279c51f..0388acc44f0b65a04e9547ae26146c5f3f9f4910 100644 (file)
@@ -45,10 +45,8 @@ flush_type <name> <RR type>
 flush_zone <name>
        removes name and everything below that name from the cache.
        has to search through the cache item by item, so this is slow.
-delegation <name>
-       see what servers would be queried for the given name.
-info <name>
-       see data about the name. Slow, searches the cache item by item.
+lookup <name>
+       see what servers would be queried for a lookup of the given name.
 local_zone_remove <name of local-zone entry>
        the local-zone entry is removed.
        All data from the local zone is also deleted.
index cd4cc0c610eea22dd08c1ea9b89fc3a7a6bede4f..b2b3b5f596c504db69768fd48e53a5040f2937a0 100644 (file)
--- a/doc/plan
+++ b/doc/plan
@@ -54,7 +54,7 @@ like dnswall does.  Allow certain subdomains to do it, config options.
        addup stats over threads.
 not    stats on SIGUSR1. perhaps also see which slow auth servers cause >1sec values.
 + 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 flush names or domains (all under a name) from the 
    cache. Include NSes. And the A, AAAA for its NSes.
index 85b5e8c4f01baaae2a75b95e552e294a037b1204..aa92b2792edf03e3840e6472fa007b9493a70d40 100644 (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
 dump_cache uses.  Loading the cache with old, or wrong data can result
 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"
 The unbound-control program exits with status code 1 on error, 0 on success.
 .SH "SET UP"
index 4c17fc8968cd1eeec94e6fa673cf898843576b38..03f4ec8f1de1e3c1ff761c3f7f064adeb50d3a49 100644 (file)
@@ -157,8 +157,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
        return 1;
 }
 
-/** count NS and number missing */
-static void
+void
 delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing)
 {
        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 */
-static void
+void
 delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, 
        size_t* numavail)
 {
index 25e8665718cb70c088ffffa05b18af8e73a1e367..8c122e5206542b97d75362dd260c54f81d959e42 100644 (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);
 
+/** 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.
  * @param dp: delegation point.
index bbdc8135b3498433aa9b4587cd485afbb774643b..d9ea574b1504df139b93aae521b80780920fb920 100644 (file)
@@ -372,7 +372,8 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
 }
 
 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;
        /* 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,
         *        and that nameserver is a glue-name for this dp.
         */
-       if(!(qstate->query_flags&BIT_RD))
+       if(!(qflags&BIT_RD))
                return 0;
        /* either available or unused targets */
        if(dp->usable_list || dp->result_list) 
                return 0;
        
        /* see if query is for one of the nameservers, which is glue */
-       if( (qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
-               qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
-               dname_subdomain_c(qstate->qinfo.qname, dp->name) &&
-               delegpt_find_ns(dp, qstate->qinfo.qname, 
-                       qstate->qinfo.qname_len))
+       if( (qinfo->qtype == LDNS_RR_TYPE_A ||
+               qinfo->qtype == LDNS_RR_TYPE_AAAA) &&
+               dname_subdomain_c(qinfo->qname, dp->name) &&
+               delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
                return 1;
        
        for(ns = dp->nslist; ns; ns = ns->next) {
index 0edbb8ed4ad924615391a50c88ad570fdf42172a..7055fbaa66068218c47b7eb2313ba837c8c0f936 100644 (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 
  * 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.
  */
-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 
index 98f8fb0953f6ff3c7d7023a1bd19b5a867e59743..e2f4901f30e66eb309dcca24999b5ae238f08578 100644 (file)
@@ -842,7 +842,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                 * could be useless but lead to loops (bumping into the
                 * 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)) {
                                /* use safety belt */
                                verbose(VERB_QUERY, "Cache has root NS but "
index c1d04a58502a52b4bf8b85558844ef8ccdeb38f1..a513db0c65d16d911ce0766a7e54e337c6f11366 100644 (file)
@@ -70,6 +70,7 @@ usage()
        printf("  local_data_remove [name]      remove local RR data from name\n");
        printf("  dump_cache                    print cache to stdout\n");
        printf("  load_cache                    load cache from stdin\n");
+       printf("  lookup [name]                 print nameservers for name\n");
        printf("Version %s\n", PACKAGE_VERSION);
        printf("BSD licensed, see LICENSE in source package for details.\n");
        printf("Report bugs to %s\n", PACKAGE_BUGREPORT);