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 at this point
1906		 * it is known to have just one child.
1907		 */
1908		*rootp = child;
1909		child->is_root = 1;
1910		PARENT(child) = PARENT(delete);
1911	}
1912
1913	/*
1914	 * Fix color violations.
1915	 */
1916	if (IS_BLACK(delete)) {
1917		parent = PARENT(delete);
1918
1919		while (child != *rootp && IS_BLACK(child)) {
1920			INSIST(child == NULL || ! IS_ROOT(child));
1921
1922			if (LEFT(parent) == child) {
1923				sibling = RIGHT(parent);
1924
1925				if (IS_RED(sibling)) {
1926					MAKE_BLACK(sibling);
1927					MAKE_RED(parent);
1928					rotate_left(parent, rootp);
1929					sibling = RIGHT(parent);
1930				}
1931
1932				INSIST(sibling != NULL);
1933
1934				if (IS_BLACK(LEFT(sibling)) &&
1935				    IS_BLACK(RIGHT(sibling))) {
1936					MAKE_RED(sibling);
1937					child = parent;
1938
1939				} else {
1940
1941					if (IS_BLACK(RIGHT(sibling))) {
1942						MAKE_BLACK(LEFT(sibling));
1943						MAKE_RED(sibling);
1944						rotate_right(sibling, rootp);
1945						sibling = RIGHT(parent);
1946					}
1947
1948					COLOR(sibling) = COLOR(parent);
1949					MAKE_BLACK(parent);
1950					MAKE_BLACK(RIGHT(sibling));
1951					rotate_left(parent, rootp);
1952					child = *rootp;
1953				}
1954
1955			} else {
1956				/*
1957				 * Child is parent's right child.
1958				 * Everything is done the same as above,
1959				 * except mirrored.
1960				 */
1961				sibling = LEFT(parent);
1962
1963				if (IS_RED(sibling)) {
1964					MAKE_BLACK(sibling);
1965					MAKE_RED(parent);
1966					rotate_right(parent, rootp);
1967					sibling = LEFT(parent);
1968				}
1969
1970				INSIST(sibling != NULL);
1971
1972				if (IS_BLACK(LEFT(sibling)) &&
1973				    IS_BLACK(RIGHT(sibling))) {
1974					MAKE_RED(sibling);
1975					child = parent;
1976
1977				} else {
1978					if (IS_BLACK(LEFT(sibling))) {
1979						MAKE_BLACK(RIGHT(sibling));
1980						MAKE_RED(sibling);
1981						rotate_left(sibling, rootp);
1982						sibling = LEFT(parent);
1983					}
1984
1985					COLOR(sibling) = COLOR(parent);
1986					MAKE_BLACK(parent);
1987					MAKE_BLACK(LEFT(sibling));
1988					rotate_right(parent, rootp);
1989					child = *rootp;
1990				}
1991			}
1992
1993			parent = PARENT(child);
1994		}
1995
1996		if (IS_RED(child))
1997			MAKE_BLACK(child);
1998	}
1999}
2000
2001/*
2002 * This should only be used on the root of a tree, because no color fixup
2003 * is done at all.
2004 *
2005 * NOTE: No root pointer maintenance is done, because the function is only
2006 * used for two cases:
2007 * + deleting everything DOWN from a node that is itself being deleted, and
2008 * + deleting the entire tree of trees from dns_rbt_destroy.
2009 * In each case, the root pointer is no longer relevant, so there
2010 * is no need for a root parameter to this function.
2011 *
2012 * If the function is ever intended to be used to delete something where
2013 * a pointer needs to be told that this tree no longer exists,
2014 * this function would need to adjusted accordingly.
2015 */
2016static isc_result_t
2017dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
2018	isc_result_t result = ISC_R_SUCCESS;
2019	REQUIRE(VALID_RBT(rbt));
2020
2021	if (node == NULL)
2022		return (result);
2023
2024	if (LEFT(node) != NULL) {
2025		result = dns_rbt_deletetree(rbt, LEFT(node));
2026		if (result != ISC_R_SUCCESS)
2027			goto done;
2028		LEFT(node) = NULL;
2029	}
2030	if (RIGHT(node) != NULL) {
2031		result = dns_rbt_deletetree(rbt, RIGHT(node));
2032		if (result != ISC_R_SUCCESS)
2033			goto done;
2034		RIGHT(node) = NULL;
2035	}
2036	if (DOWN(node) != NULL) {
2037		result = dns_rbt_deletetree(rbt, DOWN(node));
2038		if (result != ISC_R_SUCCESS)
2039			goto done;
2040		DOWN(node) = NULL;
2041	}
2042 done:
2043	if (result != ISC_R_SUCCESS)
2044		return (result);
2045
2046	if (DATA(node) != NULL && rbt->data_deleter != NULL)
2047		rbt->data_deleter(DATA(node), rbt->deleter_arg);
2048
2049	unhash_node(rbt, node);
2050#if DNS_RBT_USEMAGIC
2051	node->magic = 0;
2052#endif
2053
2054	isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
2055	rbt->nodecount--;
2056	return (result);
2057}
2058
2059static void
2060dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
2061		       dns_rbtnode_t **nodep)
2062{
2063	dns_rbtnode_t *parent;
2064	dns_rbtnode_t *node = *nodep;
2065	REQUIRE(VALID_RBT(rbt));
2066
2067 again:
2068	if (node == NULL) {
2069		*nodep = NULL;
2070		return;
2071	}
2072
2073 traverse:
2074	if (LEFT(node) != NULL) {
2075		node = LEFT(node);
2076		goto traverse;
2077	}
2078	if (DOWN(node) != NULL) {
2079		node = DOWN(node);
2080		goto traverse;
2081	}
2082
2083	if (DATA(node) != NULL && rbt->data_deleter != NULL)
2084		rbt->data_deleter(DATA(node), rbt->deleter_arg);
2085
2086	/*
2087	 * Note: we don't call unhash_node() here as we are destroying
2088	 * the complete rbt tree.
2089	 */
2090#if DNS_RBT_USEMAGIC
2091	node->magic = 0;
2092#endif
2093	parent = PARENT(node);
2094	if (RIGHT(node) != NULL)
2095		PARENT(RIGHT(node)) = parent;
2096	if (parent != NULL) {
2097		if (LEFT(parent) == node)
2098			LEFT(parent) = RIGHT(node);
2099		else if (DOWN(parent) == node)
2100			DOWN(parent) = RIGHT(node);
2101	} else
2102		parent = RIGHT(node);
2103
2104	isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
2105	rbt->nodecount--;
2106	node = parent;
2107	if (quantum != 0 && --quantum == 0) {
2108		*nodep = node;
2109		return;
2110	}
2111	goto again;
2112}
2113
2114static void
2115dns_rbt_indent(int depth) {
2116	int i;
2117
2118	for (i = 0; i < depth; i++)
2119		putchar('\t');
2120}
2121
2122static void
2123dns_rbt_printnodename(dns_rbtnode_t *node) {
2124	isc_region_t r;
2125	dns_name_t name;
2126	char buffer[DNS_NAME_FORMATSIZE];
2127	dns_offsets_t offsets;
2128
2129	r.length = NAMELEN(node);
2130	r.base = NAME(node);
2131
2132	dns_name_init(&name, offsets);
2133	dns_name_fromregion(&name, &r);
2134
2135	dns_name_format(&name, buffer, sizeof(buffer));
2136
2137	printf("%s", buffer);
2138}
2139
2140static void
2141dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) {
2142	dns_rbt_indent(depth);
2143
2144	if (root != NULL) {
2145		dns_rbt_printnodename(root);
2146		printf(" (%s", IS_RED(root) ? "RED" : "black");
2147		if (parent) {
2148			printf(" from ");
2149			dns_rbt_printnodename(parent);
2150		}
2151
2152		if ((! IS_ROOT(root) && PARENT(root) != parent) ||
2153		    (  IS_ROOT(root) && depth > 0 &&
2154		       DOWN(PARENT(root)) != root)) {
2155
2156			printf(" (BAD parent pointer! -> ");
2157			if (PARENT(root) != NULL)
2158				dns_rbt_printnodename(PARENT(root));
2159			else
2160				printf("NULL");
2161			printf(")");
2162		}
2163
2164		printf(")\n");
2165
2166
2167		depth++;
2168
2169		if (DOWN(root)) {
2170			dns_rbt_indent(depth);
2171			printf("++ BEG down from ");
2172			dns_rbt_printnodename(root);
2173			printf("\n");
2174			dns_rbt_printtree(DOWN(root), NULL, depth);
2175			dns_rbt_indent(depth);
2176			printf("-- END down from ");
2177			dns_rbt_printnodename(root);
2178			printf("\n");
2179		}
2180
2181		if (IS_RED(root) && IS_RED(LEFT(root)))
2182		    printf("** Red/Red color violation on left\n");
2183		dns_rbt_printtree(LEFT(root), root, depth);
2184
2185		if (IS_RED(root) && IS_RED(RIGHT(root)))
2186		    printf("** Red/Red color violation on right\n");
2187		dns_rbt_printtree(RIGHT(root), root, depth);
2188
2189	} else
2190		printf("NULL\n");
2191}
2192
2193void
2194dns_rbt_printall(dns_rbt_t *rbt) {
2195	REQUIRE(VALID_RBT(rbt));
2196
2197	dns_rbt_printtree(rbt->root, NULL, 0);
2198}
2199
2200/*
2201 * Chain Functions
2202 */
2203
2204void
2205dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
2206	/*
2207	 * Initialize 'chain'.
2208	 */
2209
2210	REQUIRE(chain != NULL);
2211
2212	chain->mctx = mctx;
2213	chain->end = NULL;
2214	chain->level_count = 0;
2215	chain->level_matches = 0;
2216	memset(chain->levels, 0, sizeof(chain->levels));
2217
2218	chain->magic = CHAIN_MAGIC;
2219}
2220
2221isc_result_t
2222dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
2223			 dns_name_t *origin, dns_rbtnode_t **node)
2224{
2225	isc_result_t result = ISC_R_SUCCESS;
2226
2227	REQUIRE(VALID_CHAIN(chain));
2228
2229	if (node != NULL)
2230		*node = chain->end;
2231
2232	if (chain->end == NULL)
2233		return (ISC_R_NOTFOUND);
2234
2235	if (name != NULL) {
2236		NODENAME(chain->end, name);
2237
2238		if (chain->level_count == 0) {
2239			/*
2240			 * Names in the top level tree are all absolute.
2241			 * Always make 'name' relative.
2242			 */
2243			INSIST(dns_name_isabsolute(name));
2244
2245			/*
2246			 * This is cheaper than dns_name_getlabelsequence().
2247			 */
2248			name->labels--;
2249			name->length--;
2250			name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
2251		}
2252	}
2253
2254	if (origin != NULL) {
2255		if (chain->level_count > 0)
2256			result = chain_name(chain, origin, ISC_FALSE);
2257		else
2258			result = dns_name_copy(dns_rootname, origin, NULL);
2259	}
2260
2261	return (result);
2262}
2263
2264isc_result_t
2265dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
2266		      dns_name_t *origin)
2267{
2268	dns_rbtnode_t *current, *previous, *predecessor;
2269	isc_result_t result = ISC_R_SUCCESS;
2270	isc_boolean_t new_origin = ISC_FALSE;
2271
2272	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2273
2274	predecessor = NULL;
2275
2276	current = chain->end;
2277
2278	if (LEFT(current) != NULL) {
2279		/*
2280		 * Moving left one then right as far as possible is the
2281		 * previous node, at least for this level.
2282		 */
2283		current = LEFT(current);
2284
2285		while (RIGHT(current) != NULL)
2286			current = RIGHT(current);
2287
2288		predecessor = current;
2289
2290	} else {
2291		/*
2292		 * No left links, so move toward the root.  If at any point on
2293		 * the way there the link from parent to child is a right
2294		 * link, then the parent is the previous node, at least
2295		 * for this level.
2296		 */
2297		while (! IS_ROOT(current)) {
2298			previous = current;
2299			current = PARENT(current);
2300
2301			if (RIGHT(current) == previous) {
2302				predecessor = current;
2303				break;
2304			}
2305		}
2306	}
2307
2308	if (predecessor != NULL) {
2309		/*
2310		 * Found a predecessor node in this level.  It might not
2311		 * really be the predecessor, however.
2312		 */
2313		if (DOWN(predecessor) != NULL) {
2314			/*
2315			 * The predecessor is really down at least one level.
2316			 * Go down and as far right as possible, and repeat
2317			 * as long as the rightmost node has a down pointer.
2318			 */
2319			do {
2320				/*
2321				 * XXX DCL Need to do something about origins
2322				 * here. See whether to go down, and if so
2323				 * whether it is truly what Bob calls a
2324				 * new origin.
2325				 */
2326				ADD_LEVEL(chain, predecessor);
2327				predecessor = DOWN(predecessor);
2328
2329				/* XXX DCL duplicated from above; clever
2330				 * way to unduplicate? */
2331
2332				while (RIGHT(predecessor) != NULL)
2333					predecessor = RIGHT(predecessor);
2334			} while (DOWN(predecessor) != NULL);
2335
2336			/* XXX DCL probably needs work on the concept */
2337			if (origin != NULL)
2338				new_origin = ISC_TRUE;
2339		}
2340
2341	} else if (chain->level_count > 0) {
2342		/*
2343		 * Dang, didn't find a predecessor in this level.
2344		 * Got to the root of this level without having traversed
2345		 * any right links.  Ascend the tree one level; the
2346		 * node that points to this tree is the predecessor.
2347		 */
2348		INSIST(chain->level_count > 0 && IS_ROOT(current));
2349		predecessor = chain->levels[--chain->level_count];
2350
2351		/* XXX DCL probably needs work on the concept */
2352		/*
2353		 * Don't declare an origin change when the new origin is "."
2354		 * at the top level tree, because "." is declared as the origin
2355		 * for the second level tree.
2356		 */
2357		if (origin != NULL &&
2358		    (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
2359			new_origin = ISC_TRUE;
2360	}
2361
2362	if (predecessor != NULL) {
2363		chain->end = predecessor;
2364
2365		if (new_origin) {
2366			result = dns_rbtnodechain_current(chain, name, origin,
2367							  NULL);
2368			if (result == ISC_R_SUCCESS)
2369				result = DNS_R_NEWORIGIN;
2370
2371		} else
2372			result = dns_rbtnodechain_current(chain, name, NULL,
2373							  NULL);
2374
2375	} else
2376		result = ISC_R_NOMORE;
2377
2378	return (result);
2379}
2380
2381isc_result_t
2382dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
2383		      dns_name_t *origin)
2384{
2385	dns_rbtnode_t *current, *successor;
2386	isc_result_t result = ISC_R_SUCCESS;
2387	isc_boolean_t new_origin = ISC_FALSE;
2388
2389	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2390
2391	successor = NULL;
2392
2393	current = chain->end;
2394
2395	if (DOWN(current) != NULL) {
2396		/*
2397		 * Don't declare an origin change when the new origin is "."
2398		 * at the second level tree, because "." is already declared
2399		 * as the origin for the top level tree.
2400		 */
2401		if (chain->level_count > 0 ||
2402		    OFFSETLEN(current) > 1)
2403			new_origin = ISC_TRUE;
2404
2405		ADD_LEVEL(chain, current);
2406		current = DOWN(current);
2407
2408		while (LEFT(current) != NULL)
2409			current = LEFT(current);
2410
2411		successor = current;
2412	}
2413
2414	if (successor != NULL) {
2415		chain->end = successor;
2416
2417		/*
2418		 * It is not necessary to use dns_rbtnodechain_current like
2419		 * the other functions because this function will never
2420		 * find a node in the topmost level.  This is because the
2421		 * root level will never be more than one name, and everything
2422		 * in the megatree is a successor to that node, down at
2423		 * the second level or below.
2424		 */
2425
2426		if (name != NULL)
2427			NODENAME(chain->end, name);
2428
2429		if (new_origin) {
2430			if (origin != NULL)
2431				result = chain_name(chain, origin, ISC_FALSE);
2432
2433			if (result == ISC_R_SUCCESS)
2434				result = DNS_R_NEWORIGIN;
2435
2436		} else
2437			result = ISC_R_SUCCESS;
2438
2439	} else
2440		result = ISC_R_NOMORE;
2441
2442	return (result);
2443}
2444
2445isc_result_t
2446dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
2447	dns_rbtnode_t *current, *previous, *successor;
2448	isc_result_t result = ISC_R_SUCCESS;
2449
2450	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2451
2452	successor = NULL;
2453
2454	current = chain->end;
2455
2456	if (RIGHT(current) == NULL) {
2457		while (! IS_ROOT(current)) {
2458			previous = current;
2459			current = PARENT(current);
2460
2461			if (LEFT(current) == previous) {
2462				successor = current;
2463				break;
2464			}
2465		}
2466	} else {
2467		current = RIGHT(current);
2468
2469		while (LEFT(current) != NULL)
2470			current = LEFT(current);
2471
2472		successor = current;
2473	}
2474
2475	if (successor != NULL) {
2476		chain->end = successor;
2477
2478		if (name != NULL)
2479			NODENAME(chain->end, name);
2480
2481		result = ISC_R_SUCCESS;
2482	} else
2483		result = ISC_R_NOMORE;
2484
2485	return (result);
2486}
2487
2488isc_result_t
2489dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
2490		      dns_name_t *origin)
2491{
2492	dns_rbtnode_t *current, *previous, *successor;
2493	isc_result_t result = ISC_R_SUCCESS;
2494	isc_boolean_t new_origin = ISC_FALSE;
2495
2496	REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2497
2498	successor = NULL;
2499
2500	current = chain->end;
2501
2502	/*
2503	 * If there is a level below this node, the next node is the leftmost
2504	 * node of the next level.
2505	 */
2506	if (DOWN(current) != NULL) {
2507		/*
2508		 * Don't declare an origin change when the new origin is "."
2509		 * at the second level tree, because "." is already declared
2510		 * as the origin for the top level tree.
2511		 */
2512		if (chain->level_count > 0 ||
2513		    OFFSETLEN(current) > 1)
2514			new_origin = ISC_TRUE;
2515
2516		ADD_LEVEL(chain, current);
2517		current = DOWN(current);
2518
2519		while (LEFT(current) != NULL)
2520			current = LEFT(current);
2521
2522		successor = current;
2523
2524	} else if (RIGHT(current) == NULL) {
2525		/*
2526		 * The successor is up, either in this level or a previous one.
2527		 * Head back toward the root of the tree, looking for any path
2528		 * that was via a left link; the successor is the node that has
2529		 * that left link.  In the event the root of the level is
2530		 * reached without having traversed any left links, ascend one
2531		 * level and look for either a right link off the point of
2532		 * ascent, or search for a left link upward again, repeating
2533		 * ascends until either case is true.
2534		 */
2535		do {
2536			while (! IS_ROOT(current)) {
2537				previous = current;
2538				current = PARENT(current);
2539
2540				if (LEFT(current) == previous) {
2541					successor = current;
2542					break;
2543				}
2544			}
2545
2546			if (successor == NULL) {
2547				/*
2548				 * Reached the root without having traversed
2549				 * any left pointers, so this level is done.
2550				 */
2551				if (chain->level_count == 0)
2552					break;
2553
2554				current = chain->levels[--chain->level_count];
2555				new_origin = ISC_TRUE;
2556
2557				if (RIGHT(current) != NULL)
2558					break;
2559			}
2560		} while (successor == NULL);
2561	}
2562
2563	if (successor == NULL && RIGHT(current) != NULL) {
2564		current = RIGHT(current);
2565
2566		while (LEFT(current) != NULL)
2567			current = LEFT(current);
2568
2569		successor = current;
2570	}
2571
2572	if (successor != NULL) {
2573		chain->end = successor;
2574
2575		/*
2576		 * It is not necessary to use dns_rbtnodechain_current like
2577		 * the other functions because this function will never
2578		 * find a node in the topmost level.  This is because the
2579		 * root level will never be more than one name, and everything
2580		 * in the megatree is a successor to that node, down at
2581		 * the second level or below.
2582		 */
2583
2584		if (name != NULL)
2585			NODENAME(chain->end, name);
2586
2587		if (new_origin) {
2588			if (origin != NULL)
2589				result = chain_name(chain, origin, ISC_FALSE);
2590
2591			if (result == ISC_R_SUCCESS)
2592				result = DNS_R_NEWORIGIN;
2593
2594		} else
2595			result = ISC_R_SUCCESS;
2596
2597	} else
2598		result = ISC_R_NOMORE;
2599
2600	return (result);
2601}
2602
2603isc_result_t
2604dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
2605		       dns_name_t *name, dns_name_t *origin)
2606
2607{
2608	isc_result_t result;
2609
2610	REQUIRE(VALID_RBT(rbt));
2611	REQUIRE(VALID_CHAIN(chain));
2612
2613	dns_rbtnodechain_reset(chain);
2614
2615	chain->end = rbt->root;
2616
2617	result = dns_rbtnodechain_current(chain, name, origin, NULL);
2618
2619	if (result == ISC_R_SUCCESS)
2620		result = DNS_R_NEWORIGIN;
2621
2622	return (result);
2623}
2624
2625isc_result_t
2626dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
2627		       dns_name_t *name, dns_name_t *origin)
2628
2629{
2630	isc_result_t result;
2631
2632	REQUIRE(VALID_RBT(rbt));
2633	REQUIRE(VALID_CHAIN(chain));
2634
2635	dns_rbtnodechain_reset(chain);
2636
2637	result = move_chain_to_last(chain, rbt->root);
2638	if (result != ISC_R_SUCCESS)
2639		return (result);
2640
2641	result = dns_rbtnodechain_current(chain, name, origin, NULL);
2642
2643	if (result == ISC_R_SUCCESS)
2644		result = DNS_R_NEWORIGIN;
2645
2646	return (result);
2647}
2648
2649
2650void
2651dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
2652	/*
2653	 * Free any dynamic storage associated with 'chain', and then
2654	 * reinitialize 'chain'.
2655	 */
2656
2657	REQUIRE(VALID_CHAIN(chain));
2658
2659	chain->end = NULL;
2660	chain->level_count = 0;
2661	chain->level_matches = 0;
2662}
2663
2664void
2665dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
2666	/*
2667	 * Free any dynamic storage associated with 'chain', and then
2668	 * invalidate 'chain'.
2669	 */
2670
2671	dns_rbtnodechain_reset(chain);
2672
2673	chain->magic = 0;
2674}
2675