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, ®);
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