diff options
Diffstat (limited to 'contrib/unbound/iterator')
-rw-r--r-- | contrib/unbound/iterator/iter_delegpt.h | 10 | ||||
-rw-r--r-- | contrib/unbound/iterator/iter_fwd.c | 32 | ||||
-rw-r--r-- | contrib/unbound/iterator/iterator.c | 32 |
3 files changed, 56 insertions, 18 deletions
diff --git a/contrib/unbound/iterator/iter_delegpt.h b/contrib/unbound/iterator/iter_delegpt.h index 49f6f6b8130f..287bf92134d2 100644 --- a/contrib/unbound/iterator/iter_delegpt.h +++ b/contrib/unbound/iterator/iter_delegpt.h @@ -79,6 +79,16 @@ struct delegpt { * Also true if the delegationpoint was created from a delegation * message and thus contains the parent-side-info already. */ uint8_t has_parent_side_NS; + /** if true, the delegation point has reached last resort processing + * and the parent side information has been possibly added to the + * delegation point. + * For now this signals that further target lookups will ignore + * the configured target-fetch-policy and only resolve on + * demand to try and avoid triggering limits at this stage (.i.e, it + * is very likely that the A/AAAA queries for the newly added name + * servers will not yield new IP addresses and trigger NXNS + * countermeasures. */ + uint8_t fallback_to_parent_side_NS; /** for assertions on type of delegpt */ uint8_t dp_type_mlc; /** use SSL for upstream query */ diff --git a/contrib/unbound/iterator/iter_fwd.c b/contrib/unbound/iterator/iter_fwd.c index 5c104a0a3217..5d70c6664862 100644 --- a/contrib/unbound/iterator/iter_fwd.c +++ b/contrib/unbound/iterator/iter_fwd.c @@ -139,6 +139,17 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm, return 1; } +static struct iter_forward_zone* +fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = c; + key.name = nm; + key.namelabs = dname_count_size_labels(nm, &key.namelen); + return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key); +} + /** insert new info into forward structure given dp */ static int forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) @@ -321,6 +332,11 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) log_err("cannot parse stub name '%s'", s->name); return 0; } + if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) { + /* Already a forward zone there. */ + free(dname); + continue; + } if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) { free(dname); log_err("out of memory"); @@ -345,6 +361,11 @@ make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg) log_err("cannot parse auth name '%s'", a->name); return 0; } + if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) { + /* Already a forward zone there. */ + free(dname); + continue; + } if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) { free(dname); log_err("out of memory"); @@ -537,17 +558,6 @@ forwards_get_mem(struct iter_forwards* fwd) return s; } -static struct iter_forward_zone* -fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) -{ - struct iter_forward_zone key; - key.node.key = &key; - key.dclass = c; - key.name = nm; - key.namelabs = dname_count_size_labels(nm, &key.namelen); - return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key); -} - int forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp, int nolock) diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c index e64dfa61ba2d..71e64655f6d0 100644 --- a/contrib/unbound/iterator/iterator.c +++ b/contrib/unbound/iterator/iterator.c @@ -2152,6 +2152,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL"); return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); } + iq->dp->fallback_to_parent_side_NS = 1; if(qstate->env->cfg->harden_unverified_glue) { if(!cache_fill_missing(qstate->env, iq->qchase.qclass, qstate->region, iq->dp, PACKED_RRSET_UNVERIFIED_GLUE)) @@ -2180,6 +2181,10 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, a->lame, a->tls_auth_name, -1, NULL); } lock_rw_unlock(&qstate->env->hints->lock); + /* copy over some configuration since we update the + * delegation point in place */ + iq->dp->tcp_upstream = dp->tcp_upstream; + iq->dp->ssl_upstream = dp->ssl_upstream; } iq->dp->has_parent_side_NS = 1; } else if(!iq->dp->has_parent_side_NS) { @@ -2768,7 +2773,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, } /* if the mesh query list is full, then do not waste cpu and sockets to * fetch promiscuous targets. They can be looked up when needed. */ - if(can_do_promisc && !mesh_jostle_exceeded(qstate->env->mesh)) { + if(!iq->dp->fallback_to_parent_side_NS && can_do_promisc + && !mesh_jostle_exceeded(qstate->env->mesh)) { tf_policy = ie->target_fetch_policy[iq->depth]; } @@ -3247,13 +3253,19 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } } if(type == RESPONSE_TYPE_CNAME && - iq->qchase.qtype == LDNS_RR_TYPE_CNAME && + (iq->qchase.qtype == LDNS_RR_TYPE_CNAME || + iq->qchase.qtype == LDNS_RR_TYPE_ANY) && iq->minimisation_state == MINIMISE_STATE && query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) { /* The minimised query for full QTYPE and hidden QTYPE can be * classified as CNAME response type, even when the original * QTYPE=CNAME. This should be treated as answer response type. */ + /* For QTYPE=ANY, it is also considered the response, that + * is what the classifier would say, if it saw qtype ANY, + * and this same response was returned for that. The response + * can already be treated as such an answer, without having + * to send another query with a new qtype. */ type = RESPONSE_TYPE_ANSWER; } @@ -3510,6 +3522,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->num_target_queries = 0; return processDSNSFind(qstate, iq, id); } + if(iq->minimisation_state == MINIMISE_STATE && + query_dname_compare(iq->qchase.qname, + iq->qinfo_out.qname) != 0) { + verbose(VERB_ALGO, "continue query minimisation, " + "downwards, after CNAME response for " + "intermediate label"); + /* continue query minimisation, downwards */ + return next_state(iq, QUERYTARGETS_STATE); + } /* Process the CNAME response. */ if(!handle_cname_response(qstate, iq, iq->response, &sname, &snamelen)) { @@ -3572,10 +3593,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->auth_zone_response = 0; iq->sent_count = 0; iq->dp_target_count = 0; - if(iq->minimisation_state != MINIMISE_STATE) - /* Only count as query restart when it is not an extra - * query as result of qname minimisation. */ - iq->query_restart_count++; + iq->query_restart_count++; if(qstate->env->cfg->qname_minimisation) iq->minimisation_state = INIT_MINIMISE_STATE; @@ -4147,7 +4165,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, /* store message with the finished prepended items, * but only if we did recursion. The nonrecursion referral * from cache does not need to be stored in the msg cache. */ - if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) { + if(!qstate->no_cache_store && (qstate->query_flags&BIT_RD)) { iter_dns_store(qstate->env, &qstate->qinfo, iq->response->rep, 0, qstate->prefetch_leeway, iq->dp&&iq->dp->has_parent_side_NS, |