diff options
Diffstat (limited to 'iterator/iterator.c')
| -rw-r--r-- | iterator/iterator.c | 84 |
1 files changed, 66 insertions, 18 deletions
diff --git a/iterator/iterator.c b/iterator/iterator.c index 78cd9485bad4..cadb95ebd0ab 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1511,6 +1511,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_ALGO, "no-cache set, going to the network"); qstate->no_cache_lookup = 1; qstate->no_cache_store = 1; + qstate->fwd_stub_no_cache = 1; msg = NULL; } else if(qstate->blacklist) { /* if cache, or anything else, was blacklisted then @@ -1530,7 +1531,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase, qstate->region, qstate->env->rrset_cache, qstate->env->scratch_buffer, - *qstate->env->now, 1/*add SOA*/, NULL, + *qstate->env->now, 1/*add SOA*/, dpname, qstate->env->cfg); } /* item taken from cache does not match our query name, thus @@ -2391,6 +2392,12 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id) /* go up one (more) step, until we hit the dp, if so, end */ dname_remove_label(&iq->dsns_point, &iq->dsns_point_len); + if(++iq->dsns_count > MAX_DSNS_FIND_COUNT) { + verbose(VERB_QUERY, "DS NS search exceeded %d labels", + MAX_DSNS_FIND_COUNT); + errinf(qstate, "DS NS search exceeded label limit"); + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } if(query_dname_compare(iq->dsns_point, iq->dp->name) == 0) { /* there was no inbetween nameserver, use the old delegation * point again. And this time, because dsns_point is nonNULL @@ -3073,7 +3080,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* Do not check ratelimit for forwarding queries or if we already got a * pass. */ - sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok); + sq_check_ratelimit = ((!(iq->chase_flags & BIT_RD) && + !iq->ratelimit_ok)); + iq->ratelimit_incremented = 0; /* We have a valid target. */ if(verbosity >= VERB_QUERY) { log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out); @@ -3099,7 +3108,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->dp->name, iq->dp->namelen, (iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream), (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), - target->tls_auth_name, qstate, &sq_was_ratelimited); + target->tls_auth_name, qstate, &sq_was_ratelimited, + &iq->ratelimit_incremented); if(!outq) { if(sq_was_ratelimited) { lock_basic_lock(&ie->queries_ratelimit_lock); @@ -3137,7 +3147,6 @@ find_NS(struct reply_info* rep, size_t from, size_t to) return NULL; } - /** * Process the query response. All queries end up at this state first. This * process generally consists of analyzing the response and routing the @@ -3179,7 +3188,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, orig_empty_nodata_found = iq->empty_nodata_found; type = response_type_from_server( (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found); + iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found, + iq->msg_lame_empty, iq->msg_lame_referral); iq->chase_to_rd = 0; /* remove TC flag, if this is erroneously set by TCP upstream */ iq->response->rep->flags &= ~BIT_TC; @@ -3457,7 +3467,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->deleg_msg = iq->response; /* Keep current delegation point for label comparison */ old_dp = iq->dp; - iq->dp = delegpt_from_message(iq->response, qstate->region); + /* A referral reply is "pleasant", refund the + * parent dp's rate charge before descending to the child. */ + if(iq->ratelimit_incremented) + infra_ratelimit_dec(qstate->env->infra_cache, + old_dp->name, old_dp->namelen, + *qstate->env->now); + iq->dp = delegpt_from_message(iq->response, qstate->region, + deleg_port_number(qstate->env)); if (qstate->env->cfg->qname_minimisation) iq->minimisation_state = INIT_MINIMISE_STATE; if(!iq->dp) { @@ -3734,7 +3751,8 @@ prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq) log_assert(qstate->is_priming || foriq->wait_priming_stub); log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR); /* Convert our response to a delegation point */ - dp = delegpt_from_message(qstate->return_msg, forq->region); + dp = delegpt_from_message(qstate->return_msg, forq->region, + deleg_port_number(forq->env)); if(!dp) { /* if there is no convertible delegation point, then * the ANSWER type was (presumably) a negative answer. */ @@ -3785,7 +3803,8 @@ processPrimeResponse(struct module_qstate* qstate, int id) iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */ type = response_type_from_server( (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qchase, iq->dp, NULL); + iq->response, &iq->qchase, iq->dp, NULL, iq->msg_lame_empty, + iq->msg_lame_referral); if(type == RESPONSE_TYPE_ANSWER) { qstate->return_rcode = LDNS_RCODE_NOERROR; qstate->return_msg = iq->response; @@ -3949,7 +3968,8 @@ processDSNSResponse(struct module_qstate* qstate, int id, /* else, store as DP and continue at querytargets */ foriq->state = QUERYTARGETS_STATE; - foriq->dp = delegpt_from_message(qstate->return_msg, forq->region); + foriq->dp = delegpt_from_message(qstate->return_msg, forq->region, + deleg_port_number(forq->env)); if(!foriq->dp) { log_err("out of memory in dsns dp alloc"); errinf(qstate, "malloc failure, in DS search"); @@ -3998,7 +4018,7 @@ processClassResponse(struct module_qstate* qstate, int id, /* if there are records, copy RCODE */ /* lower sec_state if this message is lower */ if(from->rep->rrset_count != 0) { - size_t n = from->rep->rrset_count+to->rep->rrset_count; + size_t i, n = from->rep->rrset_count+to->rep->rrset_count; struct ub_packed_rrset_key** dest, **d; /* copy appropriate rcode */ to->rep->flags = from->rep->flags; @@ -4020,24 +4040,49 @@ processClassResponse(struct module_qstate* qstate, int id, memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets * sizeof(dest[0])); dest += to->rep->an_numrrsets; - memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets - * sizeof(dest[0])); + for(i=0; i<from->rep->an_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[i], forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } dest += from->rep->an_numrrsets; /* copy NS */ memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets, to->rep->ns_numrrsets * sizeof(dest[0])); dest += to->rep->ns_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets, - from->rep->ns_numrrsets * sizeof(dest[0])); + for(i=0; i<from->rep->ns_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[ + from->rep->an_numrrsets+i], + forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } dest += from->rep->ns_numrrsets; /* copy AR */ memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets+ to->rep->ns_numrrsets, to->rep->ar_numrrsets * sizeof(dest[0])); dest += to->rep->ar_numrrsets; - memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+ - from->rep->ns_numrrsets, - from->rep->ar_numrrsets * sizeof(dest[0])); + for(i=0; i<from->rep->ar_numrrsets; i++) { + dest[i] = packed_rrset_copy_region( + from->rep->rrsets[ + from->rep->an_numrrsets+ + from->rep->ns_numrrsets+i], + forq->region, 0); + if(!dest[i]) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + } /* update counts */ to->rep->rrsets = d; to->rep->an_numrrsets += from->rep->an_numrrsets; @@ -4395,7 +4440,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, /* normalize and sanitize: easy to delete items from linked lists */ if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name, - qstate->env->scratch, qstate->env, qstate, ie)) { + qstate->env->scratch, qstate->env, qstate, ie, + &iq->msg_lame_empty, &iq->msg_lame_referral, + (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd) + )) { /* if 0x20 enabled, start fallback, but we have no message */ if(event == module_event_capsfail && !iq->caps_fallback) { iq->caps_fallback = 1; |
