diff --git a/doc/Changelog b/doc/Changelog index b2ec1cd9c..cc1342136 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,11 @@ - more quiet about ipv6 network failures, i.e. when ipv6 is not available (network unreachable). Debug still printed on high verbosity. + - unbound-host -4 and -6 options. Stops annoying ipv6 errors when + debugging with unbound -4 -d ... + - more cycle detection for NS-check, addr-check, root-prime and + stub-prime queries in the iterator. Avoids possible deadlock + when priming fails. 15 January 2009: Wouter - bug #229: fixup configure checks for compilation with Solaris diff --git a/doc/unbound-host.1 b/doc/unbound-host.1 index dccc0c156..528e75653 100644 --- a/doc/unbound-host.1 +++ b/doc/unbound-host.1 @@ -14,7 +14,7 @@ .SH "SYNOPSIS" .LP .B unbound\-host -.RB [ \-vdhr ] +.RB [ \-vdhr46 ] .RB [ \-c .IR class ] .RB [ \-t @@ -87,6 +87,12 @@ Read /etc/resolv.conf, and use the forward DNS servers from there (those could have been set by DHCP). More info in .IR resolv.conf (5). Breaks validation if those servers do not support DNSSEC. +.TP +.B \-4 +Use solely the IPv4 network for sending packets. +.TP +.B \-6 +Use solely the IPv6 network for sending packets. .SH "EXAMPLES" .LP Some examples of use. The keys shown below are fakes, thus a security failure diff --git a/iterator/iterator.c b/iterator/iterator.c index 66d86cbd6..dac8581e0 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -460,13 +460,15 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq, * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does * not need initialisation. * @param v: if true, validation is done on the subquery. + * @param detcyc: if true, cycle detection is done on the subquery. * @return false on error (malloc). */ static int generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, struct module_qstate* qstate, int id, struct iter_qstate* iq, enum iter_state initial_state, - enum iter_state final_state, struct module_qstate** subq_ret, int v) + enum iter_state final_state, struct module_qstate** subq_ret, int v, + int detcyc) { struct module_qstate* subq = NULL; struct iter_qstate* subiq = NULL; @@ -488,6 +490,15 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, * path. */ if(!v) qflags |= BIT_CD; + + if(detcyc) { + fptr_ok(fptr_whitelist_modenv_detect_cycle( + qstate->env->detect_cycle)); + if((*qstate->env->detect_cycle)(qstate, &qinf, qflags, prime)){ + log_query_info(VERB_DETAIL, "cycle detected", &qinf); + return 0; + } + } /* attach subquery, lookup existing or make a new one */ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); @@ -555,8 +566,8 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, * the normal INIT state logic (which would cause an infloop). */ if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE, - &subq, 0)) { - log_err("out of memory priming root"); + &subq, 0, 1)) { + verbose(VERB_ALGO, "could not prime root"); return 0; } if(subq) { @@ -624,8 +635,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, * redundant INIT state processing. */ if(!generate_sub_request(stub_dp->name, stub_dp->namelen, LDNS_RR_TYPE_NS, qclass, qstate, id, iq, - QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) { - log_err("out of memory priming stub"); + QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 1)) { + verbose(VERB_ALGO, "could not prime stub"); (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); return 1; /* return 1 to make module stop, with error */ } @@ -702,8 +713,8 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq, if(!generate_sub_request(s->rk.dname, s->rk.dname_len, ntohs(s->rk.type), ntohs(s->rk.rrset_class), qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { - log_err("out of memory generating ns check"); + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) { + verbose(VERB_ALGO, "could not generate addr check"); return; } /* ignore subq - not need for more init */ @@ -737,8 +748,8 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); if(!generate_sub_request(iq->dp->name, iq->dp->namelen, LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { - log_err("out of memory generating ns check"); + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) { + verbose(VERB_ALGO, "could not generate ns check"); return; } if(subq) { @@ -1086,7 +1097,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq, { struct module_qstate* subq; if(!generate_sub_request(name, namelen, qtype, qclass, qstate, - id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) + id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) return 0; if(subq) { struct iter_qstate* subiq = @@ -1721,8 +1732,8 @@ processPrimeResponse(struct module_qstate* qstate, int id) if(!generate_sub_request(qstate->qinfo.qname, qstate->qinfo.qname_len, qstate->qinfo.qtype, qstate->qinfo.qclass, qstate, id, iq, - INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { - log_err("out of memory generating prime check"); + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) { + verbose(VERB_ALGO, "could not generate prime check"); } generate_a_aaaa_check(qstate, iq, id); } diff --git a/smallapp/unbound-host.c b/smallapp/unbound-host.c index 43b05432d..c3bc1d0c7 100644 --- a/smallapp/unbound-host.c +++ b/smallapp/unbound-host.c @@ -51,7 +51,7 @@ static int verb = 0; static void usage() { - printf("Usage: unbound-host [-vdhr] [-c class] [-t type] hostname\n"); + printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n"); printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n"); printf(" [-C configfile]\n"); printf(" Queries the DNS for information.\n"); @@ -69,6 +69,8 @@ usage() printf(" breaks validation if the fwder does not do DNSSEC.\n"); printf(" -v be more verbose, shows nodata and security.\n"); printf(" -d debug, traces the action, -d -d shows more.\n"); + printf(" -4 use ipv4 network, avoid ipv6.\n"); + printf(" -6 use ipv6 network, avoid ipv4.\n"); printf(" -h show this usage help.\n"); printf("Version %s\n", PACKAGE_VERSION); printf("BSD licensed, see LICENSE in source package for details.\n"); @@ -413,8 +415,14 @@ int main(int argc, char* argv[]) } /* parse the options */ - while( (c=getopt(argc, argv, "F:c:df:hrt:vy:C:")) != -1) { + while( (c=getopt(argc, argv, "46F:c:df:hrt:vy:C:")) != -1) { switch(c) { + case '4': + check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no")); + break; + case '6': + check_ub_res(ub_ctx_set_option(ctx, "do-ip4:", "no")); + break; case 'c': qclass = optarg; break;