Commit f8671f37 authored by Lubos Slovak's avatar Lubos Slovak

Function for comparing domain names.

Added dnslib_dname_compare().
Added constant for max domain name labels.

TODO: consider saving label offsets in the domain name structure,
      may make the comparation quicker.

refs #118
parent 75758632
......@@ -118,5 +118,6 @@ const uint16_t DNSLIB_CLASS_ANY = 255; /* Class ANY */
* Other
*/
const unsigned int DNSLIB_MAX_DNAME_LENGTH = 255;
const unsigned int DNSLIB_MAX_DNAME_LABELS = 127; // 1-char labels
#endif /* _CUTEDNS_CONSTS_H */
......@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h> // tolower()
#include "common.h"
#include "consts.h"
#include "dname.h"
......@@ -224,3 +225,71 @@ void dnslib_dname_free( dnslib_dname_t **dname )
free(*dname);
*dname = NULL;
}
/*----------------------------------------------------------------------------*/
int dnslib_dname_compare( const dnslib_dname_t *d1, const dnslib_dname_t *d2 )
{
if (d1 == d2) {
return 0;
}
const uint8_t *pos1, *pos2;
// jump to the last label and store addresses of labels on the way there
// TODO: consider storing label offsets in the domain name structure
const uint8_t *labels1[DNSLIB_MAX_DNAME_LABELS];
const uint8_t *labels2[DNSLIB_MAX_DNAME_LABELS];
int i1 = 0;
int i2 = 0;
while (*pos1 != '\0') {
labels1[i1++] = pos1;
pos1 += *pos1;
}
while (*pos2 != '\0') {
labels2[i2++] = pos2;
pos2 += *pos2;
}
// compare labels from last to first
while (i1 > 0 && i2 > 0) {
pos1 = labels1[--i1];
pos2 = labels2[--i2];
int label_length = (*pos1 < *pos2) ? *pos1 : *pos2;
int i = 0;
while (i < label_length && tolower(*(++pos1)) == tolower(*(++pos2))) {
++i;
}
if (i < label_length) { // difference in some octet
if (tolower(*pos1) < tolower(*pos2)) {
return -1;
} else {
assert(tolower(*pos1) > tolower(*pos2));
return 1;
}
}
if (*(labels1[i1]) < *(labels2[i2])) { // one label shorter
return -1;
} else if (*(labels1[i1]) > *(labels2[i2])) {
return 1;
}
// otherwise the labels are identical, continue with previous labels
}
// if all labels matched, the shorter name is first
if (i1 == 0 && i2 > 0) {
return 1;
}
if (i1 > 0 && i2 == 0) {
return -1;
}
return 0;
}
......@@ -136,6 +136,18 @@ const struct dnslib_node *dnslib_dname_node( const dnslib_dname_t *dname );
*/
void dnslib_dname_free( dnslib_dname_t **dname );
/*!
* \brief Compares two domain names.
*
* \param d1 First domain name.
* \param d2 Second domain name.
*
* \retval -1 if \a d1 goes before \a d2 in canonical order.
* \retval 1 if \a d1 goes after \a d2 in canonical order.
* \retval 0 if the domain names are identical.
*/
int dnslib_dname_compare( const dnslib_dname_t *d1, const dnslib_dname_t *d2 );
#endif /* _CUTEDNS_DNAME_H */
/*! @} */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment