2
* Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
2
* Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3
3
* Copyright (C) 1998-2003 Internet Software Consortium.
5
* Permission to use, copy, modify, and distribute this software for any
5
* Permission to use, copy, modify, and/or distribute this software for any
6
6
* purpose with or without fee is hereby granted, provided that the above
7
7
* copyright notice and this permission notice appear in all copies.
15
15
* PERFORMANCE OF THIS SOFTWARE.
18
/* $Id: name.c,v 1.127.2.7.2.14 2005/10/14 01:38:48 marka Exp $ */
18
/* $Id: name.c,v 1.163.128.2 2008/03/31 23:46:42 tbox Exp $ */
20
22
#include <config.h>
24
27
#include <isc/buffer.h>
25
28
#include <isc/hash.h>
26
29
#include <isc/mem.h>
27
31
#include <isc/print.h>
28
32
#include <isc/string.h>
33
#include <isc/thread.h>
29
34
#include <isc/util.h>
31
36
#include <dns/compress.h>
122
127
set_offsets(name, var, NULL); \
126
131
* Note: If additional attributes are added that should not be set for
127
132
* empty names, MAKE_EMPTY() must be changed so it clears them.
142
147
((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
146
151
* Note that the name data must be a char array, not a string
147
152
* literal, to avoid compiler warnings about discarding
148
153
* the const attribute of a string.
183
188
dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
191
* dns_name_t to text post-conversion procedure.
193
#ifdef ISC_PLATFORM_USETHREADS
194
static int thread_key_initialized = 0;
195
static isc_mutex_t thread_key_mutex;
196
static isc_mem_t *thread_key_mctx = NULL;
197
static isc_thread_key_t totext_filter_proc_key;
198
static isc_once_t once = ISC_ONCE_INIT;
200
static dns_name_totextfilter_t totext_filter_proc = NULL;
186
204
set_offsets(const dns_name_t *name, unsigned char *offsets,
187
205
dns_name_t *set_name);
385
403
return (ISC_FALSE);
407
dns_name_internalwildcard(const dns_name_t *name) {
408
unsigned char *ndata;
413
* Does 'name' contain a internal wildcard?
416
REQUIRE(VALID_NAME(name));
417
REQUIRE(name->labels > 0);
428
* Check all but the last of the remaining labels.
430
while (label + 1 < name->labels) {
433
if (count == 1 && *ndata == '*')
388
441
static inline unsigned int
389
442
name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
390
443
unsigned int length;
664
717
return (ISC_TRUE);
721
dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
724
* Are 'name1' and 'name2' equal?
726
* Note: It makes no sense for one of the names to be relative and the
727
* other absolute. If both names are relative, then to be meaningfully
728
* compared the caller must ensure that they are both relative to the
732
REQUIRE(VALID_NAME(name1));
733
REQUIRE(VALID_NAME(name2));
735
* Either name1 is absolute and name2 is absolute, or neither is.
737
REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
738
(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
740
if (name1->length != name2->length)
743
if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
668
750
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
669
751
unsigned int l1, l2, l, count1, count2, count;
837
919
target->ndata = &source->ndata[firstoffset];
838
920
target->length = endoffset - firstoffset;
840
922
if (first + n == source->labels && n > 0 &&
841
923
(source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
842
924
target->attributes |= DNS_NAMEATTR_ABSOLUTE;
967
1049
REQUIRE(ISC_BUFFER_VALID(source));
968
1050
REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
969
1051
(target == NULL && ISC_BUFFER_VALID(name->buffer)));
971
1053
downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
973
1055
if (target == NULL && name->buffer != NULL) {
1189
1271
return (ISC_R_SUCCESS);
1274
#ifdef ISC_PLATFORM_USETHREADS
1276
free_specific(void *arg) {
1277
dns_name_totextfilter_t *mem = arg;
1278
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1279
/* Stop use being called again. */
1280
(void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1284
thread_key_mutex_init(void) {
1285
RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1289
totext_filter_proc_key_init(void) {
1290
isc_result_t result;
1293
* We need the call to isc_once_do() to support profiled mutex
1294
* otherwise thread_key_mutex could be initialized at compile time.
1296
result = isc_once_do(&once, thread_key_mutex_init);
1297
if (result != ISC_R_SUCCESS)
1300
if (!thread_key_initialized) {
1301
LOCK(&thread_key_mutex);
1302
if (thread_key_mctx == NULL)
1303
result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1304
if (result != ISC_R_SUCCESS)
1306
isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1307
isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1309
if (!thread_key_initialized &&
1310
isc_thread_key_create(&totext_filter_proc_key,
1311
free_specific) != 0) {
1312
result = ISC_R_FAILURE;
1313
isc_mem_detach(&thread_key_mctx);
1315
thread_key_initialized = 1;
1317
UNLOCK(&thread_key_mutex);
1193
1324
dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1194
1325
isc_buffer_t *target)
1200
1331
unsigned int trem, count;
1201
1332
unsigned int labels;
1202
1333
isc_boolean_t saw_root = ISC_FALSE;
1334
unsigned int oused = target->used;
1335
#ifdef ISC_PLATFORM_USETHREADS
1336
dns_name_totextfilter_t *mem;
1337
dns_name_totextfilter_t totext_filter_proc = NULL;
1338
isc_result_t result;
1205
1342
* This function assumes the name is in proper uncompressed
1208
1345
REQUIRE(VALID_NAME(name));
1209
1346
REQUIRE(ISC_BUFFER_VALID(target));
1348
#ifdef ISC_PLATFORM_USETHREADS
1349
result = totext_filter_proc_key_init();
1350
if (result != ISC_R_SUCCESS)
1211
1353
ndata = name->ndata;
1212
1354
nlen = name->length;
1213
1355
labels = name->labels;
1340
1482
isc_buffer_add(target, tlen - trem);
1484
#ifdef ISC_PLATFORM_USETHREADS
1485
mem = isc_thread_key_getspecific(totext_filter_proc_key);
1487
totext_filter_proc = *mem;
1489
if (totext_filter_proc != NULL)
1490
return ((*totext_filter_proc)(target, oused, saw_root));
1342
1492
return (ISC_R_SUCCESS);
1574
1724
unsigned char *cdata, *ndata;
1575
1725
unsigned int cused; /* Bytes of compressed name data used */
1576
unsigned int hops, nused, labels, n, nmax;
1726
unsigned int nused, labels, n, nmax;
1577
1727
unsigned int current, new_current, biggest_pointer;
1578
1728
isc_boolean_t done;
1579
1729
fw_state state = fw_start;
1581
1731
unsigned char *offsets;
1582
1732
dns_offsets_t odata;
1583
1733
isc_boolean_t downcase;
1734
isc_boolean_t seen_pointer;
1586
1737
* Copy the possibly-compressed name at source into target,
1738
* decompressing it. Loop prevention is performed by checking
1739
* the new pointer against biggest_pointer.
1590
1742
REQUIRE(VALID_NAME(name));
1704
1856
return (DNS_R_BADPOINTER);
1705
1857
biggest_pointer = new_current;
1706
1858
current = new_current;
1707
cdata = (unsigned char *)source->base +
1710
if (hops > DNS_POINTER_MAXHOPS)
1711
return (DNS_R_TOOMANYHOPS);
1859
cdata = (unsigned char *)source->base + current;
1860
seen_pointer = ISC_TRUE;
1712
1861
state = fw_start;
1744
1893
* big enough buffer.
1746
1895
return (ISC_R_NOSPACE);
1751
dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
1899
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1900
isc_buffer_t *target)
1752
1902
unsigned int methods;
1753
1903
isc_uint16_t offset;
1754
1904
dns_name_t gp; /* Global compression prefix */
1782
1932
methods = dns_compress_getmethods(cctx);
1784
if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
1934
if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1935
(methods & DNS_COMPRESS_GLOBAL14) != 0)
1785
1936
gf = dns_compress_findglobal(cctx, name, &gp, &go);
1787
1938
gf = ISC_FALSE;
1965
dns_name_dup(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
2116
dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
1967
2120
* Make 'target' a dynamically allocated copy of 'source'.
2120
2273
return (ISC_R_SUCCESS);
2277
dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2278
#ifdef ISC_PLATFORM_USETHREADS
2279
isc_result_t result;
2280
dns_name_totextfilter_t *mem;
2283
result = totext_filter_proc_key_init();
2284
if (result != ISC_R_SUCCESS)
2288
* If we already have been here set / clear as appropriate.
2289
* Otherwise allocate memory.
2291
mem = isc_thread_key_getspecific(totext_filter_proc_key);
2292
if (mem != NULL && proc != NULL) {
2294
return (ISC_R_SUCCESS);
2297
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2298
res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2300
result = ISC_R_UNEXPECTED;
2304
mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2306
return (ISC_R_NOMEMORY);
2308
if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2309
isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2310
result = ISC_R_UNEXPECTED;
2314
totext_filter_proc = proc;
2315
return (ISC_R_SUCCESS);
2124
2320
dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2125
2321
isc_result_t result;
2194
2390
return (ISC_R_SUCCESS);
2394
dns_name_destroy(void) {
2395
#ifdef ISC_PLATFORM_USETHREADS
2396
RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2399
LOCK(&thread_key_mutex);
2400
if (thread_key_initialized) {
2401
isc_mem_detach(&thread_key_mctx);
2402
isc_thread_key_delete(totext_filter_proc_key);
2403
thread_key_initialized = 0;
2405
UNLOCK(&thread_key_mutex);