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