* @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;
* 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));
* 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) {
* 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 */
}
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 */
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) {
{
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 =
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);
}
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");
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");
}
/* 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;