"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/name.c" (7 Sep 2020, 64715 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "name.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.3_vs_9.17.4.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 
   13 /*! \file */
   14 
   15 #include <config.h>
   16 
   17 #include <ctype.h>
   18 #include <inttypes.h>
   19 #include <stdbool.h>
   20 #include <stdlib.h>
   21 
   22 #include <isc/buffer.h>
   23 #include <isc/hash.h>
   24 #include <isc/mem.h>
   25 #include <isc/once.h>
   26 #include <isc/print.h>
   27 #include <isc/random.h>
   28 #include <isc/string.h>
   29 #include <isc/thread.h>
   30 #include <isc/util.h>
   31 
   32 #include <dns/compress.h>
   33 #include <dns/fixedname.h>
   34 #include <dns/name.h>
   35 #include <dns/result.h>
   36 
   37 #define VALID_NAME(n)   ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
   38 
   39 typedef enum {
   40     ft_init = 0,
   41     ft_start,
   42     ft_ordinary,
   43     ft_initialescape,
   44     ft_escape,
   45     ft_escdecimal,
   46     ft_at
   47 } ft_state;
   48 
   49 typedef enum {
   50     fw_start = 0,
   51     fw_ordinary,
   52     fw_newcurrent
   53 } fw_state;
   54 
   55 static char digitvalue[256] = {
   56     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
   57     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
   58     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
   59      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
   60     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
   61     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
   62     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
   63     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
   64     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   65     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   66     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   67     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   68     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   69     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   70     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   71     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
   72 };
   73 
   74 static unsigned char maptolower[] = {
   75     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   76     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   77     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   78     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   79     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
   80     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   81     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   82     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   83     0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
   84     0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   85     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
   86     0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   87     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
   88     0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   89     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
   90     0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   91     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
   92     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
   93     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
   94     0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
   95     0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
   96     0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
   97     0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
   98     0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
   99     0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
  100     0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
  101     0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
  102     0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
  103     0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
  104     0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
  105     0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
  106     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
  107 };
  108 
  109 #define CONVERTTOASCII(c)
  110 #define CONVERTFROMASCII(c)
  111 
  112 #define INIT_OFFSETS(name, var, default_offsets) \
  113     if ((name)->offsets != NULL)         \
  114         var = (name)->offsets;       \
  115     else \
  116         var = (default_offsets);
  117 
  118 #define SETUP_OFFSETS(name, var, default_offsets) \
  119     if ((name)->offsets != NULL)          \
  120         var = (name)->offsets;        \
  121     else { \
  122         var = (default_offsets);      \
  123         set_offsets(name, var, NULL); \
  124     }
  125 
  126 /*%
  127  * Note:  If additional attributes are added that should not be set for
  128  *    empty names, MAKE_EMPTY() must be changed so it clears them.
  129  */
  130 #define MAKE_EMPTY(name) \
  131 do { \
  132     name->ndata = NULL; \
  133     name->length = 0; \
  134     name->labels = 0; \
  135     name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
  136 } while (0);
  137 
  138 /*%
  139  * A name is "bindable" if it can be set to point to a new value, i.e.
  140  * name->ndata and name->length may be changed.
  141  */
  142 #define BINDABLE(name) \
  143     ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
  144      == 0)
  145 
  146 /*%
  147  * Note that the name data must be a char array, not a string
  148  * literal, to avoid compiler warnings about discarding
  149  * the const attribute of a string.
  150  */
  151 static unsigned char root_ndata[] = { "" };
  152 static unsigned char root_offsets[] = { 0 };
  153 
  154 static dns_name_t root = DNS_NAME_INITABSOLUTE(root_ndata, root_offsets);
  155 LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
  156 
  157 static unsigned char wild_ndata[] = { "\001*" };
  158 static unsigned char wild_offsets[] = { 0 };
  159 
  160 static dns_name_t wild =
  161     DNS_NAME_INITNONABSOLUTE(wild_ndata, wild_offsets);
  162 
  163 /* XXXDCL make const? */
  164 LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
  165 
  166 unsigned int
  167 dns_fullname_hash(dns_name_t *name, bool case_sensitive);
  168 
  169 /*
  170  * dns_name_t to text post-conversion procedure.
  171  */
  172 #ifdef ISC_PLATFORM_USETHREADS
  173 static int thread_key_initialized = 0;
  174 static isc_mutex_t thread_key_mutex;
  175 static isc_mem_t *thread_key_mctx = NULL;
  176 static isc_thread_key_t totext_filter_proc_key;
  177 static isc_once_t once = ISC_ONCE_INIT;
  178 #else
  179 static dns_name_totextfilter_t totext_filter_proc = NULL;
  180 #endif
  181 
  182 static void
  183 set_offsets(const dns_name_t *name, unsigned char *offsets,
  184         dns_name_t *set_name);
  185 
  186 void
  187 dns_name_init(dns_name_t *name, unsigned char *offsets) {
  188     /*
  189      * Initialize 'name'.
  190      */
  191     DNS_NAME_INIT(name, offsets);
  192 }
  193 
  194 void
  195 dns_name_reset(dns_name_t *name) {
  196     REQUIRE(VALID_NAME(name));
  197     REQUIRE(BINDABLE(name));
  198 
  199     DNS_NAME_RESET(name);
  200 }
  201 
  202 void
  203 dns_name_invalidate(dns_name_t *name) {
  204     /*
  205      * Make 'name' invalid.
  206      */
  207 
  208     REQUIRE(VALID_NAME(name));
  209 
  210     name->magic = 0;
  211     name->ndata = NULL;
  212     name->length = 0;
  213     name->labels = 0;
  214     name->attributes = 0;
  215     name->offsets = NULL;
  216     name->buffer = NULL;
  217     ISC_LINK_INIT(name, link);
  218 }
  219 
  220 bool
  221 dns_name_isvalid(const dns_name_t *name) {
  222     unsigned char *ndata, *offsets;
  223     unsigned int offset, count, length, nlabels;
  224 
  225     if (!VALID_NAME(name))
  226         return (false);
  227 
  228     if (name->length > 255U || name->labels > 127U)
  229         return (false);
  230 
  231     ndata = name->ndata;
  232     length = name->length;
  233     offsets = name->offsets;
  234     offset = 0;
  235     nlabels = 0;
  236 
  237     while (offset != length) {
  238         count = *ndata;
  239         if (count > 63U)
  240             return (false);
  241         if (offsets != NULL && offsets[nlabels] != offset)
  242             return (false);
  243 
  244         nlabels++;
  245         offset += count + 1;
  246         ndata += count + 1;
  247         if (offset > length)
  248             return (false);
  249 
  250         if (count == 0)
  251             break;
  252     }
  253 
  254     if (nlabels != name->labels || offset != name->length)
  255         return (false);
  256 
  257     return (true);
  258 }
  259 
  260 void
  261 dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
  262     /*
  263      * Dedicate a buffer for use with 'name'.
  264      */
  265 
  266     REQUIRE(VALID_NAME(name));
  267     REQUIRE((buffer != NULL && name->buffer == NULL) ||
  268         (buffer == NULL));
  269 
  270     name->buffer = buffer;
  271 }
  272 
  273 bool
  274 dns_name_hasbuffer(const dns_name_t *name) {
  275     /*
  276      * Does 'name' have a dedicated buffer?
  277      */
  278 
  279     REQUIRE(VALID_NAME(name));
  280 
  281     if (name->buffer != NULL)
  282         return (true);
  283 
  284     return (false);
  285 }
  286 
  287 bool
  288 dns_name_isabsolute(const dns_name_t *name) {
  289 
  290     /*
  291      * Does 'name' end in the root label?
  292      */
  293 
  294     REQUIRE(VALID_NAME(name));
  295 
  296     if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
  297         return (true);
  298     return (false);
  299 }
  300 
  301 #define hyphenchar(c) ((c) == 0x2d)
  302 #define asterchar(c) ((c) == 0x2a)
  303 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
  304               || ((c) >= 0x61 && (c) <= 0x7a))
  305 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
  306 #define borderchar(c) (alphachar(c) || digitchar(c))
  307 #define middlechar(c) (borderchar(c) || hyphenchar(c))
  308 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
  309 
  310 bool
  311 dns_name_ismailbox(const dns_name_t *name) {
  312     unsigned char *ndata, ch;
  313     unsigned int n;
  314     bool first;
  315 
  316     REQUIRE(VALID_NAME(name));
  317     REQUIRE(name->labels > 0);
  318     REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
  319 
  320     /*
  321      * Root label.
  322      */
  323     if (name->length == 1)
  324         return (true);
  325 
  326     ndata = name->ndata;
  327     n = *ndata++;
  328     INSIST(n <= 63);
  329     while (n--) {
  330         ch = *ndata++;
  331         if (!domainchar(ch))
  332             return (false);
  333     }
  334 
  335     if (ndata == name->ndata + name->length)
  336         return (false);
  337 
  338     /*
  339      * RFC292/RFC1123 hostname.
  340      */
  341     while (ndata < (name->ndata + name->length)) {
  342         n = *ndata++;
  343         INSIST(n <= 63);
  344         first = true;
  345         while (n--) {
  346             ch = *ndata++;
  347             if (first || n == 0) {
  348                 if (!borderchar(ch))
  349                     return (false);
  350             } else {
  351                 if (!middlechar(ch))
  352                     return (false);
  353             }
  354             first = false;
  355         }
  356     }
  357     return (true);
  358 }
  359 
  360 bool
  361 dns_name_ishostname(const dns_name_t *name, bool wildcard) {
  362     unsigned char *ndata, ch;
  363     unsigned int n;
  364     bool first;
  365 
  366     REQUIRE(VALID_NAME(name));
  367     REQUIRE(name->labels > 0);
  368     REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
  369 
  370     /*
  371      * Root label.
  372      */
  373     if (name->length == 1)
  374         return (true);
  375 
  376     /*
  377      * Skip wildcard if this is a ownername.
  378      */
  379     ndata = name->ndata;
  380     if (wildcard && ndata[0] == 1 && ndata[1] == '*')
  381         ndata += 2;
  382 
  383     /*
  384      * RFC292/RFC1123 hostname.
  385      */
  386     while (ndata < (name->ndata + name->length)) {
  387         n = *ndata++;
  388         INSIST(n <= 63);
  389         first = true;
  390         while (n--) {
  391             ch = *ndata++;
  392             if (first || n == 0) {
  393                 if (!borderchar(ch))
  394                     return (false);
  395             } else {
  396                 if (!middlechar(ch))
  397                     return (false);
  398             }
  399             first = false;
  400         }
  401     }
  402     return (true);
  403 }
  404 
  405 bool
  406 dns_name_iswildcard(const dns_name_t *name) {
  407     unsigned char *ndata;
  408 
  409     /*
  410      * Is 'name' a wildcard name?
  411      */
  412 
  413     REQUIRE(VALID_NAME(name));
  414     REQUIRE(name->labels > 0);
  415 
  416     if (name->length >= 2) {
  417         ndata = name->ndata;
  418         if (ndata[0] == 1 && ndata[1] == '*')
  419             return (true);
  420     }
  421 
  422     return (false);
  423 }
  424 
  425 bool
  426 dns_name_internalwildcard(const dns_name_t *name) {
  427     unsigned char *ndata;
  428     unsigned int count;
  429     unsigned int label;
  430 
  431     /*
  432      * Does 'name' contain a internal wildcard?
  433      */
  434 
  435     REQUIRE(VALID_NAME(name));
  436     REQUIRE(name->labels > 0);
  437 
  438     /*
  439      * Skip first label.
  440      */
  441     ndata = name->ndata;
  442     count = *ndata++;
  443     INSIST(count <= 63);
  444     ndata += count;
  445     label = 1;
  446     /*
  447      * Check all but the last of the remaining labels.
  448      */
  449     while (label + 1 < name->labels) {
  450         count = *ndata++;
  451         INSIST(count <= 63);
  452         if (count == 1 && *ndata == '*')
  453             return (true);
  454         ndata += count;
  455         label++;
  456     }
  457     return (false);
  458 }
  459 
  460 unsigned int
  461 dns_name_hash(dns_name_t *name, bool case_sensitive) {
  462     unsigned int length;
  463 
  464     /*
  465      * Provide a hash value for 'name'.
  466      */
  467     REQUIRE(VALID_NAME(name));
  468 
  469     if (name->labels == 0)
  470         return (0);
  471 
  472     length = name->length;
  473     if (length > 16)
  474         length = 16;
  475 
  476     return (isc_hash_function_reverse(name->ndata, length,
  477                       case_sensitive, NULL));
  478 }
  479 
  480 unsigned int
  481 dns_name_fullhash(dns_name_t *name, bool case_sensitive) {
  482     /*
  483      * Provide a hash value for 'name'.
  484      */
  485     REQUIRE(VALID_NAME(name));
  486 
  487     if (name->labels == 0)
  488         return (0);
  489 
  490     return (isc_hash_function_reverse(name->ndata, name->length,
  491                       case_sensitive, NULL));
  492 }
  493 
  494 unsigned int
  495 dns_fullname_hash(dns_name_t *name, bool case_sensitive) {
  496     /*
  497      * This function was deprecated due to the breakage of the name space
  498      * convention.  We only keep this internally to provide binary backward
  499      * compatibility.
  500      */
  501     return (dns_name_fullhash(name, case_sensitive));
  502 }
  503 
  504 unsigned int
  505 dns_name_hashbylabel(dns_name_t *name, bool case_sensitive) {
  506     unsigned char *offsets;
  507     dns_offsets_t odata;
  508     dns_name_t tname;
  509     unsigned int h = 0;
  510     unsigned int i;
  511 
  512     /*
  513      * Provide a hash value for 'name'.
  514      */
  515     REQUIRE(VALID_NAME(name));
  516 
  517     if (name->labels == 0)
  518         return (0);
  519     else if (name->labels == 1)
  520         return (isc_hash_function_reverse(name->ndata, name->length,
  521                           case_sensitive, NULL));
  522 
  523     SETUP_OFFSETS(name, offsets, odata);
  524     DNS_NAME_INIT(&tname, NULL);
  525     tname.labels = 1;
  526     h = 0;
  527     for (i = 0; i < name->labels; i++) {
  528         tname.ndata = name->ndata + offsets[i];
  529         if (i == name->labels - 1)
  530             tname.length = name->length - offsets[i];
  531         else
  532             tname.length = offsets[i + 1] - offsets[i];
  533         h += isc_hash_function_reverse(tname.ndata, tname.length,
  534                            case_sensitive, NULL);
  535     }
  536 
  537     return (h);
  538 }
  539 
  540 dns_namereln_t
  541 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
  542              int *orderp, unsigned int *nlabelsp)
  543 {
  544     unsigned int l1, l2, l, count1, count2, count, nlabels;
  545     int cdiff, ldiff, chdiff;
  546     unsigned char *label1, *label2;
  547     unsigned char *offsets1, *offsets2;
  548     dns_offsets_t odata1, odata2;
  549     dns_namereln_t namereln = dns_namereln_none;
  550 
  551     /*
  552      * Determine the relative ordering under the DNSSEC order relation of
  553      * 'name1' and 'name2', and also determine the hierarchical
  554      * relationship of the names.
  555      *
  556      * Note: It makes no sense for one of the names to be relative and the
  557      * other absolute.  If both names are relative, then to be meaningfully
  558      * compared the caller must ensure that they are both relative to the
  559      * same domain.
  560      */
  561 
  562     REQUIRE(VALID_NAME(name1));
  563     REQUIRE(VALID_NAME(name2));
  564     REQUIRE(orderp != NULL);
  565     REQUIRE(nlabelsp != NULL);
  566     /*
  567      * Either name1 is absolute and name2 is absolute, or neither is.
  568      */
  569     REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
  570         (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
  571 
  572     if (ISC_UNLIKELY(name1 == name2)) {
  573         *orderp = 0;
  574         *nlabelsp = name1->labels;
  575         return (dns_namereln_equal);
  576     }
  577 
  578     SETUP_OFFSETS(name1, offsets1, odata1);
  579     SETUP_OFFSETS(name2, offsets2, odata2);
  580 
  581     nlabels = 0;
  582     l1 = name1->labels;
  583     l2 = name2->labels;
  584     if (l2 > l1) {
  585         l = l1;
  586         ldiff = 0 - (l2 - l1);
  587     } else {
  588         l = l2;
  589         ldiff = l1 - l2;
  590     }
  591 
  592     offsets1 += l1;
  593     offsets2 += l2;
  594 
  595     while (ISC_LIKELY(l > 0)) {
  596         l--;
  597         offsets1--;
  598         offsets2--;
  599         label1 = &name1->ndata[*offsets1];
  600         label2 = &name2->ndata[*offsets2];
  601         count1 = *label1++;
  602         count2 = *label2++;
  603 
  604         /*
  605          * We dropped bitstring labels, and we don't support any
  606          * other extended label types.
  607          */
  608         INSIST(count1 <= 63 && count2 <= 63);
  609 
  610         cdiff = (int)count1 - (int)count2;
  611         if (cdiff < 0)
  612             count = count1;
  613         else
  614             count = count2;
  615 
  616         /* Loop unrolled for performance */
  617         while (ISC_LIKELY(count > 3)) {
  618             chdiff = (int)maptolower[label1[0]] -
  619                  (int)maptolower[label2[0]];
  620             if (chdiff != 0) {
  621                 *orderp = chdiff;
  622                 goto done;
  623             }
  624             chdiff = (int)maptolower[label1[1]] -
  625                  (int)maptolower[label2[1]];
  626             if (chdiff != 0) {
  627                 *orderp = chdiff;
  628                 goto done;
  629             }
  630             chdiff = (int)maptolower[label1[2]] -
  631                  (int)maptolower[label2[2]];
  632             if (chdiff != 0) {
  633                 *orderp = chdiff;
  634                 goto done;
  635             }
  636             chdiff = (int)maptolower[label1[3]] -
  637                  (int)maptolower[label2[3]];
  638             if (chdiff != 0) {
  639                 *orderp = chdiff;
  640                 goto done;
  641             }
  642             count -= 4;
  643             label1 += 4;
  644             label2 += 4;
  645         }
  646         while (ISC_LIKELY(count-- > 0)) {
  647             chdiff = (int)maptolower[*label1++] -
  648                  (int)maptolower[*label2++];
  649             if (chdiff != 0) {
  650                 *orderp = chdiff;
  651                 goto done;
  652             }
  653         }
  654         if (cdiff != 0) {
  655             *orderp = cdiff;
  656             goto done;
  657         }
  658         nlabels++;
  659     }
  660 
  661     *orderp = ldiff;
  662     if (ldiff < 0)
  663         namereln = dns_namereln_contains;
  664     else if (ldiff > 0)
  665         namereln = dns_namereln_subdomain;
  666     else
  667         namereln = dns_namereln_equal;
  668     *nlabelsp = nlabels;
  669     return (namereln);
  670 
  671  done:
  672     *nlabelsp = nlabels;
  673     if (nlabels > 0)
  674         namereln = dns_namereln_commonancestor;
  675 
  676     return (namereln);
  677 }
  678 
  679 int
  680 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
  681     int order;
  682     unsigned int nlabels;
  683 
  684     /*
  685      * Determine the relative ordering under the DNSSEC order relation of
  686      * 'name1' and 'name2'.
  687      *
  688      * Note: It makes no sense for one of the names to be relative and the
  689      * other absolute.  If both names are relative, then to be meaningfully
  690      * compared the caller must ensure that they are both relative to the
  691      * same domain.
  692      */
  693 
  694     (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
  695 
  696     return (order);
  697 }
  698 
  699 bool
  700 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
  701     unsigned int l, count;
  702     unsigned char c;
  703     unsigned char *label1, *label2;
  704 
  705     /*
  706      * Are 'name1' and 'name2' equal?
  707      *
  708      * Note: It makes no sense for one of the names to be relative and the
  709      * other absolute.  If both names are relative, then to be meaningfully
  710      * compared the caller must ensure that they are both relative to the
  711      * same domain.
  712      */
  713 
  714     REQUIRE(VALID_NAME(name1));
  715     REQUIRE(VALID_NAME(name2));
  716     /*
  717      * Either name1 is absolute and name2 is absolute, or neither is.
  718      */
  719     REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
  720         (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
  721 
  722     if (ISC_UNLIKELY(name1 == name2))
  723         return (true);
  724 
  725     if (name1->length != name2->length)
  726         return (false);
  727 
  728     l = name1->labels;
  729 
  730     if (l != name2->labels)
  731         return (false);
  732 
  733     label1 = name1->ndata;
  734     label2 = name2->ndata;
  735     while (ISC_LIKELY(l-- > 0)) {
  736         count = *label1++;
  737         if (count != *label2++)
  738             return (false);
  739 
  740         INSIST(count <= 63); /* no bitstring support */
  741 
  742         /* Loop unrolled for performance */
  743         while (ISC_LIKELY(count > 3)) {
  744             c = maptolower[label1[0]];
  745             if (c != maptolower[label2[0]])
  746                 return (false);
  747             c = maptolower[label1[1]];
  748             if (c != maptolower[label2[1]])
  749                 return (false);
  750             c = maptolower[label1[2]];
  751             if (c != maptolower[label2[2]])
  752                 return (false);
  753             c = maptolower[label1[3]];
  754             if (c != maptolower[label2[3]])
  755                 return (false);
  756             count -= 4;
  757             label1 += 4;
  758             label2 += 4;
  759         }
  760         while (ISC_LIKELY(count-- > 0)) {
  761             c = maptolower[*label1++];
  762             if (c != maptolower[*label2++])
  763                 return (false);
  764         }
  765     }
  766 
  767     return (true);
  768 }
  769 
  770 bool
  771 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
  772 
  773     /*
  774      * Are 'name1' and 'name2' equal?
  775      *
  776      * Note: It makes no sense for one of the names to be relative and the
  777      * other absolute.  If both names are relative, then to be meaningfully
  778      * compared the caller must ensure that they are both relative to the
  779      * same domain.
  780      */
  781 
  782     REQUIRE(VALID_NAME(name1));
  783     REQUIRE(VALID_NAME(name2));
  784     /*
  785      * Either name1 is absolute and name2 is absolute, or neither is.
  786      */
  787     REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
  788         (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
  789 
  790     if (name1->length != name2->length)
  791         return (false);
  792 
  793     if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
  794         return (false);
  795 
  796     return (true);
  797 }
  798 
  799 int
  800 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
  801     unsigned int l1, l2, l, count1, count2, count;
  802     unsigned char c1, c2;
  803     unsigned char *label1, *label2;
  804 
  805     /*
  806      * Compare two absolute names as rdata.
  807      */
  808 
  809     REQUIRE(VALID_NAME(name1));
  810     REQUIRE(name1->labels > 0);
  811     REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
  812     REQUIRE(VALID_NAME(name2));
  813     REQUIRE(name2->labels > 0);
  814     REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
  815 
  816     l1 = name1->labels;
  817     l2 = name2->labels;
  818 
  819     l = (l1 < l2) ? l1 : l2;
  820 
  821     label1 = name1->ndata;
  822     label2 = name2->ndata;
  823     while (l > 0) {
  824         l--;
  825         count1 = *label1++;
  826         count2 = *label2++;
  827 
  828         /* no bitstring support */
  829         INSIST(count1 <= 63 && count2 <= 63);
  830 
  831         if (count1 != count2)
  832             return ((count1 < count2) ? -1 : 1);
  833         count = count1;
  834         while (count > 0) {
  835             count--;
  836             c1 = maptolower[*label1++];
  837             c2 = maptolower[*label2++];
  838             if (c1 < c2)
  839                 return (-1);
  840             else if (c1 > c2)
  841                 return (1);
  842         }
  843     }
  844 
  845     /*
  846      * If one name had more labels than the other, their common
  847      * prefix must have been different because the shorter name
  848      * ended with the root label and the longer one can't have
  849      * a root label in the middle of it.  Therefore, if we get
  850      * to this point, the lengths must be equal.
  851      */
  852     INSIST(l1 == l2);
  853 
  854     return (0);
  855 }
  856 
  857 bool
  858 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
  859     int order;
  860     unsigned int nlabels;
  861     dns_namereln_t namereln;
  862 
  863     /*
  864      * Is 'name1' a subdomain of 'name2'?
  865      *
  866      * Note: It makes no sense for one of the names to be relative and the
  867      * other absolute.  If both names are relative, then to be meaningfully
  868      * compared the caller must ensure that they are both relative to the
  869      * same domain.
  870      */
  871 
  872     namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
  873     if (namereln == dns_namereln_subdomain ||
  874         namereln == dns_namereln_equal)
  875         return (true);
  876 
  877     return (false);
  878 }
  879 
  880 bool
  881 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
  882     int order;
  883     unsigned int nlabels, labels;
  884     dns_name_t tname;
  885 
  886     REQUIRE(VALID_NAME(name));
  887     REQUIRE(name->labels > 0);
  888     REQUIRE(VALID_NAME(wname));
  889     labels = wname->labels;
  890     REQUIRE(labels > 0);
  891     REQUIRE(dns_name_iswildcard(wname));
  892 
  893 #if defined(__clang__)  && \
  894        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
  895     memset(&tname, 0, sizeof(tname));
  896 #endif
  897     DNS_NAME_INIT(&tname, NULL);
  898     dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
  899     if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
  900         dns_namereln_subdomain)
  901         return (true);
  902     return (false);
  903 }
  904 
  905 unsigned int
  906 dns_name_countlabels(const dns_name_t *name) {
  907     /*
  908      * How many labels does 'name' have?
  909      */
  910 
  911     REQUIRE(VALID_NAME(name));
  912 
  913     ENSURE(name->labels <= 128);
  914 
  915     return (name->labels);
  916 }
  917 
  918 void
  919 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
  920     unsigned char *offsets;
  921     dns_offsets_t odata;
  922 
  923     /*
  924      * Make 'label' refer to the 'n'th least significant label of 'name'.
  925      */
  926 
  927     REQUIRE(VALID_NAME(name));
  928     REQUIRE(name->labels > 0);
  929     REQUIRE(n < name->labels);
  930     REQUIRE(label != NULL);
  931 
  932     SETUP_OFFSETS(name, offsets, odata);
  933 
  934     label->base = &name->ndata[offsets[n]];
  935     if (n == name->labels - 1)
  936         label->length = name->length - offsets[n];
  937     else
  938         label->length = offsets[n + 1] - offsets[n];
  939 }
  940 
  941 void
  942 dns_name_getlabelsequence(const dns_name_t *source,
  943               unsigned int first, unsigned int n,
  944               dns_name_t *target)
  945 {
  946     unsigned char *p, l;
  947     unsigned int firstoffset, endoffset;
  948     unsigned int i;
  949 
  950     /*
  951      * Make 'target' refer to the 'n' labels including and following
  952      * 'first' in 'source'.
  953      */
  954 
  955     REQUIRE(VALID_NAME(source));
  956     REQUIRE(VALID_NAME(target));
  957     REQUIRE(first <= source->labels);
  958     REQUIRE(n <= source->labels - first); /* note first+n could overflow */
  959     REQUIRE(BINDABLE(target));
  960 
  961     p = source->ndata;
  962     if (ISC_UNLIKELY(first == source->labels)) {
  963         firstoffset = source->length;
  964     } else {
  965         for (i = 0; i < first; i++) {
  966             l = *p;
  967             p += l + 1;
  968         }
  969         firstoffset = p - source->ndata;
  970     }
  971 
  972     if (ISC_LIKELY(first + n == source->labels))
  973         endoffset = source->length;
  974     else {
  975         for (i = 0; i < n; i++) {
  976             l = *p;
  977             p += l + 1;
  978         }
  979         endoffset = p - source->ndata;
  980     }
  981 
  982     target->ndata = &source->ndata[firstoffset];
  983     target->length = endoffset - firstoffset;
  984 
  985     if (first + n == source->labels && n > 0 &&
  986         (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
  987         target->attributes |= DNS_NAMEATTR_ABSOLUTE;
  988     else
  989         target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
  990 
  991     target->labels = n;
  992 
  993     /*
  994      * If source and target are the same, and we're making target
  995      * a prefix of source, the offsets table is correct already
  996      * so we don't need to call set_offsets().
  997      */
  998     if (target->offsets != NULL &&
  999         (target != source || first != 0))
 1000         set_offsets(target, target->offsets, NULL);
 1001 }
 1002 
 1003 void
 1004 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
 1005 
 1006     /*
 1007      * Make 'target' refer to the same name as 'source'.
 1008      */
 1009 
 1010     REQUIRE(VALID_NAME(source));
 1011     REQUIRE(VALID_NAME(target));
 1012     REQUIRE(BINDABLE(target));
 1013 
 1014     target->ndata = source->ndata;
 1015     target->length = source->length;
 1016     target->labels = source->labels;
 1017     target->attributes = source->attributes &
 1018         (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
 1019                 DNS_NAMEATTR_DYNOFFSETS);
 1020     if (target->offsets != NULL && source->labels > 0) {
 1021         if (source->offsets != NULL)
 1022             memmove(target->offsets, source->offsets,
 1023                 source->labels);
 1024         else
 1025             set_offsets(target, target->offsets, NULL);
 1026     }
 1027 }
 1028 
 1029 void
 1030 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
 1031     unsigned char *offsets;
 1032     dns_offsets_t odata;
 1033     unsigned int len;
 1034     isc_region_t r2;
 1035 
 1036     /*
 1037      * Make 'name' refer to region 'r'.
 1038      */
 1039 
 1040     REQUIRE(VALID_NAME(name));
 1041     REQUIRE(r != NULL);
 1042     REQUIRE(BINDABLE(name));
 1043 
 1044     INIT_OFFSETS(name, offsets, odata);
 1045 
 1046     if (name->buffer != NULL) {
 1047         isc_buffer_clear(name->buffer);
 1048         isc_buffer_availableregion(name->buffer, &r2);
 1049         len = (r->length < r2.length) ? r->length : r2.length;
 1050         if (len > DNS_NAME_MAXWIRE)
 1051             len = DNS_NAME_MAXWIRE;
 1052         if (len != 0)
 1053             memmove(r2.base, r->base, len);
 1054         name->ndata = r2.base;
 1055         name->length = len;
 1056     } else {
 1057         name->ndata = r->base;
 1058         name->length = (r->length <= DNS_NAME_MAXWIRE) ?
 1059             r->length : DNS_NAME_MAXWIRE;
 1060     }
 1061 
 1062     if (r->length > 0)
 1063         set_offsets(name, offsets, name);
 1064     else {
 1065         name->labels = 0;
 1066         name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
 1067     }
 1068 
 1069     if (name->buffer != NULL)
 1070         isc_buffer_add(name->buffer, name->length);
 1071 }
 1072 
 1073 void
 1074 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
 1075     /*
 1076      * Make 'r' refer to 'name'.
 1077      */
 1078 
 1079     REQUIRE(VALID_NAME(name));
 1080     REQUIRE(r != NULL);
 1081 
 1082     DNS_NAME_TOREGION(name, r);
 1083 }
 1084 
 1085 isc_result_t
 1086 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
 1087           const dns_name_t *origin, unsigned int options,
 1088           isc_buffer_t *target)
 1089 {
 1090     unsigned char *ndata, *label = NULL;
 1091     char *tdata;
 1092     char c;
 1093     ft_state state;
 1094     unsigned int value = 0, count = 0;
 1095     unsigned int n1 = 0, n2 = 0;
 1096     unsigned int tlen, nrem, nused, digits = 0, labels, tused;
 1097     bool done;
 1098     unsigned char *offsets;
 1099     dns_offsets_t odata;
 1100     bool downcase;
 1101 
 1102     /*
 1103      * Convert the textual representation of a DNS name at source
 1104      * into uncompressed wire form stored in target.
 1105      *
 1106      * Notes:
 1107      *  Relative domain names will have 'origin' appended to them
 1108      *  unless 'origin' is NULL, in which case relative domain names
 1109      *  will remain relative.
 1110      */
 1111 
 1112     REQUIRE(VALID_NAME(name));
 1113     REQUIRE(ISC_BUFFER_VALID(source));
 1114     REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
 1115         (target == NULL && ISC_BUFFER_VALID(name->buffer)));
 1116 
 1117     downcase = ((options & DNS_NAME_DOWNCASE) != 0);
 1118 
 1119     if (target == NULL && name->buffer != NULL) {
 1120         target = name->buffer;
 1121         isc_buffer_clear(target);
 1122     }
 1123 
 1124     REQUIRE(BINDABLE(name));
 1125 
 1126     INIT_OFFSETS(name, offsets, odata);
 1127     offsets[0] = 0;
 1128 
 1129     /*
 1130      * Make 'name' empty in case of failure.
 1131      */
 1132     MAKE_EMPTY(name);
 1133 
 1134     /*
 1135      * Set up the state machine.
 1136      */
 1137     tdata = (char *)source->base + source->current;
 1138     tlen = isc_buffer_remaininglength(source);
 1139     tused = 0;
 1140     ndata = isc_buffer_used(target);
 1141     nrem = isc_buffer_availablelength(target);
 1142     if (nrem > 255)
 1143         nrem = 255;
 1144     nused = 0;
 1145     labels = 0;
 1146     done = false;
 1147     state = ft_init;
 1148 
 1149     while (nrem > 0 && tlen > 0 && !done) {
 1150         c = *tdata++;
 1151         tlen--;
 1152         tused++;
 1153 
 1154         switch (state) {
 1155         case ft_init:
 1156             /*
 1157              * Is this the root name?
 1158              */
 1159             if (c == '.') {
 1160                 if (tlen != 0)
 1161                     return (DNS_R_EMPTYLABEL);
 1162                 labels++;
 1163                 *ndata++ = 0;
 1164                 nrem--;
 1165                 nused++;
 1166                 done = true;
 1167                 break;
 1168             }
 1169             if (c == '@' && tlen == 0) {
 1170                 state = ft_at;
 1171                 break;
 1172             }
 1173 
 1174             /* FALLTHROUGH */
 1175         case ft_start:
 1176             label = ndata;
 1177             ndata++;
 1178             nrem--;
 1179             nused++;
 1180             count = 0;
 1181             if (c == '\\') {
 1182                 state = ft_initialescape;
 1183                 break;
 1184             }
 1185             state = ft_ordinary;
 1186             if (nrem == 0)
 1187                 return (ISC_R_NOSPACE);
 1188             /* FALLTHROUGH */
 1189         case ft_ordinary:
 1190             if (c == '.') {
 1191                 if (count == 0)
 1192                     return (DNS_R_EMPTYLABEL);
 1193                 *label = count;
 1194                 labels++;
 1195                 INSIST(labels <= 127);
 1196                 offsets[labels] = nused;
 1197                 if (tlen == 0) {
 1198                     labels++;
 1199                     *ndata++ = 0;
 1200                     nrem--;
 1201                     nused++;
 1202                     done = true;
 1203                 }
 1204                 state = ft_start;
 1205             } else if (c == '\\') {
 1206                 state = ft_escape;
 1207             } else {
 1208                 if (count >= 63)
 1209                     return (DNS_R_LABELTOOLONG);
 1210                 count++;
 1211                 CONVERTTOASCII(c);
 1212                 if (downcase)
 1213                     c = maptolower[c & 0xff];
 1214                 *ndata++ = c;
 1215                 nrem--;
 1216                 nused++;
 1217             }
 1218             break;
 1219         case ft_initialescape:
 1220             if (c == '[') {
 1221                 /*
 1222                  * This looks like a bitstring label, which
 1223                  * was deprecated.  Intentionally drop it.
 1224                  */
 1225                 return (DNS_R_BADLABELTYPE);
 1226             }
 1227             state = ft_escape;
 1228             POST(state);
 1229             /* FALLTHROUGH */
 1230         case ft_escape:
 1231             if (!isdigit(c & 0xff)) {
 1232                 if (count >= 63)
 1233                     return (DNS_R_LABELTOOLONG);
 1234                 count++;
 1235                 CONVERTTOASCII(c);
 1236                 if (downcase)
 1237                     c = maptolower[c & 0xff];
 1238                 *ndata++ = c;
 1239                 nrem--;
 1240                 nused++;
 1241                 state = ft_ordinary;
 1242                 break;
 1243             }
 1244             digits = 0;
 1245             value = 0;
 1246             state = ft_escdecimal;
 1247             /* FALLTHROUGH */
 1248         case ft_escdecimal:
 1249             if (!isdigit(c & 0xff))
 1250                 return (DNS_R_BADESCAPE);
 1251             value *= 10;
 1252             value += digitvalue[c & 0xff];
 1253             digits++;
 1254             if (digits == 3) {
 1255                 if (value > 255)
 1256                     return (DNS_R_BADESCAPE);
 1257                 if (count >= 63)
 1258                     return (DNS_R_LABELTOOLONG);
 1259                 count++;
 1260                 if (downcase)
 1261                     value = maptolower[value];
 1262                 *ndata++ = value;
 1263                 nrem--;
 1264                 nused++;
 1265                 state = ft_ordinary;
 1266             }
 1267             break;
 1268         default:
 1269             FATAL_ERROR(__FILE__, __LINE__,
 1270                     "Unexpected state %d", state);
 1271             /* Does not return. */
 1272         }
 1273     }
 1274 
 1275     if (!done) {
 1276         if (nrem == 0)
 1277             return (ISC_R_NOSPACE);
 1278         INSIST(tlen == 0);
 1279         if (state != ft_ordinary && state != ft_at)
 1280             return (ISC_R_UNEXPECTEDEND);
 1281         if (state == ft_ordinary) {
 1282             INSIST(count != 0);
 1283             *label = count;
 1284             labels++;
 1285             INSIST(labels <= 127);
 1286             offsets[labels] = nused;
 1287         }
 1288         if (origin != NULL) {
 1289             if (nrem < origin->length)
 1290                 return (ISC_R_NOSPACE);
 1291             label = origin->ndata;
 1292             n1 = origin->length;
 1293             nrem -= n1;
 1294             POST(nrem);
 1295             while (n1 > 0) {
 1296                 n2 = *label++;
 1297                 INSIST(n2 <= 63); /* no bitstring support */
 1298                 *ndata++ = n2;
 1299                 n1 -= n2 + 1;
 1300                 nused += n2 + 1;
 1301                 while (n2 > 0) {
 1302                     c = *label++;
 1303                     if (downcase)
 1304                         c = maptolower[c & 0xff];
 1305                     *ndata++ = c;
 1306                     n2--;
 1307                 }
 1308                 labels++;
 1309                 if (n1 > 0) {
 1310                     INSIST(labels <= 127);
 1311                     offsets[labels] = nused;
 1312                 }
 1313             }
 1314             if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 1315                 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
 1316         }
 1317     } else
 1318         name->attributes |= DNS_NAMEATTR_ABSOLUTE;
 1319 
 1320     name->ndata = (unsigned char *)target->base + target->used;
 1321     name->labels = labels;
 1322     name->length = nused;
 1323 
 1324     isc_buffer_forward(source, tused);
 1325     isc_buffer_add(target, name->length);
 1326 
 1327     return (ISC_R_SUCCESS);
 1328 }
 1329 
 1330 #ifdef ISC_PLATFORM_USETHREADS
 1331 static void
 1332 free_specific(void *arg) {
 1333     dns_name_totextfilter_t *mem = arg;
 1334     isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
 1335     /* Stop use being called again. */
 1336     (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
 1337 }
 1338 
 1339 static void
 1340 thread_key_mutex_init(void) {
 1341     RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
 1342 }
 1343 
 1344 static isc_result_t
 1345 totext_filter_proc_key_init(void) {
 1346     isc_result_t result;
 1347 
 1348     /*
 1349      * We need the call to isc_once_do() to support profiled mutex
 1350      * otherwise thread_key_mutex could be initialized at compile time.
 1351      */
 1352     result = isc_once_do(&once, thread_key_mutex_init);
 1353     if (result != ISC_R_SUCCESS)
 1354         return (result);
 1355 
 1356     if (!thread_key_initialized) {
 1357         LOCK(&thread_key_mutex);
 1358         if (thread_key_mctx == NULL)
 1359             result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
 1360         if (result != ISC_R_SUCCESS)
 1361             goto unlock;
 1362         isc_mem_setname(thread_key_mctx, "threadkey", NULL);
 1363         isc_mem_setdestroycheck(thread_key_mctx, false);
 1364 
 1365         if (!thread_key_initialized &&
 1366              isc_thread_key_create(&totext_filter_proc_key,
 1367                        free_specific) != 0) {
 1368             result = ISC_R_FAILURE;
 1369             isc_mem_detach(&thread_key_mctx);
 1370         } else
 1371             thread_key_initialized = 1;
 1372  unlock:
 1373         UNLOCK(&thread_key_mutex);
 1374     }
 1375     return (result);
 1376 }
 1377 #endif
 1378 
 1379 isc_result_t
 1380 dns_name_totext(const dns_name_t *name, bool omit_final_dot,
 1381         isc_buffer_t *target)
 1382 {
 1383     unsigned int options = DNS_NAME_MASTERFILE;
 1384 
 1385     if (omit_final_dot)
 1386         options |= DNS_NAME_OMITFINALDOT;
 1387     return (dns_name_totext2(name, options, target));
 1388 }
 1389 
 1390 isc_result_t
 1391 dns_name_toprincipal(const dns_name_t *name, isc_buffer_t *target) {
 1392     return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
 1393 }
 1394 
 1395 isc_result_t
 1396 dns_name_totext2(const dns_name_t *name, unsigned int options,
 1397          isc_buffer_t *target)
 1398 {
 1399     unsigned char *ndata;
 1400     char *tdata;
 1401     unsigned int nlen, tlen;
 1402     unsigned char c;
 1403     unsigned int trem, count;
 1404     unsigned int labels;
 1405     bool saw_root = false;
 1406     unsigned int oused;
 1407 #ifdef ISC_PLATFORM_USETHREADS
 1408     dns_name_totextfilter_t *mem;
 1409     dns_name_totextfilter_t totext_filter_proc = NULL;
 1410     isc_result_t result;
 1411 #endif
 1412     bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
 1413 
 1414     /*
 1415      * This function assumes the name is in proper uncompressed
 1416      * wire format.
 1417      */
 1418     REQUIRE(VALID_NAME(name));
 1419     REQUIRE(ISC_BUFFER_VALID(target));
 1420 
 1421     oused = target->used;
 1422 
 1423 #ifdef ISC_PLATFORM_USETHREADS
 1424     result = totext_filter_proc_key_init();
 1425     if (result != ISC_R_SUCCESS)
 1426         return (result);
 1427 #endif
 1428     ndata = name->ndata;
 1429     nlen = name->length;
 1430     labels = name->labels;
 1431     tdata = isc_buffer_used(target);
 1432     tlen = isc_buffer_availablelength(target);
 1433 
 1434     trem = tlen;
 1435 
 1436     if (labels == 0 && nlen == 0) {
 1437         /*
 1438          * Special handling for an empty name.
 1439          */
 1440         if (trem == 0)
 1441             return (ISC_R_NOSPACE);
 1442 
 1443         /*
 1444          * The names of these booleans are misleading in this case.
 1445          * This empty name is not necessarily from the root node of
 1446          * the DNS root zone, nor is a final dot going to be included.
 1447          * They need to be set this way, though, to keep the "@"
 1448          * from being trounced.
 1449          */
 1450         saw_root = true;
 1451         omit_final_dot = false;
 1452         *tdata++ = '@';
 1453         trem--;
 1454 
 1455         /*
 1456          * Skip the while() loop.
 1457          */
 1458         nlen = 0;
 1459     } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
 1460         /*
 1461          * Special handling for the root label.
 1462          */
 1463         if (trem == 0)
 1464             return (ISC_R_NOSPACE);
 1465 
 1466         saw_root = true;
 1467         omit_final_dot = false;
 1468         *tdata++ = '.';
 1469         trem--;
 1470 
 1471         /*
 1472          * Skip the while() loop.
 1473          */
 1474         nlen = 0;
 1475     }
 1476 
 1477     while (labels > 0 && nlen > 0 && trem > 0) {
 1478         labels--;
 1479         count = *ndata++;
 1480         nlen--;
 1481         if (count == 0) {
 1482             saw_root = true;
 1483             break;
 1484         }
 1485         if (count < 64) {
 1486             INSIST(nlen >= count);
 1487             while (count > 0) {
 1488                 c = *ndata;
 1489                 switch (c) {
 1490                 /* Special modifiers in zone files. */
 1491                 case 0x40: /* '@' */
 1492                 case 0x24: /* '$' */
 1493                     if ((options & DNS_NAME_MASTERFILE) == 0)
 1494                         goto no_escape;
 1495                     /* FALLTHROUGH */
 1496                 case 0x22: /* '"' */
 1497                 case 0x28: /* '(' */
 1498                 case 0x29: /* ')' */
 1499                 case 0x2E: /* '.' */
 1500                 case 0x3B: /* ';' */
 1501                 case 0x5C: /* '\\' */
 1502                     if (trem < 2)
 1503                         return (ISC_R_NOSPACE);
 1504                     *tdata++ = '\\';
 1505                     CONVERTFROMASCII(c);
 1506                     *tdata++ = c;
 1507                     ndata++;
 1508                     trem -= 2;
 1509                     nlen--;
 1510                     break;
 1511                 no_escape:
 1512                 default:
 1513                     if (c > 0x20 && c < 0x7f) {
 1514                         if (trem == 0)
 1515                             return (ISC_R_NOSPACE);
 1516                         CONVERTFROMASCII(c);
 1517                         *tdata++ = c;
 1518                         ndata++;
 1519                         trem--;
 1520                         nlen--;
 1521                     } else {
 1522                         if (trem < 4)
 1523                             return (ISC_R_NOSPACE);
 1524                         *tdata++ = 0x5c;
 1525                         *tdata++ = 0x30 +
 1526                                ((c / 100) % 10);
 1527                         *tdata++ = 0x30 +
 1528                                ((c / 10) % 10);
 1529                         *tdata++ = 0x30 + (c % 10);
 1530                         trem -= 4;
 1531                         ndata++;
 1532                         nlen--;
 1533                     }
 1534                 }
 1535                 count--;
 1536             }
 1537         } else {
 1538             FATAL_ERROR(__FILE__, __LINE__,
 1539                     "Unexpected label type %02x", count);
 1540             /* NOTREACHED */
 1541         }
 1542 
 1543         /*
 1544          * The following assumes names are absolute.  If not, we
 1545          * fix things up later.  Note that this means that in some
 1546          * cases one more byte of text buffer is required than is
 1547          * needed in the final output.
 1548          */
 1549         if (trem == 0)
 1550             return (ISC_R_NOSPACE);
 1551         *tdata++ = '.';
 1552         trem--;
 1553     }
 1554 
 1555     if (nlen != 0 && trem == 0)
 1556         return (ISC_R_NOSPACE);
 1557 
 1558     if (!saw_root || omit_final_dot) {
 1559         trem++;
 1560         tdata--;
 1561     }
 1562     if (trem > 0) {
 1563         *tdata = 0;
 1564     }
 1565     isc_buffer_add(target, tlen - trem);
 1566 
 1567 #ifdef ISC_PLATFORM_USETHREADS
 1568     mem = isc_thread_key_getspecific(totext_filter_proc_key);
 1569     if (mem != NULL)
 1570         totext_filter_proc = *mem;
 1571 #endif
 1572     if (totext_filter_proc != NULL)
 1573         return ((*totext_filter_proc)(target, oused, saw_root));
 1574 
 1575     return (ISC_R_SUCCESS);
 1576 }
 1577 
 1578 isc_result_t
 1579 dns_name_tofilenametext(dns_name_t *name, bool omit_final_dot,
 1580             isc_buffer_t *target)
 1581 {
 1582     unsigned char *ndata;
 1583     char *tdata;
 1584     unsigned int nlen, tlen;
 1585     unsigned char c;
 1586     unsigned int trem, count;
 1587     unsigned int labels;
 1588 
 1589     /*
 1590      * This function assumes the name is in proper uncompressed
 1591      * wire format.
 1592      */
 1593     REQUIRE(VALID_NAME(name));
 1594     REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
 1595     REQUIRE(ISC_BUFFER_VALID(target));
 1596 
 1597     ndata = name->ndata;
 1598     nlen = name->length;
 1599     labels = name->labels;
 1600     tdata = isc_buffer_used(target);
 1601     tlen = isc_buffer_availablelength(target);
 1602 
 1603     trem = tlen;
 1604 
 1605     if (nlen == 1 && labels == 1 && *ndata == '\0') {
 1606         /*
 1607          * Special handling for the root label.
 1608          */
 1609         if (trem == 0)
 1610             return (ISC_R_NOSPACE);
 1611 
 1612         omit_final_dot = false;
 1613         *tdata++ = '.';
 1614         trem--;
 1615 
 1616         /*
 1617          * Skip the while() loop.
 1618          */
 1619         nlen = 0;
 1620     }
 1621 
 1622     while (labels > 0 && nlen > 0 && trem > 0) {
 1623         labels--;
 1624         count = *ndata++;
 1625         nlen--;
 1626         if (count == 0)
 1627             break;
 1628         if (count < 64) {
 1629             INSIST(nlen >= count);
 1630             while (count > 0) {
 1631                 c = *ndata;
 1632                 if ((c >= 0x30 && c <= 0x39) || /* digit */
 1633                     (c >= 0x41 && c <= 0x5A) || /* uppercase */
 1634                     (c >= 0x61 && c <= 0x7A) || /* lowercase */
 1635                     c == 0x2D ||        /* hyphen */
 1636                     c == 0x5F)          /* underscore */
 1637                 {
 1638                     if (trem == 0)
 1639                         return (ISC_R_NOSPACE);
 1640                     /* downcase */
 1641                     if (c >= 0x41 && c <= 0x5A)
 1642                         c += 0x20;
 1643                     CONVERTFROMASCII(c);
 1644                     *tdata++ = c;
 1645                     ndata++;
 1646                     trem--;
 1647                     nlen--;
 1648                 } else {
 1649                     if (trem < 4)
 1650                         return (ISC_R_NOSPACE);
 1651                     snprintf(tdata, trem, "%%%02X", c);
 1652                     tdata += 3;
 1653                     trem -= 3;
 1654                     ndata++;
 1655                     nlen--;
 1656                 }
 1657                 count--;
 1658             }
 1659         } else {
 1660             FATAL_ERROR(__FILE__, __LINE__,
 1661                     "Unexpected label type %02x", count);
 1662             /* NOTREACHED */
 1663         }
 1664 
 1665         /*
 1666          * The following assumes names are absolute.  If not, we
 1667          * fix things up later.  Note that this means that in some
 1668          * cases one more byte of text buffer is required than is
 1669          * needed in the final output.
 1670          */
 1671         if (trem == 0)
 1672             return (ISC_R_NOSPACE);
 1673         *tdata++ = '.';
 1674         trem--;
 1675     }
 1676 
 1677     if (nlen != 0 && trem == 0)
 1678         return (ISC_R_NOSPACE);
 1679 
 1680     if (omit_final_dot)
 1681         trem++;
 1682 
 1683     isc_buffer_add(target, tlen - trem);
 1684 
 1685     return (ISC_R_SUCCESS);
 1686 }
 1687 
 1688 isc_result_t
 1689 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
 1690     unsigned char *sndata, *ndata;
 1691     unsigned int nlen, count, labels;
 1692     isc_buffer_t buffer;
 1693 
 1694     /*
 1695      * Downcase 'source'.
 1696      */
 1697 
 1698     REQUIRE(VALID_NAME(source));
 1699     REQUIRE(VALID_NAME(name));
 1700     if (source == name) {
 1701         REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
 1702         isc_buffer_init(&buffer, source->ndata, source->length);
 1703         target = &buffer;
 1704         ndata = source->ndata;
 1705     } else {
 1706         REQUIRE(BINDABLE(name));
 1707         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
 1708             (target == NULL && ISC_BUFFER_VALID(name->buffer)));
 1709         if (target == NULL) {
 1710             target = name->buffer;
 1711             isc_buffer_clear(name->buffer);
 1712         }
 1713         ndata = (unsigned char *)target->base + target->used;
 1714         name->ndata = ndata;
 1715     }
 1716 
 1717     sndata = source->ndata;
 1718     nlen = source->length;
 1719     labels = source->labels;
 1720 
 1721     if (nlen > (target->length - target->used)) {
 1722         MAKE_EMPTY(name);
 1723         return (ISC_R_NOSPACE);
 1724     }
 1725 
 1726     while (labels > 0 && nlen > 0) {
 1727         labels--;
 1728         count = *sndata++;
 1729         *ndata++ = count;
 1730         nlen--;
 1731         if (count < 64) {
 1732             INSIST(nlen >= count);
 1733             while (count > 0) {
 1734                 *ndata++ = maptolower[(*sndata++)];
 1735                 nlen--;
 1736                 count--;
 1737             }
 1738         } else {
 1739             FATAL_ERROR(__FILE__, __LINE__,
 1740                     "Unexpected label type %02x", count);
 1741             /* Does not return. */
 1742         }
 1743     }
 1744 
 1745     if (source != name) {
 1746         name->labels = source->labels;
 1747         name->length = source->length;
 1748         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 1749             name->attributes = DNS_NAMEATTR_ABSOLUTE;
 1750         else
 1751             name->attributes = 0;
 1752         if (name->labels > 0 && name->offsets != NULL)
 1753             set_offsets(name, name->offsets, NULL);
 1754     }
 1755 
 1756     isc_buffer_add(target, name->length);
 1757 
 1758     return (ISC_R_SUCCESS);
 1759 }
 1760 
 1761 static void
 1762 set_offsets(const dns_name_t *name, unsigned char *offsets,
 1763         dns_name_t *set_name)
 1764 {
 1765     unsigned int offset, count, length, nlabels;
 1766     unsigned char *ndata;
 1767     bool absolute;
 1768 
 1769     ndata = name->ndata;
 1770     length = name->length;
 1771     offset = 0;
 1772     nlabels = 0;
 1773     absolute = false;
 1774     while (ISC_LIKELY(offset != length)) {
 1775         INSIST(nlabels < 128);
 1776         offsets[nlabels++] = offset;
 1777         count = *ndata;
 1778         INSIST(count <= 63);
 1779         offset += count + 1;
 1780         ndata += count + 1;
 1781         INSIST(offset <= length);
 1782         if (ISC_UNLIKELY(count == 0)) {
 1783             absolute = true;
 1784             break;
 1785         }
 1786     }
 1787     if (set_name != NULL) {
 1788         INSIST(set_name == name);
 1789 
 1790         set_name->labels = nlabels;
 1791         set_name->length = offset;
 1792         if (absolute)
 1793             set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
 1794         else
 1795             set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
 1796     }
 1797     INSIST(nlabels == name->labels);
 1798     INSIST(offset == name->length);
 1799 }
 1800 
 1801 isc_result_t
 1802 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
 1803           dns_decompress_t *dctx, unsigned int options,
 1804           isc_buffer_t *target)
 1805 {
 1806     unsigned char *cdata, *ndata;
 1807     unsigned int cused; /* Bytes of compressed name data used */
 1808     unsigned int nused, labels, n, nmax;
 1809     unsigned int current, new_current, biggest_pointer;
 1810     bool done;
 1811     fw_state state = fw_start;
 1812     unsigned int c;
 1813     unsigned char *offsets;
 1814     dns_offsets_t odata;
 1815     bool downcase;
 1816     bool seen_pointer;
 1817 
 1818     /*
 1819      * Copy the possibly-compressed name at source into target,
 1820      * decompressing it.  Loop prevention is performed by checking
 1821      * the new pointer against biggest_pointer.
 1822      */
 1823 
 1824     REQUIRE(VALID_NAME(name));
 1825     REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
 1826         (target == NULL && ISC_BUFFER_VALID(name->buffer)));
 1827 
 1828     downcase = ((options & DNS_NAME_DOWNCASE) != 0);
 1829 
 1830     if (target == NULL && name->buffer != NULL) {
 1831         target = name->buffer;
 1832         isc_buffer_clear(target);
 1833     }
 1834 
 1835     REQUIRE(dctx != NULL);
 1836     REQUIRE(BINDABLE(name));
 1837 
 1838     INIT_OFFSETS(name, offsets, odata);
 1839 
 1840     /*
 1841      * Make 'name' empty in case of failure.
 1842      */
 1843     MAKE_EMPTY(name);
 1844 
 1845     /*
 1846      * Initialize things to make the compiler happy; they're not required.
 1847      */
 1848     n = 0;
 1849     new_current = 0;
 1850 
 1851     /*
 1852      * Set up.
 1853      */
 1854     labels = 0;
 1855     done = false;
 1856 
 1857     ndata = isc_buffer_used(target);
 1858     nused = 0;
 1859     seen_pointer = false;
 1860 
 1861     /*
 1862      * Find the maximum number of uncompressed target name
 1863      * bytes we are willing to generate.  This is the smaller
 1864      * of the available target buffer length and the
 1865      * maximum legal domain name length (255).
 1866      */
 1867     nmax = isc_buffer_availablelength(target);
 1868     if (nmax > DNS_NAME_MAXWIRE)
 1869         nmax = DNS_NAME_MAXWIRE;
 1870 
 1871     cdata = isc_buffer_current(source);
 1872     cused = 0;
 1873 
 1874     current = source->current;
 1875     biggest_pointer = current;
 1876 
 1877     /*
 1878      * Note:  The following code is not optimized for speed, but
 1879      * rather for correctness.  Speed will be addressed in the future.
 1880      */
 1881 
 1882     while (current < source->active && !done) {
 1883         c = *cdata++;
 1884         current++;
 1885         if (!seen_pointer)
 1886             cused++;
 1887 
 1888         switch (state) {
 1889         case fw_start:
 1890             if (c < 64) {
 1891                 offsets[labels] = nused;
 1892                 labels++;
 1893                 if (nused + c + 1 > nmax)
 1894                     goto full;
 1895                 nused += c + 1;
 1896                 *ndata++ = c;
 1897                 if (c == 0)
 1898                     done = true;
 1899                 n = c;
 1900                 state = fw_ordinary;
 1901             } else if (c >= 128 && c < 192) {
 1902                 /*
 1903                  * 14 bit local compression pointer.
 1904                  * Local compression is no longer an
 1905                  * IETF draft.
 1906                  */
 1907                 return (DNS_R_BADLABELTYPE);
 1908             } else if (c >= 192) {
 1909                 /*
 1910                  * Ordinary 14-bit pointer.
 1911                  */
 1912                 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 0)
 1913                 {
 1914                     return (DNS_R_DISALLOWED);
 1915                 }
 1916                 new_current = c & 0x3F;
 1917                 state = fw_newcurrent;
 1918             } else
 1919                 return (DNS_R_BADLABELTYPE);
 1920             break;
 1921         case fw_ordinary:
 1922             if (downcase)
 1923                 c = maptolower[c];
 1924             *ndata++ = c;
 1925             n--;
 1926             if (n == 0)
 1927                 state = fw_start;
 1928             break;
 1929         case fw_newcurrent:
 1930             new_current *= 256;
 1931             new_current += c;
 1932             if (new_current >= biggest_pointer)
 1933                 return (DNS_R_BADPOINTER);
 1934             biggest_pointer = new_current;
 1935             current = new_current;
 1936             cdata = (unsigned char *)source->base + current;
 1937             seen_pointer = true;
 1938             state = fw_start;
 1939             break;
 1940         default:
 1941             FATAL_ERROR(__FILE__, __LINE__,
 1942                     "Unknown state %d", state);
 1943             /* Does not return. */
 1944         }
 1945     }
 1946 
 1947     if (!done)
 1948         return (ISC_R_UNEXPECTEDEND);
 1949 
 1950     name->ndata = (unsigned char *)target->base + target->used;
 1951     name->labels = labels;
 1952     name->length = nused;
 1953     name->attributes |= DNS_NAMEATTR_ABSOLUTE;
 1954 
 1955     isc_buffer_forward(source, cused);
 1956     isc_buffer_add(target, name->length);
 1957 
 1958     return (ISC_R_SUCCESS);
 1959 
 1960  full:
 1961     if (nmax == DNS_NAME_MAXWIRE)
 1962         /*
 1963          * The name did not fit even though we had a buffer
 1964          * big enough to fit a maximum-length name.
 1965          */
 1966         return (DNS_R_NAMETOOLONG);
 1967     else
 1968         /*
 1969          * The name might fit if only the caller could give us a
 1970          * big enough buffer.
 1971          */
 1972         return (ISC_R_NOSPACE);
 1973 }
 1974 
 1975 isc_result_t
 1976 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
 1977         isc_buffer_t *target)
 1978 {
 1979     unsigned int methods;
 1980     uint16_t offset;
 1981     dns_name_t gp;  /* Global compression prefix */
 1982     bool gf;    /* Global compression target found */
 1983     uint16_t go;    /* Global compression offset */
 1984     dns_offsets_t clo;
 1985     dns_name_t clname;
 1986 
 1987     /*
 1988      * Convert 'name' into wire format, compressing it as specified by the
 1989      * compression context 'cctx', and storing the result in 'target'.
 1990      */
 1991 
 1992     REQUIRE(VALID_NAME(name));
 1993     REQUIRE(cctx != NULL);
 1994     REQUIRE(ISC_BUFFER_VALID(target));
 1995 
 1996     /*
 1997      * If 'name' doesn't have an offsets table, make a clone which
 1998      * has one.
 1999      */
 2000     if (name->offsets == NULL) {
 2001 #if defined(__clang__)  && \
 2002        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
 2003         memset(&clname, 0, sizeof(clname));
 2004 #endif
 2005         DNS_NAME_INIT(&clname, clo);
 2006         dns_name_clone(name, &clname);
 2007         name = &clname;
 2008     }
 2009     DNS_NAME_INIT(&gp, NULL);
 2010 
 2011     offset = target->used;  /*XXX*/
 2012 
 2013     methods = dns_compress_getmethods(cctx);
 2014 
 2015     if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
 2016         (methods & DNS_COMPRESS_GLOBAL14) != 0)
 2017         gf = dns_compress_findglobal(cctx, name, &gp, &go);
 2018     else
 2019         gf = false;
 2020 
 2021     /*
 2022      * If the offset is too high for 14 bit global compression, we're
 2023      * out of luck.
 2024      */
 2025     if (gf && go >= 0x4000)
 2026         gf = false;
 2027 
 2028     /*
 2029      * Will the compression pointer reduce the message size?
 2030      */
 2031     if (gf && (gp.length + 2) >= name->length)
 2032         gf = false;
 2033 
 2034     if (gf) {
 2035         if (target->length - target->used < gp.length)
 2036             return (ISC_R_NOSPACE);
 2037         if (gp.length != 0) {
 2038             unsigned char *base = target->base;
 2039             (void)memmove(base + target->used, gp.ndata,
 2040                       (size_t)gp.length);
 2041         }
 2042         isc_buffer_add(target, gp.length);
 2043         go |= 0xc000;
 2044         if (target->length - target->used < 2)
 2045             return (ISC_R_NOSPACE);
 2046         isc_buffer_putuint16(target, go);
 2047         if (gp.length != 0)
 2048             dns_compress_add(cctx, name, &gp, offset);
 2049     } else {
 2050         if (target->length - target->used < name->length)
 2051             return (ISC_R_NOSPACE);
 2052         if (name->length != 0) {
 2053             unsigned char *base = target->base;
 2054             (void)memmove(base + target->used, name->ndata,
 2055                       (size_t)name->length);
 2056         }
 2057         isc_buffer_add(target, name->length);
 2058         dns_compress_add(cctx, name, name, offset);
 2059     }
 2060     return (ISC_R_SUCCESS);
 2061 }
 2062 
 2063 isc_result_t
 2064 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
 2065              isc_buffer_t *target)
 2066 {
 2067     unsigned char *ndata, *offsets;
 2068     unsigned int nrem, labels, prefix_length, length;
 2069     bool copy_prefix = true;
 2070     bool copy_suffix = true;
 2071     bool absolute = false;
 2072     dns_name_t tmp_name;
 2073     dns_offsets_t odata;
 2074 
 2075     /*
 2076      * Concatenate 'prefix' and 'suffix'.
 2077      */
 2078 
 2079     REQUIRE(prefix == NULL || VALID_NAME(prefix));
 2080     REQUIRE(suffix == NULL || VALID_NAME(suffix));
 2081     REQUIRE(name == NULL || VALID_NAME(name));
 2082     REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
 2083         (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
 2084     if (prefix == NULL || prefix->labels == 0)
 2085         copy_prefix = false;
 2086     if (suffix == NULL || suffix->labels == 0)
 2087         copy_suffix = false;
 2088     if (copy_prefix &&
 2089         (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
 2090         absolute = true;
 2091         REQUIRE(!copy_suffix);
 2092     }
 2093     if (name == NULL) {
 2094         DNS_NAME_INIT(&tmp_name, odata);
 2095         name = &tmp_name;
 2096     }
 2097     if (target == NULL) {
 2098         INSIST(name->buffer != NULL);
 2099         target = name->buffer;
 2100         isc_buffer_clear(name->buffer);
 2101     }
 2102 
 2103     REQUIRE(BINDABLE(name));
 2104 
 2105     /*
 2106      * Set up.
 2107      */
 2108     nrem = target->length - target->used;
 2109     ndata = (unsigned char *)target->base + target->used;
 2110     if (nrem > DNS_NAME_MAXWIRE)
 2111         nrem = DNS_NAME_MAXWIRE;
 2112     length = 0;
 2113     prefix_length = 0;
 2114     labels = 0;
 2115     if (copy_prefix) {
 2116         prefix_length = prefix->length;
 2117         length += prefix_length;
 2118         labels += prefix->labels;
 2119     }
 2120     if (copy_suffix) {
 2121         length += suffix->length;
 2122         labels += suffix->labels;
 2123     }
 2124     if (length > DNS_NAME_MAXWIRE) {
 2125         MAKE_EMPTY(name);
 2126         return (DNS_R_NAMETOOLONG);
 2127     }
 2128     if (length > nrem) {
 2129         MAKE_EMPTY(name);
 2130         return (ISC_R_NOSPACE);
 2131     }
 2132 
 2133     if (copy_suffix) {
 2134         if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 2135             absolute = true;
 2136         memmove(ndata + prefix_length, suffix->ndata, suffix->length);
 2137     }
 2138 
 2139     /*
 2140      * If 'prefix' and 'name' are the same object, and the object has
 2141      * a dedicated buffer, and we're using it, then we don't have to
 2142      * copy anything.
 2143      */
 2144     if (copy_prefix && (prefix != name || prefix->buffer != target))
 2145         memmove(ndata, prefix->ndata, prefix_length);
 2146 
 2147     name->ndata = ndata;
 2148     name->labels = labels;
 2149     name->length = length;
 2150     if (absolute)
 2151         name->attributes = DNS_NAMEATTR_ABSOLUTE;
 2152     else
 2153         name->attributes = 0;
 2154 
 2155     if (name->labels > 0 && name->offsets != NULL) {
 2156         INIT_OFFSETS(name, offsets, odata);
 2157         set_offsets(name, offsets, NULL);
 2158     }
 2159 
 2160     isc_buffer_add(target, name->length);
 2161 
 2162     return (ISC_R_SUCCESS);
 2163 }
 2164 
 2165 void
 2166 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
 2167            dns_name_t *prefix, dns_name_t *suffix)
 2168 
 2169 {
 2170     unsigned int splitlabel;
 2171 
 2172     REQUIRE(VALID_NAME(name));
 2173     REQUIRE(suffixlabels > 0);
 2174     REQUIRE(suffixlabels <= name->labels);
 2175     REQUIRE(prefix != NULL || suffix != NULL);
 2176     REQUIRE(prefix == NULL ||
 2177         (VALID_NAME(prefix) &&
 2178          BINDABLE(prefix)));
 2179     REQUIRE(suffix == NULL ||
 2180         (VALID_NAME(suffix) &&
 2181          BINDABLE(suffix)));
 2182 
 2183     splitlabel = name->labels - suffixlabels;
 2184 
 2185     if (prefix != NULL)
 2186         dns_name_getlabelsequence(name, 0, splitlabel, prefix);
 2187 
 2188     if (suffix != NULL)
 2189         dns_name_getlabelsequence(name, splitlabel,
 2190                       suffixlabels, suffix);
 2191 
 2192     return;
 2193 }
 2194 
 2195 isc_result_t
 2196 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
 2197          dns_name_t *target)
 2198 {
 2199     /*
 2200      * Make 'target' a dynamically allocated copy of 'source'.
 2201      */
 2202 
 2203     REQUIRE(VALID_NAME(source));
 2204     REQUIRE(source->length > 0);
 2205     REQUIRE(VALID_NAME(target));
 2206     REQUIRE(BINDABLE(target));
 2207 
 2208     /*
 2209      * Make 'target' empty in case of failure.
 2210      */
 2211     MAKE_EMPTY(target);
 2212 
 2213     target->ndata = isc_mem_get(mctx, source->length);
 2214     if (target->ndata == NULL)
 2215         return (ISC_R_NOMEMORY);
 2216 
 2217     memmove(target->ndata, source->ndata, source->length);
 2218 
 2219     target->length = source->length;
 2220     target->labels = source->labels;
 2221     target->attributes = DNS_NAMEATTR_DYNAMIC;
 2222     if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 2223         target->attributes |= DNS_NAMEATTR_ABSOLUTE;
 2224     if (target->offsets != NULL) {
 2225         if (source->offsets != NULL)
 2226             memmove(target->offsets, source->offsets,
 2227                 source->labels);
 2228         else
 2229             set_offsets(target, target->offsets, NULL);
 2230     }
 2231 
 2232     return (ISC_R_SUCCESS);
 2233 }
 2234 
 2235 isc_result_t
 2236 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
 2237             dns_name_t *target)
 2238 {
 2239     /*
 2240      * Make 'target' a read-only dynamically allocated copy of 'source'.
 2241      * 'target' will also have a dynamically allocated offsets table.
 2242      */
 2243 
 2244     REQUIRE(VALID_NAME(source));
 2245     REQUIRE(source->length > 0);
 2246     REQUIRE(VALID_NAME(target));
 2247     REQUIRE(BINDABLE(target));
 2248     REQUIRE(target->offsets == NULL);
 2249 
 2250     /*
 2251      * Make 'target' empty in case of failure.
 2252      */
 2253     MAKE_EMPTY(target);
 2254 
 2255     target->ndata = isc_mem_get(mctx, source->length + source->labels);
 2256     if (target->ndata == NULL)
 2257         return (ISC_R_NOMEMORY);
 2258 
 2259     memmove(target->ndata, source->ndata, source->length);
 2260 
 2261     target->length = source->length;
 2262     target->labels = source->labels;
 2263     target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
 2264         DNS_NAMEATTR_READONLY;
 2265     if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 2266         target->attributes |= DNS_NAMEATTR_ABSOLUTE;
 2267     target->offsets = target->ndata + source->length;
 2268     if (source->offsets != NULL)
 2269         memmove(target->offsets, source->offsets, source->labels);
 2270     else
 2271         set_offsets(target, target->offsets, NULL);
 2272 
 2273     return (ISC_R_SUCCESS);
 2274 }
 2275 
 2276 void
 2277 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
 2278     size_t size;
 2279 
 2280     /*
 2281      * Free 'name'.
 2282      */
 2283 
 2284     REQUIRE(VALID_NAME(name));
 2285     REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
 2286 
 2287     size = name->length;
 2288     if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
 2289         size += name->labels;
 2290     isc_mem_put(mctx, name->ndata, size);
 2291     dns_name_invalidate(name);
 2292 }
 2293 
 2294 isc_result_t
 2295 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
 2296     dns_name_t downname;
 2297     unsigned char data[256];
 2298     isc_buffer_t buffer;
 2299     isc_result_t result;
 2300     isc_region_t r;
 2301 
 2302     /*
 2303      * Send 'name' in DNSSEC canonical form to 'digest'.
 2304      */
 2305 
 2306     REQUIRE(VALID_NAME(name));
 2307     REQUIRE(digest != NULL);
 2308 
 2309 #if defined(__clang__)  && \
 2310        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
 2311     memset(&downname, 0, sizeof(downname));
 2312 #endif
 2313     DNS_NAME_INIT(&downname, NULL);
 2314 
 2315     isc_buffer_init(&buffer, data, sizeof(data));
 2316 
 2317     result = dns_name_downcase(name, &downname, &buffer);
 2318     if (result != ISC_R_SUCCESS)
 2319         return (result);
 2320 
 2321     isc_buffer_usedregion(&buffer, &r);
 2322 
 2323     return ((digest)(arg, &r));
 2324 }
 2325 
 2326 bool
 2327 dns_name_dynamic(dns_name_t *name) {
 2328     REQUIRE(VALID_NAME(name));
 2329 
 2330     /*
 2331      * Returns whether there is dynamic memory associated with this name.
 2332      */
 2333 
 2334     return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
 2335         true : false);
 2336 }
 2337 
 2338 isc_result_t
 2339 dns_name_print(dns_name_t *name, FILE *stream) {
 2340     isc_result_t result;
 2341     isc_buffer_t b;
 2342     isc_region_t r;
 2343     char t[1024];
 2344 
 2345     /*
 2346      * Print 'name' on 'stream'.
 2347      */
 2348 
 2349     REQUIRE(VALID_NAME(name));
 2350 
 2351     isc_buffer_init(&b, t, sizeof(t));
 2352     result = dns_name_totext(name, false, &b);
 2353     if (result != ISC_R_SUCCESS)
 2354         return (result);
 2355     isc_buffer_usedregion(&b, &r);
 2356     fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
 2357 
 2358     return (ISC_R_SUCCESS);
 2359 }
 2360 
 2361 isc_result_t
 2362 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
 2363 #ifdef ISC_PLATFORM_USETHREADS
 2364     isc_result_t result;
 2365     dns_name_totextfilter_t *mem;
 2366     int res;
 2367 
 2368     result = totext_filter_proc_key_init();
 2369     if (result != ISC_R_SUCCESS)
 2370         return (result);
 2371 
 2372     /*
 2373      * If we already have been here set / clear as appropriate.
 2374      * Otherwise allocate memory.
 2375      */
 2376     mem = isc_thread_key_getspecific(totext_filter_proc_key);
 2377     if (mem != NULL && proc != NULL) {
 2378         *mem = proc;
 2379         return (ISC_R_SUCCESS);
 2380     }
 2381     if (proc == NULL) {
 2382         if (mem != NULL)
 2383             isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
 2384         res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
 2385         if (res != 0)
 2386             result = ISC_R_UNEXPECTED;
 2387         return (result);
 2388     }
 2389 
 2390     mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
 2391     if (mem == NULL)
 2392         return (ISC_R_NOMEMORY);
 2393     *mem = proc;
 2394     if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
 2395         isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
 2396         result = ISC_R_UNEXPECTED;
 2397     }
 2398     return (result);
 2399 #else
 2400     totext_filter_proc = proc;
 2401     return (ISC_R_SUCCESS);
 2402 #endif
 2403 }
 2404 
 2405 void
 2406 dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
 2407     isc_result_t result;
 2408     isc_buffer_t buf;
 2409 
 2410     REQUIRE(size > 0);
 2411 
 2412     /*
 2413      * Leave room for null termination after buffer.
 2414      */
 2415     isc_buffer_init(&buf, cp, size - 1);
 2416     result = dns_name_totext(name, true, &buf);
 2417     if (result == ISC_R_SUCCESS) {
 2418         isc_buffer_putuint8(&buf, (uint8_t)'\0');
 2419     } else {
 2420         snprintf(cp, size, "<unknown>");
 2421     }
 2422 }
 2423 
 2424 /*
 2425  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
 2426  * memory.
 2427  */
 2428 isc_result_t
 2429 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
 2430     isc_result_t result;
 2431     isc_buffer_t buf;
 2432     isc_region_t reg;
 2433     char *p, txt[DNS_NAME_FORMATSIZE];
 2434 
 2435     REQUIRE(VALID_NAME(name));
 2436     REQUIRE(target != NULL && *target == NULL);
 2437 
 2438     isc_buffer_init(&buf, txt, sizeof(txt));
 2439     result = dns_name_totext(name, false, &buf);
 2440     if (result != ISC_R_SUCCESS)
 2441         return (result);
 2442 
 2443     isc_buffer_usedregion(&buf, &reg);
 2444     p = isc_mem_allocate(mctx, reg.length + 1);
 2445     if (p == NULL)
 2446         return (ISC_R_NOMEMORY);
 2447     memmove(p, (char *) reg.base, (int) reg.length);
 2448     p[reg.length] = '\0';
 2449 
 2450     *target = p;
 2451     return (ISC_R_SUCCESS);
 2452 }
 2453 
 2454 /*
 2455  * dns_name_fromstring() -- convert directly from a string to a name,
 2456  * allocating memory as needed
 2457  */
 2458 isc_result_t
 2459 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
 2460             isc_mem_t *mctx)
 2461 {
 2462     return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
 2463 }
 2464 
 2465 isc_result_t
 2466 dns_name_fromstring2(dns_name_t *target, const char *src,
 2467              const dns_name_t *origin, unsigned int options,
 2468              isc_mem_t *mctx)
 2469 {
 2470     isc_result_t result;
 2471     isc_buffer_t buf;
 2472     dns_fixedname_t fn;
 2473     dns_name_t *name;
 2474 
 2475     REQUIRE(src != NULL);
 2476 
 2477     isc_buffer_constinit(&buf, src, strlen(src));
 2478     isc_buffer_add(&buf, strlen(src));
 2479     if (BINDABLE(target) && target->buffer != NULL)
 2480         name = target;
 2481     else {
 2482         name = dns_fixedname_initname(&fn);
 2483     }
 2484 
 2485     result = dns_name_fromtext(name, &buf, origin, options, NULL);
 2486     if (result != ISC_R_SUCCESS)
 2487         return (result);
 2488 
 2489     if (name != target)
 2490         result = dns_name_dupwithoffsets(name, mctx, target);
 2491     return (result);
 2492 }
 2493 
 2494 isc_result_t
 2495 dns_name_copy(const dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
 2496     unsigned char *ndata;
 2497 
 2498     /*
 2499      * Make dest a copy of source.
 2500      */
 2501 
 2502     REQUIRE(VALID_NAME(source));
 2503     REQUIRE(VALID_NAME(dest));
 2504     REQUIRE(target != NULL || dest->buffer != NULL);
 2505 
 2506     if (target == NULL) {
 2507         target = dest->buffer;
 2508         isc_buffer_clear(dest->buffer);
 2509     }
 2510 
 2511     REQUIRE(BINDABLE(dest));
 2512 
 2513     /*
 2514      * Set up.
 2515      */
 2516     if (target->length - target->used < source->length)
 2517         return (ISC_R_NOSPACE);
 2518 
 2519     ndata = (unsigned char *)target->base + target->used;
 2520     dest->ndata = target->base;
 2521 
 2522     if (source->length != 0)
 2523         memmove(ndata, source->ndata, source->length);
 2524 
 2525     dest->ndata = ndata;
 2526     dest->labels = source->labels;
 2527     dest->length = source->length;
 2528     if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
 2529         dest->attributes = DNS_NAMEATTR_ABSOLUTE;
 2530     else
 2531         dest->attributes = 0;
 2532 
 2533     if (dest->labels > 0 && dest->offsets != NULL) {
 2534         if (source->offsets != NULL)
 2535             memmove(dest->offsets, source->offsets, source->labels);
 2536         else
 2537             set_offsets(dest, dest->offsets, NULL);
 2538     }
 2539 
 2540     isc_buffer_add(target, dest->length);
 2541 
 2542     return (ISC_R_SUCCESS);
 2543 }
 2544 
 2545 void
 2546 dns_name_destroy(void) {
 2547 #ifdef ISC_PLATFORM_USETHREADS
 2548     RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
 2549                   == ISC_R_SUCCESS);
 2550 
 2551     LOCK(&thread_key_mutex);
 2552     if (thread_key_initialized) {
 2553         isc_mem_detach(&thread_key_mctx);
 2554         isc_thread_key_delete(totext_filter_proc_key);
 2555         thread_key_initialized = 0;
 2556     }
 2557     UNLOCK(&thread_key_mutex);
 2558 
 2559 #endif
 2560 }
 2561 
 2562 /*
 2563  * Service Discovery Prefixes RFC 6763.
 2564  */
 2565 static unsigned char b_dns_sd_udp_data[]  = "\001b\007_dns-sd\004_udp";
 2566 static unsigned char b_dns_sd_udp_offsets[] = { 0, 2, 10 };
 2567 static unsigned char db_dns_sd_udp_data[]  = "\002db\007_dns-sd\004_udp";
 2568 static unsigned char db_dns_sd_udp_offsets[] = { 0, 3, 11 };
 2569 static unsigned char r_dns_sd_udp_data[]  = "\001r\007_dns-sd\004_udp";
 2570 static unsigned char r_dns_sd_udp_offsets[] = { 0, 2, 10 };
 2571 static unsigned char dr_dns_sd_udp_data[]  = "\002dr\007_dns-sd\004_udp";
 2572 static unsigned char dr_dns_sd_udp_offsets[] = { 0, 3, 11 };
 2573 static unsigned char lb_dns_sd_udp_data[]  = "\002lb\007_dns-sd\004_udp";
 2574 static unsigned char lb_dns_sd_udp_offsets[] = { 0, 3, 11 };
 2575 
 2576 static dns_name_t const dns_sd[] = {
 2577     DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data, b_dns_sd_udp_offsets),
 2578     DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data, db_dns_sd_udp_offsets),
 2579     DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data, r_dns_sd_udp_offsets),
 2580     DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data, dr_dns_sd_udp_offsets),
 2581     DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data, lb_dns_sd_udp_offsets)
 2582 };
 2583 
 2584 bool
 2585 dns_name_isdnssd(const dns_name_t *name) {
 2586     size_t i;
 2587     dns_name_t prefix;
 2588 
 2589     if (dns_name_countlabels(name) > 3U) {
 2590         dns_name_init(&prefix, NULL);
 2591         dns_name_getlabelsequence(name, 0, 3, &prefix);
 2592         for (i = 0; i < (sizeof(dns_sd)/sizeof(dns_sd[0])); i++)
 2593             if (dns_name_equal(&prefix, &dns_sd[i]))
 2594                 return (true);
 2595     }
 2596 
 2597     return (false);
 2598 }
 2599 
 2600 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
 2601 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
 2602 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
 2603 
 2604 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
 2605 
 2606 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
 2607 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
 2608 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
 2609 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
 2610 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
 2611 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
 2612 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
 2613 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
 2614 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
 2615 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
 2616 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
 2617 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
 2618 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
 2619 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
 2620 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
 2621 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
 2622 
 2623 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
 2624 
 2625 static dns_name_t const rfc1918names[] = {
 2626     DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
 2627     DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
 2628     DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
 2629     DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
 2630     DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
 2631     DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
 2632     DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
 2633     DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
 2634     DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
 2635     DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
 2636     DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
 2637     DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
 2638     DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
 2639     DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
 2640     DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
 2641     DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
 2642     DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
 2643     DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
 2644 };
 2645 
 2646 bool
 2647 dns_name_isrfc1918(const dns_name_t *name) {
 2648     size_t i;
 2649 
 2650     for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++)
 2651         if (dns_name_issubdomain(name, &rfc1918names[i]))
 2652             return (true);
 2653     return (false);
 2654 }
 2655 
 2656 static unsigned char ulaoffsets[] = { 0, 2, 4, 8, 13 };
 2657 static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
 2658 static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
 2659 
 2660 static dns_name_t const ulanames[] = {
 2661     DNS_NAME_INITABSOLUTE(ip6fc, ulaoffsets),
 2662     DNS_NAME_INITABSOLUTE(ip6fd, ulaoffsets)
 2663 };
 2664 
 2665 bool
 2666 dns_name_isula(const dns_name_t *name) {
 2667     size_t i;
 2668 
 2669     for (i = 0; i < (sizeof(ulanames)/sizeof(*ulanames)); i++)
 2670         if (dns_name_issubdomain(name, &ulanames[i]))
 2671             return (true);
 2672     return (false);
 2673 }
 2674 
 2675 /*
 2676  * Use a simple table as we don't want all the locale stuff
 2677  * associated with ishexdigit().
 2678  */
 2679 const char
 2680 ishex[256] = {
 2681      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2682      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2683      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2684      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
 2685      0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2686      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2687      0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 2688      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 2689 };
 2690 
 2691 bool
 2692 dns_name_istat(const dns_name_t *name) {
 2693     unsigned char len;
 2694     const unsigned char *ndata;
 2695 
 2696     REQUIRE(VALID_NAME(name));
 2697 
 2698     if (name->labels < 1)
 2699         return (false);
 2700 
 2701     ndata = name->ndata;
 2702     len = ndata[0];
 2703     INSIST(len <= name->length);
 2704     ndata++;
 2705 
 2706     /*
 2707      * Is there at least one trust anchor reported and is the
 2708      * label length consistent with a trust-anchor-telemetry label.
 2709      */
 2710     if ((len < 8) || (len - 3) % 5 != 0) {
 2711         return (false);
 2712     }
 2713 
 2714     if (ndata[0] != '_' ||
 2715         maptolower[ndata[1]] != 't' ||
 2716         maptolower[ndata[2]] != 'a') {
 2717         return (false);
 2718     }
 2719     ndata += 3;
 2720     len -= 3;
 2721 
 2722     while (len > 0) {
 2723         INSIST(len >= 5);
 2724         if (ndata[0] != '-' || !ishex[ndata[1]] || !ishex[ndata[2]] ||
 2725             !ishex[ndata[3]] || !ishex[ndata[4]]) {
 2726             return (false);
 2727         }
 2728         ndata += 5;
 2729         len -= 5;
 2730     }
 2731     return (true);
 2732 }