]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bind9/lib/dns/rbt.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / bind9 / lib / dns / rbt.c
1 /*
2  * Copyright (C) 2004, 2005, 2007-2009  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: rbt.c,v 1.142.50.3 2009/10/20 05:06:04 marka Exp $ */
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
62 struct 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) \
146 do { \
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
156 static isc_result_t
157 inithash(dns_rbt_t *rbt);
158 #endif
159
160 #ifdef DEBUG
161 #define inline
162 /*
163  * A little something to help out in GDB.
164  */
165 dns_name_t Name(dns_rbtnode_t *node);
166 dns_name_t
167 Name(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
177 static void dns_rbt_printnodename(dns_rbtnode_t *node);
178 #endif
179
180 static inline dns_rbtnode_t *
181 find_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  */
198 static isc_result_t
199 create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
200
201 #ifdef DNS_RBT_USEHASH
202 static inline void
203 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
204 static inline void
205 unhash_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
211 static inline void
212 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
213 static inline void
214 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
215
216 static void
217 dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
218                    dns_rbtnode_t **rootp);
219
220 static void
221 dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
222
223 static isc_result_t
224 dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
225
226 static void
227 dns_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  */
233 isc_result_t
234 dns_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  */
277 void
278 dns_rbt_destroy(dns_rbt_t **rbtp) {
279         RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
280 }
281
282 isc_result_t
283 dns_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
307 unsigned int
308 dns_rbt_nodecount(dns_rbt_t *rbt) {
309         REQUIRE(VALID_RBT(rbt));
310         return (rbt->nodecount);
311 }
312
313 static inline isc_result_t
314 chain_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
341 static inline isc_result_t
342 move_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
367 isc_result_t
368 dns_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                                 new_current->nsec3 = current->nsec3;
541                                 PARENT(new_current)  = PARENT(current);
542                                 LEFT(new_current)    = LEFT(current);
543                                 RIGHT(new_current)   = RIGHT(current);
544                                 COLOR(new_current)   = COLOR(current);
545
546                                 /*
547                                  * Fix pointers that were to the current node.
548                                  */
549                                 if (parent != NULL) {
550                                         if (LEFT(parent) == current)
551                                                 LEFT(parent) = new_current;
552                                         else
553                                                 RIGHT(parent) = new_current;
554                                 }
555                                 if (LEFT(new_current) != NULL)
556                                         PARENT(LEFT(new_current)) =
557                                                 new_current;
558                                 if (RIGHT(new_current) != NULL)
559                                         PARENT(RIGHT(new_current)) =
560                                                 new_current;
561                                 if (*root == current)
562                                         *root = new_current;
563
564                                 NAMELEN(current) = prefix->length;
565                                 OFFSETLEN(current) = prefix->labels;
566
567                                 /*
568                                  * Set up the new root of the next level.
569                                  * By definition it will not be the top
570                                  * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
571                                  */
572                                 current->is_root = 1;
573                                 PARENT(current) = new_current;
574                                 DOWN(new_current) = current;
575                                 root = &DOWN(new_current);
576
577                                 ADD_LEVEL(&chain, new_current);
578
579                                 LEFT(current) = NULL;
580                                 RIGHT(current) = NULL;
581
582                                 MAKE_BLACK(current);
583                                 ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
584
585                                 rbt->nodecount++;
586                                 dns_name_getlabelsequence(name,
587                                                           nlabels - hlabels,
588                                                           hlabels, new_name);
589                                 hash_node(rbt, new_current, new_name);
590
591                                 if (common_labels ==
592                                     dns_name_countlabels(add_name)) {
593                                         /*
594                                          * The name has been added by pushing
595                                          * the not-in-common parts down to
596                                          * a new level.
597                                          */
598                                         *nodep = new_current;
599                                         return (ISC_R_SUCCESS);
600
601                                 } else {
602                                         /*
603                                          * The current node has no data,
604                                          * because it is just a placeholder.
605                                          * Its data pointer is already NULL
606                                          * from create_node()), so there's
607                                          * nothing more to do to it.
608                                          */
609
610                                         /*
611                                          * The not-in-common parts of the new
612                                          * name will be inserted into the new
613                                          * level following this loop (unless
614                                          * result != ISC_R_SUCCESS, which
615                                          * is tested after the loop ends).
616                                          */
617                                         dns_name_split(add_name, common_labels,
618                                                        add_name, NULL);
619
620                                         break;
621                                 }
622
623                         }
624
625                 }
626
627         } while (child != NULL);
628
629         if (result == ISC_R_SUCCESS)
630                 result = create_node(rbt->mctx, add_name, &new_current);
631
632         if (result == ISC_R_SUCCESS) {
633                 dns_rbt_addonlevel(new_current, current, order, root);
634                 rbt->nodecount++;
635                 *nodep = new_current;
636                 hash_node(rbt, new_current, name);
637         }
638
639         return (result);
640 }
641
642 /*
643  * Add a name to the tree of trees, associating it with some data.
644  */
645 isc_result_t
646 dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
647         isc_result_t result;
648         dns_rbtnode_t *node;
649
650         REQUIRE(VALID_RBT(rbt));
651         REQUIRE(dns_name_isabsolute(name));
652
653         node = NULL;
654
655         result = dns_rbt_addnode(rbt, name, &node);
656
657         /*
658          * dns_rbt_addnode will report the node exists even when
659          * it does not have data associated with it, but the
660          * dns_rbt_*name functions all behave depending on whether
661          * there is data associated with a node.
662          */
663         if (result == ISC_R_SUCCESS ||
664             (result == ISC_R_EXISTS && DATA(node) == NULL)) {
665                 DATA(node) = data;
666                 result = ISC_R_SUCCESS;
667         }
668
669         return (result);
670 }
671
672 /*
673  * Find the node for "name" in the tree of trees.
674  */
675 isc_result_t
676 dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
677                  dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
678                  unsigned int options, dns_rbtfindcallback_t callback,
679                  void *callback_arg)
680 {
681         dns_rbtnode_t *current, *last_compared, *current_root;
682         dns_rbtnodechain_t localchain;
683         dns_name_t *search_name, current_name, *callback_name;
684         dns_fixedname_t fixedcallbackname, fixedsearchname;
685         dns_namereln_t compared;
686         isc_result_t result, saved_result;
687         unsigned int common_labels;
688         unsigned int hlabels = 0;
689         int order;
690
691         REQUIRE(VALID_RBT(rbt));
692         REQUIRE(dns_name_isabsolute(name));
693         REQUIRE(node != NULL && *node == NULL);
694         REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
695                 !=         (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
696
697         /*
698          * If there is a chain it needs to appear to be in a sane state,
699          * otherwise a chain is still needed to generate foundname and
700          * callback_name.
701          */
702         if (chain == NULL) {
703                 options |= DNS_RBTFIND_NOPREDECESSOR;
704                 chain = &localchain;
705                 dns_rbtnodechain_init(chain, rbt->mctx);
706         } else
707                 dns_rbtnodechain_reset(chain);
708
709         if (rbt->root == NULL)
710                 return (ISC_R_NOTFOUND);
711         else {
712                 /*
713                  * Appease GCC about variables it incorrectly thinks are
714                  * possibly used uninitialized.
715                  */
716                 compared = dns_namereln_none;
717                 last_compared = NULL;
718         }
719
720         dns_fixedname_init(&fixedcallbackname);
721         callback_name = dns_fixedname_name(&fixedcallbackname);
722
723         /*
724          * search_name is the name segment being sought in each tree level.
725          * By using a fixedname, the search_name will definitely have offsets
726          * for use by any splitting.
727          * By using dns_name_clone, no name data should be copied thanks to
728          * the lack of bitstring labels.
729          */
730         dns_fixedname_init(&fixedsearchname);
731         search_name = dns_fixedname_name(&fixedsearchname);
732         dns_name_clone(name, search_name);
733
734         dns_name_init(&current_name, NULL);
735
736         saved_result = ISC_R_SUCCESS;
737         current = rbt->root;
738         current_root = rbt->root;
739
740         while (current != NULL) {
741                 NODENAME(current, &current_name);
742                 compared = dns_name_fullcompare(search_name, &current_name,
743                                                 &order, &common_labels);
744                 last_compared = current;
745
746                 if (compared == dns_namereln_equal)
747                         break;
748
749                 if (compared == dns_namereln_none) {
750 #ifdef DNS_RBT_USEHASH
751                         dns_name_t hash_name;
752                         dns_rbtnode_t *hnode;
753                         dns_rbtnode_t *up_current;
754                         unsigned int nlabels;
755                         unsigned int tlabels = 1;
756                         unsigned int hash;
757
758                         /*
759                          * If there is no hash table, hashing can't be done.
760                          */
761                         if (rbt->hashtable == NULL)
762                                 goto nohash;
763
764                         /*
765                          * The case of current != current_root, that
766                          * means a left or right pointer was followed,
767                          * only happens when the algorithm fell through to
768                          * the traditional binary search because of a
769                          * bitstring label.  Since we dropped the bitstring
770                          * support, this should not happen.
771                          */
772                         INSIST(current == current_root);
773
774                         nlabels = dns_name_countlabels(search_name);
775
776                         /*
777                          * current_root is the root of the current level, so
778                          * it's parent is the same as it's "up" pointer.
779                          */
780                         up_current = PARENT(current_root);
781                         dns_name_init(&hash_name, NULL);
782
783                 hashagain:
784                         /*
785                          * Hash includes tail.
786                          */
787                         dns_name_getlabelsequence(name,
788                                                   nlabels - tlabels,
789                                                   hlabels + tlabels,
790                                                   &hash_name);
791                         hash = dns_name_fullhash(&hash_name, ISC_FALSE);
792                         dns_name_getlabelsequence(search_name,
793                                                   nlabels - tlabels,
794                                                   tlabels, &hash_name);
795
796                         for (hnode = rbt->hashtable[hash % rbt->hashsize];
797                              hnode != NULL;
798                              hnode = hnode->hashnext)
799                         {
800                                 dns_name_t hnode_name;
801
802                                 if (hash != HASHVAL(hnode))
803                                         continue;
804                                 if (find_up(hnode) != up_current)
805                                         continue;
806                                 dns_name_init(&hnode_name, NULL);
807                                 NODENAME(hnode, &hnode_name);
808                                 if (dns_name_equal(&hnode_name, &hash_name))
809                                         break;
810                         }
811
812                         if (hnode != NULL) {
813                                 current = hnode;
814                                 /*
815                                  * This is an optimization.  If hashing found
816                                  * the right node, the next call to
817                                  * dns_name_fullcompare() would obviously
818                                  * return _equal or _subdomain.  Determine
819                                  * which of those would be the case by
820                                  * checking if the full name was hashed.  Then
821                                  * make it look like dns_name_fullcompare
822                                  * was called and jump to the right place.
823                                  */
824                                 if (tlabels == nlabels) {
825                                         compared = dns_namereln_equal;
826                                         break;
827                                 } else {
828                                         common_labels = tlabels;
829                                         compared = dns_namereln_subdomain;
830                                         goto subdomain;
831                                 }
832                         }
833
834                         if (tlabels++ < nlabels)
835                                 goto hashagain;
836
837                         /*
838                          * All of the labels have been tried against the hash
839                          * table.  Since we dropped the support of bitstring
840                          * labels, the name isn't in the table.
841                          */
842                         current = NULL;
843                         continue;
844
845                 nohash:
846 #endif /* DNS_RBT_USEHASH */
847                         /*
848                          * Standard binary search tree movement.
849                          */
850                         if (order < 0)
851                                 current = LEFT(current);
852                         else
853                                 current = RIGHT(current);
854
855                 } else {
856                         /*
857                          * The names have some common suffix labels.
858                          *
859                          * If the number in common are equal in length to
860                          * the current node's name length, then follow the
861                          * down pointer and search in the new tree.
862                          */
863                         if (compared == dns_namereln_subdomain) {
864                 subdomain:
865                                 /*
866                                  * Whack off the current node's common parts
867                                  * for the name to search in the next level.
868                                  */
869                                 dns_name_split(search_name, common_labels,
870                                                search_name, NULL);
871                                 hlabels += common_labels;
872                                 /*
873                                  * This might be the closest enclosing name.
874                                  */
875                                 if (DATA(current) != NULL ||
876                                     (options & DNS_RBTFIND_EMPTYDATA) != 0)
877                                         *node = current;
878
879                                 /*
880                                  * Point the chain to the next level.   This
881                                  * needs to be done before 'current' is pointed
882                                  * there because the callback in the next
883                                  * block of code needs the current 'current',
884                                  * but in the event the callback requests that
885                                  * the search be stopped then the
886                                  * DNS_R_PARTIALMATCH code at the end of this
887                                  * function needs the chain pointed to the
888                                  * next level.
889                                  */
890                                 ADD_LEVEL(chain, current);
891
892                                 /*
893                                  * The caller may want to interrupt the
894                                  * downward search when certain special nodes
895                                  * are traversed.  If this is a special node,
896                                  * the callback is used to learn what the
897                                  * caller wants to do.
898                                  */
899                                 if (callback != NULL &&
900                                     FINDCALLBACK(current)) {
901                                         result = chain_name(chain,
902                                                             callback_name,
903                                                             ISC_FALSE);
904                                         if (result != ISC_R_SUCCESS) {
905                                                 dns_rbtnodechain_reset(chain);
906                                                 return (result);
907                                         }
908
909                                         result = (callback)(current,
910                                                             callback_name,
911                                                             callback_arg);
912                                         if (result != DNS_R_CONTINUE) {
913                                                 saved_result = result;
914                                                 /*
915                                                  * Treat this node as if it
916                                                  * had no down pointer.
917                                                  */
918                                                 current = NULL;
919                                                 break;
920                                         }
921                                 }
922
923                                 /*
924                                  * Finally, head to the next tree level.
925                                  */
926                                 current = DOWN(current);
927                                 current_root = current;
928
929                         } else {
930                                 /*
931                                  * Though there are labels in common, the
932                                  * entire name at this node is not common
933                                  * with the search name so the search
934                                  * name does not exist in the tree.
935                                  */
936                                 INSIST(compared == dns_namereln_commonancestor
937                                        || compared == dns_namereln_contains);
938
939                                 current = NULL;
940                         }
941                 }
942         }
943
944         /*
945          * If current is not NULL, NOEXACT is not disallowing exact matches,
946          * and either the node has data or an empty node is ok, return
947          * ISC_R_SUCCESS to indicate an exact match.
948          */
949         if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
950             (DATA(current) != NULL ||
951              (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
952                 /*
953                  * Found an exact match.
954                  */
955                 chain->end = current;
956                 chain->level_matches = chain->level_count;
957
958                 if (foundname != NULL)
959                         result = chain_name(chain, foundname, ISC_TRUE);
960                 else
961                         result = ISC_R_SUCCESS;
962
963                 if (result == ISC_R_SUCCESS) {
964                         *node = current;
965                         result = saved_result;
966                 } else
967                         *node = NULL;
968         } else {
969                 /*
970                  * Did not find an exact match (or did not want one).
971                  */
972                 if (*node != NULL) {
973                         /*
974                          * ... but found a partially matching superdomain.
975                          * Unwind the chain to the partial match node
976                          * to set level_matches to the level above the node,
977                          * and then to derive the name.
978                          *
979                          * chain->level_count is guaranteed to be at least 1
980                          * here because by definition of finding a superdomain,
981                          * the chain is pointed to at least the first subtree.
982                          */
983                         chain->level_matches = chain->level_count - 1;
984
985                         while (chain->levels[chain->level_matches] != *node) {
986                                 INSIST(chain->level_matches > 0);
987                                 chain->level_matches--;
988                         }
989
990                         if (foundname != NULL) {
991                                 unsigned int saved_count = chain->level_count;
992
993                                 chain->level_count = chain->level_matches + 1;
994
995                                 result = chain_name(chain, foundname,
996                                                     ISC_FALSE);
997
998                                 chain->level_count = saved_count;
999                         } else
1000                                 result = ISC_R_SUCCESS;
1001
1002                         if (result == ISC_R_SUCCESS)
1003                                 result = DNS_R_PARTIALMATCH;
1004
1005                 } else
1006                         result = ISC_R_NOTFOUND;
1007
1008                 if (current != NULL) {
1009                         /*
1010                          * There was an exact match but either
1011                          * DNS_RBTFIND_NOEXACT was set, or
1012                          * DNS_RBTFIND_EMPTYDATA was set and the node had no
1013                          * data.  A policy decision was made to set the
1014                          * chain to the exact match, but this is subject
1015                          * to change if it becomes apparent that something
1016                          * else would be more useful.  It is important that
1017                          * this case is handled here, because the predecessor
1018                          * setting code below assumes the match was not exact.
1019                          */
1020                         INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
1021                                ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
1022                                 DATA(current) == NULL));
1023                         chain->end = current;
1024
1025                 } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
1026                         /*
1027                          * Ensure the chain points nowhere.
1028                          */
1029                         chain->end = NULL;
1030
1031                 } else {
1032                         /*
1033                          * Since there was no exact match, the chain argument
1034                          * needs to be pointed at the DNSSEC predecessor of
1035                          * the search name.
1036                          */
1037                         if (compared == dns_namereln_subdomain) {
1038                                 /*
1039                                  * Attempted to follow a down pointer that was
1040                                  * NULL, which means the searched for name was
1041                                  * a subdomain of a terminal name in the tree.
1042                                  * Since there are no existing subdomains to
1043                                  * order against, the terminal name is the
1044                                  * predecessor.
1045                                  */
1046                                 INSIST(chain->level_count > 0);
1047                                 INSIST(chain->level_matches <
1048                                        chain->level_count);
1049                                 chain->end =
1050                                         chain->levels[--chain->level_count];
1051
1052                         } else {
1053                                 isc_result_t result2;
1054
1055                                 /*
1056                                  * Point current to the node that stopped
1057                                  * the search.
1058                                  *
1059                                  * With the hashing modification that has been
1060                                  * added to the algorithm, the stop node of a
1061                                  * standard binary search is not known.  So it
1062                                  * has to be found.  There is probably a more
1063                                  * clever way of doing this.
1064                                  *
1065                                  * The assignment of current to NULL when
1066                                  * the relationship is *not* dns_namereln_none,
1067                                  * even though it later gets set to the same
1068                                  * last_compared anyway, is simply to not push
1069                                  * the while loop in one more level of
1070                                  * indentation.
1071                                  */
1072                                 if (compared == dns_namereln_none)
1073                                         current = last_compared;
1074                                 else
1075                                         current = NULL;
1076
1077                                 while (current != NULL) {
1078                                         NODENAME(current, &current_name);
1079                                         compared = dns_name_fullcompare(
1080                                                                 search_name,
1081                                                                 &current_name,
1082                                                                 &order,
1083                                                                 &common_labels);
1084
1085                                         last_compared = current;
1086
1087                                         /*
1088                                          * Standard binary search movement.
1089                                          */
1090                                         if (order < 0)
1091                                                 current = LEFT(current);
1092                                         else
1093                                                 current = RIGHT(current);
1094
1095                                 }
1096
1097                                 current = last_compared;
1098
1099                                 /*
1100                                  * Reached a point within a level tree that
1101                                  * positively indicates the name is not
1102                                  * present, but the stop node could be either
1103                                  * less than the desired name (order > 0) or
1104                                  * greater than the desired name (order < 0).
1105                                  *
1106                                  * If the stop node is less, it is not
1107                                  * necessarily the predecessor.  If the stop
1108                                  * node has a down pointer, then the real
1109                                  * predecessor is at the end of a level below
1110                                  * (not necessarily the next level).
1111                                  * Move down levels until the rightmost node
1112                                  * does not have a down pointer.
1113                                  *
1114                                  * When the stop node is greater, it is
1115                                  * the successor.  All the logic for finding
1116                                  * the predecessor is handily encapsulated
1117                                  * in dns_rbtnodechain_prev.  In the event
1118                                  * that the search name is less than anything
1119                                  * else in the tree, the chain is reset.
1120                                  * XXX DCL What is the best way for the caller
1121                                  *         to know that the search name has
1122                                  *         no predecessor?
1123                                  */
1124
1125
1126                                 if (order > 0) {
1127                                         if (DOWN(current) != NULL) {
1128                                                 ADD_LEVEL(chain, current);
1129
1130                                                 result2 =
1131                                                       move_chain_to_last(chain,
1132                                                                 DOWN(current));
1133
1134                                                 if (result2 != ISC_R_SUCCESS)
1135                                                         result = result2;
1136                                         } else
1137                                                 /*
1138                                                  * Ah, the pure and simple
1139                                                  * case.  The stop node is the
1140                                                  * predecessor.
1141                                                  */
1142                                                 chain->end = current;
1143
1144                                 } else {
1145                                         INSIST(order < 0);
1146
1147                                         chain->end = current;
1148
1149                                         result2 = dns_rbtnodechain_prev(chain,
1150                                                                         NULL,
1151                                                                         NULL);
1152                                         if (result2 == ISC_R_SUCCESS ||
1153                                             result2 == DNS_R_NEWORIGIN)
1154                                                 ;       /* Nothing. */
1155                                         else if (result2 == ISC_R_NOMORE)
1156                                                 /*
1157                                                  * There is no predecessor.
1158                                                  */
1159                                                 dns_rbtnodechain_reset(chain);
1160                                         else
1161                                                 result = result2;
1162                                 }
1163
1164                         }
1165                 }
1166         }
1167
1168         ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
1169
1170         return (result);
1171 }
1172
1173 /*
1174  * Get the data pointer associated with 'name'.
1175  */
1176 isc_result_t
1177 dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
1178                  dns_name_t *foundname, void **data) {
1179         dns_rbtnode_t *node = NULL;
1180         isc_result_t result;
1181
1182         REQUIRE(data != NULL && *data == NULL);
1183
1184         result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
1185                                   options, NULL, NULL);
1186
1187         if (node != NULL &&
1188             (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
1189                 *data = DATA(node);
1190         else
1191                 result = ISC_R_NOTFOUND;
1192
1193         return (result);
1194 }
1195
1196 /*
1197  * Delete a name from the tree of trees.
1198  */
1199 isc_result_t
1200 dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
1201         dns_rbtnode_t *node = NULL;
1202         isc_result_t result;
1203
1204         REQUIRE(VALID_RBT(rbt));
1205         REQUIRE(dns_name_isabsolute(name));
1206
1207         /*
1208          * First, find the node.
1209          *
1210          * When searching, the name might not have an exact match:
1211          * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
1212          * elements of a tree, which would make layer 1 a single
1213          * node tree of "b.a.com" and layer 2 a three node tree of
1214          * a, b, and c.  Deleting a.com would find only a partial depth
1215          * match in the first layer.  Should it be a requirement that
1216          * that the name to be deleted have data?  For now, it is.
1217          *
1218          * ->dirty, ->locknum and ->references are ignored; they are
1219          * solely the province of rbtdb.c.
1220          */
1221         result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
1222                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
1223
1224         if (result == ISC_R_SUCCESS) {
1225                 if (DATA(node) != NULL)
1226                         result = dns_rbt_deletenode(rbt, node, recurse);
1227                 else
1228                         result = ISC_R_NOTFOUND;
1229
1230         } else if (result == DNS_R_PARTIALMATCH)
1231                 result = ISC_R_NOTFOUND;
1232
1233         return (result);
1234 }
1235
1236 /*
1237  * Remove a node from the tree of trees.
1238  *
1239  * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
1240  * a sequence of additions to be deletions will not generally get the
1241  * tree back to the state it started in.  For example, if the addition
1242  * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
1243  * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
1244  * restoring "a.b.c".  The RBT *used* to do this kind of rejoining, but it
1245  * turned out to be a bad idea because it could corrupt an active nodechain
1246  * that had "b.c" as one of its levels -- and the RBT has no idea what
1247  * nodechains are in use by callers, so it can't even *try* to helpfully
1248  * fix them up (which would probably be doomed to failure anyway).
1249  *
1250  * Similarly, it is possible to leave the tree in a state where a supposedly
1251  * deleted node still exists.  The first case of this is obvious; take
1252  * the tree which has "b.c" on one level, pointing to "a".  Now deleted "b.c".
1253  * It was just established in the previous paragraph why we can't pull "a"
1254  * back up to its parent level.  But what happens when "a" then gets deleted?
1255  * "b.c" is left hanging around without data or children.  This condition
1256  * is actually pretty easy to detect, but ... should it really be removed?
1257  * Is a chain pointing to it?  An iterator?  Who knows!  (Note that the
1258  * references structure member cannot be looked at because it is private to
1259  * rbtdb.)  This is ugly and makes me unhappy, but after hours of trying to
1260  * make it more aesthetically proper and getting nowhere, this is the way it
1261  * is going to stay until such time as it proves to be a *real* problem.
1262  *
1263  * Finally, for reference, note that the original routine that did node
1264  * joining was called join_nodes().  It has been excised, living now only
1265  * in the CVS history, but comments have been left behind that point to it just
1266  * in case someone wants to muck with this some more.
1267  *
1268  * The one positive aspect of all of this is that joining used to have a
1269  * case where it might fail.  Without trying to join, now this function always
1270  * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
1271  */
1272 isc_result_t
1273 dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
1274 {
1275         dns_rbtnode_t *parent;
1276
1277         REQUIRE(VALID_RBT(rbt));
1278         REQUIRE(DNS_RBTNODE_VALID(node));
1279
1280         if (DOWN(node) != NULL) {
1281                 if (recurse)
1282                         RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node))
1283                                       == ISC_R_SUCCESS);
1284                 else {
1285                         if (DATA(node) != NULL && rbt->data_deleter != NULL)
1286                                 rbt->data_deleter(DATA(node), rbt->deleter_arg);
1287                         DATA(node) = NULL;
1288
1289                         /*
1290                          * Since there is at least one node below this one and
1291                          * no recursion was requested, the deletion is
1292                          * complete.  The down node from this node might be all
1293                          * by itself on a single level, so join_nodes() could
1294                          * be used to collapse the tree (with all the caveats
1295                          * of the comment at the start of this function).
1296                          */
1297                         return (ISC_R_SUCCESS);
1298                 }
1299         }
1300
1301         /*
1302          * Note the node that points to the level of the node that is being
1303          * deleted.  If the deleted node is the top level, parent will be set
1304          * to NULL.
1305          */
1306         parent = find_up(node);
1307
1308         /*
1309          * This node now has no down pointer (either because it didn't
1310          * have one to start, or because it was recursively removed).
1311          * So now the node needs to be removed from this level.
1312          */
1313         dns_rbt_deletefromlevel(node, parent == NULL ? &rbt->root :
1314                                                        &DOWN(parent));
1315
1316         if (DATA(node) != NULL && rbt->data_deleter != NULL)
1317                 rbt->data_deleter(DATA(node), rbt->deleter_arg);
1318
1319         unhash_node(rbt, node);
1320 #if DNS_RBT_USEMAGIC
1321         node->magic = 0;
1322 #endif
1323         dns_rbtnode_refdestroy(node);
1324         isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
1325         rbt->nodecount--;
1326
1327         /*
1328          * There are now two special cases that can exist that would
1329          * not have existed if the tree had been created using only
1330          * the names that now exist in it.  (This is all related to
1331          * join_nodes() as described in this function's introductory comment.)
1332          * Both cases exist when the deleted node's parent (the node
1333          * that pointed to the deleted node's level) is not null but
1334          * it has no data:  parent != NULL && DATA(parent) == NULL.
1335          *
1336          * The first case is that the deleted node was the last on its level:
1337          * DOWN(parent) == NULL.  This case can only exist if the parent was
1338          * previously deleted -- and so now, apparently, the parent should go
1339          * away.  That can't be done though because there might be external
1340          * references to it, such as through a nodechain.
1341          *
1342          * The other case also involves a parent with no data, but with the
1343          * deleted node being the next-to-last node instead of the last:
1344          * LEFT(DOWN(parent)) == NULL && RIGHT(DOWN(parent)) == NULL.
1345          * Presumably now the remaining node on the level should be joined
1346          * with the parent, but it's already been described why that can't be
1347          * done.
1348          */
1349
1350         /*
1351          * This function never fails.
1352          */
1353         return (ISC_R_SUCCESS);
1354 }
1355
1356 void
1357 dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
1358
1359         REQUIRE(DNS_RBTNODE_VALID(node));
1360         REQUIRE(name != NULL);
1361         REQUIRE(name->offsets == NULL);
1362
1363         NODENAME(node, name);
1364 }
1365
1366 isc_result_t
1367 dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
1368         dns_name_t current;
1369         isc_result_t result;
1370
1371         REQUIRE(DNS_RBTNODE_VALID(node));
1372         REQUIRE(name != NULL);
1373         REQUIRE(name->buffer != NULL);
1374
1375         dns_name_init(&current, NULL);
1376         dns_name_reset(name);
1377
1378         do {
1379                 INSIST(node != NULL);
1380
1381                 NODENAME(node, &current);
1382
1383                 result = dns_name_concatenate(name, &current, name, NULL);
1384                 if (result != ISC_R_SUCCESS)
1385                         break;
1386
1387                 node = find_up(node);
1388         } while (! dns_name_isabsolute(name));
1389
1390         return (result);
1391 }
1392
1393 char *
1394 dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
1395 {
1396         dns_fixedname_t fixedname;
1397         dns_name_t *name;
1398         isc_result_t result;
1399
1400         REQUIRE(DNS_RBTNODE_VALID(node));
1401         REQUIRE(printname != NULL);
1402
1403         dns_fixedname_init(&fixedname);
1404         name = dns_fixedname_name(&fixedname);
1405         result = dns_rbt_fullnamefromnode(node, name);
1406         if (result == ISC_R_SUCCESS)
1407                 dns_name_format(name, printname, size);
1408         else
1409                 snprintf(printname, size, "<error building name: %s>",
1410                          dns_result_totext(result));
1411
1412         return (printname);
1413 }
1414
1415 static isc_result_t
1416 create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
1417         dns_rbtnode_t *node;
1418         isc_region_t region;
1419         unsigned int labels;
1420
1421         REQUIRE(name->offsets != NULL);
1422
1423         dns_name_toregion(name, &region);
1424         labels = dns_name_countlabels(name);
1425         ENSURE(labels > 0);
1426
1427         /*
1428          * Allocate space for the node structure, the name, and the offsets.
1429          */
1430         node = (dns_rbtnode_t *)isc_mem_get(mctx, sizeof(*node) +
1431                                             region.length + labels + 1);
1432
1433         if (node == NULL)
1434                 return (ISC_R_NOMEMORY);
1435
1436         node->is_root = 0;
1437         PARENT(node) = NULL;
1438         RIGHT(node) = NULL;
1439         LEFT(node) = NULL;
1440         DOWN(node) = NULL;
1441         DATA(node) = NULL;
1442 #ifdef DNS_RBT_USEHASH
1443         HASHNEXT(node) = NULL;
1444         HASHVAL(node) = 0;
1445 #endif
1446
1447         ISC_LINK_INIT(node, deadlink);
1448
1449         LOCKNUM(node) = 0;
1450         WILD(node) = 0;
1451         DIRTY(node) = 0;
1452         dns_rbtnode_refinit(node, 0);
1453         node->find_callback = 0;
1454         node->nsec3 = 0;
1455
1456         MAKE_BLACK(node);
1457
1458         /*
1459          * The following is stored to make reconstructing a name from the
1460          * stored value in the node easy:  the length of the name, the number
1461          * of labels, whether the name is absolute or not, the name itself,
1462          * and the name's offsets table.
1463          *
1464          * XXX RTH
1465          *      The offsets table could be made smaller by eliminating the
1466          *      first offset, which is always 0.  This requires changes to
1467          *      lib/dns/name.c.
1468          *
1469          * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
1470          *       as it uses OLDNAMELEN.
1471          */
1472         OLDNAMELEN(node) = NAMELEN(node) = region.length;
1473         OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
1474         ATTRS(node) = name->attributes;
1475
1476         memcpy(NAME(node), region.base, region.length);
1477         memcpy(OFFSETS(node), name->offsets, labels);
1478
1479 #if DNS_RBT_USEMAGIC
1480         node->magic = DNS_RBTNODE_MAGIC;
1481 #endif
1482         *nodep = node;
1483
1484         return (ISC_R_SUCCESS);
1485 }
1486
1487 #ifdef DNS_RBT_USEHASH
1488 static inline void
1489 hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
1490         unsigned int hash;
1491
1492         HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
1493
1494         hash = HASHVAL(node) % rbt->hashsize;
1495         HASHNEXT(node) = rbt->hashtable[hash];
1496
1497         rbt->hashtable[hash] = node;
1498 }
1499
1500 static isc_result_t
1501 inithash(dns_rbt_t *rbt) {
1502         unsigned int bytes;
1503
1504         rbt->hashsize = RBT_HASH_SIZE;
1505         bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
1506         rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
1507
1508         if (rbt->hashtable == NULL)
1509                 return (ISC_R_NOMEMORY);
1510
1511         memset(rbt->hashtable, 0, bytes);
1512
1513         return (ISC_R_SUCCESS);
1514 }
1515
1516 static void
1517 rehash(dns_rbt_t *rbt) {
1518         unsigned int oldsize;
1519         dns_rbtnode_t **oldtable;
1520         dns_rbtnode_t *node;
1521         unsigned int hash;
1522         unsigned int i;
1523
1524         oldsize = rbt->hashsize;
1525         oldtable = rbt->hashtable;
1526         rbt->hashsize *= 2 + 1;
1527         rbt->hashtable = isc_mem_get(rbt->mctx,
1528                                      rbt->hashsize * sizeof(dns_rbtnode_t *));
1529         if (rbt->hashtable == NULL) {
1530                 rbt->hashtable = oldtable;
1531                 rbt->hashsize = oldsize;
1532                 return;
1533         }
1534
1535         for (i = 0; i < rbt->hashsize; i++)
1536                 rbt->hashtable[i] = NULL;
1537
1538         for (i = 0; i < oldsize; i++) {
1539                 node = oldtable[i];
1540                 while (node != NULL) {
1541                         hash = HASHVAL(node) % rbt->hashsize;
1542                         oldtable[i] = HASHNEXT(node);
1543                         HASHNEXT(node) = rbt->hashtable[hash];
1544                         rbt->hashtable[hash] = node;
1545                         node = oldtable[i];
1546                 }
1547         }
1548
1549         isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
1550 }
1551
1552 static inline void
1553 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
1554
1555         REQUIRE(DNS_RBTNODE_VALID(node));
1556
1557         if (rbt->nodecount >= (rbt->hashsize *3))
1558                 rehash(rbt);
1559
1560         hash_add_node(rbt, node, name);
1561 }
1562
1563 static inline void
1564 unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
1565         unsigned int bucket;
1566         dns_rbtnode_t *bucket_node;
1567
1568         REQUIRE(DNS_RBTNODE_VALID(node));
1569
1570         if (rbt->hashtable != NULL) {
1571                 bucket = HASHVAL(node) % rbt->hashsize;
1572                 bucket_node = rbt->hashtable[bucket];
1573
1574                 if (bucket_node == node)
1575                         rbt->hashtable[bucket] = HASHNEXT(node);
1576                 else {
1577                         while (HASHNEXT(bucket_node) != node) {
1578                                 INSIST(HASHNEXT(bucket_node) != NULL);
1579                                 bucket_node = HASHNEXT(bucket_node);
1580                         }
1581                         HASHNEXT(bucket_node) = HASHNEXT(node);
1582                 }
1583         }
1584 }
1585 #endif /* DNS_RBT_USEHASH */
1586
1587 static inline void
1588 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
1589         dns_rbtnode_t *child;
1590
1591         REQUIRE(DNS_RBTNODE_VALID(node));
1592         REQUIRE(rootp != NULL);
1593
1594         child = RIGHT(node);
1595         INSIST(child != NULL);
1596
1597         RIGHT(node) = LEFT(child);
1598         if (LEFT(child) != NULL)
1599                 PARENT(LEFT(child)) = node;
1600         LEFT(child) = node;
1601
1602         if (child != NULL)
1603                 PARENT(child) = PARENT(node);
1604
1605         if (IS_ROOT(node)) {
1606                 *rootp = child;
1607                 child->is_root = 1;
1608                 node->is_root = 0;
1609
1610         } else {
1611                 if (LEFT(PARENT(node)) == node)
1612                         LEFT(PARENT(node)) = child;
1613                 else
1614                         RIGHT(PARENT(node)) = child;
1615         }
1616
1617         PARENT(node) = child;
1618 }
1619
1620 static inline void
1621 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
1622         dns_rbtnode_t *child;
1623
1624         REQUIRE(DNS_RBTNODE_VALID(node));
1625         REQUIRE(rootp != NULL);
1626
1627         child = LEFT(node);
1628         INSIST(child != NULL);
1629
1630         LEFT(node) = RIGHT(child);
1631         if (RIGHT(child) != NULL)
1632                 PARENT(RIGHT(child)) = node;
1633         RIGHT(child) = node;
1634
1635         if (child != NULL)
1636                 PARENT(child) = PARENT(node);
1637
1638         if (IS_ROOT(node)) {
1639                 *rootp = child;
1640                 child->is_root = 1;
1641                 node->is_root = 0;
1642
1643         } else {
1644                 if (LEFT(PARENT(node)) == node)
1645                         LEFT(PARENT(node)) = child;
1646                 else
1647                         RIGHT(PARENT(node)) = child;
1648         }
1649
1650         PARENT(node) = child;
1651 }
1652
1653 /*
1654  * This is the real workhorse of the insertion code, because it does the
1655  * true red/black tree on a single level.
1656  */
1657 static void
1658 dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
1659                    dns_rbtnode_t **rootp)
1660 {
1661         dns_rbtnode_t *child, *root, *parent, *grandparent;
1662         dns_name_t add_name, current_name;
1663         dns_offsets_t add_offsets, current_offsets;
1664
1665         REQUIRE(rootp != NULL);
1666         REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
1667                 RIGHT(node) == NULL);
1668         REQUIRE(current != NULL);
1669
1670         root = *rootp;
1671         if (root == NULL) {
1672                 /*
1673                  * First node of a level.
1674                  */
1675                 MAKE_BLACK(node);
1676                 node->is_root = 1;
1677                 PARENT(node) = current;
1678                 *rootp = node;
1679                 return;
1680         }
1681
1682         child = root;
1683
1684         dns_name_init(&add_name, add_offsets);
1685         NODENAME(node, &add_name);
1686
1687         dns_name_init(&current_name, current_offsets);
1688         NODENAME(current, &current_name);
1689
1690         if (order < 0) {
1691                 INSIST(LEFT(current) == NULL);
1692                 LEFT(current) = node;
1693         } else {
1694                 INSIST(RIGHT(current) == NULL);
1695                 RIGHT(current) = node;
1696         }
1697
1698         INSIST(PARENT(node) == NULL);
1699         PARENT(node) = current;
1700
1701         MAKE_RED(node);
1702
1703         while (node != root && IS_RED(PARENT(node))) {
1704                 /*
1705                  * XXXDCL could do away with separate parent and grandparent
1706                  * variables.  They are vestiges of the days before parent
1707                  * pointers.  However, they make the code a little clearer.
1708                  */
1709
1710                 parent = PARENT(node);
1711                 grandparent = PARENT(parent);
1712
1713                 if (parent == LEFT(grandparent)) {
1714                         child = RIGHT(grandparent);
1715                         if (child != NULL && IS_RED(child)) {
1716                                 MAKE_BLACK(parent);
1717                                 MAKE_BLACK(child);
1718                                 MAKE_RED(grandparent);
1719                                 node = grandparent;
1720                         } else {
1721                                 if (node == RIGHT(parent)) {
1722                                         rotate_left(parent, &root);
1723                                         node = parent;
1724                                         parent = PARENT(node);
1725                                         grandparent = PARENT(parent);
1726                                 }
1727                                 MAKE_BLACK(parent);
1728                                 MAKE_RED(grandparent);
1729                                 rotate_right(grandparent, &root);
1730                         }
1731                 } else {
1732                         child = LEFT(grandparent);
1733                         if (child != NULL && IS_RED(child)) {
1734                                 MAKE_BLACK(parent);
1735                                 MAKE_BLACK(child);
1736                                 MAKE_RED(grandparent);
1737                                 node = grandparent;
1738                         } else {
1739                                 if (node == LEFT(parent)) {
1740                                         rotate_right(parent, &root);
1741                                         node = parent;
1742                                         parent = PARENT(node);
1743                                         grandparent = PARENT(parent);
1744                                 }
1745                                 MAKE_BLACK(parent);
1746                                 MAKE_RED(grandparent);
1747                                 rotate_left(grandparent, &root);
1748                         }
1749                 }
1750         }
1751
1752         MAKE_BLACK(root);
1753         ENSURE(IS_ROOT(root));
1754         *rootp = root;
1755
1756         return;
1757 }
1758
1759 /*
1760  * This is the real workhorse of the deletion code, because it does the
1761  * true red/black tree on a single level.
1762  */
1763 static void
1764 dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
1765         dns_rbtnode_t *child, *sibling, *parent;
1766         dns_rbtnode_t *successor;
1767
1768         REQUIRE(delete != NULL);
1769
1770         /*
1771          * Verify that the parent history is (apparently) correct.
1772          */
1773         INSIST((IS_ROOT(delete) && *rootp == delete) ||
1774                (! IS_ROOT(delete) &&
1775                 (LEFT(PARENT(delete)) == delete ||
1776                  RIGHT(PARENT(delete)) == delete)));
1777
1778         child = NULL;
1779
1780         if (LEFT(delete) == NULL) {
1781                 if (RIGHT(delete) == NULL) {
1782                         if (IS_ROOT(delete)) {
1783                                 /*
1784                                  * This is the only item in the tree.
1785                                  */
1786                                 *rootp = NULL;
1787                                 return;
1788                         }
1789                 } else
1790                         /*
1791                          * This node has one child, on the right.
1792                          */
1793                         child = RIGHT(delete);
1794
1795         } else if (RIGHT(delete) == NULL)
1796                 /*
1797                  * This node has one child, on the left.
1798                  */
1799                 child = LEFT(delete);
1800         else {
1801                 dns_rbtnode_t holder, *tmp = &holder;
1802
1803                 /*
1804                  * This node has two children, so it cannot be directly
1805                  * deleted.  Find its immediate in-order successor and
1806                  * move it to this location, then do the deletion at the
1807                  * old site of the successor.
1808                  */
1809                 successor = RIGHT(delete);
1810                 while (LEFT(successor) != NULL)
1811                         successor = LEFT(successor);
1812
1813                 /*
1814                  * The successor cannot possibly have a left child;
1815                  * if there is any child, it is on the right.
1816                  */
1817                 if (RIGHT(successor) != NULL)
1818                         child = RIGHT(successor);
1819
1820                 /*
1821                  * Swap the two nodes; it would be simpler to just replace
1822                  * the value being deleted with that of the successor,
1823                  * but this rigamarole is done so the caller has complete
1824                  * control over the pointers (and memory allocation) of
1825                  * all of nodes.  If just the key value were removed from
1826                  * the tree, the pointer to the node would be unchanged.
1827                  */
1828
1829                 /*
1830                  * First, put the successor in the tree location of the
1831                  * node to be deleted.  Save its existing tree pointer
1832                  * information, which will be needed when linking up
1833                  * delete to the successor's old location.
1834                  */
1835                 memcpy(tmp, successor, sizeof(dns_rbtnode_t));
1836
1837                 if (IS_ROOT(delete)) {
1838                         *rootp = successor;
1839                         successor->is_root = ISC_TRUE;
1840                         delete->is_root = ISC_FALSE;
1841
1842                 } else
1843                         if (LEFT(PARENT(delete)) == delete)
1844                                 LEFT(PARENT(delete)) = successor;
1845                         else
1846                                 RIGHT(PARENT(delete)) = successor;
1847
1848                 PARENT(successor) = PARENT(delete);
1849                 LEFT(successor)   = LEFT(delete);
1850                 RIGHT(successor)  = RIGHT(delete);
1851                 COLOR(successor)  = COLOR(delete);
1852
1853                 if (LEFT(successor) != NULL)
1854                         PARENT(LEFT(successor)) = successor;
1855                 if (RIGHT(successor) != successor)
1856                         PARENT(RIGHT(successor)) = successor;
1857
1858                 /*
1859                  * Now relink the node to be deleted into the
1860                  * successor's previous tree location.  PARENT(tmp)
1861                  * is the successor's original parent.
1862                  */
1863                 INSIST(! IS_ROOT(delete));
1864
1865                 if (PARENT(tmp) == delete) {
1866                         /*
1867                          * Node being deleted was successor's parent.
1868                          */
1869                         RIGHT(successor) = delete;
1870                         PARENT(delete) = successor;
1871
1872                 } else {
1873                         LEFT(PARENT(tmp)) = delete;
1874                         PARENT(delete) = PARENT(tmp);
1875                 }
1876
1877                 /*
1878                  * Original location of successor node has no left.
1879                  */
1880                 LEFT(delete)   = NULL;
1881                 RIGHT(delete)  = RIGHT(tmp);
1882                 COLOR(delete)  = COLOR(tmp);
1883         }
1884
1885         /*
1886          * Remove the node by removing the links from its parent.
1887          */
1888         if (! IS_ROOT(delete)) {
1889                 if (LEFT(PARENT(delete)) == delete)
1890                         LEFT(PARENT(delete)) = child;
1891                 else
1892                         RIGHT(PARENT(delete)) = child;
1893
1894                 if (child != NULL)
1895                         PARENT(child) = PARENT(delete);
1896
1897         } else {
1898                 /*
1899                  * This is the root being deleted, and at this point
1900                  * it is known to have just one child.
1901                  */
1902                 *rootp = child;
1903                 child->is_root = 1;
1904                 PARENT(child) = PARENT(delete);
1905         }
1906
1907         /*
1908          * Fix color violations.
1909          */
1910         if (IS_BLACK(delete)) {
1911                 parent = PARENT(delete);
1912
1913                 while (child != *rootp && IS_BLACK(child)) {
1914                         INSIST(child == NULL || ! IS_ROOT(child));
1915
1916                         if (LEFT(parent) == child) {
1917                                 sibling = RIGHT(parent);
1918
1919                                 if (IS_RED(sibling)) {
1920                                         MAKE_BLACK(sibling);
1921                                         MAKE_RED(parent);
1922                                         rotate_left(parent, rootp);
1923                                         sibling = RIGHT(parent);
1924                                 }
1925
1926                                 if (IS_BLACK(LEFT(sibling)) &&
1927                                     IS_BLACK(RIGHT(sibling))) {
1928                                         MAKE_RED(sibling);
1929                                         child = parent;
1930
1931                                 } else {
1932
1933                                         if (IS_BLACK(RIGHT(sibling))) {
1934                                                 MAKE_BLACK(LEFT(sibling));
1935                                                 MAKE_RED(sibling);
1936                                                 rotate_right(sibling, rootp);
1937                                                 sibling = RIGHT(parent);
1938                                         }
1939
1940                                         COLOR(sibling) = COLOR(parent);
1941                                         MAKE_BLACK(parent);
1942                                         MAKE_BLACK(RIGHT(sibling));
1943                                         rotate_left(parent, rootp);
1944                                         child = *rootp;
1945                                 }
1946
1947                         } else {
1948                                 /*
1949                                  * Child is parent's right child.
1950                                  * Everything is done the same as above,
1951                                  * except mirrored.
1952                                  */
1953                                 sibling = LEFT(parent);
1954
1955                                 if (IS_RED(sibling)) {
1956                                         MAKE_BLACK(sibling);
1957                                         MAKE_RED(parent);
1958                                         rotate_right(parent, rootp);
1959                                         sibling = LEFT(parent);
1960                                 }
1961
1962                                 if (IS_BLACK(LEFT(sibling)) &&
1963                                     IS_BLACK(RIGHT(sibling))) {
1964                                         MAKE_RED(sibling);
1965                                         child = parent;
1966
1967                                 } else {
1968                                         if (IS_BLACK(LEFT(sibling))) {
1969                                                 MAKE_BLACK(RIGHT(sibling));
1970                                                 MAKE_RED(sibling);
1971                                                 rotate_left(sibling, rootp);
1972                                                 sibling = LEFT(parent);
1973                                         }
1974
1975                                         COLOR(sibling) = COLOR(parent);
1976                                         MAKE_BLACK(parent);
1977                                         MAKE_BLACK(LEFT(sibling));
1978                                         rotate_right(parent, rootp);
1979                                         child = *rootp;
1980                                 }
1981                         }
1982
1983                         parent = PARENT(child);
1984                 }
1985
1986                 if (IS_RED(child))
1987                         MAKE_BLACK(child);
1988         }
1989 }
1990
1991 /*
1992  * This should only be used on the root of a tree, because no color fixup
1993  * is done at all.
1994  *
1995  * NOTE: No root pointer maintenance is done, because the function is only
1996  * used for two cases:
1997  * + deleting everything DOWN from a node that is itself being deleted, and
1998  * + deleting the entire tree of trees from dns_rbt_destroy.
1999  * In each case, the root pointer is no longer relevant, so there
2000  * is no need for a root parameter to this function.
2001  *
2002  * If the function is ever intended to be used to delete something where
2003  * a pointer needs to be told that this tree no longer exists,
2004  * this function would need to adjusted accordingly.
2005  */
2006 static isc_result_t
2007 dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
2008         isc_result_t result = ISC_R_SUCCESS;
2009         REQUIRE(VALID_RBT(rbt));
2010
2011         if (node == NULL)
2012                 return (result);
2013
2014         if (LEFT(node) != NULL) {
2015                 result = dns_rbt_deletetree(rbt, LEFT(node));
2016                 if (result != ISC_R_SUCCESS)
2017                         goto done;
2018                 LEFT(node) = NULL;
2019         }
2020         if (RIGHT(node) != NULL) {
2021                 result = dns_rbt_deletetree(rbt, RIGHT(node));
2022                 if (result != ISC_R_SUCCESS)
2023                         goto done;
2024                 RIGHT(node) = NULL;
2025         }
2026         if (DOWN(node) != NULL) {
2027                 result = dns_rbt_deletetree(rbt, DOWN(node));
2028                 if (result != ISC_R_SUCCESS)
2029                         goto done;
2030                 DOWN(node) = NULL;
2031         }
2032  done:
2033         if (result != ISC_R_SUCCESS)
2034                 return (result);
2035
2036         if (DATA(node) != NULL && rbt->data_deleter != NULL)
2037                 rbt->data_deleter(DATA(node), rbt->deleter_arg);
2038
2039         unhash_node(rbt, node);
2040 #if DNS_RBT_USEMAGIC
2041         node->magic = 0;
2042 #endif
2043
2044         isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
2045         rbt->nodecount--;
2046         return (result);
2047 }
2048
2049 static void
2050 dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
2051                        dns_rbtnode_t **nodep)
2052 {
2053         dns_rbtnode_t *parent;
2054         dns_rbtnode_t *node = *nodep;
2055         REQUIRE(VALID_RBT(rbt));
2056
2057  again:
2058         if (node == NULL) {
2059                 *nodep = NULL;
2060                 return;
2061         }
2062
2063  traverse:
2064         if (LEFT(node) != NULL) {
2065                 node = LEFT(node);
2066                 goto traverse;
2067         }
2068         if (DOWN(node) != NULL) {
2069                 node = DOWN(node);
2070                 goto traverse;
2071         }
2072
2073         if (DATA(node) != NULL && rbt->data_deleter != NULL)
2074                 rbt->data_deleter(DATA(node), rbt->deleter_arg);
2075
2076         /*
2077          * Note: we don't call unhash_node() here as we are destroying
2078          * the complete rbt tree.
2079          */
2080 #if DNS_RBT_USEMAGIC
2081         node->magic = 0;
2082 #endif
2083         parent = PARENT(node);
2084         if (RIGHT(node) != NULL)
2085                 PARENT(RIGHT(node)) = parent;
2086         if (parent != NULL) {
2087                 if (LEFT(parent) == node)
2088                         LEFT(parent) = RIGHT(node);
2089                 else if (DOWN(parent) == node)
2090                         DOWN(parent) = RIGHT(node);
2091         } else
2092                 parent = RIGHT(node);
2093
2094         isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
2095         rbt->nodecount--;
2096         node = parent;
2097         if (quantum != 0 && --quantum == 0) {
2098                 *nodep = node;
2099                 return;
2100         }
2101         goto again;
2102 }
2103
2104 static void
2105 dns_rbt_indent(int depth) {
2106         int i;
2107
2108         for (i = 0; i < depth; i++)
2109                 putchar('\t');
2110 }
2111
2112 static void
2113 dns_rbt_printnodename(dns_rbtnode_t *node) {
2114         isc_region_t r;
2115         dns_name_t name;
2116         char buffer[DNS_NAME_FORMATSIZE];
2117         dns_offsets_t offsets;
2118
2119         r.length = NAMELEN(node);
2120         r.base = NAME(node);
2121
2122         dns_name_init(&name, offsets);
2123         dns_name_fromregion(&name, &r);
2124
2125         dns_name_format(&name, buffer, sizeof(buffer));
2126
2127         printf("%s", buffer);
2128 }
2129
2130 static void
2131 dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) {
2132         dns_rbt_indent(depth);
2133
2134         if (root != NULL) {
2135                 dns_rbt_printnodename(root);
2136                 printf(" (%s", IS_RED(root) ? "RED" : "black");
2137                 if (parent) {
2138                         printf(" from ");
2139                         dns_rbt_printnodename(parent);
2140                 }
2141
2142                 if ((! IS_ROOT(root) && PARENT(root) != parent) ||
2143                     (  IS_ROOT(root) && depth > 0 &&
2144                        DOWN(PARENT(root)) != root)) {
2145
2146                         printf(" (BAD parent pointer! -> ");
2147                         if (PARENT(root) != NULL)
2148                                 dns_rbt_printnodename(PARENT(root));
2149                         else
2150                                 printf("NULL");
2151                         printf(")");
2152                 }
2153
2154                 printf(")\n");
2155
2156
2157                 depth++;
2158
2159                 if (DOWN(root)) {
2160                         dns_rbt_indent(depth);
2161                         printf("++ BEG down from ");
2162                         dns_rbt_printnodename(root);
2163                         printf("\n");
2164                         dns_rbt_printtree(DOWN(root), NULL, depth);
2165                         dns_rbt_indent(depth);
2166                         printf("-- END down from ");
2167                         dns_rbt_printnodename(root);
2168                         printf("\n");
2169                 }
2170
2171                 if (IS_RED(root) && IS_RED(LEFT(root)))
2172                     printf("** Red/Red color violation on left\n");
2173                 dns_rbt_printtree(LEFT(root), root, depth);
2174
2175                 if (IS_RED(root) && IS_RED(RIGHT(root)))
2176                     printf("** Red/Red color violation on right\n");
2177                 dns_rbt_printtree(RIGHT(root), root, depth);
2178
2179         } else
2180                 printf("NULL\n");
2181 }
2182
2183 void
2184 dns_rbt_printall(dns_rbt_t *rbt) {
2185         REQUIRE(VALID_RBT(rbt));
2186
2187         dns_rbt_printtree(rbt->root, NULL, 0);
2188 }
2189
2190 /*
2191  * Chain Functions
2192  */
2193
2194 void
2195 dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
2196         /*
2197          * Initialize 'chain'.
2198          */
2199
2200         REQUIRE(chain != NULL);
2201
2202         chain->mctx = mctx;
2203         chain->end = NULL;
2204         chain->level_count = 0;
2205         chain->level_matches = 0;
2206         memset(chain->levels, 0, sizeof(chain->levels));
2207
2208         chain->magic = CHAIN_MAGIC;
2209 }
2210
2211 isc_result_t
2212 dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
2213                          dns_name_t *origin, dns_rbtnode_t **node)
2214 {
2215         isc_result_t result = ISC_R_SUCCESS;
2216
2217         REQUIRE(VALID_CHAIN(chain));
2218
2219         if (node != NULL)
2220                 *node = chain->end;
2221
2222         if (chain->end == NULL)
2223                 return (ISC_R_NOTFOUND);
2224
2225         if (name != NULL) {
2226                 NODENAME(chain->end, name);
2227
2228                 if (chain->level_count == 0) {
2229                         /*
2230                          * Names in the top level tree are all absolute.
2231                          * Always make 'name' relative.
2232                          */
2233                         INSIST(dns_name_isabsolute(name));
2234
2235                         /*
2236                          * This is cheaper than dns_name_getlabelsequence().
2237                          */
2238                         name->labels--;
2239                         name->length--;
2240                         name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
2241                 }
2242         }
2243
2244         if (origin != NULL) {
2245                 if (chain->level_count > 0)
2246                         result = chain_name(chain, origin, ISC_FALSE);
2247                 else
2248                         result = dns_name_copy(dns_rootname, origin, NULL);
2249         }
2250
2251         return (result);
2252 }
2253
2254 isc_result_t
2255 dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
2256                       dns_name_t *origin)
2257 {
2258         dns_rbtnode_t *current, *previous, *predecessor;
2259         isc_result_t result = ISC_R_SUCCESS;
2260         isc_boolean_t new_origin = ISC_FALSE;
2261
2262         REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2263
2264         predecessor = NULL;
2265
2266         current = chain->end;
2267
2268         if (LEFT(current) != NULL) {
2269                 /*
2270                  * Moving left one then right as far as possible is the
2271                  * previous node, at least for this level.
2272                  */
2273                 current = LEFT(current);
2274
2275                 while (RIGHT(current) != NULL)
2276                         current = RIGHT(current);
2277
2278                 predecessor = current;
2279
2280         } else {
2281                 /*
2282                  * No left links, so move toward the root.  If at any point on
2283                  * the way there the link from parent to child is a right
2284                  * link, then the parent is the previous node, at least
2285                  * for this level.
2286                  */
2287                 while (! IS_ROOT(current)) {
2288                         previous = current;
2289                         current = PARENT(current);
2290
2291                         if (RIGHT(current) == previous) {
2292                                 predecessor = current;
2293                                 break;
2294                         }
2295                 }
2296         }
2297
2298         if (predecessor != NULL) {
2299                 /*
2300                  * Found a predecessor node in this level.  It might not
2301                  * really be the predecessor, however.
2302                  */
2303                 if (DOWN(predecessor) != NULL) {
2304                         /*
2305                          * The predecessor is really down at least one level.
2306                          * Go down and as far right as possible, and repeat
2307                          * as long as the rightmost node has a down pointer.
2308                          */
2309                         do {
2310                                 /*
2311                                  * XXX DCL Need to do something about origins
2312                                  * here. See whether to go down, and if so
2313                                  * whether it is truly what Bob calls a
2314                                  * new origin.
2315                                  */
2316                                 ADD_LEVEL(chain, predecessor);
2317                                 predecessor = DOWN(predecessor);
2318
2319                                 /* XXX DCL duplicated from above; clever
2320                                  * way to unduplicate? */
2321
2322                                 while (RIGHT(predecessor) != NULL)
2323                                         predecessor = RIGHT(predecessor);
2324                         } while (DOWN(predecessor) != NULL);
2325
2326                         /* XXX DCL probably needs work on the concept */
2327                         if (origin != NULL)
2328                                 new_origin = ISC_TRUE;
2329                 }
2330
2331         } else if (chain->level_count > 0) {
2332                 /*
2333                  * Dang, didn't find a predecessor in this level.
2334                  * Got to the root of this level without having traversed
2335                  * any right links.  Ascend the tree one level; the
2336                  * node that points to this tree is the predecessor.
2337                  */
2338                 INSIST(chain->level_count > 0 && IS_ROOT(current));
2339                 predecessor = chain->levels[--chain->level_count];
2340
2341                 /* XXX DCL probably needs work on the concept */
2342                 /*
2343                  * Don't declare an origin change when the new origin is "."
2344                  * at the top level tree, because "." is declared as the origin
2345                  * for the second level tree.
2346                  */
2347                 if (origin != NULL &&
2348                     (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
2349                         new_origin = ISC_TRUE;
2350         }
2351
2352         if (predecessor != NULL) {
2353                 chain->end = predecessor;
2354
2355                 if (new_origin) {
2356                         result = dns_rbtnodechain_current(chain, name, origin,
2357                                                           NULL);
2358                         if (result == ISC_R_SUCCESS)
2359                                 result = DNS_R_NEWORIGIN;
2360
2361                 } else
2362                         result = dns_rbtnodechain_current(chain, name, NULL,
2363                                                           NULL);
2364
2365         } else
2366                 result = ISC_R_NOMORE;
2367
2368         return (result);
2369 }
2370
2371 isc_result_t
2372 dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
2373                       dns_name_t *origin)
2374 {
2375         dns_rbtnode_t *current, *successor;
2376         isc_result_t result = ISC_R_SUCCESS;
2377         isc_boolean_t new_origin = ISC_FALSE;
2378
2379         REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2380
2381         successor = NULL;
2382
2383         current = chain->end;
2384
2385         if (DOWN(current) != NULL) {
2386                 /*
2387                  * Don't declare an origin change when the new origin is "."
2388                  * at the second level tree, because "." is already declared
2389                  * as the origin for the top level tree.
2390                  */
2391                 if (chain->level_count > 0 ||
2392                     OFFSETLEN(current) > 1)
2393                         new_origin = ISC_TRUE;
2394
2395                 ADD_LEVEL(chain, current);
2396                 current = DOWN(current);
2397
2398                 while (LEFT(current) != NULL)
2399                         current = LEFT(current);
2400
2401                 successor = current;
2402         }
2403
2404         if (successor != NULL) {
2405                 chain->end = successor;
2406
2407                 /*
2408                  * It is not necessary to use dns_rbtnodechain_current like
2409                  * the other functions because this function will never
2410                  * find a node in the topmost level.  This is because the
2411                  * root level will never be more than one name, and everything
2412                  * in the megatree is a successor to that node, down at
2413                  * the second level or below.
2414                  */
2415
2416                 if (name != NULL)
2417                         NODENAME(chain->end, name);
2418
2419                 if (new_origin) {
2420                         if (origin != NULL)
2421                                 result = chain_name(chain, origin, ISC_FALSE);
2422
2423                         if (result == ISC_R_SUCCESS)
2424                                 result = DNS_R_NEWORIGIN;
2425
2426                 } else
2427                         result = ISC_R_SUCCESS;
2428
2429         } else
2430                 result = ISC_R_NOMORE;
2431
2432         return (result);
2433 }
2434
2435 isc_result_t
2436 dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
2437         dns_rbtnode_t *current, *previous, *successor;
2438         isc_result_t result = ISC_R_SUCCESS;
2439
2440         REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2441
2442         successor = NULL;
2443
2444         current = chain->end;
2445
2446         if (RIGHT(current) == NULL) {
2447                 while (! IS_ROOT(current)) {
2448                         previous = current;
2449                         current = PARENT(current);
2450
2451                         if (LEFT(current) == previous) {
2452                                 successor = current;
2453                                 break;
2454                         }
2455                 }
2456         } else {
2457                 current = RIGHT(current);
2458
2459                 while (LEFT(current) != NULL)
2460                         current = LEFT(current);
2461
2462                 successor = current;
2463         }
2464
2465         if (successor != NULL) {
2466                 chain->end = successor;
2467
2468                 if (name != NULL)
2469                         NODENAME(chain->end, name);
2470
2471                 result = ISC_R_SUCCESS;
2472         } else
2473                 result = ISC_R_NOMORE;
2474
2475         return (result);
2476 }
2477
2478 isc_result_t
2479 dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
2480                       dns_name_t *origin)
2481 {
2482         dns_rbtnode_t *current, *previous, *successor;
2483         isc_result_t result = ISC_R_SUCCESS;
2484         isc_boolean_t new_origin = ISC_FALSE;
2485
2486         REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
2487
2488         successor = NULL;
2489
2490         current = chain->end;
2491
2492         /*
2493          * If there is a level below this node, the next node is the leftmost
2494          * node of the next level.
2495          */
2496         if (DOWN(current) != NULL) {
2497                 /*
2498                  * Don't declare an origin change when the new origin is "."
2499                  * at the second level tree, because "." is already declared
2500                  * as the origin for the top level tree.
2501                  */
2502                 if (chain->level_count > 0 ||
2503                     OFFSETLEN(current) > 1)
2504                         new_origin = ISC_TRUE;
2505
2506                 ADD_LEVEL(chain, current);
2507                 current = DOWN(current);
2508
2509                 while (LEFT(current) != NULL)
2510                         current = LEFT(current);
2511
2512                 successor = current;
2513
2514         } else if (RIGHT(current) == NULL) {
2515                 /*
2516                  * The successor is up, either in this level or a previous one.
2517                  * Head back toward the root of the tree, looking for any path
2518                  * that was via a left link; the successor is the node that has
2519                  * that left link.  In the event the root of the level is
2520                  * reached without having traversed any left links, ascend one
2521                  * level and look for either a right link off the point of
2522                  * ascent, or search for a left link upward again, repeating
2523                  * ascends until either case is true.
2524                  */
2525                 do {
2526                         while (! IS_ROOT(current)) {
2527                                 previous = current;
2528                                 current = PARENT(current);
2529
2530                                 if (LEFT(current) == previous) {
2531                                         successor = current;
2532                                         break;
2533                                 }
2534                         }
2535
2536                         if (successor == NULL) {
2537                                 /*
2538                                  * Reached the root without having traversed
2539                                  * any left pointers, so this level is done.
2540                                  */
2541                                 if (chain->level_count == 0)
2542                                         break;
2543
2544                                 current = chain->levels[--chain->level_count];
2545                                 new_origin = ISC_TRUE;
2546
2547                                 if (RIGHT(current) != NULL)
2548                                         break;
2549                         }
2550                 } while (successor == NULL);
2551         }
2552
2553         if (successor == NULL && RIGHT(current) != NULL) {
2554                 current = RIGHT(current);
2555
2556                 while (LEFT(current) != NULL)
2557                         current = LEFT(current);
2558
2559                 successor = current;
2560         }
2561
2562         if (successor != NULL) {
2563                 chain->end = successor;
2564
2565                 /*
2566                  * It is not necessary to use dns_rbtnodechain_current like
2567                  * the other functions because this function will never
2568                  * find a node in the topmost level.  This is because the
2569                  * root level will never be more than one name, and everything
2570                  * in the megatree is a successor to that node, down at
2571                  * the second level or below.
2572                  */
2573
2574                 if (name != NULL)
2575                         NODENAME(chain->end, name);
2576
2577                 if (new_origin) {
2578                         if (origin != NULL)
2579                                 result = chain_name(chain, origin, ISC_FALSE);
2580
2581                         if (result == ISC_R_SUCCESS)
2582                                 result = DNS_R_NEWORIGIN;
2583
2584                 } else
2585                         result = ISC_R_SUCCESS;
2586
2587         } else
2588                 result = ISC_R_NOMORE;
2589
2590         return (result);
2591 }
2592
2593 isc_result_t
2594 dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
2595                        dns_name_t *name, dns_name_t *origin)
2596
2597 {
2598         isc_result_t result;
2599
2600         REQUIRE(VALID_RBT(rbt));
2601         REQUIRE(VALID_CHAIN(chain));
2602
2603         dns_rbtnodechain_reset(chain);
2604
2605         chain->end = rbt->root;
2606
2607         result = dns_rbtnodechain_current(chain, name, origin, NULL);
2608
2609         if (result == ISC_R_SUCCESS)
2610                 result = DNS_R_NEWORIGIN;
2611
2612         return (result);
2613 }
2614
2615 isc_result_t
2616 dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
2617                        dns_name_t *name, dns_name_t *origin)
2618
2619 {
2620         isc_result_t result;
2621
2622         REQUIRE(VALID_RBT(rbt));
2623         REQUIRE(VALID_CHAIN(chain));
2624
2625         dns_rbtnodechain_reset(chain);
2626
2627         result = move_chain_to_last(chain, rbt->root);
2628         if (result != ISC_R_SUCCESS)
2629                 return (result);
2630
2631         result = dns_rbtnodechain_current(chain, name, origin, NULL);
2632
2633         if (result == ISC_R_SUCCESS)
2634                 result = DNS_R_NEWORIGIN;
2635
2636         return (result);
2637 }
2638
2639
2640 void
2641 dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
2642         /*
2643          * Free any dynamic storage associated with 'chain', and then
2644          * reinitialize 'chain'.
2645          */
2646
2647         REQUIRE(VALID_CHAIN(chain));
2648
2649         chain->end = NULL;
2650         chain->level_count = 0;
2651         chain->level_matches = 0;
2652 }
2653
2654 void
2655 dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
2656         /*
2657          * Free any dynamic storage associated with 'chain', and then
2658          * invalidate 'chain'.
2659          */
2660
2661         dns_rbtnodechain_reset(chain);
2662
2663         chain->magic = 0;
2664 }