$(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)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/iterator/iter_fwd.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)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h $(srcdir)/iterator/iter_fwd.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)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/iterator/iter_fwd.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 \
static int
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
{
+ uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
uint8_t* dpname=NULL;
size_t dpnamelen=0;
struct dns_msg* msg;
return 0;
}
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
- &dpname, &dpnamelen))
+ &dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
return 0; /* no cache for these queries */
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
if(!ssl_printf(ssl, "The following name servers are used for lookup "
"of %s\n", b))
return 0;
-
+
+ lock_rw_rdlock(&worker->env.fwds->lock);
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
if(dp) {
- if(!ssl_printf(ssl, "forwarding request:\n"))
+ if(!ssl_printf(ssl, "forwarding request:\n")) {
+ lock_rw_unlock(&worker->env.fwds->lock);
return 0;
+ }
print_dp_main(ssl, dp, NULL);
print_dp_details(ssl, worker, dp);
+ lock_rw_unlock(&worker->env.fwds->lock);
return 1;
}
+ lock_rw_unlock(&worker->env.fwds->lock);
while(1) {
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
#include "util/net_help.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
+#include "iterator/iter_fwd.h"
#include <signal.h>
#ifdef HAVE_SYSTEMD
fatal_exit("Could not create local zones: out of memory");
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
fatal_exit("Could not set up local zones");
+ if(!(daemon->env->fwds = forwards_create()) ||
+ !forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
+ fatal_exit("Could not set forward zones");
/* process raw response-ip configuration data */
if(!(daemon->respip_set = respip_set_create()))
slabhash_clear(daemon->env->msg_cache);
}
daemon->old_num = daemon->num; /* save the current num */
+ forwards_delete(daemon->env->fwds);
+ daemon->env->fwds = NULL;
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
respip_set_delete(daemon->respip_set);
print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root)
{
struct delegpt* dp;
+ lock_rw_rdlock(&fwds->lock);
dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
- if(!dp)
+ if(!dp) {
+ lock_rw_unlock(&fwds->lock);
return ssl_printf(ssl, "off (using root hints)\n");
+ }
/* if dp is returned it must be the root */
log_assert(query_dname_compare(dp->name, root)==0);
- return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp);
+ if(!ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp)) {
+ lock_rw_unlock(&fwds->lock);
+ return 0;
+ }
+ lock_rw_unlock(&fwds->lock);
+ return 1;
}
/** parse args into delegpt */
/* delete all the existing queries first */
mesh_delete_all(worker->env.mesh);
if(strcmp(args, "off") == 0) {
+ lock_rw_wrlock(&fwd->lock);
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
+ lock_rw_unlock(&fwd->lock);
} else {
struct delegpt* dp;
if(!(dp = parse_delegpt(ssl, args, root)))
return;
+ lock_rw_wrlock(&fwd->lock);
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
+ lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
return;
}
+ lock_rw_unlock(&fwd->lock);
}
send_ok(ssl);
}
return;
if(tls)
dp->ssl_upstream = 1;
+ lock_rw_wrlock(&fwd->lock);
if(insecure && worker->env.anchors) {
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm)) {
+ lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
}
}
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
+ lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
free(nm);
return;
}
+ lock_rw_unlock(&fwd->lock);
free(nm);
send_ok(ssl);
}
uint8_t* nm = NULL;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL))
return;
+ lock_rw_wrlock(&fwd->lock);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm);
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm);
+ lock_rw_unlock(&fwd->lock);
free(nm);
send_ok(ssl);
}
return;
if(tls)
dp->ssl_upstream = 1;
+ lock_rw_wrlock(&fwd->lock);
if(insecure && worker->env.anchors) {
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm)) {
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
+ lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
+ lock_rw_unlock(&fwd->lock);
free(nm);
return;
}
+ lock_rw_unlock(&fwd->lock);
free(nm);
send_ok(ssl);
}
uint8_t* nm = NULL;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL))
return;
+ lock_rw_wrlock(&fwd->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);
free(nm);
send_ok(ssl);
}
struct iter_forward_zone* z;
struct trust_anchor* a;
int insecure;
+ lock_rw_rdlock(&fwds->lock);
RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) {
if(!z->dp) continue; /* skip empty marker for stub */
}
if(!ssl_print_name_dp(ssl, (insecure?"forward +i":"forward"),
- z->name, z->dclass, z->dp))
+ z->name, z->dclass, z->dp)) {
+ lock_rw_unlock(&fwds->lock);
return;
+ }
}
+ lock_rw_unlock(&fwds->lock);
}
/** do the list_stubs command */
do_stub_remove(ssl, worker, skipwhite(p+11));
return;
} else if(cmdcmp(p, "forward_add", 11)) {
- /* must always distribute this cmd */
- if(rc) distribute_cmd(rc, ssl, cmd);
do_forward_add(ssl, worker, skipwhite(p+11));
return;
} else if(cmdcmp(p, "forward_remove", 14)) {
- /* must always distribute this cmd */
- if(rc) distribute_cmd(rc, ssl, cmd);
do_forward_remove(ssl, worker, skipwhite(p+14));
return;
} else if(cmdcmp(p, "insecure_add", 12)) {
do_insecure_remove(ssl, worker, skipwhite(p+15));
return;
} else if(cmdcmp(p, "forward", 7)) {
- /* must always distribute this cmd */
- if(rc) distribute_cmd(rc, ssl, cmd);
do_forward(ssl, worker, skipwhite(p+7));
return;
} else if(cmdcmp(p, "flush_stats", 11)) {
worker_delete(worker);
return 0;
}
- if(!(worker->env.fwds = forwards_create()) ||
- !forwards_apply_cfg(worker->env.fwds, cfg)) {
- log_err("Could not set forward zones");
- 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");
outside_network_quit_prepare(worker->back);
mesh_delete(worker->env.mesh);
sldns_buffer_free(worker->env.scratch_buffer);
- forwards_delete(worker->env.fwds);
hints_delete(worker->env.hints);
listen_delete(worker->front);
outside_network_delete(worker->back);
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
- if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
+ if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
qstate->no_cache_store = 0;
}
sizeof(struct iter_forwards));
if(!fwd)
return NULL;
+ lock_rw_init(&fwd->lock);
return fwd;
}
{
if(!fwd)
return;
+ lock_rw_destroy(&fwd->lock);
fwd_del_tree(fwd);
free(fwd);
}
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
+ if(fwd->tree) {
+ lock_unprotect(&fwd->lock, fwd->tree);
+ }
fwd_del_tree(fwd);
fwd->tree = rbtree_create(fwd_cmp);
if(!fwd->tree)
return 0;
+ lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
+ lock_rw_wrlock(&fwd->lock);
/* read forward zones */
- if(!read_forwards(fwd, cfg))
+ if(!read_forwards(fwd, cfg)) {
+ lock_rw_unlock(&fwd->lock);
return 0;
- if(!make_stub_holes(fwd, cfg))
+ }
+ if(!make_stub_holes(fwd, cfg)) {
+ lock_rw_unlock(&fwd->lock);
return 0;
+ }
fwd_init_parents(fwd);
+ lock_rw_unlock(&fwd->lock);
return 1;
}
size_t s;
if(!fwd)
return 0;
+ lock_rw_rdlock(&fwd->lock);
s = sizeof(*fwd) + sizeof(*fwd->tree);
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
}
+ lock_rw_unlock(&fwd->lock);
return s;
}
int
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
{
+ if(fwd_zone_find(fwd, c, nm) != NULL)
+ return 1; /* already a stub zone there */
if(!fwd_add_stub_hole(fwd, c, nm)) {
return 0;
}
#ifndef ITERATOR_ITER_FWD_H
#define ITERATOR_ITER_FWD_H
#include "util/rbtree.h"
+#include "util/locks.h"
struct config_file;
struct delegpt;
* Iterator forward zones structure
*/
struct iter_forwards {
+ /** lock on the forwards tree.
+ * When grabbing both this lock and the anchors.lock, this lock
+ * is grabbed first. */
+ lock_rw_type lock;
/**
* Zones are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
/**
* Find forward zone exactly by name
+ * The return value is contents of the forwards structure, caller should
+ * lock and unlock a readlock on the forwards structure.
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* Find forward zone information
* For this qname/qclass find forward zone information, returns delegation
* point with server names and addresses, or NULL if no forwarding is needed.
+ * The return value is contents of the forwards structure, caller should
+ * lock and unlock a readlock on the forwards structure.
*
* @param fwd: forward storage.
* @param qname: The qname of the query.
/**
* Get memory in use by forward storage
+ * Locks and unlocks the structure.
* @param fwd: forward storage.
* @return bytes in use
*/
{
uint16_t c1 = *c, c2 = *c;
int r1 = hints_next_root(hints, &c1);
- int r2 = forwards_next_root(fwd, &c2);
+ int r2;
+
+ lock_rw_rdlock(&fwd->lock);
+ r2 = forwards_next_root(fwd, &c2);
+ lock_rw_unlock(&fwd->lock);
+
if(!r1 && !r2) /* got none, end of list */
return 0;
else if(!r1) /* got one, return that */
int
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
- uint8_t** retdpname, size_t* retdpnamelen)
+ uint8_t** retdpname, size_t* retdpnamelen, uint8_t* dpname_storage,
+ size_t dpname_storage_len)
{
struct iter_hints_stub *stub;
struct delegpt *dp;
/* Check for stub. */
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) {
+ lock_rw_unlock(&qstate->env->fwds->lock);
if(stub->dp->no_cache) {
char qname[255+1];
char dpname[255+1];
/* Check for forward. */
if (dp) {
- if(dp->no_cache) {
+ int dp_no_cache = dp->no_cache;
+ if(dp_no_cache) {
char qname[255+1];
char dpname[255+1];
dname_str(qinf->qname, qname);
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
- *retdpname = dp->name;
+ 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);
+ }
+ memmove(dpname_storage, dp->name, dp->namelen);
+ *retdpname = dpname_storage;
*retdpnamelen = dp->namelen;
}
- return (dp->no_cache);
+ lock_rw_unlock(&qstate->env->fwds->lock);
+ return (dp_no_cache);
}
+ lock_rw_unlock(&qstate->env->fwds->lock);
if(retdpname) {
*retdpname = NULL;
*retdpnamelen = 0;
* Used for NXDOMAIN checks, above that it is an nxdomain from a
* different server and zone. You can pass NULL to not get it.
* @param retdpnamelen: returns the length of the dpname.
+ * @param dpname_storage: this is where the dpname buf is stored, if any.
+ * So that caller can manage the buffer.
+ * @param dpname_storage_len: size of dpname_storage buffer.
* @return true if no_cache is set in stub or fwd.
*/
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
- struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
+ struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen,
+ uint8_t* dpname_storage, size_t dpname_storage_len);
/**
* Set support for IP4 and IP6 depending on outgoing interfaces
/** see if last resort is possible - does config allow queries to parent */
static int
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
- uint16_t qclass, struct delegpt** retdp)
+ uint16_t qclass, int* have_dp, struct delegpt** retdp,
+ struct regional* region)
{
struct delegpt* fwddp;
struct iter_hints_stub* stub;
* are allowed to go to the parent */
stub->dp->has_parent_side_NS) {
if(retdp) *retdp = stub->dp;
+ if(have_dp) *have_dp = 1;
return 0;
}
+ lock_rw_rdlock(&env->fwds->lock);
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
/* has_parent_side is turned off for forward_first, where
* we are allowed to go to the parent */
fwddp->has_parent_side_NS) {
- if(retdp) *retdp = fwddp;
+ if(retdp) *retdp = delegpt_copy(fwddp, region);
+ lock_rw_unlock(&env->fwds->lock);
+ if(have_dp) *have_dp = 1;
return 0;
}
+ lock_rw_unlock(&env->fwds->lock);
return 1;
}
if(iq->depth == ie->max_dependency_depth)
return;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
- iq->qchase.qclass, NULL))
+ iq->qchase.qclass, NULL, NULL, NULL))
return;
/* is this query the same as the nscheck? */
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue)
&& !dname_is_root(iq->qchase.qname))
dname_remove_label(&delname, &delnamelen);
+ lock_rw_rdlock(&qstate->env->fwds->lock);
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass);
- if(!dp)
+ if(!dp) {
+ lock_rw_unlock(&qstate->env->fwds->lock);
return 0;
+ }
/* send recursion desired to forward addr */
iq->chase_flags |= BIT_RD;
iq->dp = delegpt_copy(dp, qstate->region);
+ lock_rw_unlock(&qstate->env->fwds->lock);
/* iq->dp checked by caller */
verbose(VERB_ALGO, "forwarding request");
return 1;
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id)
{
+ uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
uint8_t* delname, *dpname=NULL;
size_t delnamelen, dpnamelen=0;
struct dns_msg* msg = NULL;
if (iq->refetch_glue &&
iq->dp &&
!can_have_last_resort(qstate->env, iq->dp->name,
- iq->dp->namelen, iq->qchase.qclass, NULL)) {
+ iq->dp->namelen, iq->qchase.qclass, NULL, NULL, NULL)) {
iq->refetch_glue = 0;
}
}
}
- if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) {
+ if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen,
+ dpname_storage, sizeof(dpname_storage))) {
/* Asked to not query cache. */
verbose(VERB_ALGO, "no-cache set, going to the network");
qstate->no_cache_lookup = 1;
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
- && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
+ && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL, NULL, NULL))) {
/* remove first label from delname, root goes to hints,
* but only to fetch glue, not for qtype=DS. */
/* also when prefetching an NS record, fetch it again from
break; /* got noprime-stub-zone, continue */
else if(r)
return 0; /* stub prime request made */
+ lock_rw_rdlock(&qstate->env->fwds->lock);
if(forwards_lookup_root(qstate->env->fwds,
iq->qchase.qclass)) {
+ lock_rw_unlock(&qstate->env->fwds->lock);
/* forward zone root, no root prime needed */
/* fill in some dp - safety belt */
iq->dp = hints_lookup_root(qstate->env->hints,
}
return next_state(iq, INIT_REQUEST_2_STATE);
}
+ lock_rw_unlock(&qstate->env->fwds->lock);
/* Note that the result of this will set a new
* DelegationPoint based on the result of priming. */
if(!prime_root(qstate, iq, id, iq->qchase.qclass))
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
ie->use_nat64)) {
- struct delegpt* retdp = NULL;
- if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
- if(retdp) {
+ int have_dp = 0;
+ if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
+ if(have_dp) {
verbose(VERB_QUERY, "cache has stub "
"or fwd but no addresses, "
"fallback to config");
- iq->dp = delegpt_copy(retdp,
- qstate->region);
- if(!iq->dp) {
+ if(have_dp && !iq->dp) {
log_err("out of memory in "
"stub/fwd fallback");
errinf(qstate, "malloc failure, for fallback to config");
log_assert(iq->dp);
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
- iq->qchase.qclass, NULL)) {
+ iq->qchase.qclass, NULL, NULL, NULL)) {
/* fail -- no more targets, no more hope of targets, no hope
* of a response. */
errinf(qstate, "all the configured stub or forward servers failed,");
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
- iq->qchase.qclass, NULL)) {
+ iq->qchase.qclass, NULL, NULL, NULL)) {
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
"because it is also a stub/forward,",
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
#include "util/storage/slabhash.h"
#include "util/edns.h"
#include "sldns/sbuffer.h"
+#include "iterator/iter_fwd.h"
int
context_finalize(struct ub_ctx* ctx)
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
ctx->env, &ctx->mods))
return UB_INITFAIL;
+ if(!(ctx->env->fwds = forwards_create()) ||
+ !forwards_apply_cfg(ctx->env->fwds, 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/authzone.h"
#include "services/listen_dnsport.h"
#include "sldns/sbuffer.h"
+#include "iterator/iter_fwd.h"
#ifdef HAVE_PTHREAD
#include <signal.h>
#endif
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
+ forwards_delete(ctx->env->fwds);
auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}
!w->is_bg || w->is_bg_thread);
sldns_buffer_free(w->env->scratch_buffer);
regional_destroy(w->env->scratch);
- forwards_delete(w->env->fwds);
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->fwds = forwards_create();
- if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
- forwards_delete(w->env->fwds);
- w->env->fwds = NULL;
- }
w->env->hints = hints_create();
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
hints_delete(w->env->hints);
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
- if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
- !w->env->hints) {
+ if(!w->env->scratch || !w->env->scratch_buffer || !w->env->hints) {
libworker_delete(w);
return NULL;
}
/** auth zones */
struct auth_zones* auth_zones;
/** Mapping of forwarding zones to targets.
- * iterator forwarder information. per-thread, created by worker */
+ * iterator forwarder information. */
struct iter_forwards* fwds;
/**
* iterator forwarder information. per-thread, created by worker.