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