]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bind9/lib/dns/name.c
Update dialog to 1.1-20110707.
[FreeBSD/FreeBSD.git] / contrib / bind9 / lib / dns / name.c
1 /*
2  * Copyright (C) 2004-2008, 2010  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.165.120.3 2010-07-09 05:15:05 each 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(n <= source->labels - first); /* note first+n could overflow */
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 int options = DNS_NAME_MASTERFILE;
1328
1329         if (omit_final_dot)
1330                 options |= DNS_NAME_OMITFINALDOT;
1331         return (dns_name_totext2(name, options, target));
1332 }
1333
1334 isc_result_t
1335 dns_name_toprincipal(dns_name_t *name, isc_buffer_t *target) {
1336         return (dns_name_totext2(name, DNS_NAME_OMITFINALDOT, target));
1337 }
1338
1339 isc_result_t
1340 dns_name_totext2(dns_name_t *name, unsigned int options, isc_buffer_t *target)
1341 {
1342         unsigned char *ndata;
1343         char *tdata;
1344         unsigned int nlen, tlen;
1345         unsigned char c;
1346         unsigned int trem, count;
1347         unsigned int labels;
1348         isc_boolean_t saw_root = ISC_FALSE;
1349         unsigned int oused = target->used;
1350 #ifdef ISC_PLATFORM_USETHREADS
1351         dns_name_totextfilter_t *mem;
1352         dns_name_totextfilter_t totext_filter_proc = NULL;
1353         isc_result_t result;
1354 #endif
1355         isc_boolean_t omit_final_dot =
1356                 ISC_TF(options & DNS_NAME_OMITFINALDOT);
1357
1358         /*
1359          * This function assumes the name is in proper uncompressed
1360          * wire format.
1361          */
1362         REQUIRE(VALID_NAME(name));
1363         REQUIRE(ISC_BUFFER_VALID(target));
1364
1365 #ifdef ISC_PLATFORM_USETHREADS
1366         result = totext_filter_proc_key_init();
1367         if (result != ISC_R_SUCCESS)
1368                 return (result);
1369 #endif
1370         ndata = name->ndata;
1371         nlen = name->length;
1372         labels = name->labels;
1373         tdata = isc_buffer_used(target);
1374         tlen = isc_buffer_availablelength(target);
1375
1376         trem = tlen;
1377
1378         if (labels == 0 && nlen == 0) {
1379                 /*
1380                  * Special handling for an empty name.
1381                  */
1382                 if (trem == 0)
1383                         return (ISC_R_NOSPACE);
1384
1385                 /*
1386                  * The names of these booleans are misleading in this case.
1387                  * This empty name is not necessarily from the root node of
1388                  * the DNS root zone, nor is a final dot going to be included.
1389                  * They need to be set this way, though, to keep the "@"
1390                  * from being trounced.
1391                  */
1392                 saw_root = ISC_TRUE;
1393                 omit_final_dot = ISC_FALSE;
1394                 *tdata++ = '@';
1395                 trem--;
1396
1397                 /*
1398                  * Skip the while() loop.
1399                  */
1400                 nlen = 0;
1401         } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1402                 /*
1403                  * Special handling for the root label.
1404                  */
1405                 if (trem == 0)
1406                         return (ISC_R_NOSPACE);
1407
1408                 saw_root = ISC_TRUE;
1409                 omit_final_dot = ISC_FALSE;
1410                 *tdata++ = '.';
1411                 trem--;
1412
1413                 /*
1414                  * Skip the while() loop.
1415                  */
1416                 nlen = 0;
1417         }
1418
1419         while (labels > 0 && nlen > 0 && trem > 0) {
1420                 labels--;
1421                 count = *ndata++;
1422                 nlen--;
1423                 if (count == 0) {
1424                         saw_root = ISC_TRUE;
1425                         break;
1426                 }
1427                 if (count < 64) {
1428                         INSIST(nlen >= count);
1429                         while (count > 0) {
1430                                 c = *ndata;
1431                                 switch (c) {
1432                                 /* Special modifiers in zone files. */
1433                                 case 0x40: /* '@' */
1434                                 case 0x24: /* '$' */
1435                                         if ((options & DNS_NAME_MASTERFILE) == 0)
1436                                                 goto no_escape;
1437                                 case 0x22: /* '"' */
1438                                 case 0x28: /* '(' */
1439                                 case 0x29: /* ')' */
1440                                 case 0x2E: /* '.' */
1441                                 case 0x3B: /* ';' */
1442                                 case 0x5C: /* '\\' */
1443                                         if (trem < 2)
1444                                                 return (ISC_R_NOSPACE);
1445                                         *tdata++ = '\\';
1446                                         CONVERTFROMASCII(c);
1447                                         *tdata++ = c;
1448                                         ndata++;
1449                                         trem -= 2;
1450                                         nlen--;
1451                                         break;
1452                                 no_escape:
1453                                 default:
1454                                         if (c > 0x20 && c < 0x7f) {
1455                                                 if (trem == 0)
1456                                                         return (ISC_R_NOSPACE);
1457                                                 CONVERTFROMASCII(c);
1458                                                 *tdata++ = c;
1459                                                 ndata++;
1460                                                 trem--;
1461                                                 nlen--;
1462                                         } else {
1463                                                 if (trem < 4)
1464                                                         return (ISC_R_NOSPACE);
1465                                                 *tdata++ = 0x5c;
1466                                                 *tdata++ = 0x30 +
1467                                                            ((c / 100) % 10);
1468                                                 *tdata++ = 0x30 +
1469                                                            ((c / 10) % 10);
1470                                                 *tdata++ = 0x30 + (c % 10);
1471                                                 trem -= 4;
1472                                                 ndata++;
1473                                                 nlen--;
1474                                         }
1475                                 }
1476                                 count--;
1477                         }
1478                 } else {
1479                         FATAL_ERROR(__FILE__, __LINE__,
1480                                     "Unexpected label type %02x", count);
1481                         /* NOTREACHED */
1482                 }
1483
1484                 /*
1485                  * The following assumes names are absolute.  If not, we
1486                  * fix things up later.  Note that this means that in some
1487                  * cases one more byte of text buffer is required than is
1488                  * needed in the final output.
1489                  */
1490                 if (trem == 0)
1491                         return (ISC_R_NOSPACE);
1492                 *tdata++ = '.';
1493                 trem--;
1494         }
1495
1496         if (nlen != 0 && trem == 0)
1497                 return (ISC_R_NOSPACE);
1498
1499         if (!saw_root || omit_final_dot)
1500                 trem++;
1501
1502         isc_buffer_add(target, tlen - trem);
1503
1504 #ifdef ISC_PLATFORM_USETHREADS
1505         mem = isc_thread_key_getspecific(totext_filter_proc_key);
1506         if (mem != NULL)
1507                 totext_filter_proc = *mem;
1508 #endif
1509         if (totext_filter_proc != NULL)
1510                 return ((*totext_filter_proc)(target, oused, saw_root));
1511
1512         return (ISC_R_SUCCESS);
1513 }
1514
1515 isc_result_t
1516 dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
1517                         isc_buffer_t *target)
1518 {
1519         unsigned char *ndata;
1520         char *tdata;
1521         unsigned int nlen, tlen;
1522         unsigned char c;
1523         unsigned int trem, count;
1524         unsigned int labels;
1525
1526         /*
1527          * This function assumes the name is in proper uncompressed
1528          * wire format.
1529          */
1530         REQUIRE(VALID_NAME(name));
1531         REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
1532         REQUIRE(ISC_BUFFER_VALID(target));
1533
1534         ndata = name->ndata;
1535         nlen = name->length;
1536         labels = name->labels;
1537         tdata = isc_buffer_used(target);
1538         tlen = isc_buffer_availablelength(target);
1539
1540         trem = tlen;
1541
1542         if (nlen == 1 && labels == 1 && *ndata == '\0') {
1543                 /*
1544                  * Special handling for the root label.
1545                  */
1546                 if (trem == 0)
1547                         return (ISC_R_NOSPACE);
1548
1549                 omit_final_dot = ISC_FALSE;
1550                 *tdata++ = '.';
1551                 trem--;
1552
1553                 /*
1554                  * Skip the while() loop.
1555                  */
1556                 nlen = 0;
1557         }
1558
1559         while (labels > 0 && nlen > 0 && trem > 0) {
1560                 labels--;
1561                 count = *ndata++;
1562                 nlen--;
1563                 if (count == 0)
1564                         break;
1565                 if (count < 64) {
1566                         INSIST(nlen >= count);
1567                         while (count > 0) {
1568                                 c = *ndata;
1569                                 if ((c >= 0x30 && c <= 0x39) || /* digit */
1570                                     (c >= 0x41 && c <= 0x5A) || /* uppercase */
1571                                     (c >= 0x61 && c <= 0x7A) || /* lowercase */
1572                                     c == 0x2D ||                /* hyphen */
1573                                     c == 0x5F)                  /* underscore */
1574                                 {
1575                                         if (trem == 0)
1576                                                 return (ISC_R_NOSPACE);
1577                                         /* downcase */
1578                                         if (c >= 0x41 && c <= 0x5A)
1579                                                 c += 0x20;
1580                                         CONVERTFROMASCII(c);
1581                                         *tdata++ = c;
1582                                         ndata++;
1583                                         trem--;
1584                                         nlen--;
1585                                 } else {
1586                                         if (trem < 3)
1587                                                 return (ISC_R_NOSPACE);
1588                                         sprintf(tdata, "%%%02X", c);
1589                                         tdata += 3;
1590                                         trem -= 3;
1591                                         ndata++;
1592                                         nlen--;
1593                                 }
1594                                 count--;
1595                         }
1596                 } else {
1597                         FATAL_ERROR(__FILE__, __LINE__,
1598                                     "Unexpected label type %02x", count);
1599                         /* NOTREACHED */
1600                 }
1601
1602                 /*
1603                  * The following assumes names are absolute.  If not, we
1604                  * fix things up later.  Note that this means that in some
1605                  * cases one more byte of text buffer is required than is
1606                  * needed in the final output.
1607                  */
1608                 if (trem == 0)
1609                         return (ISC_R_NOSPACE);
1610                 *tdata++ = '.';
1611                 trem--;
1612         }
1613
1614         if (nlen != 0 && trem == 0)
1615                 return (ISC_R_NOSPACE);
1616
1617         if (omit_final_dot)
1618                 trem++;
1619
1620         isc_buffer_add(target, tlen - trem);
1621
1622         return (ISC_R_SUCCESS);
1623 }
1624
1625 isc_result_t
1626 dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
1627         unsigned char *sndata, *ndata;
1628         unsigned int nlen, count, labels;
1629         isc_buffer_t buffer;
1630
1631         /*
1632          * Downcase 'source'.
1633          */
1634
1635         REQUIRE(VALID_NAME(source));
1636         REQUIRE(VALID_NAME(name));
1637         if (source == name) {
1638                 REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
1639                 isc_buffer_init(&buffer, source->ndata, source->length);
1640                 target = &buffer;
1641                 ndata = source->ndata;
1642         } else {
1643                 REQUIRE(BINDABLE(name));
1644                 REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1645                         (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1646                 if (target == NULL) {
1647                         target = name->buffer;
1648                         isc_buffer_clear(name->buffer);
1649                 }
1650                 ndata = (unsigned char *)target->base + target->used;
1651                 name->ndata = ndata;
1652         }
1653
1654         sndata = source->ndata;
1655         nlen = source->length;
1656         labels = source->labels;
1657
1658         if (nlen > (target->length - target->used)) {
1659                 MAKE_EMPTY(name);
1660                 return (ISC_R_NOSPACE);
1661         }
1662
1663         while (labels > 0 && nlen > 0) {
1664                 labels--;
1665                 count = *sndata++;
1666                 *ndata++ = count;
1667                 nlen--;
1668                 if (count < 64) {
1669                         INSIST(nlen >= count);
1670                         while (count > 0) {
1671                                 *ndata++ = maptolower[(*sndata++)];
1672                                 nlen--;
1673                                 count--;
1674                         }
1675                 } else {
1676                         FATAL_ERROR(__FILE__, __LINE__,
1677                                     "Unexpected label type %02x", count);
1678                         /* Does not return. */
1679                 }
1680         }
1681
1682         if (source != name) {
1683                 name->labels = source->labels;
1684                 name->length = source->length;
1685                 if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1686                         name->attributes = DNS_NAMEATTR_ABSOLUTE;
1687                 else
1688                         name->attributes = 0;
1689                 if (name->labels > 0 && name->offsets != NULL)
1690                         set_offsets(name, name->offsets, NULL);
1691         }
1692
1693         isc_buffer_add(target, name->length);
1694
1695         return (ISC_R_SUCCESS);
1696 }
1697
1698 static void
1699 set_offsets(const dns_name_t *name, unsigned char *offsets,
1700             dns_name_t *set_name)
1701 {
1702         unsigned int offset, count, length, nlabels;
1703         unsigned char *ndata;
1704         isc_boolean_t absolute;
1705
1706         ndata = name->ndata;
1707         length = name->length;
1708         offset = 0;
1709         nlabels = 0;
1710         absolute = ISC_FALSE;
1711         while (offset != length) {
1712                 INSIST(nlabels < 128);
1713                 offsets[nlabels++] = offset;
1714                 count = *ndata++;
1715                 offset++;
1716                 INSIST(count <= 63);
1717                 offset += count;
1718                 ndata += count;
1719                 INSIST(offset <= length);
1720                 if (count == 0) {
1721                         absolute = ISC_TRUE;
1722                         break;
1723                 }
1724         }
1725         if (set_name != NULL) {
1726                 INSIST(set_name == name);
1727
1728                 set_name->labels = nlabels;
1729                 set_name->length = offset;
1730                 if (absolute)
1731                         set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1732                 else
1733                         set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1734         }
1735         INSIST(nlabels == name->labels);
1736         INSIST(offset == name->length);
1737 }
1738
1739 isc_result_t
1740 dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
1741                   dns_decompress_t *dctx, unsigned int options,
1742                   isc_buffer_t *target)
1743 {
1744         unsigned char *cdata, *ndata;
1745         unsigned int cused; /* Bytes of compressed name data used */
1746         unsigned int nused, labels, n, nmax;
1747         unsigned int current, new_current, biggest_pointer;
1748         isc_boolean_t done;
1749         fw_state state = fw_start;
1750         unsigned int c;
1751         unsigned char *offsets;
1752         dns_offsets_t odata;
1753         isc_boolean_t downcase;
1754         isc_boolean_t seen_pointer;
1755
1756         /*
1757          * Copy the possibly-compressed name at source into target,
1758          * decompressing it.  Loop prevention is performed by checking
1759          * the new pointer against biggest_pointer.
1760          */
1761
1762         REQUIRE(VALID_NAME(name));
1763         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1764                 (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1765
1766         downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
1767
1768         if (target == NULL && name->buffer != NULL) {
1769                 target = name->buffer;
1770                 isc_buffer_clear(target);
1771         }
1772
1773         REQUIRE(dctx != NULL);
1774         REQUIRE(BINDABLE(name));
1775
1776         INIT_OFFSETS(name, offsets, odata);
1777
1778         /*
1779          * Make 'name' empty in case of failure.
1780          */
1781         MAKE_EMPTY(name);
1782
1783         /*
1784          * Initialize things to make the compiler happy; they're not required.
1785          */
1786         n = 0;
1787         new_current = 0;
1788
1789         /*
1790          * Set up.
1791          */
1792         labels = 0;
1793         done = ISC_FALSE;
1794
1795         ndata = isc_buffer_used(target);
1796         nused = 0;
1797         seen_pointer = ISC_FALSE;
1798
1799         /*
1800          * Find the maximum number of uncompressed target name
1801          * bytes we are willing to generate.  This is the smaller
1802          * of the available target buffer length and the
1803          * maximum legal domain name length (255).
1804          */
1805         nmax = isc_buffer_availablelength(target);
1806         if (nmax > DNS_NAME_MAXWIRE)
1807                 nmax = DNS_NAME_MAXWIRE;
1808
1809         cdata = isc_buffer_current(source);
1810         cused = 0;
1811
1812         current = source->current;
1813         biggest_pointer = current;
1814
1815         /*
1816          * Note:  The following code is not optimized for speed, but
1817          * rather for correctness.  Speed will be addressed in the future.
1818          */
1819
1820         while (current < source->active && !done) {
1821                 c = *cdata++;
1822                 current++;
1823                 if (!seen_pointer)
1824                         cused++;
1825
1826                 switch (state) {
1827                 case fw_start:
1828                         if (c < 64) {
1829                                 offsets[labels] = nused;
1830                                 labels++;
1831                                 if (nused + c + 1 > nmax)
1832                                         goto full;
1833                                 nused += c + 1;
1834                                 *ndata++ = c;
1835                                 if (c == 0)
1836                                         done = ISC_TRUE;
1837                                 n = c;
1838                                 state = fw_ordinary;
1839                         } else if (c >= 128 && c < 192) {
1840                                 /*
1841                                  * 14 bit local compression pointer.
1842                                  * Local compression is no longer an
1843                                  * IETF draft.
1844                                  */
1845                                 return (DNS_R_BADLABELTYPE);
1846                         } else if (c >= 192) {
1847                                 /*
1848                                  * Ordinary 14-bit pointer.
1849                                  */
1850                                 if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
1851                                     0)
1852                                         return (DNS_R_DISALLOWED);
1853                                 new_current = c & 0x3F;
1854                                 n = 1;
1855                                 state = fw_newcurrent;
1856                         } else
1857                                 return (DNS_R_BADLABELTYPE);
1858                         break;
1859                 case fw_ordinary:
1860                         if (downcase)
1861                                 c = maptolower[c];
1862                         /* FALLTHROUGH */
1863                 case fw_copy:
1864                         *ndata++ = c;
1865                         n--;
1866                         if (n == 0)
1867                                 state = fw_start;
1868                         break;
1869                 case fw_newcurrent:
1870                         new_current *= 256;
1871                         new_current += c;
1872                         n--;
1873                         if (n != 0)
1874                                 break;
1875                         if (new_current >= biggest_pointer)
1876                                 return (DNS_R_BADPOINTER);
1877                         biggest_pointer = new_current;
1878                         current = new_current;
1879                         cdata = (unsigned char *)source->base + current;
1880                         seen_pointer = ISC_TRUE;
1881                         state = fw_start;
1882                         break;
1883                 default:
1884                         FATAL_ERROR(__FILE__, __LINE__,
1885                                     "Unknown state %d", state);
1886                         /* Does not return. */
1887                 }
1888         }
1889
1890         if (!done)
1891                 return (ISC_R_UNEXPECTEDEND);
1892
1893         name->ndata = (unsigned char *)target->base + target->used;
1894         name->labels = labels;
1895         name->length = nused;
1896         name->attributes |= DNS_NAMEATTR_ABSOLUTE;
1897
1898         isc_buffer_forward(source, cused);
1899         isc_buffer_add(target, name->length);
1900
1901         return (ISC_R_SUCCESS);
1902
1903  full:
1904         if (nmax == DNS_NAME_MAXWIRE)
1905                 /*
1906                  * The name did not fit even though we had a buffer
1907                  * big enough to fit a maximum-length name.
1908                  */
1909                 return (DNS_R_NAMETOOLONG);
1910         else
1911                 /*
1912                  * The name might fit if only the caller could give us a
1913                  * big enough buffer.
1914                  */
1915                 return (ISC_R_NOSPACE);
1916 }
1917
1918 isc_result_t
1919 dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1920                 isc_buffer_t *target)
1921 {
1922         unsigned int methods;
1923         isc_uint16_t offset;
1924         dns_name_t gp;  /* Global compression prefix */
1925         isc_boolean_t gf;       /* Global compression target found */
1926         isc_uint16_t go;        /* Global compression offset */
1927         dns_offsets_t clo;
1928         dns_name_t clname;
1929
1930         /*
1931          * Convert 'name' into wire format, compressing it as specified by the
1932          * compression context 'cctx', and storing the result in 'target'.
1933          */
1934
1935         REQUIRE(VALID_NAME(name));
1936         REQUIRE(cctx != NULL);
1937         REQUIRE(ISC_BUFFER_VALID(target));
1938
1939         /*
1940          * If 'name' doesn't have an offsets table, make a clone which
1941          * has one.
1942          */
1943         if (name->offsets == NULL) {
1944                 DNS_NAME_INIT(&clname, clo);
1945                 dns_name_clone(name, &clname);
1946                 name = &clname;
1947         }
1948         DNS_NAME_INIT(&gp, NULL);
1949
1950         offset = target->used;  /*XXX*/
1951
1952         methods = dns_compress_getmethods(cctx);
1953
1954         if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
1955             (methods & DNS_COMPRESS_GLOBAL14) != 0)
1956                 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1957         else
1958                 gf = ISC_FALSE;
1959
1960         /*
1961          * If the offset is too high for 14 bit global compression, we're
1962          * out of luck.
1963          */
1964         if (gf && go >= 0x4000)
1965                 gf = ISC_FALSE;
1966
1967         /*
1968          * Will the compression pointer reduce the message size?
1969          */
1970         if (gf && (gp.length + 2) >= name->length)
1971                 gf = ISC_FALSE;
1972
1973         if (gf) {
1974                 if (target->length - target->used < gp.length)
1975                         return (ISC_R_NOSPACE);
1976                 (void)memcpy((unsigned char *)target->base + target->used,
1977                              gp.ndata, (size_t)gp.length);
1978                 isc_buffer_add(target, gp.length);
1979                 go |= 0xc000;
1980                 if (target->length - target->used < 2)
1981                         return (ISC_R_NOSPACE);
1982                 isc_buffer_putuint16(target, go);
1983                 if (gp.length != 0)
1984                         dns_compress_add(cctx, name, &gp, offset);
1985         } else {
1986                 if (target->length - target->used < name->length)
1987                         return (ISC_R_NOSPACE);
1988                 (void)memcpy((unsigned char *)target->base + target->used,
1989                              name->ndata, (size_t)name->length);
1990                 isc_buffer_add(target, name->length);
1991                 dns_compress_add(cctx, name, name, offset);
1992         }
1993         return (ISC_R_SUCCESS);
1994 }
1995
1996 isc_result_t
1997 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1998                      isc_buffer_t *target)
1999 {
2000         unsigned char *ndata, *offsets;
2001         unsigned int nrem, labels, prefix_length, length;
2002         isc_boolean_t copy_prefix = ISC_TRUE;
2003         isc_boolean_t copy_suffix = ISC_TRUE;
2004         isc_boolean_t absolute = ISC_FALSE;
2005         dns_name_t tmp_name;
2006         dns_offsets_t odata;
2007
2008         /*
2009          * Concatenate 'prefix' and 'suffix'.
2010          */
2011
2012         REQUIRE(prefix == NULL || VALID_NAME(prefix));
2013         REQUIRE(suffix == NULL || VALID_NAME(suffix));
2014         REQUIRE(name == NULL || VALID_NAME(name));
2015         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
2016                 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
2017         if (prefix == NULL || prefix->labels == 0)
2018                 copy_prefix = ISC_FALSE;
2019         if (suffix == NULL || suffix->labels == 0)
2020                 copy_suffix = ISC_FALSE;
2021         if (copy_prefix &&
2022             (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
2023                 absolute = ISC_TRUE;
2024                 REQUIRE(!copy_suffix);
2025         }
2026         if (name == NULL) {
2027                 DNS_NAME_INIT(&tmp_name, odata);
2028                 name = &tmp_name;
2029         }
2030         if (target == NULL) {
2031                 INSIST(name->buffer != NULL);
2032                 target = name->buffer;
2033                 isc_buffer_clear(name->buffer);
2034         }
2035
2036         REQUIRE(BINDABLE(name));
2037
2038         /*
2039          * Set up.
2040          */
2041         nrem = target->length - target->used;
2042         ndata = (unsigned char *)target->base + target->used;
2043         if (nrem > DNS_NAME_MAXWIRE)
2044                 nrem = DNS_NAME_MAXWIRE;
2045         length = 0;
2046         prefix_length = 0;
2047         labels = 0;
2048         if (copy_prefix) {
2049                 prefix_length = prefix->length;
2050                 length += prefix_length;
2051                 labels += prefix->labels;
2052         }
2053         if (copy_suffix) {
2054                 length += suffix->length;
2055                 labels += suffix->labels;
2056         }
2057         if (length > DNS_NAME_MAXWIRE) {
2058                 MAKE_EMPTY(name);
2059                 return (DNS_R_NAMETOOLONG);
2060         }
2061         if (length > nrem) {
2062                 MAKE_EMPTY(name);
2063                 return (ISC_R_NOSPACE);
2064         }
2065
2066         if (copy_suffix) {
2067                 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2068                         absolute = ISC_TRUE;
2069                 if (suffix == name && suffix->buffer == target)
2070                         memmove(ndata + prefix_length, suffix->ndata,
2071                                 suffix->length);
2072                 else
2073                         memcpy(ndata + prefix_length, suffix->ndata,
2074                                suffix->length);
2075         }
2076
2077         /*
2078          * If 'prefix' and 'name' are the same object, and the object has
2079          * a dedicated buffer, and we're using it, then we don't have to
2080          * copy anything.
2081          */
2082         if (copy_prefix && (prefix != name || prefix->buffer != target))
2083                 memcpy(ndata, prefix->ndata, prefix_length);
2084
2085         name->ndata = ndata;
2086         name->labels = labels;
2087         name->length = length;
2088         if (absolute)
2089                 name->attributes = DNS_NAMEATTR_ABSOLUTE;
2090         else
2091                 name->attributes = 0;
2092
2093         if (name->labels > 0 && name->offsets != NULL) {
2094                 INIT_OFFSETS(name, offsets, odata);
2095                 set_offsets(name, offsets, NULL);
2096         }
2097
2098         isc_buffer_add(target, name->length);
2099
2100         return (ISC_R_SUCCESS);
2101 }
2102
2103 void
2104 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
2105                dns_name_t *prefix, dns_name_t *suffix)
2106
2107 {
2108         unsigned int splitlabel;
2109
2110         REQUIRE(VALID_NAME(name));
2111         REQUIRE(suffixlabels > 0);
2112         REQUIRE(suffixlabels < name->labels);
2113         REQUIRE(prefix != NULL || suffix != NULL);
2114         REQUIRE(prefix == NULL ||
2115                 (VALID_NAME(prefix) &&
2116                  prefix->buffer != NULL &&
2117                  BINDABLE(prefix)));
2118         REQUIRE(suffix == NULL ||
2119                 (VALID_NAME(suffix) &&
2120                  suffix->buffer != NULL &&
2121                  BINDABLE(suffix)));
2122
2123         splitlabel = name->labels - suffixlabels;
2124
2125         if (prefix != NULL)
2126                 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
2127
2128         if (suffix != NULL)
2129                 dns_name_getlabelsequence(name, splitlabel,
2130                                           suffixlabels, suffix);
2131
2132         return;
2133 }
2134
2135 isc_result_t
2136 dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
2137              dns_name_t *target)
2138 {
2139         /*
2140          * Make 'target' a dynamically allocated copy of 'source'.
2141          */
2142
2143         REQUIRE(VALID_NAME(source));
2144         REQUIRE(source->length > 0);
2145         REQUIRE(VALID_NAME(target));
2146         REQUIRE(BINDABLE(target));
2147
2148         /*
2149          * Make 'target' empty in case of failure.
2150          */
2151         MAKE_EMPTY(target);
2152
2153         target->ndata = isc_mem_get(mctx, source->length);
2154         if (target->ndata == NULL)
2155                 return (ISC_R_NOMEMORY);
2156
2157         memcpy(target->ndata, source->ndata, source->length);
2158
2159         target->length = source->length;
2160         target->labels = source->labels;
2161         target->attributes = DNS_NAMEATTR_DYNAMIC;
2162         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2163                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2164         if (target->offsets != NULL) {
2165                 if (source->offsets != NULL)
2166                         memcpy(target->offsets, source->offsets,
2167                                source->labels);
2168                 else
2169                         set_offsets(target, target->offsets, NULL);
2170         }
2171
2172         return (ISC_R_SUCCESS);
2173 }
2174
2175 isc_result_t
2176 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2177                         dns_name_t *target)
2178 {
2179         /*
2180          * Make 'target' a read-only dynamically allocated copy of 'source'.
2181          * 'target' will also have a dynamically allocated offsets table.
2182          */
2183
2184         REQUIRE(VALID_NAME(source));
2185         REQUIRE(source->length > 0);
2186         REQUIRE(VALID_NAME(target));
2187         REQUIRE(BINDABLE(target));
2188         REQUIRE(target->offsets == NULL);
2189
2190         /*
2191          * Make 'target' empty in case of failure.
2192          */
2193         MAKE_EMPTY(target);
2194
2195         target->ndata = isc_mem_get(mctx, source->length + source->labels);
2196         if (target->ndata == NULL)
2197                 return (ISC_R_NOMEMORY);
2198
2199         memcpy(target->ndata, source->ndata, source->length);
2200
2201         target->length = source->length;
2202         target->labels = source->labels;
2203         target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2204                 DNS_NAMEATTR_READONLY;
2205         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2206                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2207         target->offsets = target->ndata + source->length;
2208         if (source->offsets != NULL)
2209                 memcpy(target->offsets, source->offsets, source->labels);
2210         else
2211                 set_offsets(target, target->offsets, NULL);
2212
2213         return (ISC_R_SUCCESS);
2214 }
2215
2216 void
2217 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2218         size_t size;
2219
2220         /*
2221          * Free 'name'.
2222          */
2223
2224         REQUIRE(VALID_NAME(name));
2225         REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2226
2227         size = name->length;
2228         if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2229                 size += name->labels;
2230         isc_mem_put(mctx, name->ndata, size);
2231         dns_name_invalidate(name);
2232 }
2233
2234 isc_result_t
2235 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2236         dns_name_t downname;
2237         unsigned char data[256];
2238         isc_buffer_t buffer;
2239         isc_result_t result;
2240         isc_region_t r;
2241
2242         /*
2243          * Send 'name' in DNSSEC canonical form to 'digest'.
2244          */
2245
2246         REQUIRE(VALID_NAME(name));
2247         REQUIRE(digest != NULL);
2248
2249         DNS_NAME_INIT(&downname, NULL);
2250         isc_buffer_init(&buffer, data, sizeof(data));
2251
2252         result = dns_name_downcase(name, &downname, &buffer);
2253         if (result != ISC_R_SUCCESS)
2254                 return (result);
2255
2256         isc_buffer_usedregion(&buffer, &r);
2257
2258         return ((digest)(arg, &r));
2259 }
2260
2261 isc_boolean_t
2262 dns_name_dynamic(dns_name_t *name) {
2263         REQUIRE(VALID_NAME(name));
2264
2265         /*
2266          * Returns whether there is dynamic memory associated with this name.
2267          */
2268
2269         return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2270                 ISC_TRUE : ISC_FALSE);
2271 }
2272
2273 isc_result_t
2274 dns_name_print(dns_name_t *name, FILE *stream) {
2275         isc_result_t result;
2276         isc_buffer_t b;
2277         isc_region_t r;
2278         char t[1024];
2279
2280         /*
2281          * Print 'name' on 'stream'.
2282          */
2283
2284         REQUIRE(VALID_NAME(name));
2285
2286         isc_buffer_init(&b, t, sizeof(t));
2287         result = dns_name_totext(name, ISC_FALSE, &b);
2288         if (result != ISC_R_SUCCESS)
2289                 return (result);
2290         isc_buffer_usedregion(&b, &r);
2291         fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2292
2293         return (ISC_R_SUCCESS);
2294 }
2295
2296 isc_result_t
2297 dns_name_settotextfilter(dns_name_totextfilter_t proc) {
2298 #ifdef ISC_PLATFORM_USETHREADS
2299         isc_result_t result;
2300         dns_name_totextfilter_t *mem;
2301         int res;
2302
2303         result = totext_filter_proc_key_init();
2304         if (result != ISC_R_SUCCESS)
2305                 return (result);
2306
2307         /*
2308          * If we already have been here set / clear as appropriate.
2309          * Otherwise allocate memory.
2310          */
2311         mem = isc_thread_key_getspecific(totext_filter_proc_key);
2312         if (mem != NULL && proc != NULL) {
2313                 *mem = proc;
2314                 return (ISC_R_SUCCESS);
2315         }
2316         if (proc == NULL) {
2317                 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2318                 res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
2319                 if (res != 0)
2320                         result = ISC_R_UNEXPECTED;
2321                 return (result);
2322         }
2323
2324         mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
2325         if (mem == NULL)
2326                 return (ISC_R_NOMEMORY);
2327         *mem = proc;
2328         if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
2329                 isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
2330                 result = ISC_R_UNEXPECTED;
2331         }
2332         return (result);
2333 #else
2334         totext_filter_proc = proc;
2335         return (ISC_R_SUCCESS);
2336 #endif
2337 }
2338
2339 void
2340 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2341         isc_result_t result;
2342         isc_buffer_t buf;
2343
2344         REQUIRE(size > 0);
2345
2346         /*
2347          * Leave room for null termination after buffer.
2348          */
2349         isc_buffer_init(&buf, cp, size - 1);
2350         result = dns_name_totext(name, ISC_TRUE, &buf);
2351         if (result == ISC_R_SUCCESS) {
2352                 /*
2353                  * Null terminate.
2354                  */
2355                 isc_region_t r;
2356                 isc_buffer_usedregion(&buf, &r);
2357                 ((char *) r.base)[r.length] = '\0';
2358
2359         } else
2360                 snprintf(cp, size, "<unknown>");
2361 }
2362
2363 isc_result_t
2364 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2365         unsigned char *ndata;
2366
2367         /*
2368          * Make dest a copy of source.
2369          */
2370
2371         REQUIRE(VALID_NAME(source));
2372         REQUIRE(VALID_NAME(dest));
2373         REQUIRE(target != NULL || dest->buffer != NULL);
2374
2375         if (target == NULL) {
2376                 target = dest->buffer;
2377                 isc_buffer_clear(dest->buffer);
2378         }
2379
2380         REQUIRE(BINDABLE(dest));
2381
2382         /*
2383          * Set up.
2384          */
2385         if (target->length - target->used < source->length)
2386                 return (ISC_R_NOSPACE);
2387
2388         ndata = (unsigned char *)target->base + target->used;
2389         dest->ndata = target->base;
2390
2391         memcpy(ndata, source->ndata, source->length);
2392
2393         dest->ndata = ndata;
2394         dest->labels = source->labels;
2395         dest->length = source->length;
2396         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2397                 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2398         else
2399                 dest->attributes = 0;
2400
2401         if (dest->labels > 0 && dest->offsets != NULL) {
2402                 if (source->offsets != NULL)
2403                         memcpy(dest->offsets, source->offsets, source->labels);
2404                 else
2405                         set_offsets(dest, dest->offsets, NULL);
2406         }
2407
2408         isc_buffer_add(target, dest->length);
2409
2410         return (ISC_R_SUCCESS);
2411 }
2412
2413 void
2414 dns_name_destroy(void) {
2415 #ifdef ISC_PLATFORM_USETHREADS
2416         RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
2417                                   == ISC_R_SUCCESS);
2418
2419         LOCK(&thread_key_mutex);
2420         if (thread_key_initialized) {
2421                 isc_mem_detach(&thread_key_mctx);
2422                 isc_thread_key_delete(totext_filter_proc_key);
2423                 thread_key_initialized = 0;
2424         }
2425         UNLOCK(&thread_key_mutex);
2426
2427 #endif
2428 }