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