Home | History | Annotate | Line # | Download | only in dns
rbt.c revision 1.2.2.2
      1 /*	$NetBSD: rbt.c,v 1.2.2.2 2018/09/06 06:55:00 pgoyette Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 /*! \file */
     15 
     16 #include <config.h>
     17 
     18 #include <sys/stat.h>
     19 #ifdef HAVE_INTTYPES_H
     20 #include <inttypes.h> /* uintptr_t */
     21 #endif
     22 
     23 #include <isc/crc64.h>
     24 #include <isc/file.h>
     25 #include <isc/hex.h>
     26 #include <isc/mem.h>
     27 #include <isc/once.h>
     28 #include <isc/platform.h>
     29 #include <isc/print.h>
     30 #include <isc/refcount.h>
     31 #include <isc/socket.h>
     32 #include <isc/stdio.h>
     33 #include <isc/string.h>
     34 #include <isc/util.h>
     35 
     36 /*%
     37  * This define is so dns/name.h (included by dns/fixedname.h) uses more
     38  * efficient macro calls instead of functions for a few operations.
     39  */
     40 #define DNS_NAME_USEINLINE 1
     41 
     42 #include <dns/fixedname.h>
     43 #include <dns/log.h>
     44 #include <dns/rbt.h>
     45 #include <dns/result.h>
     46 #include <dns/version.h>
     47 
     48 #include <unistd.h>
     49 
     50 #define CHECK(x) \
     51 	do { \
     52 		result = (x); \
     53 		if (result != ISC_R_SUCCESS) \
     54 			goto cleanup; \
     55 	} while (/*CONSTCOND*/0)
     56 
     57 #define RBT_MAGIC               ISC_MAGIC('R', 'B', 'T', '+')
     58 #define VALID_RBT(rbt)          ISC_MAGIC_VALID(rbt, RBT_MAGIC)
     59 
     60 /*
     61  * XXXDCL Since parent pointers were added in again, I could remove all of the
     62  * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
     63  * _lastnode.  This would involve pretty major change to the API.
     64  */
     65 #define CHAIN_MAGIC             ISC_MAGIC('0', '-', '0', '-')
     66 #define VALID_CHAIN(chain)      ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
     67 
     68 #define RBT_HASH_SIZE           64
     69 
     70 #ifdef RBT_MEM_TEST
     71 #undef RBT_HASH_SIZE
     72 #define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
     73 #endif
     74 
     75 struct dns_rbt {
     76 	unsigned int		magic;
     77 	isc_mem_t *		mctx;
     78 	dns_rbtnode_t *		root;
     79 	void			(*data_deleter)(void *, void *);
     80 	void *			deleter_arg;
     81 	unsigned int		nodecount;
     82 	size_t			hashsize;
     83 	dns_rbtnode_t **	hashtable;
     84 	void *			mmap_location;
     85 };
     86 
     87 #define RED 0
     88 #define BLACK 1
     89 
     90 /*
     91  * This is the header for map-format RBT images.  It is populated,
     92  * and then written, as the LAST thing done to the file before returning.
     93  * Writing this last (with zeros in the header area initially) will ensure
     94  * that the header is only valid when the RBT image is also valid.
     95  */
     96 typedef struct file_header file_header_t;
     97 
     98 /* Pad to 32 bytes */
     99 static char FILE_VERSION[32] = "\0";
    100 
    101 /* Header length, always the same size regardless of structure size */
    102 #define HEADER_LENGTH		1024
    103 
    104 struct file_header {
    105 	char version1[32];
    106 	isc_uint64_t first_node_offset;	/* usually 1024 */
    107 	/*
    108 	 * information about the system on which the map file was generated
    109 	 * will be used to tell if we can load the map file or not
    110 	 */
    111 	isc_uint32_t ptrsize;
    112 	unsigned int bigendian:1;	/* big or little endian system */
    113 	unsigned int rdataset_fixed:1;	/* compiled with --enable-rrset-fixed */
    114 	unsigned int nodecount;		/* shadow from rbt structure */
    115 	isc_uint64_t crc;
    116 	char version2[32];  		/* repeated; must match version1 */
    117 };
    118 
    119 /*
    120  * The following declarations are for the serialization of an RBT:
    121  *
    122  * step one: write out a zeroed header of 1024 bytes
    123  * step two: walk the tree in a depth-first, left-right-down order, writing
    124  * out the nodes, reserving space as we go, correcting addresses to point
    125  * at the proper offset in the file, and setting a flag for each pointer to
    126  * indicate that it is a reference to a location in the file, rather than in
    127  * memory.
    128  * step three: write out the header, adding the information that will be
    129  * needed to re-create the tree object itself.
    130  *
    131  * The RBTDB object will do this three times, once for each of the three
    132  * RBT objects it contains.
    133  *
    134  * Note: 'file' must point an actual open file that can be mmapped
    135  * and fseeked, not to a pipe or stream
    136  */
    137 
    138 static isc_result_t
    139 dns_rbt_zero_header(FILE *file);
    140 
    141 static isc_result_t
    142 write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
    143 	     isc_uint64_t crc);
    144 
    145 static isc_boolean_t
    146 match_header_version(file_header_t *header);
    147 
    148 static isc_result_t
    149 serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
    150 	       uintptr_t right, uintptr_t down, uintptr_t parent,
    151 	       uintptr_t data, isc_uint64_t *crc);
    152 
    153 static isc_result_t
    154 serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
    155 		dns_rbtdatawriter_t datawriter, void *writer_arg,
    156 		uintptr_t *where, isc_uint64_t *crc);
    157 /*
    158  * The following functions allow you to get the actual address of a pointer
    159  * without having to use an if statement to check to see if that address is
    160  * relative or not
    161  */
    162 static inline dns_rbtnode_t *
    163 getparent(dns_rbtnode_t *node, file_header_t *header) {
    164 	char *adjusted_address = (char *)(node->parent);
    165 	adjusted_address += node->parent_is_relative * (uintptr_t)header;
    166 
    167 	return ((dns_rbtnode_t *)adjusted_address);
    168 }
    169 
    170 static inline dns_rbtnode_t *
    171 getleft(dns_rbtnode_t *node, file_header_t *header) {
    172 	char *adjusted_address = (char *)(node->left);
    173 	adjusted_address += node->left_is_relative * (uintptr_t)header;
    174 
    175 	return ((dns_rbtnode_t *)adjusted_address);
    176 }
    177 
    178 static inline dns_rbtnode_t *
    179 getright(dns_rbtnode_t *node, file_header_t *header) {
    180 	char *adjusted_address = (char *)(node->right);
    181 	adjusted_address += node->right_is_relative * (uintptr_t)header;
    182 
    183 	return ((dns_rbtnode_t *)adjusted_address);
    184 }
    185 
    186 static inline dns_rbtnode_t *
    187 getdown(dns_rbtnode_t *node, file_header_t *header) {
    188 	char *adjusted_address = (char *)(node->down);
    189 	adjusted_address += node->down_is_relative * (uintptr_t)header;
    190 
    191 	return ((dns_rbtnode_t *)adjusted_address);
    192 }
    193 
    194 static inline dns_rbtnode_t *
    195 getdata(dns_rbtnode_t *node, file_header_t *header) {
    196 	char *adjusted_address = (char *)(node->data);
    197 	adjusted_address += node->data_is_relative * (uintptr_t)header;
    198 
    199 	return ((dns_rbtnode_t *)adjusted_address);
    200 }
    201 
    202 /*%
    203  * Elements of the rbtnode structure.
    204  */
    205 #define PARENT(node)            ((node)->parent)
    206 #define LEFT(node)              ((node)->left)
    207 #define RIGHT(node)             ((node)->right)
    208 #define DOWN(node)              ((node)->down)
    209 #ifdef DNS_RBT_USEHASH
    210 #define UPPERNODE(node)         ((node)->uppernode)
    211 #endif /* DNS_RBT_USEHASH */
    212 #define DATA(node)              ((node)->data)
    213 #define IS_EMPTY(node)          ((node)->data == NULL)
    214 #define HASHNEXT(node)          ((node)->hashnext)
    215 #define HASHVAL(node)           ((node)->hashval)
    216 #define COLOR(node)             ((node)->color)
    217 #define NAMELEN(node)           ((node)->namelen)
    218 #define OLDNAMELEN(node)        ((node)->oldnamelen)
    219 #define OFFSETLEN(node)         ((node)->offsetlen)
    220 #define ATTRS(node)             ((node)->attributes)
    221 #define IS_ROOT(node)           ISC_TF((node)->is_root == 1)
    222 #define FINDCALLBACK(node)      ISC_TF((node)->find_callback == 1)
    223 
    224 /*%
    225  * Structure elements from the rbtdb.c, not
    226  * used as part of the rbt.c algorithms.
    227  */
    228 #define DIRTY(node)     ((node)->dirty)
    229 #define WILD(node)      ((node)->wild)
    230 #define LOCKNUM(node)   ((node)->locknum)
    231 
    232 /*%
    233  * The variable length stuff stored after the node has the following
    234  * structure.
    235  *
    236  *	&lt;name_data&gt;{1..255}&lt;oldoffsetlen&gt;{1}&lt;offsets&gt;{1..128}
    237  *
    238  * &lt;name_data&gt; contains the name of the node when it was created.
    239  * &lt;oldoffsetlen&gt; contains the length of &lt;offsets&gt; when the node was created.
    240  * &lt;offsets&gt; contains the offets into name for each label when the node was
    241  * created.
    242  */
    243 
    244 #define NAME(node)      ((unsigned char *)((node) + 1))
    245 #define OFFSETS(node)   (NAME(node) + OLDNAMELEN(node) + 1)
    246 #define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
    247 
    248 #define NODE_SIZE(node) (sizeof(*node) + \
    249 			 OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
    250 
    251 /*%
    252  * Color management.
    253  */
    254 #define IS_RED(node)            ((node) != NULL && (node)->color == RED)
    255 #define IS_BLACK(node)          ((node) == NULL || (node)->color == BLACK)
    256 #define MAKE_RED(node)          ((node)->color = RED)
    257 #define MAKE_BLACK(node)        ((node)->color = BLACK)
    258 
    259 /*%
    260  * Chain management.
    261  *
    262  * The "ancestors" member of chains were removed, with their job now
    263  * being wholly handled by parent pointers (which didn't exist, because
    264  * of memory concerns, when chains were first implemented).
    265  */
    266 #define ADD_LEVEL(chain, node) \
    267 	do { \
    268 		INSIST((chain)->level_count < DNS_RBT_LEVELBLOCK); \
    269 		(chain)->levels[(chain)->level_count++] = (node); \
    270 	} while (0)
    271 
    272 /*%
    273  * The following macros directly access normally private name variables.
    274  * These macros are used to avoid a lot of function calls in the critical
    275  * path of the tree traversal code.
    276  */
    277 
    278 static inline void
    279 NODENAME(dns_rbtnode_t *node, dns_name_t *name) {
    280 	name->length = NAMELEN(node);
    281 	name->labels = OFFSETLEN(node);
    282 	name->ndata = NAME(node);
    283 	name->offsets = OFFSETS(node);
    284 	name->attributes = ATTRS(node);
    285 	name->attributes |= DNS_NAMEATTR_READONLY;
    286 }
    287 
    288 void
    289 dns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name) {
    290 	name->length = NAMELEN(node);
    291 	name->labels = OFFSETLEN(node);
    292 	name->ndata = NAME(node);
    293 	name->offsets = OFFSETS(node);
    294 	name->attributes = ATTRS(node);
    295 	name->attributes |= DNS_NAMEATTR_READONLY;
    296 }
    297 
    298 dns_rbtnode_t *
    299 dns_rbt_root(dns_rbt_t *rbt) {
    300   return rbt->root;
    301 }
    302 
    303 #ifdef DNS_RBT_USEHASH
    304 static isc_result_t
    305 inithash(dns_rbt_t *rbt);
    306 #endif
    307 
    308 #ifdef DEBUG
    309 #define inline
    310 /*
    311  * A little something to help out in GDB.
    312  */
    313 dns_name_t Name(dns_rbtnode_t *node);
    314 dns_name_t
    315 Name(dns_rbtnode_t *node) {
    316 	dns_name_t name;
    317 
    318 	dns_name_init(&name, NULL);
    319 	if (node != NULL)
    320 		NODENAME(node, &name);
    321 
    322 	return (name);
    323 }
    324 
    325 static void
    326 hexdump(const char *desc, void *blob, size_t size) {
    327 	char hexdump[BUFSIZ * 2 + 1];
    328 	isc_buffer_t b;
    329 	isc_region_t r;
    330 	isc_result_t result;
    331 	size_t bytes;
    332 	isc_uint8_t *data = blob;
    333 
    334 	fprintf(stderr, "%s: ", desc);
    335 	do {
    336 		isc_buffer_init(&b, hexdump, sizeof(hexdump));
    337 		r.base = data;
    338 		r.length = bytes = (size > BUFSIZ) ? BUFSIZ : size;
    339 		result = isc_hex_totext(&r, 0, "", &b);
    340 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
    341 		isc_buffer_putuint8(&b, 0);
    342 		fprintf(stderr, "%s", hexdump);
    343 		data += bytes;
    344 		size -= bytes;
    345 	} while (size > 0);
    346 	fprintf(stderr, "\n");
    347 }
    348 #endif /* DEBUG */
    349 
    350 #ifdef DNS_RBT_USEHASH
    351 
    352 /*
    353  * Upper node is the parent of the root of the passed node's
    354  * subtree. The passed node must not be NULL.
    355  */
    356 static inline dns_rbtnode_t *
    357 get_upper_node(dns_rbtnode_t *node) {
    358 	return (UPPERNODE(node));
    359 }
    360 
    361 static void
    362 fixup_uppernodes_helper(dns_rbtnode_t *node, dns_rbtnode_t *uppernode) {
    363 	if (node == NULL)
    364 		return;
    365 
    366 	UPPERNODE(node) = uppernode;
    367 
    368 	fixup_uppernodes_helper(LEFT(node), uppernode);
    369 	fixup_uppernodes_helper(RIGHT(node), uppernode);
    370 	fixup_uppernodes_helper(DOWN(node), node);
    371 }
    372 
    373 /*
    374  * This function is used to fixup uppernode members of all dns_rbtnodes
    375  * after deserialization.
    376  */
    377 static void
    378 fixup_uppernodes(dns_rbt_t *rbt) {
    379 	fixup_uppernodes_helper(rbt->root, NULL);
    380 }
    381 
    382 #else
    383 
    384 /* The passed node must not be NULL. */
    385 static inline dns_rbtnode_t *
    386 get_subtree_root(dns_rbtnode_t *node) {
    387 	while (!IS_ROOT(node)) {
    388 		node = PARENT(node);
    389 	}
    390 
    391 	return (node);
    392 }
    393 
    394 /* Upper node is the parent of the root of the passed node's
    395  * subtree. The passed node must not be NULL.
    396  */
    397 static inline dns_rbtnode_t *
    398 get_upper_node(dns_rbtnode_t *node) {
    399 	dns_rbtnode_t *root = get_subtree_root(node);
    400 
    401 	/*
    402 	 * Return the node in the level above the argument node that points
    403 	 * to the level the argument node is in.  If the argument node is in
    404 	 * the top level, the return value is NULL.
    405 	 */
    406 	return (PARENT(root));
    407 }
    408 
    409 #endif /* DNS_RBT_USEHASH */
    410 
    411 size_t
    412 dns__rbtnode_getdistance(dns_rbtnode_t *node) {
    413 	size_t nodes = 1;
    414 
    415 	while (node != NULL) {
    416 		if (IS_ROOT(node))
    417 			break;
    418 		nodes++;
    419 		node = PARENT(node);
    420 	}
    421 
    422 	return (nodes);
    423 }
    424 
    425 /*
    426  * Forward declarations.
    427  */
    428 static isc_result_t
    429 create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep);
    430 
    431 #ifdef DNS_RBT_USEHASH
    432 static inline void
    433 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name);
    434 static inline void
    435 unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
    436 static void
    437 rehash(dns_rbt_t *rbt, unsigned int newcount);
    438 #else
    439 #define hash_node(rbt, node, name)
    440 #define unhash_node(rbt, node)
    441 #define rehash(rbt, newcount)
    442 #endif
    443 
    444 static inline void
    445 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
    446 static inline void
    447 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
    448 
    449 static void
    450 addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
    451 	   dns_rbtnode_t **rootp);
    452 
    453 static void
    454 deletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp);
    455 
    456 static isc_result_t
    457 treefix(dns_rbt_t *rbt, void *base, size_t size,
    458 	dns_rbtnode_t *n, const dns_name_t *name,
    459 	dns_rbtdatafixer_t datafixer, void *fixer_arg,
    460 	isc_uint64_t *crc);
    461 
    462 static void
    463 deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, isc_boolean_t unhash,
    464 	       dns_rbtnode_t **nodep);
    465 
    466 static void
    467 printnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f);
    468 
    469 static void
    470 freenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
    471 
    472 static isc_result_t
    473 dns_rbt_zero_header(FILE *file) {
    474 	/*
    475 	 * Write out a zeroed header as a placeholder.  Doing this ensures
    476 	 * that the file will not read while it is partially written, should
    477 	 * writing fail or be interrupted.
    478 	 */
    479 	char buffer[HEADER_LENGTH];
    480 	isc_result_t result;
    481 
    482 	memset(buffer, 0, HEADER_LENGTH);
    483 	result = isc_stdio_write(buffer, 1, HEADER_LENGTH, file, NULL);
    484 	if (result != ISC_R_SUCCESS)
    485 		return (result);
    486 
    487 	result = fflush(file);
    488 	if (result != ISC_R_SUCCESS)
    489 		return (result);
    490 
    491 	return (ISC_R_SUCCESS);
    492 }
    493 
    494 static isc_once_t once = ISC_ONCE_INIT;
    495 
    496 static void
    497 init_file_version(void) {
    498 	int n;
    499 
    500 	memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
    501 	n = snprintf(FILE_VERSION, sizeof(FILE_VERSION),
    502 		 "RBT Image %s %s", dns_major, dns_mapapi);
    503 	INSIST(n > 0 && (unsigned int)n < sizeof(FILE_VERSION));
    504 }
    505 
    506 /*
    507  * Write out the real header, including NodeDump version information
    508  * and the offset of the first node.
    509  *
    510  * Any information stored in the rbt object itself should be stored
    511  * here.
    512  */
    513 static isc_result_t
    514 write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
    515 	     isc_uint64_t crc)
    516 {
    517 	file_header_t header;
    518 	isc_result_t result;
    519 	off_t location;
    520 
    521 	RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
    522 
    523 	memset(&header, 0, sizeof(file_header_t));
    524 	memmove(header.version1, FILE_VERSION, sizeof(header.version1));
    525 	memmove(header.version2, FILE_VERSION, sizeof(header.version2));
    526 	header.first_node_offset = first_node_offset;
    527 	header.ptrsize = (isc_uint32_t) sizeof(void *);
    528 	header.bigendian = (1 == htonl(1)) ? 1 : 0;
    529 
    530 #ifdef DNS_RDATASET_FIXED
    531 	header.rdataset_fixed = 1;
    532 #else
    533 	header.rdataset_fixed = 0;
    534 #endif
    535 
    536 	header.nodecount = rbt->nodecount;
    537 
    538 	header.crc = crc;
    539 
    540 	CHECK(isc_stdio_tell(file, &location));
    541 	location = dns_rbt_serialize_align(location);
    542 	CHECK(isc_stdio_seek(file, location, SEEK_SET));
    543 	CHECK(isc_stdio_write(&header, 1, sizeof(file_header_t), file, NULL));
    544 	CHECK(fflush(file));
    545 
    546 	/* Ensure we are always at the end of the file. */
    547 	CHECK(isc_stdio_seek(file, 0, SEEK_END));
    548 
    549  cleanup:
    550 	return (result);
    551 }
    552 
    553 static isc_boolean_t
    554 match_header_version(file_header_t *header) {
    555 	RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
    556 
    557 	if (memcmp(header->version1, FILE_VERSION,
    558 		   sizeof(header->version1)) != 0 ||
    559 	    memcmp(header->version2, FILE_VERSION,
    560 		   sizeof(header->version1)) != 0)
    561 	{
    562 		return (ISC_FALSE);
    563 	}
    564 
    565 	return (ISC_TRUE);
    566 }
    567 
    568 static isc_result_t
    569 serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
    570 	       uintptr_t right, uintptr_t down, uintptr_t parent,
    571 	       uintptr_t data, isc_uint64_t *crc)
    572 {
    573 	dns_rbtnode_t temp_node;
    574 	off_t file_position;
    575 	unsigned char *node_data;
    576 	size_t datasize;
    577 	isc_result_t result;
    578 #ifdef DEBUG
    579 	dns_name_t nodename;
    580 #endif
    581 
    582 	INSIST(node != NULL);
    583 
    584 	CHECK(isc_stdio_tell(file, &file_position));
    585 	file_position = dns_rbt_serialize_align(file_position);
    586 	CHECK(isc_stdio_seek(file, file_position, SEEK_SET));
    587 
    588 	temp_node = *node;
    589 	temp_node.down_is_relative = 0;
    590 	temp_node.left_is_relative = 0;
    591 	temp_node.right_is_relative = 0;
    592 	temp_node.parent_is_relative = 0;
    593 	temp_node.data_is_relative = 0;
    594 	temp_node.is_mmapped = 1;
    595 
    596 	/*
    597 	 * If the next node is not NULL, calculate the next node's location
    598 	 * in the file.  Note that this will have to change when the data
    599 	 * structure changes, and it also assumes that we always write the
    600 	 * nodes out in list order (which we currently do.)
    601 	*/
    602 	if (temp_node.parent != NULL) {
    603 		temp_node.parent = (dns_rbtnode_t *)(parent);
    604 		temp_node.parent_is_relative = 1;
    605 	}
    606 	if (temp_node.left != NULL) {
    607 		temp_node.left = (dns_rbtnode_t *)(left);
    608 		temp_node.left_is_relative = 1;
    609 	}
    610 	if (temp_node.right != NULL) {
    611 		temp_node.right = (dns_rbtnode_t *)(right);
    612 		temp_node.right_is_relative = 1;
    613 	}
    614 	if (temp_node.down != NULL) {
    615 		temp_node.down = (dns_rbtnode_t *)(down);
    616 		temp_node.down_is_relative = 1;
    617 	}
    618 	if (temp_node.data != NULL) {
    619 		temp_node.data = (dns_rbtnode_t *)(data);
    620 		temp_node.data_is_relative = 1;
    621 	}
    622 
    623 	node_data = (unsigned char *) node + sizeof(dns_rbtnode_t);
    624 	datasize = NODE_SIZE(node) - sizeof(dns_rbtnode_t);
    625 
    626 	CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
    627 			      file, NULL));
    628 	CHECK(isc_stdio_write(node_data, 1, datasize, file, NULL));
    629 
    630 #ifdef DEBUG
    631 	dns_name_init(&nodename, NULL);
    632 	NODENAME(node, &nodename);
    633 	fprintf(stderr, "serialize ");
    634 	dns_name_print(&nodename, stderr);
    635 	fprintf(stderr, "\n");
    636 	hexdump("node header", &temp_node,
    637 		sizeof(dns_rbtnode_t));
    638 	hexdump("node data", node_data, datasize);
    639 #endif
    640 
    641 	isc_crc64_update(crc, (const isc_uint8_t *) &temp_node,
    642 			 sizeof(dns_rbtnode_t));
    643 	isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize);
    644 
    645  cleanup:
    646 	return (result);
    647 }
    648 
    649 static isc_result_t
    650 serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
    651 		dns_rbtdatawriter_t datawriter, void *writer_arg,
    652 		uintptr_t *where, isc_uint64_t *crc)
    653 {
    654 	uintptr_t left = 0, right = 0, down = 0, data = 0;
    655 	off_t location = 0, offset_adjust;
    656 	isc_result_t result;
    657 
    658 	if (node == NULL) {
    659 		if (where != NULL)
    660 			*where = 0;
    661 		return (ISC_R_SUCCESS);
    662 	}
    663 
    664 	/* Reserve space for current node. */
    665 	CHECK(isc_stdio_tell(file, &location));
    666 	location = dns_rbt_serialize_align(location);
    667 	CHECK(isc_stdio_seek(file, location, SEEK_SET));
    668 
    669 	offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
    670 	CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET));
    671 
    672 	/*
    673 	 * Serialize the rest of the tree.
    674 	 *
    675 	 * WARNING: A change in the order (from left, right, down)
    676 	 * will break the way the crc hash is computed.
    677 	 */
    678 	CHECK(serialize_nodes(file, getleft(node, NULL), location,
    679 			      datawriter, writer_arg, &left, crc));
    680 	CHECK(serialize_nodes(file, getright(node, NULL), location,
    681 			      datawriter, writer_arg, &right, crc));
    682 	CHECK(serialize_nodes(file, getdown(node, NULL), location,
    683 			      datawriter, writer_arg, &down, crc));
    684 
    685 	if (node->data != NULL) {
    686 		off_t ret;
    687 
    688 		CHECK(isc_stdio_tell(file, &ret));
    689 		ret = dns_rbt_serialize_align(ret);
    690 		CHECK(isc_stdio_seek(file, ret, SEEK_SET));
    691 		data = ret;
    692 
    693 		datawriter(file, node->data, writer_arg, crc);
    694 	}
    695 
    696 	/* Seek back to reserved space. */
    697 	CHECK(isc_stdio_seek(file, location, SEEK_SET));
    698 
    699 	/* Serialize the current node. */
    700 	CHECK(serialize_node(file, node, left, right, down, parent, data, crc));
    701 
    702 	/* Ensure we are always at the end of the file. */
    703 	CHECK(isc_stdio_seek(file, 0, SEEK_END));
    704 
    705 	if (where != NULL)
    706 		*where = (uintptr_t) location;
    707 
    708  cleanup:
    709 	return (result);
    710 }
    711 
    712 off_t
    713 dns_rbt_serialize_align(off_t target) {
    714 	off_t offset = target % 8;
    715 
    716 	if (offset == 0)
    717 		return (target);
    718 	else
    719 		return (target + 8 - offset);
    720 }
    721 
    722 isc_result_t
    723 dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
    724 		       dns_rbtdatawriter_t datawriter,
    725 		       void *writer_arg, off_t *offset)
    726 {
    727 	isc_result_t result;
    728 	off_t header_position, node_position, end_position;
    729 	isc_uint64_t crc;
    730 
    731 	REQUIRE(file != NULL);
    732 
    733 	CHECK(isc_file_isplainfilefd(fileno(file)));
    734 
    735 	isc_crc64_init(&crc);
    736 
    737 	CHECK(isc_stdio_tell(file, &header_position));
    738 
    739 	/* Write dummy header */
    740 	CHECK(dns_rbt_zero_header(file));
    741 
    742 	/* Serialize nodes */
    743 	CHECK(isc_stdio_tell(file, &node_position));
    744 	CHECK(serialize_nodes(file, rbt->root, 0, datawriter,
    745 			      writer_arg, NULL, &crc));
    746 
    747 	CHECK(isc_stdio_tell(file, &end_position));
    748 	if (node_position == end_position) {
    749 		CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
    750 		*offset = 0;
    751 		return (ISC_R_SUCCESS);
    752 	}
    753 
    754 	isc_crc64_final(&crc);
    755 #ifdef DEBUG
    756 	hexdump("serializing CRC", &crc, sizeof(crc));
    757 #endif
    758 
    759 	/* Serialize header */
    760 	CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
    761 	CHECK(write_header(file, rbt, HEADER_LENGTH, crc));
    762 
    763 	/* Ensure we are always at the end of the file. */
    764 	CHECK(isc_stdio_seek(file, 0, SEEK_END));
    765 	*offset = dns_rbt_serialize_align(header_position);
    766 
    767  cleanup:
    768 	return (result);
    769 }
    770 
    771 #define CONFIRM(a) do { \
    772 	if (! (a)) { \
    773 		result = ISC_R_INVALIDFILE; \
    774 		goto cleanup; \
    775 	} \
    776 } while(/*CONSTCOND*/0);
    777 
    778 static isc_result_t
    779 treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n,
    780 	const dns_name_t *name, dns_rbtdatafixer_t datafixer,
    781 	void *fixer_arg, isc_uint64_t *crc)
    782 {
    783 	isc_result_t result = ISC_R_SUCCESS;
    784 	dns_fixedname_t fixed;
    785 	dns_name_t nodename, *fullname;
    786 	unsigned char *node_data;
    787 	dns_rbtnode_t header;
    788 	size_t datasize, nodemax = filesize - sizeof(dns_rbtnode_t);
    789 
    790 	if (n == NULL)
    791 		return (ISC_R_SUCCESS);
    792 
    793 	CONFIRM((void *) n >= base);
    794 	CONFIRM((char *) n - (char *) base <= (int) nodemax);
    795 	CONFIRM(DNS_RBTNODE_VALID(n));
    796 
    797 	dns_name_init(&nodename, NULL);
    798 	NODENAME(n, &nodename);
    799 
    800 	fullname = &nodename;
    801 	CONFIRM(dns_name_isvalid(fullname));
    802 
    803 	if (!dns_name_isabsolute(&nodename)) {
    804 		fullname = dns_fixedname_initname(&fixed);
    805 		CHECK(dns_name_concatenate(&nodename, name, fullname, NULL));
    806 	}
    807 
    808 	/* memorize header contents prior to fixup */
    809 	memmove(&header, n, sizeof(header));
    810 
    811 	if (n->left_is_relative) {
    812 		CONFIRM(n->left <= (dns_rbtnode_t *) nodemax);
    813 		n->left = getleft(n, rbt->mmap_location);
    814 		n->left_is_relative = 0;
    815 		CONFIRM(DNS_RBTNODE_VALID(n->left));
    816 	} else
    817 		CONFIRM(n->left == NULL);
    818 
    819 	if (n->right_is_relative) {
    820 		CONFIRM(n->right <= (dns_rbtnode_t *) nodemax);
    821 		n->right = getright(n, rbt->mmap_location);
    822 		n->right_is_relative = 0;
    823 		CONFIRM(DNS_RBTNODE_VALID(n->right));
    824 	} else
    825 		CONFIRM(n->right == NULL);
    826 
    827 	if (n->down_is_relative) {
    828 		CONFIRM(n->down <= (dns_rbtnode_t *) nodemax);
    829 		n->down = getdown(n, rbt->mmap_location);
    830 		n->down_is_relative = 0;
    831 		CONFIRM(n->down > (dns_rbtnode_t *) n);
    832 		CONFIRM(DNS_RBTNODE_VALID(n->down));
    833 	} else
    834 		CONFIRM(n->down == NULL);
    835 
    836 	if (n->parent_is_relative) {
    837 		CONFIRM(n->parent <= (dns_rbtnode_t *) nodemax);
    838 		n->parent = getparent(n, rbt->mmap_location);
    839 		n->parent_is_relative = 0;
    840 		CONFIRM(n->parent < (dns_rbtnode_t *) n);
    841 		CONFIRM(DNS_RBTNODE_VALID(n->parent));
    842 	} else
    843 		CONFIRM(n->parent == NULL);
    844 
    845 	if (n->data_is_relative) {
    846 		CONFIRM(n->data <= (void *) filesize);
    847 		n->data = getdata(n, rbt->mmap_location);
    848 		n->data_is_relative = 0;
    849 		CONFIRM(n->data > (void *) n);
    850 	} else
    851 		CONFIRM(n->data == NULL);
    852 
    853 	hash_node(rbt, n, fullname);
    854 
    855 	/* a change in the order (from left, right, down) will break hashing*/
    856 	if (n->left != NULL)
    857 		CHECK(treefix(rbt, base, filesize, n->left, name,
    858 			      datafixer, fixer_arg, crc));
    859 	if (n->right != NULL)
    860 		CHECK(treefix(rbt, base, filesize, n->right, name,
    861 			      datafixer, fixer_arg, crc));
    862 	if (n->down != NULL)
    863 		CHECK(treefix(rbt, base, filesize, n->down, fullname,
    864 			      datafixer, fixer_arg, crc));
    865 
    866 	if (datafixer != NULL && n->data != NULL)
    867 		CHECK(datafixer(n, base, filesize, fixer_arg, crc));
    868 
    869 	rbt->nodecount++;
    870 	node_data = (unsigned char *) n + sizeof(dns_rbtnode_t);
    871 	datasize = NODE_SIZE(n) - sizeof(dns_rbtnode_t);
    872 
    873 #ifdef DEBUG
    874 	fprintf(stderr, "deserialize ");
    875 	dns_name_print(&nodename, stderr);
    876 	fprintf(stderr, "\n");
    877 	hexdump("node header", &header,
    878 		sizeof(dns_rbtnode_t));
    879 	hexdump("node data", node_data, datasize);
    880 #endif
    881 	isc_crc64_update(crc, (const isc_uint8_t *) &header,
    882 			sizeof(dns_rbtnode_t));
    883 	isc_crc64_update(crc, (const isc_uint8_t *) node_data,
    884 			datasize);
    885 
    886  cleanup:
    887 	return (result);
    888 }
    889 
    890 isc_result_t
    891 dns_rbt_deserialize_tree(void *base_address, size_t filesize,
    892 			 off_t header_offset, isc_mem_t *mctx,
    893 			 dns_rbtdeleter_t deleter, void *deleter_arg,
    894 			 dns_rbtdatafixer_t datafixer, void *fixer_arg,
    895 			 dns_rbtnode_t **originp, dns_rbt_t **rbtp)
    896 {
    897 	isc_result_t result = ISC_R_SUCCESS;
    898 	file_header_t *header;
    899 	dns_rbt_t *rbt = NULL;
    900 	isc_uint64_t crc;
    901 	unsigned int host_big_endian;
    902 
    903 	REQUIRE(originp == NULL || *originp == NULL);
    904 	REQUIRE(rbtp != NULL && *rbtp == NULL);
    905 
    906 	isc_crc64_init(&crc);
    907 
    908 	CHECK(dns_rbt_create(mctx, deleter, deleter_arg, &rbt));
    909 
    910 	rbt->mmap_location = base_address;
    911 
    912 	header = (file_header_t *)((char *)base_address + header_offset);
    913 	if (!match_header_version(header)) {
    914 		result = ISC_R_INVALIDFILE;
    915 		goto cleanup;
    916 	}
    917 
    918 #ifdef DNS_RDATASET_FIXED
    919 	if (header->rdataset_fixed != 1) {
    920 		result = ISC_R_INVALIDFILE;
    921 		goto cleanup;
    922 	}
    923 
    924 #else
    925 	if (header->rdataset_fixed != 0) {
    926 		result = ISC_R_INVALIDFILE;
    927 		goto cleanup;
    928 	}
    929 #endif
    930 
    931 	if (header->ptrsize != (isc_uint32_t) sizeof(void *)) {
    932 		result = ISC_R_INVALIDFILE;
    933 		goto cleanup;
    934 	}
    935 
    936 	host_big_endian = (1 == htonl(1));
    937 	if (header->bigendian != host_big_endian) {
    938 		result = ISC_R_INVALIDFILE;
    939 		goto cleanup;
    940 	}
    941 
    942 	/* Copy other data items from the header into our rbt. */
    943 	rbt->root = (dns_rbtnode_t *)((char *)base_address +
    944 				header_offset + header->first_node_offset);
    945 
    946 	if ((header->nodecount * sizeof(dns_rbtnode_t)) > filesize) {
    947 		result = ISC_R_INVALIDFILE;
    948 		goto cleanup;
    949 	}
    950 	rehash(rbt, header->nodecount);
    951 
    952 	CHECK(treefix(rbt, base_address, filesize, rbt->root,
    953 		      dns_rootname, datafixer, fixer_arg, &crc));
    954 
    955 	isc_crc64_final(&crc);
    956 #ifdef DEBUG
    957 	hexdump("deserializing CRC", &crc, sizeof(crc));
    958 #endif
    959 
    960 	/* Check file hash */
    961 	if (header->crc != crc) {
    962 		result = ISC_R_INVALIDFILE;
    963 		goto cleanup;
    964 	}
    965 
    966 	if (header->nodecount != rbt->nodecount) {
    967 		result = ISC_R_INVALIDFILE;
    968 		goto cleanup;
    969 	}
    970 
    971 #ifdef DNS_RBT_USEHASH
    972 	fixup_uppernodes(rbt);
    973 #endif /* DNS_RBT_USEHASH */
    974 
    975 	*rbtp = rbt;
    976 	if (originp != NULL)
    977 		*originp = rbt->root;
    978 
    979  cleanup:
    980 	if (result != ISC_R_SUCCESS && rbt != NULL) {
    981 		rbt->root = NULL;
    982 		rbt->nodecount = 0;
    983 		dns_rbt_destroy(&rbt);
    984 	}
    985 
    986 	return (result);
    987 }
    988 
    989 /*
    990  * Initialize a red/black tree of trees.
    991  */
    992 isc_result_t
    993 dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter,
    994 	       void *deleter_arg, dns_rbt_t **rbtp)
    995 {
    996 #ifdef DNS_RBT_USEHASH
    997 	isc_result_t result;
    998 #endif
    999 	dns_rbt_t *rbt;
   1000 
   1001 	REQUIRE(mctx != NULL);
   1002 	REQUIRE(rbtp != NULL && *rbtp == NULL);
   1003 	REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
   1004 
   1005 	rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
   1006 	if (rbt == NULL)
   1007 		return (ISC_R_NOMEMORY);
   1008 
   1009 	rbt->mctx = NULL;
   1010 	isc_mem_attach(mctx, &rbt->mctx);
   1011 	rbt->data_deleter = deleter;
   1012 	rbt->deleter_arg = deleter_arg;
   1013 	rbt->root = NULL;
   1014 	rbt->nodecount = 0;
   1015 	rbt->hashtable = NULL;
   1016 	rbt->hashsize = 0;
   1017 	rbt->mmap_location = NULL;
   1018 
   1019 #ifdef DNS_RBT_USEHASH
   1020 	result = inithash(rbt);
   1021 	if (result != ISC_R_SUCCESS) {
   1022 		isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
   1023 		return (result);
   1024 	}
   1025 #endif
   1026 
   1027 	rbt->magic = RBT_MAGIC;
   1028 
   1029 	*rbtp = rbt;
   1030 
   1031 	return (ISC_R_SUCCESS);
   1032 }
   1033 
   1034 /*
   1035  * Deallocate a red/black tree of trees.
   1036  */
   1037 void
   1038 dns_rbt_destroy(dns_rbt_t **rbtp) {
   1039 	RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
   1040 }
   1041 
   1042 isc_result_t
   1043 dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
   1044 	dns_rbt_t *rbt;
   1045 
   1046 	REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
   1047 
   1048 	rbt = *rbtp;
   1049 
   1050 	deletetreeflat(rbt, quantum, ISC_FALSE, &rbt->root);
   1051 	if (rbt->root != NULL)
   1052 		return (ISC_R_QUOTA);
   1053 
   1054 	INSIST(rbt->nodecount == 0);
   1055 
   1056 	rbt->mmap_location = NULL;
   1057 
   1058 	if (rbt->hashtable != NULL)
   1059 		isc_mem_put(rbt->mctx, rbt->hashtable,
   1060 			    rbt->hashsize * sizeof(dns_rbtnode_t *));
   1061 
   1062 	rbt->magic = 0;
   1063 
   1064 	isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
   1065 	*rbtp = NULL;
   1066 	return (ISC_R_SUCCESS);
   1067 }
   1068 
   1069 unsigned int
   1070 dns_rbt_nodecount(dns_rbt_t *rbt) {
   1071 
   1072 	REQUIRE(VALID_RBT(rbt));
   1073 
   1074 	return (rbt->nodecount);
   1075 }
   1076 
   1077 size_t
   1078 dns_rbt_hashsize(dns_rbt_t *rbt) {
   1079 
   1080 	REQUIRE(VALID_RBT(rbt));
   1081 
   1082 	return (rbt->hashsize);
   1083 }
   1084 
   1085 static inline isc_result_t
   1086 chain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
   1087 	   isc_boolean_t include_chain_end)
   1088 {
   1089 	dns_name_t nodename;
   1090 	isc_result_t result = ISC_R_SUCCESS;
   1091 	int i;
   1092 
   1093 	dns_name_init(&nodename, NULL);
   1094 
   1095 	if (include_chain_end && chain->end != NULL) {
   1096 		NODENAME(chain->end, &nodename);
   1097 		result = dns_name_copy(&nodename, name, NULL);
   1098 		if (result != ISC_R_SUCCESS)
   1099 			return (result);
   1100 	} else
   1101 		dns_name_reset(name);
   1102 
   1103 	for (i = (int)chain->level_count - 1; i >= 0; i--) {
   1104 		NODENAME(chain->levels[i], &nodename);
   1105 		result = dns_name_concatenate(name, &nodename, name, NULL);
   1106 
   1107 		if (result != ISC_R_SUCCESS)
   1108 			return (result);
   1109 	}
   1110 	return (result);
   1111 }
   1112 
   1113 static inline isc_result_t
   1114 move_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
   1115 	do {
   1116 		/*
   1117 		 * Go as far right and then down as much as possible,
   1118 		 * as long as the rightmost node has a down pointer.
   1119 		 */
   1120 		while (RIGHT(node) != NULL)
   1121 			node = RIGHT(node);
   1122 
   1123 		if (DOWN(node) == NULL)
   1124 			break;
   1125 
   1126 		ADD_LEVEL(chain, node);
   1127 		node = DOWN(node);
   1128 	} while (1);
   1129 
   1130 	chain->end = node;
   1131 
   1132 	return (ISC_R_SUCCESS);
   1133 }
   1134 
   1135 /*
   1136  * Add 'name' to tree, initializing its data pointer with 'data'.
   1137  */
   1138 
   1139 isc_result_t
   1140 dns_rbt_addnode(dns_rbt_t *rbt, const dns_name_t *name, dns_rbtnode_t **nodep) {
   1141 	/*
   1142 	 * Does this thing have too many variables or what?
   1143 	 */
   1144 	dns_rbtnode_t **root, *parent, *child, *current, *new_current;
   1145 	dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
   1146 	dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
   1147 	dns_offsets_t current_offsets;
   1148 	dns_namereln_t compared;
   1149 	isc_result_t result = ISC_R_SUCCESS;
   1150 	unsigned int level_count;
   1151 	unsigned int common_labels;
   1152 	unsigned int nlabels, hlabels;
   1153 	int order;
   1154 
   1155 	REQUIRE(VALID_RBT(rbt));
   1156 	REQUIRE(dns_name_isabsolute(name));
   1157 	REQUIRE(nodep != NULL && *nodep == NULL);
   1158 
   1159 	/*
   1160 	 * Dear future BIND developer,
   1161 	 *
   1162 	 * After you have tried attempting to optimize this routine by
   1163 	 * using the hashtable and have realized your folly, please
   1164 	 * append another cross ("X") below as a warning to the next
   1165 	 * future BIND developer:
   1166 	 *
   1167 	 * Number of victim developers: X
   1168 	 *
   1169 	 * I wish the past developer had included such a notice.
   1170 	 *
   1171 	 * Long form: Unlike dns_rbt_findnode(), this function does not
   1172 	 * lend itself to be optimized using the hashtable:
   1173 	 *
   1174 	 * 1. In the subtree where the insertion occurs, this function
   1175 	 * needs to have the insertion point and the order where the
   1176 	 * lookup terminated (i.e., at the insertion point where left or
   1177 	 * right child is NULL). This cannot be determined from the
   1178 	 * hashtable, so at least in that subtree, a BST O(log N) lookup
   1179 	 * is necessary.
   1180 	 *
   1181 	 * 2. Our RBT nodes contain not only single labels but label
   1182 	 * sequences to optimize space usage. So at every level, we have
   1183 	 * to look for a match in the hashtable for all superdomains in
   1184 	 * the rest of the name we're searching. This is an O(N)
   1185 	 * operation at least, here N being the label size of name, each
   1186 	 * of which is a hashtable lookup involving dns_name_equal()
   1187 	 * comparisons.
   1188 	 */
   1189 
   1190 	/*
   1191 	 * Create a copy of the name so the original name structure is
   1192 	 * not modified.
   1193 	 */
   1194 	add_name = dns_fixedname_initname(&fixedcopy);
   1195 	dns_name_clone(name, add_name);
   1196 
   1197 	if (ISC_UNLIKELY(rbt->root == NULL)) {
   1198 		result = create_node(rbt->mctx, add_name, &new_current);
   1199 		if (result == ISC_R_SUCCESS) {
   1200 			rbt->nodecount++;
   1201 			new_current->is_root = 1;
   1202 #ifdef DNS_RBT_USEHASH
   1203 			UPPERNODE(new_current) = NULL;
   1204 #endif /* DNS_RBT_USEHASH */
   1205 			rbt->root = new_current;
   1206 			*nodep = new_current;
   1207 			hash_node(rbt, new_current, name);
   1208 		}
   1209 		return (result);
   1210 	}
   1211 
   1212 	level_count = 0;
   1213 
   1214 	prefix = dns_fixedname_initname(&fixedprefix);
   1215 	suffix = dns_fixedname_initname(&fixedsuffix);
   1216 
   1217 	root = &rbt->root;
   1218 	INSIST(IS_ROOT(*root));
   1219 	parent = NULL;
   1220 	current = NULL;
   1221 	child = *root;
   1222 	dns_name_init(&current_name, current_offsets);
   1223 	new_name = dns_fixedname_initname(&fnewname);
   1224 	nlabels = dns_name_countlabels(name);
   1225 	hlabels = 0;
   1226 
   1227 	do {
   1228 		current = child;
   1229 
   1230 		NODENAME(current, &current_name);
   1231 		compared = dns_name_fullcompare(add_name, &current_name,
   1232 						&order, &common_labels);
   1233 
   1234 		if (compared == dns_namereln_equal) {
   1235 			*nodep = current;
   1236 			result = ISC_R_EXISTS;
   1237 			break;
   1238 
   1239 		}
   1240 
   1241 		if (compared == dns_namereln_none) {
   1242 
   1243 			if (order < 0) {
   1244 				parent = current;
   1245 				child = LEFT(current);
   1246 
   1247 			} else if (order > 0) {
   1248 				parent = current;
   1249 				child = RIGHT(current);
   1250 
   1251 			}
   1252 
   1253 		} else {
   1254 			/*
   1255 			 * This name has some suffix in common with the
   1256 			 * name at the current node.  If the name at
   1257 			 * the current node is shorter, that means the
   1258 			 * new name should be in a subtree.  If the
   1259 			 * name at the current node is longer, that means
   1260 			 * the down pointer to this tree should point
   1261 			 * to a new tree that has the common suffix, and
   1262 			 * the non-common parts of these two names should
   1263 			 * start a new tree.
   1264 			 */
   1265 			hlabels += common_labels;
   1266 			if (compared == dns_namereln_subdomain) {
   1267 				/*
   1268 				 * All of the existing labels are in common,
   1269 				 * so the new name is in a subtree.
   1270 				 * Whack off the common labels for the
   1271 				 * not-in-common part to be searched for
   1272 				 * in the next level.
   1273 				 */
   1274 				dns_name_split(add_name, common_labels,
   1275 					       add_name, NULL);
   1276 
   1277 				/*
   1278 				 * Follow the down pointer (possibly NULL).
   1279 				 */
   1280 				root = &DOWN(current);
   1281 
   1282 				INSIST(*root == NULL ||
   1283 				       (IS_ROOT(*root) &&
   1284 					PARENT(*root) == current));
   1285 
   1286 				parent = NULL;
   1287 				child = DOWN(current);
   1288 
   1289 				INSIST(level_count < DNS_RBT_LEVELBLOCK);
   1290 				level_count++;
   1291 			} else {
   1292 				/*
   1293 				 * The number of labels in common is fewer
   1294 				 * than the number of labels at the current
   1295 				 * node, so the current node must be adjusted
   1296 				 * to have just the common suffix, and a down
   1297 				 * pointer made to a new tree.
   1298 				 */
   1299 
   1300 				INSIST(compared == dns_namereln_commonancestor
   1301 				       || compared == dns_namereln_contains);
   1302 
   1303 				/*
   1304 				 * Ensure the number of levels in the tree
   1305 				 * does not exceed the number of logical
   1306 				 * levels allowed by DNSSEC.
   1307 				 *
   1308 				 * XXXDCL need a better error result?
   1309 				 */
   1310 				if (level_count >= DNS_RBT_LEVELBLOCK) {
   1311 					result = ISC_R_NOSPACE;
   1312 					break;
   1313 				}
   1314 
   1315 				/*
   1316 				 * Split the name into two parts, a prefix
   1317 				 * which is the not-in-common parts of the
   1318 				 * two names and a suffix that is the common
   1319 				 * parts of them.
   1320 				 */
   1321 				dns_name_split(&current_name, common_labels,
   1322 					       prefix, suffix);
   1323 				result = create_node(rbt->mctx, suffix,
   1324 						     &new_current);
   1325 
   1326 				if (result != ISC_R_SUCCESS)
   1327 					break;
   1328 
   1329 				/*
   1330 				 * Reproduce the tree attributes of the
   1331 				 * current node.
   1332 				 */
   1333 				new_current->is_root = current->is_root;
   1334 				if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
   1335 					new_current->nsec = DNS_RBT_NSEC_NORMAL;
   1336 				else
   1337 					new_current->nsec = current->nsec;
   1338 				PARENT(new_current)  = PARENT(current);
   1339 				LEFT(new_current)    = LEFT(current);
   1340 				RIGHT(new_current)   = RIGHT(current);
   1341 				COLOR(new_current)   = COLOR(current);
   1342 
   1343 				/*
   1344 				 * Fix pointers that were to the current node.
   1345 				 */
   1346 				if (parent != NULL) {
   1347 					if (LEFT(parent) == current)
   1348 						LEFT(parent) = new_current;
   1349 					else
   1350 						RIGHT(parent) = new_current;
   1351 				}
   1352 				if (LEFT(new_current) != NULL)
   1353 					PARENT(LEFT(new_current)) =
   1354 						new_current;
   1355 				if (RIGHT(new_current) != NULL)
   1356 					PARENT(RIGHT(new_current)) =
   1357 						new_current;
   1358 				if (*root == current)
   1359 					*root = new_current;
   1360 
   1361 				NAMELEN(current) = prefix->length;
   1362 				OFFSETLEN(current) = prefix->labels;
   1363 
   1364 				/*
   1365 				 * Set up the new root of the next level.
   1366 				 * By definition it will not be the top
   1367 				 * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
   1368 				 */
   1369 				current->is_root = 1;
   1370 				PARENT(current) = new_current;
   1371 				DOWN(new_current) = current;
   1372 				root = &DOWN(new_current);
   1373 #ifdef DNS_RBT_USEHASH
   1374 				UPPERNODE(new_current) = UPPERNODE(current);
   1375 				UPPERNODE(current) = new_current;
   1376 #endif /* DNS_RBT_USEHASH */
   1377 
   1378 				INSIST(level_count < DNS_RBT_LEVELBLOCK);
   1379 				level_count++;
   1380 
   1381 				LEFT(current) = NULL;
   1382 				RIGHT(current) = NULL;
   1383 
   1384 				MAKE_BLACK(current);
   1385 				ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
   1386 
   1387 				rbt->nodecount++;
   1388 				dns_name_getlabelsequence(name,
   1389 							  nlabels - hlabels,
   1390 							  hlabels, new_name);
   1391 				hash_node(rbt, new_current, new_name);
   1392 
   1393 				if (common_labels ==
   1394 				    dns_name_countlabels(add_name)) {
   1395 					/*
   1396 					 * The name has been added by pushing
   1397 					 * the not-in-common parts down to
   1398 					 * a new level.
   1399 					 */
   1400 					*nodep = new_current;
   1401 					return (ISC_R_SUCCESS);
   1402 
   1403 				} else {
   1404 					/*
   1405 					 * The current node has no data,
   1406 					 * because it is just a placeholder.
   1407 					 * Its data pointer is already NULL
   1408 					 * from create_node()), so there's
   1409 					 * nothing more to do to it.
   1410 					 */
   1411 
   1412 					/*
   1413 					 * The not-in-common parts of the new
   1414 					 * name will be inserted into the new
   1415 					 * level following this loop (unless
   1416 					 * result != ISC_R_SUCCESS, which
   1417 					 * is tested after the loop ends).
   1418 					 */
   1419 					dns_name_split(add_name, common_labels,
   1420 						       add_name, NULL);
   1421 
   1422 					break;
   1423 				}
   1424 
   1425 			}
   1426 
   1427 		}
   1428 
   1429 	} while (ISC_LIKELY(child != NULL));
   1430 
   1431 	if (ISC_LIKELY(result == ISC_R_SUCCESS))
   1432 		result = create_node(rbt->mctx, add_name, &new_current);
   1433 
   1434 	if (ISC_LIKELY(result == ISC_R_SUCCESS)) {
   1435 #ifdef DNS_RBT_USEHASH
   1436 		if (*root == NULL)
   1437 			UPPERNODE(new_current) = current;
   1438 		else
   1439 			UPPERNODE(new_current) = PARENT(*root);
   1440 #endif /* DNS_RBT_USEHASH */
   1441 		addonlevel(new_current, current, order, root);
   1442 		rbt->nodecount++;
   1443 		*nodep = new_current;
   1444 		hash_node(rbt, new_current, name);
   1445 	}
   1446 
   1447 	return (result);
   1448 }
   1449 
   1450 /*
   1451  * Add a name to the tree of trees, associating it with some data.
   1452  */
   1453 isc_result_t
   1454 dns_rbt_addname(dns_rbt_t *rbt, const dns_name_t *name, void *data) {
   1455 	isc_result_t result;
   1456 	dns_rbtnode_t *node;
   1457 
   1458 	REQUIRE(VALID_RBT(rbt));
   1459 	REQUIRE(dns_name_isabsolute(name));
   1460 
   1461 	node = NULL;
   1462 
   1463 	result = dns_rbt_addnode(rbt, name, &node);
   1464 
   1465 	/*
   1466 	 * dns_rbt_addnode will report the node exists even when
   1467 	 * it does not have data associated with it, but the
   1468 	 * dns_rbt_*name functions all behave depending on whether
   1469 	 * there is data associated with a node.
   1470 	 */
   1471 	if (result == ISC_R_SUCCESS ||
   1472 	    (result == ISC_R_EXISTS && DATA(node) == NULL)) {
   1473 		DATA(node) = data;
   1474 		result = ISC_R_SUCCESS;
   1475 	}
   1476 
   1477 	return (result);
   1478 }
   1479 
   1480 /*
   1481  * Find the node for "name" in the tree of trees.
   1482  */
   1483 isc_result_t
   1484 dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
   1485 		 dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
   1486 		 unsigned int options, dns_rbtfindcallback_t callback,
   1487 		 void *callback_arg)
   1488 {
   1489 	dns_rbtnode_t *current, *last_compared;
   1490 	dns_rbtnodechain_t localchain;
   1491 	dns_name_t *search_name, current_name, *callback_name;
   1492 	dns_fixedname_t fixedcallbackname, fixedsearchname;
   1493 	dns_namereln_t compared;
   1494 	isc_result_t result, saved_result;
   1495 	unsigned int common_labels;
   1496 	unsigned int hlabels = 0;
   1497 	int order;
   1498 
   1499 	REQUIRE(VALID_RBT(rbt));
   1500 	REQUIRE(dns_name_isabsolute(name));
   1501 	REQUIRE(node != NULL && *node == NULL);
   1502 	REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
   1503 		!=         (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
   1504 
   1505 	/*
   1506 	 * If there is a chain it needs to appear to be in a sane state,
   1507 	 * otherwise a chain is still needed to generate foundname and
   1508 	 * callback_name.
   1509 	 */
   1510 	if (chain == NULL) {
   1511 		options |= DNS_RBTFIND_NOPREDECESSOR;
   1512 		chain = &localchain;
   1513 		dns_rbtnodechain_init(chain, rbt->mctx);
   1514 	} else
   1515 		dns_rbtnodechain_reset(chain);
   1516 
   1517 	if (ISC_UNLIKELY(rbt->root == NULL))
   1518 		return (ISC_R_NOTFOUND);
   1519 
   1520 	/*
   1521 	 * Appease GCC about variables it incorrectly thinks are
   1522 	 * possibly used uninitialized.
   1523 	 */
   1524 	compared = dns_namereln_none;
   1525 	last_compared = NULL;
   1526 	order = 0;
   1527 
   1528 	callback_name = dns_fixedname_initname(&fixedcallbackname);
   1529 
   1530 	/*
   1531 	 * search_name is the name segment being sought in each tree level.
   1532 	 * By using a fixedname, the search_name will definitely have offsets
   1533 	 * for use by any splitting.
   1534 	 * By using dns_name_clone, no name data should be copied thanks to
   1535 	 * the lack of bitstring labels.
   1536 	 */
   1537 	search_name = dns_fixedname_initname(&fixedsearchname);
   1538 	dns_name_clone(name, search_name);
   1539 
   1540 	dns_name_init(&current_name, NULL);
   1541 
   1542 	saved_result = ISC_R_SUCCESS;
   1543 	current = rbt->root;
   1544 
   1545 	while (ISC_LIKELY(current != NULL)) {
   1546 		NODENAME(current, &current_name);
   1547 		compared = dns_name_fullcompare(search_name, &current_name,
   1548 						&order, &common_labels);
   1549 		/*
   1550 		 * last_compared is used as a shortcut to start (or
   1551 		 * continue rather) finding the stop-node of the search
   1552 		 * when hashing was used (see much below in this
   1553 		 * function).
   1554 		 */
   1555 		last_compared = current;
   1556 
   1557 		if (compared == dns_namereln_equal)
   1558 			break;
   1559 
   1560 		if (compared == dns_namereln_none) {
   1561 #ifdef DNS_RBT_USEHASH
   1562 			/*
   1563 			 * Here, current is pointing at a subtree root
   1564 			 * node. We try to find a matching node using
   1565 			 * the hashtable. We can get one of 3 results
   1566 			 * here: (a) we locate the matching node, (b) we
   1567 			 * find a node to which the current node has a
   1568 			 * subdomain relation, (c) we fail to find (a)
   1569 			 * or (b).
   1570 			 */
   1571 
   1572 			dns_name_t hash_name;
   1573 			dns_rbtnode_t *hnode;
   1574 			dns_rbtnode_t *up_current;
   1575 			unsigned int nlabels;
   1576 			unsigned int tlabels = 1;
   1577 			unsigned int hash;
   1578 
   1579 			/*
   1580 			 * The case of current not being a subtree root,
   1581 			 * that means a left or right pointer was
   1582 			 * followed, only happens when the algorithm
   1583 			 * fell through to the traditional binary search
   1584 			 * because of a bitstring label.  Since we
   1585 			 * dropped the bitstring support, this should
   1586 			 * not happen.
   1587 			 */
   1588 			INSIST(IS_ROOT(current));
   1589 
   1590 			nlabels = dns_name_countlabels(search_name);
   1591 
   1592 			/*
   1593 			 * current is the root of the current level, so
   1594 			 * its parent is the same as its "up" pointer.
   1595 			 */
   1596 			up_current = PARENT(current);
   1597 			dns_name_init(&hash_name, NULL);
   1598 
   1599 		hashagain:
   1600 			/*
   1601 			 * Compute the hash over the full absolute
   1602 			 * name. Look for the smallest suffix match at
   1603 			 * this tree level (hlevel), and then at every
   1604 			 * iteration, look for the next smallest suffix
   1605 			 * match (add another subdomain label to the
   1606 			 * absolute name being hashed).
   1607 			 */
   1608 			dns_name_getlabelsequence(name,
   1609 						  nlabels - tlabels,
   1610 						  hlabels + tlabels,
   1611 						  &hash_name);
   1612 			hash = dns_name_fullhash(&hash_name, ISC_FALSE);
   1613 			dns_name_getlabelsequence(search_name,
   1614 						  nlabels - tlabels,
   1615 						  tlabels, &hash_name);
   1616 
   1617 			/*
   1618 			 * Walk all the nodes in the hash bucket pointed
   1619 			 * by the computed hash value.
   1620 			 */
   1621 			for (hnode = rbt->hashtable[hash % rbt->hashsize];
   1622 			     hnode != NULL;
   1623 			     hnode = hnode->hashnext)
   1624 			{
   1625 				dns_name_t hnode_name;
   1626 
   1627 				if (ISC_LIKELY(hash != HASHVAL(hnode)))
   1628 					continue;
   1629 				/*
   1630 				 * This checks that the hashed label
   1631 				 * sequence being looked up is at the
   1632 				 * same tree level, so that we don't
   1633 				 * match a labelsequence from some other
   1634 				 * subdomain.
   1635 				 */
   1636 				if (ISC_LIKELY(get_upper_node(hnode) != up_current))
   1637 					continue;
   1638 
   1639 				dns_name_init(&hnode_name, NULL);
   1640 				NODENAME(hnode, &hnode_name);
   1641 				if (ISC_LIKELY(dns_name_equal(&hnode_name, &hash_name)))
   1642 					break;
   1643 			}
   1644 
   1645 			if (hnode != NULL) {
   1646 				current = hnode;
   1647 				/*
   1648 				 * This is an optimization.  If hashing found
   1649 				 * the right node, the next call to
   1650 				 * dns_name_fullcompare() would obviously
   1651 				 * return _equal or _subdomain.  Determine
   1652 				 * which of those would be the case by
   1653 				 * checking if the full name was hashed.  Then
   1654 				 * make it look like dns_name_fullcompare
   1655 				 * was called and jump to the right place.
   1656 				 */
   1657 				if (tlabels == nlabels) {
   1658 					compared = dns_namereln_equal;
   1659 					break;
   1660 				} else {
   1661 					common_labels = tlabels;
   1662 					compared = dns_namereln_subdomain;
   1663 					goto subdomain;
   1664 				}
   1665 			}
   1666 
   1667 			if (tlabels++ < nlabels)
   1668 				goto hashagain;
   1669 
   1670 			/*
   1671 			 * All of the labels have been tried against the hash
   1672 			 * table.  Since we dropped the support of bitstring
   1673 			 * labels, the name isn't in the table.
   1674 			 */
   1675 			current = NULL;
   1676 			continue;
   1677 
   1678 #else /* DNS_RBT_USEHASH */
   1679 
   1680 			/*
   1681 			 * Standard binary search tree movement.
   1682 			 */
   1683 			if (order < 0)
   1684 				current = LEFT(current);
   1685 			else
   1686 				current = RIGHT(current);
   1687 
   1688 #endif /* DNS_RBT_USEHASH */
   1689 
   1690 		} else {
   1691 			/*
   1692 			 * The names have some common suffix labels.
   1693 			 *
   1694 			 * If the number in common are equal in length to
   1695 			 * the current node's name length, then follow the
   1696 			 * down pointer and search in the new tree.
   1697 			 */
   1698 			if (compared == dns_namereln_subdomain) {
   1699 #ifdef DNS_RBT_USEHASH
   1700 		subdomain:
   1701 #endif
   1702 				/*
   1703 				 * Whack off the current node's common parts
   1704 				 * for the name to search in the next level.
   1705 				 */
   1706 				dns_name_split(search_name, common_labels,
   1707 					       search_name, NULL);
   1708 				hlabels += common_labels;
   1709 				/*
   1710 				 * This might be the closest enclosing name.
   1711 				 */
   1712 				if (DATA(current) != NULL ||
   1713 				    (options & DNS_RBTFIND_EMPTYDATA) != 0)
   1714 					*node = current;
   1715 
   1716 				/*
   1717 				 * Point the chain to the next level.   This
   1718 				 * needs to be done before 'current' is pointed
   1719 				 * there because the callback in the next
   1720 				 * block of code needs the current 'current',
   1721 				 * but in the event the callback requests that
   1722 				 * the search be stopped then the
   1723 				 * DNS_R_PARTIALMATCH code at the end of this
   1724 				 * function needs the chain pointed to the
   1725 				 * next level.
   1726 				 */
   1727 				ADD_LEVEL(chain, current);
   1728 
   1729 				/*
   1730 				 * The caller may want to interrupt the
   1731 				 * downward search when certain special nodes
   1732 				 * are traversed.  If this is a special node,
   1733 				 * the callback is used to learn what the
   1734 				 * caller wants to do.
   1735 				 */
   1736 				if (callback != NULL &&
   1737 				    FINDCALLBACK(current)) {
   1738 					result = chain_name(chain,
   1739 							    callback_name,
   1740 							    ISC_FALSE);
   1741 					if (result != ISC_R_SUCCESS) {
   1742 						dns_rbtnodechain_reset(chain);
   1743 						return (result);
   1744 					}
   1745 
   1746 					result = (callback)(current,
   1747 							    callback_name,
   1748 							    callback_arg);
   1749 					if (result != DNS_R_CONTINUE) {
   1750 						saved_result = result;
   1751 						/*
   1752 						 * Treat this node as if it
   1753 						 * had no down pointer.
   1754 						 */
   1755 						current = NULL;
   1756 						break;
   1757 					}
   1758 				}
   1759 
   1760 				/*
   1761 				 * Finally, head to the next tree level.
   1762 				 */
   1763 				current = DOWN(current);
   1764 			} else {
   1765 				/*
   1766 				 * Though there are labels in common, the
   1767 				 * entire name at this node is not common
   1768 				 * with the search name so the search
   1769 				 * name does not exist in the tree.
   1770 				 */
   1771 				INSIST(compared == dns_namereln_commonancestor
   1772 				       || compared == dns_namereln_contains);
   1773 
   1774 				current = NULL;
   1775 			}
   1776 		}
   1777 	}
   1778 
   1779 	/*
   1780 	 * If current is not NULL, NOEXACT is not disallowing exact matches,
   1781 	 * and either the node has data or an empty node is ok, return
   1782 	 * ISC_R_SUCCESS to indicate an exact match.
   1783 	 */
   1784 	if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
   1785 	    (DATA(current) != NULL ||
   1786 	     (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
   1787 		/*
   1788 		 * Found an exact match.
   1789 		 */
   1790 		chain->end = current;
   1791 		chain->level_matches = chain->level_count;
   1792 
   1793 		if (foundname != NULL)
   1794 			result = chain_name(chain, foundname, ISC_TRUE);
   1795 		else
   1796 			result = ISC_R_SUCCESS;
   1797 
   1798 		if (result == ISC_R_SUCCESS) {
   1799 			*node = current;
   1800 			result = saved_result;
   1801 		} else
   1802 			*node = NULL;
   1803 	} else {
   1804 		/*
   1805 		 * Did not find an exact match (or did not want one).
   1806 		 */
   1807 		if (*node != NULL) {
   1808 			/*
   1809 			 * ... but found a partially matching superdomain.
   1810 			 * Unwind the chain to the partial match node
   1811 			 * to set level_matches to the level above the node,
   1812 			 * and then to derive the name.
   1813 			 *
   1814 			 * chain->level_count is guaranteed to be at least 1
   1815 			 * here because by definition of finding a superdomain,
   1816 			 * the chain is pointed to at least the first subtree.
   1817 			 */
   1818 			chain->level_matches = chain->level_count - 1;
   1819 
   1820 			while (chain->levels[chain->level_matches] != *node) {
   1821 				INSIST(chain->level_matches > 0);
   1822 				chain->level_matches--;
   1823 			}
   1824 
   1825 			if (foundname != NULL) {
   1826 				unsigned int saved_count = chain->level_count;
   1827 
   1828 				chain->level_count = chain->level_matches + 1;
   1829 
   1830 				result = chain_name(chain, foundname,
   1831 						    ISC_FALSE);
   1832 
   1833 				chain->level_count = saved_count;
   1834 			} else
   1835 				result = ISC_R_SUCCESS;
   1836 
   1837 			if (result == ISC_R_SUCCESS)
   1838 				result = DNS_R_PARTIALMATCH;
   1839 
   1840 		} else
   1841 			result = ISC_R_NOTFOUND;
   1842 
   1843 		if (current != NULL) {
   1844 			/*
   1845 			 * There was an exact match but either
   1846 			 * DNS_RBTFIND_NOEXACT was set, or
   1847 			 * DNS_RBTFIND_EMPTYDATA was set and the node had no
   1848 			 * data.  A policy decision was made to set the
   1849 			 * chain to the exact match, but this is subject
   1850 			 * to change if it becomes apparent that something
   1851 			 * else would be more useful.  It is important that
   1852 			 * this case is handled here, because the predecessor
   1853 			 * setting code below assumes the match was not exact.
   1854 			 */
   1855 			INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
   1856 			       ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
   1857 				DATA(current) == NULL));
   1858 			chain->end = current;
   1859 
   1860 		} else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
   1861 			/*
   1862 			 * Ensure the chain points nowhere.
   1863 			 */
   1864 			chain->end = NULL;
   1865 
   1866 		} else {
   1867 			/*
   1868 			 * Since there was no exact match, the chain argument
   1869 			 * needs to be pointed at the DNSSEC predecessor of
   1870 			 * the search name.
   1871 			 */
   1872 			if (compared == dns_namereln_subdomain) {
   1873 				/*
   1874 				 * Attempted to follow a down pointer that was
   1875 				 * NULL, which means the searched for name was
   1876 				 * a subdomain of a terminal name in the tree.
   1877 				 * Since there are no existing subdomains to
   1878 				 * order against, the terminal name is the
   1879 				 * predecessor.
   1880 				 */
   1881 				INSIST(chain->level_count > 0);
   1882 				INSIST(chain->level_matches <
   1883 				       chain->level_count);
   1884 				chain->end =
   1885 					chain->levels[--chain->level_count];
   1886 
   1887 			} else {
   1888 				isc_result_t result2;
   1889 
   1890 				/*
   1891 				 * Point current to the node that stopped
   1892 				 * the search.
   1893 				 *
   1894 				 * With the hashing modification that has been
   1895 				 * added to the algorithm, the stop node of a
   1896 				 * standard binary search is not known.  So it
   1897 				 * has to be found.  There is probably a more
   1898 				 * clever way of doing this.
   1899 				 *
   1900 				 * The assignment of current to NULL when
   1901 				 * the relationship is *not* dns_namereln_none,
   1902 				 * even though it later gets set to the same
   1903 				 * last_compared anyway, is simply to not push
   1904 				 * the while loop in one more level of
   1905 				 * indentation.
   1906 				 */
   1907 				if (compared == dns_namereln_none)
   1908 					current = last_compared;
   1909 				else
   1910 					current = NULL;
   1911 
   1912 				while (current != NULL) {
   1913 					NODENAME(current, &current_name);
   1914 					compared = dns_name_fullcompare(
   1915 								search_name,
   1916 								&current_name,
   1917 								&order,
   1918 								&common_labels);
   1919 					POST(compared);
   1920 
   1921 					last_compared = current;
   1922 
   1923 					/*
   1924 					 * Standard binary search movement.
   1925 					 */
   1926 					if (order < 0)
   1927 						current = LEFT(current);
   1928 					else
   1929 						current = RIGHT(current);
   1930 
   1931 				}
   1932 
   1933 				current = last_compared;
   1934 
   1935 				/*
   1936 				 * Reached a point within a level tree that
   1937 				 * positively indicates the name is not
   1938 				 * present, but the stop node could be either
   1939 				 * less than the desired name (order > 0) or
   1940 				 * greater than the desired name (order < 0).
   1941 				 *
   1942 				 * If the stop node is less, it is not
   1943 				 * necessarily the predecessor.  If the stop
   1944 				 * node has a down pointer, then the real
   1945 				 * predecessor is at the end of a level below
   1946 				 * (not necessarily the next level).
   1947 				 * Move down levels until the rightmost node
   1948 				 * does not have a down pointer.
   1949 				 *
   1950 				 * When the stop node is greater, it is
   1951 				 * the successor.  All the logic for finding
   1952 				 * the predecessor is handily encapsulated
   1953 				 * in dns_rbtnodechain_prev.  In the event
   1954 				 * that the search name is less than anything
   1955 				 * else in the tree, the chain is reset.
   1956 				 * XXX DCL What is the best way for the caller
   1957 				 *         to know that the search name has
   1958 				 *         no predecessor?
   1959 				 */
   1960 
   1961 
   1962 				if (order > 0) {
   1963 					if (DOWN(current) != NULL) {
   1964 						ADD_LEVEL(chain, current);
   1965 
   1966 						result2 =
   1967 						      move_chain_to_last(chain,
   1968 								DOWN(current));
   1969 
   1970 						if (result2 != ISC_R_SUCCESS)
   1971 							result = result2;
   1972 					} else
   1973 						/*
   1974 						 * Ah, the pure and simple
   1975 						 * case.  The stop node is the
   1976 						 * predecessor.
   1977 						 */
   1978 						chain->end = current;
   1979 
   1980 				} else {
   1981 					INSIST(order < 0);
   1982 
   1983 					chain->end = current;
   1984 
   1985 					result2 = dns_rbtnodechain_prev(chain,
   1986 									NULL,
   1987 									NULL);
   1988 					if (result2 == ISC_R_SUCCESS ||
   1989 					    result2 == DNS_R_NEWORIGIN)
   1990 						;       /* Nothing. */
   1991 					else if (result2 == ISC_R_NOMORE)
   1992 						/*
   1993 						 * There is no predecessor.
   1994 						 */
   1995 						dns_rbtnodechain_reset(chain);
   1996 					else
   1997 						result = result2;
   1998 				}
   1999 
   2000 			}
   2001 		}
   2002 	}
   2003 
   2004 	ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
   2005 
   2006 	return (result);
   2007 }
   2008 
   2009 /*
   2010  * Get the data pointer associated with 'name'.
   2011  */
   2012 isc_result_t
   2013 dns_rbt_findname(dns_rbt_t *rbt, const dns_name_t *name, unsigned int options,
   2014 		 dns_name_t *foundname, void **data) {
   2015 	dns_rbtnode_t *node = NULL;
   2016 	isc_result_t result;
   2017 
   2018 	REQUIRE(data != NULL && *data == NULL);
   2019 
   2020 	result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
   2021 				  options, NULL, NULL);
   2022 
   2023 	if (node != NULL &&
   2024 	    (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
   2025 		*data = DATA(node);
   2026 	else
   2027 		result = ISC_R_NOTFOUND;
   2028 
   2029 	return (result);
   2030 }
   2031 
   2032 /*
   2033  * Delete a name from the tree of trees.
   2034  */
   2035 isc_result_t
   2036 dns_rbt_deletename(dns_rbt_t *rbt, const dns_name_t *name,
   2037 		   isc_boolean_t recurse)
   2038 {
   2039 	dns_rbtnode_t *node = NULL;
   2040 	isc_result_t result;
   2041 
   2042 	REQUIRE(VALID_RBT(rbt));
   2043 	REQUIRE(dns_name_isabsolute(name));
   2044 
   2045 	/*
   2046 	 * First, find the node.
   2047 	 *
   2048 	 * When searching, the name might not have an exact match:
   2049 	 * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
   2050 	 * elements of a tree, which would make layer 1 a single
   2051 	 * node tree of "b.a.com" and layer 2 a three node tree of
   2052 	 * a, b, and c.  Deleting a.com would find only a partial depth
   2053 	 * match in the first layer.  Should it be a requirement that
   2054 	 * that the name to be deleted have data?  For now, it is.
   2055 	 *
   2056 	 * ->dirty, ->locknum and ->references are ignored; they are
   2057 	 * solely the province of rbtdb.c.
   2058 	 */
   2059 	result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
   2060 				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
   2061 
   2062 	if (result == ISC_R_SUCCESS) {
   2063 		if (DATA(node) != NULL)
   2064 			result = dns_rbt_deletenode(rbt, node, recurse);
   2065 		else
   2066 			result = ISC_R_NOTFOUND;
   2067 
   2068 	} else if (result == DNS_R_PARTIALMATCH)
   2069 		result = ISC_R_NOTFOUND;
   2070 
   2071 	return (result);
   2072 }
   2073 
   2074 /*
   2075  * Remove a node from the tree of trees.
   2076  *
   2077  * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
   2078  * a sequence of additions to be deletions will not generally get the
   2079  * tree back to the state it started in.  For example, if the addition
   2080  * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
   2081  * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
   2082  * restoring "a.b.c".  The RBT *used* to do this kind of rejoining, but it
   2083  * turned out to be a bad idea because it could corrupt an active nodechain
   2084  * that had "b.c" as one of its levels -- and the RBT has no idea what
   2085  * nodechains are in use by callers, so it can't even *try* to helpfully
   2086  * fix them up (which would probably be doomed to failure anyway).
   2087  *
   2088  * Similarly, it is possible to leave the tree in a state where a supposedly
   2089  * deleted node still exists.  The first case of this is obvious; take
   2090  * the tree which has "b.c" on one level, pointing to "a".  Now deleted "b.c".
   2091  * It was just established in the previous paragraph why we can't pull "a"
   2092  * back up to its parent level.  But what happens when "a" then gets deleted?
   2093  * "b.c" is left hanging around without data or children.  This condition
   2094  * is actually pretty easy to detect, but ... should it really be removed?
   2095  * Is a chain pointing to it?  An iterator?  Who knows!  (Note that the
   2096  * references structure member cannot be looked at because it is private to
   2097  * rbtdb.)  This is ugly and makes me unhappy, but after hours of trying to
   2098  * make it more aesthetically proper and getting nowhere, this is the way it
   2099  * is going to stay until such time as it proves to be a *real* problem.
   2100  *
   2101  * Finally, for reference, note that the original routine that did node
   2102  * joining was called join_nodes().  It has been excised, living now only
   2103  * in the CVS history, but comments have been left behind that point to it just
   2104  * in case someone wants to muck with this some more.
   2105  *
   2106  * The one positive aspect of all of this is that joining used to have a
   2107  * case where it might fail.  Without trying to join, now this function always
   2108  * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
   2109  */
   2110 isc_result_t
   2111 dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
   2112 {
   2113 	dns_rbtnode_t *parent;
   2114 
   2115 	REQUIRE(VALID_RBT(rbt));
   2116 	REQUIRE(DNS_RBTNODE_VALID(node));
   2117 	INSIST(rbt->nodecount != 0);
   2118 
   2119 	if (DOWN(node) != NULL) {
   2120 		if (recurse) {
   2121 			PARENT(DOWN(node)) = NULL;
   2122 			deletetreeflat(rbt, 0, ISC_TRUE, &DOWN(node));
   2123 		} else {
   2124 			if (DATA(node) != NULL && rbt->data_deleter != NULL)
   2125 				rbt->data_deleter(DATA(node), rbt->deleter_arg);
   2126 			DATA(node) = NULL;
   2127 
   2128 			/*
   2129 			 * Since there is at least one node below this one and
   2130 			 * no recursion was requested, the deletion is
   2131 			 * complete.  The down node from this node might be all
   2132 			 * by itself on a single level, so join_nodes() could
   2133 			 * be used to collapse the tree (with all the caveats
   2134 			 * of the comment at the start of this function).
   2135 			 * But join_nodes() function has now been removed.
   2136 			 */
   2137 			return (ISC_R_SUCCESS);
   2138 		}
   2139 	}
   2140 
   2141 	/*
   2142 	 * Note the node that points to the level of the node
   2143 	 * that is being deleted.  If the deleted node is the
   2144 	 * top level, parent will be set to NULL.
   2145 	 */
   2146 	parent = get_upper_node(node);
   2147 
   2148 	/*
   2149 	 * This node now has no down pointer, so now it needs
   2150 	 * to be removed from this level.
   2151 	 */
   2152 	deletefromlevel(node, parent == NULL ? &rbt->root : &DOWN(parent));
   2153 
   2154 	if (DATA(node) != NULL && rbt->data_deleter != NULL)
   2155 		rbt->data_deleter(DATA(node), rbt->deleter_arg);
   2156 
   2157 	unhash_node(rbt, node);
   2158 #if DNS_RBT_USEMAGIC
   2159 	node->magic = 0;
   2160 #endif
   2161 	dns_rbtnode_refdestroy(node);
   2162 
   2163 	freenode(rbt, &node);
   2164 
   2165 	/*
   2166 	 * This function never fails.
   2167 	 */
   2168 	return (ISC_R_SUCCESS);
   2169 }
   2170 
   2171 void
   2172 dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
   2173 
   2174 	REQUIRE(DNS_RBTNODE_VALID(node));
   2175 	REQUIRE(name != NULL);
   2176 	REQUIRE(name->offsets == NULL);
   2177 
   2178 	NODENAME(node, name);
   2179 }
   2180 
   2181 isc_result_t
   2182 dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
   2183 	dns_name_t current;
   2184 	isc_result_t result;
   2185 
   2186 	REQUIRE(DNS_RBTNODE_VALID(node));
   2187 	REQUIRE(name != NULL);
   2188 	REQUIRE(name->buffer != NULL);
   2189 
   2190 	dns_name_init(&current, NULL);
   2191 	dns_name_reset(name);
   2192 
   2193 	do {
   2194 		INSIST(node != NULL);
   2195 
   2196 		NODENAME(node, &current);
   2197 
   2198 		result = dns_name_concatenate(name, &current, name, NULL);
   2199 		if (result != ISC_R_SUCCESS)
   2200 			break;
   2201 
   2202 		node = get_upper_node(node);
   2203 	} while (! dns_name_isabsolute(name));
   2204 
   2205 	return (result);
   2206 }
   2207 
   2208 char *
   2209 dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
   2210 {
   2211 	dns_fixedname_t fixedname;
   2212 	dns_name_t *name;
   2213 	isc_result_t result;
   2214 
   2215 	REQUIRE(DNS_RBTNODE_VALID(node));
   2216 	REQUIRE(printname != NULL);
   2217 
   2218 	name = dns_fixedname_initname(&fixedname);
   2219 	result = dns_rbt_fullnamefromnode(node, name);
   2220 	if (result == ISC_R_SUCCESS)
   2221 		dns_name_format(name, printname, size);
   2222 	else
   2223 		snprintf(printname, size, "<error building name: %s>",
   2224 			 dns_result_totext(result));
   2225 
   2226 	return (printname);
   2227 }
   2228 
   2229 static isc_result_t
   2230 create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) {
   2231 	dns_rbtnode_t *node;
   2232 	isc_region_t region;
   2233 	unsigned int labels;
   2234 	size_t nodelen;
   2235 
   2236 	REQUIRE(name->offsets != NULL);
   2237 
   2238 	dns_name_toregion(name, &region);
   2239 	labels = dns_name_countlabels(name);
   2240 	ENSURE(labels > 0);
   2241 
   2242 	/*
   2243 	 * Allocate space for the node structure, the name, and the offsets.
   2244 	 */
   2245 	nodelen = sizeof(dns_rbtnode_t) + region.length + labels + 1;
   2246 	node = (dns_rbtnode_t *)isc_mem_get(mctx, nodelen);
   2247 	if (node == NULL)
   2248 		return (ISC_R_NOMEMORY);
   2249 	memset(node, 0, nodelen);
   2250 
   2251 	node->is_root = 0;
   2252 	PARENT(node) = NULL;
   2253 	RIGHT(node) = NULL;
   2254 	LEFT(node) = NULL;
   2255 	DOWN(node) = NULL;
   2256 	DATA(node) = NULL;
   2257 	node->is_mmapped = 0;
   2258 	node->down_is_relative = 0;
   2259 	node->left_is_relative = 0;
   2260 	node->right_is_relative = 0;
   2261 	node->parent_is_relative = 0;
   2262 	node->data_is_relative = 0;
   2263 	node->rpz = 0;
   2264 
   2265 #ifdef DNS_RBT_USEHASH
   2266 	HASHNEXT(node) = NULL;
   2267 	HASHVAL(node) = 0;
   2268 #endif
   2269 
   2270 	ISC_LINK_INIT(node, deadlink);
   2271 
   2272 	LOCKNUM(node) = 0;
   2273 	WILD(node) = 0;
   2274 	DIRTY(node) = 0;
   2275 	dns_rbtnode_refinit(node, 0);
   2276 	node->find_callback = 0;
   2277 	node->nsec = DNS_RBT_NSEC_NORMAL;
   2278 
   2279 	MAKE_BLACK(node);
   2280 
   2281 	/*
   2282 	 * The following is stored to make reconstructing a name from the
   2283 	 * stored value in the node easy:  the length of the name, the number
   2284 	 * of labels, whether the name is absolute or not, the name itself,
   2285 	 * and the name's offsets table.
   2286 	 *
   2287 	 * XXX RTH
   2288 	 *      The offsets table could be made smaller by eliminating the
   2289 	 *      first offset, which is always 0.  This requires changes to
   2290 	 *      lib/dns/name.c.
   2291 	 *
   2292 	 * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
   2293 	 * 	 as it uses OLDNAMELEN.
   2294 	 */
   2295 	OLDNAMELEN(node) = NAMELEN(node) = region.length;
   2296 	OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
   2297 	ATTRS(node) = name->attributes;
   2298 
   2299 	memmove(NAME(node), region.base, region.length);
   2300 	memmove(OFFSETS(node), name->offsets, labels);
   2301 
   2302 #if DNS_RBT_USEMAGIC
   2303 	node->magic = DNS_RBTNODE_MAGIC;
   2304 #endif
   2305 	*nodep = node;
   2306 
   2307 	return (ISC_R_SUCCESS);
   2308 }
   2309 
   2310 #ifdef DNS_RBT_USEHASH
   2311 static inline void
   2312 hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
   2313 	unsigned int hash;
   2314 
   2315 	REQUIRE(name != NULL);
   2316 
   2317 	HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
   2318 
   2319 	hash = HASHVAL(node) % rbt->hashsize;
   2320 	HASHNEXT(node) = rbt->hashtable[hash];
   2321 
   2322 	rbt->hashtable[hash] = node;
   2323 }
   2324 
   2325 static isc_result_t
   2326 inithash(dns_rbt_t *rbt) {
   2327 	unsigned int bytes;
   2328 
   2329 	rbt->hashsize = RBT_HASH_SIZE;
   2330 	bytes = (unsigned int)rbt->hashsize * sizeof(dns_rbtnode_t *);
   2331 	rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
   2332 
   2333 	if (rbt->hashtable == NULL)
   2334 		return (ISC_R_NOMEMORY);
   2335 
   2336 	memset(rbt->hashtable, 0, bytes);
   2337 
   2338 	return (ISC_R_SUCCESS);
   2339 }
   2340 
   2341 static void
   2342 rehash(dns_rbt_t *rbt, unsigned int newcount) {
   2343 	unsigned int oldsize;
   2344 	dns_rbtnode_t **oldtable;
   2345 	dns_rbtnode_t *node;
   2346 	dns_rbtnode_t *nextnode;
   2347 	unsigned int hash;
   2348 	unsigned int i;
   2349 
   2350 	oldsize = (unsigned int)rbt->hashsize;
   2351 	oldtable = rbt->hashtable;
   2352 	do {
   2353 		INSIST((rbt->hashsize * 2 + 1) > rbt->hashsize);
   2354 		rbt->hashsize = rbt->hashsize * 2 + 1;
   2355 	} while (newcount >= (rbt->hashsize * 3));
   2356 	rbt->hashtable = isc_mem_get(rbt->mctx,
   2357 				     rbt->hashsize * sizeof(dns_rbtnode_t *));
   2358 	if (rbt->hashtable == NULL) {
   2359 		rbt->hashtable = oldtable;
   2360 		rbt->hashsize = oldsize;
   2361 		return;
   2362 	}
   2363 
   2364 	for (i = 0; i < rbt->hashsize; i++)
   2365 		rbt->hashtable[i] = NULL;
   2366 
   2367 	for (i = 0; i < oldsize; i++) {
   2368 		for (node = oldtable[i]; node != NULL; node = nextnode) {
   2369 			hash = HASHVAL(node) % rbt->hashsize;
   2370 			nextnode = HASHNEXT(node);
   2371 			HASHNEXT(node) = rbt->hashtable[hash];
   2372 			rbt->hashtable[hash] = node;
   2373 		}
   2374 	}
   2375 
   2376 	isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
   2377 }
   2378 
   2379 static inline void
   2380 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
   2381 	REQUIRE(DNS_RBTNODE_VALID(node));
   2382 
   2383 	if (rbt->nodecount >= (rbt->hashsize * 3))
   2384 		rehash(rbt, rbt->nodecount);
   2385 
   2386 	hash_add_node(rbt, node, name);
   2387 }
   2388 
   2389 static inline void
   2390 unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
   2391 	unsigned int bucket;
   2392 	dns_rbtnode_t *bucket_node;
   2393 
   2394 	REQUIRE(DNS_RBTNODE_VALID(node));
   2395 
   2396 	bucket = HASHVAL(node) % rbt->hashsize;
   2397 	bucket_node = rbt->hashtable[bucket];
   2398 
   2399 	if (bucket_node == node) {
   2400 		rbt->hashtable[bucket] = HASHNEXT(node);
   2401 	} else {
   2402 		while (HASHNEXT(bucket_node) != node) {
   2403 			INSIST(HASHNEXT(bucket_node) != NULL);
   2404 			bucket_node = HASHNEXT(bucket_node);
   2405 		}
   2406 		HASHNEXT(bucket_node) = HASHNEXT(node);
   2407 	}
   2408 }
   2409 #endif /* DNS_RBT_USEHASH */
   2410 
   2411 static inline void
   2412 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
   2413 	dns_rbtnode_t *child;
   2414 
   2415 	REQUIRE(DNS_RBTNODE_VALID(node));
   2416 	REQUIRE(rootp != NULL);
   2417 
   2418 	child = RIGHT(node);
   2419 	INSIST(child != NULL);
   2420 
   2421 	RIGHT(node) = LEFT(child);
   2422 	if (LEFT(child) != NULL)
   2423 		PARENT(LEFT(child)) = node;
   2424 	LEFT(child) = node;
   2425 
   2426 	PARENT(child) = PARENT(node);
   2427 
   2428 	if (IS_ROOT(node)) {
   2429 		*rootp = child;
   2430 		child->is_root = 1;
   2431 		node->is_root = 0;
   2432 
   2433 	} else {
   2434 		if (LEFT(PARENT(node)) == node)
   2435 			LEFT(PARENT(node)) = child;
   2436 		else
   2437 			RIGHT(PARENT(node)) = child;
   2438 	}
   2439 
   2440 	PARENT(node) = child;
   2441 }
   2442 
   2443 static inline void
   2444 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
   2445 	dns_rbtnode_t *child;
   2446 
   2447 	REQUIRE(DNS_RBTNODE_VALID(node));
   2448 	REQUIRE(rootp != NULL);
   2449 
   2450 	child = LEFT(node);
   2451 	INSIST(child != NULL);
   2452 
   2453 	LEFT(node) = RIGHT(child);
   2454 	if (RIGHT(child) != NULL)
   2455 		PARENT(RIGHT(child)) = node;
   2456 	RIGHT(child) = node;
   2457 
   2458 	PARENT(child) = PARENT(node);
   2459 
   2460 	if (IS_ROOT(node)) {
   2461 		*rootp = child;
   2462 		child->is_root = 1;
   2463 		node->is_root = 0;
   2464 
   2465 	} else {
   2466 		if (LEFT(PARENT(node)) == node)
   2467 			LEFT(PARENT(node)) = child;
   2468 		else
   2469 			RIGHT(PARENT(node)) = child;
   2470 	}
   2471 
   2472 	PARENT(node) = child;
   2473 }
   2474 
   2475 /*
   2476  * This is the real workhorse of the insertion code, because it does the
   2477  * true red/black tree on a single level.
   2478  */
   2479 static void
   2480 addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
   2481 	   dns_rbtnode_t **rootp)
   2482 {
   2483 	dns_rbtnode_t *child, *root, *parent, *grandparent;
   2484 	dns_name_t add_name, current_name;
   2485 	dns_offsets_t add_offsets, current_offsets;
   2486 
   2487 	REQUIRE(rootp != NULL);
   2488 	REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
   2489 		RIGHT(node) == NULL);
   2490 	REQUIRE(current != NULL);
   2491 
   2492 	root = *rootp;
   2493 	if (root == NULL) {
   2494 		/*
   2495 		 * First node of a level.
   2496 		 */
   2497 		MAKE_BLACK(node);
   2498 		node->is_root = 1;
   2499 		PARENT(node) = current;
   2500 		*rootp = node;
   2501 		return;
   2502 	}
   2503 
   2504 	child = root;
   2505 	POST(child);
   2506 
   2507 	dns_name_init(&add_name, add_offsets);
   2508 	NODENAME(node, &add_name);
   2509 
   2510 	dns_name_init(&current_name, current_offsets);
   2511 	NODENAME(current, &current_name);
   2512 
   2513 	if (order < 0) {
   2514 		INSIST(LEFT(current) == NULL);
   2515 		LEFT(current) = node;
   2516 	} else {
   2517 		INSIST(RIGHT(current) == NULL);
   2518 		RIGHT(current) = node;
   2519 	}
   2520 
   2521 	INSIST(PARENT(node) == NULL);
   2522 	PARENT(node) = current;
   2523 
   2524 	MAKE_RED(node);
   2525 
   2526 	while (node != root && IS_RED(PARENT(node))) {
   2527 		/*
   2528 		 * XXXDCL could do away with separate parent and grandparent
   2529 		 * variables.  They are vestiges of the days before parent
   2530 		 * pointers.  However, they make the code a little clearer.
   2531 		 */
   2532 
   2533 		parent = PARENT(node);
   2534 		grandparent = PARENT(parent);
   2535 
   2536 		if (parent == LEFT(grandparent)) {
   2537 			child = RIGHT(grandparent);
   2538 			if (child != NULL && IS_RED(child)) {
   2539 				MAKE_BLACK(parent);
   2540 				MAKE_BLACK(child);
   2541 				MAKE_RED(grandparent);
   2542 				node = grandparent;
   2543 			} else {
   2544 				if (node == RIGHT(parent)) {
   2545 					rotate_left(parent, &root);
   2546 					node = parent;
   2547 					parent = PARENT(node);
   2548 					grandparent = PARENT(parent);
   2549 				}
   2550 				MAKE_BLACK(parent);
   2551 				MAKE_RED(grandparent);
   2552 				rotate_right(grandparent, &root);
   2553 			}
   2554 		} else {
   2555 			child = LEFT(grandparent);
   2556 			if (child != NULL && IS_RED(child)) {
   2557 				MAKE_BLACK(parent);
   2558 				MAKE_BLACK(child);
   2559 				MAKE_RED(grandparent);
   2560 				node = grandparent;
   2561 			} else {
   2562 				if (node == LEFT(parent)) {
   2563 					rotate_right(parent, &root);
   2564 					node = parent;
   2565 					parent = PARENT(node);
   2566 					grandparent = PARENT(parent);
   2567 				}
   2568 				MAKE_BLACK(parent);
   2569 				MAKE_RED(grandparent);
   2570 				rotate_left(grandparent, &root);
   2571 			}
   2572 		}
   2573 	}
   2574 
   2575 	MAKE_BLACK(root);
   2576 	ENSURE(IS_ROOT(root));
   2577 	*rootp = root;
   2578 
   2579 	return;
   2580 }
   2581 
   2582 /*
   2583  * This is the real workhorse of the deletion code, because it does the
   2584  * true red/black tree on a single level.
   2585  */
   2586 static void
   2587 deletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp) {
   2588 	dns_rbtnode_t *child, *sibling, *parent;
   2589 	dns_rbtnode_t *successor;
   2590 
   2591 	REQUIRE(item != NULL);
   2592 
   2593 	/*
   2594 	 * Verify that the parent history is (apparently) correct.
   2595 	 */
   2596 	INSIST((IS_ROOT(item) && *rootp == item) ||
   2597 	       (! IS_ROOT(item) &&
   2598 		(LEFT(PARENT(item)) == item ||
   2599 		 RIGHT(PARENT(item)) == item)));
   2600 
   2601 	child = NULL;
   2602 
   2603 	if (LEFT(item) == NULL) {
   2604 		if (RIGHT(item) == NULL) {
   2605 			if (IS_ROOT(item)) {
   2606 				/*
   2607 				 * This is the only item in the tree.
   2608 				 */
   2609 				*rootp = NULL;
   2610 				return;
   2611 			}
   2612 		} else
   2613 			/*
   2614 			 * This node has one child, on the right.
   2615 			 */
   2616 			child = RIGHT(item);
   2617 
   2618 	} else if (RIGHT(item) == NULL)
   2619 		/*
   2620 		 * This node has one child, on the left.
   2621 		 */
   2622 		child = LEFT(item);
   2623 	else {
   2624 		dns_rbtnode_t holder, *tmp = &holder;
   2625 
   2626 		/*
   2627 		 * This node has two children, so it cannot be directly
   2628 		 * deleted.  Find its immediate in-order successor and
   2629 		 * move it to this location, then do the deletion at the
   2630 		 * old site of the successor.
   2631 		 */
   2632 		successor = RIGHT(item);
   2633 		while (LEFT(successor) != NULL)
   2634 			successor = LEFT(successor);
   2635 
   2636 		/*
   2637 		 * The successor cannot possibly have a left child;
   2638 		 * if there is any child, it is on the right.
   2639 		 */
   2640 		if (RIGHT(successor) != NULL)
   2641 			child = RIGHT(successor);
   2642 
   2643 		/*
   2644 		 * Swap the two nodes; it would be simpler to just replace
   2645 		 * the value being deleted with that of the successor,
   2646 		 * but this rigamarole is done so the caller has complete
   2647 		 * control over the pointers (and memory allocation) of
   2648 		 * all of nodes.  If just the key value were removed from
   2649 		 * the tree, the pointer to the node would be unchanged.
   2650 		 */
   2651 
   2652 		/*
   2653 		 * First, put the successor in the tree location of the
   2654 		 * node to be deleted.  Save its existing tree pointer
   2655 		 * information, which will be needed when linking up
   2656 		 * delete to the successor's old location.
   2657 		 */
   2658 		memmove(tmp, successor, sizeof(dns_rbtnode_t));
   2659 
   2660 		if (IS_ROOT(item)) {
   2661 			*rootp = successor;
   2662 			successor->is_root = ISC_TRUE;
   2663 			item->is_root = ISC_FALSE;
   2664 
   2665 		} else
   2666 			if (LEFT(PARENT(item)) == item)
   2667 				LEFT(PARENT(item)) = successor;
   2668 			else
   2669 				RIGHT(PARENT(item)) = successor;
   2670 
   2671 		PARENT(successor) = PARENT(item);
   2672 		LEFT(successor)   = LEFT(item);
   2673 		RIGHT(successor)  = RIGHT(item);
   2674 		COLOR(successor)  = COLOR(item);
   2675 
   2676 		if (LEFT(successor) != NULL)
   2677 			PARENT(LEFT(successor)) = successor;
   2678 		if (RIGHT(successor) != successor)
   2679 			PARENT(RIGHT(successor)) = successor;
   2680 
   2681 		/*
   2682 		 * Now relink the node to be deleted into the
   2683 		 * successor's previous tree location.  PARENT(tmp)
   2684 		 * is the successor's original parent.
   2685 		 */
   2686 		INSIST(! IS_ROOT(item));
   2687 
   2688 		if (PARENT(tmp) == item) {
   2689 			/*
   2690 			 * Node being deleted was successor's parent.
   2691 			 */
   2692 			RIGHT(successor) = item;
   2693 			PARENT(item) = successor;
   2694 
   2695 		} else {
   2696 			LEFT(PARENT(tmp)) = item;
   2697 			PARENT(item) = PARENT(tmp);
   2698 		}
   2699 
   2700 		/*
   2701 		 * Original location of successor node has no left.
   2702 		 */
   2703 		LEFT(item)   = NULL;
   2704 		RIGHT(item)  = RIGHT(tmp);
   2705 		COLOR(item)  = COLOR(tmp);
   2706 	}
   2707 
   2708 	/*
   2709 	 * Remove the node by removing the links from its parent.
   2710 	 */
   2711 	if (! IS_ROOT(item)) {
   2712 		if (LEFT(PARENT(item)) == item)
   2713 			LEFT(PARENT(item)) = child;
   2714 		else
   2715 			RIGHT(PARENT(item)) = child;
   2716 
   2717 		if (child != NULL)
   2718 			PARENT(child) = PARENT(item);
   2719 
   2720 	} else {
   2721 		/*
   2722 		 * This is the root being deleted, and at this point
   2723 		 * it is known to have just one child.
   2724 		 */
   2725 		*rootp = child;
   2726 		child->is_root = 1;
   2727 		PARENT(child) = PARENT(item);
   2728 	}
   2729 
   2730 	/*
   2731 	 * Fix color violations.
   2732 	 */
   2733 	if (IS_BLACK(item)) {
   2734 		parent = PARENT(item);
   2735 
   2736 		while (child != *rootp && IS_BLACK(child)) {
   2737 			INSIST(child == NULL || ! IS_ROOT(child));
   2738 
   2739 			if (LEFT(parent) == child) {
   2740 				sibling = RIGHT(parent);
   2741 
   2742 				if (IS_RED(sibling)) {
   2743 					MAKE_BLACK(sibling);
   2744 					MAKE_RED(parent);
   2745 					rotate_left(parent, rootp);
   2746 					sibling = RIGHT(parent);
   2747 				}
   2748 
   2749 				INSIST(sibling != NULL);
   2750 
   2751 				if (IS_BLACK(LEFT(sibling)) &&
   2752 				    IS_BLACK(RIGHT(sibling))) {
   2753 					MAKE_RED(sibling);
   2754 					child = parent;
   2755 
   2756 				} else {
   2757 
   2758 					if (IS_BLACK(RIGHT(sibling))) {
   2759 						MAKE_BLACK(LEFT(sibling));
   2760 						MAKE_RED(sibling);
   2761 						rotate_right(sibling, rootp);
   2762 						sibling = RIGHT(parent);
   2763 					}
   2764 
   2765 					COLOR(sibling) = COLOR(parent);
   2766 					MAKE_BLACK(parent);
   2767 					INSIST(RIGHT(sibling) != NULL);
   2768 					MAKE_BLACK(RIGHT(sibling));
   2769 					rotate_left(parent, rootp);
   2770 					child = *rootp;
   2771 				}
   2772 
   2773 			} else {
   2774 				/*
   2775 				 * Child is parent's right child.
   2776 				 * Everything is done the same as above,
   2777 				 * except mirrored.
   2778 				 */
   2779 				sibling = LEFT(parent);
   2780 
   2781 				if (IS_RED(sibling)) {
   2782 					MAKE_BLACK(sibling);
   2783 					MAKE_RED(parent);
   2784 					rotate_right(parent, rootp);
   2785 					sibling = LEFT(parent);
   2786 				}
   2787 
   2788 				INSIST(sibling != NULL);
   2789 
   2790 				if (IS_BLACK(LEFT(sibling)) &&
   2791 				    IS_BLACK(RIGHT(sibling))) {
   2792 					MAKE_RED(sibling);
   2793 					child = parent;
   2794 
   2795 				} else {
   2796 					if (IS_BLACK(LEFT(sibling))) {
   2797 						MAKE_BLACK(RIGHT(sibling));
   2798 						MAKE_RED(sibling);
   2799 						rotate_left(sibling, rootp);
   2800 						sibling = LEFT(parent);
   2801 					}
   2802 
   2803 					COLOR(sibling) = COLOR(parent);
   2804 					MAKE_BLACK(parent);
   2805 					INSIST(LEFT(sibling) != NULL);
   2806 					MAKE_BLACK(LEFT(sibling));
   2807 					rotate_right(parent, rootp);
   2808 					child = *rootp;
   2809 				}
   2810 			}
   2811 
   2812 			parent = PARENT(child);
   2813 		}
   2814 
   2815 		if (IS_RED(child))
   2816 			MAKE_BLACK(child);
   2817 	}
   2818 }
   2819 
   2820 static void
   2821 freenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep) {
   2822 	dns_rbtnode_t *node = *nodep;
   2823 
   2824 	if (node->is_mmapped == 0) {
   2825 		isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
   2826 	}
   2827 	*nodep = NULL;
   2828 
   2829 	rbt->nodecount--;
   2830 }
   2831 
   2832 static void
   2833 deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, isc_boolean_t unhash,
   2834 	       dns_rbtnode_t **nodep)
   2835 {
   2836 	dns_rbtnode_t *root = *nodep;
   2837 
   2838 	while (root != NULL) {
   2839 		/*
   2840 		 * If there is a left, right or down node, walk into it
   2841 		 * and iterate.
   2842 		 */
   2843 		if (LEFT(root) != NULL) {
   2844 			dns_rbtnode_t *node = root;
   2845 			root = LEFT(root);
   2846 			LEFT(node) = NULL;
   2847 		} else if (RIGHT(root) != NULL) {
   2848 			dns_rbtnode_t *node = root;
   2849 			root = RIGHT(root);
   2850 			RIGHT(node) = NULL;
   2851 		} else if (DOWN(root) != NULL) {
   2852 			dns_rbtnode_t *node = root;
   2853 			root = DOWN(root);
   2854 			DOWN(node) = NULL;
   2855 		} else {
   2856 			/*
   2857 			 * There are no left, right or down nodes, so we
   2858 			 * can free this one and go back to its parent.
   2859 			 */
   2860 			dns_rbtnode_t *node = root;
   2861 			root = PARENT(root);
   2862 
   2863 			if (DATA(node) != NULL && rbt->data_deleter != NULL)
   2864 				rbt->data_deleter(DATA(node),
   2865 						  rbt->deleter_arg);
   2866 			if (unhash)
   2867 				unhash_node(rbt, node);
   2868 			/*
   2869 			 * Note: we don't call unhash_node() here as we
   2870 			 * are destroying the complete RBT tree.
   2871 			 */
   2872 #if DNS_RBT_USEMAGIC
   2873 			node->magic = 0;
   2874 #endif
   2875 			freenode(rbt, &node);
   2876 			if (quantum != 0 && --quantum == 0)
   2877 				break;
   2878 		}
   2879 	}
   2880 
   2881 	*nodep = root;
   2882 }
   2883 
   2884 static size_t
   2885 getheight_helper(dns_rbtnode_t *node) {
   2886 	size_t dl, dr;
   2887 	size_t this_height, down_height;
   2888 
   2889 	if (node == NULL)
   2890 		return (0);
   2891 
   2892 	dl = getheight_helper(LEFT(node));
   2893 	dr = getheight_helper(RIGHT(node));
   2894 
   2895 	this_height = ISC_MAX(dl + 1, dr + 1);
   2896 	down_height = getheight_helper(DOWN(node));
   2897 
   2898 	return (ISC_MAX(this_height, down_height));
   2899 }
   2900 
   2901 size_t
   2902 dns__rbt_getheight(dns_rbt_t *rbt) {
   2903 	return (getheight_helper(rbt->root));
   2904 }
   2905 
   2906 static isc_boolean_t
   2907 check_properties_helper(dns_rbtnode_t *node) {
   2908 	if (node == NULL)
   2909 		return (ISC_TRUE);
   2910 
   2911 	if (IS_RED(node)) {
   2912 		/* Root nodes must be BLACK. */
   2913 		if (IS_ROOT(node))
   2914 			return (ISC_FALSE);
   2915 
   2916 		/* Both children of RED nodes must be BLACK. */
   2917 		if (IS_RED(LEFT(node)) || IS_RED(RIGHT(node)))
   2918 			return (ISC_FALSE);
   2919 	}
   2920 
   2921 	if ((DOWN(node) != NULL) && (!IS_ROOT(DOWN(node))))
   2922 		return (ISC_FALSE);
   2923 
   2924 	if (IS_ROOT(node)) {
   2925 		if ((PARENT(node) != NULL) &&
   2926 		    (DOWN(PARENT(node)) != node))
   2927 			return (ISC_FALSE);
   2928 
   2929 		if (get_upper_node(node) != PARENT(node))
   2930 			return (ISC_FALSE);
   2931 	}
   2932 
   2933 	/* If node is assigned to the down_ pointer of its parent, it is
   2934 	 * a subtree root and must have the flag set.
   2935 	 */
   2936 	if (((!PARENT(node)) ||
   2937 	     (DOWN(PARENT(node)) == node)) &&
   2938 	    (!IS_ROOT(node)))
   2939 	{
   2940 		return (ISC_FALSE);
   2941 	}
   2942 
   2943 	/* Repeat tests with this node's children. */
   2944 	return (check_properties_helper(LEFT(node)) &&
   2945 		check_properties_helper(RIGHT(node)) &&
   2946 		check_properties_helper(DOWN(node)));
   2947 }
   2948 
   2949 static isc_boolean_t
   2950 check_black_distance_helper(dns_rbtnode_t *node, size_t *distance) {
   2951 	size_t dl, dr, dd;
   2952 
   2953 	if (node == NULL) {
   2954 		*distance = 1;
   2955 		return (ISC_TRUE);
   2956 	}
   2957 
   2958 	if (!check_black_distance_helper(LEFT(node), &dl))
   2959 		return (ISC_FALSE);
   2960 
   2961 	if (!check_black_distance_helper(RIGHT(node), &dr))
   2962 		return (ISC_FALSE);
   2963 
   2964 	if (!check_black_distance_helper(DOWN(node), &dd))
   2965 		return (ISC_FALSE);
   2966 
   2967 	/* Left and right side black node counts must match. */
   2968 	if (dl != dr)
   2969 		return (ISC_FALSE);
   2970 
   2971 	if (IS_BLACK(node))
   2972 		dl++;
   2973 
   2974 	*distance = dl;
   2975 
   2976 	return (ISC_TRUE);
   2977 }
   2978 
   2979 isc_boolean_t
   2980 dns__rbt_checkproperties(dns_rbt_t *rbt) {
   2981 	size_t dd;
   2982 
   2983 	if (!check_properties_helper(rbt->root))
   2984 		return (ISC_FALSE);
   2985 
   2986 	/* Path from a given node to all its leaves must contain the
   2987 	 * same number of BLACK child nodes. This is done separately
   2988 	 * here instead of inside check_properties_helper() as
   2989 	 * it would take (n log n) complexity otherwise.
   2990 	 */
   2991 	return (check_black_distance_helper(rbt->root, &dd));
   2992 }
   2993 
   2994 static void
   2995 dns_rbt_indent(FILE *f, int depth) {
   2996 	int i;
   2997 
   2998 	fprintf(f, "%4d ", depth);
   2999 
   3000 	for (i = 0; i < depth; i++)
   3001 		fprintf(f, "- ");
   3002 }
   3003 
   3004 void
   3005 dns_rbt_printnodeinfo(dns_rbtnode_t *n, FILE *f) {
   3006 	fprintf(f, "Node info for nodename: ");
   3007 	printnodename(n, ISC_TRUE, f);
   3008 	fprintf(f, "\n");
   3009 
   3010 	fprintf(f, "n = %p\n", n);
   3011 
   3012 	fprintf(f, "Relative pointers: %s%s%s%s%s\n",
   3013 			(n->parent_is_relative == 1 ? " P" : ""),
   3014 			(n->right_is_relative == 1 ? " R" : ""),
   3015 			(n->left_is_relative == 1 ? " L" : ""),
   3016 			(n->down_is_relative == 1 ? " D" : ""),
   3017 			(n->data_is_relative == 1 ? " T" : ""));
   3018 
   3019 	fprintf(f, "node lock address = %u\n", n->locknum);
   3020 
   3021 	fprintf(f, "Parent: %p\n", n->parent);
   3022 	fprintf(f, "Right: %p\n", n->right);
   3023 	fprintf(f, "Left: %p\n", n->left);
   3024 	fprintf(f, "Down: %p\n", n->down);
   3025 	fprintf(f, "daTa: %p\n", n->data);
   3026 }
   3027 
   3028 static void
   3029 printnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f) {
   3030 	isc_region_t r;
   3031 	dns_name_t name;
   3032 	char buffer[DNS_NAME_FORMATSIZE];
   3033 	dns_offsets_t offsets;
   3034 
   3035 	r.length = NAMELEN(node);
   3036 	r.base = NAME(node);
   3037 
   3038 	dns_name_init(&name, offsets);
   3039 	dns_name_fromregion(&name, &r);
   3040 
   3041 	dns_name_format(&name, buffer, sizeof(buffer));
   3042 
   3043 	if (quoted)
   3044 		fprintf(f, "\"%s\"", buffer);
   3045 	else
   3046 		fprintf(f, "%s", buffer);
   3047 }
   3048 
   3049 static void
   3050 print_text_helper(dns_rbtnode_t *root, dns_rbtnode_t *parent,
   3051 		  int depth, const char *direction,
   3052 		  void (*data_printer)(FILE *, void *), FILE *f)
   3053 {
   3054 	dns_rbt_indent(f, depth);
   3055 
   3056 	if (root != NULL) {
   3057 		printnodename(root, ISC_TRUE, f);
   3058 		fprintf(f, " (%s, %s", direction,
   3059 			IS_RED(root) ? "RED" : "BLACK");
   3060 
   3061 		if ((! IS_ROOT(root) && PARENT(root) != parent) ||
   3062 		    (  IS_ROOT(root) && depth > 0 &&
   3063 		       DOWN(PARENT(root)) != root)) {
   3064 
   3065 			fprintf(f, " (BAD parent pointer! -> ");
   3066 			if (PARENT(root) != NULL)
   3067 				printnodename(PARENT(root), ISC_TRUE, f);
   3068 			else
   3069 				fprintf(f, "NULL");
   3070 			fprintf(f, ")");
   3071 		}
   3072 
   3073 		fprintf(f, ")");
   3074 
   3075 		if (root->data != NULL && data_printer != NULL) {
   3076 			fprintf(f, " data@%p: ", root->data);
   3077 			data_printer(f, root->data);
   3078 		}
   3079 		fprintf(f, "\n");
   3080 
   3081 		depth++;
   3082 
   3083 		if (IS_RED(root) && IS_RED(LEFT(root)))
   3084 			fprintf(f, "** Red/Red color violation on left\n");
   3085 		print_text_helper(LEFT(root), root, depth, "left",
   3086 					  data_printer, f);
   3087 
   3088 		if (IS_RED(root) && IS_RED(RIGHT(root)))
   3089 			fprintf(f, "** Red/Red color violation on right\n");
   3090 		print_text_helper(RIGHT(root), root, depth, "right",
   3091 					  data_printer, f);
   3092 
   3093 		print_text_helper(DOWN(root), NULL, depth, "down",
   3094 					  data_printer, f);
   3095 	} else {
   3096 		fprintf(f, "NULL (%s)\n", direction);
   3097 	}
   3098 }
   3099 
   3100 void
   3101 dns_rbt_printtext(dns_rbt_t *rbt,
   3102 		  void (*data_printer)(FILE *, void *), FILE *f)
   3103 {
   3104 	REQUIRE(VALID_RBT(rbt));
   3105 
   3106 	print_text_helper(rbt->root, NULL, 0, "root", data_printer, f);
   3107 }
   3108 
   3109 static int
   3110 print_dot_helper(dns_rbtnode_t *node, unsigned int *nodecount,
   3111 		 isc_boolean_t show_pointers, FILE *f)
   3112 {
   3113 	unsigned int l, r, d;
   3114 
   3115 	if (node == NULL)
   3116 		return (0);
   3117 
   3118 	l = print_dot_helper(LEFT(node), nodecount, show_pointers, f);
   3119 	r = print_dot_helper(RIGHT(node), nodecount, show_pointers, f);
   3120 	d = print_dot_helper(DOWN(node), nodecount, show_pointers, f);
   3121 
   3122 	*nodecount += 1;
   3123 
   3124 	fprintf(f, "node%u[label = \"<f0> |<f1> ", *nodecount);
   3125 	printnodename(node, ISC_FALSE, f);
   3126 	fprintf(f, "|<f2>");
   3127 
   3128 	if (show_pointers)
   3129 		fprintf(f, "|<f3> n=%p|<f4> p=%p", node, PARENT(node));
   3130 
   3131 	fprintf(f, "\"] [");
   3132 
   3133 	if (IS_RED(node))
   3134 		fprintf(f, "color=red");
   3135 	else
   3136 		fprintf(f, "color=black");
   3137 
   3138 	/* XXXMUKS: verify that IS_ROOT() indicates subtree root and not
   3139 	 * forest root.
   3140 	 */
   3141 	if (IS_ROOT(node))
   3142 		fprintf(f, ",penwidth=3");
   3143 
   3144 	if (IS_EMPTY(node))
   3145 		fprintf(f, ",style=filled,fillcolor=lightgrey");
   3146 
   3147 	fprintf(f, "];\n");
   3148 
   3149 	if (LEFT(node) != NULL)
   3150 		fprintf(f, "\"node%u\":f0 -> \"node%u\":f1;\n", *nodecount, l);
   3151 
   3152 	if (DOWN(node) != NULL)
   3153 		fprintf(f, "\"node%u\":f1 -> \"node%u\":f1 [penwidth=5];\n",
   3154 			*nodecount, d);
   3155 
   3156 	if (RIGHT(node) != NULL)
   3157 		fprintf(f, "\"node%u\":f2 -> \"node%u\":f1;\n", *nodecount, r);
   3158 
   3159 	return (*nodecount);
   3160 }
   3161 
   3162 void
   3163 dns_rbt_printdot(dns_rbt_t *rbt, isc_boolean_t show_pointers, FILE *f) {
   3164 	unsigned int nodecount = 0;
   3165 
   3166 	REQUIRE(VALID_RBT(rbt));
   3167 
   3168 	fprintf(f, "digraph g {\n");
   3169 	fprintf(f, "node [shape = record,height=.1];\n");
   3170 	print_dot_helper(rbt->root, &nodecount, show_pointers, f);
   3171 	fprintf(f, "}\n");
   3172 }
   3173 
   3174 /*
   3175  * Chain Functions
   3176  */
   3177 
   3178 void
   3179 dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
   3180 
   3181 	REQUIRE(chain != NULL);
   3182 
   3183 	/*
   3184 	 * Initialize 'chain'.
   3185 	 */
   3186 	chain->mctx = mctx;
   3187 	chain->end = NULL;
   3188 	chain->level_count = 0;
   3189 	chain->level_matches = 0;
   3190 	memset(chain->levels, 0, sizeof(chain->levels));
   3191 
   3192 	chain->magic = CHAIN_MAGIC;
   3193 }
   3194 
   3195 isc_result_t
   3196 dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
   3197 			 dns_name_t *origin, dns_rbtnode_t **node)
   3198 {
   3199 	isc_result_t result = ISC_R_SUCCESS;
   3200 
   3201 	REQUIRE(VALID_CHAIN(chain));
   3202 
   3203 	if (node != NULL)
   3204 		*node = chain->end;
   3205 
   3206 	if (chain->end == NULL)
   3207 		return (ISC_R_NOTFOUND);
   3208 
   3209 	if (name != NULL) {
   3210 		NODENAME(chain->end, name);
   3211 
   3212 		if (chain->level_count == 0) {
   3213 			/*
   3214 			 * Names in the top level tree are all absolute.
   3215 			 * Always make 'name' relative.
   3216 			 */
   3217 			INSIST(dns_name_isabsolute(name));
   3218 
   3219 			/*
   3220 			 * This is cheaper than dns_name_getlabelsequence().
   3221 			 */
   3222 			name->labels--;
   3223 			name->length--;
   3224 			name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
   3225 		}
   3226 	}
   3227 
   3228 	if (origin != NULL) {
   3229 		if (chain->level_count > 0)
   3230 			result = chain_name(chain, origin, ISC_FALSE);
   3231 		else
   3232 			result = dns_name_copy(dns_rootname, origin, NULL);
   3233 	}
   3234 
   3235 	return (result);
   3236 }
   3237 
   3238 isc_result_t
   3239 dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
   3240 		      dns_name_t *origin)
   3241 {
   3242 	dns_rbtnode_t *current, *previous, *predecessor;
   3243 	isc_result_t result = ISC_R_SUCCESS;
   3244 	isc_boolean_t new_origin = ISC_FALSE;
   3245 
   3246 	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
   3247 
   3248 	predecessor = NULL;
   3249 
   3250 	current = chain->end;
   3251 
   3252 	if (LEFT(current) != NULL) {
   3253 		/*
   3254 		 * Moving left one then right as far as possible is the
   3255 		 * previous node, at least for this level.
   3256 		 */
   3257 		current = LEFT(current);
   3258 
   3259 		while (RIGHT(current) != NULL)
   3260 			current = RIGHT(current);
   3261 
   3262 		predecessor = current;
   3263 
   3264 	} else {
   3265 		/*
   3266 		 * No left links, so move toward the root.  If at any point on
   3267 		 * the way there the link from parent to child is a right
   3268 		 * link, then the parent is the previous node, at least
   3269 		 * for this level.
   3270 		 */
   3271 		while (! IS_ROOT(current)) {
   3272 			previous = current;
   3273 			current = PARENT(current);
   3274 
   3275 			if (RIGHT(current) == previous) {
   3276 				predecessor = current;
   3277 				break;
   3278 			}
   3279 		}
   3280 	}
   3281 
   3282 	if (predecessor != NULL) {
   3283 		/*
   3284 		 * Found a predecessor node in this level.  It might not
   3285 		 * really be the predecessor, however.
   3286 		 */
   3287 		if (DOWN(predecessor) != NULL) {
   3288 			/*
   3289 			 * The predecessor is really down at least one level.
   3290 			 * Go down and as far right as possible, and repeat
   3291 			 * as long as the rightmost node has a down pointer.
   3292 			 */
   3293 			do {
   3294 				/*
   3295 				 * XXX DCL Need to do something about origins
   3296 				 * here. See whether to go down, and if so
   3297 				 * whether it is truly what Bob calls a
   3298 				 * new origin.
   3299 				 */
   3300 				ADD_LEVEL(chain, predecessor);
   3301 				predecessor = DOWN(predecessor);
   3302 
   3303 				/* XXX DCL duplicated from above; clever
   3304 				 * way to unduplicate? */
   3305 
   3306 				while (RIGHT(predecessor) != NULL)
   3307 					predecessor = RIGHT(predecessor);
   3308 			} while (DOWN(predecessor) != NULL);
   3309 
   3310 			/* XXX DCL probably needs work on the concept */
   3311 			if (origin != NULL)
   3312 				new_origin = ISC_TRUE;
   3313 		}
   3314 
   3315 	} else if (chain->level_count > 0) {
   3316 		/*
   3317 		 * Dang, didn't find a predecessor in this level.
   3318 		 * Got to the root of this level without having traversed
   3319 		 * any right links.  Ascend the tree one level; the
   3320 		 * node that points to this tree is the predecessor.
   3321 		 */
   3322 		INSIST(chain->level_count > 0 && IS_ROOT(current));
   3323 		predecessor = chain->levels[--chain->level_count];
   3324 
   3325 		/* XXX DCL probably needs work on the concept */
   3326 		/*
   3327 		 * Don't declare an origin change when the new origin is "."
   3328 		 * at the top level tree, because "." is declared as the origin
   3329 		 * for the second level tree.
   3330 		 */
   3331 		if (origin != NULL &&
   3332 		    (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
   3333 			new_origin = ISC_TRUE;
   3334 	}
   3335 
   3336 	if (predecessor != NULL) {
   3337 		chain->end = predecessor;
   3338 
   3339 		if (new_origin) {
   3340 			result = dns_rbtnodechain_current(chain, name, origin,
   3341 							  NULL);
   3342 			if (result == ISC_R_SUCCESS)
   3343 				result = DNS_R_NEWORIGIN;
   3344 
   3345 		} else
   3346 			result = dns_rbtnodechain_current(chain, name, NULL,
   3347 							  NULL);
   3348 
   3349 	} else
   3350 		result = ISC_R_NOMORE;
   3351 
   3352 	return (result);
   3353 }
   3354 
   3355 isc_result_t
   3356 dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
   3357 		      dns_name_t *origin)
   3358 {
   3359 	dns_rbtnode_t *current, *successor;
   3360 	isc_result_t result = ISC_R_SUCCESS;
   3361 	isc_boolean_t new_origin = ISC_FALSE;
   3362 
   3363 	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
   3364 
   3365 	successor = NULL;
   3366 
   3367 	current = chain->end;
   3368 
   3369 	if (DOWN(current) != NULL) {
   3370 		/*
   3371 		 * Don't declare an origin change when the new origin is "."
   3372 		 * at the second level tree, because "." is already declared
   3373 		 * as the origin for the top level tree.
   3374 		 */
   3375 		if (chain->level_count > 0 ||
   3376 		    OFFSETLEN(current) > 1)
   3377 			new_origin = ISC_TRUE;
   3378 
   3379 		ADD_LEVEL(chain, current);
   3380 		current = DOWN(current);
   3381 
   3382 		while (LEFT(current) != NULL)
   3383 			current = LEFT(current);
   3384 
   3385 		successor = current;
   3386 	}
   3387 
   3388 	if (successor != NULL) {
   3389 		chain->end = successor;
   3390 
   3391 		/*
   3392 		 * It is not necessary to use dns_rbtnodechain_current like
   3393 		 * the other functions because this function will never
   3394 		 * find a node in the topmost level.  This is because the
   3395 		 * root level will never be more than one name, and everything
   3396 		 * in the megatree is a successor to that node, down at
   3397 		 * the second level or below.
   3398 		 */
   3399 
   3400 		if (name != NULL)
   3401 			NODENAME(chain->end, name);
   3402 
   3403 		if (new_origin) {
   3404 			if (origin != NULL)
   3405 				result = chain_name(chain, origin, ISC_FALSE);
   3406 
   3407 			if (result == ISC_R_SUCCESS)
   3408 				result = DNS_R_NEWORIGIN;
   3409 
   3410 		} else
   3411 			result = ISC_R_SUCCESS;
   3412 
   3413 	} else
   3414 		result = ISC_R_NOMORE;
   3415 
   3416 	return (result);
   3417 }
   3418 
   3419 isc_result_t
   3420 dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
   3421 	dns_rbtnode_t *current, *previous, *successor;
   3422 	isc_result_t result = ISC_R_SUCCESS;
   3423 
   3424 	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
   3425 
   3426 	successor = NULL;
   3427 
   3428 	current = chain->end;
   3429 
   3430 	if (RIGHT(current) == NULL) {
   3431 		while (! IS_ROOT(current)) {
   3432 			previous = current;
   3433 			current = PARENT(current);
   3434 
   3435 			if (LEFT(current) == previous) {
   3436 				successor = current;
   3437 				break;
   3438 			}
   3439 		}
   3440 	} else {
   3441 		current = RIGHT(current);
   3442 
   3443 		while (LEFT(current) != NULL)
   3444 			current = LEFT(current);
   3445 
   3446 		successor = current;
   3447 	}
   3448 
   3449 	if (successor != NULL) {
   3450 		chain->end = successor;
   3451 
   3452 		if (name != NULL)
   3453 			NODENAME(chain->end, name);
   3454 
   3455 		result = ISC_R_SUCCESS;
   3456 	} else
   3457 		result = ISC_R_NOMORE;
   3458 
   3459 	return (result);
   3460 }
   3461 
   3462 isc_result_t
   3463 dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
   3464 		      dns_name_t *origin)
   3465 {
   3466 	dns_rbtnode_t *current, *previous, *successor;
   3467 	isc_result_t result = ISC_R_SUCCESS;
   3468 	isc_boolean_t new_origin = ISC_FALSE;
   3469 
   3470 	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
   3471 
   3472 	successor = NULL;
   3473 
   3474 	current = chain->end;
   3475 
   3476 	/*
   3477 	 * If there is a level below this node, the next node is the leftmost
   3478 	 * node of the next level.
   3479 	 */
   3480 	if (DOWN(current) != NULL) {
   3481 		/*
   3482 		 * Don't declare an origin change when the new origin is "."
   3483 		 * at the second level tree, because "." is already declared
   3484 		 * as the origin for the top level tree.
   3485 		 */
   3486 		if (chain->level_count > 0 ||
   3487 		    OFFSETLEN(current) > 1)
   3488 			new_origin = ISC_TRUE;
   3489 
   3490 		ADD_LEVEL(chain, current);
   3491 		current = DOWN(current);
   3492 
   3493 		while (LEFT(current) != NULL)
   3494 			current = LEFT(current);
   3495 
   3496 		successor = current;
   3497 
   3498 	} else if (RIGHT(current) == NULL) {
   3499 		/*
   3500 		 * The successor is up, either in this level or a previous one.
   3501 		 * Head back toward the root of the tree, looking for any path
   3502 		 * that was via a left link; the successor is the node that has
   3503 		 * that left link.  In the event the root of the level is
   3504 		 * reached without having traversed any left links, ascend one
   3505 		 * level and look for either a right link off the point of
   3506 		 * ascent, or search for a left link upward again, repeating
   3507 		 * ascends until either case is true.
   3508 		 */
   3509 		do {
   3510 			while (! IS_ROOT(current)) {
   3511 				previous = current;
   3512 				current = PARENT(current);
   3513 
   3514 				if (LEFT(current) == previous) {
   3515 					successor = current;
   3516 					break;
   3517 				}
   3518 			}
   3519 
   3520 			if (successor == NULL) {
   3521 				/*
   3522 				 * Reached the root without having traversed
   3523 				 * any left pointers, so this level is done.
   3524 				 */
   3525 				if (chain->level_count == 0) {
   3526 					/*
   3527 					 * If the tree we are iterating over
   3528 					 * was modified since this chain was
   3529 					 * initialized in a way that caused
   3530 					 * node splits to occur, "current" may
   3531 					 * now be pointing to a root node which
   3532 					 * appears to be at level 0, but still
   3533 					 * has a parent.  If that happens,
   3534 					 * abort.  Otherwise, we are done
   3535 					 * looking for a successor as we really
   3536 					 * reached the root node on level 0.
   3537 					 */
   3538 					INSIST(PARENT(current) == NULL);
   3539 					break;
   3540 				}
   3541 
   3542 				current = chain->levels[--chain->level_count];
   3543 				new_origin = ISC_TRUE;
   3544 
   3545 				if (RIGHT(current) != NULL)
   3546 					break;
   3547 			}
   3548 		} while (successor == NULL);
   3549 	}
   3550 
   3551 	if (successor == NULL && RIGHT(current) != NULL) {
   3552 		current = RIGHT(current);
   3553 
   3554 		while (LEFT(current) != NULL)
   3555 			current = LEFT(current);
   3556 
   3557 		successor = current;
   3558 	}
   3559 
   3560 	if (successor != NULL) {
   3561 		/*
   3562 		 * If we determine that the current node is the successor to
   3563 		 * itself, we will run into an infinite loop, so abort instead.
   3564 		 */
   3565 		INSIST(chain->end != successor);
   3566 
   3567 		chain->end = successor;
   3568 
   3569 		/*
   3570 		 * It is not necessary to use dns_rbtnodechain_current like
   3571 		 * the other functions because this function will never
   3572 		 * find a node in the topmost level.  This is because the
   3573 		 * root level will never be more than one name, and everything
   3574 		 * in the megatree is a successor to that node, down at
   3575 		 * the second level or below.
   3576 		 */
   3577 
   3578 		if (name != NULL)
   3579 			NODENAME(chain->end, name);
   3580 
   3581 		if (new_origin) {
   3582 			if (origin != NULL)
   3583 				result = chain_name(chain, origin, ISC_FALSE);
   3584 
   3585 			if (result == ISC_R_SUCCESS)
   3586 				result = DNS_R_NEWORIGIN;
   3587 
   3588 		} else
   3589 			result = ISC_R_SUCCESS;
   3590 
   3591 	} else
   3592 		result = ISC_R_NOMORE;
   3593 
   3594 	return (result);
   3595 }
   3596 
   3597 isc_result_t
   3598 dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
   3599 		       dns_name_t *name, dns_name_t *origin)
   3600 
   3601 {
   3602 	isc_result_t result;
   3603 
   3604 	REQUIRE(VALID_RBT(rbt));
   3605 	REQUIRE(VALID_CHAIN(chain));
   3606 
   3607 	dns_rbtnodechain_reset(chain);
   3608 
   3609 	chain->end = rbt->root;
   3610 
   3611 	result = dns_rbtnodechain_current(chain, name, origin, NULL);
   3612 
   3613 	if (result == ISC_R_SUCCESS)
   3614 		result = DNS_R_NEWORIGIN;
   3615 
   3616 	return (result);
   3617 }
   3618 
   3619 isc_result_t
   3620 dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
   3621 		       dns_name_t *name, dns_name_t *origin)
   3622 
   3623 {
   3624 	isc_result_t result;
   3625 
   3626 	REQUIRE(VALID_RBT(rbt));
   3627 	REQUIRE(VALID_CHAIN(chain));
   3628 
   3629 	dns_rbtnodechain_reset(chain);
   3630 
   3631 	result = move_chain_to_last(chain, rbt->root);
   3632 	if (result != ISC_R_SUCCESS)
   3633 		return (result);
   3634 
   3635 	result = dns_rbtnodechain_current(chain, name, origin, NULL);
   3636 
   3637 	if (result == ISC_R_SUCCESS)
   3638 		result = DNS_R_NEWORIGIN;
   3639 
   3640 	return (result);
   3641 }
   3642 
   3643 
   3644 void
   3645 dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
   3646 
   3647 	REQUIRE(VALID_CHAIN(chain));
   3648 
   3649 	/*
   3650 	 * Free any dynamic storage associated with 'chain', and then
   3651 	 * reinitialize 'chain'.
   3652 	 */
   3653 	chain->end = NULL;
   3654 	chain->level_count = 0;
   3655 	chain->level_matches = 0;
   3656 }
   3657 
   3658 void
   3659 dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
   3660 	/*
   3661 	 * Free any dynamic storage associated with 'chain', and then
   3662 	 * invalidate 'chain'.
   3663 	 */
   3664 
   3665 	dns_rbtnodechain_reset(chain);
   3666 
   3667 	chain->magic = 0;
   3668 }
   3669 
   3670 /* XXXMUKS:
   3671  *
   3672  * - worth removing inline as static functions are inlined automatically
   3673  *   where suitable by modern compilers.
   3674  * - bump the size of dns_rbt.nodecount to size_t.
   3675  * - the dumpfile header also contains a nodecount that is unsigned
   3676  *   int. If large files (> 2^32 nodes) are to be supported, the
   3677  *   allocation for this field should be increased.
   3678  */
   3679