#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*
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;
+}
*/
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 */
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);
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;
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);
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)
(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);
}
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.
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.
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"
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;
}
}
-/** 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)
{
*/
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.
}
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:
* 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) {
/**
* 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
* 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 "
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);