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