name.c revision 40f53fa8d9c6a4fc38c0014495e7a42b08f52481
c19f42a378f76af272166f9cababe7bfbc1cf6abTinderbox User * Copyright (C) 1998-2000 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
e7008e7007f440490174a52b7117f3c6d121d303Mark Andrews/* $Id: name.c,v 1.100 2000/08/01 01:22:33 tale Exp $ */
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunttypedef enum {
de52784e45e3a7a92c0d8ad843eb4db313bbfd97Mark Andrewstypedef enum {
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntstatic unsigned char maptolower[] = {
de52784e45e3a7a92c0d8ad843eb4db313bbfd97Mark Andrews 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
de52784e45e3a7a92c0d8ad843eb4db313bbfd97Mark Andrews 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
5e965459a66e9e83e56091d5366c17f1953ab3ceAutomatic Updater 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
d64e3b29bd1b66a4bc80b60ef87a5bafe741d7caMark Andrews 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
d64e3b29bd1b66a4bc80b60ef87a5bafe741d7caMark Andrews 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
d64e3b29bd1b66a4bc80b60ef87a5bafe741d7caMark Andrews 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt var = default; \
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Note: If additional attributes are added that should not be set for
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * empty names, MAKE_EMPTY() must be changed so it clears them.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * A name is "bindable" if it can be set to point to a new value, i.e.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * name->ndata and name->length may be changed.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * This silliness is to avoid warnings about the const attribute of a string
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * being discarded, as can happen (depending on the compiler and flags)
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * when name.ndata or name.offsets is assigned to via a string literal.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Unfortunately, gcc -Wwrite-strings produces incorrect warnings for
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * assigning a const string to the ndata or offsets members in
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * "const struct dns_name root", which (at least according to the ANSI
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Draft dated August 3, 1998) should have the effect of declaring all
de52784e45e3a7a92c0d8ad843eb4db313bbfd97Mark Andrews * members of the struct as const.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt/* XXXDCL make const? */
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt/* XXXDCL make const? */
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntset_offsets(const dns_name_t *name, unsigned char *offsets,
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Yes, get_bit and set_bit are lame. We define them here so they can
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * be inlined by smart compilers.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntstatic inline unsigned int
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntstatic inline void
de52784e45e3a7a92c0d8ad843eb4db313bbfd97Mark Andrewsset_bit(unsigned char *array, unsigned int idx, unsigned int bit) {
d64e3b29bd1b66a4bc80b60ef87a5bafe741d7caMark Andrews * Get the type of 'label'.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt unsigned int count;
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * The number of bits in a bitstring label.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntdns_label_getbit(dns_label_t *label, unsigned int n) {
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * The 'n'th most significant bit of 'label'.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Numbering starts at 0.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntdns_name_init(dns_name_t *name, unsigned char *offsets) {
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Initialize 'name'.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Make 'name' invalid.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Huntdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Dedicate a buffer for use with 'name'.
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt REQUIRE((buffer != NULL && name->buffer == NULL) ||
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Does 'name' have a dedicated buffer?
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Does 'name' end in the root label?
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt unsigned char *ndata;
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Is 'name' a wildcard name?
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt unsigned char *ndata;
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt * Does 'name' require EDNS for transmission?
5a75f61dd413720c16d229b24ebba6bd6ecdb738Evan Hunt while (nrem > 0) {
nrem--;
if (count == 0)
return (requiresedns);
unsigned int length;
if (case_sensitive) {
while (length > 0) {
length--;
while (length > 0) {
c = maptolower[*s];
length--;
int *orderp,
nlabels = 0;
nbits = 0;
if (ldiff < 0)
l = l1;
l = l2;
l1--;
l2--;
if (cdiff < 0)
while (count > 0) {
if (chdiff != 0) {
goto done;
count--;
label1++;
label2++;
if (cdiff != 0) {
goto done;
nlabels++;
if (count2 == 0)
goto done;
if (count1 == 0)
goto done;
if (count1 == 0)
if (count2 == 0)
cdiff = 0;
for (n = 0; n < count; n++) {
goto done;
goto done;
if (nbits == 0)
nlabels++;
nbits++;
if (cdiff != 0) {
if (cdiff < 0) {
if (l1 > 0)
namereln =
if (l2 > 0)
namereln =
goto done;
nbits = 0;
if (ldiff < 0)
else if (ldiff > 0)
done:
return (namereln);
int order;
return (order);
unsigned int l, count;
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
while (count > 0) {
count--;
return (ISC_FALSE);
return (ISC_FALSE);
if (count == 0)
while (count > 0) {
count--;
c = *label1++;
if (c != *label2++)
return (ISC_FALSE);
return (ISC_TRUE);
while (count > 0) {
count--;
if (count1 == 0)
if (count2 == 0)
while (count > 0) {
count--;
int order;
&nbits);
return (ISC_TRUE);
return (ISC_FALSE);
int order;
return (ISC_TRUE);
return (ISC_FALSE);
unsigned char *ndata;
depth = 0;
while (nrem > 0) {
nrem--;
n = *ndata++;
nrem--;
depth += n;
count++;
depth++;
if (count == 0)
return (depth);
unsigned char *offsets;
unsigned int first, unsigned int n,
unsigned char *offsets;
REQUIRE(n > 0);
unsigned char *offsets;
unsigned int len;
if (r->length > 0)
char *tdata;
unsigned char *offsets;
offsets[0] = 0;
n1 = 0;
n2 = 0;
vlen = 0;
digits = 0;
value = 0;
count = 0;
tbcount = 0;
bitlength = 0;
maxlength = 0;
tused = 0;
nused = 0;
labels = 0;
c = *tdata++;
tlen--;
tused++;
switch (state) {
case ft_init:
if (tlen != 0)
return (DNS_R_EMPTYLABEL);
labels++;
*ndata++ = 0;
nrem--;
nused++;
case ft_start:
ndata++;
nrem--;
nused++;
count = 0;
case ft_ordinary:
if (count == 0)
return (DNS_R_EMPTYLABEL);
labels++;
if (tlen == 0) {
labels++;
*ndata++ = 0;
nrem--;
nused++;
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
case ft_initialescape:
ndata++;
nrem--;
nused++;
case ft_escape:
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
digits = 0;
value = 0;
case ft_escdecimal:
return (DNS_R_BADESCAPE);
digits++;
return (DNS_R_BADESCAPE);
return (DNS_R_LABELTOOLONG);
count++;
if (downcase)
nrem--;
nused++;
case ft_bitstring:
tbcount = 0;
value = 0;
n1 = 0;
n2 = 0;
digits = 0;
goto no_read;
return (DNS_R_BADBITSTRING);
case ft_binary:
goto no_read;
count++;
tbcount++;
return (DNS_R_BITSTRINGTOOLONG);
nrem--;
nused++;
count = 0;
case ft_octal:
goto no_read;
return (DNS_R_BITSTRINGTOOLONG);
nrem--;
nused++;
count = 0;
nrem--;
nused++;
nrem--;
nused++;
case ft_hex:
goto no_read;
return (DNS_R_BITSTRINGTOOLONG);
nrem--;
nused++;
count = 0;
case ft_dottedquad:
return (DNS_R_BADDOTTEDQUAD);
n1++;
goto no_read;
value = 0;
digits = 0;
case ft_dqdecimal:
return (DNS_R_BADDOTTEDQUAD);
goto no_read;
digits++;
return (DNS_R_BADDOTTEDQUAD);
case ft_maybeslash:
bitlength = 0;
case ft_finishbitstring:
if (tbcount == 0)
return (DNS_R_BADBITSTRING);
if (count > 0) {
if (n1 != 0)
if (bitlength != 0) {
return (DNS_R_BADBITSTRING);
return (DNS_R_BADBITSTRING);
n1++;
return (DNS_R_BADBITSTRING);
if (value != 0)
count = 0;
n1++;
return (DNS_R_BADBITSTRING);
if (n1 != 0) {
if ((value &
return (DNS_R_BADBITSTRING);
return (DNS_R_BADBITSTRING);
if (count > 0) {
nrem--;
nused++;
n1++;
return (ISC_R_NOSPACE);
nrem--;
nused++;
*label = 0;
labels++;
return (DNS_R_BADBITSTRING);
case ft_bitlength:
if (bitlength == 0)
return (DNS_R_BADBITSTRING);
goto no_read;
return (DNS_R_BADBITSTRING);
case ft_eatdot:
return (DNS_R_BADBITSTRING);
if (tlen == 0) {
labels++;
*ndata++ = 0;
nrem--;
nused++;
if (!done) {
if (nrem == 0)
return (ISC_R_NOSPACE);
return (ISC_R_UNEXPECTEDEND);
labels++;
return (ISC_R_NOSPACE);
while (n1 > 0) {
while (n2 > 0) {
c = *label++;
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
n2--;
if (bitlength == 0)
n2++;
while (n2 > 0) {
n2--;
labels++;
if (n1 > 0) {
if (saw_bitstring)
return (ISC_R_SUCCESS);
unsigned char *ndata;
char *tdata;
unsigned int labels;
if (trem == 0)
return (ISC_R_NOSPACE);
trem--;
nlen = 0;
if (trem == 0)
return (ISC_R_NOSPACE);
trem--;
nlen = 0;
labels--;
nlen--;
if (count == 0) {
while (count > 0) {
c = *ndata;
return (ISC_R_NOSPACE);
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
nlen--;
if (trem == 0)
return (ISC_R_NOSPACE);
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
return (ISC_R_NOSPACE);
ndata++;
nlen--;
count--;
return (ISC_R_NOSPACE);
if (count == 0)
nlen--;
bytes++;
nibbles++;
return (ISC_R_NOSPACE);
while (nibbles > 0) {
c = *ndata++;
nibbles--;
if (nibbles != 0) {
nibbles--;
return (ISC_R_NOSPACE);
for (i = 0; i < len; i++)
if (trem == 0)
return (ISC_R_NOSPACE);
trem--;
return (ISC_R_NOSPACE);
trem++;
return (ISC_R_SUCCESS);
return (ISC_R_NOSPACE);
labels--;
nlen--;
while (count > 0) {
nlen--;
count--;
if (count == 0)
nlen--;
bytes++;
while (bytes > 0) {
bytes--;
return (ISC_R_SUCCESS);
unsigned char *ndata;
offset = 0;
nlabels = 0;
offset++;
if (count == 0) {
n = *ndata++;
offset++;
count++;
if (absolute)
if (currbits == 0)
currindex = 0;
if (headbits == 0)
if (headrem != 0)
if (headrem != 0) {
bit);
currindex++;
headindex++;
headbits++;
count--;
headrem--;
} while (headrem != 0);
tailindex = 0;
tailbits = 0;
while (count > 0) {
currindex++;
tailindex++;
tailbits++;
count--;
newbits = 0;
newindex = 0;
bit);
currindex++;
newindex++;
newbits++;
if (newrem != 0) {
count++;
while (newrem > 0) {
newrem--;
newindex++;
count++;
while (count > 0) {
count--;
count++;
while (count > 0) {
count--;
goto again;
unsigned char *offsets;
new_current = 0;
labels = 0;
hops = 0;
nused = 0;
cused = 0;
c = *cdata++;
current++;
if (hops == 0)
cused++;
switch (state) {
case fw_start:
labels++;
goto full;
*ndata++ = c;
return (DNS_R_BADLABELTYPE);
return (DNS_R_DISALLOWED);
} else if (c == DNS_LABELTYPE_BITSTRING) {
labels++;
goto full;
nused++;
*ndata++ = c;
} else if (c == DNS_LABELTYPE_GLOBALCOMP16) {
return (DNS_R_DISALLOWED);
new_current = 0;
return (DNS_R_BADLABELTYPE);
case fw_ordinary:
if (downcase)
c = maptolower[c];
case fw_copy:
*ndata++ = c;
case fw_bitstring:
goto full;
*ndata++ = c;
case fw_newcurrent:
new_current += c;
return (DNS_R_BADPOINTER);
hops++;
return (DNS_R_TOOMANYHOPS);
if (!done)
return (ISC_R_UNEXPECTEDEND);
if (saw_bitstring)
return (ISC_R_SUCCESS);
full:
return (DNS_R_NAMETOOLONG);
return (ISC_R_NOSPACE);
unsigned int methods;
if (gf) {
return (ISC_R_NOSPACE);
return (ISC_R_NOSPACE);
return (ISC_R_NOSPACE);
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
if (copy_prefix &&
length = 0;
prefix_length = 0;
labels = 0;
if (copy_prefix) {
if (copy_suffix) {
return (DNS_R_NAMETOOLONG);
return (ISC_R_NOSPACE);
if (copy_suffix) {
if (copy_prefix &&
if (absolute)
if (saw_bitstring)
return (ISC_R_SUCCESS);
(nbits != 0 &&
(*p == 0 || *p > nbits)));
if (nbits > 0) {
*p = *p - nbits;
return(ISC_R_NOSPACE);
if (mod == 0) {
while (len--) {
if (len > 0)
*dst++ |=
prefix);
if (nbits > 0) {
return (ISC_R_NOSPACE);
if (len > 0) {
src = p;
if (len > 0) {
if (mod)
return (result);
suffixlabels = 0;
nbits = 0;
label--;
n = *ndata++;
suffixlabels++;
if (n <= depth) {
depth -= n;
depth = 0;
suffixlabels++;
depth--;
if (depth != 0) {
INSIST(0);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
isc_region_t r;
return (result);
isc_buffer_t b;
isc_region_t r;
isc_buffer_init(&b, t, sizeof(t));
return (result);
isc_buffer_usedregion(&b, &r);
return (ISC_R_SUCCESS);
isc_region_t r;