+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
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);
}
}
}
+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)
{
/** 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.
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;
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;
}