summaryrefslogtreecommitdiff
path: root/iterator
diff options
context:
space:
mode:
Diffstat (limited to 'iterator')
-rw-r--r--iterator/iter_delegpt.c2
-rw-r--r--iterator/iter_fwd.c52
-rw-r--r--iterator/iter_fwd.h9
-rw-r--r--iterator/iter_hints.c13
-rw-r--r--iterator/iter_hints.h9
-rw-r--r--iterator/iter_utils.c153
-rw-r--r--iterator/iter_utils.h49
-rw-r--r--iterator/iterator.c81
-rw-r--r--iterator/iterator.h26
9 files changed, 290 insertions, 104 deletions
diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c
index c8b9a3ffe29d..be5bf482d673 100644
--- a/iterator/iter_delegpt.c
+++ b/iterator/iter_delegpt.c
@@ -278,7 +278,7 @@ delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
{
- char buf[LDNS_MAX_DOMAINLEN+1];
+ char buf[LDNS_MAX_DOMAINLEN];
struct delegpt_ns* ns;
struct delegpt_addr* a;
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c
index b9d42553a8b2..5c104a0a3217 100644
--- a/iterator/iter_fwd.c
+++ b/iterator/iter_fwd.c
@@ -129,7 +129,7 @@ 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)) {
- char buf[257];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(nm, buf);
log_err("duplicate forward zone %s ignored.", buf);
delegpt_free_mlc(dp);
@@ -331,6 +331,30 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
return 1;
}
+/** make NULL entries for auths */
+static int
+make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg)
+{
+ struct config_auth* a;
+ uint8_t* dname;
+ size_t dname_len;
+ for(a = cfg->auths; a; a = a->next) {
+ if(!a->name) continue;
+ dname = sldns_str2wire_dname(a->name, &dname_len);
+ if(!dname) {
+ log_err("cannot parse auth name '%s'", a->name);
+ return 0;
+ }
+ if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
+ free(dname);
+ log_err("out of memory");
+ return 0;
+ }
+ free(dname);
+ }
+ return 1;
+}
+
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
@@ -353,6 +377,16 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
lock_rw_unlock(&fwd->lock);
return 0;
}
+ /* TODO: Now we punch holes for auth zones as well so that in
+ * iterator:forward_request() we see the configured
+ * delegation point, but code flow/naming is hard to follow.
+ * Consider having a single tree with configured
+ * delegation points for all categories
+ * (stubs, forwards, auths). */
+ if(!make_auth_holes(fwd, cfg)) {
+ lock_rw_unlock(&fwd->lock);
+ return 0;
+ }
fwd_init_parents(fwd);
lock_rw_unlock(&fwd->lock);
return 1;
@@ -590,3 +624,19 @@ forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
}
+
+void
+forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data)
+{
+ rbtree_type* oldtree = fwd->tree;
+ if(oldtree) {
+ lock_unprotect(&fwd->lock, oldtree);
+ }
+ if(data->tree) {
+ lock_unprotect(&data->lock, data->tree);
+ }
+ fwd->tree = data->tree;
+ data->tree = oldtree;
+ lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
+ lock_protect(&data->lock, data->tree, sizeof(*data->tree));
+}
diff --git a/iterator/iter_fwd.h b/iterator/iter_fwd.h
index 4527d899c793..095cd96df852 100644
--- a/iterator/iter_fwd.h
+++ b/iterator/iter_fwd.h
@@ -234,4 +234,13 @@ int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock);
+/**
+ * Swap internal tree with preallocated entries. Caller should manage
+ * the locks.
+ * @param fwd: the forward data structure.
+ * @param data: the data structure used to take elements from. This contains
+ * the old elements on return.
+ */
+void forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data);
+
#endif /* ITERATOR_ITER_FWD_H */
diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c
index 8b168271c7f0..9faf155ababe 100644
--- a/iterator/iter_hints.c
+++ b/iterator/iter_hints.c
@@ -181,7 +181,7 @@ 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)) {
- char buf[257];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(dp->name, buf);
log_err("second hints for zone %s ignored.", buf);
delegpt_free_mlc(dp);
@@ -611,3 +611,14 @@ hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
name_tree_init_parents(&hints->tree);
if(!nolock) { lock_rw_unlock(&hints->lock); }
}
+
+void
+hints_swap_tree(struct iter_hints* hints, struct iter_hints* data)
+{
+ rbnode_type* oldroot = hints->tree.root;
+ size_t oldcount = hints->tree.count;
+ hints->tree.root = data->tree.root;
+ hints->tree.count = data->tree.count;
+ data->tree.root = oldroot;
+ data->tree.count = oldcount;
+}
diff --git a/iterator/iter_hints.h b/iterator/iter_hints.h
index 26de323c9e98..87434b5ac2e6 100644
--- a/iterator/iter_hints.h
+++ b/iterator/iter_hints.h
@@ -198,4 +198,13 @@ int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
uint8_t* nm, int nolock);
+/**
+ * Swap internal tree with preallocated entries. Caller should manage
+ * the locks.
+ * @param hints: the hints data structure.
+ * @param data: the data structure used to take elements from. This contains
+ * the old elements on return.
+ */
+void hints_swap_tree(struct iter_hints* hints, struct iter_hints* data);
+
#endif /* ITERATOR_ITER_HINTS_H */
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index cacba420e845..1da21896cb20 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -77,41 +77,73 @@
static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96";
/** fillup fetch policy array */
-static void
-fetch_fill(struct iter_env* ie, const char* str)
+static int
+fetch_fill(int* target_fetch_policy, int max_dependency_depth, const char* str)
{
char* s = (char*)str, *e;
int i;
- for(i=0; i<ie->max_dependency_depth+1; i++) {
- ie->target_fetch_policy[i] = strtol(s, &e, 10);
- if(s == e)
- fatal_exit("cannot parse fetch policy number %s", s);
+ for(i=0; i<max_dependency_depth+1; i++) {
+ target_fetch_policy[i] = strtol(s, &e, 10);
+ if(s == e) {
+ log_err("cannot parse fetch policy number %s", s);
+ return 0;
+ }
s = e;
}
+ return 1;
}
/** Read config string that represents the target fetch policy */
-static int
-read_fetch_policy(struct iter_env* ie, const char* str)
+int
+read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
+ const char* str)
{
int count = cfg_count_numbers(str);
if(count < 1) {
log_err("Cannot parse target fetch policy: \"%s\"", str);
return 0;
}
- ie->max_dependency_depth = count - 1;
- ie->target_fetch_policy = (int*)calloc(
- (size_t)ie->max_dependency_depth+1, sizeof(int));
- if(!ie->target_fetch_policy) {
+ *max_dependency_depth = count - 1;
+ *target_fetch_policy = (int*)calloc(
+ (size_t)(*max_dependency_depth)+1, sizeof(int));
+ if(!*target_fetch_policy) {
log_err("alloc fetch policy: out of memory");
return 0;
}
- fetch_fill(ie, str);
+ if(!fetch_fill(*target_fetch_policy, *max_dependency_depth, str))
+ return 0;
return 1;
}
-/** apply config caps whitelist items to name tree */
-static int
+struct rbtree_type*
+caps_white_create(void)
+{
+ struct rbtree_type* caps_white = rbtree_create(name_tree_compare);
+ if(!caps_white)
+ log_err("out of memory");
+ return caps_white;
+}
+
+/** delete caps_whitelist element */
+static void
+caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
+{
+ if(n) {
+ free(((struct name_tree_node*)n)->name);
+ free(n);
+ }
+}
+
+void
+caps_white_delete(struct rbtree_type* caps_white)
+{
+ if(!caps_white)
+ return;
+ traverse_postorder(caps_white, caps_free, NULL);
+ free(caps_white);
+}
+
+int
caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
{
struct config_strlist* p;
@@ -145,12 +177,41 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
}
int
-iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
+nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg)
{
const char *nat64_prefix;
+
+ nat64_prefix = cfg->nat64_prefix;
+ if(!nat64_prefix)
+ nat64_prefix = cfg->dns64_prefix;
+ if(!nat64_prefix)
+ nat64_prefix = DEFAULT_NAT64_PREFIX;
+ if(!netblockstrtoaddr(nat64_prefix, 0, &nat64->nat64_prefix_addr,
+ &nat64->nat64_prefix_addrlen, &nat64->nat64_prefix_net)) {
+ log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
+ return 0;
+ }
+ if(!addr_is_ip6(&nat64->nat64_prefix_addr,
+ nat64->nat64_prefix_addrlen)) {
+ log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
+ return 0;
+ }
+ if(!prefixnet_is_nat64(nat64->nat64_prefix_net)) {
+ log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
+ nat64_prefix);
+ return 0;
+ }
+ nat64->use_nat64 = cfg->do_nat64;
+ return 1;
+}
+
+int
+iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
+{
int i;
/* target fetch policy */
- if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
+ if(!read_fetch_policy(&iter_env->target_fetch_policy,
+ &iter_env->max_dependency_depth, cfg->target_fetch_policy))
return 0;
for(i=0; i<iter_env->max_dependency_depth+1; i++)
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
@@ -170,7 +231,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
if(cfg->caps_whitelist) {
if(!iter_env->caps_white)
- iter_env->caps_white = rbtree_create(name_tree_compare);
+ iter_env->caps_white = caps_white_create();
if(!iter_env->caps_white || !caps_white_apply_cfg(
iter_env->caps_white, cfg)) {
log_err("Could not set capsforid whitelist");
@@ -179,31 +240,13 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
- nat64_prefix = cfg->nat64_prefix;
- if(!nat64_prefix)
- nat64_prefix = cfg->dns64_prefix;
- if(!nat64_prefix)
- nat64_prefix = DEFAULT_NAT64_PREFIX;
- if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr,
- &iter_env->nat64_prefix_addrlen,
- &iter_env->nat64_prefix_net)) {
- log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
- return 0;
- }
- if(!addr_is_ip6(&iter_env->nat64_prefix_addr,
- iter_env->nat64_prefix_addrlen)) {
- log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
- return 0;
- }
- if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) {
- log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
- nat64_prefix);
+ if(!nat64_apply_cfg(&iter_env->nat64, cfg)) {
+ log_err("Could not setup nat64");
return 0;
}
iter_env->supports_ipv6 = cfg->do_ip6;
iter_env->supports_ipv4 = cfg->do_ip4;
- iter_env->use_nat64 = cfg->do_nat64;
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
iter_env->max_sent_count = cfg->max_sent_count;
iter_env->max_query_restarts = cfg->max_query_restarts;
@@ -270,7 +313,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip6 available */
}
- if(!iter_env->supports_ipv4 && !iter_env->use_nat64 &&
+ if(!iter_env->supports_ipv4 && !iter_env->nat64.use_nat64 &&
!addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip4 available */
}
@@ -693,10 +736,11 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
void
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags, time_t qstarttime)
+ struct regional* region, uint16_t flags, time_t qstarttime,
+ int is_valrec)
{
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
- pside, region, flags, qstarttime))
+ pside, region, flags, qstarttime, is_valrec))
log_err("out of memory: cannot store data in cache");
}
@@ -1488,14 +1532,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* check stub */
if (stub != NULL && stub->dp != NULL) {
+ enum verbosity_value level = VERB_ALGO;
int stub_no_cache = stub->dp->no_cache;
lock_rw_unlock(&qstate->env->fwds->lock);
- if(stub_no_cache) {
- char qname[255+1];
- char dpname[255+1];
+ if(verbosity >= level && stub_no_cache) {
+ char qname[LDNS_MAX_DOMAINLEN];
+ char dpname[LDNS_MAX_DOMAINLEN];
dname_str(qinf->qname, qname);
dname_str(stub->dp->name, dpname);
- verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
+ verbose(level, "stub for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
if(stub->dp->namelen > dpname_storage_len) {
@@ -1516,14 +1561,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* Check for forward. */
if (dp) {
+ enum verbosity_value level = VERB_ALGO;
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(verbosity >= level && dp_no_cache) {
+ char qname[LDNS_MAX_DOMAINLEN];
+ char dpname[LDNS_MAX_DOMAINLEN];
dname_str(qinf->qname, qname);
dname_str(dp->name, dpname);
- verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
+ verbose(level, "forward for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
if(dp->namelen > dpname_storage_len) {
@@ -1606,3 +1652,12 @@ limit_nsec_ttl(struct dns_msg* msg)
}
}
}
+
+void
+iter_make_minimal(struct reply_info* rep)
+{
+ size_t rem = rep->ns_numrrsets + rep->ar_numrrsets;
+ rep->ns_numrrsets = 0;
+ rep->ar_numrrsets = 0;
+ rep->rrset_count -= rem;
+}
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index 0361e43775e1..b17b091e6639 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -61,6 +61,7 @@ struct sock_list;
struct ub_packed_rrset_key;
struct module_stack;
struct outside_network;
+struct iter_nat64;
/* max number of lookups in the cache for target nameserver names.
* This stops, for large delegations, N*N lookups in the cache. */
@@ -142,6 +143,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
* @param region: to copy modified (cache is better) rrs back to.
* @param flags: with BIT_CD for dns64 AAAA translated queries.
* @param qstarttime: time of query start.
+ * @param is_valrec: if the query is validation recursion and does not get
* 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.
@@ -150,7 +152,8 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
*/
void iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags, time_t qstarttime);
+ struct regional* region, uint16_t flags, time_t qstarttime,
+ int is_valrec);
/**
* Select randomly with n/m probability.
@@ -429,10 +432,54 @@ void iterator_set_ip46_support(struct module_stack* mods,
struct module_env* env, struct outside_network* outnet);
/**
+ * Read config string that represents the target fetch policy.
+ * @param target_fetch_policy: alloced on return.
+ * @param max_dependency_depth: set on return.
+ * @param str: the config string
+ * @return false on failure.
+ */
+int read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
+ const char* str);
+
+/**
+ * Create caps exempt data structure.
+ * @return NULL on failure.
+ */
+struct rbtree_type* caps_white_create(void);
+
+/**
+ * Delete caps exempt data structure.
+ * @param caps_white: caps exempt tree.
+ */
+void caps_white_delete(struct rbtree_type* caps_white);
+
+/**
+ * Apply config caps whitelist items to name tree
+ * @param ntree: caps exempt tree.
+ * @param cfg: config with options.
+ */
+int caps_white_apply_cfg(struct rbtree_type* ntree, struct config_file* cfg);
+
+/**
+ * Apply config for nat64
+ * @param nat64: the nat64 state.
+ * @param cfg: config with options.
+ * @return false on failure.
+ */
+int nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg);
+
+/**
* Limit NSEC and NSEC3 TTL in response, RFC9077
* @param msg: dns message, the SOA record ttl is used to restrict ttls
* of NSEC and NSEC3 RRsets. If no SOA record, nothing happens.
*/
void limit_nsec_ttl(struct dns_msg* msg);
+/**
+ * Make the response minimal. Removed authority and additional section,
+ * that works when there is an answer in the answer section.
+ * @param rep: reply to modify.
+ */
+void iter_make_minimal(struct reply_info* rep);
+
#endif /* ITERATOR_ITER_UTILS_H */
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 59e4b36ce364..e64dfa61ba2d 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -71,13 +71,15 @@
#include "sldns/sbuffer.h"
/* number of packets */
-int MAX_GLOBAL_QUOTA = 128;
+int MAX_GLOBAL_QUOTA = 200;
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
/* in msec */
int USEFUL_SERVER_TOP_TIMEOUT = 120000;
/* Equals USEFUL_SERVER_TOP_TIMEOUT*4 */
int BLACKLIST_PENALTY = (120000*4);
+/** Timeout when only a single probe query per IP is allowed. */
+int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
static void target_count_increase_nx(struct iter_qstate* iq, int num);
@@ -105,16 +107,6 @@ iter_init(struct module_env* env, int id)
return 1;
}
-/** delete caps_whitelist element */
-static void
-caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
-{
- if(n) {
- free(((struct name_tree_node*)n)->name);
- free(n);
- }
-}
-
void
iter_deinit(struct module_env* env, int id)
{
@@ -126,10 +118,7 @@ iter_deinit(struct module_env* env, int id)
free(iter_env->target_fetch_policy);
priv_delete(iter_env->priv);
donotq_delete(iter_env->donotq);
- if(iter_env->caps_white) {
- traverse_postorder(iter_env->caps_white, caps_free, NULL);
- free(iter_env->caps_white);
- }
+ caps_white_delete(iter_env->caps_white);
free(iter_env);
env->modinfo[id] = NULL;
}
@@ -258,7 +247,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
- if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
+ if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super_iq, 1);
@@ -368,7 +357,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
- qstate->query_flags, qstate->qstarttime);
+ qstate->query_flags, qstate->qstarttime, qstate->is_valrec);
return error_response(qstate, id, rcode);
}
@@ -1092,7 +1081,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
/* cache is blacklisted and fallback, and we
* already have an auth_zone dp */
if(verbosity>=VERB_ALGO) {
- char buf[255+1];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(z->name, buf);
verbose(VERB_ALGO, "auth_zone %s "
"fallback because cache blacklisted",
@@ -1109,7 +1098,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
* validation failure, and the zone allows
* fallback to the internet, query there. */
if(verbosity>=VERB_ALGO) {
- char buf[255+1];
+ char buf[LDNS_MAX_DOMAINLEN];
dname_str(z->name, buf);
verbose(VERB_ALGO, "auth_zone %s "
"fallback because cache blacklisted",
@@ -1723,7 +1712,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
- ie->use_nat64)) {
+ ie->nat64.use_nat64)) {
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) {
@@ -2033,7 +2022,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
return 1;
if(iq->depth > 0 && iq->target_count &&
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
- char s[LDNS_MAX_DOMAINLEN+1];
+ char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d", s,
@@ -2041,7 +2030,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
return 2;
}
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
- char s[LDNS_MAX_DOMAINLEN+1];
+ char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d to a single delegation point",
@@ -2087,7 +2076,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
if(mesh_jostle_exceeded(qstate->env->mesh)) {
/* If no ip4 query is possible, that makes
* this ns resolved. */
- if(!((ie->supports_ipv4 || ie->use_nat64) &&
+ if(!((ie->supports_ipv4 || ie->nat64.use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4)))) {
ns->resolved = 1;
@@ -2096,7 +2085,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
/* Send the A request. */
- if((ie->supports_ipv4 || ie->use_nat64) &&
+ if((ie->supports_ipv4 || ie->nat64.use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4))) {
if(!generate_target_query(qstate, iq, id,
@@ -2252,7 +2241,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(iq->depth > 0 && iq->target_count &&
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
- char s[LDNS_MAX_DOMAINLEN+1];
+ char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d", s,
@@ -2268,14 +2257,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
/* if this nameserver is at a delegation point, but that
* delegation point is a stub and we cannot go higher, skip*/
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
- ((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
+ ((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
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);
if(ie->supports_ipv6) ns->done_pside6 = 1;
- if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1;
+ if(ie->supports_ipv4 || ie->nat64.use_nat64) ns->done_pside4 = 1;
continue;
}
/* query for parent-side A and AAAA for nameservers */
@@ -2300,7 +2289,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
}
- if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) {
+ if((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4) {
/* Send the A request. */
if(!generate_parentside_target_query(qstate, iq, id,
ns->name, ns->namelen,
@@ -2569,7 +2558,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(!ie->supports_ipv6)
delegpt_no_ipv6(iq->dp);
- if(!ie->supports_ipv4 && !ie->use_nat64)
+ if(!ie->supports_ipv4 && !ie->nat64.use_nat64)
delegpt_no_ipv4(iq->dp);
delegpt_log(VERB_ALGO, iq->dp);
@@ -2741,9 +2730,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
} else {
- lock_rw_wrlock(&qstate->env->auth_zones->lock);
- qstate->env->auth_zones->num_query_up++;
- lock_rw_unlock(&qstate->env->auth_zones->lock);
+ qstate->env->mesh->num_query_authzone_up++;
iq->num_current_queries++;
iq->chase_to_rd = 0;
iq->dnssec_lame_query = 0;
@@ -3046,7 +3033,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
target_count_increase_global_quota(iq, 1);
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
> MAX_GLOBAL_QUOTA) {
- char s[LDNS_MAX_DOMAINLEN+1];
+ char s[LDNS_MAX_DOMAINLEN];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"global quota on number of upstream queries %d", s,
@@ -3070,9 +3057,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
real_addr = target->addr;
real_addrlen = target->addrlen;
- if(ie->use_nat64 && target->addr.ss_family == AF_INET) {
- addr_to_nat64(&target->addr, &ie->nat64_prefix_addr,
- ie->nat64_prefix_addrlen, ie->nat64_prefix_net,
+ if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) {
+ addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr,
+ ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "applied NAT64:",
iq->dp->name, &real_addr, real_addrlen);
@@ -3296,6 +3283,16 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_target_queries = 0;
return processDSNSFind(qstate, iq, id);
}
+ if(iq->qchase.qtype == LDNS_RR_TYPE_DNSKEY && SERVE_EXPIRED
+ && qstate->is_valrec &&
+ reply_find_answer_rrset(&iq->qchase, iq->response->rep) != NULL) {
+ /* clean out the authority section, if any, so it
+ * does not overwrite dnssec valid data in the
+ * validation recursion lookup. */
+ verbose(VERB_ALGO, "make DNSKEY minimal for serve "
+ "expired");
+ iter_make_minimal(iq->response->rep);
+ }
if(!qstate->no_cache_store)
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep,
@@ -3303,7 +3300,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region, qstate->query_flags,
- qstate->qstarttime);
+ qstate->qstarttime, qstate->is_valrec);
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
@@ -3397,7 +3394,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* no prefetch-leeway, since its not the answer */
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, 0, 0, NULL, 0,
- qstate->qstarttime);
+ qstate->qstarttime, qstate->is_valrec);
if(iq->store_parent_NS)
iter_store_parentside_NS(qstate->env,
iq->response->rep);
@@ -3527,7 +3524,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS, NULL,
- qstate->query_flags, qstate->qstarttime);
+ qstate->query_flags, qstate->qstarttime,
+ qstate->is_valrec);
/* set the current request's qname to the new value. */
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
@@ -3871,7 +3869,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
} else {
verbose(VERB_ALGO, "iterator TargetResponse failed");
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
- if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
+ if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
@@ -4154,7 +4152,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
qstate->region, qstate->query_flags,
- qstate->qstarttime);
+ qstate->qstarttime, qstate->is_valrec);
}
}
qstate->return_rcode = LDNS_RCODE_NOERROR;
@@ -4334,6 +4332,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* Copy the edns options we may got from the back end */
+ qstate->edns_opts_back_in = NULL;
if(edns.opt_list_in) {
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in,
qstate->region);
diff --git a/iterator/iterator.h b/iterator/iterator.h
index 46701f6eee75..ae4b4e45170a 100644
--- a/iterator/iterator.h
+++ b/iterator/iterator.h
@@ -46,8 +46,6 @@
#include "util/data/msgreply.h"
#include "util/module.h"
struct delegpt;
-struct iter_hints;
-struct iter_forwards;
struct iter_donotq;
struct iter_prep_list;
struct iter_priv;
@@ -108,15 +106,9 @@ extern int BLACKLIST_PENALTY;
#define EMPTY_NODATA_RETRY_COUNT 2
/**
- * Global state for the iterator.
+ * Iterator global state for nat64.
*/
-struct iter_env {
- /** A flag to indicate whether or not we have an IPv6 route */
- int supports_ipv6;
-
- /** A flag to indicate whether or not we have an IPv4 route */
- int supports_ipv4;
-
+struct iter_nat64 {
/** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */
int use_nat64;
@@ -128,6 +120,20 @@ struct iter_env {
/** CIDR mask length of NAT64 prefix */
int nat64_prefix_net;
+};
+
+/**
+ * Global state for the iterator.
+ */
+struct iter_env {
+ /** A flag to indicate whether or not we have an IPv6 route */
+ int supports_ipv6;
+
+ /** A flag to indicate whether or not we have an IPv4 route */
+ int supports_ipv4;
+
+ /** State for nat64 */
+ struct iter_nat64 nat64;
/** A set of inetaddrs that should never be queried. */
struct iter_donotq* donotq;