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