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