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

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

Large files are truncated click here to view the full file

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