Merge from vendor branch AWK:
[dragonfly.git] / contrib / bind-9.3 / lib / dns / name.c
1 /*
2  * Copyright (C) 2004, 2005  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.14 2005/10/14 01:38:48 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(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(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {
1752         unsigned int methods;
1753         isc_uint16_t offset;
1754         dns_name_t gp;  /* Global compression prefix */
1755         isc_boolean_t gf;       /* Global compression target found */
1756         isc_uint16_t go;        /* Global compression offset */
1757         dns_offsets_t clo;
1758         dns_name_t clname;
1759
1760         /*
1761          * Convert 'name' into wire format, compressing it as specified by the
1762          * compression context 'cctx', and storing the result in 'target'.
1763          */
1764
1765         REQUIRE(VALID_NAME(name));
1766         REQUIRE(cctx != NULL);
1767         REQUIRE(ISC_BUFFER_VALID(target));
1768
1769         /*
1770          * If 'name' doesn't have an offsets table, make a clone which
1771          * has one.
1772          */
1773         if (name->offsets == NULL) {
1774                 DNS_NAME_INIT(&clname, clo);
1775                 dns_name_clone(name, &clname);
1776                 name = &clname;
1777         }
1778         DNS_NAME_INIT(&gp, NULL);
1779
1780         offset = target->used;  /*XXX*/
1781
1782         methods = dns_compress_getmethods(cctx);
1783
1784         if ((methods & DNS_COMPRESS_GLOBAL14) != 0)
1785                 gf = dns_compress_findglobal(cctx, name, &gp, &go);
1786         else
1787                 gf = ISC_FALSE;
1788
1789         /*
1790          * If the offset is too high for 14 bit global compression, we're
1791          * out of luck.
1792          */
1793         if (gf && go >= 0x4000)
1794                 gf = ISC_FALSE;
1795
1796         /*
1797          * Will the compression pointer reduce the message size?
1798          */
1799         if (gf && (gp.length + 2) >= name->length)
1800                 gf = ISC_FALSE;
1801
1802         if (gf) {
1803                 if (target->length - target->used < gp.length)
1804                         return (ISC_R_NOSPACE);
1805                 (void)memcpy((unsigned char *)target->base + target->used,
1806                              gp.ndata, (size_t)gp.length);
1807                 isc_buffer_add(target, gp.length);
1808                 go |= 0xc000;
1809                 if (target->length - target->used < 2)
1810                         return (ISC_R_NOSPACE);
1811                 isc_buffer_putuint16(target, go);
1812                 if (gp.length != 0)
1813                         dns_compress_add(cctx, name, &gp, offset);
1814         } else {
1815                 if (target->length - target->used < name->length)
1816                         return (ISC_R_NOSPACE);
1817                 (void)memcpy((unsigned char *)target->base + target->used,
1818                              name->ndata, (size_t)name->length);
1819                 isc_buffer_add(target, name->length);
1820                 dns_compress_add(cctx, name, name, offset);
1821         }
1822         return (ISC_R_SUCCESS);
1823 }
1824
1825 isc_result_t
1826 dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
1827                      isc_buffer_t *target)
1828 {
1829         unsigned char *ndata, *offsets;
1830         unsigned int nrem, labels, prefix_length, length;
1831         isc_boolean_t copy_prefix = ISC_TRUE;
1832         isc_boolean_t copy_suffix = ISC_TRUE;
1833         isc_boolean_t absolute = ISC_FALSE;
1834         dns_name_t tmp_name;
1835         dns_offsets_t odata;
1836
1837         /*
1838          * Concatenate 'prefix' and 'suffix'.
1839          */
1840
1841         REQUIRE(prefix == NULL || VALID_NAME(prefix));
1842         REQUIRE(suffix == NULL || VALID_NAME(suffix));
1843         REQUIRE(name == NULL || VALID_NAME(name));
1844         REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1845                 (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
1846         if (prefix == NULL || prefix->labels == 0)
1847                 copy_prefix = ISC_FALSE;
1848         if (suffix == NULL || suffix->labels == 0)
1849                 copy_suffix = ISC_FALSE;
1850         if (copy_prefix &&
1851             (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
1852                 absolute = ISC_TRUE;
1853                 REQUIRE(!copy_suffix);
1854         }
1855         if (name == NULL) {
1856                 DNS_NAME_INIT(&tmp_name, odata);
1857                 name = &tmp_name;
1858         }
1859         if (target == NULL) {
1860                 INSIST(name->buffer != NULL);
1861                 target = name->buffer;
1862                 isc_buffer_clear(name->buffer);
1863         }
1864
1865         REQUIRE(BINDABLE(name));
1866
1867         /*
1868          * Set up.
1869          */
1870         nrem = target->length - target->used;
1871         ndata = (unsigned char *)target->base + target->used;
1872         if (nrem > DNS_NAME_MAXWIRE)
1873                 nrem = DNS_NAME_MAXWIRE;
1874         length = 0;
1875         prefix_length = 0;
1876         labels = 0;
1877         if (copy_prefix) {
1878                 prefix_length = prefix->length;
1879                 length += prefix_length;
1880                 labels += prefix->labels;
1881         }
1882         if (copy_suffix) {
1883                 length += suffix->length;
1884                 labels += suffix->labels;
1885         }
1886         if (length > DNS_NAME_MAXWIRE) {
1887                 MAKE_EMPTY(name);
1888                 return (DNS_R_NAMETOOLONG);
1889         }
1890         if (length > nrem) {
1891                 MAKE_EMPTY(name);
1892                 return (ISC_R_NOSPACE);
1893         }
1894
1895         if (copy_suffix) {
1896                 if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1897                         absolute = ISC_TRUE;
1898                 if (suffix == name && suffix->buffer == target)
1899                         memmove(ndata + prefix_length, suffix->ndata,
1900                                 suffix->length);
1901                 else
1902                         memcpy(ndata + prefix_length, suffix->ndata,
1903                                suffix->length);
1904         }
1905
1906         /*
1907          * If 'prefix' and 'name' are the same object, and the object has
1908          * a dedicated buffer, and we're using it, then we don't have to
1909          * copy anything.
1910          */
1911         if (copy_prefix && (prefix != name || prefix->buffer != target))
1912                 memcpy(ndata, prefix->ndata, prefix_length);
1913
1914         name->ndata = ndata;
1915         name->labels = labels;
1916         name->length = length;
1917         if (absolute)
1918                 name->attributes = DNS_NAMEATTR_ABSOLUTE;
1919         else
1920                 name->attributes = 0;
1921
1922         if (name->labels > 0 && name->offsets != NULL) {
1923                 INIT_OFFSETS(name, offsets, odata);
1924                 set_offsets(name, offsets, NULL);
1925         }
1926
1927         isc_buffer_add(target, name->length);
1928
1929         return (ISC_R_SUCCESS);
1930 }
1931
1932 void
1933 dns_name_split(dns_name_t *name, unsigned int suffixlabels,
1934                dns_name_t *prefix, dns_name_t *suffix)
1935
1936 {
1937         unsigned int splitlabel;
1938
1939         REQUIRE(VALID_NAME(name));
1940         REQUIRE(suffixlabels > 0);
1941         REQUIRE(suffixlabels < name->labels);
1942         REQUIRE(prefix != NULL || suffix != NULL);
1943         REQUIRE(prefix == NULL ||
1944                 (VALID_NAME(prefix) &&
1945                  prefix->buffer != NULL &&
1946                  BINDABLE(prefix)));
1947         REQUIRE(suffix == NULL ||
1948                 (VALID_NAME(suffix) &&
1949                  suffix->buffer != NULL &&
1950                  BINDABLE(suffix)));
1951
1952         splitlabel = name->labels - suffixlabels;
1953
1954         if (prefix != NULL)
1955                 dns_name_getlabelsequence(name, 0, splitlabel, prefix);
1956
1957         if (suffix != NULL)
1958                 dns_name_getlabelsequence(name, splitlabel,
1959                                           suffixlabels, suffix);
1960
1961         return;
1962 }
1963
1964 isc_result_t
1965 dns_name_dup(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
1966         /*
1967          * Make 'target' a dynamically allocated copy of 'source'.
1968          */
1969
1970         REQUIRE(VALID_NAME(source));
1971         REQUIRE(source->length > 0);
1972         REQUIRE(VALID_NAME(target));
1973         REQUIRE(BINDABLE(target));
1974
1975         /*
1976          * Make 'target' empty in case of failure.
1977          */
1978         MAKE_EMPTY(target);
1979
1980         target->ndata = isc_mem_get(mctx, source->length);
1981         if (target->ndata == NULL)
1982                 return (ISC_R_NOMEMORY);
1983
1984         memcpy(target->ndata, source->ndata, source->length);
1985
1986         target->length = source->length;
1987         target->labels = source->labels;
1988         target->attributes = DNS_NAMEATTR_DYNAMIC;
1989         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
1990                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
1991         if (target->offsets != NULL) {
1992                 if (source->offsets != NULL)
1993                         memcpy(target->offsets, source->offsets,
1994                                source->labels);
1995                 else
1996                         set_offsets(target, target->offsets, NULL);
1997         }
1998
1999         return (ISC_R_SUCCESS);
2000 }
2001
2002 isc_result_t
2003 dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
2004                         dns_name_t *target)
2005 {
2006         /*
2007          * Make 'target' a read-only dynamically allocated copy of 'source'.
2008          * 'target' will also have a dynamically allocated offsets table.
2009          */
2010
2011         REQUIRE(VALID_NAME(source));
2012         REQUIRE(source->length > 0);
2013         REQUIRE(VALID_NAME(target));
2014         REQUIRE(BINDABLE(target));
2015         REQUIRE(target->offsets == NULL);
2016
2017         /*
2018          * Make 'target' empty in case of failure.
2019          */
2020         MAKE_EMPTY(target);
2021
2022         target->ndata = isc_mem_get(mctx, source->length + source->labels);
2023         if (target->ndata == NULL)
2024                 return (ISC_R_NOMEMORY);
2025
2026         memcpy(target->ndata, source->ndata, source->length);
2027
2028         target->length = source->length;
2029         target->labels = source->labels;
2030         target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
2031                 DNS_NAMEATTR_READONLY;
2032         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2033                 target->attributes |= DNS_NAMEATTR_ABSOLUTE;
2034         target->offsets = target->ndata + source->length;
2035         if (source->offsets != NULL)
2036                 memcpy(target->offsets, source->offsets, source->labels);
2037         else
2038                 set_offsets(target, target->offsets, NULL);
2039
2040         return (ISC_R_SUCCESS);
2041 }
2042
2043 void
2044 dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
2045         size_t size;
2046
2047         /*
2048          * Free 'name'.
2049          */
2050
2051         REQUIRE(VALID_NAME(name));
2052         REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
2053
2054         size = name->length;
2055         if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
2056                 size += name->labels;
2057         isc_mem_put(mctx, name->ndata, size);
2058         dns_name_invalidate(name);
2059 }
2060
2061 isc_result_t
2062 dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
2063         dns_name_t downname;
2064         unsigned char data[256];
2065         isc_buffer_t buffer;
2066         isc_result_t result;
2067         isc_region_t r;
2068
2069         /*
2070          * Send 'name' in DNSSEC canonical form to 'digest'.
2071          */
2072
2073         REQUIRE(VALID_NAME(name));
2074         REQUIRE(digest != NULL);
2075
2076         DNS_NAME_INIT(&downname, NULL);
2077         isc_buffer_init(&buffer, data, sizeof(data));
2078
2079         result = dns_name_downcase(name, &downname, &buffer);
2080         if (result != ISC_R_SUCCESS)
2081                 return (result);
2082
2083         isc_buffer_usedregion(&buffer, &r);
2084
2085         return ((digest)(arg, &r));
2086 }
2087
2088 isc_boolean_t
2089 dns_name_dynamic(dns_name_t *name) {
2090         REQUIRE(VALID_NAME(name));
2091
2092         /*
2093          * Returns whether there is dynamic memory associated with this name.
2094          */
2095
2096         return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
2097                 ISC_TRUE : ISC_FALSE);
2098 }
2099
2100 isc_result_t
2101 dns_name_print(dns_name_t *name, FILE *stream) {
2102         isc_result_t result;
2103         isc_buffer_t b;
2104         isc_region_t r;
2105         char t[1024];
2106
2107         /*
2108          * Print 'name' on 'stream'.
2109          */
2110
2111         REQUIRE(VALID_NAME(name));
2112
2113         isc_buffer_init(&b, t, sizeof(t));
2114         result = dns_name_totext(name, ISC_FALSE, &b);
2115         if (result != ISC_R_SUCCESS)
2116                 return (result);
2117         isc_buffer_usedregion(&b, &r);
2118         fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
2119
2120         return (ISC_R_SUCCESS);
2121 }
2122
2123 void
2124 dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
2125         isc_result_t result;
2126         isc_buffer_t buf;
2127
2128         REQUIRE(size > 0);
2129
2130         /*
2131          * Leave room for null termination after buffer.
2132          */
2133         isc_buffer_init(&buf, cp, size - 1);
2134         result = dns_name_totext(name, ISC_TRUE, &buf);
2135         if (result == ISC_R_SUCCESS) {
2136                 /*
2137                  * Null terminate.
2138                  */
2139                 isc_region_t r;
2140                 isc_buffer_usedregion(&buf, &r);
2141                 ((char *) r.base)[r.length] = '\0';
2142
2143         } else
2144                 snprintf(cp, size, "<unknown>");
2145 }
2146
2147 isc_result_t
2148 dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
2149         unsigned char *ndata;
2150
2151         /*
2152          * Make dest a copy of source.
2153          */
2154
2155         REQUIRE(VALID_NAME(source));
2156         REQUIRE(VALID_NAME(dest));
2157         REQUIRE(target != NULL || dest->buffer != NULL);
2158
2159         if (target == NULL) {
2160                 target = dest->buffer;
2161                 isc_buffer_clear(dest->buffer);
2162         }
2163
2164         REQUIRE(BINDABLE(dest));
2165
2166         /*
2167          * Set up.
2168          */
2169         if (target->length - target->used < source->length)
2170                 return (ISC_R_NOSPACE);
2171
2172         ndata = (unsigned char *)target->base + target->used;
2173         dest->ndata = target->base;
2174
2175         memcpy(ndata, source->ndata, source->length);
2176
2177         dest->ndata = ndata;
2178         dest->labels = source->labels;
2179         dest->length = source->length;
2180         if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
2181                 dest->attributes = DNS_NAMEATTR_ABSOLUTE;
2182         else
2183                 dest->attributes = 0;
2184
2185         if (dest->labels > 0 && dest->offsets != NULL) {
2186                 if (source->offsets != NULL)
2187                         memcpy(dest->offsets, source->offsets, source->labels);
2188                 else
2189                         set_offsets(dest, dest->offsets, NULL);
2190         }
2191
2192         isc_buffer_add(target, dest->length);
2193
2194         return (ISC_R_SUCCESS);
2195 }
2196