name.c revision f083a44415365f6464f8bd35f439dc13ee0b684f
/*
* Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: name.c,v 1.170 2010/05/12 05:40:32 marka Exp $ */
/*! \file */
#include <config.h>
#include <ctype.h>
#include <stdlib.h>
#include <dns/compress.h>
#include <dns/fixedname.h>
typedef enum {
ft_init = 0,
} ft_state;
typedef enum {
fw_start = 0,
} fw_state;
static char digitvalue[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
};
static unsigned char maptolower[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#define CONVERTTOASCII(c)
#define CONVERTFROMASCII(c)
else \
var = default;
else { \
var = default; \
}
/*%
* Note: If additional attributes are added that should not be set for
* empty names, MAKE_EMPTY() must be changed so it clears them.
*/
#define MAKE_EMPTY(name) \
do { \
} while (0);
/*%
* A name is "bindable" if it can be set to point to a new value, i.e.
* name->ndata and name->length may be changed.
*/
== 0)
/*%
* Note that the name data must be a char array, not a string
* literal, to avoid compiler warnings about discarding
* the const attribute of a string.
*/
static unsigned char root_ndata[] = { '\0' };
static unsigned char root_offsets[] = { 0 };
static dns_name_t root =
{
{(void *)-1, (void *)-1},
};
/* XXXDCL make const? */
static unsigned char wild_offsets[] = { 0 };
static dns_name_t wild =
{
{(void *)-1, (void *)-1},
};
/* XXXDCL make const? */
unsigned int
/*
* dns_name_t to text post-conversion procedure.
*/
#ifdef ISC_PLATFORM_USETHREADS
static int thread_key_initialized = 0;
static isc_mutex_t thread_key_mutex;
#else
#endif
static void
void
/*
* Initialize 'name'.
*/
}
void
}
void
/*
* Make 'name' invalid.
*/
name->attributes = 0;
}
void
/*
* Dedicate a buffer for use with 'name'.
*/
}
/*
* Does 'name' have a dedicated buffer?
*/
return (ISC_TRUE);
return (ISC_FALSE);
}
/*
* Does 'name' end in the root label?
*/
return (ISC_TRUE);
return (ISC_FALSE);
}
#define hyphenchar(c) ((c) == 0x2d)
#define asterchar(c) ((c) == 0x2a)
|| ((c) >= 0x61 && (c) <= 0x7a))
unsigned int n;
/*
* Root label.
*/
return (ISC_TRUE);
n = *ndata++;
INSIST(n <= 63);
while (n--) {
if (!domainchar(ch))
return (ISC_FALSE);
}
return (ISC_FALSE);
/*
*/
n = *ndata++;
INSIST(n <= 63);
while (n--) {
if (first || n == 0) {
if (!borderchar(ch))
return (ISC_FALSE);
} else {
if (!middlechar(ch))
return (ISC_FALSE);
}
}
}
return (ISC_TRUE);
}
unsigned int n;
/*
* Root label.
*/
return (ISC_TRUE);
/*
* Skip wildcard if this is a ownername.
*/
ndata += 2;
/*
*/
n = *ndata++;
INSIST(n <= 63);
while (n--) {
if (first || n == 0) {
if (!borderchar(ch))
return (ISC_FALSE);
} else {
if (!middlechar(ch))
return (ISC_FALSE);
}
}
}
return (ISC_TRUE);
}
unsigned char *ndata;
/*
* Is 'name' a wildcard name?
*/
return (ISC_TRUE);
}
return (ISC_FALSE);
}
unsigned char *ndata;
unsigned int count;
unsigned int label;
/*
* Does 'name' contain a internal wildcard?
*/
/*
* Skip first label.
*/
label = 1;
/*
* Check all but the last of the remaining labels.
*/
return (ISC_TRUE);
label++;
}
return (ISC_FALSE);
}
static inline unsigned int
unsigned int length;
const unsigned char *s;
unsigned int h = 0;
unsigned char c;
if (length > 16)
length = 16;
/*
* This hash function is similar to the one Ousterhout
* uses in Tcl.
*/
if (case_sensitive) {
while (length > 0) {
h += ( h << 3 ) + *s;
s++;
length--;
}
} else {
while (length > 0) {
c = maptolower[*s];
h += ( h << 3 ) + c;
s++;
length--;
}
}
return (h);
}
unsigned int
/*
* Provide a hash value for 'name'.
*/
return (0);
}
unsigned int
/*
* Provide a hash value for 'name'.
*/
return (0);
}
unsigned int
/*
* This function was deprecated due to the breakage of the name space
* convention. We only keep this internally to provide binary backward
* compatibility.
*/
}
unsigned int
unsigned char *offsets;
unsigned int h = 0;
unsigned int i;
/*
* Provide a hash value for 'name'.
*/
return (0);
h = 0;
else
}
return (h);
}
{
/*
* Determine the relative ordering under the DNSSEC order relation of
* '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.
*/
/*
* Either name1 is absolute and name2 is absolute, or neither is.
*/
nlabels = 0;
if (ldiff < 0)
l = l1;
else
l = l2;
while (l > 0) {
l--;
l1--;
l2--;
/*
* We dropped bitstring labels, and we don't support any
* other extended label types.
*/
if (cdiff < 0)
else
while (count > 0) {
(int)maptolower[*label2];
if (chdiff != 0) {
goto done;
}
count--;
label1++;
label2++;
}
if (cdiff != 0) {
goto done;
}
nlabels++;
}
if (ldiff < 0)
else if (ldiff > 0)
else
done:
return (namereln);
}
int
int order;
unsigned int nlabels;
/*
* 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.
*/
return (order);
}
unsigned int l, count;
unsigned char c;
/*
* Are 'name1' and 'name2' equal?
*
* 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.
*/
/*
* Either name1 is absolute and name2 is absolute, or neither is.
*/
return (ISC_FALSE);
return (ISC_FALSE);
while (l > 0) {
l--;
return (ISC_FALSE);
while (count > 0) {
count--;
c = maptolower[*label1++];
if (c != maptolower[*label2++])
return (ISC_FALSE);
}
}
return (ISC_TRUE);
}
/*
* Are 'name1' and 'name2' equal?
*
* 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.
*/
/*
* Either name1 is absolute and name2 is absolute, or neither is.
*/
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
}
int
/*
* Compare two absolute names as rdata.
*/
while (l > 0) {
l--;
/* no bitstring support */
while (count > 0) {
count--;
return (-1);
return (1);
}
}
/*
* If one name had more labels than the other, their common
* prefix must have been different because the shorter name
* ended with the root label and the longer one can't have
* a root label in the middle of it. Therefore, if we get
* to this point, the lengths must be equal.
*/
return (0);
}
int order;
unsigned int nlabels;
/*
* Is 'name1' a subdomain of '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.
*/
if (namereln == dns_namereln_subdomain ||
return (ISC_TRUE);
return (ISC_FALSE);
}
int order;
return (ISC_TRUE);
return (ISC_FALSE);
}
unsigned int
/*
* How many labels does 'name' have?
*/
}
void
unsigned char *offsets;
/*
* Make 'label' refer to the 'n'th least significant label of 'name'.
*/
else
}
void
unsigned int first, unsigned int n,
{
unsigned char *offsets;
unsigned int firstoffset, endoffset;
/*
* Make 'target' refer to the 'n' labels including and following
* 'first' in 'source'.
*/
else
else
else
/*
* If source and target are the same, and we're making target
* a prefix of source, the offsets table is correct already
* so we don't need to call set_offsets().
*/
}
void
/*
* Make 'target' refer to the same name as 'source'.
*/
(unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
else
}
}
void
unsigned char *offsets;
unsigned int len;
/*
* Make 'name' refer to region 'r'.
*/
if (len > DNS_NAME_MAXWIRE)
} else {
r->length : DNS_NAME_MAXWIRE;
}
if (r->length > 0)
else {
}
}
void
/*
* Make 'r' refer to 'name'.
*/
DNS_NAME_TOREGION(name, r);
}
{
char *tdata;
char c;
unsigned char *offsets;
/*
* Convert the textual representation of a DNS name at source
* into uncompressed wire form stored in target.
*
* Notes:
* Relative domain names will have 'origin' appended to them
* unless 'origin' is NULL, in which case relative domain names
* will remain relative.
*/
}
offsets[0] = 0;
/*
* Initialize things to make the compiler happy; they're not required.
*/
n1 = 0;
n2 = 0;
digits = 0;
value = 0;
count = 0;
/*
* Make 'name' empty in case of failure.
*/
/*
* Set up the state machine.
*/
tused = 0;
if (nrem > 255)
nrem = 255;
nused = 0;
labels = 0;
c = *tdata++;
tlen--;
tused++;
switch (state) {
case ft_init:
/*
* Is this the root name?
*/
if (c == '.') {
if (tlen != 0)
return (DNS_R_EMPTYLABEL);
labels++;
*ndata++ = 0;
nrem--;
nused++;
break;
}
if (c == '@' && tlen == 0) {
break;
}
/* FALLTHROUGH */
case ft_start:
ndata++;
nrem--;
nused++;
count = 0;
if (c == '\\') {
break;
}
state = ft_ordinary;
if (nrem == 0)
return (ISC_R_NOSPACE);
/* FALLTHROUGH */
case ft_ordinary:
if (c == '.') {
if (count == 0)
return (DNS_R_EMPTYLABEL);
labels++;
if (tlen == 0) {
labels++;
*ndata++ = 0;
nrem--;
nused++;
}
} else if (c == '\\') {
} else {
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
}
break;
case ft_initialescape:
if (c == '[') {
/*
* This looks like a bitstring label, which
* was deprecated. Intentionally drop it.
*/
return (DNS_R_BADLABELTYPE);
}
/* FALLTHROUGH */
case ft_escape:
if (!isdigit(c & 0xff)) {
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
CONVERTTOASCII(c);
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
nrem--;
nused++;
state = ft_ordinary;
break;
}
digits = 0;
value = 0;
/* FALLTHROUGH */
case ft_escdecimal:
if (!isdigit(c & 0xff))
return (DNS_R_BADESCAPE);
value *= 10;
value += digitvalue[(int)c];
digits++;
if (digits == 3) {
if (value > 255)
return (DNS_R_BADESCAPE);
if (count >= 63)
return (DNS_R_LABELTOOLONG);
count++;
if (downcase)
nrem--;
nused++;
state = ft_ordinary;
}
break;
default:
"Unexpected state %d", state);
/* Does not return. */
}
}
if (!done) {
if (nrem == 0)
return (ISC_R_NOSPACE);
return (ISC_R_UNEXPECTEDEND);
if (state == ft_ordinary) {
labels++;
}
return (ISC_R_NOSPACE);
while (n1 > 0) {
while (n2 > 0) {
c = *label++;
if (downcase)
c = maptolower[(int)c];
*ndata++ = c;
n2--;
}
labels++;
if (n1 > 0) {
}
}
}
} else
return (ISC_R_SUCCESS);
}
#ifdef ISC_PLATFORM_USETHREADS
static void
free_specific(void *arg) {
/* Stop use being called again. */
}
static void
thread_key_mutex_init(void) {
}
static isc_result_t
totext_filter_proc_key_init(void) {
/*
* We need the call to isc_once_do() to support profiled mutex
* otherwise thread_key_mutex could be initialized at compile time.
*/
if (result != ISC_R_SUCCESS)
return (result);
if (!thread_key_initialized) {
if (thread_key_mctx == NULL)
if (result != ISC_R_SUCCESS)
goto unlock;
if (!thread_key_initialized &&
free_specific) != 0) {
} else
}
return (result);
}
#endif
{
unsigned char *ndata;
char *tdata;
unsigned char c;
unsigned int labels;
#ifdef ISC_PLATFORM_USETHREADS
#endif
/*
* This function assumes the name is in proper uncompressed
* wire format.
*/
#ifdef ISC_PLATFORM_USETHREADS
if (result != ISC_R_SUCCESS)
return (result);
#endif
/*
* Special handling for an empty name.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
/*
* The names of these booleans are misleading in this case.
* This empty name is not necessarily from the root node of
* the DNS root zone, nor is a final dot going to be included.
* They need to be set this way, though, to keep the "@"
* from being trounced.
*/
*tdata++ = '@';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
/*
* Special handling for the root label.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
}
labels--;
nlen--;
if (count == 0) {
break;
}
if (count < 64) {
while (count > 0) {
c = *ndata;
switch (c) {
case 0x22: /* '"' */
case 0x28: /* '(' */
case 0x29: /* ')' */
case 0x2E: /* '.' */
case 0x3B: /* ';' */
case 0x5C: /* '\\' */
/* Special modifiers in zone files. */
case 0x40: /* '@' */
case 0x24: /* '$' */
if (trem < 2)
return (ISC_R_NOSPACE);
*tdata++ = '\\';
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem -= 2;
nlen--;
break;
default:
if (c > 0x20 && c < 0x7f) {
if (trem == 0)
return (ISC_R_NOSPACE);
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
} else {
if (trem < 4)
return (ISC_R_NOSPACE);
*tdata++ = 0x5c;
*tdata++ = 0x30 +
((c / 100) % 10);
*tdata++ = 0x30 +
((c / 10) % 10);
trem -= 4;
ndata++;
nlen--;
}
}
count--;
}
} else {
"Unexpected label type %02x", count);
/* NOTREACHED */
}
/*
* The following assumes names are absolute. If not, we
* fix things up later. Note that this means that in some
* cases one more byte of text buffer is required than is
* needed in the final output.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
}
return (ISC_R_NOSPACE);
if (!saw_root || omit_final_dot)
trem++;
#ifdef ISC_PLATFORM_USETHREADS
#endif
if (totext_filter_proc != NULL)
return (ISC_R_SUCCESS);
}
{
unsigned char *ndata;
char *tdata;
unsigned char c;
unsigned int labels;
/*
* This function assumes the name is in proper uncompressed
* wire format.
*/
/*
* Special handling for the root label.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
/*
* Skip the while() loop.
*/
nlen = 0;
}
labels--;
nlen--;
if (count == 0)
break;
if (count < 64) {
while (count > 0) {
c = *ndata;
if ((c >= 0x30 && c <= 0x39) || /* digit */
(c >= 0x41 && c <= 0x5A) || /* uppercase */
(c >= 0x61 && c <= 0x7A) || /* lowercase */
c == 0x2D || /* hyphen */
c == 0x5F) /* underscore */
{
if (trem == 0)
return (ISC_R_NOSPACE);
/* downcase */
if (c >= 0x41 && c <= 0x5A)
c += 0x20;
CONVERTFROMASCII(c);
*tdata++ = c;
ndata++;
trem--;
nlen--;
} else {
if (trem < 3)
return (ISC_R_NOSPACE);
tdata += 3;
trem -= 3;
ndata++;
nlen--;
}
count--;
}
} else {
"Unexpected label type %02x", count);
/* NOTREACHED */
}
/*
* The following assumes names are absolute. If not, we
* fix things up later. Note that this means that in some
* cases one more byte of text buffer is required than is
* needed in the final output.
*/
if (trem == 0)
return (ISC_R_NOSPACE);
*tdata++ = '.';
trem--;
}
return (ISC_R_NOSPACE);
if (omit_final_dot)
trem++;
return (ISC_R_SUCCESS);
}
/*
* Downcase 'source'.
*/
} else {
}
}
return (ISC_R_NOSPACE);
}
labels--;
nlen--;
if (count < 64) {
while (count > 0) {
nlen--;
count--;
}
} else {
"Unexpected label type %02x", count);
/* Does not return. */
}
}
else
name->attributes = 0;
}
return (ISC_R_SUCCESS);
}
static void
{
unsigned char *ndata;
offset = 0;
nlabels = 0;
offset++;
if (count == 0) {
break;
}
}
if (absolute)
else
}
}
{
unsigned int cused; /* Bytes of compressed name data used */
unsigned int c;
unsigned char *offsets;
/*
* Copy the possibly-compressed name at source into target,
* decompressing it. Loop prevention is performed by checking
* the new pointer against biggest_pointer.
*/
}
/*
* Make 'name' empty in case of failure.
*/
/*
* Initialize things to make the compiler happy; they're not required.
*/
n = 0;
new_current = 0;
/*
* Set up.
*/
labels = 0;
nused = 0;
/*
* Find the maximum number of uncompressed target name
* bytes we are willing to generate. This is the smaller
* of the available target buffer length and the
* maximum legal domain name length (255).
*/
if (nmax > DNS_NAME_MAXWIRE)
cused = 0;
/*
* Note: The following code is not optimized for speed, but
* rather for correctness. Speed will be addressed in the future.
*/
c = *cdata++;
current++;
if (!seen_pointer)
cused++;
switch (state) {
case fw_start:
if (c < 64) {
labels++;
goto full;
nused += c + 1;
*ndata++ = c;
if (c == 0)
n = c;
state = fw_ordinary;
} else if (c >= 128 && c < 192) {
/*
* 14 bit local compression pointer.
* Local compression is no longer an
* IETF draft.
*/
return (DNS_R_BADLABELTYPE);
} else if (c >= 192) {
/*
* Ordinary 14-bit pointer.
*/
0)
return (DNS_R_DISALLOWED);
new_current = c & 0x3F;
n = 1;
} else
return (DNS_R_BADLABELTYPE);
break;
case fw_ordinary:
if (downcase)
c = maptolower[c];
/* FALLTHROUGH */
case fw_copy:
*ndata++ = c;
n--;
if (n == 0)
break;
case fw_newcurrent:
new_current *= 256;
new_current += c;
n--;
if (n != 0)
break;
if (new_current >= biggest_pointer)
return (DNS_R_BADPOINTER);
break;
default:
"Unknown state %d", state);
/* Does not return. */
}
}
if (!done)
return (ISC_R_UNEXPECTEDEND);
return (ISC_R_SUCCESS);
full:
if (nmax == DNS_NAME_MAXWIRE)
/*
* The name did not fit even though we had a buffer
* big enough to fit a maximum-length name.
*/
return (DNS_R_NAMETOOLONG);
else
/*
* The name might fit if only the caller could give us a
* big enough buffer.
*/
return (ISC_R_NOSPACE);
}
{
unsigned int methods;
/*
* Convert 'name' into wire format, compressing it as specified by the
* compression context 'cctx', and storing the result in 'target'.
*/
/*
* If 'name' doesn't have an offsets table, make a clone which
* has one.
*/
}
(methods & DNS_COMPRESS_GLOBAL14) != 0)
else
/*
* If the offset is too high for 14 bit global compression, we're
* out of luck.
*/
/*
* Will the compression pointer reduce the message size?
*/
if (gf) {
return (ISC_R_NOSPACE);
go |= 0xc000;
return (ISC_R_NOSPACE);
} else {
return (ISC_R_NOSPACE);
}
return (ISC_R_SUCCESS);
}
{
/*
* Concatenate 'prefix' and 'suffix'.
*/
if (copy_prefix &&
}
}
}
/*
* Set up.
*/
if (nrem > DNS_NAME_MAXWIRE)
length = 0;
prefix_length = 0;
labels = 0;
if (copy_prefix) {
length += prefix_length;
}
if (copy_suffix) {
}
if (length > DNS_NAME_MAXWIRE) {
return (DNS_R_NAMETOOLONG);
}
return (ISC_R_NOSPACE);
}
if (copy_suffix) {
else
}
/*
* If 'prefix' and 'name' are the same object, and the object has
* a dedicated buffer, and we're using it, then we don't have to
* copy anything.
*/
if (absolute)
else
name->attributes = 0;
}
return (ISC_R_SUCCESS);
}
void
{
unsigned int splitlabel;
REQUIRE(suffixlabels > 0);
(VALID_NAME(prefix) &&
(VALID_NAME(suffix) &&
return;
}
{
/*
* Make 'target' a dynamically allocated copy of 'source'.
*/
/*
* Make 'target' empty in case of failure.
*/
return (ISC_R_NOMEMORY);
else
}
return (ISC_R_SUCCESS);
}
{
/*
* Make 'target' a read-only dynamically allocated copy of 'source'.
* 'target' will also have a dynamically allocated offsets table.
*/
/*
* Make 'target' empty in case of failure.
*/
return (ISC_R_NOMEMORY);
else
return (ISC_R_SUCCESS);
}
void
/*
* Free 'name'.
*/
}
unsigned char data[256];
isc_region_t r;
/*
* Send 'name' in DNSSEC canonical form to 'digest'.
*/
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&buffer, &r);
}
/*
* Returns whether there is dynamic memory associated with this name.
*/
}
isc_buffer_t b;
isc_region_t r;
char t[1024];
/*
* Print 'name' on 'stream'.
*/
isc_buffer_init(&b, t, sizeof(t));
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&b, &r);
return (ISC_R_SUCCESS);
}
#ifdef ISC_PLATFORM_USETHREADS
int res;
if (result != ISC_R_SUCCESS)
return (result);
/*
* If we already have been here set / clear as appropriate.
* Otherwise allocate memory.
*/
return (ISC_R_SUCCESS);
}
if (res != 0)
return (result);
}
return (ISC_R_NOMEMORY);
}
return (result);
#else
return (ISC_R_SUCCESS);
#endif
}
void
/*
* Leave room for null termination after buffer.
*/
if (result == ISC_R_SUCCESS) {
/*
* Null terminate.
*/
isc_region_t r;
isc_buffer_usedregion(&buf, &r);
} else
}
/*
* dns_name_tostring() -- similar to dns_name_format() but allocates its own
* memory.
*/
char *p, txt[DNS_NAME_FORMATSIZE];
if (result != ISC_R_SUCCESS)
return (result);
*target = p;
return (ISC_R_SUCCESS);
}
/*
* dns_name_fromstring() -- convert directly from a string to a name,
* allocating memory as needed
*/
{
if (result != ISC_R_SUCCESS)
return (result);
return (result);
}
unsigned char *ndata;
/*
* Make dest a copy of source.
*/
}
/*
* Set up.
*/
return (ISC_R_NOSPACE);
else
dest->attributes = 0;
else
}
return (ISC_R_SUCCESS);
}
void
dns_name_destroy(void) {
#ifdef ISC_PLATFORM_USETHREADS
== ISC_R_SUCCESS);
if (thread_key_initialized) {
}
#endif
}