diff options
Diffstat (limited to 'iterator')
| -rw-r--r-- | iterator/iter_delegpt.c | 2 | ||||
| -rw-r--r-- | iterator/iter_fwd.c | 52 | ||||
| -rw-r--r-- | iterator/iter_fwd.h | 9 | ||||
| -rw-r--r-- | iterator/iter_hints.c | 13 | ||||
| -rw-r--r-- | iterator/iter_hints.h | 9 | ||||
| -rw-r--r-- | iterator/iter_utils.c | 153 | ||||
| -rw-r--r-- | iterator/iter_utils.h | 49 | ||||
| -rw-r--r-- | iterator/iterator.c | 81 | ||||
| -rw-r--r-- | iterator/iterator.h | 26 |
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; |
