- 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.


git-svn-id: file:///svn/unbound/trunk@1444 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2009-01-16 10:38:19 +00:00
parent 37c3bef544
commit 7ac31bc1d5
4 changed files with 45 additions and 15 deletions

View file

@ -2,6 +2,11 @@
- more quiet about ipv6 network failures, i.e. when ipv6 is not - more quiet about ipv6 network failures, i.e. when ipv6 is not
available (network unreachable). Debug still printed on high available (network unreachable). Debug still printed on high
verbosity. 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 15 January 2009: Wouter
- bug #229: fixup configure checks for compilation with Solaris - bug #229: fixup configure checks for compilation with Solaris

View file

@ -14,7 +14,7 @@
.SH "SYNOPSIS" .SH "SYNOPSIS"
.LP .LP
.B unbound\-host .B unbound\-host
.RB [ \-vdhr ] .RB [ \-vdhr46 ]
.RB [ \-c .RB [ \-c
.IR class ] .IR class ]
.RB [ \-t .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 have been set by DHCP). More info in
.IR resolv.conf (5). .IR resolv.conf (5).
Breaks validation if those servers do not support DNSSEC. 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" .SH "EXAMPLES"
.LP .LP
Some examples of use. The keys shown below are fakes, thus a security failure Some examples of use. The keys shown below are fakes, thus a security failure

View file

@ -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 * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does
* not need initialisation. * not need initialisation.
* @param v: if true, validation is done on the subquery. * @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). * @return false on error (malloc).
*/ */
static int static int
generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, struct module_qstate* qstate, int id, uint16_t qclass, struct module_qstate* qstate, int id,
struct iter_qstate* iq, enum iter_state initial_state, 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 module_qstate* subq = NULL;
struct iter_qstate* subiq = NULL; struct iter_qstate* subiq = NULL;
@ -488,6 +490,15 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
* path. */ * path. */
if(!v) if(!v)
qflags |= BIT_CD; 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 */ /* attach subquery, lookup existing or make a new one */
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); 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). */ * the normal INIT state logic (which would cause an infloop). */
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE, qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
&subq, 0)) { &subq, 0, 1)) {
log_err("out of memory priming root"); verbose(VERB_ALGO, "could not prime root");
return 0; return 0;
} }
if(subq) { if(subq) {
@ -624,8 +635,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
* redundant INIT state processing. */ * redundant INIT state processing. */
if(!generate_sub_request(stub_dp->name, stub_dp->namelen, if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
LDNS_RR_TYPE_NS, qclass, qstate, id, iq, LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) { QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 1)) {
log_err("out of memory priming stub"); verbose(VERB_ALGO, "could not prime stub");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return 1; /* return 1 to make module stop, with error */ 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, if(!generate_sub_request(s->rk.dname, s->rk.dname_len,
ntohs(s->rk.type), ntohs(s->rk.rrset_class), ntohs(s->rk.type), ntohs(s->rk.rrset_class),
qstate, id, iq, qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
log_err("out of memory generating ns check"); verbose(VERB_ALGO, "could not generate addr check");
return; return;
} }
/* ignore subq - not need for more init */ /* 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); iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
if(!generate_sub_request(iq->dp->name, iq->dp->namelen, if(!generate_sub_request(iq->dp->name, iq->dp->namelen,
LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
log_err("out of memory generating ns check"); verbose(VERB_ALGO, "could not generate ns check");
return; return;
} }
if(subq) { if(subq) {
@ -1086,7 +1097,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
{ {
struct module_qstate* subq; struct module_qstate* subq;
if(!generate_sub_request(name, namelen, qtype, qclass, qstate, 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; return 0;
if(subq) { if(subq) {
struct iter_qstate* subiq = struct iter_qstate* subiq =
@ -1721,8 +1732,8 @@ processPrimeResponse(struct module_qstate* qstate, int id)
if(!generate_sub_request(qstate->qinfo.qname, if(!generate_sub_request(qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype, qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate, id, iq, qstate->qinfo.qclass, qstate, id, iq,
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 1)) {
log_err("out of memory generating prime check"); verbose(VERB_ALGO, "could not generate prime check");
} }
generate_a_aaaa_check(qstate, iq, id); generate_a_aaaa_check(qstate, iq, id);
} }

View file

@ -51,7 +51,7 @@ static int verb = 0;
static void static void
usage() 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(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
printf(" [-C configfile]\n"); printf(" [-C configfile]\n");
printf(" Queries the DNS for information.\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(" breaks validation if the fwder does not do DNSSEC.\n");
printf(" -v be more verbose, shows nodata and security.\n"); printf(" -v be more verbose, shows nodata and security.\n");
printf(" -d debug, traces the action, -d -d shows more.\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(" -h show this usage help.\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");
@ -413,8 +415,14 @@ int main(int argc, char* argv[])
} }
/* parse the options */ /* 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) { 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': case 'c':
qclass = optarg; qclass = optarg;
break; break;