diff options
Diffstat (limited to 'iterator')
| -rw-r--r-- | iterator/iter_fwd.c | 2 | ||||
| -rw-r--r-- | iterator/iter_hints.c | 2 | ||||
| -rw-r--r-- | iterator/iter_utils.c | 60 | ||||
| -rw-r--r-- | iterator/iterator.c | 24 |
4 files changed, 80 insertions, 8 deletions
diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c index 4eb0eb718607..ea3d70e07320 100644 --- a/iterator/iter_fwd.c +++ b/iterator/iter_fwd.c @@ -239,7 +239,7 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp) s->name, p->str); return 0; } -#ifndef HAVE_SSL_SET1_HOST +#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) if(tls_auth_name) log_err("no name verification functionality in " "ssl library, ignored name for %s", p->str); diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c index 0b35a9d9e24f..60e518122ed1 100644 --- a/iterator/iter_hints.c +++ b/iterator/iter_hints.c @@ -252,7 +252,7 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp) s->name, p->str); return 0; } -#ifndef HAVE_SSL_SET1_HOST +#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST) if(auth_name) log_err("no name verification functionality in " "ssl library, ignored name for %s", p->str); diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 4ac8efd0d17a..be7965a60e39 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -882,10 +882,35 @@ rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) return 1; } +/** compare rrsets and sort canonically. Compares rrset name, type, class. + * return 0 if equal, +1 if x > y, and -1 if x < y. + */ +static int +rrset_canonical_sort_cmp(const void* x, const void* y) +{ + struct ub_packed_rrset_key* rrx = *(struct ub_packed_rrset_key**)x; + struct ub_packed_rrset_key* rry = *(struct ub_packed_rrset_key**)y; + int r = dname_canonical_compare(rrx->rk.dname, rry->rk.dname); + if(r != 0) + return r; + if(rrx->rk.type != rry->rk.type) { + if(ntohs(rrx->rk.type) > ntohs(rry->rk.type)) + return 1; + else return -1; + } + if(rrx->rk.rrset_class != rry->rk.rrset_class) { + if(ntohs(rrx->rk.rrset_class) > ntohs(rry->rk.rrset_class)) + return 1; + else return -1; + } + return 0; +} + int reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region) { size_t i; + struct ub_packed_rrset_key** sorted_p, **sorted_q; if(p->flags != q->flags || p->qdcount != q->qdcount || /* do not check TTL, this may differ */ @@ -899,16 +924,43 @@ reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region) p->ar_numrrsets != q->ar_numrrsets || p->rrset_count != q->rrset_count) return 0; + /* sort the rrsets in the authority and additional sections before + * compare, the query and answer sections are ordered in the sequence + * they should have (eg. one after the other for aliases). */ + sorted_p = (struct ub_packed_rrset_key**)regional_alloc_init( + region, p->rrsets, sizeof(*sorted_p)*p->rrset_count); + if(!sorted_p) return 0; + log_assert(p->an_numrrsets + p->ns_numrrsets + p->ar_numrrsets <= + p->rrset_count); + qsort(sorted_p + p->an_numrrsets, p->ns_numrrsets, + sizeof(*sorted_p), rrset_canonical_sort_cmp); + qsort(sorted_p + p->an_numrrsets + p->ns_numrrsets, p->ar_numrrsets, + sizeof(*sorted_p), rrset_canonical_sort_cmp); + + sorted_q = (struct ub_packed_rrset_key**)regional_alloc_init( + region, q->rrsets, sizeof(*sorted_q)*q->rrset_count); + if(!sorted_q) { + regional_free_all(region); + return 0; + } + log_assert(q->an_numrrsets + q->ns_numrrsets + q->ar_numrrsets <= + q->rrset_count); + qsort(sorted_q + q->an_numrrsets, q->ns_numrrsets, + sizeof(*sorted_q), rrset_canonical_sort_cmp); + qsort(sorted_q + q->an_numrrsets + q->ns_numrrsets, q->ar_numrrsets, + sizeof(*sorted_q), rrset_canonical_sort_cmp); + + /* compare the rrsets */ for(i=0; i<p->rrset_count; i++) { - if(!rrset_equal(p->rrsets[i], q->rrsets[i])) { - if(!rrset_canonical_equal(region, p->rrsets[i], - q->rrsets[i])) { + if(!rrset_equal(sorted_p[i], sorted_q[i])) { + if(!rrset_canonical_equal(region, sorted_p[i], + sorted_q[i])) { regional_free_all(region); return 0; } - regional_free_all(region); } } + regional_free_all(region); return 1; } diff --git a/iterator/iterator.c b/iterator/iterator.c index 8312dfd53313..c73fb5177489 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1448,7 +1448,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, * now will also exceed the rate, keeping cache fresh */ (void)infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name, iq->dp->namelen, - *qstate->env->now); + *qstate->env->now, &qstate->qinfo, + qstate->reply); /* see if we are passed through with slip factor */ if(qstate->env->cfg->ratelimit_factor != 0 && ub_random_max(qstate->env->rnd, @@ -2105,6 +2106,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, struct delegpt_addr* target; struct outbound_entry* outq; int auth_fallback = 0; + uint8_t* qout_orig = NULL; + size_t qout_orig_len = 0; /* NOTE: a request will encounter this state for each target it * needs to send a query to. That is, at least one per referral, @@ -2178,6 +2181,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, int labdiff = qchaselabs - dname_count_labels(iq->qinfo_out.qname); + qout_orig = iq->qinfo_out.qname; + qout_orig_len = iq->qinfo_out.qname_len; iq->qinfo_out.qname = iq->qchase.qname; iq->qinfo_out.qname_len = iq->qchase.qname_len; iq->minimise_count++; @@ -2330,6 +2335,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* wait to get all targets, we want to try em */ verbose(VERB_ALGO, "wait for all targets for fallback"); qstate->ext_state[id] = module_wait_reply; + /* undo qname minimise step because we'll get back here + * to do it again */ + if(qout_orig && iq->minimise_count > 0) { + iq->minimise_count--; + iq->qinfo_out.qname = qout_orig; + iq->qinfo_out.qname_len = qout_orig_len; + } return 0; } /* did we do enough fallback queries already? */ @@ -2463,13 +2475,21 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->num_current_queries); qstate->ext_state[id] = module_wait_reply; } + /* undo qname minimise step because we'll get back here + * to do it again */ + if(qout_orig && iq->minimise_count > 0) { + iq->minimise_count--; + iq->qinfo_out.qname = qout_orig; + iq->qinfo_out.qname_len = qout_orig_len; + } return 0; } /* if not forwarding, check ratelimits per delegationpoint name */ if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) { if(!infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name, - iq->dp->namelen, *qstate->env->now)) { + iq->dp->namelen, *qstate->env->now, &qstate->qinfo, + qstate->reply)) { lock_basic_lock(&ie->queries_ratelimit_lock); ie->num_queries_ratelimited++; lock_basic_unlock(&ie->queries_ratelimit_lock); |
