name.c revision 135446
140875Smsmith/* 240875Smsmith * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 340875Smsmith * Copyright (C) 1998-2003 Internet Software Consortium. 440875Smsmith * 540875Smsmith * Permission to use, copy, modify, and distribute this software for any 640875Smsmith * purpose with or without fee is hereby granted, provided that the above 740875Smsmith * copyright notice and this permission notice appear in all copies. 840875Smsmith * 940875Smsmith * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 1040875Smsmith * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1140875Smsmith * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 1240875Smsmith * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1340875Smsmith * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 1440875Smsmith * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1540875Smsmith * PERFORMANCE OF THIS SOFTWARE. 1640875Smsmith */ 1740875Smsmith 1840875Smsmith/* $Id: name.c,v 1.127.2.7.2.11 2004/09/01 05:19:59 marka Exp $ */ 1940875Smsmith 2040875Smsmith#include <config.h> 2140875Smsmith 2240875Smsmith#include <ctype.h> 2340875Smsmith 2440875Smsmith#include <isc/buffer.h> 2540875Smsmith#include <isc/hash.h> 2641254Spaul#include <isc/mem.h> 2740834Smsmith#include <isc/print.h> 2840834Smsmith#include <isc/string.h> 2940834Smsmith#include <isc/util.h> 3040834Smsmith 3140834Smsmith#include <dns/compress.h> 3240834Smsmith#include <dns/name.h> 3340834Smsmith#include <dns/result.h> 3440834Smsmith 3540834Smsmith#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC) 3640834Smsmith 3740834Smsmithtypedef enum { 3840834Smsmith ft_init = 0, 3940834Smsmith ft_start, 4040834Smsmith ft_ordinary, 4140834Smsmith ft_initialescape, 4240834Smsmith ft_escape, 4340834Smsmith ft_escdecimal, 4440834Smsmith ft_at 4540834Smsmith} ft_state; 4640834Smsmith 4740834Smsmithtypedef enum { 4840834Smsmith fw_start = 0, 4940834Smsmith fw_ordinary, 5040834Smsmith fw_copy, 5140834Smsmith fw_newcurrent 5240834Smsmith} fw_state; 5340834Smsmith 5440835Smsmithstatic char digitvalue[256] = { 5540834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ 5640834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ 5740834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ 5840834Smsmith 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ 5940834Smsmith -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ 6040834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ 6140834Smsmith -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ 6240834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ 6340835Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6440834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6540834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6640834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6740834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6840834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6940834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7040834Smsmith -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ 7140834Smsmith}; 7240834Smsmith 7340834Smsmithstatic unsigned char maptolower[] = { 7440834Smsmith 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 7540834Smsmith 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 7640834Smsmith 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 7740834Smsmith 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 7840834Smsmith 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 7940834Smsmith 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 8040834Smsmith 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 8140834Smsmith 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 8240834Smsmith 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 8340834Smsmith 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 8440834Smsmith 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 8540834Smsmith 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 8640834Smsmith 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 8740834Smsmith 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 8840834Smsmith 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 8940834Smsmith 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 9040834Smsmith 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 9140834Smsmith 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 9240834Smsmith 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 9340834Smsmith 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 9440834Smsmith 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 9540834Smsmith 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 9640834Smsmith 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 9740834Smsmith 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 9840834Smsmith 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 9940834Smsmith 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 10040834Smsmith 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 10141254Spaul 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 10240835Smsmith 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 10341254Spaul 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 10441254Spaul 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 10540834Smsmith 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff 10640834Smsmith}; 10740834Smsmith 10840834Smsmith#define CONVERTTOASCII(c) 10940834Smsmith#define CONVERTFROMASCII(c) 11040834Smsmith 11140834Smsmith#define INIT_OFFSETS(name, var, default) \ 11240834Smsmith if (name->offsets != NULL) \ 11340834Smsmith var = name->offsets; \ 11440834Smsmith else \ 11540834Smsmith var = default; 11640834Smsmith 11740834Smsmith#define SETUP_OFFSETS(name, var, default) \ 11840834Smsmith if (name->offsets != NULL) \ 11940834Smsmith var = name->offsets; \ 12040834Smsmith else { \ 12140834Smsmith var = default; \ 12240834Smsmith set_offsets(name, var, NULL); \ 12340834Smsmith } 12440834Smsmith 12540834Smsmith/* 12640834Smsmith * Note: If additional attributes are added that should not be set for 12740834Smsmith * empty names, MAKE_EMPTY() must be changed so it clears them. 12840834Smsmith */ 12940834Smsmith#define MAKE_EMPTY(name) \ 13040834Smsmithdo { \ 13140834Smsmith name->ndata = NULL; \ 13240834Smsmith name->length = 0; \ 13340834Smsmith name->labels = 0; \ 13440834Smsmith name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \ 13540834Smsmith} while (0); 13640834Smsmith 13740834Smsmith/* 13840834Smsmith * A name is "bindable" if it can be set to point to a new value, i.e. 13940834Smsmith * name->ndata and name->length may be changed. 14040834Smsmith */ 14140834Smsmith#define BINDABLE(name) \ 14240834Smsmith ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \ 14340834Smsmith == 0) 14440834Smsmith 14540834Smsmith/* 14640834Smsmith * Note that the name data must be a char array, not a string 14740834Smsmith * literal, to avoid compiler warnings about discarding 14840834Smsmith * the const attribute of a string. 14940834Smsmith */ 15040834Smsmithstatic unsigned char root_ndata[] = { '\0' }; 15140834Smsmithstatic unsigned char root_offsets[] = { 0 }; 15240834Smsmith 15340834Smsmithstatic dns_name_t root = 15440834Smsmith{ 15540834Smsmith DNS_NAME_MAGIC, 15640834Smsmith root_ndata, 1, 1, 15740834Smsmith DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, 15840834Smsmith root_offsets, NULL, 15940834Smsmith {(void *)-1, (void *)-1}, 16040834Smsmith {NULL, NULL} 16140834Smsmith}; 16240834Smsmith 16340834Smsmith/* XXXDCL make const? */ 16440834SmsmithLIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root; 16540834Smsmith 16640834Smsmithstatic unsigned char wild_ndata[] = { '\001', '*' }; 16740834Smsmithstatic unsigned char wild_offsets[] = { 0 }; 16840834Smsmith 16940834Smsmithstatic dns_name_t wild = 17040834Smsmith{ 17140834Smsmith DNS_NAME_MAGIC, 17240834Smsmith wild_ndata, 2, 1, 17340834Smsmith DNS_NAMEATTR_READONLY, 17440834Smsmith wild_offsets, NULL, 17540834Smsmith {(void *)-1, (void *)-1}, 17640834Smsmith {NULL, NULL} 17740834Smsmith}; 17840834Smsmith 17940834Smsmith/* XXXDCL make const? */ 18040834SmsmithLIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild; 18140834Smsmith 18240834Smsmithunsigned int 18340834Smsmithdns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive); 18440834Smsmith 18540834Smsmithstatic void 18640834Smsmithset_offsets(const dns_name_t *name, unsigned char *offsets, 18740834Smsmith dns_name_t *set_name); 18840834Smsmith 18940834Smsmithvoid 19040834Smsmithdns_name_init(dns_name_t *name, unsigned char *offsets) { 19140835Smsmith /* 19240835Smsmith * Initialize 'name'. 19340834Smsmith */ 19440834Smsmith DNS_NAME_INIT(name, offsets); 19540834Smsmith} 19640834Smsmith 19740834Smsmithvoid 19840835Smsmithdns_name_reset(dns_name_t *name) { 19940834Smsmith REQUIRE(VALID_NAME(name)); 20040834Smsmith REQUIRE(BINDABLE(name)); 20140835Smsmith 20240835Smsmith DNS_NAME_RESET(name); 20340834Smsmith} 20440834Smsmith 20540835Smsmithvoid 20640834Smsmithdns_name_invalidate(dns_name_t *name) { 20740834Smsmith /* 20840834Smsmith * Make 'name' invalid. 20940834Smsmith */ 21040834Smsmith 21140835Smsmith REQUIRE(VALID_NAME(name)); 21240835Smsmith 21340834Smsmith name->magic = 0; 21440835Smsmith name->ndata = NULL; 21540834Smsmith name->length = 0; 21640834Smsmith name->labels = 0; 21740835Smsmith name->attributes = 0; 21840834Smsmith name->offsets = NULL; 21940834Smsmith name->buffer = NULL; 22040834Smsmith ISC_LINK_INIT(name, link); 22140835Smsmith} 22240834Smsmith 22340834Smsmithvoid 22440834Smsmithdns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) { 22540834Smsmith /* 22640835Smsmith * Dedicate a buffer for use with 'name'. 22740834Smsmith */ 22840834Smsmith 22940834Smsmith REQUIRE(VALID_NAME(name)); 23040834Smsmith REQUIRE((buffer != NULL && name->buffer == NULL) || 23140834Smsmith (buffer == NULL)); 23240834Smsmith 23340834Smsmith name->buffer = buffer; 23440834Smsmith} 23540834Smsmith 23640834Smsmithisc_boolean_t 23740834Smsmithdns_name_hasbuffer(const dns_name_t *name) { 23840834Smsmith /* 23940834Smsmith * Does 'name' have a dedicated buffer? 24040834Smsmith */ 24140834Smsmith 24240834Smsmith REQUIRE(VALID_NAME(name)); 24340834Smsmith 24440834Smsmith if (name->buffer != NULL) 24540834Smsmith return (ISC_TRUE); 24640834Smsmith 24740834Smsmith return (ISC_FALSE); 24840834Smsmith} 24940834Smsmith 25040834Smsmithisc_boolean_t 25140834Smsmithdns_name_isabsolute(const dns_name_t *name) { 25240834Smsmith 25340834Smsmith /* 25440834Smsmith * Does 'name' end in the root label? 25540835Smsmith */ 25640834Smsmith 25740834Smsmith REQUIRE(VALID_NAME(name)); 25840834Smsmith 25940834Smsmith if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 26040834Smsmith return (ISC_TRUE); 26140834Smsmith return (ISC_FALSE); 26240834Smsmith} 263 264#define hyphenchar(c) ((c) == 0x2d) 265#define asterchar(c) ((c) == 0x2a) 266#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ 267 || ((c) >= 0x61 && (c) <= 0x7a)) 268#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) 269#define borderchar(c) (alphachar(c) || digitchar(c)) 270#define middlechar(c) (borderchar(c) || hyphenchar(c)) 271#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) 272 273isc_boolean_t 274dns_name_ismailbox(const dns_name_t *name) { 275 unsigned char *ndata, ch; 276 unsigned int n; 277 isc_boolean_t first; 278 279 REQUIRE(VALID_NAME(name)); 280 REQUIRE(name->labels > 0); 281 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); 282 283 /* 284 * Root label. 285 */ 286 if (name->length == 1) 287 return (ISC_TRUE); 288 289 ndata = name->ndata; 290 n = *ndata++; 291 INSIST(n <= 63); 292 while (n--) { 293 ch = *ndata++; 294 if (!domainchar(ch)) 295 return (ISC_FALSE); 296 } 297 298 if (ndata == name->ndata + name->length) 299 return (ISC_FALSE); 300 301 /* 302 * RFC292/RFC1123 hostname. 303 */ 304 while (ndata < (name->ndata + name->length)) { 305 n = *ndata++; 306 INSIST(n <= 63); 307 first = ISC_TRUE; 308 while (n--) { 309 ch = *ndata++; 310 if (first || n == 0) { 311 if (!borderchar(ch)) 312 return (ISC_FALSE); 313 } else { 314 if (!middlechar(ch)) 315 return (ISC_FALSE); 316 } 317 first = ISC_FALSE; 318 } 319 } 320 return (ISC_TRUE); 321} 322 323isc_boolean_t 324dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) { 325 unsigned char *ndata, ch; 326 unsigned int n; 327 isc_boolean_t first; 328 329 REQUIRE(VALID_NAME(name)); 330 REQUIRE(name->labels > 0); 331 REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE); 332 333 /* 334 * Root label. 335 */ 336 if (name->length == 1) 337 return (ISC_TRUE); 338 339 /* 340 * Skip wildcard if this is a ownername. 341 */ 342 ndata = name->ndata; 343 if (wildcard && ndata[0] == 1 && ndata[1] == '*') 344 ndata += 2; 345 346 /* 347 * RFC292/RFC1123 hostname. 348 */ 349 while (ndata < (name->ndata + name->length)) { 350 n = *ndata++; 351 INSIST(n <= 63); 352 first = ISC_TRUE; 353 while (n--) { 354 ch = *ndata++; 355 if (first || n == 0) { 356 if (!borderchar(ch)) 357 return (ISC_FALSE); 358 } else { 359 if (!middlechar(ch)) 360 return (ISC_FALSE); 361 } 362 first = ISC_FALSE; 363 } 364 } 365 return (ISC_TRUE); 366} 367 368isc_boolean_t 369dns_name_iswildcard(const dns_name_t *name) { 370 unsigned char *ndata; 371 372 /* 373 * Is 'name' a wildcard name? 374 */ 375 376 REQUIRE(VALID_NAME(name)); 377 REQUIRE(name->labels > 0); 378 379 if (name->length >= 2) { 380 ndata = name->ndata; 381 if (ndata[0] == 1 && ndata[1] == '*') 382 return (ISC_TRUE); 383 } 384 385 return (ISC_FALSE); 386} 387 388static inline unsigned int 389name_hash(dns_name_t *name, isc_boolean_t case_sensitive) { 390 unsigned int length; 391 const unsigned char *s; 392 unsigned int h = 0; 393 unsigned char c; 394 395 length = name->length; 396 if (length > 16) 397 length = 16; 398 399 /* 400 * This hash function is similar to the one Ousterhout 401 * uses in Tcl. 402 */ 403 s = name->ndata; 404 if (case_sensitive) { 405 while (length > 0) { 406 h += ( h << 3 ) + *s; 407 s++; 408 length--; 409 } 410 } else { 411 while (length > 0) { 412 c = maptolower[*s]; 413 h += ( h << 3 ) + c; 414 s++; 415 length--; 416 } 417 } 418 419 return (h); 420} 421 422unsigned int 423dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) { 424 /* 425 * Provide a hash value for 'name'. 426 */ 427 REQUIRE(VALID_NAME(name)); 428 429 if (name->labels == 0) 430 return (0); 431 432 return (name_hash(name, case_sensitive)); 433} 434 435unsigned int 436dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) { 437 /* 438 * Provide a hash value for 'name'. 439 */ 440 REQUIRE(VALID_NAME(name)); 441 442 if (name->labels == 0) 443 return (0); 444 445 return (isc_hash_calc((const unsigned char *)name->ndata, 446 name->length, case_sensitive)); 447} 448 449unsigned int 450dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) { 451 /* 452 * This function was deprecated due to the breakage of the name space 453 * convention. We only keep this internally to provide binary backward 454 * compatibility. 455 */ 456 REQUIRE(VALID_NAME(name)); 457 458 return (dns_name_fullhash(name, case_sensitive)); 459} 460 461unsigned int 462dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) { 463 unsigned char *offsets; 464 dns_offsets_t odata; 465 dns_name_t tname; 466 unsigned int h = 0; 467 unsigned int i; 468 469 /* 470 * Provide a hash value for 'name'. 471 */ 472 REQUIRE(VALID_NAME(name)); 473 474 if (name->labels == 0) 475 return (0); 476 else if (name->labels == 1) 477 return (name_hash(name, case_sensitive)); 478 479 SETUP_OFFSETS(name, offsets, odata); 480 DNS_NAME_INIT(&tname, NULL); 481 tname.labels = 1; 482 h = 0; 483 for (i = 0; i < name->labels; i++) { 484 tname.ndata = name->ndata + offsets[i]; 485 if (i == name->labels - 1) 486 tname.length = name->length - offsets[i]; 487 else 488 tname.length = offsets[i + 1] - offsets[i]; 489 h += name_hash(&tname, case_sensitive); 490 } 491 492 return (h); 493} 494 495dns_namereln_t 496dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, 497 int *orderp, unsigned int *nlabelsp) 498{ 499 unsigned int l1, l2, l, count1, count2, count, nlabels; 500 int cdiff, ldiff, chdiff; 501 unsigned char *label1, *label2; 502 unsigned char *offsets1, *offsets2; 503 dns_offsets_t odata1, odata2; 504 dns_namereln_t namereln = dns_namereln_none; 505 506 /* 507 * Determine the relative ordering under the DNSSEC order relation of 508 * 'name1' and 'name2', and also determine the hierarchical 509 * relationship of the names. 510 * 511 * Note: It makes no sense for one of the names to be relative and the 512 * other absolute. If both names are relative, then to be meaningfully 513 * compared the caller must ensure that they are both relative to the 514 * same domain. 515 */ 516 517 REQUIRE(VALID_NAME(name1)); 518 REQUIRE(VALID_NAME(name2)); 519 REQUIRE(orderp != NULL); 520 REQUIRE(nlabelsp != NULL); 521 /* 522 * Either name1 is absolute and name2 is absolute, or neither is. 523 */ 524 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 525 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 526 527 SETUP_OFFSETS(name1, offsets1, odata1); 528 SETUP_OFFSETS(name2, offsets2, odata2); 529 530 nlabels = 0; 531 l1 = name1->labels; 532 l2 = name2->labels; 533 ldiff = (int)l1 - (int)l2; 534 if (ldiff < 0) 535 l = l1; 536 else 537 l = l2; 538 539 while (l > 0) { 540 l--; 541 l1--; 542 l2--; 543 label1 = &name1->ndata[offsets1[l1]]; 544 label2 = &name2->ndata[offsets2[l2]]; 545 count1 = *label1++; 546 count2 = *label2++; 547 548 /* 549 * We dropped bitstring labels, and we don't support any 550 * other extended label types. 551 */ 552 INSIST(count1 <= 63 && count2 <= 63); 553 554 cdiff = (int)count1 - (int)count2; 555 if (cdiff < 0) 556 count = count1; 557 else 558 count = count2; 559 560 while (count > 0) { 561 chdiff = (int)maptolower[*label1] - 562 (int)maptolower[*label2]; 563 if (chdiff != 0) { 564 *orderp = chdiff; 565 goto done; 566 } 567 count--; 568 label1++; 569 label2++; 570 } 571 if (cdiff != 0) { 572 *orderp = cdiff; 573 goto done; 574 } 575 nlabels++; 576 } 577 578 *orderp = ldiff; 579 if (ldiff < 0) 580 namereln = dns_namereln_contains; 581 else if (ldiff > 0) 582 namereln = dns_namereln_subdomain; 583 else 584 namereln = dns_namereln_equal; 585 586 done: 587 *nlabelsp = nlabels; 588 589 if (nlabels > 0 && namereln == dns_namereln_none) 590 namereln = dns_namereln_commonancestor; 591 592 return (namereln); 593} 594 595int 596dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) { 597 int order; 598 unsigned int nlabels; 599 600 /* 601 * Determine the relative ordering under the DNSSEC order relation of 602 * 'name1' and 'name2'. 603 * 604 * Note: It makes no sense for one of the names to be relative and the 605 * other absolute. If both names are relative, then to be meaningfully 606 * compared the caller must ensure that they are both relative to the 607 * same domain. 608 */ 609 610 (void)dns_name_fullcompare(name1, name2, &order, &nlabels); 611 612 return (order); 613} 614 615isc_boolean_t 616dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) { 617 unsigned int l, count; 618 unsigned char c; 619 unsigned char *label1, *label2; 620 621 /* 622 * Are 'name1' and 'name2' equal? 623 * 624 * Note: It makes no sense for one of the names to be relative and the 625 * other absolute. If both names are relative, then to be meaningfully 626 * compared the caller must ensure that they are both relative to the 627 * same domain. 628 */ 629 630 REQUIRE(VALID_NAME(name1)); 631 REQUIRE(VALID_NAME(name2)); 632 /* 633 * Either name1 is absolute and name2 is absolute, or neither is. 634 */ 635 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) == 636 (name2->attributes & DNS_NAMEATTR_ABSOLUTE)); 637 638 if (name1->length != name2->length) 639 return (ISC_FALSE); 640 641 l = name1->labels; 642 643 if (l != name2->labels) 644 return (ISC_FALSE); 645 646 label1 = name1->ndata; 647 label2 = name2->ndata; 648 while (l > 0) { 649 l--; 650 count = *label1++; 651 if (count != *label2++) 652 return (ISC_FALSE); 653 654 INSIST(count <= 63); /* no bitstring support */ 655 656 while (count > 0) { 657 count--; 658 c = maptolower[*label1++]; 659 if (c != maptolower[*label2++]) 660 return (ISC_FALSE); 661 } 662 } 663 664 return (ISC_TRUE); 665} 666 667int 668dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) { 669 unsigned int l1, l2, l, count1, count2, count; 670 unsigned char c1, c2; 671 unsigned char *label1, *label2; 672 673 /* 674 * Compare two absolute names as rdata. 675 */ 676 677 REQUIRE(VALID_NAME(name1)); 678 REQUIRE(name1->labels > 0); 679 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 680 REQUIRE(VALID_NAME(name2)); 681 REQUIRE(name2->labels > 0); 682 REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 683 684 l1 = name1->labels; 685 l2 = name2->labels; 686 687 l = (l1 < l2) ? l1 : l2; 688 689 label1 = name1->ndata; 690 label2 = name2->ndata; 691 while (l > 0) { 692 l--; 693 count1 = *label1++; 694 count2 = *label2++; 695 696 /* no bitstring support */ 697 INSIST(count1 <= 63 && count2 <= 63); 698 699 if (count1 != count2) 700 return ((count1 < count2) ? -1 : 1); 701 count = count1; 702 while (count > 0) { 703 count--; 704 c1 = maptolower[*label1++]; 705 c2 = maptolower[*label2++]; 706 if (c1 < c2) 707 return (-1); 708 else if (c1 > c2) 709 return (1); 710 } 711 } 712 713 /* 714 * If one name had more labels than the other, their common 715 * prefix must have been different because the shorter name 716 * ended with the root label and the longer one can't have 717 * a root label in the middle of it. Therefore, if we get 718 * to this point, the lengths must be equal. 719 */ 720 INSIST(l1 == l2); 721 722 return (0); 723} 724 725isc_boolean_t 726dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) { 727 int order; 728 unsigned int nlabels; 729 dns_namereln_t namereln; 730 731 /* 732 * Is 'name1' a subdomain of 'name2'? 733 * 734 * Note: It makes no sense for one of the names to be relative and the 735 * other absolute. If both names are relative, then to be meaningfully 736 * compared the caller must ensure that they are both relative to the 737 * same domain. 738 */ 739 740 namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); 741 if (namereln == dns_namereln_subdomain || 742 namereln == dns_namereln_equal) 743 return (ISC_TRUE); 744 745 return (ISC_FALSE); 746} 747 748isc_boolean_t 749dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) { 750 int order; 751 unsigned int nlabels, labels; 752 dns_name_t tname; 753 754 REQUIRE(VALID_NAME(name)); 755 REQUIRE(name->labels > 0); 756 REQUIRE(VALID_NAME(wname)); 757 labels = wname->labels; 758 REQUIRE(labels > 0); 759 REQUIRE(dns_name_iswildcard(wname)); 760 761 DNS_NAME_INIT(&tname, NULL); 762 dns_name_getlabelsequence(wname, 1, labels - 1, &tname); 763 if (dns_name_fullcompare(name, &tname, &order, &nlabels) == 764 dns_namereln_subdomain) 765 return (ISC_TRUE); 766 return (ISC_FALSE); 767} 768 769unsigned int 770dns_name_countlabels(const dns_name_t *name) { 771 /* 772 * How many labels does 'name' have? 773 */ 774 775 REQUIRE(VALID_NAME(name)); 776 777 ENSURE(name->labels <= 128); 778 779 return (name->labels); 780} 781 782void 783dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) { 784 unsigned char *offsets; 785 dns_offsets_t odata; 786 787 /* 788 * Make 'label' refer to the 'n'th least significant label of 'name'. 789 */ 790 791 REQUIRE(VALID_NAME(name)); 792 REQUIRE(name->labels > 0); 793 REQUIRE(n < name->labels); 794 REQUIRE(label != NULL); 795 796 SETUP_OFFSETS(name, offsets, odata); 797 798 label->base = &name->ndata[offsets[n]]; 799 if (n == name->labels - 1) 800 label->length = name->length - offsets[n]; 801 else 802 label->length = offsets[n + 1] - offsets[n]; 803} 804 805void 806dns_name_getlabelsequence(const dns_name_t *source, 807 unsigned int first, unsigned int n, 808 dns_name_t *target) 809{ 810 unsigned char *offsets; 811 dns_offsets_t odata; 812 unsigned int firstoffset, endoffset; 813 814 /* 815 * Make 'target' refer to the 'n' labels including and following 816 * 'first' in 'source'. 817 */ 818 819 REQUIRE(VALID_NAME(source)); 820 REQUIRE(VALID_NAME(target)); 821 REQUIRE(first <= source->labels); 822 REQUIRE(first + n <= source->labels); 823 REQUIRE(BINDABLE(target)); 824 825 SETUP_OFFSETS(source, offsets, odata); 826 827 if (first == source->labels) 828 firstoffset = source->length; 829 else 830 firstoffset = offsets[first]; 831 832 if (first + n == source->labels) 833 endoffset = source->length; 834 else 835 endoffset = offsets[first + n]; 836 837 target->ndata = &source->ndata[firstoffset]; 838 target->length = endoffset - firstoffset; 839 840 if (first + n == source->labels && n > 0 && 841 (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 842 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 843 else 844 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 845 846 target->labels = n; 847 848 /* 849 * If source and target are the same, and we're making target 850 * a prefix of source, the offsets table is correct already 851 * so we don't need to call set_offsets(). 852 */ 853 if (target->offsets != NULL && 854 (target != source || first != 0)) 855 set_offsets(target, target->offsets, NULL); 856} 857 858void 859dns_name_clone(dns_name_t *source, dns_name_t *target) { 860 861 /* 862 * Make 'target' refer to the same name as 'source'. 863 */ 864 865 REQUIRE(VALID_NAME(source)); 866 REQUIRE(VALID_NAME(target)); 867 REQUIRE(BINDABLE(target)); 868 869 target->ndata = source->ndata; 870 target->length = source->length; 871 target->labels = source->labels; 872 target->attributes = source->attributes & 873 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC | 874 DNS_NAMEATTR_DYNOFFSETS); 875 if (target->offsets != NULL && source->labels > 0) { 876 if (source->offsets != NULL) 877 memcpy(target->offsets, source->offsets, 878 source->labels); 879 else 880 set_offsets(target, target->offsets, NULL); 881 } 882} 883 884void 885dns_name_fromregion(dns_name_t *name, const isc_region_t *r) { 886 unsigned char *offsets; 887 dns_offsets_t odata; 888 unsigned int len; 889 isc_region_t r2; 890 891 /* 892 * Make 'name' refer to region 'r'. 893 */ 894 895 REQUIRE(VALID_NAME(name)); 896 REQUIRE(r != NULL); 897 REQUIRE(BINDABLE(name)); 898 899 INIT_OFFSETS(name, offsets, odata); 900 901 if (name->buffer != NULL) { 902 isc_buffer_clear(name->buffer); 903 isc_buffer_availableregion(name->buffer, &r2); 904 len = (r->length < r2.length) ? r->length : r2.length; 905 if (len > DNS_NAME_MAXWIRE) 906 len = DNS_NAME_MAXWIRE; 907 memcpy(r2.base, r->base, len); 908 name->ndata = r2.base; 909 name->length = len; 910 } else { 911 name->ndata = r->base; 912 name->length = (r->length <= DNS_NAME_MAXWIRE) ? 913 r->length : DNS_NAME_MAXWIRE; 914 } 915 916 if (r->length > 0) 917 set_offsets(name, offsets, name); 918 else { 919 name->labels = 0; 920 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 921 } 922 923 if (name->buffer != NULL) 924 isc_buffer_add(name->buffer, name->length); 925} 926 927void 928dns_name_toregion(dns_name_t *name, isc_region_t *r) { 929 /* 930 * Make 'r' refer to 'name'. 931 */ 932 933 REQUIRE(VALID_NAME(name)); 934 REQUIRE(r != NULL); 935 936 DNS_NAME_TOREGION(name, r); 937} 938 939 940isc_result_t 941dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, 942 dns_name_t *origin, unsigned int options, 943 isc_buffer_t *target) 944{ 945 unsigned char *ndata, *label; 946 char *tdata; 947 char c; 948 ft_state state, kind; 949 unsigned int value, count, tbcount, bitlength, maxlength; 950 unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused; 951 isc_boolean_t done; 952 unsigned char *offsets; 953 dns_offsets_t odata; 954 isc_boolean_t downcase; 955 956 /* 957 * Convert the textual representation of a DNS name at source 958 * into uncompressed wire form stored in target. 959 * 960 * Notes: 961 * Relative domain names will have 'origin' appended to them 962 * unless 'origin' is NULL, in which case relative domain names 963 * will remain relative. 964 */ 965 966 REQUIRE(VALID_NAME(name)); 967 REQUIRE(ISC_BUFFER_VALID(source)); 968 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 969 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 970 971 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 972 973 if (target == NULL && name->buffer != NULL) { 974 target = name->buffer; 975 isc_buffer_clear(target); 976 } 977 978 REQUIRE(BINDABLE(name)); 979 980 INIT_OFFSETS(name, offsets, odata); 981 offsets[0] = 0; 982 983 /* 984 * Initialize things to make the compiler happy; they're not required. 985 */ 986 n1 = 0; 987 n2 = 0; 988 vlen = 0; 989 label = NULL; 990 digits = 0; 991 value = 0; 992 count = 0; 993 tbcount = 0; 994 bitlength = 0; 995 maxlength = 0; 996 kind = ft_init; 997 998 /* 999 * Make 'name' empty in case of failure. 1000 */ 1001 MAKE_EMPTY(name); 1002 1003 /* 1004 * Set up the state machine. 1005 */ 1006 tdata = (char *)source->base + source->current; 1007 tlen = isc_buffer_remaininglength(source); 1008 tused = 0; 1009 ndata = isc_buffer_used(target); 1010 nrem = isc_buffer_availablelength(target); 1011 if (nrem > 255) 1012 nrem = 255; 1013 nused = 0; 1014 labels = 0; 1015 done = ISC_FALSE; 1016 state = ft_init; 1017 1018 while (nrem > 0 && tlen > 0 && !done) { 1019 c = *tdata++; 1020 tlen--; 1021 tused++; 1022 1023 switch (state) { 1024 case ft_init: 1025 /* 1026 * Is this the root name? 1027 */ 1028 if (c == '.') { 1029 if (tlen != 0) 1030 return (DNS_R_EMPTYLABEL); 1031 labels++; 1032 *ndata++ = 0; 1033 nrem--; 1034 nused++; 1035 done = ISC_TRUE; 1036 break; 1037 } 1038 if (c == '@' && tlen == 0) { 1039 state = ft_at; 1040 break; 1041 } 1042 1043 /* FALLTHROUGH */ 1044 case ft_start: 1045 label = ndata; 1046 ndata++; 1047 nrem--; 1048 nused++; 1049 count = 0; 1050 if (c == '\\') { 1051 state = ft_initialescape; 1052 break; 1053 } 1054 kind = ft_ordinary; 1055 state = ft_ordinary; 1056 if (nrem == 0) 1057 return (ISC_R_NOSPACE); 1058 /* FALLTHROUGH */ 1059 case ft_ordinary: 1060 if (c == '.') { 1061 if (count == 0) 1062 return (DNS_R_EMPTYLABEL); 1063 *label = count; 1064 labels++; 1065 INSIST(labels <= 127); 1066 offsets[labels] = nused; 1067 if (tlen == 0) { 1068 labels++; 1069 *ndata++ = 0; 1070 nrem--; 1071 nused++; 1072 done = ISC_TRUE; 1073 } 1074 state = ft_start; 1075 } else if (c == '\\') { 1076 state = ft_escape; 1077 } else { 1078 if (count >= 63) 1079 return (DNS_R_LABELTOOLONG); 1080 count++; 1081 CONVERTTOASCII(c); 1082 if (downcase) 1083 c = maptolower[(int)c]; 1084 *ndata++ = c; 1085 nrem--; 1086 nused++; 1087 } 1088 break; 1089 case ft_initialescape: 1090 if (c == '[') { 1091 /* 1092 * This looks like a bitstring label, which 1093 * was deprecated. Intentionally drop it. 1094 */ 1095 return (DNS_R_BADLABELTYPE); 1096 } 1097 kind = ft_ordinary; 1098 state = ft_escape; 1099 /* FALLTHROUGH */ 1100 case ft_escape: 1101 if (!isdigit(c & 0xff)) { 1102 if (count >= 63) 1103 return (DNS_R_LABELTOOLONG); 1104 count++; 1105 CONVERTTOASCII(c); 1106 if (downcase) 1107 c = maptolower[(int)c]; 1108 *ndata++ = c; 1109 nrem--; 1110 nused++; 1111 state = ft_ordinary; 1112 break; 1113 } 1114 digits = 0; 1115 value = 0; 1116 state = ft_escdecimal; 1117 /* FALLTHROUGH */ 1118 case ft_escdecimal: 1119 if (!isdigit(c & 0xff)) 1120 return (DNS_R_BADESCAPE); 1121 value *= 10; 1122 value += digitvalue[(int)c]; 1123 digits++; 1124 if (digits == 3) { 1125 if (value > 255) 1126 return (DNS_R_BADESCAPE); 1127 if (count >= 63) 1128 return (DNS_R_LABELTOOLONG); 1129 count++; 1130 if (downcase) 1131 value = maptolower[value]; 1132 *ndata++ = value; 1133 nrem--; 1134 nused++; 1135 state = ft_ordinary; 1136 } 1137 break; 1138 default: 1139 FATAL_ERROR(__FILE__, __LINE__, 1140 "Unexpected state %d", state); 1141 /* Does not return. */ 1142 } 1143 } 1144 1145 if (!done) { 1146 if (nrem == 0) 1147 return (ISC_R_NOSPACE); 1148 INSIST(tlen == 0); 1149 if (state != ft_ordinary && state != ft_at) 1150 return (ISC_R_UNEXPECTEDEND); 1151 if (state == ft_ordinary) { 1152 INSIST(count != 0); 1153 *label = count; 1154 labels++; 1155 INSIST(labels <= 127); 1156 offsets[labels] = nused; 1157 } 1158 if (origin != NULL) { 1159 if (nrem < origin->length) 1160 return (ISC_R_NOSPACE); 1161 label = origin->ndata; 1162 n1 = origin->length; 1163 nrem -= n1; 1164 while (n1 > 0) { 1165 n2 = *label++; 1166 INSIST(n2 <= 63); /* no bitstring support */ 1167 *ndata++ = n2; 1168 n1 -= n2 + 1; 1169 nused += n2 + 1; 1170 while (n2 > 0) { 1171 c = *label++; 1172 if (downcase) 1173 c = maptolower[(int)c]; 1174 *ndata++ = c; 1175 n2--; 1176 } 1177 labels++; 1178 if (n1 > 0) { 1179 INSIST(labels <= 127); 1180 offsets[labels] = nused; 1181 } 1182 } 1183 if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1184 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1185 } 1186 } else 1187 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1188 1189 name->ndata = (unsigned char *)target->base + target->used; 1190 name->labels = labels; 1191 name->length = nused; 1192 1193 isc_buffer_forward(source, tused); 1194 isc_buffer_add(target, name->length); 1195 1196 return (ISC_R_SUCCESS); 1197} 1198 1199isc_result_t 1200dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot, 1201 isc_buffer_t *target) 1202{ 1203 unsigned char *ndata; 1204 char *tdata; 1205 unsigned int nlen, tlen; 1206 unsigned char c; 1207 unsigned int trem, count; 1208 unsigned int labels; 1209 isc_boolean_t saw_root = ISC_FALSE; 1210 1211 /* 1212 * This function assumes the name is in proper uncompressed 1213 * wire format. 1214 */ 1215 REQUIRE(VALID_NAME(name)); 1216 REQUIRE(ISC_BUFFER_VALID(target)); 1217 1218 ndata = name->ndata; 1219 nlen = name->length; 1220 labels = name->labels; 1221 tdata = isc_buffer_used(target); 1222 tlen = isc_buffer_availablelength(target); 1223 1224 trem = tlen; 1225 1226 if (labels == 0 && nlen == 0) { 1227 /* 1228 * Special handling for an empty name. 1229 */ 1230 if (trem == 0) 1231 return (ISC_R_NOSPACE); 1232 1233 /* 1234 * The names of these booleans are misleading in this case. 1235 * This empty name is not necessarily from the root node of 1236 * the DNS root zone, nor is a final dot going to be included. 1237 * They need to be set this way, though, to keep the "@" 1238 * from being trounced. 1239 */ 1240 saw_root = ISC_TRUE; 1241 omit_final_dot = ISC_FALSE; 1242 *tdata++ = '@'; 1243 trem--; 1244 1245 /* 1246 * Skip the while() loop. 1247 */ 1248 nlen = 0; 1249 } else if (nlen == 1 && labels == 1 && *ndata == '\0') { 1250 /* 1251 * Special handling for the root label. 1252 */ 1253 if (trem == 0) 1254 return (ISC_R_NOSPACE); 1255 1256 saw_root = ISC_TRUE; 1257 omit_final_dot = ISC_FALSE; 1258 *tdata++ = '.'; 1259 trem--; 1260 1261 /* 1262 * Skip the while() loop. 1263 */ 1264 nlen = 0; 1265 } 1266 1267 while (labels > 0 && nlen > 0 && trem > 0) { 1268 labels--; 1269 count = *ndata++; 1270 nlen--; 1271 if (count == 0) { 1272 saw_root = ISC_TRUE; 1273 break; 1274 } 1275 if (count < 64) { 1276 INSIST(nlen >= count); 1277 while (count > 0) { 1278 c = *ndata; 1279 switch (c) { 1280 case 0x22: /* '"' */ 1281 case 0x28: /* '(' */ 1282 case 0x29: /* ')' */ 1283 case 0x2E: /* '.' */ 1284 case 0x3B: /* ';' */ 1285 case 0x5C: /* '\\' */ 1286 /* Special modifiers in zone files. */ 1287 case 0x40: /* '@' */ 1288 case 0x24: /* '$' */ 1289 if (trem < 2) 1290 return (ISC_R_NOSPACE); 1291 *tdata++ = '\\'; 1292 CONVERTFROMASCII(c); 1293 *tdata++ = c; 1294 ndata++; 1295 trem -= 2; 1296 nlen--; 1297 break; 1298 default: 1299 if (c > 0x20 && c < 0x7f) { 1300 if (trem == 0) 1301 return (ISC_R_NOSPACE); 1302 CONVERTFROMASCII(c); 1303 *tdata++ = c; 1304 ndata++; 1305 trem--; 1306 nlen--; 1307 } else { 1308 char buf[5]; 1309 if (trem < 4) 1310 return (ISC_R_NOSPACE); 1311 snprintf(buf, sizeof(buf), 1312 "\\%03u", c); 1313 memcpy(tdata, buf, 4); 1314 tdata += 4; 1315 trem -= 4; 1316 ndata++; 1317 nlen--; 1318 } 1319 } 1320 count--; 1321 } 1322 } else { 1323 FATAL_ERROR(__FILE__, __LINE__, 1324 "Unexpected label type %02x", count); 1325 /* NOTREACHED */ 1326 } 1327 1328 /* 1329 * The following assumes names are absolute. If not, we 1330 * fix things up later. Note that this means that in some 1331 * cases one more byte of text buffer is required than is 1332 * needed in the final output. 1333 */ 1334 if (trem == 0) 1335 return (ISC_R_NOSPACE); 1336 *tdata++ = '.'; 1337 trem--; 1338 } 1339 1340 if (nlen != 0 && trem == 0) 1341 return (ISC_R_NOSPACE); 1342 1343 if (!saw_root || omit_final_dot) 1344 trem++; 1345 1346 isc_buffer_add(target, tlen - trem); 1347 1348 return (ISC_R_SUCCESS); 1349} 1350 1351isc_result_t 1352dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot, 1353 isc_buffer_t *target) 1354{ 1355 unsigned char *ndata; 1356 char *tdata; 1357 unsigned int nlen, tlen; 1358 unsigned char c; 1359 unsigned int trem, count; 1360 unsigned int labels; 1361 1362 /* 1363 * This function assumes the name is in proper uncompressed 1364 * wire format. 1365 */ 1366 REQUIRE(VALID_NAME(name)); 1367 REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0); 1368 REQUIRE(ISC_BUFFER_VALID(target)); 1369 1370 ndata = name->ndata; 1371 nlen = name->length; 1372 labels = name->labels; 1373 tdata = isc_buffer_used(target); 1374 tlen = isc_buffer_availablelength(target); 1375 1376 trem = tlen; 1377 1378 if (nlen == 1 && labels == 1 && *ndata == '\0') { 1379 /* 1380 * Special handling for the root label. 1381 */ 1382 if (trem == 0) 1383 return (ISC_R_NOSPACE); 1384 1385 omit_final_dot = ISC_FALSE; 1386 *tdata++ = '.'; 1387 trem--; 1388 1389 /* 1390 * Skip the while() loop. 1391 */ 1392 nlen = 0; 1393 } 1394 1395 while (labels > 0 && nlen > 0 && trem > 0) { 1396 labels--; 1397 count = *ndata++; 1398 nlen--; 1399 if (count == 0) 1400 break; 1401 if (count < 64) { 1402 INSIST(nlen >= count); 1403 while (count > 0) { 1404 c = *ndata; 1405 if ((c >= 0x30 && c <= 0x39) || /* digit */ 1406 (c >= 0x41 && c <= 0x5A) || /* uppercase */ 1407 (c >= 0x61 && c <= 0x7A) || /* lowercase */ 1408 c == 0x2D || /* hyphen */ 1409 c == 0x5F) /* underscore */ 1410 { 1411 if (trem == 0) 1412 return (ISC_R_NOSPACE); 1413 /* downcase */ 1414 if (c >= 0x41 && c <= 0x5A) 1415 c += 0x20; 1416 CONVERTFROMASCII(c); 1417 *tdata++ = c; 1418 ndata++; 1419 trem--; 1420 nlen--; 1421 } else { 1422 if (trem < 3) 1423 return (ISC_R_NOSPACE); 1424 sprintf(tdata, "%%%02X", c); 1425 tdata += 3; 1426 trem -= 3; 1427 ndata++; 1428 nlen--; 1429 } 1430 count--; 1431 } 1432 } else { 1433 FATAL_ERROR(__FILE__, __LINE__, 1434 "Unexpected label type %02x", count); 1435 /* NOTREACHED */ 1436 } 1437 1438 /* 1439 * The following assumes names are absolute. If not, we 1440 * fix things up later. Note that this means that in some 1441 * cases one more byte of text buffer is required than is 1442 * needed in the final output. 1443 */ 1444 if (trem == 0) 1445 return (ISC_R_NOSPACE); 1446 *tdata++ = '.'; 1447 trem--; 1448 } 1449 1450 if (nlen != 0 && trem == 0) 1451 return (ISC_R_NOSPACE); 1452 1453 if (omit_final_dot) 1454 trem++; 1455 1456 isc_buffer_add(target, tlen - trem); 1457 1458 return (ISC_R_SUCCESS); 1459} 1460 1461isc_result_t 1462dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) { 1463 unsigned char *sndata, *ndata; 1464 unsigned int nlen, count, labels; 1465 isc_buffer_t buffer; 1466 1467 /* 1468 * Downcase 'source'. 1469 */ 1470 1471 REQUIRE(VALID_NAME(source)); 1472 REQUIRE(VALID_NAME(name)); 1473 if (source == name) { 1474 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0); 1475 isc_buffer_init(&buffer, source->ndata, source->length); 1476 target = &buffer; 1477 ndata = source->ndata; 1478 } else { 1479 REQUIRE(BINDABLE(name)); 1480 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1481 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1482 if (target == NULL) { 1483 target = name->buffer; 1484 isc_buffer_clear(name->buffer); 1485 } 1486 ndata = (unsigned char *)target->base + target->used; 1487 name->ndata = ndata; 1488 } 1489 1490 sndata = source->ndata; 1491 nlen = source->length; 1492 labels = source->labels; 1493 1494 if (nlen > (target->length - target->used)) { 1495 MAKE_EMPTY(name); 1496 return (ISC_R_NOSPACE); 1497 } 1498 1499 while (labels > 0 && nlen > 0) { 1500 labels--; 1501 count = *sndata++; 1502 *ndata++ = count; 1503 nlen--; 1504 if (count < 64) { 1505 INSIST(nlen >= count); 1506 while (count > 0) { 1507 *ndata++ = maptolower[(*sndata++)]; 1508 nlen--; 1509 count--; 1510 } 1511 } else { 1512 FATAL_ERROR(__FILE__, __LINE__, 1513 "Unexpected label type %02x", count); 1514 /* Does not return. */ 1515 } 1516 } 1517 1518 if (source != name) { 1519 name->labels = source->labels; 1520 name->length = source->length; 1521 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1522 name->attributes = DNS_NAMEATTR_ABSOLUTE; 1523 else 1524 name->attributes = 0; 1525 if (name->labels > 0 && name->offsets != NULL) 1526 set_offsets(name, name->offsets, NULL); 1527 } 1528 1529 isc_buffer_add(target, name->length); 1530 1531 return (ISC_R_SUCCESS); 1532} 1533 1534static void 1535set_offsets(const dns_name_t *name, unsigned char *offsets, 1536 dns_name_t *set_name) 1537{ 1538 unsigned int offset, count, length, nlabels; 1539 unsigned char *ndata; 1540 isc_boolean_t absolute; 1541 1542 ndata = name->ndata; 1543 length = name->length; 1544 offset = 0; 1545 nlabels = 0; 1546 absolute = ISC_FALSE; 1547 while (offset != length) { 1548 INSIST(nlabels < 128); 1549 offsets[nlabels++] = offset; 1550 count = *ndata++; 1551 offset++; 1552 INSIST(count <= 63); 1553 offset += count; 1554 ndata += count; 1555 INSIST(offset <= length); 1556 if (count == 0) { 1557 absolute = ISC_TRUE; 1558 break; 1559 } 1560 } 1561 if (set_name != NULL) { 1562 INSIST(set_name == name); 1563 1564 set_name->labels = nlabels; 1565 set_name->length = offset; 1566 if (absolute) 1567 set_name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1568 else 1569 set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; 1570 } 1571 INSIST(nlabels == name->labels); 1572 INSIST(offset == name->length); 1573} 1574 1575isc_result_t 1576dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, 1577 dns_decompress_t *dctx, unsigned int options, 1578 isc_buffer_t *target) 1579{ 1580 unsigned char *cdata, *ndata; 1581 unsigned int cused; /* Bytes of compressed name data used */ 1582 unsigned int hops, nused, labels, n, nmax; 1583 unsigned int current, new_current, biggest_pointer; 1584 isc_boolean_t done; 1585 fw_state state = fw_start; 1586 unsigned int c; 1587 unsigned char *offsets; 1588 dns_offsets_t odata; 1589 isc_boolean_t downcase; 1590 1591 /* 1592 * Copy the possibly-compressed name at source into target, 1593 * decompressing it. 1594 */ 1595 1596 REQUIRE(VALID_NAME(name)); 1597 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1598 (target == NULL && ISC_BUFFER_VALID(name->buffer))); 1599 1600 downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0); 1601 1602 if (target == NULL && name->buffer != NULL) { 1603 target = name->buffer; 1604 isc_buffer_clear(target); 1605 } 1606 1607 REQUIRE(dctx != NULL); 1608 REQUIRE(BINDABLE(name)); 1609 1610 INIT_OFFSETS(name, offsets, odata); 1611 1612 /* 1613 * Make 'name' empty in case of failure. 1614 */ 1615 MAKE_EMPTY(name); 1616 1617 /* 1618 * Initialize things to make the compiler happy; they're not required. 1619 */ 1620 n = 0; 1621 new_current = 0; 1622 1623 /* 1624 * Set up. 1625 */ 1626 labels = 0; 1627 hops = 0; 1628 done = ISC_FALSE; 1629 1630 ndata = isc_buffer_used(target); 1631 nused = 0; 1632 1633 /* 1634 * Find the maximum number of uncompressed target name 1635 * bytes we are willing to generate. This is the smaller 1636 * of the available target buffer length and the 1637 * maximum legal domain name length (255). 1638 */ 1639 nmax = isc_buffer_availablelength(target); 1640 if (nmax > DNS_NAME_MAXWIRE) 1641 nmax = DNS_NAME_MAXWIRE; 1642 1643 cdata = isc_buffer_current(source); 1644 cused = 0; 1645 1646 current = source->current; 1647 biggest_pointer = current; 1648 1649 /* 1650 * Note: The following code is not optimized for speed, but 1651 * rather for correctness. Speed will be addressed in the future. 1652 */ 1653 1654 while (current < source->active && !done) { 1655 c = *cdata++; 1656 current++; 1657 if (hops == 0) 1658 cused++; 1659 1660 switch (state) { 1661 case fw_start: 1662 if (c < 64) { 1663 offsets[labels] = nused; 1664 labels++; 1665 if (nused + c + 1 > nmax) 1666 goto full; 1667 nused += c + 1; 1668 *ndata++ = c; 1669 if (c == 0) 1670 done = ISC_TRUE; 1671 n = c; 1672 state = fw_ordinary; 1673 } else if (c >= 128 && c < 192) { 1674 /* 1675 * 14 bit local compression pointer. 1676 * Local compression is no longer an 1677 * IETF draft. 1678 */ 1679 return (DNS_R_BADLABELTYPE); 1680 } else if (c >= 192) { 1681 /* 1682 * Ordinary 14-bit pointer. 1683 */ 1684 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 1685 0) 1686 return (DNS_R_DISALLOWED); 1687 new_current = c & 0x3F; 1688 n = 1; 1689 state = fw_newcurrent; 1690 } else 1691 return (DNS_R_BADLABELTYPE); 1692 break; 1693 case fw_ordinary: 1694 if (downcase) 1695 c = maptolower[c]; 1696 /* FALLTHROUGH */ 1697 case fw_copy: 1698 *ndata++ = c; 1699 n--; 1700 if (n == 0) 1701 state = fw_start; 1702 break; 1703 case fw_newcurrent: 1704 new_current *= 256; 1705 new_current += c; 1706 n--; 1707 if (n != 0) 1708 break; 1709 if (new_current >= biggest_pointer) 1710 return (DNS_R_BADPOINTER); 1711 biggest_pointer = new_current; 1712 current = new_current; 1713 cdata = (unsigned char *)source->base + 1714 current; 1715 hops++; 1716 if (hops > DNS_POINTER_MAXHOPS) 1717 return (DNS_R_TOOMANYHOPS); 1718 state = fw_start; 1719 break; 1720 default: 1721 FATAL_ERROR(__FILE__, __LINE__, 1722 "Unknown state %d", state); 1723 /* Does not return. */ 1724 } 1725 } 1726 1727 if (!done) 1728 return (ISC_R_UNEXPECTEDEND); 1729 1730 name->ndata = (unsigned char *)target->base + target->used; 1731 name->labels = labels; 1732 name->length = nused; 1733 name->attributes |= DNS_NAMEATTR_ABSOLUTE; 1734 1735 isc_buffer_forward(source, cused); 1736 isc_buffer_add(target, name->length); 1737 1738 return (ISC_R_SUCCESS); 1739 1740 full: 1741 if (nmax == DNS_NAME_MAXWIRE) 1742 /* 1743 * The name did not fit even though we had a buffer 1744 * big enough to fit a maximum-length name. 1745 */ 1746 return (DNS_R_NAMETOOLONG); 1747 else 1748 /* 1749 * The name might fit if only the caller could give us a 1750 * big enough buffer. 1751 */ 1752 return (ISC_R_NOSPACE); 1753 1754} 1755 1756isc_result_t 1757dns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) { 1758 unsigned int methods; 1759 isc_uint16_t offset; 1760 dns_name_t gp; /* Global compression prefix */ 1761 isc_boolean_t gf; /* Global compression target found */ 1762 isc_uint16_t go; /* Global compression offset */ 1763 dns_offsets_t clo; 1764 dns_name_t clname; 1765 1766 /* 1767 * Convert 'name' into wire format, compressing it as specified by the 1768 * compression context 'cctx', and storing the result in 'target'. 1769 */ 1770 1771 REQUIRE(VALID_NAME(name)); 1772 REQUIRE(cctx != NULL); 1773 REQUIRE(ISC_BUFFER_VALID(target)); 1774 1775 /* 1776 * If 'name' doesn't have an offsets table, make a clone which 1777 * has one. 1778 */ 1779 if (name->offsets == NULL) { 1780 DNS_NAME_INIT(&clname, clo); 1781 dns_name_clone(name, &clname); 1782 name = &clname; 1783 } 1784 DNS_NAME_INIT(&gp, NULL); 1785 1786 offset = target->used; /*XXX*/ 1787 1788 methods = dns_compress_getmethods(cctx); 1789 1790 if ((methods & DNS_COMPRESS_GLOBAL14) != 0) 1791 gf = dns_compress_findglobal(cctx, name, &gp, &go); 1792 else 1793 gf = ISC_FALSE; 1794 1795 /* 1796 * If the offset is too high for 14 bit global compression, we're 1797 * out of luck. 1798 */ 1799 if (gf && go >= 0x4000) 1800 gf = ISC_FALSE; 1801 1802 /* 1803 * Will the compression pointer reduce the message size? 1804 */ 1805 if (gf && (gp.length + 2) >= name->length) 1806 gf = ISC_FALSE; 1807 1808 if (gf) { 1809 if (target->length - target->used < gp.length) 1810 return (ISC_R_NOSPACE); 1811 (void)memcpy((unsigned char *)target->base + target->used, 1812 gp.ndata, (size_t)gp.length); 1813 isc_buffer_add(target, gp.length); 1814 go |= 0xc000; 1815 if (target->length - target->used < 2) 1816 return (ISC_R_NOSPACE); 1817 isc_buffer_putuint16(target, go); 1818 if (gp.length != 0) 1819 dns_compress_add(cctx, name, &gp, offset); 1820 } else { 1821 if (target->length - target->used < name->length) 1822 return (ISC_R_NOSPACE); 1823 (void)memcpy((unsigned char *)target->base + target->used, 1824 name->ndata, (size_t)name->length); 1825 isc_buffer_add(target, name->length); 1826 dns_compress_add(cctx, name, name, offset); 1827 } 1828 return (ISC_R_SUCCESS); 1829} 1830 1831isc_result_t 1832dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, 1833 isc_buffer_t *target) 1834{ 1835 unsigned char *ndata, *offsets; 1836 unsigned int nrem, labels, prefix_length, length; 1837 isc_boolean_t copy_prefix = ISC_TRUE; 1838 isc_boolean_t copy_suffix = ISC_TRUE; 1839 isc_boolean_t absolute = ISC_FALSE; 1840 dns_name_t tmp_name; 1841 dns_offsets_t odata; 1842 1843 /* 1844 * Concatenate 'prefix' and 'suffix'. 1845 */ 1846 1847 REQUIRE(prefix == NULL || VALID_NAME(prefix)); 1848 REQUIRE(suffix == NULL || VALID_NAME(suffix)); 1849 REQUIRE(name == NULL || VALID_NAME(name)); 1850 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || 1851 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer))); 1852 if (prefix == NULL || prefix->labels == 0) 1853 copy_prefix = ISC_FALSE; 1854 if (suffix == NULL || suffix->labels == 0) 1855 copy_suffix = ISC_FALSE; 1856 if (copy_prefix && 1857 (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { 1858 absolute = ISC_TRUE; 1859 REQUIRE(!copy_suffix); 1860 } 1861 if (name == NULL) { 1862 DNS_NAME_INIT(&tmp_name, odata); 1863 name = &tmp_name; 1864 } 1865 if (target == NULL) { 1866 INSIST(name->buffer != NULL); 1867 target = name->buffer; 1868 isc_buffer_clear(name->buffer); 1869 } 1870 1871 REQUIRE(BINDABLE(name)); 1872 1873 /* 1874 * Set up. 1875 */ 1876 nrem = target->length - target->used; 1877 ndata = (unsigned char *)target->base + target->used; 1878 if (nrem > DNS_NAME_MAXWIRE) 1879 nrem = DNS_NAME_MAXWIRE; 1880 length = 0; 1881 prefix_length = 0; 1882 labels = 0; 1883 if (copy_prefix) { 1884 prefix_length = prefix->length; 1885 length += prefix_length; 1886 labels += prefix->labels; 1887 } 1888 if (copy_suffix) { 1889 length += suffix->length; 1890 labels += suffix->labels; 1891 } 1892 if (length > DNS_NAME_MAXWIRE) { 1893 MAKE_EMPTY(name); 1894 return (DNS_R_NAMETOOLONG); 1895 } 1896 if (length > nrem) { 1897 MAKE_EMPTY(name); 1898 return (ISC_R_NOSPACE); 1899 } 1900 1901 if (copy_suffix) { 1902 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1903 absolute = ISC_TRUE; 1904 if (suffix == name && suffix->buffer == target) 1905 memmove(ndata + prefix_length, suffix->ndata, 1906 suffix->length); 1907 else 1908 memcpy(ndata + prefix_length, suffix->ndata, 1909 suffix->length); 1910 } 1911 1912 /* 1913 * If 'prefix' and 'name' are the same object, and the object has 1914 * a dedicated buffer, and we're using it, then we don't have to 1915 * copy anything. 1916 */ 1917 if (copy_prefix && (prefix != name || prefix->buffer != target)) 1918 memcpy(ndata, prefix->ndata, prefix_length); 1919 1920 name->ndata = ndata; 1921 name->labels = labels; 1922 name->length = length; 1923 if (absolute) 1924 name->attributes = DNS_NAMEATTR_ABSOLUTE; 1925 else 1926 name->attributes = 0; 1927 1928 if (name->labels > 0 && name->offsets != NULL) { 1929 INIT_OFFSETS(name, offsets, odata); 1930 set_offsets(name, offsets, NULL); 1931 } 1932 1933 isc_buffer_add(target, name->length); 1934 1935 return (ISC_R_SUCCESS); 1936} 1937 1938void 1939dns_name_split(dns_name_t *name, unsigned int suffixlabels, 1940 dns_name_t *prefix, dns_name_t *suffix) 1941 1942{ 1943 unsigned int splitlabel; 1944 1945 REQUIRE(VALID_NAME(name)); 1946 REQUIRE(suffixlabels > 0); 1947 REQUIRE(suffixlabels < name->labels); 1948 REQUIRE(prefix != NULL || suffix != NULL); 1949 REQUIRE(prefix == NULL || 1950 (VALID_NAME(prefix) && 1951 prefix->buffer != NULL && 1952 BINDABLE(prefix))); 1953 REQUIRE(suffix == NULL || 1954 (VALID_NAME(suffix) && 1955 suffix->buffer != NULL && 1956 BINDABLE(suffix))); 1957 1958 splitlabel = name->labels - suffixlabels; 1959 1960 if (prefix != NULL) 1961 dns_name_getlabelsequence(name, 0, splitlabel, prefix); 1962 1963 if (suffix != NULL) 1964 dns_name_getlabelsequence(name, splitlabel, 1965 suffixlabels, suffix); 1966 1967 return; 1968} 1969 1970isc_result_t 1971dns_name_dup(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) { 1972 /* 1973 * Make 'target' a dynamically allocated copy of 'source'. 1974 */ 1975 1976 REQUIRE(VALID_NAME(source)); 1977 REQUIRE(source->length > 0); 1978 REQUIRE(VALID_NAME(target)); 1979 REQUIRE(BINDABLE(target)); 1980 1981 /* 1982 * Make 'target' empty in case of failure. 1983 */ 1984 MAKE_EMPTY(target); 1985 1986 target->ndata = isc_mem_get(mctx, source->length); 1987 if (target->ndata == NULL) 1988 return (ISC_R_NOMEMORY); 1989 1990 memcpy(target->ndata, source->ndata, source->length); 1991 1992 target->length = source->length; 1993 target->labels = source->labels; 1994 target->attributes = DNS_NAMEATTR_DYNAMIC; 1995 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 1996 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 1997 if (target->offsets != NULL) { 1998 if (source->offsets != NULL) 1999 memcpy(target->offsets, source->offsets, 2000 source->labels); 2001 else 2002 set_offsets(target, target->offsets, NULL); 2003 } 2004 2005 return (ISC_R_SUCCESS); 2006} 2007 2008isc_result_t 2009dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx, 2010 dns_name_t *target) 2011{ 2012 /* 2013 * Make 'target' a read-only dynamically allocated copy of 'source'. 2014 * 'target' will also have a dynamically allocated offsets table. 2015 */ 2016 2017 REQUIRE(VALID_NAME(source)); 2018 REQUIRE(source->length > 0); 2019 REQUIRE(VALID_NAME(target)); 2020 REQUIRE(BINDABLE(target)); 2021 REQUIRE(target->offsets == NULL); 2022 2023 /* 2024 * Make 'target' empty in case of failure. 2025 */ 2026 MAKE_EMPTY(target); 2027 2028 target->ndata = isc_mem_get(mctx, source->length + source->labels); 2029 if (target->ndata == NULL) 2030 return (ISC_R_NOMEMORY); 2031 2032 memcpy(target->ndata, source->ndata, source->length); 2033 2034 target->length = source->length; 2035 target->labels = source->labels; 2036 target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS | 2037 DNS_NAMEATTR_READONLY; 2038 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2039 target->attributes |= DNS_NAMEATTR_ABSOLUTE; 2040 target->offsets = target->ndata + source->length; 2041 if (source->offsets != NULL) 2042 memcpy(target->offsets, source->offsets, source->labels); 2043 else 2044 set_offsets(target, target->offsets, NULL); 2045 2046 return (ISC_R_SUCCESS); 2047} 2048 2049void 2050dns_name_free(dns_name_t *name, isc_mem_t *mctx) { 2051 size_t size; 2052 2053 /* 2054 * Free 'name'. 2055 */ 2056 2057 REQUIRE(VALID_NAME(name)); 2058 REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0); 2059 2060 size = name->length; 2061 if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0) 2062 size += name->labels; 2063 isc_mem_put(mctx, name->ndata, size); 2064 dns_name_invalidate(name); 2065} 2066 2067isc_result_t 2068dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) { 2069 dns_name_t downname; 2070 unsigned char data[256]; 2071 isc_buffer_t buffer; 2072 isc_result_t result; 2073 isc_region_t r; 2074 2075 /* 2076 * Send 'name' in DNSSEC canonical form to 'digest'. 2077 */ 2078 2079 REQUIRE(VALID_NAME(name)); 2080 REQUIRE(digest != NULL); 2081 2082 DNS_NAME_INIT(&downname, NULL); 2083 isc_buffer_init(&buffer, data, sizeof(data)); 2084 2085 result = dns_name_downcase(name, &downname, &buffer); 2086 if (result != ISC_R_SUCCESS) 2087 return (result); 2088 2089 isc_buffer_usedregion(&buffer, &r); 2090 2091 return ((digest)(arg, &r)); 2092} 2093 2094isc_boolean_t 2095dns_name_dynamic(dns_name_t *name) { 2096 REQUIRE(VALID_NAME(name)); 2097 2098 /* 2099 * Returns whether there is dynamic memory associated with this name. 2100 */ 2101 2102 return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ? 2103 ISC_TRUE : ISC_FALSE); 2104} 2105 2106isc_result_t 2107dns_name_print(dns_name_t *name, FILE *stream) { 2108 isc_result_t result; 2109 isc_buffer_t b; 2110 isc_region_t r; 2111 char t[1024]; 2112 2113 /* 2114 * Print 'name' on 'stream'. 2115 */ 2116 2117 REQUIRE(VALID_NAME(name)); 2118 2119 isc_buffer_init(&b, t, sizeof(t)); 2120 result = dns_name_totext(name, ISC_FALSE, &b); 2121 if (result != ISC_R_SUCCESS) 2122 return (result); 2123 isc_buffer_usedregion(&b, &r); 2124 fprintf(stream, "%.*s", (int)r.length, (char *)r.base); 2125 2126 return (ISC_R_SUCCESS); 2127} 2128 2129void 2130dns_name_format(dns_name_t *name, char *cp, unsigned int size) { 2131 isc_result_t result; 2132 isc_buffer_t buf; 2133 2134 REQUIRE(size > 0); 2135 2136 /* 2137 * Leave room for null termination after buffer. 2138 */ 2139 isc_buffer_init(&buf, cp, size - 1); 2140 result = dns_name_totext(name, ISC_TRUE, &buf); 2141 if (result == ISC_R_SUCCESS) { 2142 /* 2143 * Null terminate. 2144 */ 2145 isc_region_t r; 2146 isc_buffer_usedregion(&buf, &r); 2147 ((char *) r.base)[r.length] = '\0'; 2148 2149 } else 2150 snprintf(cp, size, "<unknown>"); 2151} 2152 2153isc_result_t 2154dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) { 2155 unsigned char *ndata; 2156 2157 /* 2158 * Make dest a copy of source. 2159 */ 2160 2161 REQUIRE(VALID_NAME(source)); 2162 REQUIRE(VALID_NAME(dest)); 2163 REQUIRE(target != NULL || dest->buffer != NULL); 2164 2165 if (target == NULL) { 2166 target = dest->buffer; 2167 isc_buffer_clear(dest->buffer); 2168 } 2169 2170 REQUIRE(BINDABLE(dest)); 2171 2172 /* 2173 * Set up. 2174 */ 2175 if (target->length - target->used < source->length) 2176 return (ISC_R_NOSPACE); 2177 2178 ndata = (unsigned char *)target->base + target->used; 2179 dest->ndata = target->base; 2180 2181 memcpy(ndata, source->ndata, source->length); 2182 2183 dest->ndata = ndata; 2184 dest->labels = source->labels; 2185 dest->length = source->length; 2186 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) 2187 dest->attributes = DNS_NAMEATTR_ABSOLUTE; 2188 else 2189 dest->attributes = 0; 2190 2191 if (dest->labels > 0 && dest->offsets != NULL) { 2192 if (source->offsets != NULL) 2193 memcpy(dest->offsets, source->offsets, source->labels); 2194 else 2195 set_offsets(dest, dest->offsets, NULL); 2196 } 2197 2198 isc_buffer_add(target, dest->length); 2199 2200 return (ISC_R_SUCCESS); 2201} 2202 2203