name.c 74.7 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
Brian Wellington's avatar
Brian Wellington committed
2
 * Copyright (C) 1998-2001  Internet Software Consortium.
3
 *
Bob Halley's avatar
Bob Halley committed
4
5
6
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
7
 *
8
9
10
11
12
13
14
15
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Bob Halley's avatar
Bob Halley committed
16
 */
Bob Halley's avatar
Bob Halley committed
17

18
/* $Id: name.c,v 1.131 2001/12/28 20:59:27 bwelling Exp $ */
David Lawrence's avatar
David Lawrence committed
19

Bob Halley's avatar
Bob Halley committed
20
21
#include <config.h>

Bob Halley's avatar
add    
Bob Halley committed
22
23
#include <ctype.h>

Andreas Gustafsson's avatar
Andreas Gustafsson committed
24
#include <isc/buffer.h>
25
#include <isc/mem.h>
26
#include <isc/print.h>
27
#include <isc/string.h>
Bob Halley's avatar
Bob Halley committed
28
#include <isc/util.h>
Bob Halley's avatar
add    
Bob Halley committed
29

30
#include <dns/compress.h>
Brian Wellington's avatar
Brian Wellington committed
31
32
#include <dns/name.h>
#include <dns/result.h>
Bob Halley's avatar
add    
Bob Halley committed
33

34
#define VALID_NAME(n)	ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
Bob Halley's avatar
add    
Bob Halley committed
35
36

typedef enum {
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	ft_init = 0,
	ft_start,
	ft_ordinary,
	ft_initialescape,
	ft_escape,
	ft_escdecimal,
	ft_bitstring,
	ft_binary,
	ft_octal,
	ft_hex,
	ft_dottedquad,
	ft_dqdecimal,
	ft_maybeslash,
	ft_finishbitstring,
	ft_bitlength,
52
53
	ft_eatdot,
	ft_at
54
55
56
57
58
59
60
} ft_state;

typedef enum {
	fw_start = 0,
	fw_ordinary,
	fw_copy,
	fw_bitstring,
David Lawrence's avatar
David Lawrence committed
61
	fw_newcurrent
62
} fw_state;
Bob Halley's avatar
add    
Bob Halley committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

static char digitvalue[256] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,	/*16*/
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /*64*/
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
};

static char hexdigits[16] = {
	'0', '1', '2', '3', '4', '5', '6', '7',
	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};

static unsigned char maptolower[] = {
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};

123
124
125
#define CONVERTTOASCII(c)
#define CONVERTFROMASCII(c)

126
127
128
129
130
131
132
133
134
135
136
#define INIT_OFFSETS(name, var, default) \
	if (name->offsets != NULL) \
		var = name->offsets; \
	else \
		var = default;

#define SETUP_OFFSETS(name, var, default) \
	if (name->offsets != NULL) \
		var = name->offsets; \
	else { \
		var = default; \
David Lawrence's avatar
David Lawrence committed
137
		set_offsets(name, var, NULL); \
138
139
	}

140
141
142
143
144
145
146
147
148
149
150
151
/*
 * Note:  If additional attributes are added that should not be set for
 *	  empty names, MAKE_EMPTY() must be changed so it clears them.
 */
#define MAKE_EMPTY(name) \
do { \
	name->ndata = NULL; \
	name->length = 0; \
	name->labels = 0; \
	name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
} while (0);

152
153
154
155
156
157
158
159
/*
 * A name is "bindable" if it can be set to point to a new value, i.e.
 * name->ndata and name->length may be changed.
 */
#define BINDABLE(name) \
	((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
	 == 0)

David Lawrence's avatar
David Lawrence committed
160
/*
161
162
163
 * Note that the name data must be a char array, not a string
 * literal, to avoid compiler warnings about discarding
 * the const attribute of a string.
David Lawrence's avatar
David Lawrence committed
164
 */
165
166
167
168
169
170
171
172
173
174
175
static unsigned char root_ndata[] = { '\0' };
static unsigned char root_offsets[] = { 0 };

static dns_name_t root = 
{
	DNS_NAME_MAGIC,
	root_ndata, 1, 1,
	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
	root_offsets, NULL,
	{(void *)-1, (void *)-1},
	{NULL, NULL}
David Lawrence's avatar
David Lawrence committed
176
};
Bob Halley's avatar
add    
Bob Halley committed
177

David Lawrence's avatar
David Lawrence committed
178
/* XXXDCL make const? */
179
LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
180
181
182
183
184
185
186
187
188
189
190
191

static unsigned char wild_ndata[] = { '\001', '*' };
static unsigned char wild_offsets[] = { 0 };

static dns_name_t wild =
{
	DNS_NAME_MAGIC,
	wild_ndata, 2, 1,
	DNS_NAMEATTR_READONLY,
	wild_offsets, NULL,
	{(void *)-1, (void *)-1},
	{NULL, NULL}
Bob Halley's avatar
Bob Halley committed
192
193
};

David Lawrence's avatar
David Lawrence committed
194
/* XXXDCL make const? */
195
LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
Bob Halley's avatar
Bob Halley committed
196

David Lawrence's avatar
David Lawrence committed
197
198
199
200
201
202
static void
set_offsets(const dns_name_t *name, unsigned char *offsets,
	    dns_name_t *set_name);

static void
compact(dns_name_t *name, unsigned char *offsets);
Bob Halley's avatar
add    
Bob Halley committed
203

204
205
206
207
208
/*
 * Yes, get_bit and set_bit are lame.  We define them here so they can
 * be inlined by smart compilers.
 */

David Lawrence's avatar
David Lawrence committed
209
210
static inline unsigned int
get_bit(unsigned char *array, unsigned int idx) {
211
	unsigned int byte, shift;
212

David Lawrence's avatar
David Lawrence committed
213
214
	byte = array[idx / 8];
	shift = 7 - (idx % 8);
215
216
217
218

	return ((byte >> shift) & 0x01);
}

David Lawrence's avatar
David Lawrence committed
219
220
static inline void
set_bit(unsigned char *array, unsigned int idx, unsigned int bit) {
David Lawrence's avatar
David Lawrence committed
221
	unsigned int shift, mask;
222

David Lawrence's avatar
David Lawrence committed
223
	shift = 7 - (idx % 8);
224
225
	mask = 1 << shift;

David Lawrence's avatar
David Lawrence committed
226
	if (bit != 0)
David Lawrence's avatar
David Lawrence committed
227
		array[idx / 8] |= mask;
228
	else
David Lawrence's avatar
David Lawrence committed
229
		array[idx / 8] &= (~mask & 0xFF);
230
}
Bob Halley's avatar
add    
Bob Halley committed
231
232

dns_labeltype_t
Bob Halley's avatar
Bob Halley committed
233
dns_label_type(dns_label_t *label) {
Bob Halley's avatar
add    
Bob Halley committed
234
235
236
237
238
239
240
241
	/*
	 * Get the type of 'label'.
	 */

	REQUIRE(label != NULL);
	REQUIRE(label->length > 0);
	REQUIRE(label->base[0] <= 63 ||
		label->base[0] == DNS_LABELTYPE_BITSTRING);
242

Bob Halley's avatar
add    
Bob Halley committed
243
244
245
246
247
248
249
	if (label->base[0] <= 63)
		return (dns_labeltype_ordinary);
	else
		return (dns_labeltype_bitstring);
}

unsigned int
Bob Halley's avatar
Bob Halley committed
250
dns_label_countbits(dns_label_t *label) {
Bob Halley's avatar
add    
Bob Halley committed
251
252
253
254
255
256
257
258
259
260
261
262
263
	unsigned int count;

	/*
	 * The number of bits in a bitstring label.
	 */

	REQUIRE(label != NULL);
	REQUIRE(label->length > 2);
	REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);

	count = label->base[1];
	if (count == 0)
		count = 256;
264

Bob Halley's avatar
add    
Bob Halley committed
265
266
267
268
	return (count);
}

dns_bitlabel_t
Bob Halley's avatar
Bob Halley committed
269
dns_label_getbit(dns_label_t *label, unsigned int n) {
Bob Halley's avatar
add    
Bob Halley committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
	unsigned int count, bit;

	/*
	 * The 'n'th most significant bit of 'label'.
	 *
	 * Notes:
	 *	Numbering starts at 0.
	 */

	REQUIRE(label != NULL);
	REQUIRE(label->length > 2);
	REQUIRE(label->base[0] == DNS_LABELTYPE_BITSTRING);

	count = label->base[1];
	if (count == 0)
		count = 256;

	REQUIRE(n < count);

	bit = get_bit(&label->base[2], n);
	if (bit == 0)
		return (dns_bitlabel_0);
	return (dns_bitlabel_1);
}

void
296
dns_name_init(dns_name_t *name, unsigned char *offsets) {
Bob Halley's avatar
add    
Bob Halley committed
297
	/*
298
	 * Initialize 'name'.
Bob Halley's avatar
add    
Bob Halley committed
299
	 */
Brian Wellington's avatar
Brian Wellington committed
300
	DNS_NAME_INIT(name, offsets);
301
302
}

303
304
305
306
307
void
dns_name_reset(dns_name_t *name) {
	REQUIRE(VALID_NAME(name));
	REQUIRE(BINDABLE(name));

Brian Wellington's avatar
Brian Wellington committed
308
	DNS_NAME_RESET(name);
309
310
}

311
312
313
314
315
316
317
318
319
void
dns_name_invalidate(dns_name_t *name) {
	/*
	 * Make 'name' invalid.
	 */

	REQUIRE(VALID_NAME(name));

	name->magic = 0;
Bob Halley's avatar
add    
Bob Halley committed
320
321
322
	name->ndata = NULL;
	name->length = 0;
	name->labels = 0;
323
	name->attributes = 0;
324
	name->offsets = NULL;
325
	name->buffer = NULL;
326
	ISC_LINK_INIT(name, link);
Bob Halley's avatar
add    
Bob Halley committed
327
328
}

329
330
331
void
dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
	/*
332
	 * Dedicate a buffer for use with 'name'.
333
334
335
	 */

	REQUIRE(VALID_NAME(name));
336
	REQUIRE((buffer != NULL && name->buffer == NULL) ||
337
		(buffer == NULL));
338
339
340
341
342

	name->buffer = buffer;
}

isc_boolean_t
David Lawrence's avatar
David Lawrence committed
343
dns_name_hasbuffer(const dns_name_t *name) {
344
345
346
347
348
349
350
351
352
353
354
355
	/*
	 * Does 'name' have a dedicated buffer?
	 */

	REQUIRE(VALID_NAME(name));

	if (name->buffer != NULL)
		return (ISC_TRUE);

	return (ISC_FALSE);
}

356
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
357
dns_name_isabsolute(const dns_name_t *name) {
358

Bob Halley's avatar
add    
Bob Halley committed
359
360
361
362
363
364
	/*
	 * Does 'name' end in the root label?
	 */

	REQUIRE(VALID_NAME(name));

365
	if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
366
367
		return (ISC_TRUE);
	return (ISC_FALSE);
Bob Halley's avatar
add    
Bob Halley committed
368
369
}

Bob Halley's avatar
Bob Halley committed
370
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
371
dns_name_iswildcard(const dns_name_t *name) {
Bob Halley's avatar
Bob Halley committed
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
	unsigned char *ndata;

	/*
	 * Is 'name' a wildcard name?
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE(name->labels > 0);

	if (name->length >= 2) {
		ndata = name->ndata;
		if (ndata[0] == 1 && ndata[1] == '*')
			return (ISC_TRUE);
	}

	return (ISC_FALSE);
}

Bob Halley's avatar
Bob Halley committed
390
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
391
dns_name_requiresedns(const dns_name_t *name) {
Bob Halley's avatar
Bob Halley committed
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
	unsigned int count, nrem;
	unsigned char *ndata;
	isc_boolean_t requiresedns = ISC_FALSE;

	/*
	 * Does 'name' require EDNS for transmission?
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE(name->labels > 0);

	ndata = name->ndata;
	nrem = name->length;
	while (nrem > 0) {
		count = *ndata++;
		nrem--;
		if (count == 0)
			break;
		if (count > 63) {
			INSIST(count == DNS_LABELTYPE_BITSTRING);
			requiresedns = ISC_TRUE;
			break;
		}
		INSIST(nrem >= count);
		nrem -= count;
		ndata += count;
	}

	return (requiresedns);
}

423
424
static inline unsigned int
name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
Bob Halley's avatar
Bob Halley committed
425
	unsigned int length;
Bob Halley's avatar
Bob Halley committed
426
	const unsigned char *s;
Bob Halley's avatar
Bob Halley committed
427
	unsigned int h = 0;
Bob Halley's avatar
Bob Halley committed
428
	unsigned char c;
Bob Halley's avatar
Bob Halley committed
429
430
431
432
433
434

	length = name->length;
	if (length > 16)
		length = 16;

	/*
435
436
	 * This hash function is similar to the one Ousterhout
	 * uses in Tcl.
Bob Halley's avatar
Bob Halley committed
437
438
	 */
	s = name->ndata;
Bob Halley's avatar
Bob Halley committed
439
440
	if (case_sensitive) {
		while (length > 0) {
441
			h += ( h << 3 ) + *s;
Bob Halley's avatar
Bob Halley committed
442
443
444
445
446
447
			s++;
			length--;
		}
	} else {
		while (length > 0) {
			c = maptolower[*s];
448
			h += ( h << 3 ) + c;
Bob Halley's avatar
Bob Halley committed
449
450
			s++;
			length--;
Bob Halley's avatar
Bob Halley committed
451
452
453
454
455
456
		}
	}

	return (h);
}

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
unsigned int
dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
	/*
	 * Provide a hash value for 'name'.
	 */
	REQUIRE(VALID_NAME(name));

	if (name->labels == 0)
		return (0);

	return (name_hash(name, case_sensitive));
}

unsigned int
dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
	unsigned char *offsets;
	dns_offsets_t odata;
	dns_name_t tname;
	unsigned int h = 0;
	unsigned int i;

	/*
	 * Provide a hash value for 'name'.
	 */
	REQUIRE(VALID_NAME(name));

	if (name->labels == 0)
		return (0);
	else if (name->labels == 1)
		return (name_hash(name, case_sensitive));

	SETUP_OFFSETS(name, offsets, odata);
	DNS_NAME_INIT(&tname, NULL);
	tname.labels = 1;
	h = 0;
	for (i = 0; i < name->labels; i++) {
		tname.ndata = name->ndata + offsets[i];
		if (i == name->labels - 1)
			tname.length = name->length - offsets[i];
		else
			tname.length = offsets[i + 1] - offsets[i];
		h += name_hash(&tname, case_sensitive);
	}

	return (h);
}

504
dns_namereln_t
David Lawrence's avatar
David Lawrence committed
505
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
506
507
508
		     int *orderp,
		     unsigned int *nlabelsp, unsigned int *nbitsp)
{
Bob Halley's avatar
add    
Bob Halley committed
509
	unsigned int l1, l2, l, count1, count2, count;
510
	unsigned int b1, b2, n, nlabels, nbits;
Bob Halley's avatar
Bob Halley committed
511
	int cdiff, ldiff, chdiff;
Bob Halley's avatar
add    
Bob Halley committed
512
	unsigned char *label1, *label2;
513
514
	unsigned char *offsets1, *offsets2;
	dns_offsets_t odata1, odata2;
515
	dns_namereln_t namereln = dns_namereln_none;
Bob Halley's avatar
add    
Bob Halley committed
516
517
518

	/*
	 * Determine the relative ordering under the DNSSEC order relation of
519
520
521
522
523
524
525
	 * 'name1' and 'name2', and also determine the hierarchical
	 * relationship of the names.
	 *
	 * Note: It makes no sense for one of the names to be relative and the
	 * other absolute.  If both names are relative, then to be meaningfully
	 * compared the caller must ensure that they are both relative to the
	 * same domain.
Bob Halley's avatar
add    
Bob Halley committed
526
527
528
529
	 */

	REQUIRE(VALID_NAME(name1));
	REQUIRE(VALID_NAME(name2));
530
531
532
533
534
535
	REQUIRE(orderp != NULL);
	REQUIRE(nlabelsp != NULL);
	REQUIRE(nbitsp != NULL);
	/*
	 * Either name1 is absolute and name2 is absolute, or neither is.
	 */
Bob Halley's avatar
Bob Halley committed
536
537
	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));
Bob Halley's avatar
add    
Bob Halley committed
538

539
540
541
	SETUP_OFFSETS(name1, offsets1, odata1);
	SETUP_OFFSETS(name2, offsets2, odata2);

542
543
	nlabels = 0;
	nbits = 0;
Bob Halley's avatar
add    
Bob Halley committed
544
545
	l1 = name1->labels;
	l2 = name2->labels;
Bob Halley's avatar
Bob Halley committed
546
547
	ldiff = (int)l1 - (int)l2;
	if (ldiff < 0)
Bob Halley's avatar
add    
Bob Halley committed
548
		l = l1;
Bob Halley's avatar
Bob Halley committed
549
	else
Bob Halley's avatar
add    
Bob Halley committed
550
551
552
553
554
555
		l = l2;

	while (l > 0) {
		l--;
		l1--;
		l2--;
556
557
		label1 = &name1->ndata[offsets1[l1]];
		label2 = &name2->ndata[offsets2[l2]];
Bob Halley's avatar
add    
Bob Halley committed
558
559
560
		count1 = *label1++;
		count2 = *label2++;
		if (count1 <= 63 && count2 <= 63) {
Bob Halley's avatar
Bob Halley committed
561
562
			cdiff = (int)count1 - (int)count2;
			if (cdiff < 0)
Bob Halley's avatar
add    
Bob Halley committed
563
				count = count1;
Bob Halley's avatar
Bob Halley committed
564
			else
Bob Halley's avatar
add    
Bob Halley committed
565
566
567
				count = count2;

			while (count > 0) {
Bob Halley's avatar
Bob Halley committed
568
569
570
571
				chdiff = (int)maptolower[*label1] -
					(int)maptolower[*label2];
				if (chdiff != 0) {
					*orderp = chdiff;
572
573
					goto done;
				}
Bob Halley's avatar
Bob Halley committed
574
575
576
				count--;
				label1++;
				label2++;
Bob Halley's avatar
add    
Bob Halley committed
577
			}
578
579
580
581
582
			if (cdiff != 0) {
				*orderp = cdiff;
				goto done;
			}
			nlabels++;
Bob Halley's avatar
add    
Bob Halley committed
583
584
		} else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
			if (count2 == 0)
585
586
587
588
				*orderp = 1;
			else
				*orderp = -1;
			goto done;
Bob Halley's avatar
add    
Bob Halley committed
589
590
		} else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
			if (count1 == 0)
591
592
593
594
				*orderp = -1;
			else
				*orderp = 1;
			goto done;
Bob Halley's avatar
add    
Bob Halley committed
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
		} else {
			INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
			       count2 == DNS_LABELTYPE_BITSTRING);
			count1 = *label1++;
			if (count1 == 0)
				count1 = 256;
			count2 = *label2++;
			if (count2 == 0)
				count2 = 256;
			if (count1 < count2) {
				cdiff = -1;
				count = count1;
			} else {
				count = count2;
				if (count1 > count2)
					cdiff = 1;
				else
					cdiff = 0;
			}
			/* Yes, this loop is really slow! */
			for (n = 0; n < count; n++) {
				b1 = get_bit(label1, n);
				b2 = get_bit(label2, n);
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
				if (b1 < b2) {
					*orderp = -1;
					goto done;
				} else if (b1 > b2) {
					*orderp = 1;
					goto done;
				}
				if (nbits == 0)
					nlabels++;
				nbits++;
			}
			if (cdiff != 0) {
				/*
				 * If we're here, then we have two bitstrings
				 * of differing length.
				 *
				 * If the name with the shorter bitstring
				 * has any labels, then it must be greater
				 * than the longer bitstring.  This is a bit
				 * counterintuitive.  If the name with the
				 * shorter bitstring has any more labels, then
				 * the next label must be an ordinary label.
				 * It can't be a bitstring label because if it
				 * were, then there would be room for it in
				 * the current bitstring label (since all
				 * bitstrings are canonicalized).  Since
				 * there's at least one more bit in the
				 * name with the longer bitstring, and since
				 * a bitlabel sorts before any ordinary label,
				 * the name with the longer bitstring must
				 * be lexically before the one with the shorter
				 * bitstring.
				 *
				 * On the other hand, if there are no more
				 * labels in the name with the shorter
				 * bitstring, then that name contains the
				 * other name.
				 */
				namereln = dns_namereln_commonancestor;
				if (cdiff < 0) {
					if (l1 > 0)
						*orderp = 1;
					else {
						*orderp = -1;
						namereln =
							dns_namereln_contains;
					}
				} else {
					if (l2 > 0)
						*orderp = -1;
					else {
						*orderp = 1;
						namereln =
							dns_namereln_subdomain;
					}
				}
				goto done;
Bob Halley's avatar
add    
Bob Halley committed
675
			}
676
			nbits = 0;
Bob Halley's avatar
add    
Bob Halley committed
677
678
679
		}
	}

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
	*orderp = ldiff;
	if (ldiff < 0)
		namereln = dns_namereln_contains;
	else if (ldiff > 0)
		namereln = dns_namereln_subdomain;
	else
		namereln = dns_namereln_equal;

 done:
	*nlabelsp = nlabels;
	*nbitsp = nbits;

	if (nlabels > 0 && namereln == dns_namereln_none)
		namereln = dns_namereln_commonancestor;

	return (namereln);
}

int
David Lawrence's avatar
David Lawrence committed
699
dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
700
701
702
703
704
705
706
707
708
709
710
711
	int order;
	unsigned int nlabels, nbits;

	/*
	 * Determine the relative ordering under the DNSSEC order relation of
	 * 'name1' and 'name2'.
	 *
	 * Note: It makes no sense for one of the names to be relative and the
	 * other absolute.  If both names are relative, then to be meaningfully
	 * compared the caller must ensure that they are both relative to the
	 * same domain.
	 */
712

713
714
715
	(void)dns_name_fullcompare(name1, name2, &order, &nlabels, &nbits);

	return (order);
Bob Halley's avatar
add    
Bob Halley committed
716
717
}

Bob Halley's avatar
Bob Halley committed
718
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
719
dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
Bob Halley's avatar
Bob Halley committed
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
	unsigned int l, count;
	unsigned char c;
	unsigned char *label1, *label2;

	/*
	 * Are 'name1' and 'name2' equal?
	 *
	 * Note: It makes no sense for one of the names to be relative and the
	 * other absolute.  If both names are relative, then to be meaningfully
	 * compared the caller must ensure that they are both relative to the
	 * same domain.
	 */

	REQUIRE(VALID_NAME(name1));
	REQUIRE(VALID_NAME(name2));
	/*
	 * Either name1 is absolute and name2 is absolute, or neither is.
	 */
	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
		(name2->attributes & DNS_NAMEATTR_ABSOLUTE));

	if (name1->length != name2->length)
		return (ISC_FALSE);

	l = name1->labels;

	if (l != name2->labels)
		return (ISC_FALSE);

	label1 = name1->ndata;
	label2 = name2->ndata;
	while (l > 0) {
		l--;
		count = *label1++;
		if (count != *label2++)
			return (ISC_FALSE);
		if (count <= 63) {
			while (count > 0) {
				count--;
				c = maptolower[*label1++];
				if (c != maptolower[*label2++])
					return (ISC_FALSE);
			}
		} else {
			INSIST(count == DNS_LABELTYPE_BITSTRING);
			count = *label1++;
			if (count != *label2++)
				return (ISC_FALSE);
			if (count == 0)
				count = 256;
David Lawrence's avatar
David Lawrence committed
770
771
772
			/*
			 * Number of bytes.
			 */
Bob Halley's avatar
Bob Halley committed
773
774
775
776
777
778
779
780
781
782
783
784
785
			count = (count + 7) / 8;
			while (count > 0) {
				count--;
				c = *label1++;
				if (c != *label2++)
					return (ISC_FALSE);
			}
		}
	}

	return (ISC_TRUE);
}

786
int
David Lawrence's avatar
David Lawrence committed
787
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
	unsigned int l1, l2, l, count1, count2, count;
	unsigned char c1, c2;
	unsigned char *label1, *label2;

	/*
	 * Compare two absolute names as rdata.
	 */

	REQUIRE(VALID_NAME(name1));
	REQUIRE(name1->labels > 0);
	REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
	REQUIRE(VALID_NAME(name2));
	REQUIRE(name2->labels > 0);
	REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);

	l1 = name1->labels;
	l2 = name2->labels;

	l = (l1 < l2) ? l1 : l2;

	label1 = name1->ndata;
	label2 = name2->ndata;
	while (l > 0) {
		l--;
		count1 = *label1++;
		count2 = *label2++;
		if (count1 <= 63 && count2 <= 63) {
			if (count1 != count2)
				return ((count1 < count2) ? -1 : 1);
			count = count1;
			while (count > 0) {
				count--;
				c1 = maptolower[*label1++];
				c2 = maptolower[*label2++];
				if (c1 < c2)
					return (-1);
				else if (c1 > c2)
					return (1);
			}
		} else if (count1 == DNS_LABELTYPE_BITSTRING && count2 <= 63) {
			return (1);
		} else if (count2 == DNS_LABELTYPE_BITSTRING && count1 <= 63) {
			return (-1);
		} else {
			INSIST(count1 == DNS_LABELTYPE_BITSTRING &&
			       count2 == DNS_LABELTYPE_BITSTRING);
			count2 = *label2++;
			count1 = *label1++;
			if (count1 != count2)
				return ((count1 < count2) ? -1 : 1);
			if (count1 == 0)
				count1 = 256;
			if (count2 == 0)
				count2 = 256;
			/* number of bytes */
			count = (count1 + 7) / 8;
			while (count > 0) {
Bob Halley's avatar
Bob Halley committed
845
				count--;
846
847
848
849
850
851
852
853
				c1 = *label1++;
				c2 = *label2++;
				if (c1 != c2)
					return ((c1 < c2) ? -1 : 1);
			}
		}
	}

854
855
856
857
858
859
860
	/*
	 * If one name had more labels than the other, their common
	 * prefix must have been different because the shorter name
	 * ended with the root label and the longer one can't have
	 * a root label in the middle of it.  Therefore, if we get
	 * to this point, the lengths must be equal.
	 */
861
862
863
864
865
	INSIST(l1 == l2);

	return (0);
}

866
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
867
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
868
869
870
	int order;
	unsigned int nlabels, nbits;
	dns_namereln_t namereln;
Bob Halley's avatar
add    
Bob Halley committed
871
872
873
874
875
876
877
878
879
880

	/*
	 * Is 'name1' a subdomain of 'name2'?
	 *
	 * Note: It makes no sense for one of the names to be relative and the
	 * other absolute.  If both names are relative, then to be meaningfully
	 * compared the caller must ensure that they are both relative to the
	 * same domain.
	 */

881
882
883
884
885
	namereln = dns_name_fullcompare(name1, name2, &order, &nlabels,
					&nbits);
	if (namereln == dns_namereln_subdomain ||
	    namereln == dns_namereln_equal)
		return (ISC_TRUE);
Bob Halley's avatar
add    
Bob Halley committed
886

887
	return (ISC_FALSE);
Bob Halley's avatar
add    
Bob Halley committed
888
889
}

890
isc_boolean_t
David Lawrence's avatar
David Lawrence committed
891
dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
892
893
	int order;
	unsigned int nlabels, nbits, labels;
894
895
896
	dns_name_t tname;

	REQUIRE(VALID_NAME(name));
897
	REQUIRE(name->labels > 0);
898
	REQUIRE(VALID_NAME(wname));
899
900
	labels = wname->labels;
	REQUIRE(labels > 0);
901
902
	REQUIRE(dns_name_iswildcard(wname));

Brian Wellington's avatar
Brian Wellington committed
903
	DNS_NAME_INIT(&tname, NULL);
904
	dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
905
906
907
908
	if (dns_name_fullcompare(name, &tname, &order, &nlabels, &nbits) ==
	    dns_namereln_subdomain)
		return (ISC_TRUE);
	return (ISC_FALSE);
909
910
}

911
unsigned int
David Lawrence's avatar
David Lawrence committed
912
dns_name_depth(const dns_name_t *name) {
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
	unsigned int depth, count, nrem, n;
	unsigned char *ndata;

	/*
	 * The depth of 'name'.
	 */

	REQUIRE(VALID_NAME(name));

	if (name->labels == 0)
		return (0);

	depth = 0;
	ndata = name->ndata;
	nrem = name->length;
	while (nrem > 0) {
		count = *ndata++;
		nrem--;
		if (count > 63) {
			INSIST(count == DNS_LABELTYPE_BITSTRING);
			INSIST(nrem != 0);
			n = *ndata++;
			nrem--;
			if (n == 0)
				n = 256;
			depth += n;
			count = n / 8;
			if (n % 8 != 0)
				count++;
		} else {
			depth++;
			if (count == 0)
				break;
		}
		INSIST(nrem >= count);
		nrem -= count;
		ndata += count;
	}

	return (depth);
}

Bob Halley's avatar
add    
Bob Halley committed
955
unsigned int
David Lawrence's avatar
David Lawrence committed
956
dns_name_countlabels(const dns_name_t *name) {
Bob Halley's avatar
add    
Bob Halley committed
957
958
959
960
961
962
963
964
965
966
967
968
	/*
	 * How many labels does 'name' have?
	 */

	REQUIRE(VALID_NAME(name));

	ENSURE(name->labels <= 128);

	return (name->labels);
}

void
David Lawrence's avatar
David Lawrence committed
969
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
970
971
972
	unsigned char *offsets;
	dns_offsets_t odata;

Bob Halley's avatar
add    
Bob Halley committed
973
974
975
	/*
	 * Make 'label' refer to the 'n'th least significant label of 'name'.
	 */
976

Bob Halley's avatar
add    
Bob Halley committed
977
	REQUIRE(VALID_NAME(name));
978
	REQUIRE(name->labels > 0);
Bob Halley's avatar
add    
Bob Halley committed
979
980
	REQUIRE(n < name->labels);
	REQUIRE(label != NULL);
981

982
983
984
	SETUP_OFFSETS(name, offsets, odata);

	label->base = &name->ndata[offsets[n]];
Bob Halley's avatar
add    
Bob Halley committed
985
	if (n == name->labels - 1)
986
		label->length = name->length - offsets[n];
Bob Halley's avatar
add    
Bob Halley committed
987
	else
988
		label->length = offsets[n + 1] - offsets[n];
Bob Halley's avatar
add    
Bob Halley committed
989
990
991
}

void
David Lawrence's avatar
David Lawrence committed
992
dns_name_getlabelsequence(const dns_name_t *source,
Bob Halley's avatar
add    
Bob Halley committed
993
			  unsigned int first, unsigned int n,
Bob Halley's avatar
Bob Halley committed
994
			  dns_name_t *target)
Bob Halley's avatar
add    
Bob Halley committed
995
{
996
997
	unsigned char *offsets;
	dns_offsets_t odata;
998
	unsigned int firstoffset, endoffset;
999

Bob Halley's avatar
add    
Bob Halley committed
1000
1001
1002
1003
1004
1005
	/*
	 * Make 'target' refer to the 'n' labels including and following
	 * 'first' in 'source'.
	 */

	REQUIRE(VALID_NAME(source));
1006
	REQUIRE(VALID_NAME(target));
1007
	REQUIRE(first <= source->labels);
Bob Halley's avatar
add    
Bob Halley committed
1008
	REQUIRE(first + n <= source->labels);
1009
	REQUIRE(BINDABLE(target));
Bob Halley's avatar
add    
Bob Halley committed
1010

1011
1012
	SETUP_OFFSETS(source, offsets, odata);

1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
	if (first == source->labels)
		firstoffset = source->length;
	else
		firstoffset = offsets[first];

	if (first + n == source->labels)
		endoffset = source->length;
	else
		endoffset = offsets[first + n];

	target->ndata = &source->ndata[firstoffset];
	target->length = endoffset - firstoffset;
	
	if (first + n == source->labels && n > 0 &&
	    (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
		target->attributes |= DNS_NAMEATTR_ABSOLUTE;
	else
1030
		target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
1031

Bob Halley's avatar
add    
Bob Halley committed
1032
1033
	target->labels = n;

Bob Halley's avatar
Bob Halley committed
1034
1035
1036
1037
1038
1039
1040
	/*
	 * If source and target are the same, and we're making target
	 * a prefix of source, the offsets table is correct already
	 * so we don't need to call set_offsets().
	 */
	if (target->offsets != NULL &&
	    (target != source || first != 0))
David Lawrence's avatar
David Lawrence committed
1041
		set_offsets(target, target->offsets, NULL);
Bob Halley's avatar
add    
Bob Halley committed
1042
1043
}

Bob Halley's avatar
Bob Halley committed
1044
1045
1046
1047
1048
1049
1050
1051
1052
void
dns_name_clone(dns_name_t *source, dns_name_t *target) {

	/*
	 * Make 'target' refer to the same name as 'source'.
	 */

	REQUIRE(VALID_NAME(source));
	REQUIRE(VALID_NAME(target));
1053
	REQUIRE(BINDABLE(target));
Bob Halley's avatar
Bob Halley committed
1054
1055
1056
1057

	target->ndata = source->ndata;
	target->length = source->length;
	target->labels = source->labels;
1058
	target->attributes = source->attributes &
David Lawrence's avatar
David Lawrence committed
1059
1060
		(unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
				DNS_NAMEATTR_DYNOFFSETS);
Bob Halley's avatar
Bob Halley committed
1061
1062
1063
1064
1065
	if (target->offsets != NULL && source->labels > 0) {
		if (source->offsets != NULL)
			memcpy(target->offsets, source->offsets,
			       source->labels);
		else
David Lawrence's avatar
David Lawrence committed
1066
			set_offsets(target, target->offsets, NULL);
Bob Halley's avatar
Bob Halley committed
1067
1068
1069
	}
}

Bob Halley's avatar
add    
Bob Halley committed
1070
void
1071
dns_name_fromregion(dns_name_t *name, isc_region_t *r) {
1072
1073
	unsigned char *offsets;
	dns_offsets_t odata;
1074
1075
	unsigned int len;
	isc_region_t r2;
1076

Bob Halley's avatar
add    
Bob Halley committed
1077
1078
1079
1080
	/*
	 * Make 'name' refer to region 'r'.
	 */

1081
	REQUIRE(VALID_NAME(name));
Bob Halley's avatar
add    
Bob Halley committed
1082
	REQUIRE(r != NULL);
1083
	REQUIRE(BINDABLE(name));
Bob Halley's avatar
add    
Bob Halley committed
1084

1085
1086
	INIT_OFFSETS(name, offsets, odata);

1087
1088
	if (name->buffer != NULL) {
		isc_buffer_clear(name->buffer);
1089
		isc_buffer_availableregion(name->buffer, &r2);
1090
		len = (r->length < r2.length) ? r->length : r2.length;
1091
1092
		if (len > DNS_NAME_MAXWIRE)
			len = DNS_NAME_MAXWIRE;
1093
1094
1095
1096
1097
		memcpy(r2.base, r->base, len);
		name->ndata = r2.base;
		name->length = len;
	} else {
		name->ndata = r->base;
1098
1099
		name->length = (r->length <= DNS_NAME_MAXWIRE) ? 
			r->length : DNS_NAME_MAXWIRE;
1100
	}
Bob Halley's avatar
add    
Bob Halley committed
1101
1102

	if (r->length > 0)
David Lawrence's avatar
David Lawrence committed
1103
		set_offsets(name, offsets, name);
1104
	else {
Bob Halley's avatar
add    
Bob Halley committed
1105
		name->labels = 0;
1106
1107
		name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
	}
1108
1109
1110

	if (name->buffer != NULL)
		isc_buffer_add(name->buffer, name->length);
Bob Halley's avatar
add    
Bob Halley committed
1111
1112
1113
}

void
1114
dns_name_toregion(dns_name_t *name, isc_region_t *r) {
Bob Halley's avatar
add    
Bob Halley committed
1115
1116
1117
1118
1119
1120
1121
	/*
	 * Make 'r' refer to 'name'.
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE(r != NULL);

1122
	DNS_NAME_TOREGION(name, r);
Bob Halley's avatar
add    
Bob Halley committed
1123
1124
1125
}


1126
isc_result_t
1127
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
1128
		  dns_name_t *origin, isc_boolean_t downcase,
1129
		  isc_buffer_t *target)
Bob Halley's avatar
add    
Bob Halley committed
1130
1131
1132
1133
{
	unsigned char *ndata, *label;
	char *tdata;
	char c;
1134
	ft_state state, kind;
Bob Halley's avatar
add    
Bob Halley committed
1135
	unsigned int value, count, tbcount, bitlength, maxlength;
Bob Halley's avatar
Bob Halley committed
1136
	unsigned int n1, n2, vlen, tlen, nrem, nused, digits, labels, tused;
1137
	isc_boolean_t done, saw_bitstring;
Bob Halley's avatar
add    
Bob Halley committed
1138
	unsigned char dqchars[4];
1139
1140
	unsigned char *offsets;
	dns_offsets_t odata;
Bob Halley's avatar
add    
Bob Halley committed
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

	/*
	 * Convert the textual representation of a DNS name at source
	 * into uncompressed wire form stored in target.
	 *
	 * Notes:
	 *	Relative domain names will have 'origin' appended to them
	 *	unless 'origin' is NULL, in which case relative domain names
	 *	will remain relative.
	 */

1152
	REQUIRE(VALID_NAME(name));
1153
1154
1155
	REQUIRE(ISC_BUFFER_VALID(source));
	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
		(target == NULL && name->buffer != NULL));
1156

1157
1158
1159
1160
	if (target == NULL && name->buffer != NULL) {
		target = name->buffer;
		isc_buffer_clear(target);
	}
1161

1162
	REQUIRE(BINDABLE(name));
1163

1164
	INIT_OFFSETS(name, offsets, odata);
1165
	offsets[0] = 0;
1166

Bob Halley's avatar
add    
Bob Halley committed
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
	/*
	 * Initialize things to make the compiler happy; they're not required.
	 */
	n1 = 0;
	n2 = 0;
	vlen = 0;
	label = NULL;
	digits = 0;
	value = 0;
	count = 0;
	tbcount = 0;
	bitlength = 0;
	maxlength = 0;
1180
	kind = ft_init;
Bob Halley's avatar
add    
Bob Halley committed
1181
1182

	/*
1183
	 * Make 'name' empty in case of failure.
Bob Halley's avatar
add    
Bob Halley committed
1184
	 */
1185
	MAKE_EMPTY(name);
Bob Halley's avatar
add    
Bob Halley committed
1186
1187
1188
1189

	/*
	 * Set up the state machine.
	 */
1190
	tdata = (char *)source->base + source->current;
1191
	tlen = isc_buffer_remaininglength(source);
1192
	tused = 0;
1193
1194
	ndata = isc_buffer_used(target);
	nrem = isc_buffer_availablelength(target);
Bob Halley's avatar
add    
Bob Halley committed
1195
1196
	if (nrem > 255)
		nrem = 255;
Bob Halley's avatar
Bob Halley committed
1197
	nused = 0;
Bob Halley's avatar
add    
Bob Halley committed
1198
	labels = 0;
1199
1200
	done = ISC_FALSE;
	saw_bitstring = ISC_FALSE;
1201
	state = ft_init;
Bob Halley's avatar
add    
Bob Halley committed
1202
1203
1204
1205

	while (nrem > 0 && tlen > 0 && !done) {
		c = *tdata++;
		tlen--;
1206
		tused++;
Bob Halley's avatar
add    
Bob Halley committed
1207
1208
1209

	no_read:
		switch (state) {
1210
		case ft_init:
Bob Halley's avatar
add    
Bob Halley committed
1211
1212
1213
1214
1215
1216
1217
1218
1219
			/*
			 * Is this the root name?
			 */
			if (c == '.') {
				if (tlen != 0)
					return (DNS_R_EMPTYLABEL);
				labels++;
				*ndata++ = 0;
				nrem--;
Bob Halley's avatar
Bob Halley committed
1220
				nused++;
1221
				done = ISC_TRUE;
Bob Halley's avatar
add    
Bob Halley committed
1222
1223
				break;
			}
1224
1225
1226
			if (c == '@' && tlen == 0) {
				state = ft_at;
				break;
1227
			}
1228

Bob Halley's avatar
add    
Bob Halley committed
1229
			/* FALLTHROUGH */
1230
		case ft_start:
Bob Halley's avatar
add    
Bob Halley committed
1231
1232
1233
			label = ndata;
			ndata++;
			nrem--;
Bob Halley's avatar
Bob Halley committed
1234
			nused++;
Bob Halley's avatar
add    
Bob Halley committed
1235
1236
			count = 0;
			if (c == '\\') {
1237
				state = ft_initialescape;
Bob Halley's avatar
add    
Bob Halley committed
1238
1239
				break;
			}
1240
1241
			kind = ft_ordinary;
			state = ft_ordinary;
Bob Halley's avatar
add    
Bob Halley committed
1242
			/* FALLTHROUGH */
1243
		case ft_ordinary:
Bob Halley's avatar
add    
Bob Halley committed
1244
1245
1246
1247
1248
			if (c == '.') {
				if (count == 0)
					return (DNS_R_EMPTYLABEL);
				*label = count;
				labels++;
1249
1250
				INSIST(labels <= 127);
				offsets[labels] = nused;
Bob Halley's avatar
add    
Bob Halley committed
1251
1252
1253
1254
				if (tlen == 0) {
					labels++;
					*ndata++ = 0;
					nrem--;
Bob Halley's avatar
Bob Halley committed
1255
					nused++;
1256
					done = ISC_TRUE;
Bob Halley's avatar
add    
Bob Halley committed
1257
				}
1258
				state = ft_start;
Bob Halley's avatar
add    
Bob Halley committed
1259
			} else if (c == '\\') {
1260
				state = ft_escape;
Bob Halley's avatar
add    
Bob Halley committed
1261
1262
1263
1264
			} else {
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
1265
				CONVERTTOASCII(c);
Bob Halley's avatar
add    
Bob Halley committed
1266
1267
1268
1269
				if (downcase)
					c = maptolower[(int)c];
				*ndata++ = c;
				nrem--;
Bob Halley's avatar
Bob Halley committed
1270
				nused++;
Bob Halley's avatar
add    
Bob Halley committed
1271
1272
			}
			break;
1273
		case ft_initialescape:
Bob Halley's avatar
add    
Bob Halley committed
1274
			if (c == '[') {
1275
				saw_bitstring = ISC_TRUE;
1276
1277
				kind = ft_bitstring;
				state = ft_bitstring;
Bob Halley's avatar
add    
Bob Halley committed
1278
1279
1280
1281
				*label = DNS_LABELTYPE_BITSTRING;
				label = ndata;
				ndata++;
				nrem--;
Bob Halley's avatar
Bob Halley committed
1282
				nused++;
Bob Halley's avatar
add    
Bob Halley committed
1283
1284
				break;
			}
1285
1286
			kind = ft_ordinary;
			state = ft_escape;
Bob Halley's avatar
add    
Bob Halley committed
1287
			/* FALLTHROUGH */
1288
		case ft_escape:
1289
			if (!isdigit(c & 0xff)) {
Bob Halley's avatar
add    
Bob Halley committed
1290
1291
1292
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
1293
				CONVERTTOASCII(c);
Bob Halley's avatar
add    
Bob Halley committed
1294
1295
1296
1297
				if (downcase)
					c = maptolower[(int)c];
				*ndata++ = c;
				nrem--;
Bob Halley's avatar
Bob Halley committed
1298
				nused++;
1299
				state = ft_ordinary;
Bob Halley's avatar
add    
Bob Halley committed
1300
1301
1302
1303
				break;
			}
			digits = 0;
			value = 0;
1304
			state = ft_escdecimal;
Bob Halley's avatar
add    
Bob Halley committed
1305
			/* FALLTHROUGH */
1306
		case ft_escdecimal:
1307
			if (!isdigit(c & 0xff))
Bob Halley's avatar
add    
Bob Halley committed
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
				return (DNS_R_BADESCAPE);
			value *= 10;
			value += digitvalue[(int)c];
			digits++;
			if (digits == 3) {
				if (value > 255)
					return (DNS_R_BADESCAPE);
				if (count >= 63)
					return (DNS_R_LABELTOOLONG);
				count++;
				if (downcase)
					value = maptolower[value];
				*ndata++ = value;
				nrem--;
Bob Halley's avatar
Bob Halley committed
1322
				nused++;
1323
				state = ft_ordinary;
Bob Halley's avatar
add    
Bob Halley committed
1324