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