add dns_name_fullcompare(); fix issubdomain and compare bugs

This commit is contained in:
Bob Halley 1999-02-16 08:18:44 +00:00
parent a866eaa4ac
commit 29b487b0a4

View file

@ -345,29 +345,49 @@ dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
return (h);
}
int
dns_name_compare(dns_name_t *name1, dns_name_t *name2) {
dns_namereln_t
dns_name_fullcompare(dns_name_t *name1, dns_name_t *name2,
int *orderp,
unsigned int *nlabelsp, unsigned int *nbitsp)
{
unsigned int l1, l2, l, count1, count2, count;
unsigned int b1, b2, n;
unsigned int b1, b2, n, nlabels, nbits;
unsigned char c1, c2;
int cdiff, ldiff;
unsigned char *label1, *label2;
unsigned char *offsets1, *offsets2;
dns_offsets_t odata1, odata2;
dns_namereln_t namereln = dns_namereln_none;
/*
* Determine the relative ordering under the DNSSEC order relation of
* 'name1' and 'name2'.
* 'name1' and 'name2', and also determine the hierarchical
* relationship of the names.
*
* Note: It makes no sense for one of the names to be relative and the
* other absolute. If both names are relative, then to be meaningfully
* compared the caller must ensure that they are both relative to the
* same domain.
*/
REQUIRE(VALID_NAME(name1));
REQUIRE(name1->labels > 0);
REQUIRE(VALID_NAME(name2));
REQUIRE(name2->labels > 0);
REQUIRE(orderp != NULL);
REQUIRE(nlabelsp != NULL);
REQUIRE(nbitsp != NULL);
/*
* Either name1 is absolute and name2 is absolute, or neither is.
*/
REQUIRE(((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ^
(name2->attributes & DNS_NAMEATTR_ABSOLUTE)) == 0);
SETUP_OFFSETS(name1, offsets1, odata1);
SETUP_OFFSETS(name2, offsets2, odata2);
nlabels = 0;
nbits = 0;
l1 = name1->labels;
l2 = name2->labels;
if (l1 < l2) {
@ -405,21 +425,31 @@ dns_name_compare(dns_name_t *name1, dns_name_t *name2) {
count--;
c1 = maptolower[*label1++];
c2 = maptolower[*label2++];
if (c1 < c2)
return (-1);
else if (c1 > c2)
return (1);
if (c1 < c2) {
*orderp = -1;
goto done;
} else if (c1 > c2) {
*orderp = 1;
goto done;
}
}
if (cdiff != 0)
return (cdiff);
if (cdiff != 0) {
*orderp = cdiff;
goto done;
}
nlabels++;
} else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
if (count2 == 0)
return (1);
return (-1);
*orderp = 1;
else
*orderp = -1;
goto done;
} else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
if (count1 == 0)
return (-1);
return (1);
*orderp = -1;
else
*orderp = 1;
goto done;
} else {
INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
count2 == DNS_LABELTYPE_BITSTRING);
@ -443,17 +473,104 @@ dns_name_compare(dns_name_t *name1, dns_name_t *name2) {
for (n = 0; n < count; n++) {
b1 = get_bit(label1, n);
b2 = get_bit(label2, n);
if (b1 < b2)
return (-1);
else if (b1 > b2)
return (1);
if (b1 < b2) {
*orderp = -1;
goto done;
} else if (b1 > b2) {
*orderp = 1;
goto done;
}
if (nbits == 0)
nlabels++;
nbits++;
}
if (cdiff != 0)
return (cdiff);
if (cdiff != 0) {
/*
* If we're here, then we have two bitstrings
* of differing length.
*
* If the name with the shorter bitstring
* has any labels, then it must be greater
* than the longer bitstring. This is a bit
* counterintuitive. If the name with the
* shorter bitstring has any more labels, then
* the next label must be an ordinary label.
* It can't be a bitstring label because if it
* were, then there would be room for it in
* the current bitstring label (since all
* bitstrings are canonicalized). Since
* there's at least one more bit in the
* name with the longer bitstring, and since
* a bitlabel sorts before any ordinary label,
* the name with the longer bitstring must
* be lexically before the one with the shorter
* bitstring.
*
* On the other hand, if there are no more
* labels in the name with the shorter
* bitstring, then that name contains the
* other name.
*/
namereln = dns_namereln_commonancestor;
if (cdiff < 0) {
if (l1 > 0)
*orderp = 1;
else {
*orderp = -1;
namereln =
dns_namereln_contains;
}
} else {
if (l2 > 0)
*orderp = -1;
else {
*orderp = 1;
namereln =
dns_namereln_subdomain;
}
}
goto done;
}
nbits = 0;
}
}
return (ldiff);
*orderp = ldiff;
if (ldiff < 0)
namereln = dns_namereln_contains;
else if (ldiff > 0)
namereln = dns_namereln_subdomain;
else
namereln = dns_namereln_equal;
done:
*nlabelsp = nlabels;
*nbitsp = nbits;
if (nlabels > 0 && namereln == dns_namereln_none)
namereln = dns_namereln_commonancestor;
return (namereln);
}
int
dns_name_compare(dns_name_t *name1, dns_name_t *name2) {
int order;
unsigned int nlabels, nbits;
/*
* Determine the relative ordering under the DNSSEC order relation of
* 'name1' and 'name2'.
*
* Note: It makes no sense for one of the names to be relative and the
* other absolute. If both names are relative, then to be meaningfully
* compared the caller must ensure that they are both relative to the
* same domain.
*/
(void)dns_name_fullcompare(name1, name2, &order, &nlabels, &nbits);
return (order);
}
int
@ -530,12 +647,9 @@ dns_name_rdatacompare(dns_name_t *name1, dns_name_t *name2) {
isc_boolean_t
dns_name_issubdomain(dns_name_t *name1, dns_name_t *name2) {
unsigned int l1, l2, count1, count2;
unsigned int b1, b2, n;
unsigned char c1, c2;
unsigned char *label1, *label2;
unsigned char *offsets1, *offsets2;
dns_offsets_t odata1, odata2;
int order;
unsigned int nlabels, nbits;
dns_namereln_t namereln;
/*
* Is 'name1' a subdomain of 'name2'?
@ -546,69 +660,13 @@ dns_name_issubdomain(dns_name_t *name1, dns_name_t *name2) {
* same domain.
*/
REQUIRE(VALID_NAME(name1));
REQUIRE(name1->labels > 0);
REQUIRE(VALID_NAME(name2));
REQUIRE(name2->labels > 0);
namereln = dns_name_fullcompare(name1, name2, &order, &nlabels,
&nbits);
if (namereln == dns_namereln_subdomain ||
namereln == dns_namereln_equal)
return (ISC_TRUE);
SETUP_OFFSETS(name1, offsets1, odata1);
SETUP_OFFSETS(name2, offsets2, odata2);
/*
* Either name1 is absolute and name2 is absolute, or neither is.
*/
REQUIRE(((name1->ndata[offsets1[name1->labels - 1]] == 0 ? 1 : 0) ^
(name2->ndata[offsets2[name2->labels - 1]] == 0 ? 1 : 0))
== 0);
l1 = name1->labels;
l2 = name2->labels;
if (l1 < l2)
return (ISC_FALSE);
while (l2 > 0) {
l1--;
l2--;
label1 = &name1->ndata[offsets1[l1]];
label2 = &name2->ndata[offsets2[l2]];
count1 = *label1++;
count2 = *label2++;
if (count1 <= 63 && count2 <= 63) {
if (count1 != count2)
return (ISC_FALSE);
while (count2 > 0) {
count2--;
c1 = maptolower[*label1++];
c2 = maptolower[*label2++];
if (c1 != c2)
return (ISC_FALSE);
}
} else {
if (count1 != count2)
return (ISC_FALSE);
INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
count2 == DNS_LABELTYPE_BITSTRING);
count1 = *label1++;
if (count1 == 0)
count1 = 256;
count2 = *label2++;
if (count2 == 0)
count2 = 256;
if (count1 < count2)
return (ISC_FALSE);
/* Yes, this loop is really slow! */
for (n = 0; n < count2; n++) {
b1 = get_bit(label1, n);
b2 = get_bit(label2, n);
if (b1 != b2)
return (ISC_FALSE);
}
if (count1 != count2 && l2 != 0)
return (ISC_FALSE);
}
}
return (ISC_TRUE);
return (ISC_FALSE);
}
unsigned int