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