From eb51f482142f097a8e482e32044875c79a06bf6d Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Thu, 12 Apr 2007 14:02:02 +0000 Subject: [PATCH] dname compare lower case version. Preserves case. git-svn-id: file:///svn/unbound/trunk@238 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 4 ++++ testcode/unitmain.c | 25 +++++++++++++++++++++++++ util/data/dname.c | 33 +++++++++++++++++++++++++++++++++ util/data/dname.h | 11 +++++++++++ util/data/msgreply.c | 26 ++++++++++++++++++++++---- 5 files changed, 95 insertions(+), 4 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 065a0b6d4..8f7c0bb2f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,10 @@ +12 April 2007: Wouter + - dname compare routine that preserves case, with unit tests. + 11 April 2007: Wouter - parse work - dname packet parse, msgparse, querysection parse, start of sectionparse. + 10 April 2007: Wouter - Improved alignment of reply_info packet, nice for 32 and 64 bit. - Put RRset counts in reply_info, because the number of RRs can change diff --git a/testcode/unitmain.c b/testcode/unitmain.c index 5f16d8970..0dd883ceb 100644 --- a/testcode/unitmain.c +++ b/testcode/unitmain.c @@ -167,6 +167,31 @@ msgreply_test() query_dname_tolower(ldns_buffer_begin(buff), 4); unit_assert( memcmp(ldns_buffer_begin(buff), "\002nl\000", 4) == 0); + /* test query_dname_compare */ + unit_assert(query_dname_compare((uint8_t*)"", (uint8_t*)"") == 0); + unit_assert(query_dname_compare((uint8_t*)"\001a", + (uint8_t*)"\001a") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc\001a") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003aBc\001a", + (uint8_t*)"\003AbC\001A") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003abc", + (uint8_t*)"\003abc\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc") == +1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"") == +1); + unit_assert(query_dname_compare((uint8_t*)"", + (uint8_t*)"\003abc\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003xxx\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003axx\001a", + (uint8_t*)"\003abc\001a") == 1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc\001Z") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001Z", + (uint8_t*)"\003abc\001a") == 1); + ldns_buffer_free(buff); } diff --git a/util/data/dname.c b/util/data/dname.c index 8c8c0e80d..b9d0bdfc8 100644 --- a/util/data/dname.c +++ b/util/data/dname.c @@ -66,6 +66,39 @@ query_dname_len(ldns_buffer* query) } } +int +query_dname_compare(uint8_t* d1, uint8_t* d2) +{ + uint8_t lab1, lab2; + log_assert(d1 && d2); + lab1 = *d1++; + lab2 = *d2++; + while( lab1 != 0 || lab2 != 0 ) { + /* compare label length */ + /* if one dname ends, it has labellength 0 */ + if(lab1 != lab2) { + if(lab1 < lab2) + return -1; + return 1; + } + log_assert(lab1 == lab2 && lab1 != 0); + /* compare lowercased labels. */ + while(lab1--) { + if(tolower((int)*d1) != tolower((int)*d2)) { + if(tolower((int)*d1) < tolower((int)*d2)) + return -1; + return 1; + } + d1++; + d2++; + } + /* next pair of labels. */ + lab1 = *d1++; + lab2 = *d2++; + } + return 0; +} + void query_dname_tolower(uint8_t* dname, size_t len) { diff --git a/util/data/dname.h b/util/data/dname.h index 4a10bdce6..ce4eaecf3 100644 --- a/util/data/dname.h +++ b/util/data/dname.h @@ -56,6 +56,17 @@ size_t query_dname_len(ldns_buffer* query); /** lowercase query dname */ void query_dname_tolower(uint8_t* dname, size_t len); +/** + * Compare query dnames (uncompressed storage). The Dnames passed do not + * have to be lowercased, comparison routine does this. + * Dnames have to be valid format. + * @param d1: dname to compare + * @param d2: dname to compare + * @return: -1, 0, or +1 depending on comparison results. + * Sort order is first difference found. not the canonical ordering. + */ +int query_dname_compare(uint8_t* d1, uint8_t* d2); + /** * Determine correct, compressed, dname present in packet. * Checks for parse errors. diff --git a/util/data/msgreply.c b/util/data/msgreply.c index d7f5ff191..b69e984d1 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -385,9 +385,9 @@ query_info_compare(void* m1, void* m2) int mc; /* from most different to least different for speed */ COMPARE_IT(msg1->qtype, msg2->qtype); - COMPARE_IT(msg1->qnamesize, msg2->qnamesize); - if((mc = memcmp(msg1->qname, msg2->qname, msg1->qnamesize)) != 0) + if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0) return mc; + log_assert(msg1->qnamesize == msg2->qnamesize); COMPARE_IT(msg1->has_cd, msg2->has_cd); COMPARE_IT(msg1->qclass, msg2->qclass); return 0; @@ -437,12 +437,30 @@ reply_info_delete(void* d, void* ATTR_UNUSED(arg)) hashvalue_t query_info_hash(struct query_info *q) { + uint8_t labuf[LDNS_MAX_LABELLEN+1]; + uint8_t lablen; + uint8_t* d; + int i; + hashvalue_t h = 0xab; h = hashlittle(&q->qtype, sizeof(q->qtype), h); h = hashlittle(&q->qclass, sizeof(q->qclass), h); h = hashlittle(&q->has_cd, sizeof(q->has_cd), h); - query_dname_tolower(q->qname, q->qnamesize); - h = hashlittle(q->qname, q->qnamesize, h); + + /* preserve case of query, make hash label by label */ + d = q->qname; + lablen = *d; + while(lablen) { + log_assert(lablen <= LDNS_MAX_LABELLEN); + labuf[0] = lablen; + d++; + i=0; + while(lablen--) + labuf[++i] = (uint8_t)tolower((int)*d++); + h = hashlittle(labuf, labuf[0] + 1, h); + lablen = *d; + } + return h; } -- 2.47.2