00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <ctype.h>
00025 #include <stdlib.h>
00026
00027 #include <isc/buffer.h>
00028 #include <isc/hash.h>
00029 #include <isc/mem.h>
00030 #include <isc/once.h>
00031 #include <isc/print.h>
00032 #include <isc/string.h>
00033 #include <isc/thread.h>
00034 #include <isc/util.h>
00035
00036 #include <dns/compress.h>
00037 #include <dns/fixedname.h>
00038 #include <dns/name.h>
00039 #include <dns/result.h>
00040
00041 #define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
00042
00043 typedef enum {
00044 ft_init = 0,
00045 ft_start,
00046 ft_ordinary,
00047 ft_initialescape,
00048 ft_escape,
00049 ft_escdecimal,
00050 ft_at
00051 } ft_state;
00052
00053 typedef enum {
00054 fw_start = 0,
00055 fw_ordinary,
00056 fw_newcurrent
00057 } fw_state;
00058
00059 static char digitvalue[256] = {
00060 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00061 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00062 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00063 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
00064 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00065 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00066 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00067 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00068 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00069 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00070 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00071 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00072 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00073 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00074 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00075 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
00076 };
00077
00078 static unsigned char maptolower[] = {
00079 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
00080 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
00081 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
00082 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
00083 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
00084 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
00085 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
00086 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
00087 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
00088 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
00089 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
00090 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
00091 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
00092 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
00093 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
00094 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
00095 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00096 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
00097 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
00098 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
00099 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
00100 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
00101 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
00102 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
00103 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
00104 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
00105 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
00106 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
00107 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
00108 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
00109 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
00110 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
00111 };
00112
00113 #define CONVERTTOASCII(c)
00114 #define CONVERTFROMASCII(c)
00115
00116 #define INIT_OFFSETS(name, var, default) \
00117 if (name->offsets != NULL) \
00118 var = name->offsets; \
00119 else \
00120 var = default;
00121
00122 #define SETUP_OFFSETS(name, var, default) \
00123 if (name->offsets != NULL) \
00124 var = name->offsets; \
00125 else { \
00126 var = default; \
00127 set_offsets(name, var, NULL); \
00128 }
00129
00130
00131
00132
00133
00134 #define MAKE_EMPTY(name) \
00135 do { \
00136 name->ndata = NULL; \
00137 name->length = 0; \
00138 name->labels = 0; \
00139 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
00140 } while (0);
00141
00142
00143
00144
00145
00146 #define BINDABLE(name) \
00147 ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
00148 == 0)
00149
00150
00151
00152
00153
00154
00155 static unsigned char root_ndata[] = { '\0' };
00156 static unsigned char root_offsets[] = { 0 };
00157
00158 static dns_name_t root =
00159 {
00160 DNS_NAME_MAGIC,
00161 root_ndata, 1, 1,
00162 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
00163 root_offsets, NULL,
00164 {(void *)-1, (void *)-1},
00165 {NULL, NULL}
00166 };
00167
00168
00169 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
00170
00171 static unsigned char wild_ndata[] = { '\001', '*' };
00172 static unsigned char wild_offsets[] = { 0 };
00173
00174 static dns_name_t wild =
00175 {
00176 DNS_NAME_MAGIC,
00177 wild_ndata, 2, 1,
00178 DNS_NAMEATTR_READONLY,
00179 wild_offsets, NULL,
00180 {(void *)-1, (void *)-1},
00181 {NULL, NULL}
00182 };
00183
00184
00185 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
00186
00187 unsigned int
00188 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
00189
00190
00191
00192
00193 #ifdef ISC_PLATFORM_USETHREADS
00194 static int thread_key_initialized = 0;
00195 static isc_mutex_t thread_key_mutex;
00196 static isc_mem_t *thread_key_mctx = NULL;
00197 static isc_thread_key_t totext_filter_proc_key;
00198 static isc_once_t once = ISC_ONCE_INIT;
00199 #else
00200 static dns_name_totextfilter_t totext_filter_proc = NULL;
00201 #endif
00202
00203 static void
00204 set_offsets(const dns_name_t *name, unsigned char *offsets,
00205 dns_name_t *set_name);
00206
00207 void
00208 dns_name_init(dns_name_t *name, unsigned char *offsets) {
00209
00210
00211
00212 DNS_NAME_INIT(name, offsets);
00213 }
00214
00215 void
00216 dns_name_reset(dns_name_t *name) {
00217 REQUIRE(VALID_NAME(name));
00218 REQUIRE(BINDABLE(name));
00219
00220 DNS_NAME_RESET(name);
00221 }
00222
00223 void
00224 dns_name_invalidate(dns_name_t *name) {
00225
00226
00227
00228
00229 REQUIRE(VALID_NAME(name));
00230
00231 name->magic = 0;
00232 name->ndata = NULL;
00233 name->length = 0;
00234 name->labels = 0;
00235 name->attributes = 0;
00236 name->offsets = NULL;
00237 name->buffer = NULL;
00238 ISC_LINK_INIT(name, link);
00239 }
00240
00241 isc_boolean_t
00242 dns_name_isvalid(const dns_name_t *name) {
00243 unsigned char *ndata, *offsets;
00244 unsigned int offset, count, length, nlabels;
00245
00246 if (!VALID_NAME(name))
00247 return (ISC_FALSE);
00248
00249 if (name->length > 255U || name->labels > 127U)
00250 return (ISC_FALSE);
00251
00252 ndata = name->ndata;
00253 length = name->length;
00254 offsets = name->offsets;
00255 offset = 0;
00256 nlabels = 0;
00257
00258 while (offset != length) {
00259 count = *ndata;
00260 if (count > 63U)
00261 return (ISC_FALSE);
00262 if (offsets != NULL && offsets[nlabels] != offset)
00263 return (ISC_FALSE);
00264
00265 nlabels++;
00266 offset += count + 1;
00267 ndata += count + 1;
00268 if (offset > length)
00269 return (ISC_FALSE);
00270
00271 if (count == 0)
00272 break;
00273 }
00274
00275 if (nlabels != name->labels || offset != name->length)
00276 return (ISC_FALSE);
00277
00278 return (ISC_TRUE);
00279 }
00280
00281 void
00282 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
00283
00284
00285
00286
00287 REQUIRE(VALID_NAME(name));
00288 REQUIRE((buffer != NULL && name->buffer == NULL) ||
00289 (buffer == NULL));
00290
00291 name->buffer = buffer;
00292 }
00293
00294 isc_boolean_t
00295 dns_name_hasbuffer(const dns_name_t *name) {
00296
00297
00298
00299
00300 REQUIRE(VALID_NAME(name));
00301
00302 if (name->buffer != NULL)
00303 return (ISC_TRUE);
00304
00305 return (ISC_FALSE);
00306 }
00307
00308 isc_boolean_t
00309 dns_name_isabsolute(const dns_name_t *name) {
00310
00311
00312
00313
00314
00315 REQUIRE(VALID_NAME(name));
00316
00317 if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
00318 return (ISC_TRUE);
00319 return (ISC_FALSE);
00320 }
00321
00322 #define hyphenchar(c) ((c) == 0x2d)
00323 #define asterchar(c) ((c) == 0x2a)
00324 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
00325 || ((c) >= 0x61 && (c) <= 0x7a))
00326 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
00327 #define borderchar(c) (alphachar(c) || digitchar(c))
00328 #define middlechar(c) (borderchar(c) || hyphenchar(c))
00329 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
00330
00331 isc_boolean_t
00332 dns_name_ismailbox(const dns_name_t *name) {
00333 unsigned char *ndata, ch;
00334 unsigned int n;
00335 isc_boolean_t first;
00336
00337 REQUIRE(VALID_NAME(name));
00338 REQUIRE(name->labels > 0);
00339 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
00340
00341
00342
00343
00344 if (name->length == 1)
00345 return (ISC_TRUE);
00346
00347 ndata = name->ndata;
00348 n = *ndata++;
00349 INSIST(n <= 63);
00350 while (n--) {
00351 ch = *ndata++;
00352 if (!domainchar(ch))
00353 return (ISC_FALSE);
00354 }
00355
00356 if (ndata == name->ndata + name->length)
00357 return (ISC_FALSE);
00358
00359
00360
00361
00362 while (ndata < (name->ndata + name->length)) {
00363 n = *ndata++;
00364 INSIST(n <= 63);
00365 first = ISC_TRUE;
00366 while (n--) {
00367 ch = *ndata++;
00368 if (first || n == 0) {
00369 if (!borderchar(ch))
00370 return (ISC_FALSE);
00371 } else {
00372 if (!middlechar(ch))
00373 return (ISC_FALSE);
00374 }
00375 first = ISC_FALSE;
00376 }
00377 }
00378 return (ISC_TRUE);
00379 }
00380
00381 isc_boolean_t
00382 dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
00383 unsigned char *ndata, ch;
00384 unsigned int n;
00385 isc_boolean_t first;
00386
00387 REQUIRE(VALID_NAME(name));
00388 REQUIRE(name->labels > 0);
00389 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
00390
00391
00392
00393
00394 if (name->length == 1)
00395 return (ISC_TRUE);
00396
00397
00398
00399
00400 ndata = name->ndata;
00401 if (wildcard && ndata[0] == 1 && ndata[1] == '*')
00402 ndata += 2;
00403
00404
00405
00406
00407 while (ndata < (name->ndata + name->length)) {
00408 n = *ndata++;
00409 INSIST(n <= 63);
00410 first = ISC_TRUE;
00411 while (n--) {
00412 ch = *ndata++;
00413 if (first || n == 0) {
00414 if (!borderchar(ch))
00415 return (ISC_FALSE);
00416 } else {
00417 if (!middlechar(ch))
00418 return (ISC_FALSE);
00419 }
00420 first = ISC_FALSE;
00421 }
00422 }
00423 return (ISC_TRUE);
00424 }
00425
00426 isc_boolean_t
00427 dns_name_iswildcard(const dns_name_t *name) {
00428 unsigned char *ndata;
00429
00430
00431
00432
00433
00434 REQUIRE(VALID_NAME(name));
00435 REQUIRE(name->labels > 0);
00436
00437 if (name->length >= 2) {
00438 ndata = name->ndata;
00439 if (ndata[0] == 1 && ndata[1] == '*')
00440 return (ISC_TRUE);
00441 }
00442
00443 return (ISC_FALSE);
00444 }
00445
00446 isc_boolean_t
00447 dns_name_internalwildcard(const dns_name_t *name) {
00448 unsigned char *ndata;
00449 unsigned int count;
00450 unsigned int label;
00451
00452
00453
00454
00455
00456 REQUIRE(VALID_NAME(name));
00457 REQUIRE(name->labels > 0);
00458
00459
00460
00461
00462 ndata = name->ndata;
00463 count = *ndata++;
00464 INSIST(count <= 63);
00465 ndata += count;
00466 label = 1;
00467
00468
00469
00470 while (label + 1 < name->labels) {
00471 count = *ndata++;
00472 INSIST(count <= 63);
00473 if (count == 1 && *ndata == '*')
00474 return (ISC_TRUE);
00475 ndata += count;
00476 label++;
00477 }
00478 return (ISC_FALSE);
00479 }
00480
00481 static inline unsigned int
00482 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
00483 unsigned int length;
00484 const unsigned char *s;
00485 unsigned int h = 0;
00486 unsigned char c;
00487
00488 length = name->length;
00489 if (length > 16)
00490 length = 16;
00491
00492
00493
00494
00495
00496 s = name->ndata;
00497 if (case_sensitive) {
00498 while (length > 0) {
00499 h += ( h << 3 ) + *s;
00500 s++;
00501 length--;
00502 }
00503 } else {
00504 while (length > 0) {
00505 c = maptolower[*s];
00506 h += ( h << 3 ) + c;
00507 s++;
00508 length--;
00509 }
00510 }
00511
00512 return (h);
00513 }
00514
00515 unsigned int
00516 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
00517
00518
00519
00520 REQUIRE(VALID_NAME(name));
00521
00522 if (name->labels == 0)
00523 return (0);
00524
00525 return (name_hash(name, case_sensitive));
00526 }
00527
00528 unsigned int
00529 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
00530
00531
00532
00533 REQUIRE(VALID_NAME(name));
00534
00535 if (name->labels == 0)
00536 return (0);
00537
00538 return (isc_hash_calc((const unsigned char *)name->ndata,
00539 name->length, case_sensitive));
00540 }
00541
00542 unsigned int
00543 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
00544
00545
00546
00547
00548
00549 REQUIRE(VALID_NAME(name));
00550
00551 return (dns_name_fullhash(name, case_sensitive));
00552 }
00553
00554 unsigned int
00555 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
00556 unsigned char *offsets;
00557 dns_offsets_t odata;
00558 dns_name_t tname;
00559 unsigned int h = 0;
00560 unsigned int i;
00561
00562
00563
00564
00565 REQUIRE(VALID_NAME(name));
00566
00567 if (name->labels == 0)
00568 return (0);
00569 else if (name->labels == 1)
00570 return (name_hash(name, case_sensitive));
00571
00572 SETUP_OFFSETS(name, offsets, odata);
00573 DNS_NAME_INIT(&tname, NULL);
00574 tname.labels = 1;
00575 h = 0;
00576 for (i = 0; i < name->labels; i++) {
00577 tname.ndata = name->ndata + offsets[i];
00578 if (i == name->labels - 1)
00579 tname.length = name->length - offsets[i];
00580 else
00581 tname.length = offsets[i + 1] - offsets[i];
00582 h += name_hash(&tname, case_sensitive);
00583 }
00584
00585 return (h);
00586 }
00587
00588 dns_namereln_t
00589 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
00590 int *orderp, unsigned int *nlabelsp)
00591 {
00592 unsigned int l1, l2, l, count1, count2, count, nlabels;
00593 int cdiff, ldiff, chdiff;
00594 unsigned char *label1, *label2;
00595 unsigned char *offsets1, *offsets2;
00596 dns_offsets_t odata1, odata2;
00597 dns_namereln_t namereln = dns_namereln_none;
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 REQUIRE(VALID_NAME(name1));
00611 REQUIRE(VALID_NAME(name2));
00612 REQUIRE(orderp != NULL);
00613 REQUIRE(nlabelsp != NULL);
00614
00615
00616
00617 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
00618 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
00619
00620 if (name1 == name2) {
00621 *orderp = 0;
00622 *nlabelsp = name1->labels;
00623 return (dns_namereln_equal);
00624 }
00625
00626 SETUP_OFFSETS(name1, offsets1, odata1);
00627 SETUP_OFFSETS(name2, offsets2, odata2);
00628
00629 nlabels = 0;
00630 l1 = name1->labels;
00631 l2 = name2->labels;
00632 if (l2 > l1) {
00633 l = l1;
00634 ldiff = 0 - (l2 - l1);
00635 } else {
00636 l = l2;
00637 ldiff = l1 - l2;
00638 }
00639
00640 while (l > 0) {
00641 l--;
00642 l1--;
00643 l2--;
00644 label1 = &name1->ndata[offsets1[l1]];
00645 label2 = &name2->ndata[offsets2[l2]];
00646 count1 = *label1++;
00647 count2 = *label2++;
00648
00649
00650
00651
00652
00653 INSIST(count1 <= 63 && count2 <= 63);
00654
00655 cdiff = (int)count1 - (int)count2;
00656 if (cdiff < 0)
00657 count = count1;
00658 else
00659 count = count2;
00660
00661 while (count > 0) {
00662 chdiff = (int)maptolower[*label1] -
00663 (int)maptolower[*label2];
00664 if (chdiff != 0) {
00665 *orderp = chdiff;
00666 goto done;
00667 }
00668 count--;
00669 label1++;
00670 label2++;
00671 }
00672 if (cdiff != 0) {
00673 *orderp = cdiff;
00674 goto done;
00675 }
00676 nlabels++;
00677 }
00678
00679 *orderp = ldiff;
00680 if (ldiff < 0)
00681 namereln = dns_namereln_contains;
00682 else if (ldiff > 0)
00683 namereln = dns_namereln_subdomain;
00684 else
00685 namereln = dns_namereln_equal;
00686
00687 done:
00688 *nlabelsp = nlabels;
00689
00690 if (nlabels > 0 && namereln == dns_namereln_none)
00691 namereln = dns_namereln_commonancestor;
00692
00693 return (namereln);
00694 }
00695
00696 int
00697 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
00698 int order;
00699 unsigned int nlabels;
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
00712
00713 return (order);
00714 }
00715
00716 isc_boolean_t
00717 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
00718 unsigned int l, count;
00719 unsigned char c;
00720 unsigned char *label1, *label2;
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 REQUIRE(VALID_NAME(name1));
00732 REQUIRE(VALID_NAME(name2));
00733
00734
00735
00736 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
00737 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
00738
00739 if (name1 == name2)
00740 return (ISC_TRUE);
00741
00742 if (name1->length != name2->length)
00743 return (ISC_FALSE);
00744
00745 l = name1->labels;
00746
00747 if (l != name2->labels)
00748 return (ISC_FALSE);
00749
00750 label1 = name1->ndata;
00751 label2 = name2->ndata;
00752 while (l > 0) {
00753 l--;
00754 count = *label1++;
00755 if (count != *label2++)
00756 return (ISC_FALSE);
00757
00758 INSIST(count <= 63);
00759
00760 while (count > 0) {
00761 count--;
00762 c = maptolower[*label1++];
00763 if (c != maptolower[*label2++])
00764 return (ISC_FALSE);
00765 }
00766 }
00767
00768 return (ISC_TRUE);
00769 }
00770
00771 isc_boolean_t
00772 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 REQUIRE(VALID_NAME(name1));
00784 REQUIRE(VALID_NAME(name2));
00785
00786
00787
00788 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
00789 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
00790
00791 if (name1->length != name2->length)
00792 return (ISC_FALSE);
00793
00794 if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
00795 return (ISC_FALSE);
00796
00797 return (ISC_TRUE);
00798 }
00799
00800 int
00801 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
00802 unsigned int l1, l2, l, count1, count2, count;
00803 unsigned char c1, c2;
00804 unsigned char *label1, *label2;
00805
00806
00807
00808
00809
00810 REQUIRE(VALID_NAME(name1));
00811 REQUIRE(name1->labels > 0);
00812 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
00813 REQUIRE(VALID_NAME(name2));
00814 REQUIRE(name2->labels > 0);
00815 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
00816
00817 l1 = name1->labels;
00818 l2 = name2->labels;
00819
00820 l = (l1 < l2) ? l1 : l2;
00821
00822 label1 = name1->ndata;
00823 label2 = name2->ndata;
00824 while (l > 0) {
00825 l--;
00826 count1 = *label1++;
00827 count2 = *label2++;
00828
00829
00830 INSIST(count1 <= 63 && count2 <= 63);
00831
00832 if (count1 != count2)
00833 return ((count1 < count2) ? -1 : 1);
00834 count = count1;
00835 while (count > 0) {
00836 count--;
00837 c1 = maptolower[*label1++];
00838 c2 = maptolower[*label2++];
00839 if (c1 < c2)
00840 return (-1);
00841 else if (c1 > c2)
00842 return (1);
00843 }
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853 INSIST(l1 == l2);
00854
00855 return (0);
00856 }
00857
00858 isc_boolean_t
00859 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
00860 int order;
00861 unsigned int nlabels;
00862 dns_namereln_t namereln;
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
00874 if (namereln == dns_namereln_subdomain ||
00875 namereln == dns_namereln_equal)
00876 return (ISC_TRUE);
00877
00878 return (ISC_FALSE);
00879 }
00880
00881 isc_boolean_t
00882 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
00883 int order;
00884 unsigned int nlabels, labels;
00885 dns_name_t tname;
00886
00887 REQUIRE(VALID_NAME(name));
00888 REQUIRE(name->labels > 0);
00889 REQUIRE(VALID_NAME(wname));
00890 labels = wname->labels;
00891 REQUIRE(labels > 0);
00892 REQUIRE(dns_name_iswildcard(wname));
00893
00894 #if defined(__clang__) && \
00895 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
00896 memset(&tname, 0, sizeof(tname));
00897 #endif
00898 DNS_NAME_INIT(&tname, NULL);
00899 dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
00900 if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
00901 dns_namereln_subdomain)
00902 return (ISC_TRUE);
00903 return (ISC_FALSE);
00904 }
00905
00906 unsigned int
00907 dns_name_countlabels(const dns_name_t *name) {
00908
00909
00910
00911
00912 REQUIRE(VALID_NAME(name));
00913
00914 ENSURE(name->labels <= 128);
00915
00916 return (name->labels);
00917 }
00918
00919 void
00920 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
00921 unsigned char *offsets;
00922 dns_offsets_t odata;
00923
00924
00925
00926
00927
00928 REQUIRE(VALID_NAME(name));
00929 REQUIRE(name->labels > 0);
00930 REQUIRE(n < name->labels);
00931 REQUIRE(label != NULL);
00932
00933 SETUP_OFFSETS(name, offsets, odata);
00934
00935 label->base = &name->ndata[offsets[n]];
00936 if (n == name->labels - 1)
00937 label->length = name->length - offsets[n];
00938 else
00939 label->length = offsets[n + 1] - offsets[n];
00940 }
00941
00942 void
00943 dns_name_getlabelsequence(const dns_name_t *source,
00944 unsigned int first, unsigned int n,
00945 dns_name_t *target)
00946 {
00947 unsigned char *offsets;
00948 dns_offsets_t odata;
00949 unsigned int firstoffset, endoffset;
00950
00951
00952
00953
00954
00955
00956 REQUIRE(VALID_NAME(source));
00957 REQUIRE(VALID_NAME(target));
00958 REQUIRE(first <= source->labels);
00959 REQUIRE(n <= source->labels - first);
00960 REQUIRE(BINDABLE(target));
00961
00962 SETUP_OFFSETS(source, offsets, odata);
00963
00964 if (first == source->labels)
00965 firstoffset = source->length;
00966 else
00967 firstoffset = offsets[first];
00968
00969 if (first + n == source->labels)
00970 endoffset = source->length;
00971 else
00972 endoffset = offsets[first + n];
00973
00974 target->ndata = &source->ndata[firstoffset];
00975 target->length = endoffset - firstoffset;
00976
00977 if (first + n == source->labels && n > 0 &&
00978 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
00979 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
00980 else
00981 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
00982
00983 target->labels = n;
00984
00985
00986
00987
00988
00989
00990 if (target->offsets != NULL &&
00991 (target != source || first != 0))
00992 set_offsets(target, target->offsets, NULL);
00993 }
00994
00995 void
00996 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
00997
00998
00999
01000
01001
01002 REQUIRE(VALID_NAME(source));
01003 REQUIRE(VALID_NAME(target));
01004 REQUIRE(BINDABLE(target));
01005
01006 target->ndata = source->ndata;
01007 target->length = source->length;
01008 target->labels = source->labels;
01009 target->attributes = source->attributes &
01010 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
01011 DNS_NAMEATTR_DYNOFFSETS);
01012 if (target->offsets != NULL && source->labels > 0) {
01013 if (source->offsets != NULL)
01014 memmove(target->offsets, source->offsets,
01015 source->labels);
01016 else
01017 set_offsets(target, target->offsets, NULL);
01018 }
01019 }
01020
01021 void
01022 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
01023 unsigned char *offsets;
01024 dns_offsets_t odata;
01025 unsigned int len;
01026 isc_region_t r2;
01027
01028
01029
01030
01031
01032 REQUIRE(VALID_NAME(name));
01033 REQUIRE(r != NULL);
01034 REQUIRE(BINDABLE(name));
01035
01036 INIT_OFFSETS(name, offsets, odata);
01037
01038 if (name->buffer != NULL) {
01039 isc_buffer_clear(name->buffer);
01040 isc_buffer_availableregion(name->buffer, &r2);
01041 len = (r->length < r2.length) ? r->length : r2.length;
01042 if (len > DNS_NAME_MAXWIRE)
01043 len = DNS_NAME_MAXWIRE;
01044 memmove(r2.base, r->base, len);
01045 name->ndata = r2.base;
01046 name->length = len;
01047 } else {
01048 name->ndata = r->base;
01049 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
01050 r->length : DNS_NAME_MAXWIRE;
01051 }
01052
01053 if (r->length > 0)
01054 set_offsets(name, offsets, name);
01055 else {
01056 name->labels = 0;
01057 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
01058 }
01059
01060 if (name->buffer != NULL)
01061 isc_buffer_add(name->buffer, name->length);
01062 }
01063
01064 void
01065 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
01066
01067
01068
01069
01070 REQUIRE(VALID_NAME(name));
01071 REQUIRE(r != NULL);
01072
01073 DNS_NAME_TOREGION(name, r);
01074 }
01075
01076 isc_result_t
01077 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
01078 const dns_name_t *origin, unsigned int options,
01079 isc_buffer_t *target)
01080 {
01081 unsigned char *ndata, *label = NULL;
01082 char *tdata;
01083 char c;
01084 ft_state state;
01085 unsigned int value = 0, count = 0;
01086 unsigned int n1 = 0, n2 = 0;
01087 unsigned int tlen, nrem, nused, digits = 0, labels, tused;
01088 isc_boolean_t done;
01089 unsigned char *offsets;
01090 dns_offsets_t odata;
01091 isc_boolean_t downcase;
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 REQUIRE(VALID_NAME(name));
01104 REQUIRE(ISC_BUFFER_VALID(source));
01105 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
01106 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
01107
01108 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
01109
01110 if (target == NULL && name->buffer != NULL) {
01111 target = name->buffer;
01112 isc_buffer_clear(target);
01113 }
01114
01115 REQUIRE(BINDABLE(name));
01116
01117 INIT_OFFSETS(name, offsets, odata);
01118 offsets[0] = 0;
01119
01120
01121
01122
01123 MAKE_EMPTY(name);
01124
01125
01126
01127
01128 tdata = (char *)source->base + source->current;
01129 tlen = isc_buffer_remaininglength(source);
01130 tused = 0;
01131 ndata = isc_buffer_used(target);
01132 nrem = isc_buffer_availablelength(target);
01133 if (nrem > 255)
01134 nrem = 255;
01135 nused = 0;
01136 labels = 0;
01137 done = ISC_FALSE;
01138 state = ft_init;
01139
01140 while (nrem > 0 && tlen > 0 && !done) {
01141 c = *tdata++;
01142 tlen--;
01143 tused++;
01144
01145 switch (state) {
01146 case ft_init:
01147
01148
01149
01150 if (c == '.') {
01151 if (tlen != 0)
01152 return (DNS_R_EMPTYLABEL);
01153 labels++;
01154 *ndata++ = 0;
01155 nrem--;
01156 nused++;
01157 done = ISC_TRUE;
01158 break;
01159 }
01160 if (c == '@' && tlen == 0) {
01161 state = ft_at;
01162 break;
01163 }
01164
01165
01166 case ft_start:
01167 label = ndata;
01168 ndata++;
01169 nrem--;
01170 nused++;
01171 count = 0;
01172 if (c == '\\') {
01173 state = ft_initialescape;
01174 break;
01175 }
01176 state = ft_ordinary;
01177 if (nrem == 0)
01178 return (ISC_R_NOSPACE);
01179
01180 case ft_ordinary:
01181 if (c == '.') {
01182 if (count == 0)
01183 return (DNS_R_EMPTYLABEL);
01184 *label = count;
01185 labels++;
01186 INSIST(labels <= 127);
01187 offsets[labels] = nused;
01188 if (tlen == 0) {
01189 labels++;
01190 *ndata++ = 0;
01191 nrem--;
01192 nused++;
01193 done = ISC_TRUE;
01194 }
01195 state = ft_start;
01196 } else if (c == '\\') {
01197 state = ft_escape;
01198 } else {
01199 if (count >= 63)
01200 return (DNS_R_LABELTOOLONG);
01201 count++;
01202 CONVERTTOASCII(c);
01203 if (downcase)
01204 c = maptolower[c & 0xff];
01205 *ndata++ = c;
01206 nrem--;
01207 nused++;
01208 }
01209 break;
01210 case ft_initialescape:
01211 if (c == '[') {
01212
01213
01214
01215
01216 return (DNS_R_BADLABELTYPE);
01217 }
01218 state = ft_escape;
01219 POST(state);
01220
01221 case ft_escape:
01222 if (!isdigit(c & 0xff)) {
01223 if (count >= 63)
01224 return (DNS_R_LABELTOOLONG);
01225 count++;
01226 CONVERTTOASCII(c);
01227 if (downcase)
01228 c = maptolower[c & 0xff];
01229 *ndata++ = c;
01230 nrem--;
01231 nused++;
01232 state = ft_ordinary;
01233 break;
01234 }
01235 digits = 0;
01236 value = 0;
01237 state = ft_escdecimal;
01238
01239 case ft_escdecimal:
01240 if (!isdigit(c & 0xff))
01241 return (DNS_R_BADESCAPE);
01242 value *= 10;
01243 value += digitvalue[c & 0xff];
01244 digits++;
01245 if (digits == 3) {
01246 if (value > 255)
01247 return (DNS_R_BADESCAPE);
01248 if (count >= 63)
01249 return (DNS_R_LABELTOOLONG);
01250 count++;
01251 if (downcase)
01252 value = maptolower[value];
01253 *ndata++ = value;
01254 nrem--;
01255 nused++;
01256 state = ft_ordinary;
01257 }
01258 break;
01259 default:
01260 FATAL_ERROR(__FILE__, __LINE__,
01261 "Unexpected state %d", state);
01262
01263 }
01264 }
01265
01266 if (!done) {
01267 if (nrem == 0)
01268 return (ISC_R_NOSPACE);
01269 INSIST(tlen == 0);
01270 if (state != ft_ordinary && state != ft_at)
01271 return (ISC_R_UNEXPECTEDEND);
01272 if (state == ft_ordinary) {
01273 INSIST(count != 0);
01274 *label = count;
01275 labels++;
01276 INSIST(labels <= 127);
01277 offsets[labels] = nused;
01278 }
01279 if (origin != NULL) {
01280 if (nrem < origin->length)
01281 return (ISC_R_NOSPACE);
01282 label = origin->ndata;
01283 n1 = origin->length;
01284 nrem -= n1;
01285 POST(nrem);
01286 while (n1 > 0) {
01287 n2 = *label++;
01288 INSIST(n2 <= 63);
01289 *ndata++ = n2;
01290 n1 -= n2 + 1;
01291 nused += n2 + 1;
01292 while (n2 > 0) {
01293 c = *label++;
01294 if (downcase)
01295 c = maptolower[c & 0xff];
01296 *ndata++ = c;
01297 n2--;
01298 }
01299 labels++;
01300 if (n1 > 0) {
01301 INSIST(labels <= 127);
01302 offsets[labels] = nused;
01303 }
01304 }
01305 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
01306 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
01307 }
01308 } else
01309 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
01310
01311 name->ndata = (unsigned char *)target->base + target->used;
01312 name->labels = labels;
01313 name->length = nused;
01314
01315 isc_buffer_forward(source, tused);
01316 isc_buffer_add(target, name->length);
01317
01318 return (ISC_R_SUCCESS);
01319 }
01320
01321 #ifdef ISC_PLATFORM_USETHREADS
01322 static void
01323 free_specific(void *arg) {
01324 dns_name_totextfilter_t *mem = arg;
01325 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
01326
01327 (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
01328 }
01329
01330 static void
01331 thread_key_mutex_init(void) {
01332 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
01333 }
01334
01335 static isc_result_t
01336 totext_filter_proc_key_init(void) {
01337 isc_result_t result;
01338
01339
01340
01341
01342
01343 result = isc_once_do(&once, thread_key_mutex_init);
01344 if (result != ISC_R_SUCCESS)
01345 return (result);
01346
01347 if (!thread_key_initialized) {
01348 LOCK(&thread_key_mutex);
01349 if (thread_key_mctx == NULL)
01350 result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
01351 if (result != ISC_R_SUCCESS)
01352 goto unlock;
01353 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
01354 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
01355
01356 if (!thread_key_initialized &&
01357 isc_thread_key_create(&totext_filter_proc_key,
01358 free_specific) != 0) {
01359 result = ISC_R_FAILURE;
01360 isc_mem_detach(&thread_key_mctx);
01361 } else
01362 thread_key_initialized = 1;
01363 unlock:
01364 UNLOCK(&thread_key_mutex);
01365 }
01366 return (result);
01367 }
01368 #endif
01369
01370 isc_result_t
01371 dns_name_totext(const dns_name_t *name, isc_boolean_t omit_final_dot,
01372 isc_buffer_t *target)
01373 {
01374 unsigned int options = DNS_NAME_MASTERFILE;
01375
01376 if (omit_final_dot)
01377 options |= DNS_NAME_OMITFINALDOT;
01378 return (dns_name_totext2(name, options, target));
01379 }
01380
01381 isc_result_t
01382 dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) {
01383 return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
01384 }
01385
01386 isc_result_t
01387 dns_name_totext2(const dns_name_t *name, unsigned int options,
01388 isc_buffer_t *target)
01389 {
01390 unsigned char *ndata;
01391 char *tdata;
01392 unsigned int nlen, tlen;
01393 unsigned char c;
01394 unsigned int trem, count;
01395 unsigned int labels;
01396 isc_boolean_t saw_root = ISC_FALSE;
01397 unsigned int oused = target->used;
01398 #ifdef ISC_PLATFORM_USETHREADS
01399 dns_name_totextfilter_t *mem;
01400 dns_name_totextfilter_t totext_filter_proc = NULL;
01401 isc_result_t result;
01402 #endif
01403 isc_boolean_t omit_final_dot =
01404 ISC_TF(options & DNS_NAME_OMITFINALDOT);
01405
01406
01407
01408
01409
01410 REQUIRE(VALID_NAME(name));
01411 REQUIRE(ISC_BUFFER_VALID(target));
01412
01413 #ifdef ISC_PLATFORM_USETHREADS
01414 result = totext_filter_proc_key_init();
01415 if (result != ISC_R_SUCCESS)
01416 return (result);
01417 #endif
01418 ndata = name->ndata;
01419 nlen = name->length;
01420 labels = name->labels;
01421 tdata = isc_buffer_used(target);
01422 tlen = isc_buffer_availablelength(target);
01423
01424 trem = tlen;
01425
01426 if (labels == 0 && nlen == 0) {
01427
01428
01429
01430 if (trem == 0)
01431 return (ISC_R_NOSPACE);
01432
01433
01434
01435
01436
01437
01438
01439
01440 saw_root = ISC_TRUE;
01441 omit_final_dot = ISC_FALSE;
01442 *tdata++ = '@';
01443 trem--;
01444
01445
01446
01447
01448 nlen = 0;
01449 } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
01450
01451
01452
01453 if (trem == 0)
01454 return (ISC_R_NOSPACE);
01455
01456 saw_root = ISC_TRUE;
01457 omit_final_dot = ISC_FALSE;
01458 *tdata++ = '.';
01459 trem--;
01460
01461
01462
01463
01464 nlen = 0;
01465 }
01466
01467 while (labels > 0 && nlen > 0 && trem > 0) {
01468 labels--;
01469 count = *ndata++;
01470 nlen--;
01471 if (count == 0) {
01472 saw_root = ISC_TRUE;
01473 break;
01474 }
01475 if (count < 64) {
01476 INSIST(nlen >= count);
01477 while (count > 0) {
01478 c = *ndata;
01479 switch (c) {
01480
01481 case 0x40:
01482 case 0x24:
01483 if ((options & DNS_NAME_MASTERFILE) == 0)
01484 goto no_escape;
01485
01486 case 0x22:
01487 case 0x28:
01488 case 0x29:
01489 case 0x2E:
01490 case 0x3B:
01491 case 0x5C:
01492 if (trem < 2)
01493 return (ISC_R_NOSPACE);
01494 *tdata++ = '\\';
01495 CONVERTFROMASCII(c);
01496 *tdata++ = c;
01497 ndata++;
01498 trem -= 2;
01499 nlen--;
01500 break;
01501 no_escape:
01502 default:
01503 if (c > 0x20 && c < 0x7f) {
01504 if (trem == 0)
01505 return (ISC_R_NOSPACE);
01506 CONVERTFROMASCII(c);
01507 *tdata++ = c;
01508 ndata++;
01509 trem--;
01510 nlen--;
01511 } else {
01512 if (trem < 4)
01513 return (ISC_R_NOSPACE);
01514 *tdata++ = 0x5c;
01515 *tdata++ = 0x30 +
01516 ((c / 100) % 10);
01517 *tdata++ = 0x30 +
01518 ((c / 10) % 10);
01519 *tdata++ = 0x30 + (c % 10);
01520 trem -= 4;
01521 ndata++;
01522 nlen--;
01523 }
01524 }
01525 count--;
01526 }
01527 } else {
01528 FATAL_ERROR(__FILE__, __LINE__,
01529 "Unexpected label type %02x", count);
01530
01531 }
01532
01533
01534
01535
01536
01537
01538
01539 if (trem == 0)
01540 return (ISC_R_NOSPACE);
01541 *tdata++ = '.';
01542 trem--;
01543 }
01544
01545 if (nlen != 0 && trem == 0)
01546 return (ISC_R_NOSPACE);
01547
01548 if (!saw_root || omit_final_dot)
01549 trem++;
01550
01551 isc_buffer_add(target, tlen - trem);
01552
01553 #ifdef ISC_PLATFORM_USETHREADS
01554 mem = isc_thread_key_getspecific(totext_filter_proc_key);
01555 if (mem != NULL)
01556 totext_filter_proc = *mem;
01557 #endif
01558 if (totext_filter_proc != NULL)
01559 return ((*totext_filter_proc)(target, oused, saw_root));
01560
01561 return (ISC_R_SUCCESS);
01562 }
01563
01564 isc_result_t
01565 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
01566 isc_buffer_t *target)
01567 {
01568 unsigned char *ndata;
01569 char *tdata;
01570 unsigned int nlen, tlen;
01571 unsigned char c;
01572 unsigned int trem, count;
01573 unsigned int labels;
01574
01575
01576
01577
01578
01579 REQUIRE(VALID_NAME(name));
01580 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
01581 REQUIRE(ISC_BUFFER_VALID(target));
01582
01583 ndata = name->ndata;
01584 nlen = name->length;
01585 labels = name->labels;
01586 tdata = isc_buffer_used(target);
01587 tlen = isc_buffer_availablelength(target);
01588
01589 trem = tlen;
01590
01591 if (nlen == 1 && labels == 1 && *ndata == '\0') {
01592
01593
01594
01595 if (trem == 0)
01596 return (ISC_R_NOSPACE);
01597
01598 omit_final_dot = ISC_FALSE;
01599 *tdata++ = '.';
01600 trem--;
01601
01602
01603
01604
01605 nlen = 0;
01606 }
01607
01608 while (labels > 0 && nlen > 0 && trem > 0) {
01609 labels--;
01610 count = *ndata++;
01611 nlen--;
01612 if (count == 0)
01613 break;
01614 if (count < 64) {
01615 INSIST(nlen >= count);
01616 while (count > 0) {
01617 c = *ndata;
01618 if ((c >= 0x30 && c <= 0x39) ||
01619 (c >= 0x41 && c <= 0x5A) ||
01620 (c >= 0x61 && c <= 0x7A) ||
01621 c == 0x2D ||
01622 c == 0x5F)
01623 {
01624 if (trem == 0)
01625 return (ISC_R_NOSPACE);
01626
01627 if (c >= 0x41 && c <= 0x5A)
01628 c += 0x20;
01629 CONVERTFROMASCII(c);
01630 *tdata++ = c;
01631 ndata++;
01632 trem--;
01633 nlen--;
01634 } else {
01635 if (trem < 3)
01636 return (ISC_R_NOSPACE);
01637 sprintf(tdata, "%%%02X", c);
01638 tdata += 3;
01639 trem -= 3;
01640 ndata++;
01641 nlen--;
01642 }
01643 count--;
01644 }
01645 } else {
01646 FATAL_ERROR(__FILE__, __LINE__,
01647 "Unexpected label type %02x", count);
01648
01649 }
01650
01651
01652
01653
01654
01655
01656
01657 if (trem == 0)
01658 return (ISC_R_NOSPACE);
01659 *tdata++ = '.';
01660 trem--;
01661 }
01662
01663 if (nlen != 0 && trem == 0)
01664 return (ISC_R_NOSPACE);
01665
01666 if (omit_final_dot)
01667 trem++;
01668
01669 isc_buffer_add(target, tlen - trem);
01670
01671 return (ISC_R_SUCCESS);
01672 }
01673
01674 isc_result_t
01675 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
01676 unsigned char *sndata, *ndata;
01677 unsigned int nlen, count, labels;
01678 isc_buffer_t buffer;
01679
01680
01681
01682
01683
01684 REQUIRE(VALID_NAME(source));
01685 REQUIRE(VALID_NAME(name));
01686 if (source == name) {
01687 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
01688 isc_buffer_init(&buffer, source->ndata, source->length);
01689 target = &buffer;
01690 ndata = source->ndata;
01691 } else {
01692 REQUIRE(BINDABLE(name));
01693 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
01694 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
01695 if (target == NULL) {
01696 target = name->buffer;
01697 isc_buffer_clear(name->buffer);
01698 }
01699 ndata = (unsigned char *)target->base + target->used;
01700 name->ndata = ndata;
01701 }
01702
01703 sndata = source->ndata;
01704 nlen = source->length;
01705 labels = source->labels;
01706
01707 if (nlen > (target->length - target->used)) {
01708 MAKE_EMPTY(name);
01709 return (ISC_R_NOSPACE);
01710 }
01711
01712 while (labels > 0 && nlen > 0) {
01713 labels--;
01714 count = *sndata++;
01715 *ndata++ = count;
01716 nlen--;
01717 if (count < 64) {
01718 INSIST(nlen >= count);
01719 while (count > 0) {
01720 *ndata++ = maptolower[(*sndata++)];
01721 nlen--;
01722 count--;
01723 }
01724 } else {
01725 FATAL_ERROR(__FILE__, __LINE__,
01726 "Unexpected label type %02x", count);
01727
01728 }
01729 }
01730
01731 if (source != name) {
01732 name->labels = source->labels;
01733 name->length = source->length;
01734 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
01735 name->attributes = DNS_NAMEATTR_ABSOLUTE;
01736 else
01737 name->attributes = 0;
01738 if (name->labels > 0 && name->offsets != NULL)
01739 set_offsets(name, name->offsets, NULL);
01740 }
01741
01742 isc_buffer_add(target, name->length);
01743
01744 return (ISC_R_SUCCESS);
01745 }
01746
01747 static void
01748 set_offsets(const dns_name_t *name, unsigned char *offsets,
01749 dns_name_t *set_name)
01750 {
01751 unsigned int offset, count, length, nlabels;
01752 unsigned char *ndata;
01753 isc_boolean_t absolute;
01754
01755 ndata = name->ndata;
01756 length = name->length;
01757 offset = 0;
01758 nlabels = 0;
01759 absolute = ISC_FALSE;
01760 while (offset != length) {
01761 INSIST(nlabels < 128);
01762 offsets[nlabels++] = offset;
01763 count = *ndata++;
01764 offset++;
01765 INSIST(count <= 63);
01766 offset += count;
01767 ndata += count;
01768 INSIST(offset <= length);
01769 if (count == 0) {
01770 absolute = ISC_TRUE;
01771 break;
01772 }
01773 }
01774 if (set_name != NULL) {
01775 INSIST(set_name == name);
01776
01777 set_name->labels = nlabels;
01778 set_name->length = offset;
01779 if (absolute)
01780 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
01781 else
01782 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
01783 }
01784 INSIST(nlabels == name->labels);
01785 INSIST(offset == name->length);
01786 }
01787
01788 isc_result_t
01789 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
01790 dns_decompress_t *dctx, unsigned int options,
01791 isc_buffer_t *target)
01792 {
01793 unsigned char *cdata, *ndata;
01794 unsigned int cused;
01795 unsigned int nused, labels, n, nmax;
01796 unsigned int current, new_current, biggest_pointer;
01797 isc_boolean_t done;
01798 fw_state state = fw_start;
01799 unsigned int c;
01800 unsigned char *offsets;
01801 dns_offsets_t odata;
01802 isc_boolean_t downcase;
01803 isc_boolean_t seen_pointer;
01804
01805
01806
01807
01808
01809
01810
01811 REQUIRE(VALID_NAME(name));
01812 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
01813 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
01814
01815 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
01816
01817 if (target == NULL && name->buffer != NULL) {
01818 target = name->buffer;
01819 isc_buffer_clear(target);
01820 }
01821
01822 REQUIRE(dctx != NULL);
01823 REQUIRE(BINDABLE(name));
01824
01825 INIT_OFFSETS(name, offsets, odata);
01826
01827
01828
01829
01830 MAKE_EMPTY(name);
01831
01832
01833
01834
01835 n = 0;
01836 new_current = 0;
01837
01838
01839
01840
01841 labels = 0;
01842 done = ISC_FALSE;
01843
01844 ndata = isc_buffer_used(target);
01845 nused = 0;
01846 seen_pointer = ISC_FALSE;
01847
01848
01849
01850
01851
01852
01853
01854 nmax = isc_buffer_availablelength(target);
01855 if (nmax > DNS_NAME_MAXWIRE)
01856 nmax = DNS_NAME_MAXWIRE;
01857
01858 cdata = isc_buffer_current(source);
01859 cused = 0;
01860
01861 current = source->current;
01862 biggest_pointer = current;
01863
01864
01865
01866
01867
01868
01869 while (current < source->active && !done) {
01870 c = *cdata++;
01871 current++;
01872 if (!seen_pointer)
01873 cused++;
01874
01875 switch (state) {
01876 case fw_start:
01877 if (c < 64) {
01878 offsets[labels] = nused;
01879 labels++;
01880 if (nused + c + 1 > nmax)
01881 goto full;
01882 nused += c + 1;
01883 *ndata++ = c;
01884 if (c == 0)
01885 done = ISC_TRUE;
01886 n = c;
01887 state = fw_ordinary;
01888 } else if (c >= 128 && c < 192) {
01889
01890
01891
01892
01893
01894 return (DNS_R_BADLABELTYPE);
01895 } else if (c >= 192) {
01896
01897
01898
01899 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
01900 0)
01901 return (DNS_R_DISALLOWED);
01902 new_current = c & 0x3F;
01903 state = fw_newcurrent;
01904 } else
01905 return (DNS_R_BADLABELTYPE);
01906 break;
01907 case fw_ordinary:
01908 if (downcase)
01909 c = maptolower[c];
01910 *ndata++ = c;
01911 n--;
01912 if (n == 0)
01913 state = fw_start;
01914 break;
01915 case fw_newcurrent:
01916 new_current *= 256;
01917 new_current += c;
01918 if (new_current >= biggest_pointer)
01919 return (DNS_R_BADPOINTER);
01920 biggest_pointer = new_current;
01921 current = new_current;
01922 cdata = (unsigned char *)source->base + current;
01923 seen_pointer = ISC_TRUE;
01924 state = fw_start;
01925 break;
01926 default:
01927 FATAL_ERROR(__FILE__, __LINE__,
01928 "Unknown state %d", state);
01929
01930 }
01931 }
01932
01933 if (!done)
01934 return (ISC_R_UNEXPECTEDEND);
01935
01936 name->ndata = (unsigned char *)target->base + target->used;
01937 name->labels = labels;
01938 name->length = nused;
01939 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
01940
01941 isc_buffer_forward(source, cused);
01942 isc_buffer_add(target, name->length);
01943
01944 return (ISC_R_SUCCESS);
01945
01946 full:
01947 if (nmax == DNS_NAME_MAXWIRE)
01948
01949
01950
01951
01952 return (DNS_R_NAMETOOLONG);
01953 else
01954
01955
01956
01957
01958 return (ISC_R_NOSPACE);
01959 }
01960
01961 isc_result_t
01962 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
01963 isc_buffer_t *target)
01964 {
01965 unsigned int methods;
01966 isc_uint16_t offset;
01967 dns_name_t gp;
01968 isc_boolean_t gf;
01969 isc_uint16_t go;
01970 dns_offsets_t clo;
01971 dns_name_t clname;
01972
01973
01974
01975
01976
01977
01978 REQUIRE(VALID_NAME(name));
01979 REQUIRE(cctx != NULL);
01980 REQUIRE(ISC_BUFFER_VALID(target));
01981
01982
01983
01984
01985
01986 if (name->offsets == NULL) {
01987 #if defined(__clang__) && \
01988 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
01989 memset(&clname, 0, sizeof(clname));
01990 #endif
01991 DNS_NAME_INIT(&clname, clo);
01992 dns_name_clone(name, &clname);
01993 name = &clname;
01994 }
01995 DNS_NAME_INIT(&gp, NULL);
01996
01997 offset = target->used;
01998
01999 methods = dns_compress_getmethods(cctx);
02000
02001 if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
02002 (methods & DNS_COMPRESS_GLOBAL14) != 0)
02003 gf = dns_compress_findglobal(cctx, name, &gp, &go);
02004 else
02005 gf = ISC_FALSE;
02006
02007
02008
02009
02010
02011 if (gf && go >= 0x4000)
02012 gf = ISC_FALSE;
02013
02014
02015
02016
02017 if (gf && (gp.length + 2) >= name->length)
02018 gf = ISC_FALSE;
02019
02020 if (gf) {
02021 if (target->length - target->used < gp.length)
02022 return (ISC_R_NOSPACE);
02023 (void)memmove((unsigned char *)target->base + target->used,
02024 gp.ndata, (size_t)gp.length);
02025 isc_buffer_add(target, gp.length);
02026 go |= 0xc000;
02027 if (target->length - target->used < 2)
02028 return (ISC_R_NOSPACE);
02029 isc_buffer_putuint16(target, go);
02030 if (gp.length != 0)
02031 dns_compress_add(cctx, name, &gp, offset);
02032 } else {
02033 if (target->length - target->used < name->length)
02034 return (ISC_R_NOSPACE);
02035 (void)memmove((unsigned char *)target->base + target->used,
02036 name->ndata, (size_t)name->length);
02037 isc_buffer_add(target, name->length);
02038 dns_compress_add(cctx, name, name, offset);
02039 }
02040 return (ISC_R_SUCCESS);
02041 }
02042
02043 isc_result_t
02044 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
02045 isc_buffer_t *target)
02046 {
02047 unsigned char *ndata, *offsets;
02048 unsigned int nrem, labels, prefix_length, length;
02049 isc_boolean_t copy_prefix = ISC_TRUE;
02050 isc_boolean_t copy_suffix = ISC_TRUE;
02051 isc_boolean_t absolute = ISC_FALSE;
02052 dns_name_t tmp_name;
02053 dns_offsets_t odata;
02054
02055
02056
02057
02058
02059 REQUIRE(prefix == NULL || VALID_NAME(prefix));
02060 REQUIRE(suffix == NULL || VALID_NAME(suffix));
02061 REQUIRE(name == NULL || VALID_NAME(name));
02062 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
02063 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
02064 if (prefix == NULL || prefix->labels == 0)
02065 copy_prefix = ISC_FALSE;
02066 if (suffix == NULL || suffix->labels == 0)
02067 copy_suffix = ISC_FALSE;
02068 if (copy_prefix &&
02069 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
02070 absolute = ISC_TRUE;
02071 REQUIRE(!copy_suffix);
02072 }
02073 if (name == NULL) {
02074 DNS_NAME_INIT(&tmp_name, odata);
02075 name = &tmp_name;
02076 }
02077 if (target == NULL) {
02078 INSIST(name->buffer != NULL);
02079 target = name->buffer;
02080 isc_buffer_clear(name->buffer);
02081 }
02082
02083 REQUIRE(BINDABLE(name));
02084
02085
02086
02087
02088 nrem = target->length - target->used;
02089 ndata = (unsigned char *)target->base + target->used;
02090 if (nrem > DNS_NAME_MAXWIRE)
02091 nrem = DNS_NAME_MAXWIRE;
02092 length = 0;
02093 prefix_length = 0;
02094 labels = 0;
02095 if (copy_prefix) {
02096 prefix_length = prefix->length;
02097 length += prefix_length;
02098 labels += prefix->labels;
02099 }
02100 if (copy_suffix) {
02101 length += suffix->length;
02102 labels += suffix->labels;
02103 }
02104 if (length > DNS_NAME_MAXWIRE) {
02105 MAKE_EMPTY(name);
02106 return (DNS_R_NAMETOOLONG);
02107 }
02108 if (length > nrem) {
02109 MAKE_EMPTY(name);
02110 return (ISC_R_NOSPACE);
02111 }
02112
02113 if (copy_suffix) {
02114 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
02115 absolute = ISC_TRUE;
02116 memmove(ndata + prefix_length, suffix->ndata, suffix->length);
02117 }
02118
02119
02120
02121
02122
02123
02124 if (copy_prefix && (prefix != name || prefix->buffer != target))
02125 memmove(ndata, prefix->ndata, prefix_length);
02126
02127 name->ndata = ndata;
02128 name->labels = labels;
02129 name->length = length;
02130 if (absolute)
02131 name->attributes = DNS_NAMEATTR_ABSOLUTE;
02132 else
02133 name->attributes = 0;
02134
02135 if (name->labels > 0 && name->offsets != NULL) {
02136 INIT_OFFSETS(name, offsets, odata);
02137 set_offsets(name, offsets, NULL);
02138 }
02139
02140 isc_buffer_add(target, name->length);
02141
02142 return (ISC_R_SUCCESS);
02143 }
02144
02145 void
02146 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
02147 dns_name_t *prefix, dns_name_t *suffix)
02148
02149 {
02150 unsigned int splitlabel;
02151
02152 REQUIRE(VALID_NAME(name));
02153 REQUIRE(suffixlabels > 0);
02154 REQUIRE(suffixlabels < name->labels);
02155 REQUIRE(prefix != NULL || suffix != NULL);
02156 REQUIRE(prefix == NULL ||
02157 (VALID_NAME(prefix) &&
02158 prefix->buffer != NULL &&
02159 BINDABLE(prefix)));
02160 REQUIRE(suffix == NULL ||
02161 (VALID_NAME(suffix) &&
02162 suffix->buffer != NULL &&
02163 BINDABLE(suffix)));
02164
02165 splitlabel = name->labels - suffixlabels;
02166
02167 if (prefix != NULL)
02168 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
02169
02170 if (suffix != NULL)
02171 dns_name_getlabelsequence(name, splitlabel,
02172 suffixlabels, suffix);
02173
02174 return;
02175 }
02176
02177 isc_result_t
02178 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
02179 dns_name_t *target)
02180 {
02181
02182
02183
02184
02185 REQUIRE(VALID_NAME(source));
02186 REQUIRE(source->length > 0);
02187 REQUIRE(VALID_NAME(target));
02188 REQUIRE(BINDABLE(target));
02189
02190
02191
02192
02193 MAKE_EMPTY(target);
02194
02195 target->ndata = isc_mem_get(mctx, source->length);
02196 if (target->ndata == NULL)
02197 return (ISC_R_NOMEMORY);
02198
02199 memmove(target->ndata, source->ndata, source->length);
02200
02201 target->length = source->length;
02202 target->labels = source->labels;
02203 target->attributes = DNS_NAMEATTR_DYNAMIC;
02204 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
02205 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
02206 if (target->offsets != NULL) {
02207 if (source->offsets != NULL)
02208 memmove(target->offsets, source->offsets,
02209 source->labels);
02210 else
02211 set_offsets(target, target->offsets, NULL);
02212 }
02213
02214 return (ISC_R_SUCCESS);
02215 }
02216
02217 isc_result_t
02218 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
02219 dns_name_t *target)
02220 {
02221
02222
02223
02224
02225
02226 REQUIRE(VALID_NAME(source));
02227 REQUIRE(source->length > 0);
02228 REQUIRE(VALID_NAME(target));
02229 REQUIRE(BINDABLE(target));
02230 REQUIRE(target->offsets == NULL);
02231
02232
02233
02234
02235 MAKE_EMPTY(target);
02236
02237 target->ndata = isc_mem_get(mctx, source->length + source->labels);
02238 if (target->ndata == NULL)
02239 return (ISC_R_NOMEMORY);
02240
02241 memmove(target->ndata, source->ndata, source->length);
02242
02243 target->length = source->length;
02244 target->labels = source->labels;
02245 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
02246 DNS_NAMEATTR_READONLY;
02247 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
02248 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
02249 target->offsets = target->ndata + source->length;
02250 if (source->offsets != NULL)
02251 memmove(target->offsets, source->offsets, source->labels);
02252 else
02253 set_offsets(target, target->offsets, NULL);
02254
02255 return (ISC_R_SUCCESS);
02256 }
02257
02258 void
02259 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
02260 size_t size;
02261
02262
02263
02264
02265
02266 REQUIRE(VALID_NAME(name));
02267 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
02268
02269 size = name->length;
02270 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
02271 size += name->labels;
02272 isc_mem_put(mctx, name->ndata, size);
02273 dns_name_invalidate(name);
02274 }
02275
02276 isc_result_t
02277 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
02278 dns_name_t downname;
02279 unsigned char data[256];
02280 isc_buffer_t buffer;
02281 isc_result_t result;
02282 isc_region_t r;
02283
02284
02285
02286
02287
02288 REQUIRE(VALID_NAME(name));
02289 REQUIRE(digest != NULL);
02290
02291 #if defined(__clang__) && \
02292 ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
02293 memset(&downname, 0, sizeof(downname));
02294 #endif
02295 DNS_NAME_INIT(&downname, NULL);
02296
02297 isc_buffer_init(&buffer, data, sizeof(data));
02298
02299 result = dns_name_downcase(name, &downname, &buffer);
02300 if (result != ISC_R_SUCCESS)
02301 return (result);
02302
02303 isc_buffer_usedregion(&buffer, &r);
02304
02305 return ((digest)(arg, &r));
02306 }
02307
02308 isc_boolean_t
02309 dns_name_dynamic(dns_name_t *name) {
02310 REQUIRE(VALID_NAME(name));
02311
02312
02313
02314
02315
02316 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
02317 ISC_TRUE : ISC_FALSE);
02318 }
02319
02320 isc_result_t
02321 dns_name_print(dns_name_t *name, FILE *stream) {
02322 isc_result_t result;
02323 isc_buffer_t b;
02324 isc_region_t r;
02325 char t[1024];
02326
02327
02328
02329
02330
02331 REQUIRE(VALID_NAME(name));
02332
02333 isc_buffer_init(&b, t, sizeof(t));
02334 result = dns_name_totext(name, ISC_FALSE, &b);
02335 if (result != ISC_R_SUCCESS)
02336 return (result);
02337 isc_buffer_usedregion(&b, &r);
02338 fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
02339
02340 return (ISC_R_SUCCESS);
02341 }
02342
02343 isc_result_t
02344 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
02345 #ifdef ISC_PLATFORM_USETHREADS
02346 isc_result_t result;
02347 dns_name_totextfilter_t *mem;
02348 int res;
02349
02350 result = totext_filter_proc_key_init();
02351 if (result != ISC_R_SUCCESS)
02352 return (result);
02353
02354
02355
02356
02357
02358 mem = isc_thread_key_getspecific(totext_filter_proc_key);
02359 if (mem != NULL && proc != NULL) {
02360 *mem = proc;
02361 return (ISC_R_SUCCESS);
02362 }
02363 if (proc == NULL) {
02364 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
02365 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
02366 if (res != 0)
02367 result = ISC_R_UNEXPECTED;
02368 return (result);
02369 }
02370
02371 mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
02372 if (mem == NULL)
02373 return (ISC_R_NOMEMORY);
02374 *mem = proc;
02375 if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
02376 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
02377 result = ISC_R_UNEXPECTED;
02378 }
02379 return (result);
02380 #else
02381 totext_filter_proc = proc;
02382 return (ISC_R_SUCCESS);
02383 #endif
02384 }
02385
02386 void
02387 dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
02388 isc_result_t result;
02389 isc_buffer_t buf;
02390
02391 REQUIRE(size > 0);
02392
02393
02394
02395
02396 isc_buffer_init(&buf, cp, size - 1);
02397 result = dns_name_totext(name, ISC_TRUE, &buf);
02398 if (result == ISC_R_SUCCESS) {
02399
02400
02401
02402 isc_region_t r;
02403 isc_buffer_usedregion(&buf, &r);
02404 ((char *) r.base)[r.length] = '\0';
02405
02406 } else
02407 snprintf(cp, size, "<unknown>");
02408 }
02409
02410
02411
02412
02413
02414 isc_result_t
02415 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
02416 isc_result_t result;
02417 isc_buffer_t buf;
02418 isc_region_t reg;
02419 char *p, txt[DNS_NAME_FORMATSIZE];
02420
02421 REQUIRE(VALID_NAME(name));
02422 REQUIRE(target != NULL && *target == NULL);
02423
02424 isc_buffer_init(&buf, txt, sizeof(txt));
02425 result = dns_name_totext(name, ISC_FALSE, &buf);
02426 if (result != ISC_R_SUCCESS)
02427 return (result);
02428
02429 isc_buffer_usedregion(&buf, ®);
02430 p = isc_mem_allocate(mctx, reg.length + 1);
02431 if (p == NULL)
02432 return (ISC_R_NOMEMORY);
02433 memmove(p, (char *) reg.base, (int) reg.length);
02434 p[reg.length] = '\0';
02435
02436 *target = p;
02437 return (ISC_R_SUCCESS);
02438 }
02439
02440
02441
02442
02443
02444 isc_result_t
02445 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
02446 isc_mem_t *mctx)
02447 {
02448 return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
02449 }
02450
02451 isc_result_t
02452 dns_name_fromstring2(dns_name_t *target, const char *src,
02453 const dns_name_t *origin, unsigned int options,
02454 isc_mem_t *mctx)
02455 {
02456 isc_result_t result;
02457 isc_buffer_t buf;
02458 dns_fixedname_t fn;
02459 dns_name_t *name;
02460
02461 REQUIRE(src != NULL);
02462
02463 isc_buffer_constinit(&buf, src, strlen(src));
02464 isc_buffer_add(&buf, strlen(src));
02465 if (BINDABLE(target) && target->buffer != NULL)
02466 name = target;
02467 else {
02468 dns_fixedname_init(&fn);
02469 name = dns_fixedname_name(&fn);
02470 }
02471
02472 result = dns_name_fromtext(name, &buf, origin, options, NULL);
02473 if (result != ISC_R_SUCCESS)
02474 return (result);
02475
02476 if (name != target)
02477 result = dns_name_dupwithoffsets(name, mctx, target);
02478 return (result);
02479 }
02480
02481 isc_result_t
02482 dns_name_copy(const dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
02483 unsigned char *ndata;
02484
02485
02486
02487
02488
02489 REQUIRE(VALID_NAME(source));
02490 REQUIRE(VALID_NAME(dest));
02491 REQUIRE(target != NULL || dest->buffer != NULL);
02492
02493 if (target == NULL) {
02494 target = dest->buffer;
02495 isc_buffer_clear(dest->buffer);
02496 }
02497
02498 REQUIRE(BINDABLE(dest));
02499
02500
02501
02502
02503 if (target->length - target->used < source->length)
02504 return (ISC_R_NOSPACE);
02505
02506 ndata = (unsigned char *)target->base + target->used;
02507 dest->ndata = target->base;
02508
02509 memmove(ndata, source->ndata, source->length);
02510
02511 dest->ndata = ndata;
02512 dest->labels = source->labels;
02513 dest->length = source->length;
02514 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
02515 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
02516 else
02517 dest->attributes = 0;
02518
02519 if (dest->labels > 0 && dest->offsets != NULL) {
02520 if (source->offsets != NULL)
02521 memmove(dest->offsets, source->offsets, source->labels);
02522 else
02523 set_offsets(dest, dest->offsets, NULL);
02524 }
02525
02526 isc_buffer_add(target, dest->length);
02527
02528 return (ISC_R_SUCCESS);
02529 }
02530
02531 void
02532 dns_name_destroy(void) {
02533 #ifdef ISC_PLATFORM_USETHREADS
02534 RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
02535 == ISC_R_SUCCESS);
02536
02537 LOCK(&thread_key_mutex);
02538 if (thread_key_initialized) {
02539 isc_mem_detach(&thread_key_mctx);
02540 isc_thread_key_delete(totext_filter_proc_key);
02541 thread_key_initialized = 0;
02542 }
02543 UNLOCK(&thread_key_mutex);
02544
02545 #endif
02546 }