$(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \
- $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/iterator/iter_fwd.h
+ $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
- $(srcdir)/sldns/str2wire.h
+ $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/str2wire.h
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
return 0;
continue;
}
- }
+ }
+ lock_rw_rdlock(&worker->env.hints->lock);
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
dp);
if(stub) {
if(stub->noprime) {
if(!ssl_printf(ssl, "The noprime stub servers "
- "are used:\n"))
+ "are used:\n")) {
+ lock_rw_unlock(&worker->env.hints->lock);
return 0;
+ }
} else {
if(!ssl_printf(ssl, "The stub is primed "
- "with servers:\n"))
+ "with servers:\n")) {
+ lock_rw_unlock(&worker->env.hints->lock);
return 0;
+ }
}
print_dp_main(ssl, stub->dp, NULL);
print_dp_details(ssl, worker, stub->dp);
+ lock_rw_unlock(&worker->env.hints->lock);
} else {
+ lock_rw_unlock(&worker->env.hints->lock);
print_dp_main(ssl, dp, msg);
print_dp_details(ssl, worker, dp);
}
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
#include <signal.h>
#ifdef HAVE_SYSTEMD
if(!(daemon->env->fwds = forwards_create()) ||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
fatal_exit("Could not set forward zones");
+ if(!(daemon->env->hints = hints_create()) ||
+ !hints_apply_cfg(daemon->env->hints, daemon->cfg))
+ fatal_exit("Could not set root or stub hints");
/* process raw response-ip configuration data */
if(!(daemon->respip_set = respip_set_create()))
daemon->old_num = daemon->num; /* save the current num */
forwards_delete(daemon->env->fwds);
daemon->env->fwds = NULL;
+ hints_delete(daemon->env->hints);
+ daemon->env->hints = NULL;
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
respip_set_delete(daemon->respip_set);
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
return;
lock_rw_wrlock(&fwd->lock);
+ lock_rw_wrlock(&worker->env.hints->lock);
if(insecure && worker->env.anchors) {
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm)) {
+ lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&worker->env.hints->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&worker->env.hints->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&worker->env.hints->lock);
free(nm);
return;
}
lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&worker->env.hints->lock);
free(nm);
send_ok(ssl);
}
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
return;
lock_rw_wrlock(&fwd->lock);
+ lock_rw_wrlock(&worker->env.hints->lock);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm);
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&worker->env.hints->lock);
free(nm);
send_ok(ssl);
}
struct trust_anchor* a;
int insecure;
char str[32];
+ lock_rw_rdlock(&worker->env.hints->lock);
RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
/* see if it is insecure */
snprintf(str, sizeof(str), "stub %sprime%s",
(z->noprime?"no":""), (insecure?" +i":""));
if(!ssl_print_name_dp(ssl, str, z->node.name,
- z->node.dclass, z->dp))
+ z->node.dclass, z->dp)) {
+ lock_rw_unlock(&worker->env.hints->lock);
return;
+ }
}
+ lock_rw_unlock(&worker->env.hints->lock);
}
/** do the list_auth_zones command */
} else if(cmdcmp(p, "auth_zone_transfer", 18)) {
do_auth_zone_transfer(ssl, worker, skipwhite(p+18));
return;
- } else if(cmdcmp(p, "stub_add", 8)) {
- /* must always distribute this cmd */
- if(rc) distribute_cmd(rc, ssl, cmd);
- do_stub_add(ssl, worker, skipwhite(p+8));
- return;
- } else if(cmdcmp(p, "stub_remove", 11)) {
- /* must always distribute this cmd */
- if(rc) distribute_cmd(rc, ssl, cmd);
- do_stub_remove(ssl, worker, skipwhite(p+11));
- return;
} else if(cmdcmp(p, "insecure_add", 12)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_forward_remove(ssl, worker, skipwhite(p+14));
} else if(cmdcmp(p, "forward", 7)) {
do_forward(ssl, worker, skipwhite(p+7));
+ } else if(cmdcmp(p, "stub_add", 8)) {
+ do_stub_add(ssl, worker, skipwhite(p+8));
+ } else if(cmdcmp(p, "stub_remove", 11)) {
+ do_stub_remove(ssl, worker, skipwhite(p+11));
} else if(cmdcmp(p, "view_local_zone_remove", 22)) {
do_view_zone_remove(ssl, worker, skipwhite(p+22));
} else if(cmdcmp(p, "view_local_zone", 15)) {
worker_delete(worker);
return 0;
}
- if(!(worker->env.hints = hints_create()) ||
- !hints_apply_cfg(worker->env.hints, cfg)) {
- log_err("Could not set root or stub hints");
- worker_delete(worker);
- return 0;
- }
/* one probe timer per process -- if we have 5011 anchors */
if(autr_get_num_anchors(worker->env.anchors) > 0
#ifndef THREADS_DISABLED
outside_network_quit_prepare(worker->back);
mesh_delete(worker->env.mesh);
sldns_buffer_free(worker->env.scratch_buffer);
- hints_delete(worker->env.hints);
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);
struct iter_forwards {
/** lock on the forwards tree.
* When grabbing both this lock and the anchors.lock, this lock
- * is grabbed first. */
+ * is grabbed first. When grabbing both this lock and the hints.lock
+ * this lock is grabbed first. */
lock_rw_type lock;
/**
* Zones are stored in this tree. Sort order is specially chosen.
sizeof(struct iter_hints));
if(!hints)
return NULL;
+ lock_rw_init(&hints->lock);
+ lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
return hints;
}
{
if(!hints)
return;
+ lock_rw_destroy(&hints->lock);
hints_del_tree(hints);
free(hints);
}
int
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
{
+ lock_rw_wrlock(&hints->lock);
hints_del_tree(hints);
name_tree_init(&hints->tree);
-
+
/* read root hints */
- if(!read_root_hints_list(hints, cfg))
+ if(!read_root_hints_list(hints, cfg)) {
+ lock_rw_unlock(&hints->lock);
return 0;
+ }
/* read stub hints */
- if(!read_stubs(hints, cfg))
+ if(!read_stubs(hints, cfg)) {
+ lock_rw_unlock(&hints->lock);
return 0;
+ }
/* use fallback compiletime root hints */
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
cfg->do_ip6);
verbose(VERB_ALGO, "no config, using builtin root hints.");
- if(!dp)
+ if(!dp) {
+ lock_rw_unlock(&hints->lock);
return 0;
- if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
+ }
+ if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
+ lock_rw_unlock(&hints->lock);
return 0;
+ }
}
name_tree_init_parents(&hints->tree);
+ lock_rw_unlock(&hints->lock);
return 1;
}
size_t s;
struct iter_hints_stub* p;
if(!hints) return 0;
+ lock_rw_rdlock(&hints->lock);
s = sizeof(*hints);
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
s += sizeof(*p) + delegpt_get_mem(p->dp);
}
+ lock_rw_unlock(&hints->lock);
return s;
}
#ifndef ITERATOR_ITER_HINTS_H
#define ITERATOR_ITER_HINTS_H
#include "util/storage/dnstree.h"
+#include "util/locks.h"
struct iter_env;
struct config_file;
struct delegpt;
* Iterator hints structure
*/
struct iter_hints {
+ /** lock on the forwards tree.
+ * When grabbing both this lock and the anchors.lock, this lock
+ * is grabbed first. */
+ lock_rw_type lock;
/**
* Hints are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
/**
* Get memory in use by hints
+ * Locks and unlocks the structure.
* @param hints: hint storage.
* @return bytes in use
*/
uint16_t* c)
{
uint16_t c1 = *c, c2 = *c;
- int r1 = hints_next_root(hints, &c1);
- int r2;
+ int r1, r2;
lock_rw_rdlock(&fwd->lock);
+ lock_rw_rdlock(&hints->lock);
+ r1 = hints_next_root(hints, &c1);
r2 = forwards_next_root(fwd, &c2);
lock_rw_unlock(&fwd->lock);
+ lock_rw_unlock(&hints->lock);
if(!r1 && !r2) /* got none, end of list */
return 0;
struct delegpt *dp;
/* Check for stub. */
+ lock_rw_rdlock(&qstate->env->fwds->lock);
+ lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
qinf->qclass, NULL);
- lock_rw_rdlock(&qstate->env->fwds->lock);
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
/* see if forward or stub is more pertinent */
/* check stub */
if (stub != NULL && stub->dp != NULL) {
+ int stub_no_cache = stub->dp->no_cache;
lock_rw_unlock(&qstate->env->fwds->lock);
- if(stub->dp->no_cache) {
+ if(stub_no_cache) {
char qname[255+1];
char dpname[255+1];
dname_str(qinf->qname, qname);
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
- *retdpname = stub->dp->name;
+ if(stub->dp->namelen > dpname_storage_len) {
+ verbose(VERB_ALGO, "no cache stub dpname too long");
+ lock_rw_unlock(&qstate->env->hints->lock);
+ *retdpname = NULL;
+ *retdpnamelen = 0;
+ return stub_no_cache;
+ }
+ memmove(dpname_storage, stub->dp->name,
+ stub->dp->namelen);
+ *retdpname = dpname_storage;
*retdpnamelen = stub->dp->namelen;
}
- return (stub->dp->no_cache);
+ lock_rw_unlock(&qstate->env->hints->lock);
+ return stub_no_cache;
}
/* Check for forward. */
if (dp) {
int dp_no_cache = dp->no_cache;
+ lock_rw_unlock(&qstate->env->hints->lock);
if(dp_no_cache) {
char qname[255+1];
char dpname[255+1];
if(dp->namelen > dpname_storage_len) {
verbose(VERB_ALGO, "no cache dpname too long");
lock_rw_unlock(&qstate->env->fwds->lock);
- return (dp_no_cache);
+ *retdpname = NULL;
+ *retdpnamelen = 0;
+ return dp_no_cache;
}
memmove(dpname_storage, dp->name, dp->namelen);
*retdpname = dpname_storage;
*retdpnamelen = dp->namelen;
}
lock_rw_unlock(&qstate->env->fwds->lock);
- return (dp_no_cache);
+ return dp_no_cache;
}
lock_rw_unlock(&qstate->env->fwds->lock);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(retdpname) {
*retdpname = NULL;
*retdpnamelen = 0;
/* do not process a last resort (the parent side) if a stub
* or forward is configured, because we do not want to go 'above'
* the configured servers */
+ lock_rw_rdlock(&env->hints->lock);
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
/* has_parent side is turned off for stub_first, where we
* are allowed to go to the parent */
stub->dp->has_parent_side_NS) {
- if(retdp) *retdp = stub->dp;
+ if(retdp) *retdp = delegpt_copy(stub->dp, region);
+ lock_rw_unlock(&env->hints->lock);
if(have_dp) *have_dp = 1;
return 0;
}
+ lock_rw_unlock(&env->hints->lock);
lock_rw_rdlock(&env->fwds->lock);
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
/* has_parent_side is turned off for forward_first, where
verbose(VERB_DETAIL, "priming . %s NS",
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??");
+ lock_rw_rdlock(&qstate->env->hints->lock);
dp = hints_lookup_root(qstate->env->hints, qclass);
if(!dp) {
+ lock_rw_unlock(&qstate->env->hints->lock);
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
return 0;
}
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
&subq, 0, 0)) {
+ lock_rw_unlock(&qstate->env->hints->lock);
verbose(VERB_ALGO, "could not prime root");
return 0;
}
* copy dp, it is now part of the root prime query.
* dp was part of in the fixed hints structure. */
subiq->dp = delegpt_copy(dp, subq->region);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(!subiq->dp) {
log_err("out of memory priming root, copydp");
fptr_ok(fptr_whitelist_modenv_kill_sub(
subiq->num_target_queries = 0;
subiq->dnssec_expected = iter_indicates_dnssec(
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
+ } else {
+ lock_rw_unlock(&qstate->env->hints->lock);
}
/* this module stops, our submodule starts, and does the query. */
struct module_qstate* subq;
if(!qname) return 0;
+ lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp);
/* The stub (if there is one) does not need priming. */
- if(!stub)
+ if(!stub) {
+ lock_rw_unlock(&qstate->env->hints->lock);
return 0;
+ }
stub_dp = stub->dp;
/* if we have an auth_zone dp, and stub is equal, don't prime stub
* yet, unless we want to fallback and avoid the auth_zone */
if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
- query_dname_compare(iq->dp->name, stub_dp->name) == 0)
+ query_dname_compare(iq->dp->name, stub_dp->name) == 0) {
+ lock_rw_unlock(&qstate->env->hints->lock);
return 0;
+ }
/* is it a noprime stub (always use) */
if(stub->noprime) {
/* copy the dp out of the fixed hints structure, so that
* it can be changed when servicing this query */
iq->dp = delegpt_copy(stub_dp, qstate->region);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory priming stub");
errinf(qstate, "malloc failure, priming stub");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return 1; /* return 1 to make module stop, with error */
}
- log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name,
+ log_nametypeclass(VERB_DETAIL, "use stub", iq->dp->name,
LDNS_RR_TYPE_NS, qclass);
return r;
}
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, 0)) {
+ lock_rw_unlock(&qstate->env->hints->lock);
verbose(VERB_ALGO, "could not prime stub");
errinf(qstate, "could not generate lookup for stub prime");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
/* Set the initial delegation point to the hint. */
/* make copy to avoid use of stub dp by different qs/threads */
subiq->dp = delegpt_copy(stub_dp, subq->region);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(!subiq->dp) {
log_err("out of memory priming stub, copydp");
fptr_ok(fptr_whitelist_modenv_kill_sub(
subiq->wait_priming_stub = 1;
subiq->dnssec_expected = iter_indicates_dnssec(
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
+ } else {
+ lock_rw_unlock(&qstate->env->hints->lock);
}
/* this module stops, our submodule starts, and does the query. */
lock_rw_unlock(&qstate->env->fwds->lock);
/* forward zone root, no root prime needed */
/* fill in some dp - safety belt */
+ lock_rw_rdlock(&qstate->env->hints->lock);
iq->dp = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
if(!iq->dp) {
+ lock_rw_unlock(&qstate->env->hints->lock);
log_err("internal error: no hints dp");
errinf(qstate, "no hints for this class");
return error_response(qstate, id,
LDNS_RCODE_SERVFAIL);
}
iq->dp = delegpt_copy(iq->dp, qstate->region);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory in safety belt");
errinf(qstate, "malloc failure, in safety belt");
/* use safety belt */
verbose(VERB_QUERY, "Cache has root NS but "
"no addresses. Fallback to the safety belt.");
+ lock_rw_rdlock(&qstate->env->hints->lock);
iq->dp = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
/* note deleg_msg is from previous lookup,
* but RD is on, so it is not used */
if(!iq->dp) {
+ lock_rw_unlock(&qstate->env->hints->lock);
log_err("internal error: no hints dp");
return error_response(qstate, id,
LDNS_RCODE_REFUSED);
}
iq->dp = delegpt_copy(iq->dp, qstate->region);
+ lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory in safety belt");
errinf(qstate, "malloc failure, in safety belt, for root");
}
/* Do not send queries above stub, do not set delname to dp if
* this is above stub without stub-first. */
+ lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
iq->dp);
delname = iq->dp->name;
delnamelen = iq->dp->namelen;
}
+ lock_rw_unlock(&qstate->env->hints->lock);
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
if(!dname_is_root(delname))
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
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);
+ struct delegpt* p;
+ lock_rw_rdlock(&qstate->env->hints->lock);
+ p = hints_lookup_root(qstate->env->hints, iq->qchase.qclass);
if(p) {
struct delegpt_addr* a;
iq->chase_flags &= ~BIT_RD; /* go to authorities */
a->lame, a->tls_auth_name, -1, NULL);
}
}
+ lock_rw_unlock(&qstate->env->hints->lock);
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,
#include "util/edns.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
int
context_finalize(struct ub_ctx* ctx)
if(!(ctx->env->fwds = forwards_create()) ||
!forwards_apply_cfg(ctx->env->fwds, cfg))
return UB_INITFAIL;
+ if(!(ctx->env->hints = hints_create()) ||
+ !hints_apply_cfg(ctx->env->hints, cfg))
+ return UB_INITFAIL;
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
return UB_INITFAIL;
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
#include "services/listen_dnsport.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
+#include "iterator/iter_hints.h"
#ifdef HAVE_PTHREAD
#include <signal.h>
#endif
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
forwards_delete(ctx->env->fwds);
+ hints_delete(ctx->env->hints);
auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/tube.h"
-#include "iterator/iter_fwd.h"
-#include "iterator/iter_hints.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
#ifdef USE_DNSTAP
!w->is_bg || w->is_bg_thread);
sldns_buffer_free(w->env->scratch_buffer);
regional_destroy(w->env->scratch);
- hints_delete(w->env->hints);
ub_randfree(w->env->rnd);
free(w->env);
}
}
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
- w->env->hints = hints_create();
- if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
- hints_delete(w->env->hints);
- w->env->hints = NULL;
- }
#ifdef HAVE_SSL
w->sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert);
if(!w->sslctx) {
/* to make the setup fail after unlock */
- hints_delete(w->env->hints);
- w->env->hints = NULL;
+ sldns_buffer_free(w->env->scratch_buffer);
+ w->env->scratch_buffer = NULL;
}
#endif
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
- if(!w->env->scratch || !w->env->scratch_buffer || !w->env->hints) {
+ if(!w->env->scratch || !w->env->scratch_buffer) {
libworker_delete(w);
return NULL;
}
dname_str((uint8_t*)nm, b);
continue;
}
+ lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp);
if (stub) {
- return stub->dp;
+ struct delegpt* stubdp = delegpt_copy(stub->dp, region);
+ lock_rw_unlock(&qstate->env->hints->lock);
+ return stubdp;
} else {
+ lock_rw_unlock(&qstate->env->hints->lock);
return dp;
}
}
* iterator forwarder information. */
struct iter_forwards* fwds;
/**
- * iterator forwarder information. per-thread, created by worker.
+ * iterator stub information.
* The hints -- these aren't stored in the cache because they don't
* expire. The hints are always used to "prime" the cache. Note
* that both root hints and stub zone "hints" are stored in this