PageRenderTime 193ms CodeModel.GetById 116ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/lib/dns/rbt.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2674 lines | 1520 code | 455 blank | 699 comment | 530 complexity | 81ad892c3e11df5bfea01cab4e611246 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
   3 * Copyright (C) 1999-2003  Internet Software Consortium.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15 * PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18/* $Id$ */
  19
  20/*! \file */
  21
  22/* Principal Authors: DCL */
  23
  24#include <config.h>
  25
  26#include <isc/mem.h>
  27#include <isc/platform.h>
  28#include <isc/print.h>
  29#include <isc/refcount.h>
  30#include <isc/string.h>
  31#include <isc/util.h>
  32
  33/*%
  34 * This define is so dns/name.h (included by dns/fixedname.h) uses more
  35 * efficient macro calls instead of functions for a few operations.
  36 */
  37#define DNS_NAME_USEINLINE 1
  38
  39#include <dns/fixedname.h>
  40#include <dns/log.h>
  41#include <dns/rbt.h>
  42#include <dns/result.h>
  43
  44#define RBT_MAGIC               ISC_MAGIC('R', 'B', 'T', '+')
  45#define VALID_RBT(rbt)          ISC_MAGIC_VALID(rbt, RBT_MAGIC)
  46
  47/*
  48 * XXXDCL Since parent pointers were added in again, I could remove all of the
  49 * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
  50 * _lastnode.  This would involve pretty major change to the API.
  51 */
  52#define CHAIN_MAGIC             ISC_MAGIC('0', '-', '0', '-')
  53#define VALID_CHAIN(chain)      ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
  54
  55#define RBT_HASH_SIZE           64
  56
  57#ifdef RBT_MEM_TEST
  58#undef RBT_HASH_SIZE
  59#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
  60#endif
  61
  62struct dns_rbt {
  63	unsigned int            magic;
  64	isc_mem_t *             mctx;
  65	dns_rbtnode_t *         root;
  66	void                    (*data_deleter)(void *, void *);
  67	void *                  deleter_arg;
  68	unsigned int            nodecount;
  69	unsigned int            hashsize;
  70	dns_rbtnode_t **        hashtable;
  71};
  72
  73#define RED 0
  74#define BLACK 1
  75
  76/*%
  77 * Elements of the rbtnode structure.
  78 */
  79#define PARENT(node)            ((node)->parent)
  80#define LEFT(node)              ((node)->left)
  81#define RIGHT(node)             ((node)->right)
  82#define DOWN(node)              ((node)->down)
  83#define DATA(node)              ((node)->data)
  84#define HASHNEXT(node)          ((node)->hashnext)
  85#define HASHVAL(node)           ((node)->hashval)
  86#define COLOR(node)             ((node)->color)
  87#define NAMELEN(node)           ((node)->namelen)
  88#define OLDNAMELEN(node)        ((node)->oldnamelen)
  89#define OFFSETLEN(node)         ((node)->offsetlen)
  90#define ATTRS(node)             ((node)->attributes)
  91#define IS_ROOT(node)           ISC_TF((node)->is_root == 1)
  92#define FINDCALLBACK(node)      ISC_TF((node)->find_callback == 1)
  93
  94/*%
  95 * Structure elements from the rbtdb.c, not
  96 * used as part of the rbt.c algorithms.
  97 */
  98#define DIRTY(node)     ((node)->dirty)
  99#define WILD(node)      ((node)->wild)
 100#define LOCKNUM(node)   ((node)->locknum)
 101
 102/*%
 103 * The variable length stuff stored after the node has the following
 104 * structure.
 105 *
 106 *	<name_data>{1..255}<oldoffsetlen>{1}<offsets>{1..128}
 107 *
 108 * <name_data> contains the name of the node when it was created.
 109 * <oldoffsetlen> contains the length of <offsets> when the node was created.
 110 * <offsets> contains the offets into name for each label when the node was
 111 * created.
 112 */
 113
 114#define NAME(node)      ((unsigned char *)((node) + 1))
 115#define OFFSETS(node)   (NAME(node) + OLDNAMELEN(node) + 1)
 116#define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
 117
 118#define NODE_SIZE(node) (sizeof(*node) + \
 119			 OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
 120
 121/*%
 122 * Color management.
 123 */
 124#define IS_RED(node)            ((node) != NULL && (node)->color == RED)
 125#define IS_BLACK(node)          ((node) == NULL || (node)->color == BLACK)
 126#define MAKE_RED(node)          ((node)->color = RED)
 127#define MAKE_BLACK(node)        ((node)->color = BLACK)
 128
 129/*%
 130 * Chain management.
 131 *
 132 * The "ancestors" member of chains were removed, with their job now
 133 * being wholly handled by parent pointers (which didn't exist, because
 134 * of memory concerns, when chains were first implemented).
 135 */
 136#define ADD_LEVEL(chain, node) \
 137			(chain)->levels[(chain)->level_count++] = (node)
 138
 139/*%
 140 * The following macros directly access normally private name variables.
 141 * These macros are used to avoid a lot of function calls in the critical
 142 * path of the tree traversal code.
 143 */
 144
 145#define NODENAME(node, name) \
 146do { \
 147	(name)->length = NAMELEN(node); \
 148	(name)->labels = OFFSETLEN(node); \
 149	(name)->ndata = NAME(node); \
 150	(name)->offsets = OFFSETS(node); \
 151	(name)->attributes = ATTRS(node); \
 152	(name)->attributes |= DNS_NAMEATTR_READONLY; \
 153} while (0)
 154
 155#ifdef DNS_RBT_USEHASH
 156static isc_result_t
 157inithash(dns_rbt_t *rbt);
 158#endif
 159
 160#ifdef DEBUG
 161#define inline
 162/*
 163 * A little something to help out in GDB.
 164 */
 165dns_name_t Name(dns_rbtnode_t *node);
 166dns_name_t
 167Name(dns_rbtnode_t *node) {
 168	dns_name_t name;
 169
 170	dns_name_init(&name, NULL);
 171	if (node != NULL)
 172		NODENAME(node, &name);
 173
 174	return (name);
 175}
 176
 177static void dns_rbt_printnodename(dns_rbtnode_t *node);
 178#endif
 179
 180static inline dns_rbtnode_t *
 181find_up(dns_rbtnode_t *node) {
 182	dns_rbtnode_t *root;
 183
 184	/*
 185	 * Return the node in the level above the argument node that points
 186	 * to the level the argument node is in.  If the argument node is in
 187	 * the top level, the return value is NULL.
 188	 */
 189	for (root = node; ! IS_ROOT(root); root = PARENT(root))
 190		; /* Nothing. */
 191
 192	return (PARENT(root));
 193}
 194
 195/*
 196 * Forward declarations.
 197 */
 198static isc_result_t
 199create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
 200
 201#ifdef DNS_RBT_USEHASH
 202static inline void
 203hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
 204static inline void
 205unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
 206#else
 207#define hash_node(rbt, node, name) (ISC_R_SUCCESS)
 208#define unhash_node(rbt, node)
 209#endif
 210
 211static inline void
 212rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
 213static inline void
 214rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
 215
 216static void
 217dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
 218		   dns_rbtnode_t **rootp);
 219
 220static void
 221dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
 222
 223static isc_result_t
 224dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
 225
 226static void
 227dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
 228		       dns_rbtnode_t **nodep);
 229
 230/*
 231 * Initialize a red/black tree of trees.
 232 */
 233isc_result_t
 234dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
 235	       void *deleter_arg, dns_rbt_t **rbtp)
 236{
 237#ifdef DNS_RBT_USEHASH
 238	isc_result_t result;
 239#endif
 240	dns_rbt_t *rbt;
 241
 242
 243	REQUIRE(mctx != NULL);
 244	REQUIRE(rbtp != NULL && *rbtp == NULL);
 245	REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
 246
 247	rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
 248	if (rbt == NULL)
 249		return (ISC_R_NOMEMORY);
 250
 251	rbt->mctx = mctx;
 252	rbt->data_deleter = deleter;
 253	rbt->deleter_arg = deleter_arg;
 254	rbt->root = NULL;
 255	rbt->nodecount = 0;
 256	rbt->hashtable = NULL;
 257	rbt->hashsize = 0;
 258
 259#ifdef DNS_RBT_USEHASH
 260	result = inithash(rbt);
 261	if (result != ISC_R_SUCCESS) {
 262		isc_mem_put(mctx, rbt, sizeof(*rbt));
 263		return (result);
 264	}
 265#endif
 266
 267	rbt->magic = RBT_MAGIC;
 268
 269	*rbtp = rbt;
 270
 271	return (ISC_R_SUCCESS);
 272}
 273
 274/*
 275 * Deallocate a red/black tree of trees.
 276 */
 277void
 278dns_rbt_destroy(dns_rbt_t **rbtp) {
 279	RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
 280}
 281
 282isc_result_t
 283dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
 284	dns_rbt_t *rbt;
 285
 286	REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
 287
 288	rbt = *rbtp;
 289
 290	dns_rbt_deletetreeflat(rbt, quantum, &rbt->root);
 291	if (rbt->root != NULL)
 292		return (ISC_R_QUOTA);
 293
 294	INSIST(rbt->nodecount == 0);
 295
 296	if (rbt->hashtable != NULL)
 297		isc_mem_put(rbt->mctx, rbt->hashtable,
 298			    rbt->hashsize * sizeof(dns_rbtnode_t *));
 299
 300	rbt->magic = 0;
 301
 302	isc_mem_put(rbt->mctx, rbt, sizeof(*rbt));
 303	*rbtp = NULL;
 304	return (ISC_R_SUCCESS);
 305}
 306
 307unsigned int
 308dns_rbt_nodecount(dns_rbt_t *rbt) {
 309	REQUIRE(VALID_RBT(rbt));
 310	return (rbt->nodecount);
 311}
 312
 313static inline isc_result_t
 314chain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
 315	   isc_boolean_t include_chain_end)
 316{
 317	dns_name_t nodename;
 318	isc_result_t result = ISC_R_SUCCESS;
 319	int i;
 320
 321	dns_name_init(&nodename, NULL);
 322
 323	if (include_chain_end && chain->end != NULL) {
 324		NODENAME(chain->end, &nodename);
 325		result = dns_name_copy(&nodename, name, NULL);
 326		if (result != ISC_R_SUCCESS)
 327			return (result);
 328	} else
 329		dns_name_reset(name);
 330
 331	for (i = (int)chain->level_count - 1; i >= 0; i--) {
 332		NODENAME(chain->levels[i], &nodename);
 333		result = dns_name_concatenate(name, &nodename, name, NULL);
 334
 335		if (result != ISC_R_SUCCESS)
 336			return (result);
 337	}
 338	return (result);
 339}
 340
 341static inline isc_result_t
 342move_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
 343	do {
 344		/*
 345		 * Go as far right and then down as much as possible,
 346		 * as long as the rightmost node has a down pointer.
 347		 */
 348		while (RIGHT(node) != NULL)
 349			node = RIGHT(node);
 350
 351		if (DOWN(node) == NULL)
 352			break;
 353
 354		ADD_LEVEL(chain, node);
 355		node = DOWN(node);
 356	} while (1);
 357
 358	chain->end = node;
 359
 360	return (ISC_R_SUCCESS);
 361}
 362
 363/*
 364 * Add 'name' to tree, initializing its data pointer with 'data'.
 365 */
 366
 367isc_result_t
 368dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
 369	/*
 370	 * Does this thing have too many variables or what?
 371	 */
 372	dns_rbtnode_t **root, *parent, *child, *current, *new_current;
 373	dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
 374	dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
 375	dns_offsets_t current_offsets;
 376	dns_namereln_t compared;
 377	isc_result_t result = ISC_R_SUCCESS;
 378	dns_rbtnodechain_t chain;
 379	unsigned int common_labels;
 380	unsigned int nlabels, hlabels;
 381	int order;
 382
 383	REQUIRE(VALID_RBT(rbt));
 384	REQUIRE(dns_name_isabsolute(name));
 385	REQUIRE(nodep != NULL && *nodep == NULL);
 386
 387	/*
 388	 * Create a copy of the name so the original name structure is
 389	 * not modified.
 390	 */
 391	dns_fixedname_init(&fixedcopy);
 392	add_name = dns_fixedname_name(&fixedcopy);
 393	dns_name_clone(name, add_name);
 394
 395	if (rbt->root == NULL) {
 396		result = create_node(rbt->mctx, add_name, &new_current);
 397		if (result == ISC_R_SUCCESS) {
 398			rbt->nodecount++;
 399			new_current->is_root = 1;
 400			rbt->root = new_current;
 401			*nodep = new_current;
 402			hash_node(rbt, new_current, name);
 403		}
 404		return (result);
 405	}
 406
 407	dns_rbtnodechain_init(&chain, rbt->mctx);
 408
 409	dns_fixedname_init(&fixedprefix);
 410	dns_fixedname_init(&fixedsuffix);
 411	prefix = dns_fixedname_name(&fixedprefix);
 412	suffix = dns_fixedname_name(&fixedsuffix);
 413
 414	root = &rbt->root;
 415	INSIST(IS_ROOT(*root));
 416	parent = NULL;
 417	current = NULL;
 418	child = *root;
 419	dns_name_init(&current_name, current_offsets);
 420	dns_fixedname_init(&fnewname);
 421	new_name = dns_fixedname_name(&fnewname);
 422	nlabels = dns_name_countlabels(name);
 423	hlabels = 0;
 424
 425	do {
 426		current = child;
 427
 428		NODENAME(current, &current_name);
 429		compared = dns_name_fullcompare(add_name, &current_name,
 430						&order, &common_labels);
 431
 432		if (compared == dns_namereln_equal) {
 433			*nodep = current;
 434			result = ISC_R_EXISTS;
 435			break;
 436
 437		}
 438
 439		if (compared == dns_namereln_none) {
 440
 441			if (order < 0) {
 442				parent = current;
 443				child = LEFT(current);
 444
 445			} else if (order > 0) {
 446				parent = current;
 447				child = RIGHT(current);
 448
 449			}
 450
 451		} else {
 452			/*
 453			 * This name has some suffix in common with the
 454			 * name at the current node.  If the name at
 455			 * the current node is shorter, that means the
 456			 * new name should be in a subtree.  If the
 457			 * name at the current node is longer, that means
 458			 * the down pointer to this tree should point
 459			 * to a new tree that has the common suffix, and
 460			 * the non-common parts of these two names should
 461			 * start a new tree.
 462			 */
 463			hlabels += common_labels;
 464			if (compared == dns_namereln_subdomain) {
 465				/*
 466				 * All of the existing labels are in common,
 467				 * so the new name is in a subtree.
 468				 * Whack off the common labels for the
 469				 * not-in-common part to be searched for
 470				 * in the next level.
 471				 */
 472				dns_name_split(add_name, common_labels,
 473					       add_name, NULL);
 474
 475				/*
 476				 * Follow the down pointer (possibly NULL).
 477				 */
 478				root = &DOWN(current);
 479
 480				INSIST(*root == NULL ||
 481				       (IS_ROOT(*root) &&
 482					PARENT(*root) == current));
 483
 484				parent = NULL;
 485				child = DOWN(current);
 486				ADD_LEVEL(&chain, current);
 487
 488			} else {
 489				/*
 490				 * The number of labels in common is fewer
 491				 * than the number of labels at the current
 492				 * node, so the current node must be adjusted
 493				 * to have just the common suffix, and a down
 494				 * pointer made to a new tree.
 495				 */
 496
 497				INSIST(compared == dns_namereln_commonancestor
 498				       || compared == dns_namereln_contains);
 499
 500				/*
 501				 * Ensure the number of levels in the tree
 502				 * does not exceed the number of logical
 503				 * levels allowed by DNSSEC.
 504				 *
 505				 * XXXDCL need a better error result?
 506				 *
 507				 * XXXDCL Since chain ancestors were removed,
 508				 * no longer used by dns_rbt_addonlevel(),
 509				 * this is the only real use of chains in the
 510				 * function.  It could be done instead with
 511				 * a simple integer variable, but I am pressed
 512				 * for time.
 513				 */
 514				if (chain.level_count ==
 515				    (sizeof(chain.levels) /
 516				     sizeof(*chain.levels))) {
 517					result = ISC_R_NOSPACE;
 518					break;
 519				}
 520
 521				/*
 522				 * Split the name into two parts, a prefix
 523				 * which is the not-in-common parts of the
 524				 * two names and a suffix that is the common
 525				 * parts of them.
 526				 */
 527				dns_name_split(&current_name, common_labels,
 528					       prefix, suffix);
 529				result = create_node(rbt->mctx, suffix,
 530						     &new_current);
 531
 532				if (result != ISC_R_SUCCESS)
 533					break;
 534
 535				/*
 536				 * Reproduce the tree attributes of the
 537				 * current node.
 538				 */
 539				new_current->is_root = current->is_root;
 540				if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
 541					new_current->nsec = DNS_RBT_NSEC_NORMAL;
 542				else
 543					new_current->nsec = current->nsec;
 544				PARENT(new_current)  = PARENT(current);
 545				LEFT(new_current)    = LEFT(current);
 546				RIGHT(new_current)   = RIGHT(current);
 547				COLOR(new_current)   = COLOR(current);
 548
 549				/*
 550				 * Fix pointers that were to the current node.
 551				 */
 552				if (parent != NULL) {
 553					if (LEFT(parent) == current)
 554						LEFT(parent) = new_current;
 555					else
 556						RIGHT(parent) = new_current;
 557				}
 558				if (LEFT(new_current) != NULL)
 559					PARENT(LEFT(new_current)) =
 560						new_current;
 561				if (RIGHT(new_current) != NULL)
 562					PARENT(RIGHT(new_current)) =
 563						new_current;
 564				if (*root == current)
 565					*root = new_current;
 566
 567				NAMELEN(current) = prefix->length;
 568				OFFSETLEN(current) = prefix->labels;
 569
 570				/*
 571				 * Set up the new root of the next level.
 572				 * By definition it will not be the top
 573				 * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
 574				 */
 575				current->is_root = 1;
 576				PARENT(current) = new_current;
 577				DOWN(new_current) = current;
 578				root = &DOWN(new_current);
 579
 580				ADD_LEVEL(&chain, new_current);
 581
 582				LEFT(current) = NULL;
 583				RIGHT(current) = NULL;
 584
 585				MAKE_BLACK(current);
 586				ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
 587
 588				rbt->nodecount++;
 589				dns_name_getlabelsequence(name,
 590							  nlabels - hlabels,
 591							  hlabels, new_name);
 592				hash_node(rbt, new_current, new_name);
 593
 594				if (common_labels ==
 595				    dns_name_countlabels(add_name)) {
 596					/*
 597					 * The name has been added by pushing
 598					 * the not-in-common parts down to
 599					 * a new level.
 600					 */
 601					*nodep = new_current;
 602					return (ISC_R_SUCCESS);
 603
 604				} else {
 605					/*
 606					 * The current node has no data,
 607					 * because it is just a placeholder.
 608					 * Its data pointer is already NULL
 609					 * from create_node()), so there's
 610					 * nothing more to do to it.
 611					 */
 612
 613					/*
 614					 * The not-in-common parts of the new
 615					 * name will be inserted into the new
 616					 * level following this loop (unless
 617					 * result != ISC_R_SUCCESS, which
 618					 * is tested after the loop ends).
 619					 */
 620					dns_name_split(add_name, common_labels,
 621						       add_name, NULL);
 622
 623					break;
 624				}
 625
 626			}
 627
 628		}
 629
 630	} while (child != NULL);
 631
 632	if (result == ISC_R_SUCCESS)
 633		result = create_node(rbt->mctx, add_name, &new_current);
 634
 635	if (result == ISC_R_SUCCESS) {
 636		dns_rbt_addonlevel(new_current, current, order, root);
 637		rbt->nodecount++;
 638		*nodep = new_current;
 639		hash_node(rbt, new_current, name);
 640	}
 641
 642	return (result);
 643}
 644
 645/*
 646 * Add a name to the tree of trees, associating it with some data.
 647 */
 648isc_result_t
 649dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
 650	isc_result_t result;
 651	dns_rbtnode_t *node;
 652
 653	REQUIRE(VALID_RBT(rbt));
 654	REQUIRE(dns_name_isabsolute(name));
 655
 656	node = NULL;
 657
 658	result = dns_rbt_addnode(rbt, name, &node);
 659
 660	/*
 661	 * dns_rbt_addnode will report the node exists even when
 662	 * it does not have data associated with it, but the
 663	 * dns_rbt_*name functions all behave depending on whether
 664	 * there is data associated with a node.
 665	 */
 666	if (result == ISC_R_SUCCESS ||
 667	    (result == ISC_R_EXISTS && DATA(node) == NULL)) {
 668		DATA(node) = data;
 669		result = ISC_R_SUCCESS;
 670	}
 671
 672	return (result);
 673}
 674
 675/*
 676 * Find the node for "name" in the tree of trees.
 677 */
 678isc_result_t
 679dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
 680		 dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
 681		 unsigned int options, dns_rbtfindcallback_t callback,
 682		 void *callback_arg)
 683{
 684	dns_rbtnode_t *current, *last_compared, *current_root;
 685	dns_rbtnodechain_t localchain;
 686	dns_name_t *search_name, current_name, *callback_name;
 687	dns_fixedname_t fixedcallbackname, fixedsearchname;
 688	dns_namereln_t compared;
 689	isc_result_t result, saved_result;
 690	unsigned int common_labels;
 691	unsigned int hlabels = 0;
 692	int order;
 693
 694	REQUIRE(VALID_RBT(rbt));
 695	REQUIRE(dns_name_isabsolute(name));
 696	REQUIRE(node != NULL && *node == NULL);
 697	REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
 698		!=         (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
 699
 700	/*
 701	 * If there is a chain it needs to appear to be in a sane state,
 702	 * otherwise a chain is still needed to generate foundname and
 703	 * callback_name.
 704	 */
 705	if (chain == NULL) {
 706		options |= DNS_RBTFIND_NOPREDECESSOR;
 707		chain = &localchain;
 708		dns_rbtnodechain_init(chain, rbt->mctx);
 709	} else
 710		dns_rbtnodechain_reset(chain);
 711
 712	if (rbt->root == NULL)
 713		return (ISC_R_NOTFOUND);
 714	else {
 715		/*
 716		 * Appease GCC about variables it incorrectly thinks are
 717		 * possibly used uninitialized.
 718		 */
 719		compared = dns_namereln_none;
 720		last_compared = NULL;
 721		order = 0;
 722	}
 723
 724	dns_fixedname_init(&fixedcallbackname);
 725	callback_name = dns_fixedname_name(&fixedcallbackname);
 726
 727	/*
 728	 * search_name is the name segment being sought in each tree level.
 729	 * By using a fixedname, the search_name will definitely have offsets
 730	 * for use by any splitting.
 731	 * By using dns_name_clone, no name data should be copied thanks to
 732	 * the lack of bitstring labels.
 733	 */
 734	dns_fixedname_init(&fixedsearchname);
 735	search_name = dns_fixedname_name(&fixedsearchname);
 736	dns_name_clone(name, search_name);
 737
 738	dns_name_init(&current_name, NULL);
 739
 740	saved_result = ISC_R_SUCCESS;
 741	current = rbt->root;
 742	current_root = rbt->root;
 743
 744	while (current != NULL) {
 745		NODENAME(current, &current_name);
 746		compared = dns_name_fullcompare(search_name, &current_name,
 747						&order, &common_labels);
 748		last_compared = current;
 749
 750		if (compared == dns_namereln_equal)
 751			break;
 752
 753		if (compared == dns_namereln_none) {
 754#ifdef DNS_RBT_USEHASH
 755			dns_name_t hash_name;
 756			dns_rbtnode_t *hnode;
 757			dns_rbtnode_t *up_current;
 758			unsigned int nlabels;
 759			unsigned int tlabels = 1;
 760			unsigned int hash;
 761
 762			/*
 763			 * If there is no hash table, hashing can't be done.
 764			 */
 765			if (rbt->hashtable == NULL)
 766				goto nohash;
 767
 768			/*
 769			 * The case of current != current_root, that
 770			 * means a left or right pointer was followed,
 771			 * only happens when the algorithm fell through to
 772			 * the traditional binary search because of a
 773			 * bitstring label.  Since we dropped the bitstring
 774			 * support, this should not happen.
 775			 */
 776			INSIST(current == current_root);
 777
 778			nlabels = dns_name_countlabels(search_name);
 779
 780			/*
 781			 * current_root is the root of the current level, so
 782			 * it's parent is the same as it's "up" pointer.
 783			 */
 784			up_current = PARENT(current_root);
 785			dns_name_init(&hash_name, NULL);
 786
 787		hashagain:
 788			/*
 789			 * Hash includes tail.
 790			 */
 791			dns_name_getlabelsequence(name,
 792						  nlabels - tlabels,
 793						  hlabels + tlabels,
 794						  &hash_name);
 795			hash = dns_name_fullhash(&hash_name, ISC_FALSE);
 796			dns_name_getlabelsequence(search_name,
 797						  nlabels - tlabels,
 798						  tlabels, &hash_name);
 799
 800			for (hnode = rbt->hashtable[hash % rbt->hashsize];
 801			     hnode != NULL;
 802			     hnode = hnode->hashnext)
 803			{
 804				dns_name_t hnode_name;
 805
 806				if (hash != HASHVAL(hnode))
 807					continue;
 808				if (find_up(hnode) != up_current)
 809					continue;
 810				dns_name_init(&hnode_name, NULL);
 811				NODENAME(hnode, &hnode_name);
 812				if (dns_name_equal(&hnode_name, &hash_name))
 813					break;
 814			}
 815
 816			if (hnode != NULL) {
 817				current = hnode;
 818				/*
 819				 * This is an optimization.  If hashing found
 820				 * the right node, the next call to
 821				 * dns_name_fullcompare() would obviously
 822				 * return _equal or _subdomain.  Determine
 823				 * which of those would be the case by
 824				 * checking if the full name was hashed.  Then
 825				 * make it look like dns_name_fullcompare
 826				 * was called and jump to the right place.
 827				 */
 828				if (tlabels == nlabels) {
 829					compared = dns_namereln_equal;
 830					break;
 831				} else {
 832					common_labels = tlabels;
 833					compared = dns_namereln_subdomain;
 834					goto subdomain;
 835				}
 836			}
 837
 838			if (tlabels++ < nlabels)
 839				goto hashagain;
 840
 841			/*
 842			 * All of the labels have been tried against the hash
 843			 * table.  Since we dropped the support of bitstring
 844			 * labels, the name isn't in the table.
 845			 */
 846			current = NULL;
 847			continue;
 848
 849		nohash:
 850#endif /* DNS_RBT_USEHASH */
 851			/*
 852			 * Standard binary search tree movement.
 853			 */
 854			if (order < 0)
 855				current = LEFT(current);
 856			else
 857				current = RIGHT(current);
 858
 859		} else {
 860			/*
 861			 * The names have some common suffix labels.
 862			 *
 863			 * If the number in common are equal in length to
 864			 * the current node's name length, then follow the
 865			 * down pointer and search in the new tree.
 866			 */
 867			if (compared == dns_namereln_subdomain) {
 868		subdomain:
 869				/*
 870				 * Whack off the current node's common parts
 871				 * for the name to search in the next level.
 872				 */
 873				dns_name_split(search_name, common_labels,
 874					       search_name, NULL);
 875				hlabels += common_labels;
 876				/*
 877				 * This might be the closest enclosing name.
 878				 */
 879				if (DATA(current) != NULL ||
 880				    (options & DNS_RBTFIND_EMPTYDATA) != 0)
 881					*node = current;
 882
 883				/*
 884				 * Point the chain to the next level.   This
 885				 * needs to be done before 'current' is pointed
 886				 * there because the callback in the next
 887				 * block of code needs the current 'current',
 888				 * but in the event the callback requests that
 889				 * the search be stopped then the
 890				 * DNS_R_PARTIALMATCH code at the end of this
 891				 * function needs the chain pointed to the
 892				 * next level.
 893				 */
 894				ADD_LEVEL(chain, current);
 895
 896				/*
 897				 * The caller may want to interrupt the
 898				 * downward search when certain special nodes
 899				 * are traversed.  If this is a special node,
 900				 * the callback is used to learn what the
 901				 * caller wants to do.
 902				 */
 903				if (callback != NULL &&
 904				    FINDCALLBACK(current)) {
 905					result = chain_name(chain,
 906							    callback_name,
 907							    ISC_FALSE);
 908					if (result != ISC_R_SUCCESS) {
 909						dns_rbtnodechain_reset(chain);
 910						return (result);
 911					}
 912
 913					result = (callback)(current,
 914							    callback_name,
 915							    callback_arg);
 916					if (result != DNS_R_CONTINUE) {
 917						saved_result = result;
 918						/*
 919						 * Treat this node as if it
 920						 * had no down pointer.
 921						 */
 922						current = NULL;
 923						break;
 924					}
 925				}
 926
 927				/*
 928				 * Finally, head to the next tree level.
 929				 */
 930				current = DOWN(current);
 931				current_root = current;
 932
 933			} else {
 934				/*
 935				 * Though there are labels in common, the
 936				 * entire name at this node is not common
 937				 * with the search name so the search
 938				 * name does not exist in the tree.
 939				 */
 940				INSIST(compared == dns_namereln_commonancestor
 941				       || compared == dns_namereln_contains);
 942
 943				current = NULL;
 944			}
 945		}
 946	}
 947
 948	/*
 949	 * If current is not NULL, NOEXACT is not disallowing exact matches,
 950	 * and either the node has data or an empty node is ok, return
 951	 * ISC_R_SUCCESS to indicate an exact match.
 952	 */
 953	if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
 954	    (DATA(current) != NULL ||
 955	     (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
 956		/*
 957		 * Found an exact match.
 958		 */
 959		chain->end = current;
 960		chain->level_matches = chain->level_count;
 961
 962		if (foundname != NULL)
 963			result = chain_name(chain, foundname, ISC_TRUE);
 964		else
 965			result = ISC_R_SUCCESS;
 966
 967		if (result == ISC_R_SUCCESS) {
 968			*node = current;
 969			result = saved_result;
 970		} else
 971			*node = NULL;
 972	} else {
 973		/*
 974		 * Did not find an exact match (or did not want one).
 975		 */
 976		if (*node != NULL) {
 977			/*
 978			 * ... but found a partially matching superdomain.
 979			 * Unwind the chain to the partial match node
 980			 * to set level_matches to the level above the node,
 981			 * and then to derive the name.
 982			 *
 983			 * chain->level_count is guaranteed to be at least 1
 984			 * here because by definition of finding a superdomain,
 985			 * the chain is pointed to at least the first subtree.
 986			 */
 987			chain->level_matches = chain->level_count - 1;
 988
 989			while (chain->levels[chain->level_matches] != *node) {
 990				INSIST(chain->level_matches > 0);
 991				chain->level_matches--;
 992			}
 993
 994			if (foundname != NULL) {
 995				unsigned int saved_count = chain->level_count;
 996
 997				chain->level_count = chain->level_matches + 1;
 998
 999				result = chain_name(chain, foundname,
1000						    ISC_FALSE);
1001
1002				chain->level_count = saved_count;
1003			} else
1004				result = ISC_R_SUCCESS;
1005
1006			if (result == ISC_R_SUCCESS)
1007				result = DNS_R_PARTIALMATCH;
1008
1009		} else
1010			result = ISC_R_NOTFOUND;
1011
1012		if (current != NULL) {
1013			/*
1014			 * There was an exact match but either
1015			 * DNS_RBTFIND_NOEXACT was set, or
1016			 * DNS_RBTFIND_EMPTYDATA was set and the node had no
1017			 * data.  A policy decision was made to set the
1018			 * chain to the exact match, but this is subject
1019			 * to change if it becomes apparent that something
1020			 * else would be more useful.  It is important that
1021			 * this case is handled here, because the predecessor
1022			 * setting code below assumes the match was not exact.
1023			 */
1024			INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
1025			       ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
1026				DATA(current) == NULL));
1027			chain->end = current;
1028
1029		} else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
1030			/*
1031			 * Ensure the chain points nowhere.
1032			 */
1033			chain->end = NULL;
1034
1035		} else {
1036			/*
1037			 * Since there was no exact match, the chain argument
1038			 * needs to be pointed at the DNSSEC predecessor of
1039			 * the search name.
1040			 */
1041			if (compared == dns_namereln_subdomain) {
1042				/*
1043				 * Attempted to follow a down pointer that was
1044				 * NULL, which means the searched for name was
1045				 * a subdomain of a terminal name in the tree.
1046				 * Since there are no existing subdomains to
1047				 * order against, the terminal name is the
1048				 * predecessor.
1049				 */
1050				INSIST(chain->level_count > 0);
1051				INSIST(chain->level_matches <
1052				       chain->level_count);
1053				chain->end =
1054					chain->levels[--chain->level_count];
1055
1056			} else {
1057				isc_result_t result2;
1058
1059				/*
1060				 * Point current to the node that stopped
1061				 * the search.
1062				 *
1063				 * With the hashing modification that has been
1064				 * added to the algorithm, the stop node of a
1065				 * standard binary search is not known.  So it
1066				 * has to be found.  There is probably a more
1067				 * clever way of doing this.
1068				 *
1069				 * The assignment of current to NULL when
1070				 * the relationship is *not* dns_namereln_none,
1071				 * even though it later gets set to the same
1072				 * last_compared anyway, is simply to not push
1073				 * the while loop in one more level of
1074				 * indentation.
1075				 */
1076				if (compared == dns_namereln_none)
1077					current = last_compared;
1078				else
1079					current = NULL;
1080
1081				while (current != NULL) {
1082					NODENAME(current, &current_name);
1083					compared = dns_name_fullcompare(
1084								search_name,
1085								&current_name,
1086								&order,
1087								&common_labels);
1088					POST(compared);
1089
1090					last_compared = current;
1091
1092					/*
1093					 * Standard binary search movement.
1094					 */
1095					if (order < 0)
1096						current = LEFT(current);
1097					else
1098						current = RIGHT(current);
1099
1100				}
1101
1102				current = last_compared;
1103
1104				/*
1105				 * Reached a point within a level tree that
1106				 * positively indicates the name is not
1107				 * present, but the stop node could be either
1108				 * less than the desired name (order > 0) or
1109				 * greater than the desired name (order < 0).
1110				 *
1111				 * If the stop node is less, it is not
1112				 * necessarily the predecessor.  If the stop
1113				 * node has a down pointer, then the real
1114				 * predecessor is at the end of a level below
1115				 * (not necessarily the next level).
1116				 * Move down levels until the rightmost node
1117				 * does not have a down pointer.
1118				 *
1119				 * When the stop node is greater, it is
1120				 * the successor.  All the logic for finding
1121				 * the predecessor is handily encapsulated
1122				 * in dns_rbtnodechain_prev.  In the event
1123				 * that the search name is less than anything
1124				 * else in the tree, the chain is reset.
1125				 * XXX DCL What is the best way for the caller
1126				 *         to know that the search name has
1127				 *         no predecessor?
1128				 */
1129
1130
1131				if (order > 0) {
1132					if (DOWN(current) != NULL) {
1133						ADD_LEVEL(chain, current);
1134
1135						result2 =
1136						      move_chain_to_last(chain,
1137								DOWN(current));
1138
1139						if (result2 != ISC_R_SUCCESS)
1140							result = result2;
1141					} else
1142						/*
1143						 * Ah, the pure and simple
1144						 * case.  The stop node is the
1145						 * predecessor.
1146						 */
1147						chain->end = current;
1148
1149				} else {
1150					INSIST(order < 0);
1151
1152					chain->end = current;
1153
1154					result2 = dns_rbtnodechain_prev(chain,
1155									NULL,
1156									NULL);
1157					if (result2 == ISC_R_SUCCESS ||
1158					    result2 == DNS_R_NEWORIGIN)
1159						;       /* Nothing. */
1160					else if (result2 == ISC_R_NOMORE)
1161						/*
1162						 * There is no predecessor.
1163						 */
1164						dns_rbtnodechain_reset(chain);
1165					else
1166						result = result2;
1167				}
1168
1169			}
1170		}
1171	}
1172
1173	ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
1174
1175	return (result);
1176}
1177
1178/*
1179 * Get the data pointer associated with 'name'.
1180 */
1181isc_result_t
1182dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
1183		 dns_name_t *foundname, void **data) {
1184	dns_rbtnode_t *node = NULL;
1185	isc_result_t result;
1186
1187	REQUIRE(data != NULL && *data == NULL);
1188
1189	result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
1190				  options, NULL, NULL);
1191
1192	if (node != NULL &&
1193	    (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
1194		*data = DATA(node);
1195	else
1196		result = ISC_R_NOTFOUND;
1197
1198	return (result);
1199}
1200
1201/*
1202 * Delete a name from the tree of trees.
1203 */
1204isc_result_t
1205dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
1206	dns_rbtnode_t *node = NULL;
1207	isc_result_t result;
1208
1209	REQUIRE(VALID_RBT(rbt));
1210	REQUIRE(dns_name_isabsolute(name));
1211
1212	/*
1213	 * First, find the node.
1214	 *
1215	 * When searching, the name might not have an exact match:
1216	 * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
1217	 * elements of a tree, which would make layer 1 a single
1218	 * node tree of "b.a.com" and layer 2 a three node tree of
1219	 * a, b, and c.  Deleting a.com would find only a partial depth
1220	 * match in the first layer.  Should it be a requirement that
1221	 * that the name to be deleted have data?  For now, it is.
1222	 *
1223	 * ->dirty, ->locknum and ->references are ignored; they are
1224	 * solely the province of rbtdb.c.
1225	 */
1226	result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
1227				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
1228
1229	if (result == ISC_R_SUCCESS) {
1230		if (DATA(node) != NULL)
1231			result = dns_rbt_deletenode(rbt, node, recurse);
1232		else
1233			result = ISC_R_NOTFOUND;
1234
1235	} else if (result == DNS_R_PARTIALMATCH)
1236		result = ISC_R_NOTFOUND;
1237
1238	return (result);
1239}
1240
1241/*
1242 * Remove a node from the tree of trees.
1243 *
1244 * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
1245 * a sequence of additions to be deletions will not generally get the
1246 * tree back to the state it started in.  For example, if the addition
1247 * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
1248 * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
1249 * restoring "a.b.c".  The RBT *used* to do this kind of rejoining, but it
1250 * turned out to be a bad idea because it could corrupt an active nodechain
1251 * that had "b.c" as one of its levels -- and the RBT has no idea what
1252 * nodechains are in use by callers, so it can't even *try* to helpfully
1253 * fix them up (which would probably be doomed to failure anyway).
1254 *
1255 * Similarly, it is possible to leave the tree in a state where a supposedly
1256 * deleted node still exists.  The first case of this is obvious; take
1257 * the tree which has "b.c" on one level, pointing to "a".  Now deleted "b.c".
1258 * It was just established in the previous paragraph why we can't pull "a"
1259 * back up to its parent level.  But what happens when "a" then gets deleted?
1260 * "b.c" is left hanging around without data or children.  This condition
1261 * is actually pretty easy to detect, but ... should it really be removed?
1262 * Is a chain pointing to it?  An iterator?  Who knows!  (Note that the
1263 * references structure member cannot be looked at because it is private to
1264 * rbtdb.)  This is ugly and makes me unhappy, but after hours of trying to
1265 * make it more aesthetically proper and getting nowhere, this is the way it
1266 * is going to stay until such time as it proves to be a *real* problem.
1267 *
1268 * Finally, for reference, note that the original routine that did node
1269 * joining was called join_nodes().  It has been excised, living now only
1270 * in the CVS history, but comments have been left behind that point to it just
1271 * in case someone wants to muck with this some more.
1272 *
1273 * The one positive aspect of all of this is that joining used to have a
1274 * case where it might fail.  Without trying to join, now this function always
1275 * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
1276 */
1277isc_result_t
1278dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
1279{
1280	dns_rbtnode_t *parent;
1281
1282	REQUIRE(VALID_RBT(rbt));
1283	REQUIRE(DNS_RBTNODE_VALID(node));
1284
1285	if (DOWN(node) != NULL) {
1286		if (recurse)
1287			RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node))
1288				      == ISC_R_SUCCESS);
1289		else {
1290			if (DATA(node) != NULL && rbt->data_deleter != NULL)
1291				rbt->data_deleter(DATA(node), rbt->deleter_arg);
1292			DATA(node) = NULL;
1293
1294			/*
1295			 * Since there is at least one node below this one and
1296			 * no recursion was requested, the deletion is
1297			 * complete.  The down node from this node might be all
1298			 * by itself on a single level, so join_nodes() could
1299			 * be used to collapse the tree (with all the caveats
1300			 * of the comment at the start of this function).
1301			 */
1302			return (ISC_R_SUCCESS);
1303		}
1304	}
1305
1306	/*
1307	 * Note the node that points to the level of the node that is being
1308	 * deleted.  If the deleted node is the top level, parent will be set
1309	 * to NULL.
1310	 */
1311	parent = find_up(node);
1312
1313	/*
1314	 * This node now has no down pointer (either because it didn't
1315	 * have one to start, or because it was recursively removed).
1316	 * So now the node needs to be removed from this level.
1317	 */
1318	dns_rbt_deletefromlevel(node, parent == NULL ? &rbt->root :
1319						       &DOWN(parent));
1320
1321	if (DATA(node) != NULL && rbt->data_deleter != NULL)
1322		rbt->data_deleter(DATA(node), rbt->deleter_arg);
1323
1324	unhash_node(rbt, node);
1325#if DNS_RBT_USEMAGIC
1326	node->magic = 0;
1327#endif
1328	dns_rbtnode_refdestroy(node);
1329	isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
1330	rbt->nodecount--;
1331
1332	/*
1333	 * There are now two special cases that can exist that would
1334	 * not have existed if the tree had been created using only
1335	 * the names that now exist in it.  (This is all related to
1336	 * join_nodes() as described in this function's introductory comment.)
1337	 * Both cases exist when the deleted node's parent (the node
1338	 * that pointed to the deleted node's level) is not null but
1339	 * it has no data:  parent != NULL && DATA(parent) == NULL.
1340	 *
1341	 * The first case is that the deleted node was the last on its level:
1342	 * DOWN(parent) == NULL.  This case can only exist if the parent was
1343	 * previously deleted -- and so now, apparently, the parent should go
1344	 * away.  That can't be done though because there might be external
1345	 * references to it, such as through a nodechain.
1346	 *
1347	 * The other case also involves a parent with no data, but with the
1348	 * deleted node being the next-to-last node instead of the last:
1349	 * LEFT(DOWN(parent)) == NULL && RIGHT(DOWN(parent)) == NULL.
1350	 * Presumably now the remaining node on the level should be joined
1351	 * with the parent, but it's already been described why that can't be
1352	 * done.
1353	 */
1354
1355	/*
1356	 * This function never fails.
1357	 */
1358	return (ISC_R_SUCCESS);
1359}
1360
1361void
1362dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
1363
1364	REQUIRE(DNS_RBTNODE_VALID(node));
1365	REQUIRE(name != NULL);
1366	REQUIRE(name->offsets == NULL);
1367
1368	NODENAME(node, name);
1369}
1370
1371isc_result_t
1372dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
1373	dns_name_t current;
1374	isc_result_t result;
1375
1376	REQUIRE(DNS_RBTNODE_VALID(node));
1377	REQUIRE(name != NULL);
1378	REQUIRE(name->buffer != NULL);
1379
1380	dns_name_init(&current, NULL);
1381	dns_name_reset(name);
1382
1383	do {
1384		INSIST(node != NULL);
1385
1386		NODENAME(node, &current);
1387
1388		result = dns_name_concatenate(name, &current, name, NULL);
1389		if (result != ISC_R_SUCCESS)
1390			break;
1391
1392		node = find_up(node);
1393	} while (! dns_name_isabsolute(name));
1394
1395	return (result);
1396}
1397
1398char *
1399dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
1400{
1401	dns_fixedname_t fixedname;
1402	dns_name_t *name;
1403	isc_result_t result;
1404
1405	REQUIRE(DNS_RBTNODE_VALID(node));
1406	REQUIRE(printname != NULL);
1407
1408	dns_fixedname_init(&fixedname);
1409	name = dns_fixedname_name(&fixedname);
1410	result = dns_rbt_fullnamefromnode(node, name);
1411	if (result == ISC_R_SUCCESS)
1412		dns_name_format(name, printname, size);
1413	else
1414		snprintf(printname, size, "<error building name: %s>",
1415			 dns_result_totext(result));
1416
1417	return (printname);
1418}
1419
1420static isc_result_t
1421create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
1422	dns_rbtnode_t *node;
1423	isc_region_t region;
1424	unsigned int labels;
1425
1426	REQUIRE(name->offsets != NULL);
1427
1428	dns_name_toregion(name, &region);
1429	labels = dns_name_countlabels(name);
1430	ENSURE(labels > 0);
1431
1432	/*
1433	 * Allocate space for the node structure, the name, and the offsets.
1434	 */
1435	node = (dns_rbtnode_t *)isc_mem_get(mctx, sizeof(*node) +
1436					    region.length + labels + 1);
1437
1438	if (node == NULL)
1439		return (ISC_R_NOMEMORY);
1440
1441	node->is_root = 0;
1442	PARENT(node) = NULL;
1443	RIGHT(node) = NULL;
1444	LEFT(node) = NULL;
1445	DOWN(node) = NULL;
1446	DATA(node) = NULL;
1447#ifdef DNS_RBT_USEHASH
1448	HASHNEXT(node) = NULL;
1449	HASHVAL(node) = 0;
1450#endif
1451
1452	ISC_LINK_INIT(node, deadlink);
1453
1454	LOCKNUM(node) = 0;
1455	WILD(node) = 0;
1456	DIRTY(node) = 0;
1457	dns_rbtnode_refinit(node, 0);
1458	node->find_callback = 0;
1459	node->nsec = DNS_RBT_NSEC_NORMAL;
1460
1461	MAKE_BLACK(node);
1462
1463	/*
1464	 * The following is stored to make reconstructing a name from the
1465	 * stored value in the node easy:  the length of the name, the number
1466	 * of labels, whether the name is absolute or not, the name itself,
1467	 * and the name's offsets table.
1468	 *
1469	 * XXX RTH
1470	 *      The offsets table could be made smaller by eliminating the
1471	 *      first offset, which is always 0.  This requires changes to
1472	 *      lib/dns/name.c.
1473	 *
1474	 * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
1475	 * 	 as it uses OLDNAMELEN.
1476	 */
1477	OLDNAMELEN(node) = NAMELEN(node) = region.length;
1478	OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
1479	ATTRS(node) = name->attributes;
1480
1481	memcpy(NAME(node), region.base, region.length);
1482	memcpy(OFFSETS(node), name->offsets, labels);
1483
1484#if DNS_RBT_USEMAGIC
1485	node->magic = DNS_RBTNODE_MAGIC;
1486#endif
1487	*nodep = node;
1488
1489	return (ISC_R_SUCCESS);
1490}
1491
1492#ifdef DNS_RBT_USEHASH
1493static inline void
1494hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
1495	unsigned int hash;
1496
1497	HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
1498
1499	hash = HASHVAL(node) % rbt->hashsize;
1500	HASHNEXT(node) = rbt->hashtable[hash];
1501
1502	rbt->hashtable[hash] = node;
1503}
1504
1505static isc_result_t
1506inithash(dns_rbt_t *rbt) {
1507	unsigned int bytes;
1508
1509	rbt->hashsize = RBT_HASH_SIZE;
1510	bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
1511	rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
1512
1513	if (rbt->hashtable == NULL)
1514		return (ISC_R_NOMEMORY);
1515
1516	memset(rbt->hashtable, 0, bytes);
1517
1518	return (ISC_R_SUCCESS);
1519}
1520
1521static void
1522rehash(dns_rbt_t *rbt) {
1523	unsigned int oldsize;
1524	dns_rbtnode_t **oldtable;
1525	dns_rbtnode_t *node;
1526	unsigned int hash;
1527	unsigned int i;
1528
1529	oldsize = rbt->hashsize;
1530	oldtable = rbt->hashtable;
1531	rbt->hashsize = rbt->hashsize * 2 + 1;
1532	rbt->hashtable = isc_mem_get(rbt->mctx,
1533				     rbt->hashsize * sizeof(dns_rbtnode_t *));
1534	if (rbt->hashtable == NULL) {
1535		rbt->hashtable = oldtable;
1536		rbt->hashsize = oldsize;
1537		return;
1538	}
1539
1540	for (i = 0; i < rbt->hashsize; i++)
1541		rbt->hashtable[i] = NULL;
1542
1543	for (i = 0; i < oldsize; i++) {
1544		node = oldtable[i];
1545		while (node != NULL) {
1546			hash = HASHVAL(node) % rbt->hashsize;
1547			oldtable[i] = HASHNEXT(node);
1548			HASHNEXT(node) = rbt->hashtable[hash];
1549			rbt->hashtable[hash] = node;
1550			node = oldtable[i];
1551		}
1552	}
1553
1554	isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
1555}
1556
1557static inline void
1558hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
1559
1560	REQUIRE(DNS_RBTNODE_VALID(node));
1561
1562	if (rbt->nodecount >= (rbt->hashsize *3))
1563		rehash(rbt);
1564
1565	hash_add_node(rbt, node, name);
1566}
1567
1568static inline void
1569unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
1570	unsigned int bucket;
1571	dns_rbtnode_t *bucket_node;
1572
1573	REQUIRE(DNS_RBTNODE_VALID(node));
1574
1575	if (rbt->hashtable != NULL) {
1576		bucket = HASHVAL(node) % rbt->hashsize;
1577		bucket_node = rbt->hashtable[bucket];
1578
1579		if (bucket_node == node)
1580			rbt->hashtable[bucket] = HASHNEXT(node);
1581		else {
1582			while (HASHNEXT(bucket_node) != node) {
1583				INSIST(HASHNEXT(bucket_node) != NULL);
1584				bucket_node = HASHNEXT(bucket_node);
1585			}
1586			HASHNEXT(bucket_node) = HASHNEXT(node);
1587		}
1588	}
1589}
1590#endif /* DNS_RBT_USEHASH */
1591
1592static inline void
1593rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
1594	dns_rbtnode_t *child;
1595
1596	REQUIRE(DNS_RBTNODE_VALID(node));
1597	REQUIRE(rootp != NULL);
1598
1599	child = RIGHT(node);
1600	INSIST(child != NULL);
1601
1602	RIGHT(node) = LEFT(child);
1603	if (LEFT(child) != NULL)
1604		PARENT(LEFT(child)) = node;
1605	LEFT(child) = node;
1606
1607	if (child != NULL)
1608		PARENT(child) = PARENT(node);
1609
1610	if (IS_ROOT(node)) {
1611		*rootp = child;
1612		child->is_root = 1;
1613		node->is_root = 0;
1614
1615	} else {
1616		if (LEFT(PARENT(node)) == node)
1617			LEFT(PARENT(node)) = child;
1618		else
1619			RIGHT(PARENT(node)) = child;
1620	}
1621
1622	PARENT(node) = child;
1623}
1624
1625static inline void
1626rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
1627	dns_rbtnode_t *child;
1628
1629	REQUIRE(DNS_RBTNODE_VALID(node));
1630	REQUIRE(rootp != NULL);
1631
1632	child = LEFT(node);
1633	INSIST(child != NULL);
1634
1635	LEFT(node) = RIGHT(child);
1636	if (RIGHT(child) != NULL)
1637		PARENT(RIGHT(child)) = node;
1638	RIGHT(child) = node;
1639
1640	if (child != NULL)
1641		PARENT(child) = PARENT(node);
1642
1643	if (IS_ROOT(node)) {
1644		*rootp = child;
1645		child->is_root = 1;
1646		node->is_root = 0;
1647
1648	} else {
1649		if (LEFT(PARENT(node)) == node)
1650			LEFT(PARENT(node)) = child;
1651		else
1652			RIGHT(PARENT(node)) = child;
1653	}
1654
1655	PARENT(node) = child;
1656}
1657
1658/*
1659 * This is the real workhorse of the insertion code, because it does the
1660 * true red/black tree on a single level.
1661 */
1662static void
1663dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
1664		   dns_rbtnode_t **rootp)
1665{
1666	dns_rbtnode_t *child, *root, *parent, *grandparent;
1667	dns_name_t add_name, current_name;
1668	dns_offsets_t add_offsets, current_offsets;
1669
1670	REQUIRE(rootp != NULL);
1671	REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
1672		RIGHT(node) == NULL);
1673	REQUIRE(current != NULL);
1674
1675	root = *rootp;
1676	if (root == NULL) {
1677		/*
1678		 * First node of a level.
1679		 */
1680		MAKE_BLACK(node);
1681		node->is_root = 1;
1682		PARENT(node) = current;
1683		*rootp = node;
1684		return;
1685	}
1686
1687	child = root;
1688	POST(child);
1689
1690	dns_name_init(&add_name, add_offsets);
1691	NODENAME(node, &add_name);
1692
1693	dns_name_init(&current_name, current_offsets);
1694	NODENAME(current, &current_name);
1695
1696	if (order < 0) {
1697		INSIST(LEFT(current) == NULL);
1698		LEFT(current) = node;
1699	} else {
1700		INSIST(RIGHT(current) == NULL);
1701		RIGHT(current) = node;
1702	}
1703
1704	INSIST(PARENT(node) == NULL);
1705	PARENT(node) = current;
1706
1707	MAKE_RED(node);
1708
1709	while (node != root && IS_RED(PARENT(node))) {
1710		/*
1711		 * XXXDCL could do away with separate parent and grandparent
1712		 * variables.  They are vestiges of the days before parent
1713		 * pointers.  However, they make the code a little clearer.
1714		 */
1715
1716		parent = PARENT(node);
1717		grandparent = PARENT(parent);
1718
1719		if (parent == LEFT(grandparent)) {
1720			child = RIGHT(grandparent);
1721			if (child != NULL && IS_RED(child)) {
1722				MAKE_BLACK(parent);
1723				MAKE_BLACK(child);
1724				MAKE_RED(grandparent);
1725				node = grandparent;
1726			} else {
1727				if (node == RIGHT(parent)) {
1728					rotate_left(parent, &root);
1729					node = parent;
1730					parent = PARENT(node);
1731					grandparent = PARENT(parent);
1732				}
1733				MAKE_BLACK(parent);
1734				MAKE_RED(grandparent);
1735				rotate_right(grandparent, &root);
1736			}
1737		} else {
1738			child = LEFT(grandparent);
1739			if (child != NULL && IS_RED(child)) {
1740				MAKE_BLACK(parent);
1741				MAKE_BLACK(child);
1742				MAKE_RED(grandparent);
1743				node = grandparent;
1744			} else {
1745				if (node == LEFT(parent)) {
1746					rotate_right(parent, &root);
1747					node = parent;
1748					parent = PARENT(node);
1749					grandparent = PARENT(parent);
1750				}
1751				MAKE_BLACK(parent);
1752				MAKE_RED(grandparent);
1753				rotate_left(grandparent, &root);
1754			}
1755		}
1756	}
1757
1758	MAKE_BLACK(root);
1759	ENSURE(IS_ROOT(root));
1760	*rootp = root;
1761
1762	return;
1763}
1764
1765/*
1766 * This is the real workhorse of the deletion code, because it does the
1767 * true red/black tree on a single level.
1768 */
1769static void
1770dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
1771	dns_rbtnode_t *child, *sibling, *parent;
1772	dns_rbtnode_t *successor;
1773
1774	REQUIRE(delete != NULL);
1775
1776	/*
1777	 * Verify that the parent history is (apparently) correct.
1778	 */
1779	INSIST((IS_ROOT(delete) && *rootp == delete) ||
1780	       (! IS_ROOT(delete) &&
1781		(LEFT(PARENT(delete)) == delete ||
1782		 RIGHT(PARENT(delete)) == delete)));
1783
1784	child = NULL;
1785
1786	if (LEFT(delete) == NULL) {
1787		if (RIGHT(delete) == NULL) {
1788			if (IS_ROOT(delete)) {
1789				/*
1790				 * This is the only item in the tree.
1791				 */
1792				*rootp = NULL;
1793				return;
1794			}
1795		} else
1796			/*
1797			 * This node has one child, on the right.
1798			 */
1799			child = RIGHT(delete);
1800
1801	} else if (RIGHT(delete) == NULL)
1802		/*
1803		 * This node has one child, on the left.
1804		 */
1805		child = LEFT(delete);
1806	else {
1807		dns_rbtnode_t holder, *tmp = &holder;
1808
1809		/*
1810		 * This node has two children, so it cannot be directly
1811		 * deleted.  Find its immediate in-order successor and
1812		 * move it to this location, then do the deletion at the
1813		 * old site of the successor.
1814		 */
1815		successor = RIGHT(delete);
1816		while (LEFT(successor) != NULL)
1817			successor = LEFT(successor);
1818
1819		/*
1820		 * The successor cannot possibly have a left child;
1821		 * if there is any child, it is on the right.
1822		 */
1823		if (RIGHT(successor) != NULL)
1824			child = RIGHT(successor);
1825
1826		/*
1827		 * Swap the two nodes; it would be simpler to just replace
1828		 * the value being deleted with that of the successor,
1829		 * but this rigamarole is done so the caller has complete
1830		 * control over the pointers (and memory allocation) of
1831		 * all of nodes.  If just the key value were removed from
1832		 * the tree, the pointer to the node would be unchanged.
1833		 */
1834
1835		/*
1836		 * First, put the successor in the tree location of the
1837		 * node to be deleted.  Save its existing tree pointer
1838		 * information, which will be needed when linking up
1839		 * delete to the successor's old location.
1840		 */
1841		memcpy(tmp, successor, sizeof(dns_rbtnode_t));
1842
1843		if (IS_ROOT(delete)) {
1844			*rootp = successor;
1845			successor->is_root = ISC_TRUE;
1846			delete->is_root = ISC_FALSE;
1847
1848		} else
1849			if (LEFT(PARENT(delete)) == delete)
1850				LEFT(PARENT(delete)) = successor;
1851			else
1852				RIGHT(PARENT(delete)) = successor;
1853
1854		PARENT(successor) = PARENT(delete);
1855		LEFT(successor)   = LEFT(delete);
1856		RIGHT(successor)  = RIGHT(delete);
1857		COLOR(successor)  = COLOR(delete);
1858
1859		if (LEFT(successor) != NULL)
1860			PARENT(LEFT(successor)) = successor;
1861		if (RIGHT(successor) != successor)
1862			PARENT(RIGHT(successor)) = successor;
1863
1864		/*
1865		 * Now relink the node to be deleted into the
1866		 * successor's previous tree location.  PARENT(tmp)
1867		 * is the successor's original parent.
1868		 */
1869		INSIST(! IS_ROOT(delete));
1870
1871		if (PARENT(tmp) == delete) {
1872			/*
1873			 * Node being deleted was successor's parent.
1874			 */
1875			RIGHT(successor) = delete;
1876			PARENT(delete) = successor;
1877
1878		} else {
1879			LEFT(PARENT(tmp)) = delete;
1880			PARENT(delete) = PARENT(tmp);
1881		}
1882
1883		/*
1884		 * Original location of successor node has no left.
1885		 */
1886		LEFT(delete)   = NULL;
1887		RIGHT(delete)  = RIGHT(tmp);
1888		COLOR(delete)  = COLOR(tmp);
1889	}
1890
1891	/*
1892	 * Remove the node by removing the links from its parent.
1893	 */
1894	if (! IS_ROOT(delete)) {
1895		if (LEFT(PARENT(delete)) == delete)
1896			LEFT(PARENT(delete)) = child;
1897		else
1898			RIGHT(PARENT(delete)) = child;
1899
1900		if (child != NULL)
1901			PARENT(child) = PARENT(delete);
1902
1903	} else {
1904		/*
1905		 * This is the root being deleted, and…

Large files files are truncated, but you can click here to view the full file