commit d7ef7b31e0dbb0a73b201649c3729508b270f43f Author: wouter Date: Mon Apr 26 14:59:44 2010 +0000 Fix bug#307: 0x20 fallback outstanding query count, together with rec_lame, and canonical rrset comparison. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 9082055..6124650 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -674,7 +674,7 @@ rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) } int -reply_equal(struct reply_info* p, struct reply_info* q) +reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* scratch) { size_t i; if(p->flags != q->flags || @@ -688,8 +688,29 @@ reply_equal(struct reply_info* p, struct reply_info* q) p->rrset_count != q->rrset_count) return 0; for(i=0; irrset_count; i++) { - if(!rrset_equal(p->rrsets[i], q->rrsets[i])) - return 0; + if(!rrset_equal(p->rrsets[i], q->rrsets[i])) { + /* fallback procedure: try to sort and canonicalize */ + ldns_rr_list* pl, *ql; + pl = packed_rrset_to_rr_list(p->rrsets[i], scratch); + ql = packed_rrset_to_rr_list(q->rrsets[i], scratch); + if(!pl || !ql) { + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + return 0; + } + ldns_rr_list2canonical(pl); + ldns_rr_list2canonical(ql); + ldns_rr_list_sort(pl); + ldns_rr_list_sort(ql); + if(ldns_rr_list_compare(pl, ql) != 0) { + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + return 0; + } + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + continue; + } } return 1; } @@ -792,3 +813,18 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z) i++; } } + +void iter_dec_attempts(struct delegpt* dp, int d) +{ + struct delegpt_addr* a; + for(a=dp->target_list; a; a = a->next_target) { + if(a->attempts >= OUTBOUND_MSG_RETRY) { + /* add back to result list */ + a->next_result = dp->result_list; + dp->result_list = a; + } + if(a->attempts > d) + a->attempts -= d; + else a->attempts = 0; + } +} diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 9a1db5f..a9f4247 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -211,9 +211,10 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, * @param p: reply one. The reply has rrset data pointers in region. * Does not check rrset-IDs * @param q: reply two + * @param buf: scratch buffer. * @return if one and two are equal. */ -int reply_equal(struct reply_info* p, struct reply_info* q); +int reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* buf); /** * Store in-zone glue in seperate rrset cache entries for later last-resort @@ -257,4 +258,11 @@ int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z); +/** + * Remove query attempts from all available ips. For 0x20. + * @param dp: delegpt. + * @param d: decrease. + */ +void iter_dec_attempts(struct delegpt* dp, int d); + #endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index c7cdbc8..b1a948d 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1416,6 +1416,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, "match for %d wanted, done.", (int)iq->caps_server+1, (int)naddr*3); iq->caps_fallback = 0; + iter_dec_attempts(iq->dp, 3); /* space for fallback */ + iq->num_current_queries++; /* RespState decrements it*/ + iq->referral_count++; /* make sure we don't loop */ iq->state = QUERY_RESP_STATE; return 1; } @@ -2384,7 +2387,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, goto handle_it; } else { /* check if reply is the same, otherwise, fail */ - if(!reply_equal(iq->response->rep, iq->caps_reply)) { + if(!reply_equal(iq->response->rep, iq->caps_reply, + qstate->env->scratch_buffer)) { verbose(VERB_DETAIL, "Capsforid fallback: " "getting different replies, failed"); outbound_list_remove(&iq->outlist, outbound);