summaryrefslogtreecommitdiff
path: root/iterator
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2013-04-05 09:06:26 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2013-04-05 09:06:26 +0000
commit697291b66c481c617cf9875497e2189bc4a4b096 (patch)
tree5c98c370bedd1d0b4cc456b94e1f7a8ceb080bff /iterator
parentafb79913ce00d885b8b43f7478e1e054edadb567 (diff)
downloadsrc-test2-vendor/unbound/1.4.20.tar.gz
src-test2-vendor/unbound/1.4.20.zip
Diffstat (limited to 'iterator')
-rw-r--r--iterator/iter_fwd.c42
-rw-r--r--iterator/iter_hints.c63
-rw-r--r--iterator/iter_utils.c7
-rw-r--r--iterator/iter_utils.h8
-rw-r--r--iterator/iterator.c69
5 files changed, 104 insertions, 85 deletions
diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c
index 04976db18b8f..0b3b6525c26b 100644
--- a/iterator/iter_fwd.c
+++ b/iterator/iter_fwd.c
@@ -128,7 +128,9 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
node->namelabs = nmlabs;
node->dp = dp;
if(!rbtree_insert(fwd->tree, &node->node)) {
- log_err("duplicate forward zone ignored.");
+ char buf[257];
+ dname_str(nm, buf);
+ log_err("duplicate forward zone %s ignored.", buf);
delegpt_free_mlc(dp);
free(node->name);
free(node);
@@ -250,43 +252,26 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
struct config_stub* s;
for(s = cfg->forwards; s; s = s->next) {
struct delegpt* dp;
- if(!(dp=read_fwds_name(s)) ||
- !read_fwds_host(s, dp) ||
- !read_fwds_addr(s, dp))
+ if(!(dp=read_fwds_name(s)))
return 0;
+ if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) {
+ delegpt_free_mlc(dp);
+ return 0;
+ }
/* set flag that parent side NS information is included.
* Asking a (higher up) server on the internet is not useful */
/* the flag is turned off for 'forward-first' so that the
* last resort will ask for parent-side NS record and thus
* fallback to the internet name servers on a failure */
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
- if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
- return 0;
verbose(VERB_QUERY, "Forward zone server list:");
delegpt_log(VERB_QUERY, dp);
+ if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
+ return 0;
}
return 1;
}
-/** see if zone needs to have a hole inserted */
-static int
-need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone)
-{
- struct iter_forward_zone k;
- if(rbtree_search(tree, zone))
- return 0; /* exact match exists */
- k = *zone;
- k.node.key = &k;
- /* search up the tree */
- do {
- dname_remove_label(&k.name, &k.namelen);
- k.namelabs --;
- if(rbtree_search(tree, &k))
- return 1; /* found an upper forward zone, need hole */
- } while(k.namelabs > 1);
- return 0; /* no forwards above, no holes needed */
-}
-
/** insert a stub hole (if necessary) for stub name */
static int
fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
@@ -296,11 +281,8 @@ fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
key.dclass = c;
key.name = nm;
key.namelabs = dname_count_size_labels(key.name, &key.namelen);
- if(need_hole_insert(fwd->tree, &key)) {
- return forwards_insert_data(fwd, key.dclass, key.name,
- key.namelen, key.namelabs, NULL);
- }
- return 1;
+ return forwards_insert_data(fwd, key.dclass, key.name,
+ key.namelen, key.namelabs, NULL);
}
/** make NULL entries for stubs */
diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c
index cfb9db7abb8c..cde3a7e1bac3 100644
--- a/iterator/iter_hints.c
+++ b/iterator/iter_hints.c
@@ -119,39 +119,42 @@ compile_time_root_prime(int do_ip4, int do_ip6)
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
;
- ; related version of root zone: 2010061700
+ ; related version of root zone: changes-on-20120103
*/
struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000");
if(!dp)
return NULL;
dp->has_parent_side_NS = 1;
if(do_ip4) {
- if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
- if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
- if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
- if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
- if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
- if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
- if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
- if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
- if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
- if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
- if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
- if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
- if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
+ if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
+ if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
+ if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
+ if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
+ if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
+ if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) goto failed;
+ if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) goto failed;
+ if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) goto failed;
+ if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) goto failed;
+ if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) goto failed;
+ if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) goto failed;
+ if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) goto failed;
+ if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) goto failed;
}
if(do_ip6) {
- if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
- if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0;
- if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
- if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
- if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
- if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
- if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
- if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
- if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
+ if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
+ if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
+ if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
+ if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) goto failed;
+ if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
+ if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
+ if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed;
+ if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) goto failed;
+ if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) goto failed;
}
return dp;
+failed:
+ delegpt_free_mlc(dp);
+ return 0;
}
/** insert new hint info into hint structure */
@@ -169,7 +172,9 @@ hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
node->noprime = (uint8_t)noprime;
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
dp->namelabs, c)) {
- log_err("second hints ignored.");
+ char buf[257];
+ dname_str(dp->name, buf);
+ log_err("second hints for zone %s ignored.", buf);
delegpt_free_mlc(dp);
free(node);
}
@@ -253,17 +258,19 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
struct config_stub* s;
struct delegpt* dp;
for(s = cfg->stubs; s; s = s->next) {
- if(!(dp=read_stubs_name(s)) ||
- !read_stubs_host(s, dp) ||
- !read_stubs_addr(s, dp))
+ if(!(dp=read_stubs_name(s)))
+ return 0;
+ if(!read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) {
+ delegpt_free_mlc(dp);
return 0;
+ }
/* the flag is turned off for 'stub-first' so that the
* last resort will ask for parent-side NS record and thus
* fallback to the internet name servers on a failure */
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
+ delegpt_log(VERB_QUERY, dp);
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
return 0;
- delegpt_log(VERB_QUERY, dp);
}
return 1;
}
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index c7a3f4f52952..a500c75e786a 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -418,13 +418,14 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
return m;
}
-int
+void
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
struct regional* region)
{
- return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
- pside, region);
+ if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
+ pside, region))
+ log_err("out of memory: cannot store data in cache");
}
int
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index 4fb8b005c197..8f5a291af678 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -124,9 +124,13 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
* @param pside: true if dp is parentside, thus message is 'fresh' and NS
* can be prefetch-updates.
* @param region: to copy modified (cache is better) rrs back to.
- * @return 0 on alloc error (out of memory).
+ * @return void, because we are not interested in alloc errors,
+ * the iterator and validator can operate on the results in their
+ * scratch space (the qstate.region) and are not dependent on the cache.
+ * It is useful to log the alloc failure (for the server operator),
+ * but the query resolution can continue without cache storage.
*/
-int iter_dns_store(struct module_env* env, struct query_info* qinf,
+void iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
struct regional* region);
diff --git a/iterator/iterator.c b/iterator/iterator.c
index af20c4261b7d..e3f058fe5122 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -259,9 +259,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
/* do not waste time trying to validate this servfail */
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
- if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL)) {
- log_err("error_response_cache: could not store error (nomem)");
- }
+ iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL);
return error_response(qstate, id, rcode);
}
@@ -1432,7 +1430,25 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "No more query targets, attempting last resort");
log_assert(iq->dp);
- if(!iq->dp->has_parent_side_NS) {
+ if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
+ struct delegpt* p = hints_lookup_root(qstate->env->hints,
+ iq->qchase.qclass);
+ if(p) {
+ struct delegpt_ns* ns;
+ struct delegpt_addr* a;
+ iq->chase_flags &= ~BIT_RD; /* go to authorities */
+ for(ns = p->nslist; ns; ns=ns->next) {
+ (void)delegpt_add_ns(iq->dp, qstate->region,
+ ns->name, (int)ns->lame);
+ }
+ for(a = p->target_list; a; a=a->next_target) {
+ (void)delegpt_add_addr(iq->dp, qstate->region,
+ &a->addr, a->addrlen, a->bogus,
+ a->lame);
+ }
+ }
+ iq->dp->has_parent_side_NS = 1;
+ } else if(!iq->dp->has_parent_side_NS) {
if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp,
qstate->region, &qstate->qinfo)
|| !iq->dp->has_parent_side_NS) {
@@ -1440,6 +1456,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
/* if: no parent NS in cache - go up one level */
verbose(VERB_ALGO, "try to grab parent NS");
iq->store_parent_NS = iq->dp;
+ iq->chase_flags &= ~BIT_RD; /* go to authorities */
iq->deleg_msg = NULL;
iq->refetch_glue = 1;
iq->query_restart_count++;
@@ -1541,8 +1558,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
* the final state (i.e., on answer).
*/
static int
-processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq,
- int id)
+processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
{
struct module_qstate* subq = NULL;
verbose(VERB_ALGO, "processDSNSFind");
@@ -1906,13 +1922,20 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
&& !(iq->chase_flags&BIT_RD)
&& iter_ds_toolow(iq->response, iq->dp)
- && iter_dp_cangodown(&iq->qchase, iq->dp))
+ && iter_dp_cangodown(&iq->qchase, iq->dp)) {
+ /* close down outstanding requests to be discarded */
+ outbound_list_clear(&iq->outlist);
+ iq->num_current_queries = 0;
+ fptr_ok(fptr_whitelist_modenv_detach_subs(
+ qstate->env->detach_subs));
+ (*qstate->env->detach_subs)(qstate);
+ iq->num_target_queries = 0;
return processDSNSFind(qstate, iq, id);
- if(!iter_dns_store(qstate->env, &iq->response->qinfo,
+ }
+ iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
- qstate->region))
- return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ qstate->region);
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
@@ -1949,10 +1972,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
)) {
/* Store the referral under the current query */
/* no prefetch-leeway, since its not the answer */
- if(!iter_dns_store(qstate->env, &iq->response->qinfo,
- iq->response->rep, 1, 0, 0, NULL))
- return error_response(qstate, id,
- LDNS_RCODE_SERVFAIL);
+ iter_dns_store(qstate->env, &iq->response->qinfo,
+ iq->response->rep, 1, 0, 0, NULL);
if(iq->store_parent_NS)
iter_store_parentside_NS(qstate->env,
iq->response->rep);
@@ -2032,8 +2053,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
&& !(iq->chase_flags&BIT_RD)
&& iter_ds_toolow(iq->response, iq->dp)
- && iter_dp_cangodown(&iq->qchase, iq->dp))
+ && iter_dp_cangodown(&iq->qchase, iq->dp)) {
+ outbound_list_clear(&iq->outlist);
+ iq->num_current_queries = 0;
+ fptr_ok(fptr_whitelist_modenv_detach_subs(
+ qstate->env->detach_subs));
+ (*qstate->env->detach_subs)(qstate);
+ iq->num_target_queries = 0;
return processDSNSFind(qstate, iq, id);
+ }
/* Process the CNAME response. */
if(!handle_cname_response(qstate, iq, iq->response,
&sname, &snamelen))
@@ -2042,10 +2070,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* NOTE : set referral=1, so that rrsets get stored but not
* the partial query answer (CNAME only). */
/* prefetchleeway applied because this updates answer parts */
- if(!iter_dns_store(qstate->env, &iq->response->qinfo,
+ iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, qstate->prefetch_leeway,
- iq->dp&&iq->dp->has_parent_side_NS, NULL))
- return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ iq->dp&&iq->dp->has_parent_side_NS, NULL);
/* set the current request's qname to the new value. */
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
@@ -2555,12 +2582,10 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
* but only if we did recursion. The nonrecursion referral
* from cache does not need to be stored in the msg cache. */
if(qstate->query_flags&BIT_RD) {
- if(!iter_dns_store(qstate->env, &qstate->qinfo,
+ iter_dns_store(qstate->env, &qstate->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
- qstate->region))
- return error_response(qstate, id,
- LDNS_RCODE_SERVFAIL);
+ qstate->region);
}
}
qstate->return_rcode = LDNS_RCODE_NOERROR;