- Perform canonical sort for 0x20 capsforid compare of replies,

this sorts rrsets in the authority and additional section before
  comparison, so that out of order rrsets do not cause failure.


git-svn-id: file:///svn/unbound/trunk@5100 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2019-02-04 15:22:08 +00:00
parent fe97f25b75
commit 99994a26b0
2 changed files with 56 additions and 4 deletions

View file

@ -4,6 +4,9 @@
It logs the original query name, not the target of the CNAME.
- Add local-zone type inform_redirect, which logs like type inform,
and redirects like type redirect.
- Perform canonical sort for 0x20 capsforid compare of replies,
this sorts rrsets in the authority and additional section before
comparison, so that out of order rrsets do not cause failure.
31 January 2019: Wouter
- Set ub_ctx_set_tls call signature in ltrace config file for

View file

@ -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,40 @@ 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) 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;
}