name.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1998-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id$ */
00019 
00020 /*! \file */
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, /*16*/
00061         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
00062         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
00063          0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
00064         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
00065         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
00066         -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
00067         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
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, /*256*/
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  * Note:  If additional attributes are added that should not be set for
00132  *        empty names, MAKE_EMPTY() must be changed so it clears them.
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  * A name is "bindable" if it can be set to point to a new value, i.e.
00144  * name->ndata and name->length may be changed.
00145  */
00146 #define BINDABLE(name) \
00147         ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
00148          == 0)
00149 
00150 /*%
00151  * Note that the name data must be a char array, not a string
00152  * literal, to avoid compiler warnings about discarding
00153  * the const attribute of a string.
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 /* XXXDCL make const? */
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 /* XXXDCL make const? */
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  * dns_name_t to text post-conversion procedure.
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          * Initialize 'name'.
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          * Make 'name' invalid.
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          * Dedicate a buffer for use with 'name'.
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          * Does 'name' have a dedicated buffer?
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          * Does 'name' end in the root label?
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          * Root label.
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          * RFC292/RFC1123 hostname.
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          * Root label.
00393          */
00394         if (name->length == 1)
00395                 return (ISC_TRUE);
00396 
00397         /*
00398          * Skip wildcard if this is a ownername.
00399          */
00400         ndata = name->ndata;
00401         if (wildcard && ndata[0] == 1 && ndata[1] == '*')
00402                 ndata += 2;
00403 
00404         /*
00405          * RFC292/RFC1123 hostname.
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          * Is 'name' a wildcard name?
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          * Does 'name' contain a internal wildcard?
00454          */
00455 
00456         REQUIRE(VALID_NAME(name));
00457         REQUIRE(name->labels > 0);
00458 
00459         /*
00460          * Skip first label.
00461          */
00462         ndata = name->ndata;
00463         count = *ndata++;
00464         INSIST(count <= 63);
00465         ndata += count;
00466         label = 1;
00467         /*
00468          * Check all but the last of the remaining labels.
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          * This hash function is similar to the one Ousterhout
00494          * uses in Tcl.
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          * Provide a hash value for 'name'.
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          * Provide a hash value for 'name'.
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          * This function was deprecated due to the breakage of the name space
00546          * convention.  We only keep this internally to provide binary backward
00547          * compatibility.
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          * Provide a hash value for 'name'.
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          * Determine the relative ordering under the DNSSEC order relation of
00601          * 'name1' and 'name2', and also determine the hierarchical
00602          * relationship of the names.
00603          *
00604          * Note: It makes no sense for one of the names to be relative and the
00605          * other absolute.  If both names are relative, then to be meaningfully
00606          * compared the caller must ensure that they are both relative to the
00607          * same domain.
00608          */
00609 
00610         REQUIRE(VALID_NAME(name1));
00611         REQUIRE(VALID_NAME(name2));
00612         REQUIRE(orderp != NULL);
00613         REQUIRE(nlabelsp != NULL);
00614         /*
00615          * Either name1 is absolute and name2 is absolute, or neither is.
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                  * We dropped bitstring labels, and we don't support any
00651                  * other extended label types.
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          * Determine the relative ordering under the DNSSEC order relation of
00703          * 'name1' and 'name2'.
00704          *
00705          * Note: It makes no sense for one of the names to be relative and the
00706          * other absolute.  If both names are relative, then to be meaningfully
00707          * compared the caller must ensure that they are both relative to the
00708          * same domain.
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          * Are 'name1' and 'name2' equal?
00724          *
00725          * Note: It makes no sense for one of the names to be relative and the
00726          * other absolute.  If both names are relative, then to be meaningfully
00727          * compared the caller must ensure that they are both relative to the
00728          * same domain.
00729          */
00730 
00731         REQUIRE(VALID_NAME(name1));
00732         REQUIRE(VALID_NAME(name2));
00733         /*
00734          * Either name1 is absolute and name2 is absolute, or neither is.
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); /* no bitstring support */
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          * Are 'name1' and 'name2' equal?
00776          *
00777          * Note: It makes no sense for one of the names to be relative and the
00778          * other absolute.  If both names are relative, then to be meaningfully
00779          * compared the caller must ensure that they are both relative to the
00780          * same domain.
00781          */
00782 
00783         REQUIRE(VALID_NAME(name1));
00784         REQUIRE(VALID_NAME(name2));
00785         /*
00786          * Either name1 is absolute and name2 is absolute, or neither is.
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          * Compare two absolute names as rdata.
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                 /* no bitstring support */
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          * If one name had more labels than the other, their common
00848          * prefix must have been different because the shorter name
00849          * ended with the root label and the longer one can't have
00850          * a root label in the middle of it.  Therefore, if we get
00851          * to this point, the lengths must be equal.
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          * Is 'name1' a subdomain of 'name2'?
00866          *
00867          * Note: It makes no sense for one of the names to be relative and the
00868          * other absolute.  If both names are relative, then to be meaningfully
00869          * compared the caller must ensure that they are both relative to the
00870          * same domain.
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          * How many labels does 'name' have?
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          * Make 'label' refer to the 'n'th least significant label of 'name'.
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          * Make 'target' refer to the 'n' labels including and following
00953          * 'first' in 'source'.
00954          */
00955 
00956         REQUIRE(VALID_NAME(source));
00957         REQUIRE(VALID_NAME(target));
00958         REQUIRE(first <= source->labels);
00959         REQUIRE(n <= source->labels - first); /* note first+n could overflow */
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          * If source and target are the same, and we're making target
00987          * a prefix of source, the offsets table is correct already
00988          * so we don't need to call set_offsets().
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          * Make 'target' refer to the same name as 'source'.
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          * Make 'name' refer to region 'r'.
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          * Make 'r' refer to 'name'.
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          * Convert the textual representation of a DNS name at source
01095          * into uncompressed wire form stored in target.
01096          *
01097          * Notes:
01098          *      Relative domain names will have 'origin' appended to them
01099          *      unless 'origin' is NULL, in which case relative domain names
01100          *      will remain relative.
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          * Make 'name' empty in case of failure.
01122          */
01123         MAKE_EMPTY(name);
01124 
01125         /*
01126          * Set up the state machine.
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                          * Is this the root name?
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                         /* FALLTHROUGH */
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                         /* FALLTHROUGH */
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                                  * This looks like a bitstring label, which
01214                                  * was deprecated.  Intentionally drop it.
01215                                  */
01216                                 return (DNS_R_BADLABELTYPE);
01217                         }
01218                         state = ft_escape;
01219                         POST(state);
01220                         /* FALLTHROUGH */
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                         /* FALLTHROUGH */
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                         /* Does not return. */
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); /* no bitstring support */
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         /* Stop use being called again. */
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          * We need the call to isc_once_do() to support profiled mutex
01341          * otherwise thread_key_mutex could be initialized at compile time.
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          * This function assumes the name is in proper uncompressed
01408          * wire format.
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                  * Special handling for an empty name.
01429                  */
01430                 if (trem == 0)
01431                         return (ISC_R_NOSPACE);
01432 
01433                 /*
01434                  * The names of these booleans are misleading in this case.
01435                  * This empty name is not necessarily from the root node of
01436                  * the DNS root zone, nor is a final dot going to be included.
01437                  * They need to be set this way, though, to keep the "@"
01438                  * from being trounced.
01439                  */
01440                 saw_root = ISC_TRUE;
01441                 omit_final_dot = ISC_FALSE;
01442                 *tdata++ = '@';
01443                 trem--;
01444 
01445                 /*
01446                  * Skip the while() loop.
01447                  */
01448                 nlen = 0;
01449         } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
01450                 /*
01451                  * Special handling for the root label.
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                  * Skip the while() loop.
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                                 /* Special modifiers in zone files. */
01481                                 case 0x40: /* '@' */
01482                                 case 0x24: /* '$' */
01483                                         if ((options & DNS_NAME_MASTERFILE) == 0)
01484                                                 goto no_escape;
01485                                         /* FALLTHROUGH */
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                         /* NOTREACHED */
01531                 }
01532 
01533                 /*
01534                  * The following assumes names are absolute.  If not, we
01535                  * fix things up later.  Note that this means that in some
01536                  * cases one more byte of text buffer is required than is
01537                  * needed in the final output.
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          * This function assumes the name is in proper uncompressed
01577          * wire format.
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                  * Special handling for the root label.
01594                  */
01595                 if (trem == 0)
01596                         return (ISC_R_NOSPACE);
01597 
01598                 omit_final_dot = ISC_FALSE;
01599                 *tdata++ = '.';
01600                 trem--;
01601 
01602                 /*
01603                  * Skip the while() loop.
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) || /* digit */
01619                                     (c >= 0x41 && c <= 0x5A) || /* uppercase */
01620                                     (c >= 0x61 && c <= 0x7A) || /* lowercase */
01621                                     c == 0x2D ||                /* hyphen */
01622                                     c == 0x5F)                  /* underscore */
01623                                 {
01624                                         if (trem == 0)
01625                                                 return (ISC_R_NOSPACE);
01626                                         /* downcase */
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                         /* NOTREACHED */
01649                 }
01650 
01651                 /*
01652                  * The following assumes names are absolute.  If not, we
01653                  * fix things up later.  Note that this means that in some
01654                  * cases one more byte of text buffer is required than is
01655                  * needed in the final output.
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          * Downcase 'source'.
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                         /* Does not return. */
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; /* Bytes of compressed name data used */
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          * Copy the possibly-compressed name at source into target,
01807          * decompressing it.  Loop prevention is performed by checking
01808          * the new pointer against biggest_pointer.
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          * Make 'name' empty in case of failure.
01829          */
01830         MAKE_EMPTY(name);
01831 
01832         /*
01833          * Initialize things to make the compiler happy; they're not required.
01834          */
01835         n = 0;
01836         new_current = 0;
01837 
01838         /*
01839          * Set up.
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          * Find the maximum number of uncompressed target name
01850          * bytes we are willing to generate.  This is the smaller
01851          * of the available target buffer length and the
01852          * maximum legal domain name length (255).
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          * Note:  The following code is not optimized for speed, but
01866          * rather for correctness.  Speed will be addressed in the future.
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                                  * 14 bit local compression pointer.
01891                                  * Local compression is no longer an
01892                                  * IETF draft.
01893                                  */
01894                                 return (DNS_R_BADLABELTYPE);
01895                         } else if (c >= 192) {
01896                                 /*
01897                                  * Ordinary 14-bit pointer.
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                         /* Does not return. */
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                  * The name did not fit even though we had a buffer
01950                  * big enough to fit a maximum-length name.
01951                  */
01952                 return (DNS_R_NAMETOOLONG);
01953         else
01954                 /*
01955                  * The name might fit if only the caller could give us a
01956                  * big enough buffer.
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;  /* Global compression prefix */
01968         isc_boolean_t gf;       /* Global compression target found */
01969         isc_uint16_t go;        /* Global compression offset */
01970         dns_offsets_t clo;
01971         dns_name_t clname;
01972 
01973         /*
01974          * Convert 'name' into wire format, compressing it as specified by the
01975          * compression context 'cctx', and storing the result in 'target'.
01976          */
01977 
01978         REQUIRE(VALID_NAME(name));
01979         REQUIRE(cctx != NULL);
01980         REQUIRE(ISC_BUFFER_VALID(target));
01981 
01982         /*
01983          * If 'name' doesn't have an offsets table, make a clone which
01984          * has one.
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;  /*XXX*/
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          * If the offset is too high for 14 bit global compression, we're
02009          * out of luck.
02010          */
02011         if (gf && go >= 0x4000)
02012                 gf = ISC_FALSE;
02013 
02014         /*
02015          * Will the compression pointer reduce the message size?
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          * Concatenate 'prefix' and 'suffix'.
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          * Set up.
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          * If 'prefix' and 'name' are the same object, and the object has
02121          * a dedicated buffer, and we're using it, then we don't have to
02122          * copy anything.
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          * Make 'target' a dynamically allocated copy of 'source'.
02183          */
02184 
02185         REQUIRE(VALID_NAME(source));
02186         REQUIRE(source->length > 0);
02187         REQUIRE(VALID_NAME(target));
02188         REQUIRE(BINDABLE(target));
02189 
02190         /*
02191          * Make 'target' empty in case of failure.
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          * Make 'target' a read-only dynamically allocated copy of 'source'.
02223          * 'target' will also have a dynamically allocated offsets table.
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          * Make 'target' empty in case of failure.
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          * Free 'name'.
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          * Send 'name' in DNSSEC canonical form to 'digest'.
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          * Returns whether there is dynamic memory associated with this name.
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          * Print 'name' on 'stream'.
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          * If we already have been here set / clear as appropriate.
02356          * Otherwise allocate memory.
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          * Leave room for null termination after buffer.
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                  * Null terminate.
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  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
02412  * memory.
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, &reg);
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  * dns_name_fromstring() -- convert directly from a string to a name,
02442  * allocating memory as needed
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          * Make dest a copy of source.
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          * Set up.
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 }

Generated on Tue Apr 28 17:40:58 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha