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