]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/lib/dns/name.c
MFV r254070:
[FreeBSD/FreeBSD.git] / contrib / bind9 / lib / dns / name.c
1 /*
2  * Copyright (C) 2004-2012  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/string.h>
33 #include <isc/thread.h>
34 #include <isc/util.h>
35
36 #include <dns/compress.h>
37 #include <dns/fixedname.h>
38 #include <dns/name.h>
39 #include <dns/result.h>
40
41 #define VALID_NAME(n)   ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
42
43 typedef enum {
44         ft_init = 0,
45         ft_start,
46         ft_ordinary,
47         ft_initialescape,
48         ft_escape,
49         ft_escdecimal,
50         ft_at
51 } ft_state;
52
53 typedef enum {
54         fw_start = 0,
55         fw_ordinary,
56         fw_copy,
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 static inline unsigned int
443 name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
444         unsigned int length;
445         const unsigned char *s;
446         unsigned int h = 0;
447         unsigned char c;
448
449         length = name->length;
450         if (length > 16)
451                 length = 16;
452
453         /*
454          * This hash function is similar to the one Ousterhout
455          * uses in Tcl.
456          */
457         s = name->ndata;
458         if (case_sensitive) {
459                 while (length > 0) {
460                         h += ( h << 3 ) + *s;
461                         s++;
462                         length--;
463                 }
464         } else {
465                 while (length > 0) {
466                         c = maptolower[*s];
467                         h += ( h << 3 ) + c;
468                         s++;
469                         length--;
470                 }
471         }
472
473         return (h);
474 }
475
476 unsigned int
477 dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
478         /*
479          * Provide a hash value for 'name'.
480          */
481         REQUIRE(VALID_NAME(name));
482
483         if (name->labels == 0)
484                 return (0);
485
486         return (name_hash(name, case_sensitive));
487 }
488
489 unsigned int
490 dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
491         /*
492          * Provide a hash value for 'name'.
493          */
494         REQUIRE(VALID_NAME(name));
495
496         if (name->labels == 0)
497                 return (0);
498
499         return (isc_hash_calc((const unsigned char *)name->ndata,
500                               name->length, case_sensitive));
501 }
502
503 unsigned int
504 dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
505         /*
506          * This function was deprecated due to the breakage of the name space
507          * convention.  We only keep this internally to provide binary backward
508          * compatibility.
509          */
510         REQUIRE(VALID_NAME(name));
511
512         return (dns_name_fullhash(name, case_sensitive));
513 }
514
515 unsigned int
516 dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
517         unsigned char *offsets;
518         dns_offsets_t odata;
519         dns_name_t tname;
520         unsigned int h = 0;
521         unsigned int i;
522
523         /*
524          * Provide a hash value for 'name'.
525          */
526         REQUIRE(VALID_NAME(name));
527
528         if (name->labels == 0)
529                 return (0);
530         else if (name->labels == 1)
531                 return (name_hash(name, case_sensitive));
532
533         SETUP_OFFSETS(name, offsets, odata);
534         DNS_NAME_INIT(&tname, NULL);
535         tname.labels = 1;
536         h = 0;
537         for (i = 0; i < name->labels; i++) {
538                 tname.ndata = name->ndata + offsets[i];
539                 if (i == name->labels - 1)
540                         tname.length = name->length - offsets[i];
541                 else
542                         tname.length = offsets[i + 1] - offsets[i];
543                 h += name_hash(&tname, case_sensitive);
544         }
545
546         return (h);
547 }
548
549 dns_namereln_t
550 dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
551                      int *orderp, unsigned int *nlabelsp)
552 {
553         unsigned int l1, l2, l, count1, count2, count, nlabels;
554         int cdiff, ldiff, chdiff;
555         unsigned char *label1, *label2;
556         unsigned char *offsets1, *offsets2;
557         dns_offsets_t odata1, odata2;
558         dns_namereln_t namereln = dns_namereln_none;
559
560         /*
561          * Determine the relative ordering under the DNSSEC order relation of
562          * 'name1' and 'name2', and also determine the hierarchical
563          * relationship of the names.
564          *
565          * Note: It makes no sense for one of the names to be relative and the
566          * other absolute.  If both names are relative, then to be meaningfully
567          * compared the caller must ensure that they are both relative to the
568          * same domain.
569          */
570
571         REQUIRE(VALID_NAME(name1));
572         REQUIRE(VALID_NAME(name2));
573         REQUIRE(orderp != NULL);
574         REQUIRE(nlabelsp != NULL);
575         /*
576          * Either name1 is absolute and name2 is absolute, or neither is.
577          */
578         REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
579                 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
580
581         SETUP_OFFSETS(name1, offsets1, odata1);
582         SETUP_OFFSETS(name2, offsets2, odata2);
583
584         nlabels = 0;
585         l1 = name1->labels;
586         l2 = name2->labels;
587         if (l2 > l1) {
588                 l = l1;
589                 ldiff = 0 - (l2 - l1);
590         } else {
591                 l = l2;
592                 ldiff = l1 - l2;
593         }
594
595         while (l > 0) {
596                 l--;
597                 l1--;
598                 l2--;
599                 label1 = &name1->ndata[offsets1[l1]];
600                 label2 = &name2->ndata[offsets2[l2]];
601                 count1 = *label1++;
602                 count2 = *label2++;
603
604                 /*
605                  * We dropped bitstring labels, and we don't support any
606                  * other extended label types.
607                  */
608                 INSIST(count1 <= 63 && count2 <= 63);
609
610                 cdiff = (int)count1 - (int)count2;
611                 if (cdiff < 0)
612                         count = count1;
613                 else
614                         count = count2;
615
616                 while (count > 0) {
617                         chdiff = (int)maptolower[*label1] -
618                             (int)maptolower[*label2];
619                         if (chdiff != 0) {
620                                 *orderp = chdiff;
621                                 goto done;
622                         }
623                         count--;
624                         label1++;
625                         label2++;
626                 }
627                 if (cdiff != 0) {
628                         *orderp = cdiff;
629                         goto done;
630                 }
631                 nlabels++;
632         }
633
634         *orderp = ldiff;
635         if (ldiff < 0)
636                 namereln = dns_namereln_contains;
637         else if (ldiff > 0)
638                 namereln = dns_namereln_subdomain;
639         else
640                 namereln = dns_namereln_equal;
641
642  done:
643         *nlabelsp = nlabels;
644
645         if (nlabels > 0 && namereln == dns_namereln_none)
646                 namereln = dns_namereln_commonancestor;
647
648         return (namereln);
649 }
650
651 int
652 dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
653         int order;
654         unsigned int nlabels;
655
656         /*
657          * Determine the relative ordering under the DNSSEC order relation of
658          * 'name1' and 'name2'.
659          *
660          * Note: It makes no sense for one of the names to be relative and the
661          * other absolute.  If both names are relative, then to be meaningfully
662          * compared the caller must ensure that they are both relative to the
663          * same domain.
664          */
665
666         (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
667
668         return (order);
669 }
670
671 isc_boolean_t
672 dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
673         unsigned int l, count;
674         unsigned char c;
675         unsigned char *label1, *label2;
676
677         /*
678          * Are 'name1' and 'name2' equal?
679          *
680          * Note: It makes no sense for one of the names to be relative and the
681          * other absolute.  If both names are relative, then to be meaningfully
682          * compared the caller must ensure that they are both relative to the
683          * same domain.
684          */
685
686         REQUIRE(VALID_NAME(name1));
687         REQUIRE(VALID_NAME(name2));
688         /*
689          * Either name1 is absolute and name2 is absolute, or neither is.
690          */
691         REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
692                 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
693
694         if (name1->length != name2->length)
695                 return (ISC_FALSE);
696
697         l = name1->labels;
698
699         if (l != name2->labels)
700                 return (ISC_FALSE);
701
702         label1 = name1->ndata;
703         label2 = name2->ndata;
704         while (l > 0) {
705                 l--;
706                 count = *label1++;
707                 if (count != *label2++)
708                         return (ISC_FALSE);
709
710                 INSIST(count <= 63); /* no bitstring support */
711
712                 while (count > 0) {
713                         count--;
714                         c = maptolower[*label1++];
715                         if (c != maptolower[*label2++])
716                                 return (ISC_FALSE);
717                 }
718         }
719
720         return (ISC_TRUE);
721 }
722
723 isc_boolean_t
724 dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
725
726         /*
727          * Are 'name1' and 'name2' equal?
728          *
729          * Note: It makes no sense for one of the names to be relative and the
730          * other absolute.  If both names are relative, then to be meaningfully
731          * compared the caller must ensure that they are both relative to the
732          * same domain.
733          */
734
735         REQUIRE(VALID_NAME(name1));
736         REQUIRE(VALID_NAME(name2));
737         /*
738          * Either name1 is absolute and name2 is absolute, or neither is.
739          */
740         REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
741                 (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
742
743         if (name1->length != name2->length)
744                 return (ISC_FALSE);
745
746         if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
747                 return (ISC_FALSE);
748
749         return (ISC_TRUE);
750 }
751
752 int
753 dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
754         unsigned int l1, l2, l, count1, count2, count;
755         unsigned char c1, c2;
756         unsigned char *label1, *label2;
757
758         /*
759          * Compare two absolute names as rdata.
760          */
761
762         REQUIRE(VALID_NAME(name1));
763         REQUIRE(name1->labels > 0);
764         REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
765         REQUIRE(VALID_NAME(name2));
766         REQUIRE(name2->labels > 0);
767         REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
768
769         l1 = name1->labels;
770         l2 = name2->labels;
771
772         l = (l1 < l2) ? l1 : l2;
773
774         label1 = name1->ndata;
775         label2 = name2->ndata;
776         while (l > 0) {
777                 l--;
778                 count1 = *label1++;
779                 count2 = *label2++;
780
781                 /* no bitstring support */
782                 INSIST(count1 <= 63 && count2 <= 63);
783
784                 if (count1 != count2)
785                         return ((count1 < count2) ? -1 : 1);
786                 count = count1;
787                 while (count > 0) {
788                         count--;
789                         c1 = maptolower[*label1++];
790                         c2 = maptolower[*label2++];
791                         if (c1 < c2)
792                                 return (-1);
793                         else if (c1 > c2)
794                                 return (1);
795                 }
796         }
797
798         /*
799          * If one name had more labels than the other, their common
800          * prefix must have been different because the shorter name
801          * ended with the root label and the longer one can't have
802          * a root label in the middle of it.  Therefore, if we get
803          * to this point, the lengths must be equal.
804          */
805         INSIST(l1 == l2);
806
807         return (0);
808 }
809
810 isc_boolean_t
811 dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
812         int order;
813         unsigned int nlabels;
814         dns_namereln_t namereln;
815
816         /*
817          * Is 'name1' a subdomain of 'name2'?
818          *
819          * Note: It makes no sense for one of the names to be relative and the
820          * other absolute.  If both names are relative, then to be meaningfully
821          * compared the caller must ensure that they are both relative to the
822          * same domain.
823          */
824
825         namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
826         if (namereln == dns_namereln_subdomain ||
827             namereln == dns_namereln_equal)
828                 return (ISC_TRUE);
829
830         return (ISC_FALSE);
831 }
832
833 isc_boolean_t
834 dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
835         int order;
836         unsigned int nlabels, labels;
837         dns_name_t tname;
838
839         REQUIRE(VALID_NAME(name));
840         REQUIRE(name->labels > 0);
841         REQUIRE(VALID_NAME(wname));
842         labels = wname->labels;
843         REQUIRE(labels > 0);
844         REQUIRE(dns_name_iswildcard(wname));
845
846 #if defined(__clang__)  && \
847        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
848         memset(&tname, 0, sizeof(tname));
849 #endif
850         DNS_NAME_INIT(&tname, NULL);
851         dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
852         if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
853             dns_namereln_subdomain)
854                 return (ISC_TRUE);
855         return (ISC_FALSE);
856 }
857
858 unsigned int
859 dns_name_countlabels(const dns_name_t *name) {
860         /*
861          * How many labels does 'name' have?
862          */
863
864         REQUIRE(VALID_NAME(name));
865
866         ENSURE(name->labels <= 128);
867
868         return (name->labels);
869 }
870
871 void
872 dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
873         unsigned char *offsets;
874         dns_offsets_t odata;
875
876         /*
877          * Make 'label' refer to the 'n'th least significant label of 'name'.
878          */
879
880         REQUIRE(VALID_NAME(name));
881         REQUIRE(name->labels > 0);
882         REQUIRE(n < name->labels);
883         REQUIRE(label != NULL);
884
885         SETUP_OFFSETS(name, offsets, odata);
886
887         label->base = &name->ndata[offsets[n]];
888         if (n == name->labels - 1)
889                 label->length = name->length - offsets[n];
890         else
891                 label->length = offsets[n + 1] - offsets[n];
892 }
893
894 void
895 dns_name_getlabelsequence(const dns_name_t *source,
896                           unsigned int first, unsigned int n,
897                           dns_name_t *target)
898 {
899         unsigned char *offsets;
900         dns_offsets_t odata;
901         unsigned int firstoffset, endoffset;
902
903         /*
904          * Make 'target' refer to the 'n' labels including and following
905          * 'first' in 'source'.
906          */
907
908         REQUIRE(VALID_NAME(source));
909         REQUIRE(VALID_NAME(target));
910         REQUIRE(first <= source->labels);
911         REQUIRE(n <= source->labels - first); /* note first+n could overflow */
912         REQUIRE(BINDABLE(target));
913
914         SETUP_OFFSETS(source, offsets, odata);
915
916         if (first == source->labels)
917                 firstoffset = source->length;
918         else
919                 firstoffset = offsets[first];
920
921         if (first + n == source->labels)
922                 endoffset = source->length;
923         else
924                 endoffset = offsets[first + n];
925
926         target->ndata = &source->ndata[firstoffset];
927         target->length = endoffset - firstoffset;
928
929         if (first + n == source->labels && n > 0 &&
930             (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
931                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
932         else
933                 target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
934
935         target->labels = n;
936
937         /*
938          * If source and target are the same, and we're making target
939          * a prefix of source, the offsets table is correct already
940          * so we don't need to call set_offsets().
941          */
942         if (target->offsets != NULL &&
943             (target != source || first != 0))
944                 set_offsets(target, target->offsets, NULL);
945 }
946
947 void
948 dns_name_clone(const dns_name_t *source, dns_name_t *target) {
949
950         /*
951          * Make 'target' refer to the same name as 'source'.
952          */
953
954         REQUIRE(VALID_NAME(source));
955         REQUIRE(VALID_NAME(target));
956         REQUIRE(BINDABLE(target));
957
958         target->ndata = source->ndata;
959         target->length = source->length;
960         target->labels = source->labels;
961         target->attributes = source->attributes &
962                 (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
963                                 DNS_NAMEATTR_DYNOFFSETS);
964         if (target->offsets != NULL && source->labels > 0) {
965                 if (source->offsets != NULL)
966                         memcpy(target->offsets, source->offsets,
967                                source->labels);
968                 else
969                         set_offsets(target, target->offsets, NULL);
970         }
971 }
972
973 void
974 dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
975         unsigned char *offsets;
976         dns_offsets_t odata;
977         unsigned int len;
978         isc_region_t r2;
979
980         /*
981          * Make 'name' refer to region 'r'.
982          */
983
984         REQUIRE(VALID_NAME(name));
985         REQUIRE(r != NULL);
986         REQUIRE(BINDABLE(name));
987
988         INIT_OFFSETS(name, offsets, odata);
989
990         if (name->buffer != NULL) {
991                 isc_buffer_clear(name->buffer);
992                 isc_buffer_availableregion(name->buffer, &r2);
993                 len = (r->length < r2.length) ? r->length : r2.length;
994                 if (len > DNS_NAME_MAXWIRE)
995                         len = DNS_NAME_MAXWIRE;
996                 memcpy(r2.base, r->base, len);
997                 name->ndata = r2.base;
998                 name->length = len;
999         } else {
1000                 name->ndata = r->base;
1001                 name->length = (r->length <= DNS_NAME_MAXWIRE) ?
1002                         r->length : DNS_NAME_MAXWIRE;
1003         }
1004
1005         if (r->length > 0)
1006                 set_offsets(name, offsets, name);
1007         else {
1008                 name->labels = 0;
1009                 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1010         }
1011
1012         if (name->buffer != NULL)
1013                 isc_buffer_add(name->buffer, name->length);
1014 }
1015
1016 void
1017 dns_name_toregion(dns_name_t *name, isc_region_t *r) {
1018         /*
1019          * Make 'r' refer to 'name'.
1020          */
1021
1022         REQUIRE(VALID_NAME(name));
1023         REQUIRE(r != NULL);
1024
1025         DNS_NAME_TOREGION(name, r);
1026 }
1027
1028 isc_result_t
1029 dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1030                   const dns_name_t *origin, unsigned int options,
1031                   isc_buffer_t *target)
1032 {
1033         unsigned char *ndata, *label = NULL;
1034         char *tdata;
1035         char c;
1036         ft_state state;
1037         unsigned int value = 0, count = 0;
1038         unsigned int n1 = 0, n2 = 0;
1039         unsigned int tlen, nrem, nused, digits = 0, labels, tused;
1040         isc_boolean_t done;
1041         unsigned char *offsets;
1042         dns_offsets_t odata;
1043         isc_boolean_t downcase;
1044
1045         /*
1046          * Convert the textual representation of a DNS name at source
1047          * into uncompressed wire form stored in target.
1048          *
1049          * Notes:
1050          *      Relative domain names will have 'origin' appended to them
1051          *      unless 'origin' is NULL, in which case relative domain names
1052          *      will remain relative.
1053          */
1054
1055         REQUIRE(VALID_NAME(name));
1056         REQUIRE(ISC_BUFFER_VALID(source));
1057         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1058                 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1059
1060         downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1061
1062         if (target == NULL && name->buffer != NULL) {
1063                 target = name->buffer;
1064                 isc_buffer_clear(target);
1065         }
1066
1067         REQUIRE(BINDABLE(name));
1068
1069         INIT_OFFSETS(name, offsets, odata);
1070         offsets[0] = 0;
1071
1072         /*
1073          * Make 'name' empty in case of failure.
1074          */
1075         MAKE_EMPTY(name);
1076
1077         /*
1078          * Set up the state machine.
1079          */
1080         tdata = (char *)source->base + source->current;
1081         tlen = isc_buffer_remaininglength(source);
1082         tused = 0;
1083         ndata = isc_buffer_used(target);
1084         nrem = isc_buffer_availablelength(target);
1085         if (nrem > 255)
1086                 nrem = 255;
1087         nused = 0;
1088         labels = 0;
1089         done = ISC_FALSE;
1090         state = ft_init;
1091
1092         while (nrem > 0 && tlen > 0 && !done) {
1093                 c = *tdata++;
1094                 tlen--;
1095                 tused++;
1096
1097                 switch (state) {
1098                 case ft_init:
1099                         /*
1100                          * Is this the root name?
1101                          */
1102                         if (c == '.') {
1103                                 if (tlen != 0)
1104                                         return (DNS_R_EMPTYLABEL);
1105                                 labels++;
1106                                 *ndata++ = 0;
1107                                 nrem--;
1108                                 nused++;
1109                                 done = ISC_TRUE;
1110                                 break;
1111                         }
1112                         if (c == '@' && tlen == 0) {
1113                                 state = ft_at;
1114                                 break;
1115                         }
1116
1117                         /* FALLTHROUGH */
1118                 case ft_start:
1119                         label = ndata;
1120                         ndata++;
1121                         nrem--;
1122                         nused++;
1123                         count = 0;
1124                         if (c == '\\') {
1125                                 state = ft_initialescape;
1126                                 break;
1127                         }
1128                         state = ft_ordinary;
1129                         if (nrem == 0)
1130                                 return (ISC_R_NOSPACE);
1131                         /* FALLTHROUGH */
1132                 case ft_ordinary:
1133                         if (c == '.') {
1134                                 if (count == 0)
1135                                         return (DNS_R_EMPTYLABEL);
1136                                 *label = count;
1137                                 labels++;
1138                                 INSIST(labels <= 127);
1139                                 offsets[labels] = nused;
1140                                 if (tlen == 0) {
1141                                         labels++;
1142                                         *ndata++ = 0;
1143                                         nrem--;
1144                                         nused++;
1145                                         done = ISC_TRUE;
1146                                 }
1147                                 state = ft_start;
1148                         } else if (c == '\\') {
1149                                 state = ft_escape;
1150                         } else {
1151                                 if (count >= 63)
1152                                         return (DNS_R_LABELTOOLONG);
1153                                 count++;
1154                                 CONVERTTOASCII(c);
1155                                 if (downcase)
1156                                         c = maptolower[(int)c];
1157                                 *ndata++ = c;
1158                                 nrem--;
1159                                 nused++;
1160                         }
1161                         break;
1162                 case ft_initialescape:
1163                         if (c == '[') {
1164                                 /*
1165                                  * This looks like a bitstring label, which
1166                                  * was deprecated.  Intentionally drop it.
1167                                  */
1168                                 return (DNS_R_BADLABELTYPE);
1169                         }
1170                         state = ft_escape;
1171                         POST(state);
1172                         /* FALLTHROUGH */
1173                 case ft_escape:
1174                         if (!isdigit(c & 0xff)) {
1175                                 if (count >= 63)
1176                                         return (DNS_R_LABELTOOLONG);
1177                                 count++;
1178                                 CONVERTTOASCII(c);
1179                                 if (downcase)
1180                                         c = maptolower[(int)c];
1181                                 *ndata++ = c;
1182                                 nrem--;
1183                                 nused++;
1184                                 state = ft_ordinary;
1185                                 break;
1186                         }
1187                         digits = 0;
1188                         value = 0;
1189                         state = ft_escdecimal;
1190                         /* FALLTHROUGH */
1191                 case ft_escdecimal:
1192                         if (!isdigit(c & 0xff))
1193                                 return (DNS_R_BADESCAPE);
1194                         value *= 10;
1195                         value += digitvalue[(int)c];
1196                         digits++;
1197                         if (digits == 3) {
1198                                 if (value > 255)
1199                                         return (DNS_R_BADESCAPE);
1200                                 if (count >= 63)
1201                                         return (DNS_R_LABELTOOLONG);
1202                                 count++;
1203                                 if (downcase)
1204                                         value = maptolower[value];
1205                                 *ndata++ = value;
1206                                 nrem--;
1207                                 nused++;
1208                                 state = ft_ordinary;
1209                         }
1210                         break;
1211                 default:
1212                         FATAL_ERROR(__FILE__, __LINE__,
1213                                     "Unexpected state %d", state);
1214                         /* Does not return. */
1215                 }
1216         }
1217
1218         if (!done) {
1219                 if (nrem == 0)
1220                         return (ISC_R_NOSPACE);
1221                 INSIST(tlen == 0);
1222                 if (state != ft_ordinary && state != ft_at)
1223                         return (ISC_R_UNEXPECTEDEND);
1224                 if (state == ft_ordinary) {
1225                         INSIST(count != 0);
1226                         *label = count;
1227                         labels++;
1228                         INSIST(labels <= 127);
1229                         offsets[labels] = nused;
1230                 }
1231                 if (origin != NULL) {
1232                         if (nrem < origin->length)
1233                                 return (ISC_R_NOSPACE);
1234                         label = origin->ndata;
1235                         n1 = origin->length;
1236                         nrem -= n1;
1237                         POST(nrem);
1238                         while (n1 > 0) {
1239                                 n2 = *label++;
1240                                 INSIST(n2 <= 63); /* no bitstring support */
1241                                 *ndata++ = n2;
1242                                 n1 -= n2 + 1;
1243                                 nused += n2 + 1;
1244                                 while (n2 > 0) {
1245                                         c = *label++;
1246                                         if (downcase)
1247                                                 c = maptolower[(int)c];
1248                                         *ndata++ = c;
1249                                         n2--;
1250                                 }
1251                                 labels++;
1252                                 if (n1 > 0) {
1253                                         INSIST(labels <= 127);
1254                                         offsets[labels] = nused;
1255                                 }
1256                         }
1257                         if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1258                                 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1259                 }
1260         } else
1261                 name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1262
1263         name->ndata = (unsigned char *)target->base + target->used;
1264         name->labels = labels;
1265         name->length = nused;
1266
1267         isc_buffer_forward(source, tused);
1268         isc_buffer_add(target, name->length);
1269
1270         return (ISC_R_SUCCESS);
1271 }
1272
1273 #ifdef ISC_PLATFORM_USETHREADS
1274 static void
1275 free_specific(void *arg) {
1276         dns_name_totextfilter_t *mem = arg;
1277         isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
1278         /* Stop use being called again. */
1279         (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
1280 }
1281
1282 static void
1283 thread_key_mutex_init(void) {
1284         RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
1285 }
1286
1287 static isc_result_t
1288 totext_filter_proc_key_init(void) {
1289         isc_result_t result;
1290
1291         /*
1292          * We need the call to isc_once_do() to support profiled mutex
1293          * otherwise thread_key_mutex could be initialized at compile time.
1294          */
1295         result = isc_once_do(&once, thread_key_mutex_init);
1296         if (result != ISC_R_SUCCESS)
1297                 return (result);
1298
1299         if (!thread_key_initialized) {
1300                 LOCK(&thread_key_mutex);
1301                 if (thread_key_mctx == NULL)
1302                         result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
1303                 if (result != ISC_R_SUCCESS)
1304                         goto unlock;
1305                 isc_mem_setname(thread_key_mctx, "threadkey", NULL);
1306                 isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
1307
1308                 if (!thread_key_initialized &&
1309                      isc_thread_key_create(&totext_filter_proc_key,
1310                                            free_specific) != 0) {
1311                         result = ISC_R_FAILURE;
1312                         isc_mem_detach(&thread_key_mctx);
1313                 } else
1314                         thread_key_initialized = 1;
1315  unlock:
1316                 UNLOCK(&thread_key_mutex);
1317         }
1318         return (result);
1319 }
1320 #endif
1321
1322 isc_result_t
1323 dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
1324                 isc_buffer_t *target)
1325 {
1326         unsigned int options = DNS_NAME_MASTERFILE;
1327
1328         if (omit_final_dot)
1329                 options |= DNS_NAME_OMITFINALDOT;
1330         return (dns_name_totext2(name, options, target));
1331 }
1332
1333 isc_result_t
1334 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1335         return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1336 }
1337
1338 isc_result_t
1339 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1340 {
1341         unsigned char *ndata;
1342         char *tdata;
1343         unsigned int nlen, tlen;
1344         unsigned char c;
1345         unsigned int trem, count;
1346         unsigned int labels;
1347         isc_boolean_t saw_root = ISC_FALSE;
1348         unsigned int oused = target->used;
1349 #ifdef ISC_PLATFORM_USETHREADS
1350         dns_name_totextfilter_t *mem;
1351         dns_name_totextfilter_t totext_filter_proc = NULL;
1352         isc_result_t result;
1353 #endif
1354         isc_boolean_t omit_final_dot =
1355                 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1356
1357         /*
1358          * This function assumes the name is in proper uncompressed
1359          * wire format.
1360          */
1361         REQUIRE(VALID_NAME(name));
1362         REQUIRE(ISC_BUFFER_VALID(target));
1363
1364 #ifdef ISC_PLATFORM_USETHREADS
1365         result = totext_filter_proc_key_init();
1366         if (result != ISC_R_SUCCESS)
1367                 return (result);
1368 #endif
1369         ndata = name->ndata;
1370         nlen = name->length;
1371         labels = name->labels;
1372         tdata = isc_buffer_used(target);
1373         tlen = isc_buffer_availablelength(target);
1374
1375         trem = tlen;
1376
1377         if (labels == 0 && nlen == 0) {
1378                 /*
1379                  * Special handling for an empty name.
1380                  */
1381                 if (trem == 0)
1382                         return (ISC_R_NOSPACE);
1383
1384                 /*
1385                  * The names of these booleans are misleading in this case.
1386                  * This empty name is not necessarily from the root node of
1387                  * the DNS root zone, nor is a final dot going to be included.
1388                  * They need to be set this way, though, to keep the "@"
1389                  * from being trounced.
1390                  */
1391                 saw_root = ISC_TRUE;
1392                 omit_final_dot = ISC_FALSE;
1393                 *tdata++ = '@';
1394                 trem--;
1395
1396                 /*
1397                  * Skip the while() loop.
1398                  */
1399                 nlen = 0;
1400         } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1401                 /*
1402                  * Special handling for the root label.
1403                  */
1404                 if (trem == 0)
1405                         return (ISC_R_NOSPACE);
1406
1407                 saw_root = ISC_TRUE;
1408                 omit_final_dot = ISC_FALSE;
1409                 *tdata++ = '.';
1410                 trem--;
1411
1412                 /*
1413                  * Skip the while() loop.
1414                  */
1415                 nlen = 0;
1416         }
1417
1418         while (labels > 0 && nlen > 0 && trem > 0) {
1419                 labels--;
1420                 count = *ndata++;
1421                 nlen--;
1422                 if (count == 0) {
1423                         saw_root = ISC_TRUE;
1424                         break;
1425                 }
1426                 if (count < 64) {
1427                         INSIST(nlen >= count);
1428                         while (count > 0) {
1429                                 c = *ndata;
1430                                 switch (c) {
1431                                 /* Special modifiers in zone files. */
1432                                 case 0x40: /* '@' */
1433                                 case 0x24: /* '$' */
1434                                         if ((options & DNS_NAME_MASTERFILE) == 0)
1435                                                 goto no_escape;
1436                                         /* FALLTHROUGH */
1437                                 case 0x22: /* '"' */
1438                                 case 0x28: /* '(' */
1439                                 case 0x29: /* ')' */
1440                                 case 0x2E: /* '.' */
1441                                 case 0x3B: /* ';' */
1442                                 case 0x5C: /* '\\' */
1443                                         if (trem < 2)
1444                                                 return (ISC_R_NOSPACE);
1445                                         *tdata++ = '\\';
1446                                         CONVERTFROMASCII(c);
1447                                         *tdata++ = c;
1448                                         ndata++;
1449                                         trem -= 2;
1450                                         nlen--;
1451                                         break;
1452                                 no_escape:
1453                                 default:
1454                                         if (c > 0x20 && c < 0x7f) {
1455                                                 if (trem == 0)
1456                                                         return (ISC_R_NOSPACE);
1457                                                 CONVERTFROMASCII(c);
1458                                                 *tdata++ = c;
1459                                                 ndata++;
1460                                                 trem--;
1461                                                 nlen--;
1462                                         } else {
1463                                                 if (trem < 4)
1464                                                         return (ISC_R_NOSPACE);
1465                                                 *tdata++ = 0x5c;
1466                                                 *tdata++ = 0x30 +
1467                                                            ((c / 100) % 10);
1468                                                 *tdata++ = 0x30 +
1469                                                            ((c / 10) % 10);
1470                                                 *tdata++ = 0x30 + (c % 10);
1471                                                 trem -= 4;
1472                                                 ndata++;
1473                                                 nlen--;
1474                                         }
1475                                 }
1476                                 count--;
1477                         }
1478                 } else {
1479                         FATAL_ERROR(__FILE__, __LINE__,
1480                                     "Unexpected label type %02x", count);
1481                         /* NOTREACHED */
1482                 }
1483
1484                 /*
1485                  * The following assumes names are absolute.  If not, we
1486                  * fix things up later.  Note that this means that in some
1487                  * cases one more byte of text buffer is required than is
1488                  * needed in the final output.
1489                  */
1490                 if (trem == 0)
1491                         return (ISC_R_NOSPACE);
1492                 *tdata++ = '.';
1493                 trem--;
1494         }
1495
1496         if (nlen != 0 && trem == 0)
1497                 return (ISC_R_NOSPACE);
1498
1499         if (!saw_root || omit_final_dot)
1500                 trem++;
1501
1502         isc_buffer_add(target, tlen - trem);
1503
1504 #ifdef ISC_PLATFORM_USETHREADS
1505         mem = isc_thread_key_getspecific(totext_filter_proc_key);
1506         if (mem != NULL)
1507                 totext_filter_proc = *mem;
1508 #endif
1509         if (totext_filter_proc != NULL)
1510                 return ((*totext_filter_proc)(target, oused, saw_root));
1511
1512         return (ISC_R_SUCCESS);
1513 }
1514
1515 isc_result_t
1516 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1517                         isc_buffer_t *target)
1518 {
1519         unsigned char *ndata;
1520         char *tdata;
1521         unsigned int nlen, tlen;
1522         unsigned char c;
1523         unsigned int trem, count;
1524         unsigned int labels;
1525
1526         /*
1527          * This function assumes the name is in proper uncompressed
1528          * wire format.
1529          */
1530         REQUIRE(VALID_NAME(name));
1531         REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1532         REQUIRE(ISC_BUFFER_VALID(target));
1533
1534         ndata = name->ndata;
1535         nlen = name->length;
1536         labels = name->labels;
1537         tdata = isc_buffer_used(target);
1538         tlen = isc_buffer_availablelength(target);
1539
1540         trem = tlen;
1541
1542         if (nlen == 1 && labels == 1 && *ndata == '\0') {
1543                 /*
1544                  * Special handling for the root label.
1545                  */
1546                 if (trem == 0)
1547                         return (ISC_R_NOSPACE);
1548
1549                 omit_final_dot = ISC_FALSE;
1550                 *tdata++ = '.';
1551                 trem--;
1552
1553                 /*
1554                  * Skip the while() loop.
1555                  */
1556                 nlen = 0;
1557         }
1558
1559         while (labels > 0 && nlen > 0 && trem > 0) {
1560                 labels--;
1561                 count = *ndata++;
1562                 nlen--;
1563                 if (count == 0)
1564                         break;
1565                 if (count < 64) {
1566                         INSIST(nlen >= count);
1567                         while (count > 0) {
1568                                 c = *ndata;
1569                                 if ((c >= 0x30 && c <= 0x39) || /* digit */
1570                                     (c >= 0x41 && c <= 0x5A) || /* uppercase */
1571                                     (c >= 0x61 && c <= 0x7A) || /* lowercase */
1572                                     c == 0x2D ||                /* hyphen */
1573                                     c == 0x5F)                  /* underscore */
1574                                 {
1575                                         if (trem == 0)
1576                                                 return (ISC_R_NOSPACE);
1577                                         /* downcase */
1578                                         if (c >= 0x41 && c <= 0x5A)
1579                                                 c += 0x20;
1580                                         CONVERTFROMASCII(c);
1581                                         *tdata++ = c;
1582                                         ndata++;
1583                                         trem--;
1584                                         nlen--;
1585                                 } else {
1586                                         if (trem < 3)
1587                                                 return (ISC_R_NOSPACE);
1588                                         sprintf(tdata, "%%%02X", c);
1589                                         tdata += 3;
1590                                         trem -= 3;
1591                                         ndata++;
1592                                         nlen--;
1593                                 }
1594                                 count--;
1595                         }
1596                 } else {
1597                         FATAL_ERROR(__FILE__, __LINE__,
1598                                     "Unexpected label type %02x", count);
1599                         /* NOTREACHED */
1600                 }
1601
1602                 /*
1603                  * The following assumes names are absolute.  If not, we
1604                  * fix things up later.  Note that this means that in some
1605                  * cases one more byte of text buffer is required than is
1606                  * needed in the final output.
1607                  */
1608                 if (trem == 0)
1609                         return (ISC_R_NOSPACE);
1610                 *tdata++ = '.';
1611                 trem--;
1612         }
1613
1614         if (nlen != 0 && trem == 0)
1615                 return (ISC_R_NOSPACE);
1616
1617         if (omit_final_dot)
1618                 trem++;
1619
1620         isc_buffer_add(target, tlen - trem);
1621
1622         return (ISC_R_SUCCESS);
1623 }
1624
1625 isc_result_t
1626 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1627         unsigned char *sndata, *ndata;
1628         unsigned int nlen, count, labels;
1629         isc_buffer_t buffer;
1630
1631         /*
1632          * Downcase 'source'.
1633          */
1634
1635         REQUIRE(VALID_NAME(source));
1636         REQUIRE(VALID_NAME(name));
1637         if (source == name) {
1638                 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1639                 isc_buffer_init(&buffer, source->ndata, source->length);
1640                 target = &buffer;
1641                 ndata = source->ndata;
1642         } else {
1643                 REQUIRE(BINDABLE(name));
1644                 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1645                         (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1646                 if (target == NULL) {
1647                         target = name->buffer;
1648                         isc_buffer_clear(name->buffer);
1649                 }
1650                 ndata = (unsigned char *)target->base + target->used;
1651                 name->ndata = ndata;
1652         }
1653
1654         sndata = source->ndata;
1655         nlen = source->length;
1656         labels = source->labels;
1657
1658         if (nlen > (target->length - target->used)) {
1659                 MAKE_EMPTY(name);
1660                 return (ISC_R_NOSPACE);
1661         }
1662
1663         while (labels > 0 && nlen > 0) {
1664                 labels--;
1665                 count = *sndata++;
1666                 *ndata++ = count;
1667                 nlen--;
1668                 if (count < 64) {
1669                         INSIST(nlen >= count);
1670                         while (count > 0) {
1671                                 *ndata++ = maptolower[(*sndata++)];
1672                                 nlen--;
1673                                 count--;
1674                         }
1675                 } else {
1676                         FATAL_ERROR(__FILE__, __LINE__,
1677                                     "Unexpected label type %02x", count);
1678                         /* Does not return. */
1679                 }
1680         }
1681
1682         if (source != name) {
1683                 name->labels = source->labels;
1684                 name->length = source->length;
1685                 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1686                         name->attributes = DNS_NAMEATTR_ABSOLUTE;
1687                 else
1688                         name->attributes = 0;
1689                 if (name->labels > 0 && name->offsets != NULL)
1690                         set_offsets(name, name->offsets, NULL);
1691         }
1692
1693         isc_buffer_add(target, name->length);
1694
1695         return (ISC_R_SUCCESS);
1696 }
1697
1698 static void
1699 set_offsets(const dns_name_t *name, unsigned char *offsets,
1700             dns_name_t *set_name)
1701 {
1702         unsigned int offset, count, length, nlabels;
1703         unsigned char *ndata;
1704         isc_boolean_t absolute;
1705
1706         ndata = name->ndata;
1707         length = name->length;
1708         offset = 0;
1709         nlabels = 0;
1710         absolute = ISC_FALSE;
1711         while (offset != length) {
1712                 INSIST(nlabels < 128);
1713                 offsets[nlabels++] = offset;
1714                 count = *ndata++;
1715                 offset++;
1716                 INSIST(count <= 63);
1717                 offset += count;
1718                 ndata += count;
1719                 INSIST(offset <= length);
1720                 if (count == 0) {
1721                         absolute = ISC_TRUE;
1722                         break;
1723                 }
1724         }
1725         if (set_name != NULL) {
1726                 INSIST(set_name == name);
1727
1728                 set_name->labels = nlabels;
1729                 set_name->length = offset;
1730                 if (absolute)
1731                         set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1732                 else
1733                         set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1734         }
1735         INSIST(nlabels == name->labels);
1736         INSIST(offset == name->length);
1737 }
1738
1739 isc_result_t
1740 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1741                   dns_decompress_t *dctx, unsigned int options,
1742                   isc_buffer_t *target)
1743 {
1744         unsigned char *cdata, *ndata;
1745         unsigned int cused; /* Bytes of compressed name data used */
1746         unsigned int nused, labels, n, nmax;
1747         unsigned int current, new_current, biggest_pointer;
1748         isc_boolean_t done;
1749         fw_state state = fw_start;
1750         unsigned int c;
1751         unsigned char *offsets;
1752         dns_offsets_t odata;
1753         isc_boolean_t downcase;
1754         isc_boolean_t seen_pointer;
1755
1756         /*
1757          * Copy the possibly-compressed name at source into target,
1758          * decompressing it.  Loop prevention is performed by checking
1759          * the new pointer against biggest_pointer.
1760          */
1761
1762         REQUIRE(VALID_NAME(name));
1763         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1764                 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1765
1766         downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1767
1768         if (target == NULL && name->buffer != NULL) {
1769                 target = name->buffer;
1770                 isc_buffer_clear(target);
1771         }
1772
1773         REQUIRE(dctx != NULL);
1774         REQUIRE(BINDABLE(name));
1775
1776         INIT_OFFSETS(name, offsets, odata);
1777
1778         /*
1779          * Make 'name' empty in case of failure.
1780          */
1781         MAKE_EMPTY(name);
1782
1783         /*
1784          * Initialize things to make the compiler happy; they're not required.
1785          */
1786         n = 0;
1787         new_current = 0;
1788
1789         /*
1790          * Set up.
1791          */
1792         labels = 0;
1793         done = ISC_FALSE;
1794
1795         ndata = isc_buffer_used(target);
1796         nused = 0;
1797         seen_pointer = ISC_FALSE;
1798
1799         /*
1800          * Find the maximum number of uncompressed target name
1801          * bytes we are willing to generate.  This is the smaller
1802          * of the available target buffer length and the
1803          * maximum legal domain name length (255).
1804          */
1805         nmax = isc_buffer_availablelength(target);
1806         if (nmax > DNS_NAME_MAXWIRE)
1807                 nmax = DNS_NAME_MAXWIRE;
1808
1809         cdata = isc_buffer_current(source);
1810         cused = 0;
1811
1812         current = source->current;
1813         biggest_pointer = current;
1814
1815         /*
1816          * Note:  The following code is not optimized for speed, but
1817          * rather for correctness.  Speed will be addressed in the future.
1818          */
1819
1820         while (current < source->active && !done) {
1821                 c = *cdata++;
1822                 current++;
1823                 if (!seen_pointer)
1824                         cused++;
1825
1826                 switch (state) {
1827                 case fw_start:
1828                         if (c < 64) {
1829                                 offsets[labels] = nused;
1830                                 labels++;
1831                                 if (nused + c + 1 > nmax)
1832                                         goto full;
1833                                 nused += c + 1;
1834                                 *ndata++ = c;
1835                                 if (c == 0)
1836                                         done = ISC_TRUE;
1837                                 n = c;
1838                                 state = fw_ordinary;
1839                         } else if (c >= 128 && c < 192) {
1840                                 /*
1841                                  * 14 bit local compression pointer.
1842                                  * Local compression is no longer an
1843                                  * IETF draft.
1844                                  */
1845                                 return (DNS_R_BADLABELTYPE);
1846                         } else if (c >= 192) {
1847                                 /*
1848                                  * Ordinary 14-bit pointer.
1849                                  */
1850                                 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1851                                     0)
1852                                         return (DNS_R_DISALLOWED);
1853                                 new_current = c & 0x3F;
1854                                 n = 1;
1855                                 state = fw_newcurrent;
1856                         } else
1857                                 return (DNS_R_BADLABELTYPE);
1858                         break;
1859                 case fw_ordinary:
1860                         if (downcase)
1861                                 c = maptolower[c];
1862                         /* FALLTHROUGH */
1863                 case fw_copy:
1864                         *ndata++ = c;
1865                         n--;
1866                         if (n == 0)
1867                                 state = fw_start;
1868                         break;
1869                 case fw_newcurrent:
1870                         new_current *= 256;
1871                         new_current += c;
1872                         n--;
1873                         if (n != 0)
1874                                 break;
1875                         if (new_current >= biggest_pointer)
1876                                 return (DNS_R_BADPOINTER);
1877                         biggest_pointer = new_current;
1878                         current = new_current;
1879                         cdata = (unsigned char *)source->base + current;
1880                         seen_pointer = ISC_TRUE;
1881                         state = fw_start;
1882                         break;
1883                 default:
1884                         FATAL_ERROR(__FILE__, __LINE__,
1885                                     "Unknown state %d", state);
1886                         /* Does not return. */
1887                 }
1888         }
1889
1890         if (!done)
1891                 return (ISC_R_UNEXPECTEDEND);
1892
1893         name->ndata = (unsigned char *)target->base + target->used;
1894         name->labels = labels;
1895         name->length = nused;
1896         name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1897
1898         isc_buffer_forward(source, cused);
1899         isc_buffer_add(target, name->length);
1900
1901         return (ISC_R_SUCCESS);
1902
1903  full:
1904         if (nmax == DNS_NAME_MAXWIRE)
1905                 /*
1906                  * The name did not fit even though we had a buffer
1907                  * big enough to fit a maximum-length name.
1908                  */
1909                 return (DNS_R_NAMETOOLONG);
1910         else
1911                 /*
1912                  * The name might fit if only the caller could give us a
1913                  * big enough buffer.
1914                  */
1915                 return (ISC_R_NOSPACE);
1916 }
1917
1918 isc_result_t
1919 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1920                 isc_buffer_t *target)
1921 {
1922         unsigned int methods;
1923         isc_uint16_t offset;
1924         dns_name_t gp;  /* Global compression prefix */
1925         isc_boolean_t gf;       /* Global compression target found */
1926         isc_uint16_t go;        /* Global compression offset */
1927         dns_offsets_t clo;
1928         dns_name_t clname;
1929
1930         /*
1931          * Convert 'name' into wire format, compressing it as specified by the
1932          * compression context 'cctx', and storing the result in 'target'.
1933          */
1934
1935         REQUIRE(VALID_NAME(name));
1936         REQUIRE(cctx != NULL);
1937         REQUIRE(ISC_BUFFER_VALID(target));
1938
1939         /*
1940          * If 'name' doesn't have an offsets table, make a clone which
1941          * has one.
1942          */
1943         if (name->offsets == NULL) {
1944 #if defined(__clang__)  && \
1945        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
1946                 memset(&clname, 0, sizeof(clname));
1947 #endif
1948                 DNS_NAME_INIT(&clname, clo);
1949                 dns_name_clone(name, &clname);
1950                 name = &clname;
1951         }
1952         DNS_NAME_INIT(&gp, NULL);
1953
1954         offset = target->used;  /*XXX*/
1955
1956         methods = dns_compress_getmethods(cctx);
1957
1958         if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1959             (methods & DNS_COMPRESS_GLOBAL14) != 0)
1960                 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1961         else
1962                 gf = ISC_FALSE;
1963
1964         /*
1965          * If the offset is too high for 14 bit global compression, we're
1966          * out of luck.
1967          */
1968         if (gf && go >= 0x4000)
1969                 gf = ISC_FALSE;
1970
1971         /*
1972          * Will the compression pointer reduce the message size?
1973          */
1974         if (gf && (gp.length + 2) >= name->length)
1975                 gf = ISC_FALSE;
1976
1977         if (gf) {
1978                 if (target->length - target->used < gp.length)
1979                         return (ISC_R_NOSPACE);
1980                 (void)memcpy((unsigned char *)target->base + target->used,
1981                              gp.ndata, (size_t)gp.length);
1982                 isc_buffer_add(target, gp.length);
1983                 go |= 0xc000;
1984                 if (target->length - target->used < 2)
1985                         return (ISC_R_NOSPACE);
1986                 isc_buffer_putuint16(target, go);
1987                 if (gp.length != 0)
1988                         dns_compress_add(cctx, name, &gp, offset);
1989         } else {
1990                 if (target->length - target->used < name->length)
1991                         return (ISC_R_NOSPACE);
1992                 (void)memcpy((unsigned char *)target->base + target->used,
1993                              name->ndata, (size_t)name->length);
1994                 isc_buffer_add(target, name->length);
1995                 dns_compress_add(cctx, name, name, offset);
1996         }
1997         return (ISC_R_SUCCESS);
1998 }
1999
2000 isc_result_t
2001 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
2002                      isc_buffer_t *target)
2003 {
2004         unsigned char *ndata, *offsets;
2005         unsigned int nrem, labels, prefix_length, length;
2006         isc_boolean_t copy_prefix = ISC_TRUE;
2007         isc_boolean_t copy_suffix = ISC_TRUE;
2008         isc_boolean_t absolute = ISC_FALSE;
2009         dns_name_t tmp_name;
2010         dns_offsets_t odata;
2011
2012         /*
2013          * Concatenate 'prefix' and 'suffix'.
2014          */
2015
2016         REQUIRE(prefix == NULL || VALID_NAME(prefix));
2017         REQUIRE(suffix == NULL || VALID_NAME(suffix));
2018         REQUIRE(name == NULL || VALID_NAME(name));
2019         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2020                 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2021         if (prefix == NULL || prefix->labels == 0)
2022                 copy_prefix = ISC_FALSE;
2023         if (suffix == NULL || suffix->labels == 0)
2024                 copy_suffix = ISC_FALSE;
2025         if (copy_prefix &&
2026             (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2027                 absolute = ISC_TRUE;
2028                 REQUIRE(!copy_suffix);
2029         }
2030         if (name == NULL) {
2031                 DNS_NAME_INIT(&tmp_name, odata);
2032                 name = &tmp_name;
2033         }
2034         if (target == NULL) {
2035                 INSIST(name->buffer != NULL);
2036                 target = name->buffer;
2037                 isc_buffer_clear(name->buffer);
2038         }
2039
2040         REQUIRE(BINDABLE(name));
2041
2042         /*
2043          * Set up.
2044          */
2045         nrem = target->length - target->used;
2046         ndata = (unsigned char *)target->base + target->used;
2047         if (nrem > DNS_NAME_MAXWIRE)
2048                 nrem = DNS_NAME_MAXWIRE;
2049         length = 0;
2050         prefix_length = 0;
2051         labels = 0;
2052         if (copy_prefix) {
2053                 prefix_length = prefix->length;
2054                 length += prefix_length;
2055                 labels += prefix->labels;
2056         }
2057         if (copy_suffix) {
2058                 length += suffix->length;
2059                 labels += suffix->labels;
2060         }
2061         if (length > DNS_NAME_MAXWIRE) {
2062                 MAKE_EMPTY(name);
2063                 return (DNS_R_NAMETOOLONG);
2064         }
2065         if (length > nrem) {
2066                 MAKE_EMPTY(name);
2067                 return (ISC_R_NOSPACE);
2068         }
2069
2070         if (copy_suffix) {
2071                 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2072                         absolute = ISC_TRUE;
2073                 if (suffix == name && suffix->buffer == target)
2074                         memmove(ndata + prefix_length, suffix->ndata,
2075                                 suffix->length);
2076                 else
2077                         memcpy(ndata + prefix_length, suffix->ndata,
2078                                suffix->length);
2079         }
2080
2081         /*
2082          * If 'prefix' and 'name' are the same object, and the object has
2083          * a dedicated buffer, and we're using it, then we don't have to
2084          * copy anything.
2085          */
2086         if (copy_prefix && (prefix != name || prefix->buffer != target))
2087                 memcpy(ndata, prefix->ndata, prefix_length);
2088
2089         name->ndata = ndata;
2090         name->labels = labels;
2091         name->length = length;
2092         if (absolute)
2093                 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2094         else
2095                 name->attributes = 0;
2096
2097         if (name->labels > 0 && name->offsets != NULL) {
2098                 INIT_OFFSETS(name, offsets, odata);
2099                 set_offsets(name, offsets, NULL);
2100         }
2101
2102         isc_buffer_add(target, name->length);
2103
2104         return (ISC_R_SUCCESS);
2105 }
2106
2107 void
2108 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2109                dns_name_t *prefix, dns_name_t *suffix)
2110
2111 {
2112         unsigned int splitlabel;
2113
2114         REQUIRE(VALID_NAME(name));
2115         REQUIRE(suffixlabels > 0);
2116         REQUIRE(suffixlabels < name->labels);
2117         REQUIRE(prefix != NULL || suffix != NULL);
2118         REQUIRE(prefix == NULL ||
2119                 (VALID_NAME(prefix) &&
2120                  prefix->buffer != NULL &&
2121                  BINDABLE(prefix)));
2122         REQUIRE(suffix == NULL ||
2123                 (VALID_NAME(suffix) &&
2124                  suffix->buffer != NULL &&
2125                  BINDABLE(suffix)));
2126
2127         splitlabel = name->labels - suffixlabels;
2128
2129         if (prefix != NULL)
2130                 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2131
2132         if (suffix != NULL)
2133                 dns_name_getlabelsequence(name, splitlabel,
2134                                           suffixlabels, suffix);
2135
2136         return;
2137 }
2138
2139 isc_result_t
2140 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2141              dns_name_t *target)
2142 {
2143         /*
2144          * Make 'target' a dynamically allocated copy of 'source'.
2145          */
2146
2147         REQUIRE(VALID_NAME(source));
2148         REQUIRE(source->length > 0);
2149         REQUIRE(VALID_NAME(target));
2150         REQUIRE(BINDABLE(target));
2151
2152         /*
2153          * Make 'target' empty in case of failure.
2154          */
2155         MAKE_EMPTY(target);
2156
2157         target->ndata = isc_mem_get(mctx, source->length);
2158         if (target->ndata == NULL)
2159                 return (ISC_R_NOMEMORY);
2160
2161         memcpy(target->ndata, source->ndata, source->length);
2162
2163         target->length = source->length;
2164         target->labels = source->labels;
2165         target->attributes = DNS_NAMEATTR_DYNAMIC;
2166         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2167                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2168         if (target->offsets != NULL) {
2169                 if (source->offsets != NULL)
2170                         memcpy(target->offsets, source->offsets,
2171                                source->labels);
2172                 else
2173                         set_offsets(target, target->offsets, NULL);
2174         }
2175
2176         return (ISC_R_SUCCESS);
2177 }
2178
2179 isc_result_t
2180 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2181                         dns_name_t *target)
2182 {
2183         /*
2184          * Make 'target' a read-only dynamically allocated copy of 'source'.
2185          * 'target' will also have a dynamically allocated offsets table.
2186          */
2187
2188         REQUIRE(VALID_NAME(source));
2189         REQUIRE(source->length > 0);
2190         REQUIRE(VALID_NAME(target));
2191         REQUIRE(BINDABLE(target));
2192         REQUIRE(target->offsets == NULL);
2193
2194         /*
2195          * Make 'target' empty in case of failure.
2196          */
2197         MAKE_EMPTY(target);
2198
2199         target->ndata = isc_mem_get(mctx, source->length + source->labels);
2200         if (target->ndata == NULL)
2201                 return (ISC_R_NOMEMORY);
2202
2203         memcpy(target->ndata, source->ndata, source->length);
2204
2205         target->length = source->length;
2206         target->labels = source->labels;
2207         target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2208                 DNS_NAMEATTR_READONLY;
2209         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2210                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2211         target->offsets = target->ndata + source->length;
2212         if (source->offsets != NULL)
2213                 memcpy(target->offsets, source->offsets, source->labels);
2214         else
2215                 set_offsets(target, target->offsets, NULL);
2216
2217         return (ISC_R_SUCCESS);
2218 }
2219
2220 void
2221 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2222         size_t size;
2223
2224         /*
2225          * Free 'name'.
2226          */
2227
2228         REQUIRE(VALID_NAME(name));
2229         REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2230
2231         size = name->length;
2232         if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2233                 size += name->labels;
2234         isc_mem_put(mctx, name->ndata, size);
2235         dns_name_invalidate(name);
2236 }
2237
2238 isc_result_t
2239 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2240         dns_name_t downname;
2241         unsigned char data[256];
2242         isc_buffer_t buffer;
2243         isc_result_t result;
2244         isc_region_t r;
2245
2246         /*
2247          * Send 'name' in DNSSEC canonical form to 'digest'.
2248          */
2249
2250         REQUIRE(VALID_NAME(name));
2251         REQUIRE(digest != NULL);
2252
2253 #if defined(__clang__)  && \
2254        ( __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2))
2255         memset(&downname, 0, sizeof(downname));
2256 #endif
2257         DNS_NAME_INIT(&downname, NULL);
2258
2259         isc_buffer_init(&buffer, data, sizeof(data));
2260
2261         result = dns_name_downcase(name, &downname, &buffer);
2262         if (result != ISC_R_SUCCESS)
2263                 return (result);
2264
2265         isc_buffer_usedregion(&buffer, &r);
2266
2267         return ((digest)(arg, &r));
2268 }
2269
2270 isc_boolean_t
2271 dns_name_dynamic(dns_name_t *name) {
2272         REQUIRE(VALID_NAME(name));
2273
2274         /*
2275          * Returns whether there is dynamic memory associated with this name.
2276          */
2277
2278         return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2279                 ISC_TRUE : ISC_FALSE);
2280 }
2281
2282 isc_result_t
2283 dns_name_print(dns_name_t *name, FILE *stream) {
2284         isc_result_t result;
2285         isc_buffer_t b;
2286         isc_region_t r;
2287         char t[1024];
2288
2289         /*
2290          * Print 'name' on 'stream'.
2291          */
2292
2293         REQUIRE(VALID_NAME(name));
2294
2295         isc_buffer_init(&b, t, sizeof(t));
2296         result = dns_name_totext(name, ISC_FALSE, &b);
2297         if (result != ISC_R_SUCCESS)
2298                 return (result);
2299         isc_buffer_usedregion(&b, &r);
2300         fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2301
2302         return (ISC_R_SUCCESS);
2303 }
2304
2305 isc_result_t
2306 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2307 #ifdef ISC_PLATFORM_USETHREADS
2308         isc_result_t result;
2309         dns_name_totextfilter_t *mem;
2310         int res;
2311
2312         result = totext_filter_proc_key_init();
2313         if (result != ISC_R_SUCCESS)
2314                 return (result);
2315
2316         /*
2317          * If we already have been here set / clear as appropriate.
2318          * Otherwise allocate memory.
2319          */
2320         mem = isc_thread_key_getspecific(totext_filter_proc_key);
2321         if (mem != NULL && proc != NULL) {
2322                 *mem = proc;
2323                 return (ISC_R_SUCCESS);
2324         }
2325         if (proc == NULL) {
2326                 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2327                 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2328                 if (res != 0)
2329                         result = ISC_R_UNEXPECTED;
2330                 return (result);
2331         }
2332
2333         mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2334         if (mem == NULL)
2335                 return (ISC_R_NOMEMORY);
2336         *mem = proc;
2337         if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2338                 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2339                 result = ISC_R_UNEXPECTED;
2340         }
2341         return (result);
2342 #else
2343         totext_filter_proc = proc;
2344         return (ISC_R_SUCCESS);
2345 #endif
2346 }
2347
2348 void
2349 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2350         isc_result_t result;
2351         isc_buffer_t buf;
2352
2353         REQUIRE(size > 0);
2354
2355         /*
2356          * Leave room for null termination after buffer.
2357          */
2358         isc_buffer_init(&buf, cp, size - 1);
2359         result = dns_name_totext(name, ISC_TRUE, &buf);
2360         if (result == ISC_R_SUCCESS) {
2361                 /*
2362                  * Null terminate.
2363                  */
2364                 isc_region_t r;
2365                 isc_buffer_usedregion(&buf, &r);
2366                 ((char *) r.base)[r.length] = '\0';
2367
2368         } else
2369                 snprintf(cp, size, "<unknown>");
2370 }
2371
2372 /*
2373  * dns_name_tostring() -- similar to dns_name_format() but allocates its own
2374  * memory.
2375  */
2376 isc_result_t
2377 dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) {
2378         isc_result_t result;
2379         isc_buffer_t buf;
2380         isc_region_t reg;
2381         char *p, txt[DNS_NAME_FORMATSIZE];
2382
2383         REQUIRE(VALID_NAME(name));
2384         REQUIRE(target != NULL && *target == NULL);
2385
2386         isc_buffer_init(&buf, txt, sizeof(txt));
2387         result = dns_name_totext(name, ISC_FALSE, &buf);
2388         if (result != ISC_R_SUCCESS)
2389                 return (result);
2390
2391         isc_buffer_usedregion(&buf, &reg);
2392         p = isc_mem_allocate(mctx, reg.length + 1);
2393         memcpy(p, (char *) reg.base, (int) reg.length);
2394         p[reg.length] = '\0';
2395
2396         *target = p;
2397         return (ISC_R_SUCCESS);
2398 }
2399
2400 /*
2401  * dns_name_fromstring() -- convert directly from a string to a name,
2402  * allocating memory as needed
2403  */
2404 isc_result_t
2405 dns_name_fromstring(dns_name_t *target, const char *src, unsigned int options,
2406                     isc_mem_t *mctx)
2407 {
2408         return (dns_name_fromstring2(target, src, dns_rootname, options, mctx));
2409 }
2410
2411 isc_result_t
2412 dns_name_fromstring2(dns_name_t *target, const char *src,
2413                      const dns_name_t *origin, unsigned int options,
2414                      isc_mem_t *mctx)
2415 {
2416         isc_result_t result;
2417         isc_buffer_t buf;
2418         dns_fixedname_t fn;
2419         dns_name_t *name;
2420
2421         REQUIRE(src != NULL);
2422
2423         isc_buffer_constinit(&buf, src, strlen(src));
2424         isc_buffer_add(&buf, strlen(src));
2425         if (BINDABLE(target) && target->buffer != NULL)
2426                 name = target;
2427         else {
2428                 dns_fixedname_init(&fn);
2429                 name = dns_fixedname_name(&fn);
2430         }
2431
2432         result = dns_name_fromtext(name, &buf, origin, options, NULL);
2433         if (result != ISC_R_SUCCESS)
2434                 return (result);
2435
2436         if (name != target)
2437                 result = dns_name_dupwithoffsets(name, mctx, target);
2438         return (result);
2439 }
2440
2441 isc_result_t
2442 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2443         unsigned char *ndata;
2444
2445         /*
2446          * Make dest a copy of source.
2447          */
2448
2449         REQUIRE(VALID_NAME(source));
2450         REQUIRE(VALID_NAME(dest));
2451         REQUIRE(target != NULL || dest->buffer != NULL);
2452
2453         if (target == NULL) {
2454                 target = dest->buffer;
2455                 isc_buffer_clear(dest->buffer);
2456         }
2457
2458         REQUIRE(BINDABLE(dest));
2459
2460         /*
2461          * Set up.
2462          */
2463         if (target->length - target->used < source->length)
2464                 return (ISC_R_NOSPACE);
2465
2466         ndata = (unsigned char *)target->base + target->used;
2467         dest->ndata = target->base;
2468
2469         memcpy(ndata, source->ndata, source->length);
2470
2471         dest->ndata = ndata;
2472         dest->labels = source->labels;
2473         dest->length = source->length;
2474         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2475                 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2476         else
2477                 dest->attributes = 0;
2478
2479         if (dest->labels > 0 && dest->offsets != NULL) {
2480                 if (source->offsets != NULL)
2481                         memcpy(dest->offsets, source->offsets, source->labels);
2482                 else
2483                         set_offsets(dest, dest->offsets, NULL);
2484         }
2485
2486         isc_buffer_add(target, dest->length);
2487
2488         return (ISC_R_SUCCESS);
2489 }
2490
2491 void
2492 dns_name_destroy(void) {
2493 #ifdef ISC_PLATFORM_USETHREADS
2494         RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2495                                   == ISC_R_SUCCESS);
2496
2497         LOCK(&thread_key_mutex);
2498         if (thread_key_initialized) {
2499                 isc_mem_detach(&thread_key_mctx);
2500                 isc_thread_key_delete(totext_filter_proc_key);
2501                 thread_key_initialized = 0;
2502         }
2503         UNLOCK(&thread_key_mutex);
2504
2505 #endif
2506 }