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