00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <sys/stat.h>
00025 #ifdef HAVE_INTTYPES_H
00026 #include <inttypes.h>
00027 #endif
00028
00029 #include <isc/crc64.h>
00030 #include <isc/file.h>
00031 #include <isc/hex.h>
00032 #include <isc/mem.h>
00033 #include <isc/platform.h>
00034 #include <isc/print.h>
00035 #include <isc/refcount.h>
00036 #include <isc/socket.h>
00037 #include <isc/stdio.h>
00038 #include <isc/string.h>
00039 #include <isc/util.h>
00040
00041
00042
00043
00044
00045 #define DNS_NAME_USEINLINE 1
00046
00047 #include <dns/fixedname.h>
00048 #include <dns/log.h>
00049 #include <dns/rbt.h>
00050 #include <dns/result.h>
00051 #include <dns/version.h>
00052
00053 #include <unistd.h>
00054
00055 #define CHECK(x) \
00056 do { \
00057 result = (x); \
00058 if (result != ISC_R_SUCCESS) \
00059 goto cleanup; \
00060 } while (0)
00061
00062 #define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
00063 #define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
00064
00065
00066
00067
00068
00069
00070 #define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
00071 #define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
00072
00073 #define RBT_HASH_SIZE 64
00074
00075 #ifdef RBT_MEM_TEST
00076 #undef RBT_HASH_SIZE
00077 #define RBT_HASH_SIZE 2
00078 #endif
00079
00080 struct dns_rbt {
00081 unsigned int magic;
00082 isc_mem_t * mctx;
00083 dns_rbtnode_t * root;
00084 void (*data_deleter)(void *, void *);
00085 void * deleter_arg;
00086 unsigned int nodecount;
00087 unsigned int hashsize;
00088 dns_rbtnode_t ** hashtable;
00089 void * mmap_location;
00090 };
00091
00092 #define RED 0
00093 #define BLACK 1
00094
00095
00096
00097
00098
00099
00100
00101 typedef struct file_header file_header_t;
00102
00103
00104 static char FILE_VERSION[32] = "\0";
00105
00106
00107 #define HEADER_LENGTH 1024
00108
00109 struct file_header {
00110 char version1[32];
00111 isc_uint64_t first_node_offset;
00112
00113
00114
00115
00116 isc_uint32_t ptrsize;
00117 unsigned int bigendian:1;
00118 unsigned int rdataset_fixed:1;
00119 unsigned int nodecount;
00120 isc_uint64_t crc;
00121 char version2[32];
00122 };
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 static isc_result_t
00144 dns_rbt_zero_header(FILE *file);
00145
00146 static isc_result_t
00147 write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
00148 isc_uint64_t crc);
00149
00150 static isc_result_t
00151 serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
00152 uintptr_t right, uintptr_t down, uintptr_t parent,
00153 uintptr_t data, isc_uint64_t *crc);
00154
00155 static isc_result_t
00156 serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
00157 dns_rbtdatawriter_t datawriter, void *writer_arg,
00158 uintptr_t *where, isc_uint64_t *crc);
00159
00160
00161
00162
00163
00164 static inline dns_rbtnode_t *
00165 getparent(dns_rbtnode_t *node, file_header_t *header) {
00166 char *adjusted_address = (char *)(node->parent);
00167 adjusted_address += node->parent_is_relative * (uintptr_t)header;
00168
00169 return ((dns_rbtnode_t *)adjusted_address);
00170 }
00171
00172 static inline dns_rbtnode_t *
00173 getleft(dns_rbtnode_t *node, file_header_t *header) {
00174 char *adjusted_address = (char *)(node->left);
00175 adjusted_address += node->left_is_relative * (uintptr_t)header;
00176
00177 return ((dns_rbtnode_t *)adjusted_address);
00178 }
00179
00180 static inline dns_rbtnode_t *
00181 getright(dns_rbtnode_t *node, file_header_t *header) {
00182 char *adjusted_address = (char *)(node->right);
00183 adjusted_address += node->right_is_relative * (uintptr_t)header;
00184
00185 return ((dns_rbtnode_t *)adjusted_address);
00186 }
00187
00188 static inline dns_rbtnode_t *
00189 getdown(dns_rbtnode_t *node, file_header_t *header) {
00190 char *adjusted_address = (char *)(node->down);
00191 adjusted_address += node->down_is_relative * (uintptr_t)header;
00192
00193 return ((dns_rbtnode_t *)adjusted_address);
00194 }
00195
00196 static inline dns_rbtnode_t *
00197 getdata(dns_rbtnode_t *node, file_header_t *header) {
00198 char *adjusted_address = (char *)(node->data);
00199 adjusted_address += node->data_is_relative * (uintptr_t)header;
00200
00201 return ((dns_rbtnode_t *)adjusted_address);
00202 }
00203
00204
00205
00206
00207 #define PARENT(node) ((node)->parent)
00208 #define LEFT(node) ((node)->left)
00209 #define RIGHT(node) ((node)->right)
00210 #define DOWN(node) ((node)->down)
00211 #define DATA(node) ((node)->data)
00212 #define IS_EMPTY(node) ((node)->data == NULL)
00213 #define HASHNEXT(node) ((node)->hashnext)
00214 #define HASHVAL(node) ((node)->hashval)
00215 #define COLOR(node) ((node)->color)
00216 #define NAMELEN(node) ((node)->namelen)
00217 #define OLDNAMELEN(node) ((node)->oldnamelen)
00218 #define OFFSETLEN(node) ((node)->offsetlen)
00219 #define ATTRS(node) ((node)->attributes)
00220 #define IS_ROOT(node) ISC_TF((node)->is_root == 1)
00221 #define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
00222
00223
00224
00225
00226
00227 #define DIRTY(node) ((node)->dirty)
00228 #define WILD(node) ((node)->wild)
00229 #define LOCKNUM(node) ((node)->locknum)
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 #define NAME(node) ((unsigned char *)((node) + 1))
00244 #define OFFSETS(node) (NAME(node) + OLDNAMELEN(node) + 1)
00245 #define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
00246
00247 #define NODE_SIZE(node) (sizeof(*node) + \
00248 OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
00249
00250
00251
00252
00253 #define IS_RED(node) ((node) != NULL && (node)->color == RED)
00254 #define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
00255 #define MAKE_RED(node) ((node)->color = RED)
00256 #define MAKE_BLACK(node) ((node)->color = BLACK)
00257
00258
00259
00260
00261
00262
00263
00264
00265 #define ADD_LEVEL(chain, node) \
00266 do { \
00267 INSIST((chain)->level_count < DNS_RBT_LEVELBLOCK); \
00268 (chain)->levels[(chain)->level_count++] = (node); \
00269 } while (0)
00270
00271
00272
00273
00274
00275
00276
00277 static inline void
00278 NODENAME(dns_rbtnode_t *node, dns_name_t *name) {
00279 name->length = NAMELEN(node);
00280 name->labels = OFFSETLEN(node);
00281 name->ndata = NAME(node);
00282 name->offsets = OFFSETS(node);
00283 name->attributes = ATTRS(node);
00284 name->attributes |= DNS_NAMEATTR_READONLY;
00285 }
00286
00287 void
00288 dns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name) {
00289 name->length = NAMELEN(node);
00290 name->labels = OFFSETLEN(node);
00291 name->ndata = NAME(node);
00292 name->offsets = OFFSETS(node);
00293 name->attributes = ATTRS(node);
00294 name->attributes |= DNS_NAMEATTR_READONLY;
00295 }
00296
00297 dns_rbtnode_t *
00298 dns_rbt_root(dns_rbt_t *rbt) {
00299 return rbt->root;
00300 }
00301
00302 #ifdef DNS_RBT_USEHASH
00303 static isc_result_t
00304 inithash(dns_rbt_t *rbt);
00305 #endif
00306
00307 #ifdef DEBUG
00308 #define inline
00309
00310
00311
00312 dns_name_t Name(dns_rbtnode_t *node);
00313 dns_name_t
00314 Name(dns_rbtnode_t *node) {
00315 dns_name_t name;
00316
00317 dns_name_init(&name, NULL);
00318 if (node != NULL)
00319 NODENAME(node, &name);
00320
00321 return (name);
00322 }
00323
00324 static void
00325 hexdump(const char *desc, unsigned char *data, size_t size) {
00326 char hexdump[BUFSIZ * 2 + 1];
00327 isc_buffer_t b;
00328 isc_region_t r;
00329 isc_result_t result;
00330 size_t bytes;
00331
00332 fprintf(stderr, "%s: ", desc);
00333 do {
00334 isc_buffer_init(&b, hexdump, sizeof(hexdump));
00335 r.base = data;
00336 r.length = bytes = (size > BUFSIZ) ? BUFSIZ : size;
00337 result = isc_hex_totext(&r, 0, "", &b);
00338 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00339 isc_buffer_putuint8(&b, 0);
00340 fprintf(stderr, "%s", hexdump);
00341 data += bytes;
00342 size -= bytes;
00343 } while (size > 0);
00344 fprintf(stderr, "\n");
00345 }
00346 #endif
00347
00348
00349 static inline dns_rbtnode_t *
00350 get_subtree_root(dns_rbtnode_t *node) {
00351 while (!IS_ROOT(node)) {
00352 node = PARENT(node);
00353 }
00354
00355 return (node);
00356 }
00357
00358
00359
00360
00361 static inline dns_rbtnode_t *
00362 get_upper_node(dns_rbtnode_t *node) {
00363 dns_rbtnode_t *root = get_subtree_root(node);
00364
00365
00366
00367
00368
00369
00370 return (PARENT(root));
00371 }
00372
00373 size_t
00374 dns__rbtnode_getdistance(dns_rbtnode_t *node) {
00375 size_t nodes = 1;
00376
00377 while (node != NULL) {
00378 if (IS_ROOT(node))
00379 break;
00380 nodes++;
00381 node = PARENT(node);
00382 }
00383
00384 return (nodes);
00385 }
00386
00387
00388
00389
00390 static isc_result_t
00391 create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
00392
00393 #ifdef DNS_RBT_USEHASH
00394 static inline void
00395 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
00396 static inline void
00397 unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
00398 static void
00399 rehash(dns_rbt_t *rbt, unsigned int newcount);
00400 #else
00401 #define hash_node(rbt, node, name)
00402 #define unhash_node(rbt, node)
00403 #define rehash(rbt, newcount)
00404 #endif
00405
00406 static inline void
00407 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
00408 static inline void
00409 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
00410
00411 static void
00412 addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
00413 dns_rbtnode_t **rootp);
00414
00415 static void
00416 deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
00417
00418 static isc_result_t
00419 treefix(dns_rbt_t *rbt, void *base, size_t size,
00420 dns_rbtnode_t *n, dns_name_t *name,
00421 dns_rbtdatafixer_t datafixer, void *fixer_arg,
00422 isc_uint64_t *crc);
00423
00424 static isc_result_t
00425 deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
00426
00427 static void
00428 deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep);
00429
00430 static void
00431 printnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f);
00432
00433 static void
00434 freenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
00435
00436 static isc_result_t
00437 dns_rbt_zero_header(FILE *file) {
00438
00439
00440
00441
00442
00443 char buffer[HEADER_LENGTH];
00444 isc_result_t result;
00445
00446 memset(buffer, 0, HEADER_LENGTH);
00447 result = isc_stdio_write(buffer, 1, HEADER_LENGTH, file, NULL);
00448 if (result != ISC_R_SUCCESS)
00449 return (result);
00450
00451 result = fflush(file);
00452 if (result != ISC_R_SUCCESS)
00453 return (result);
00454
00455 return (ISC_R_SUCCESS);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465 static isc_result_t
00466 write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
00467 isc_uint64_t crc)
00468 {
00469 file_header_t header;
00470 isc_result_t result;
00471 off_t location;
00472
00473 if (FILE_VERSION[0] == '\0') {
00474 memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
00475 snprintf(FILE_VERSION, sizeof(FILE_VERSION),
00476 "RBT Image %s %s", dns_major, dns_mapapi);
00477 }
00478
00479 memset(&header, 0, sizeof(file_header_t));
00480 memmove(header.version1, FILE_VERSION, sizeof(header.version1));
00481 memmove(header.version2, FILE_VERSION, sizeof(header.version2));
00482 header.first_node_offset = first_node_offset;
00483 header.ptrsize = (isc_uint32_t) sizeof(void *);
00484 header.bigendian = (1 == htonl(1)) ? 1 : 0;
00485
00486 #ifdef DNS_RDATASET_FIXED
00487 header.rdataset_fixed = 1;
00488 #else
00489 header.rdataset_fixed = 0;
00490 #endif
00491
00492 header.nodecount = rbt->nodecount;
00493
00494 header.crc = crc;
00495
00496 CHECK(isc_stdio_tell(file, &location));
00497 location = dns_rbt_serialize_align(location);
00498 CHECK(isc_stdio_seek(file, location, SEEK_SET));
00499 CHECK(isc_stdio_write(&header, 1, sizeof(file_header_t), file, NULL));
00500 CHECK(fflush(file));
00501
00502
00503 CHECK(isc_stdio_seek(file, 0, SEEK_END));
00504
00505 cleanup:
00506 return (result);
00507 }
00508
00509 static isc_result_t
00510 serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
00511 uintptr_t right, uintptr_t down, uintptr_t parent,
00512 uintptr_t data, isc_uint64_t *crc)
00513 {
00514 dns_rbtnode_t temp_node;
00515 off_t file_position;
00516 unsigned char *node_data;
00517 size_t datasize;
00518 isc_result_t result;
00519 #ifdef DEBUG
00520 dns_name_t nodename;
00521 #endif
00522
00523 INSIST(node != NULL);
00524
00525 CHECK(isc_stdio_tell(file, &file_position));
00526 file_position = dns_rbt_serialize_align(file_position);
00527 CHECK(isc_stdio_seek(file, file_position, SEEK_SET));
00528
00529 temp_node = *node;
00530 temp_node.down_is_relative = 0;
00531 temp_node.left_is_relative = 0;
00532 temp_node.right_is_relative = 0;
00533 temp_node.parent_is_relative = 0;
00534 temp_node.data_is_relative = 0;
00535 temp_node.is_mmapped = 1;
00536
00537
00538
00539
00540
00541
00542
00543 if (temp_node.parent != NULL) {
00544 temp_node.parent = (dns_rbtnode_t *)(parent);
00545 temp_node.parent_is_relative = 1;
00546 }
00547 if (temp_node.left != NULL) {
00548 temp_node.left = (dns_rbtnode_t *)(left);
00549 temp_node.left_is_relative = 1;
00550 }
00551 if (temp_node.right != NULL) {
00552 temp_node.right = (dns_rbtnode_t *)(right);
00553 temp_node.right_is_relative = 1;
00554 }
00555 if (temp_node.down != NULL) {
00556 temp_node.down = (dns_rbtnode_t *)(down);
00557 temp_node.down_is_relative = 1;
00558 }
00559 if (temp_node.data != NULL) {
00560 temp_node.data = (dns_rbtnode_t *)(data);
00561 temp_node.data_is_relative = 1;
00562 }
00563
00564 node_data = (unsigned char *) node + sizeof(dns_rbtnode_t);
00565 datasize = NODE_SIZE(node) - sizeof(dns_rbtnode_t);
00566
00567 CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
00568 file, NULL));
00569 CHECK(isc_stdio_write(node_data, 1, datasize, file, NULL));
00570
00571 #ifdef DEBUG
00572 dns_name_init(&nodename, NULL);
00573 NODENAME(node, &nodename);
00574 fprintf(stderr, "serialize ");
00575 dns_name_print(&nodename, stderr);
00576 fprintf(stderr, "\n");
00577 hexdump("node header", (unsigned char*) &temp_node,
00578 sizeof(dns_rbtnode_t));
00579 hexdump("node data", node_data, datasize);
00580 #endif
00581
00582 isc_crc64_update(crc, (const isc_uint8_t *) &temp_node,
00583 sizeof(dns_rbtnode_t));
00584 isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize);
00585
00586 cleanup:
00587 return (result);
00588 }
00589
00590 static isc_result_t
00591 serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
00592 dns_rbtdatawriter_t datawriter, void *writer_arg,
00593 uintptr_t *where, isc_uint64_t *crc)
00594 {
00595 uintptr_t left = 0, right = 0, down = 0, data = 0;
00596 off_t location = 0, offset_adjust;
00597 isc_result_t result;
00598
00599 if (node == NULL) {
00600 if (where != NULL)
00601 *where = 0;
00602 return (ISC_R_SUCCESS);
00603 }
00604
00605
00606 CHECK(isc_stdio_tell(file, &location));
00607 location = dns_rbt_serialize_align(location);
00608 CHECK(isc_stdio_seek(file, location, SEEK_SET));
00609
00610 offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
00611 CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET));
00612
00613
00614
00615
00616
00617
00618
00619 CHECK(serialize_nodes(file, getleft(node, NULL), location,
00620 datawriter, writer_arg, &left, crc));
00621 CHECK(serialize_nodes(file, getright(node, NULL), location,
00622 datawriter, writer_arg, &right, crc));
00623 CHECK(serialize_nodes(file, getdown(node, NULL), location,
00624 datawriter, writer_arg, &down, crc));
00625
00626 if (node->data != NULL) {
00627 off_t ret;
00628
00629 CHECK(isc_stdio_tell(file, &ret));
00630 ret = dns_rbt_serialize_align(ret);
00631 CHECK(isc_stdio_seek(file, ret, SEEK_SET));
00632 data = ret;
00633
00634 datawriter(file, node->data, writer_arg, crc);
00635 }
00636
00637
00638 CHECK(isc_stdio_seek(file, location, SEEK_SET));
00639
00640
00641 CHECK(serialize_node(file, node, left, right, down, parent, data, crc));
00642
00643
00644 CHECK(isc_stdio_seek(file, 0, SEEK_END));
00645
00646 if (where != NULL)
00647 *where = (uintptr_t) location;
00648
00649 cleanup:
00650 return (result);
00651 }
00652
00653 off_t
00654 dns_rbt_serialize_align(off_t target) {
00655 off_t offset = target % 8;
00656
00657 if (offset == 0)
00658 return (target);
00659 else
00660 return (target + 8 - offset);
00661 }
00662
00663 isc_result_t
00664 dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
00665 dns_rbtdatawriter_t datawriter,
00666 void *writer_arg, off_t *offset)
00667 {
00668 isc_result_t result;
00669 off_t header_position, node_position, end_position;
00670 isc_uint64_t crc;
00671
00672 REQUIRE(file != NULL);
00673
00674 CHECK(isc_file_isplainfilefd(fileno(file)));
00675
00676 isc_crc64_init(&crc);
00677
00678 CHECK(isc_stdio_tell(file, &header_position));
00679
00680
00681 CHECK(dns_rbt_zero_header(file));
00682
00683
00684 CHECK(isc_stdio_tell(file, &node_position));
00685 CHECK(serialize_nodes(file, rbt->root, 0, datawriter,
00686 writer_arg, NULL, &crc));
00687
00688 CHECK(isc_stdio_tell(file, &end_position));
00689 if (node_position == end_position) {
00690 CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
00691 *offset = 0;
00692 return (ISC_R_SUCCESS);
00693 }
00694
00695 isc_crc64_final(&crc);
00696 #ifdef DEBUG
00697 hexdump("serializing CRC", (unsigned char *)&crc, sizeof(crc));
00698 #endif
00699
00700
00701 CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
00702 CHECK(write_header(file, rbt, HEADER_LENGTH, crc));
00703
00704
00705 CHECK(isc_stdio_seek(file, 0, SEEK_END));
00706 *offset = dns_rbt_serialize_align(header_position);
00707
00708 cleanup:
00709 return (result);
00710 }
00711
00712 #define CONFIRM(a) do { \
00713 if (! (a)) { \
00714 result = ISC_R_INVALIDFILE; \
00715 goto cleanup; \
00716 } \
00717 } while(0);
00718
00719 static isc_result_t
00720 treefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n,
00721 dns_name_t *name, dns_rbtdatafixer_t datafixer,
00722 void *fixer_arg, isc_uint64_t *crc)
00723 {
00724 isc_result_t result = ISC_R_SUCCESS;
00725 dns_fixedname_t fixed;
00726 dns_name_t nodename, *fullname;
00727 unsigned char *node_data;
00728 dns_rbtnode_t header;
00729 size_t datasize, nodemax = filesize - sizeof(dns_rbtnode_t);
00730
00731 if (n == NULL)
00732 return (ISC_R_SUCCESS);
00733
00734 CONFIRM((void *) n >= base);
00735 CONFIRM((char *) n - (char *) base <= (int) nodemax);
00736 CONFIRM(DNS_RBTNODE_VALID(n));
00737
00738 dns_name_init(&nodename, NULL);
00739 NODENAME(n, &nodename);
00740
00741 fullname = &nodename;
00742 CONFIRM(dns_name_isvalid(fullname));
00743
00744 if (!dns_name_isabsolute(&nodename)) {
00745 dns_fixedname_init(&fixed);
00746 fullname = dns_fixedname_name(&fixed);
00747 CHECK(dns_name_concatenate(&nodename, name, fullname, NULL));
00748 }
00749
00750
00751 memmove(&header, n, sizeof(header));
00752
00753 if (n->left_is_relative) {
00754 CONFIRM(n->left <= (dns_rbtnode_t *) nodemax);
00755 n->left = getleft(n, rbt->mmap_location);
00756 n->left_is_relative = 0;
00757 CONFIRM(DNS_RBTNODE_VALID(n->left));
00758 } else
00759 CONFIRM(n->left == NULL);
00760
00761 if (n->right_is_relative) {
00762 CONFIRM(n->right <= (dns_rbtnode_t *) nodemax);
00763 n->right = getright(n, rbt->mmap_location);
00764 n->right_is_relative = 0;
00765 CONFIRM(DNS_RBTNODE_VALID(n->right));
00766 } else
00767 CONFIRM(n->right == NULL);
00768
00769 if (n->down_is_relative) {
00770 CONFIRM(n->down <= (dns_rbtnode_t *) nodemax);
00771 n->down = getdown(n, rbt->mmap_location);
00772 n->down_is_relative = 0;
00773 CONFIRM(n->down > (dns_rbtnode_t *) n);
00774 CONFIRM(DNS_RBTNODE_VALID(n->down));
00775 } else
00776 CONFIRM(n->down == NULL);
00777
00778 if (n->parent_is_relative) {
00779 CONFIRM(n->parent <= (dns_rbtnode_t *) nodemax);
00780 n->parent = getparent(n, rbt->mmap_location);
00781 n->parent_is_relative = 0;
00782 CONFIRM(n->parent < (dns_rbtnode_t *) n);
00783 CONFIRM(DNS_RBTNODE_VALID(n->parent));
00784 } else
00785 CONFIRM(n->parent == NULL);
00786
00787 if (n->data_is_relative) {
00788 CONFIRM(n->data <= (void *) filesize);
00789 n->data = getdata(n, rbt->mmap_location);
00790 n->data_is_relative = 0;
00791 CONFIRM(n->data > (void *) n);
00792 } else
00793 CONFIRM(n->data == NULL);
00794
00795 hash_node(rbt, n, fullname);
00796
00797
00798 if (n->left != NULL)
00799 CHECK(treefix(rbt, base, filesize, n->left, name,
00800 datafixer, fixer_arg, crc));
00801 if (n->right != NULL)
00802 CHECK(treefix(rbt, base, filesize, n->right, name,
00803 datafixer, fixer_arg, crc));
00804 if (n->down != NULL)
00805 CHECK(treefix(rbt, base, filesize, n->down, fullname,
00806 datafixer, fixer_arg, crc));
00807
00808 if (datafixer != NULL && n->data != NULL)
00809 CHECK(datafixer(n, base, filesize, fixer_arg, crc));
00810
00811 rbt->nodecount++;
00812 node_data = (unsigned char *) n + sizeof(dns_rbtnode_t);
00813 datasize = NODE_SIZE(n) - sizeof(dns_rbtnode_t);
00814
00815 #ifdef DEBUG
00816 fprintf(stderr, "deserialize ");
00817 dns_name_print(&nodename, stderr);
00818 fprintf(stderr, "\n");
00819 hexdump("node header", (unsigned char *) &header,
00820 sizeof(dns_rbtnode_t));
00821 hexdump("node data", node_data, datasize);
00822 #endif
00823 isc_crc64_update(crc, (const isc_uint8_t *) &header,
00824 sizeof(dns_rbtnode_t));
00825 isc_crc64_update(crc, (const isc_uint8_t *) node_data,
00826 datasize);
00827
00828 cleanup:
00829 return (result);
00830 }
00831
00832 isc_result_t
00833 dns_rbt_deserialize_tree(void *base_address, size_t filesize,
00834 off_t header_offset, isc_mem_t *mctx,
00835 dns_rbtdeleter_t deleter, void *deleter_arg,
00836 dns_rbtdatafixer_t datafixer, void *fixer_arg,
00837 dns_rbtnode_t **originp, dns_rbt_t **rbtp)
00838 {
00839 isc_result_t result = ISC_R_SUCCESS;
00840 file_header_t *header;
00841 dns_rbt_t *rbt = NULL;
00842 isc_uint64_t crc;
00843
00844 REQUIRE(originp == NULL || *originp == NULL);
00845 REQUIRE(rbtp != NULL && *rbtp == NULL);
00846
00847 isc_crc64_init(&crc);
00848
00849 CHECK(dns_rbt_create(mctx, deleter, deleter_arg, &rbt));
00850
00851 rbt->mmap_location = base_address;
00852
00853 header = (file_header_t *)((char *)base_address + header_offset);
00854
00855 #ifdef DNS_RDATASET_FIXED
00856 if (header->rdataset_fixed != 1) {
00857 result = ISC_R_INVALIDFILE;
00858 goto cleanup;
00859 }
00860
00861 #else
00862 if (header->rdataset_fixed != 0) {
00863 result = ISC_R_INVALIDFILE;
00864 goto cleanup;
00865 }
00866 #endif
00867
00868 if (header->ptrsize != (isc_uint32_t) sizeof(void *)) {
00869 result = ISC_R_INVALIDFILE;
00870 goto cleanup;
00871 }
00872 if (header->bigendian != (1 == htonl(1)) ? 1 : 0) {
00873 result = ISC_R_INVALIDFILE;
00874 goto cleanup;
00875 }
00876
00877
00878 rbt->root = (dns_rbtnode_t *)((char *)base_address +
00879 header_offset + header->first_node_offset);
00880
00881 if ((header->nodecount * sizeof(dns_rbtnode_t)) > filesize) {
00882 result = ISC_R_INVALIDFILE;
00883 goto cleanup;
00884 }
00885 rehash(rbt, header->nodecount);
00886
00887 CHECK(treefix(rbt, base_address, filesize, rbt->root,
00888 dns_rootname, datafixer, fixer_arg, &crc));
00889
00890 isc_crc64_final(&crc);
00891 #ifdef DEBUG
00892 hexdump("deserializing CRC", (unsigned char *)&crc, sizeof(crc));
00893 #endif
00894
00895
00896 if (header->crc != crc) {
00897 result = ISC_R_INVALIDFILE;
00898 goto cleanup;
00899 }
00900
00901 *rbtp = rbt;
00902 if (originp != NULL)
00903 *originp = rbt->root;
00904
00905 if (header->nodecount != rbt->nodecount)
00906 result = ISC_R_INVALIDFILE;
00907
00908 cleanup:
00909 if (result != ISC_R_SUCCESS && rbt != NULL) {
00910 rbt->root = NULL;
00911 rbt->nodecount = 0;
00912 dns_rbt_destroy(&rbt);
00913 }
00914
00915 return (result);
00916 }
00917
00918
00919
00920
00921 isc_result_t
00922 dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter,
00923 void *deleter_arg, dns_rbt_t **rbtp)
00924 {
00925 #ifdef DNS_RBT_USEHASH
00926 isc_result_t result;
00927 #endif
00928 dns_rbt_t *rbt;
00929
00930 REQUIRE(mctx != NULL);
00931 REQUIRE(rbtp != NULL && *rbtp == NULL);
00932 REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
00933
00934 rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
00935 if (rbt == NULL)
00936 return (ISC_R_NOMEMORY);
00937
00938 rbt->mctx = NULL;
00939 isc_mem_attach(mctx, &rbt->mctx);
00940 rbt->data_deleter = deleter;
00941 rbt->deleter_arg = deleter_arg;
00942 rbt->root = NULL;
00943 rbt->nodecount = 0;
00944 rbt->hashtable = NULL;
00945 rbt->hashsize = 0;
00946 rbt->mmap_location = NULL;
00947
00948 #ifdef DNS_RBT_USEHASH
00949 result = inithash(rbt);
00950 if (result != ISC_R_SUCCESS) {
00951 isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
00952 return (result);
00953 }
00954 #endif
00955
00956 rbt->magic = RBT_MAGIC;
00957
00958 *rbtp = rbt;
00959
00960 return (ISC_R_SUCCESS);
00961 }
00962
00963
00964
00965
00966 void
00967 dns_rbt_destroy(dns_rbt_t **rbtp) {
00968 RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
00969 }
00970
00971 isc_result_t
00972 dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
00973 dns_rbt_t *rbt;
00974
00975 REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
00976
00977 rbt = *rbtp;
00978
00979 deletetreeflat(rbt, quantum, &rbt->root);
00980 if (rbt->root != NULL)
00981 return (ISC_R_QUOTA);
00982
00983 INSIST(rbt->nodecount == 0);
00984
00985 rbt->mmap_location = NULL;
00986
00987 if (rbt->hashtable != NULL)
00988 isc_mem_put(rbt->mctx, rbt->hashtable,
00989 rbt->hashsize * sizeof(dns_rbtnode_t *));
00990
00991 rbt->magic = 0;
00992
00993 isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
00994 *rbtp = NULL;
00995 return (ISC_R_SUCCESS);
00996 }
00997
00998 unsigned int
00999 dns_rbt_nodecount(dns_rbt_t *rbt) {
01000
01001 REQUIRE(VALID_RBT(rbt));
01002
01003 return (rbt->nodecount);
01004 }
01005
01006 unsigned int
01007 dns_rbt_hashsize(dns_rbt_t *rbt) {
01008
01009 REQUIRE(VALID_RBT(rbt));
01010
01011 return (rbt->hashsize);
01012 }
01013
01014 static inline isc_result_t
01015 chain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
01016 isc_boolean_t include_chain_end)
01017 {
01018 dns_name_t nodename;
01019 isc_result_t result = ISC_R_SUCCESS;
01020 int i;
01021
01022 dns_name_init(&nodename, NULL);
01023
01024 if (include_chain_end && chain->end != NULL) {
01025 NODENAME(chain->end, &nodename);
01026 result = dns_name_copy(&nodename, name, NULL);
01027 if (result != ISC_R_SUCCESS)
01028 return (result);
01029 } else
01030 dns_name_reset(name);
01031
01032 for (i = (int)chain->level_count - 1; i >= 0; i--) {
01033 NODENAME(chain->levels[i], &nodename);
01034 result = dns_name_concatenate(name, &nodename, name, NULL);
01035
01036 if (result != ISC_R_SUCCESS)
01037 return (result);
01038 }
01039 return (result);
01040 }
01041
01042 static inline isc_result_t
01043 move_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
01044 do {
01045
01046
01047
01048
01049 while (RIGHT(node) != NULL)
01050 node = RIGHT(node);
01051
01052 if (DOWN(node) == NULL)
01053 break;
01054
01055 ADD_LEVEL(chain, node);
01056 node = DOWN(node);
01057 } while (1);
01058
01059 chain->end = node;
01060
01061 return (ISC_R_SUCCESS);
01062 }
01063
01064
01065
01066
01067
01068 isc_result_t
01069 dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
01070
01071
01072
01073 dns_rbtnode_t **root, *parent, *child, *current, *new_current;
01074 dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
01075 dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
01076 dns_offsets_t current_offsets;
01077 dns_namereln_t compared;
01078 isc_result_t result = ISC_R_SUCCESS;
01079 dns_rbtnodechain_t chain;
01080 unsigned int common_labels;
01081 unsigned int nlabels, hlabels;
01082 int order;
01083
01084 REQUIRE(VALID_RBT(rbt));
01085 REQUIRE(dns_name_isabsolute(name));
01086 REQUIRE(nodep != NULL && *nodep == NULL);
01087
01088
01089
01090
01091
01092 dns_fixedname_init(&fixedcopy);
01093 add_name = dns_fixedname_name(&fixedcopy);
01094 dns_name_clone(name, add_name);
01095
01096 if (rbt->root == NULL) {
01097 result = create_node(rbt->mctx, add_name, &new_current);
01098 if (result == ISC_R_SUCCESS) {
01099 rbt->nodecount++;
01100 new_current->is_root = 1;
01101 rbt->root = new_current;
01102 *nodep = new_current;
01103 hash_node(rbt, new_current, name);
01104 }
01105 return (result);
01106 }
01107
01108 dns_rbtnodechain_init(&chain, rbt->mctx);
01109
01110 dns_fixedname_init(&fixedprefix);
01111 dns_fixedname_init(&fixedsuffix);
01112 prefix = dns_fixedname_name(&fixedprefix);
01113 suffix = dns_fixedname_name(&fixedsuffix);
01114
01115 root = &rbt->root;
01116 INSIST(IS_ROOT(*root));
01117 parent = NULL;
01118 current = NULL;
01119 child = *root;
01120 dns_name_init(¤t_name, current_offsets);
01121 dns_fixedname_init(&fnewname);
01122 new_name = dns_fixedname_name(&fnewname);
01123 nlabels = dns_name_countlabels(name);
01124 hlabels = 0;
01125
01126 do {
01127 current = child;
01128
01129 NODENAME(current, ¤t_name);
01130 compared = dns_name_fullcompare(add_name, ¤t_name,
01131 &order, &common_labels);
01132
01133 if (compared == dns_namereln_equal) {
01134 *nodep = current;
01135 result = ISC_R_EXISTS;
01136 break;
01137
01138 }
01139
01140 if (compared == dns_namereln_none) {
01141
01142 if (order < 0) {
01143 parent = current;
01144 child = LEFT(current);
01145
01146 } else if (order > 0) {
01147 parent = current;
01148 child = RIGHT(current);
01149
01150 }
01151
01152 } else {
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 hlabels += common_labels;
01165 if (compared == dns_namereln_subdomain) {
01166
01167
01168
01169
01170
01171
01172
01173 dns_name_split(add_name, common_labels,
01174 add_name, NULL);
01175
01176
01177
01178
01179 root = &DOWN(current);
01180
01181 INSIST(*root == NULL ||
01182 (IS_ROOT(*root) &&
01183 PARENT(*root) == current));
01184
01185 parent = NULL;
01186 child = DOWN(current);
01187 ADD_LEVEL(&chain, current);
01188
01189 } else {
01190
01191
01192
01193
01194
01195
01196
01197
01198 INSIST(compared == dns_namereln_commonancestor
01199 || compared == dns_namereln_contains);
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 if (chain.level_count ==
01216 (sizeof(chain.levels) /
01217 sizeof(*chain.levels))) {
01218 result = ISC_R_NOSPACE;
01219 break;
01220 }
01221
01222
01223
01224
01225
01226
01227
01228 dns_name_split(¤t_name, common_labels,
01229 prefix, suffix);
01230 result = create_node(rbt->mctx, suffix,
01231 &new_current);
01232
01233 if (result != ISC_R_SUCCESS)
01234 break;
01235
01236
01237
01238
01239
01240 new_current->is_root = current->is_root;
01241 if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
01242 new_current->nsec = DNS_RBT_NSEC_NORMAL;
01243 else
01244 new_current->nsec = current->nsec;
01245 PARENT(new_current) = PARENT(current);
01246 LEFT(new_current) = LEFT(current);
01247 RIGHT(new_current) = RIGHT(current);
01248 COLOR(new_current) = COLOR(current);
01249
01250
01251
01252
01253 if (parent != NULL) {
01254 if (LEFT(parent) == current)
01255 LEFT(parent) = new_current;
01256 else
01257 RIGHT(parent) = new_current;
01258 }
01259 if (LEFT(new_current) != NULL)
01260 PARENT(LEFT(new_current)) =
01261 new_current;
01262 if (RIGHT(new_current) != NULL)
01263 PARENT(RIGHT(new_current)) =
01264 new_current;
01265 if (*root == current)
01266 *root = new_current;
01267
01268 NAMELEN(current) = prefix->length;
01269 OFFSETLEN(current) = prefix->labels;
01270
01271
01272
01273
01274
01275
01276 current->is_root = 1;
01277 PARENT(current) = new_current;
01278 DOWN(new_current) = current;
01279 root = &DOWN(new_current);
01280
01281 ADD_LEVEL(&chain, new_current);
01282
01283 LEFT(current) = NULL;
01284 RIGHT(current) = NULL;
01285
01286 MAKE_BLACK(current);
01287 ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
01288
01289 rbt->nodecount++;
01290 dns_name_getlabelsequence(name,
01291 nlabels - hlabels,
01292 hlabels, new_name);
01293 hash_node(rbt, new_current, new_name);
01294
01295 if (common_labels ==
01296 dns_name_countlabels(add_name)) {
01297
01298
01299
01300
01301
01302 *nodep = new_current;
01303 return (ISC_R_SUCCESS);
01304
01305 } else {
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 dns_name_split(add_name, common_labels,
01322 add_name, NULL);
01323
01324 break;
01325 }
01326
01327 }
01328
01329 }
01330
01331 } while (child != NULL);
01332
01333 if (result == ISC_R_SUCCESS)
01334 result = create_node(rbt->mctx, add_name, &new_current);
01335
01336 if (result == ISC_R_SUCCESS) {
01337 addonlevel(new_current, current, order, root);
01338 rbt->nodecount++;
01339 *nodep = new_current;
01340 hash_node(rbt, new_current, name);
01341 }
01342
01343 return (result);
01344 }
01345
01346
01347
01348
01349 isc_result_t
01350 dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
01351 isc_result_t result;
01352 dns_rbtnode_t *node;
01353
01354 REQUIRE(VALID_RBT(rbt));
01355 REQUIRE(dns_name_isabsolute(name));
01356
01357 node = NULL;
01358
01359 result = dns_rbt_addnode(rbt, name, &node);
01360
01361
01362
01363
01364
01365
01366
01367 if (result == ISC_R_SUCCESS ||
01368 (result == ISC_R_EXISTS && DATA(node) == NULL)) {
01369 DATA(node) = data;
01370 result = ISC_R_SUCCESS;
01371 }
01372
01373 return (result);
01374 }
01375
01376
01377
01378
01379 isc_result_t
01380 dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
01381 dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
01382 unsigned int options, dns_rbtfindcallback_t callback,
01383 void *callback_arg)
01384 {
01385 dns_rbtnode_t *current, *last_compared, *current_root;
01386 dns_rbtnodechain_t localchain;
01387 dns_name_t *search_name, current_name, *callback_name;
01388 dns_fixedname_t fixedcallbackname, fixedsearchname;
01389 dns_namereln_t compared;
01390 isc_result_t result, saved_result;
01391 unsigned int common_labels;
01392 unsigned int hlabels = 0;
01393 int order;
01394
01395 REQUIRE(VALID_RBT(rbt));
01396 REQUIRE(dns_name_isabsolute(name));
01397 REQUIRE(node != NULL && *node == NULL);
01398 REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
01399 != (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
01400
01401
01402
01403
01404
01405
01406 if (chain == NULL) {
01407 options |= DNS_RBTFIND_NOPREDECESSOR;
01408 chain = &localchain;
01409 dns_rbtnodechain_init(chain, rbt->mctx);
01410 } else
01411 dns_rbtnodechain_reset(chain);
01412
01413 if (rbt->root == NULL)
01414 return (ISC_R_NOTFOUND);
01415
01416
01417
01418
01419
01420 compared = dns_namereln_none;
01421 last_compared = NULL;
01422 order = 0;
01423
01424 dns_fixedname_init(&fixedcallbackname);
01425 callback_name = dns_fixedname_name(&fixedcallbackname);
01426
01427
01428
01429
01430
01431
01432
01433
01434 dns_fixedname_init(&fixedsearchname);
01435 search_name = dns_fixedname_name(&fixedsearchname);
01436 dns_name_clone(name, search_name);
01437
01438 dns_name_init(¤t_name, NULL);
01439
01440 saved_result = ISC_R_SUCCESS;
01441 current = rbt->root;
01442 current_root = rbt->root;
01443
01444 while (current != NULL) {
01445 NODENAME(current, ¤t_name);
01446 compared = dns_name_fullcompare(search_name, ¤t_name,
01447 &order, &common_labels);
01448
01449
01450
01451
01452
01453
01454 last_compared = current;
01455
01456 if (compared == dns_namereln_equal)
01457 break;
01458
01459 if (compared == dns_namereln_none) {
01460 #ifdef DNS_RBT_USEHASH
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 dns_name_t hash_name;
01472 dns_rbtnode_t *hnode;
01473 dns_rbtnode_t *up_current;
01474 unsigned int nlabels;
01475 unsigned int tlabels = 1;
01476 unsigned int hash;
01477
01478
01479
01480
01481 if (rbt->hashtable == NULL)
01482 goto nohash;
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 INSIST(current == current_root);
01493
01494 nlabels = dns_name_countlabels(search_name);
01495
01496
01497
01498
01499
01500 up_current = PARENT(current_root);
01501 dns_name_init(&hash_name, NULL);
01502
01503 hashagain:
01504
01505
01506
01507
01508
01509
01510
01511
01512 dns_name_getlabelsequence(name,
01513 nlabels - tlabels,
01514 hlabels + tlabels,
01515 &hash_name);
01516 hash = dns_name_fullhash(&hash_name, ISC_FALSE);
01517 dns_name_getlabelsequence(search_name,
01518 nlabels - tlabels,
01519 tlabels, &hash_name);
01520
01521
01522
01523
01524
01525 for (hnode = rbt->hashtable[hash % rbt->hashsize];
01526 hnode != NULL;
01527 hnode = hnode->hashnext)
01528 {
01529 dns_name_t hnode_name;
01530
01531 if (hash != HASHVAL(hnode))
01532 continue;
01533
01534
01535
01536
01537
01538
01539
01540 if (get_upper_node(hnode) != up_current)
01541 continue;
01542
01543 dns_name_init(&hnode_name, NULL);
01544 NODENAME(hnode, &hnode_name);
01545 if (dns_name_equal(&hnode_name, &hash_name))
01546 break;
01547 }
01548
01549 if (hnode != NULL) {
01550 current = hnode;
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561 if (tlabels == nlabels) {
01562 compared = dns_namereln_equal;
01563 break;
01564 } else {
01565 common_labels = tlabels;
01566 compared = dns_namereln_subdomain;
01567 goto subdomain;
01568 }
01569 }
01570
01571 if (tlabels++ < nlabels)
01572 goto hashagain;
01573
01574
01575
01576
01577
01578
01579 current = NULL;
01580 continue;
01581
01582 nohash:
01583 #endif
01584
01585
01586
01587 if (order < 0)
01588 current = LEFT(current);
01589 else
01590 current = RIGHT(current);
01591
01592 } else {
01593
01594
01595
01596
01597
01598
01599
01600 if (compared == dns_namereln_subdomain) {
01601 #ifdef DNS_RBT_USEHASH
01602 subdomain:
01603 #endif
01604
01605
01606
01607
01608 dns_name_split(search_name, common_labels,
01609 search_name, NULL);
01610 hlabels += common_labels;
01611
01612
01613
01614 if (DATA(current) != NULL ||
01615 (options & DNS_RBTFIND_EMPTYDATA) != 0)
01616 *node = current;
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 ADD_LEVEL(chain, current);
01630
01631
01632
01633
01634
01635
01636
01637
01638 if (callback != NULL &&
01639 FINDCALLBACK(current)) {
01640 result = chain_name(chain,
01641 callback_name,
01642 ISC_FALSE);
01643 if (result != ISC_R_SUCCESS) {
01644 dns_rbtnodechain_reset(chain);
01645 return (result);
01646 }
01647
01648 result = (callback)(current,
01649 callback_name,
01650 callback_arg);
01651 if (result != DNS_R_CONTINUE) {
01652 saved_result = result;
01653
01654
01655
01656
01657 current = NULL;
01658 break;
01659 }
01660 }
01661
01662
01663
01664
01665 current = DOWN(current);
01666 current_root = current;
01667
01668 } else {
01669
01670
01671
01672
01673
01674
01675 INSIST(compared == dns_namereln_commonancestor
01676 || compared == dns_namereln_contains);
01677
01678 current = NULL;
01679 }
01680 }
01681 }
01682
01683
01684
01685
01686
01687
01688 if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
01689 (DATA(current) != NULL ||
01690 (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
01691
01692
01693
01694 chain->end = current;
01695 chain->level_matches = chain->level_count;
01696
01697 if (foundname != NULL)
01698 result = chain_name(chain, foundname, ISC_TRUE);
01699 else
01700 result = ISC_R_SUCCESS;
01701
01702 if (result == ISC_R_SUCCESS) {
01703 *node = current;
01704 result = saved_result;
01705 } else
01706 *node = NULL;
01707 } else {
01708
01709
01710
01711 if (*node != NULL) {
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722 chain->level_matches = chain->level_count - 1;
01723
01724 while (chain->levels[chain->level_matches] != *node) {
01725 INSIST(chain->level_matches > 0);
01726 chain->level_matches--;
01727 }
01728
01729 if (foundname != NULL) {
01730 unsigned int saved_count = chain->level_count;
01731
01732 chain->level_count = chain->level_matches + 1;
01733
01734 result = chain_name(chain, foundname,
01735 ISC_FALSE);
01736
01737 chain->level_count = saved_count;
01738 } else
01739 result = ISC_R_SUCCESS;
01740
01741 if (result == ISC_R_SUCCESS)
01742 result = DNS_R_PARTIALMATCH;
01743
01744 } else
01745 result = ISC_R_NOTFOUND;
01746
01747 if (current != NULL) {
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
01760 ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
01761 DATA(current) == NULL));
01762 chain->end = current;
01763
01764 } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
01765
01766
01767
01768 chain->end = NULL;
01769
01770 } else {
01771
01772
01773
01774
01775
01776 if (compared == dns_namereln_subdomain) {
01777
01778
01779
01780
01781
01782
01783
01784
01785 INSIST(chain->level_count > 0);
01786 INSIST(chain->level_matches <
01787 chain->level_count);
01788 chain->end =
01789 chain->levels[--chain->level_count];
01790
01791 } else {
01792 isc_result_t result2;
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 if (compared == dns_namereln_none)
01812 current = last_compared;
01813 else
01814 current = NULL;
01815
01816 while (current != NULL) {
01817 NODENAME(current, ¤t_name);
01818 compared = dns_name_fullcompare(
01819 search_name,
01820 ¤t_name,
01821 &order,
01822 &common_labels);
01823 POST(compared);
01824
01825 last_compared = current;
01826
01827
01828
01829
01830 if (order < 0)
01831 current = LEFT(current);
01832 else
01833 current = RIGHT(current);
01834
01835 }
01836
01837 current = last_compared;
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 if (order > 0) {
01867 if (DOWN(current) != NULL) {
01868 ADD_LEVEL(chain, current);
01869
01870 result2 =
01871 move_chain_to_last(chain,
01872 DOWN(current));
01873
01874 if (result2 != ISC_R_SUCCESS)
01875 result = result2;
01876 } else
01877
01878
01879
01880
01881
01882 chain->end = current;
01883
01884 } else {
01885 INSIST(order < 0);
01886
01887 chain->end = current;
01888
01889 result2 = dns_rbtnodechain_prev(chain,
01890 NULL,
01891 NULL);
01892 if (result2 == ISC_R_SUCCESS ||
01893 result2 == DNS_R_NEWORIGIN)
01894 ;
01895 else if (result2 == ISC_R_NOMORE)
01896
01897
01898
01899 dns_rbtnodechain_reset(chain);
01900 else
01901 result = result2;
01902 }
01903
01904 }
01905 }
01906 }
01907
01908 ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
01909
01910 return (result);
01911 }
01912
01913
01914
01915
01916 isc_result_t
01917 dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
01918 dns_name_t *foundname, void **data) {
01919 dns_rbtnode_t *node = NULL;
01920 isc_result_t result;
01921
01922 REQUIRE(data != NULL && *data == NULL);
01923
01924 result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
01925 options, NULL, NULL);
01926
01927 if (node != NULL &&
01928 (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
01929 *data = DATA(node);
01930 else
01931 result = ISC_R_NOTFOUND;
01932
01933 return (result);
01934 }
01935
01936
01937
01938
01939 isc_result_t
01940 dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
01941 dns_rbtnode_t *node = NULL;
01942 isc_result_t result;
01943
01944 REQUIRE(VALID_RBT(rbt));
01945 REQUIRE(dns_name_isabsolute(name));
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961 result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
01962 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
01963
01964 if (result == ISC_R_SUCCESS) {
01965 if (DATA(node) != NULL)
01966 result = dns_rbt_deletenode(rbt, node, recurse);
01967 else
01968 result = ISC_R_NOTFOUND;
01969
01970 } else if (result == DNS_R_PARTIALMATCH)
01971 result = ISC_R_NOTFOUND;
01972
01973 return (result);
01974 }
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012 isc_result_t
02013 dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
02014 {
02015 dns_rbtnode_t *parent;
02016
02017 REQUIRE(VALID_RBT(rbt));
02018 REQUIRE(DNS_RBTNODE_VALID(node));
02019 INSIST(rbt->nodecount != 0);
02020
02021 if (DOWN(node) != NULL) {
02022 if (recurse)
02023 RUNTIME_CHECK(deletetree(rbt, DOWN(node))
02024 == ISC_R_SUCCESS);
02025 else {
02026 if (DATA(node) != NULL && rbt->data_deleter != NULL)
02027 rbt->data_deleter(DATA(node), rbt->deleter_arg);
02028 DATA(node) = NULL;
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038 return (ISC_R_SUCCESS);
02039 }
02040 }
02041
02042
02043
02044
02045
02046
02047 parent = get_upper_node(node);
02048
02049
02050
02051
02052
02053
02054 deletefromlevel(node, parent == NULL ? &rbt->root : &DOWN(parent));
02055
02056 if (DATA(node) != NULL && rbt->data_deleter != NULL)
02057 rbt->data_deleter(DATA(node), rbt->deleter_arg);
02058
02059 unhash_node(rbt, node);
02060 #if DNS_RBT_USEMAGIC
02061 node->magic = 0;
02062 #endif
02063 dns_rbtnode_refdestroy(node);
02064
02065 freenode(rbt, &node);
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093 return (ISC_R_SUCCESS);
02094 }
02095
02096 void
02097 dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
02098
02099 REQUIRE(DNS_RBTNODE_VALID(node));
02100 REQUIRE(name != NULL);
02101 REQUIRE(name->offsets == NULL);
02102
02103 NODENAME(node, name);
02104 }
02105
02106 isc_result_t
02107 dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
02108 dns_name_t current;
02109 isc_result_t result;
02110
02111 REQUIRE(DNS_RBTNODE_VALID(node));
02112 REQUIRE(name != NULL);
02113 REQUIRE(name->buffer != NULL);
02114
02115 dns_name_init(¤t, NULL);
02116 dns_name_reset(name);
02117
02118 do {
02119 INSIST(node != NULL);
02120
02121 NODENAME(node, ¤t);
02122
02123 result = dns_name_concatenate(name, ¤t, name, NULL);
02124 if (result != ISC_R_SUCCESS)
02125 break;
02126
02127 node = get_upper_node(node);
02128 } while (! dns_name_isabsolute(name));
02129
02130 return (result);
02131 }
02132
02133 char *
02134 dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
02135 {
02136 dns_fixedname_t fixedname;
02137 dns_name_t *name;
02138 isc_result_t result;
02139
02140 REQUIRE(DNS_RBTNODE_VALID(node));
02141 REQUIRE(printname != NULL);
02142
02143 dns_fixedname_init(&fixedname);
02144 name = dns_fixedname_name(&fixedname);
02145 result = dns_rbt_fullnamefromnode(node, name);
02146 if (result == ISC_R_SUCCESS)
02147 dns_name_format(name, printname, size);
02148 else
02149 snprintf(printname, size, "<error building name: %s>",
02150 dns_result_totext(result));
02151
02152 return (printname);
02153 }
02154
02155 static isc_result_t
02156 create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
02157 dns_rbtnode_t *node;
02158 isc_region_t region;
02159 unsigned int labels;
02160 size_t nodelen;
02161
02162 REQUIRE(name->offsets != NULL);
02163
02164 dns_name_toregion(name, ®ion);
02165 labels = dns_name_countlabels(name);
02166 ENSURE(labels > 0);
02167
02168
02169
02170
02171 nodelen = sizeof(dns_rbtnode_t) + region.length + labels + 1;
02172 node = (dns_rbtnode_t *)isc_mem_get(mctx, nodelen);
02173 if (node == NULL)
02174 return (ISC_R_NOMEMORY);
02175 memset(node, 0, nodelen);
02176
02177 node->is_root = 0;
02178 PARENT(node) = NULL;
02179 RIGHT(node) = NULL;
02180 LEFT(node) = NULL;
02181 DOWN(node) = NULL;
02182 DATA(node) = NULL;
02183 node->is_mmapped = 0;
02184 node->down_is_relative = 0;
02185 node->left_is_relative = 0;
02186 node->right_is_relative = 0;
02187 node->parent_is_relative = 0;
02188 node->data_is_relative = 0;
02189 node->rpz = 0;
02190
02191 #ifdef DNS_RBT_USEHASH
02192 HASHNEXT(node) = NULL;
02193 HASHVAL(node) = 0;
02194 #endif
02195
02196 ISC_LINK_INIT(node, deadlink);
02197
02198 LOCKNUM(node) = 0;
02199 WILD(node) = 0;
02200 DIRTY(node) = 0;
02201 dns_rbtnode_refinit(node, 0);
02202 node->find_callback = 0;
02203 node->nsec = DNS_RBT_NSEC_NORMAL;
02204
02205 MAKE_BLACK(node);
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 OLDNAMELEN(node) = NAMELEN(node) = region.length;
02222 OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
02223 ATTRS(node) = name->attributes;
02224
02225 memmove(NAME(node), region.base, region.length);
02226 memmove(OFFSETS(node), name->offsets, labels);
02227
02228 #if DNS_RBT_USEMAGIC
02229 node->magic = DNS_RBTNODE_MAGIC;
02230 #endif
02231 *nodep = node;
02232
02233 return (ISC_R_SUCCESS);
02234 }
02235
02236 #ifdef DNS_RBT_USEHASH
02237 static inline void
02238 hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
02239 unsigned int hash;
02240
02241 REQUIRE(name != NULL);
02242
02243 HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
02244
02245 hash = HASHVAL(node) % rbt->hashsize;
02246 HASHNEXT(node) = rbt->hashtable[hash];
02247
02248 rbt->hashtable[hash] = node;
02249 }
02250
02251 static isc_result_t
02252 inithash(dns_rbt_t *rbt) {
02253 unsigned int bytes;
02254
02255 rbt->hashsize = RBT_HASH_SIZE;
02256 bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
02257 rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
02258
02259 if (rbt->hashtable == NULL)
02260 return (ISC_R_NOMEMORY);
02261
02262 memset(rbt->hashtable, 0, bytes);
02263
02264 return (ISC_R_SUCCESS);
02265 }
02266
02267 static void
02268 rehash(dns_rbt_t *rbt, unsigned int newcount) {
02269 unsigned int oldsize;
02270 dns_rbtnode_t **oldtable;
02271 dns_rbtnode_t *node;
02272 unsigned int hash;
02273 unsigned int i;
02274
02275 oldsize = rbt->hashsize;
02276 oldtable = rbt->hashtable;
02277 do {
02278 rbt->hashsize = rbt->hashsize * 2 + 1;
02279 } while (newcount >= (rbt->hashsize * 3));
02280 rbt->hashtable = isc_mem_get(rbt->mctx,
02281 rbt->hashsize * sizeof(dns_rbtnode_t *));
02282 if (rbt->hashtable == NULL) {
02283 rbt->hashtable = oldtable;
02284 rbt->hashsize = oldsize;
02285 return;
02286 }
02287
02288 INSIST(rbt->hashsize > 0);
02289
02290 for (i = 0; i < rbt->hashsize; i++)
02291 rbt->hashtable[i] = NULL;
02292
02293 for (i = 0; i < oldsize; i++) {
02294 node = oldtable[i];
02295 while (node != NULL) {
02296 hash = HASHVAL(node) % rbt->hashsize;
02297 oldtable[i] = HASHNEXT(node);
02298 HASHNEXT(node) = rbt->hashtable[hash];
02299 rbt->hashtable[hash] = node;
02300 node = oldtable[i];
02301 }
02302 }
02303
02304 isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
02305 }
02306
02307 static inline void
02308 hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
02309 REQUIRE(DNS_RBTNODE_VALID(node));
02310
02311 if (rbt->nodecount >= (rbt->hashsize * 3))
02312 rehash(rbt, rbt->nodecount);
02313
02314 hash_add_node(rbt, node, name);
02315 }
02316
02317 static inline void
02318 unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
02319 unsigned int bucket;
02320 dns_rbtnode_t *bucket_node;
02321
02322 REQUIRE(DNS_RBTNODE_VALID(node));
02323
02324 if (rbt->hashtable != NULL) {
02325 bucket = HASHVAL(node) % rbt->hashsize;
02326 bucket_node = rbt->hashtable[bucket];
02327
02328 if (bucket_node == node)
02329 rbt->hashtable[bucket] = HASHNEXT(node);
02330 else {
02331 while (HASHNEXT(bucket_node) != node) {
02332 INSIST(HASHNEXT(bucket_node) != NULL);
02333 bucket_node = HASHNEXT(bucket_node);
02334 }
02335 HASHNEXT(bucket_node) = HASHNEXT(node);
02336 }
02337 }
02338 }
02339 #endif
02340
02341 static inline void
02342 rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
02343 dns_rbtnode_t *child;
02344
02345 REQUIRE(DNS_RBTNODE_VALID(node));
02346 REQUIRE(rootp != NULL);
02347
02348 child = RIGHT(node);
02349 INSIST(child != NULL);
02350
02351 RIGHT(node) = LEFT(child);
02352 if (LEFT(child) != NULL)
02353 PARENT(LEFT(child)) = node;
02354 LEFT(child) = node;
02355
02356 if (child != NULL)
02357 PARENT(child) = PARENT(node);
02358
02359 if (IS_ROOT(node)) {
02360 *rootp = child;
02361 child->is_root = 1;
02362 node->is_root = 0;
02363
02364 } else {
02365 if (LEFT(PARENT(node)) == node)
02366 LEFT(PARENT(node)) = child;
02367 else
02368 RIGHT(PARENT(node)) = child;
02369 }
02370
02371 PARENT(node) = child;
02372 }
02373
02374 static inline void
02375 rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
02376 dns_rbtnode_t *child;
02377
02378 REQUIRE(DNS_RBTNODE_VALID(node));
02379 REQUIRE(rootp != NULL);
02380
02381 child = LEFT(node);
02382 INSIST(child != NULL);
02383
02384 LEFT(node) = RIGHT(child);
02385 if (RIGHT(child) != NULL)
02386 PARENT(RIGHT(child)) = node;
02387 RIGHT(child) = node;
02388
02389 if (child != NULL)
02390 PARENT(child) = PARENT(node);
02391
02392 if (IS_ROOT(node)) {
02393 *rootp = child;
02394 child->is_root = 1;
02395 node->is_root = 0;
02396
02397 } else {
02398 if (LEFT(PARENT(node)) == node)
02399 LEFT(PARENT(node)) = child;
02400 else
02401 RIGHT(PARENT(node)) = child;
02402 }
02403
02404 PARENT(node) = child;
02405 }
02406
02407
02408
02409
02410
02411 static void
02412 addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
02413 dns_rbtnode_t **rootp)
02414 {
02415 dns_rbtnode_t *child, *root, *parent, *grandparent;
02416 dns_name_t add_name, current_name;
02417 dns_offsets_t add_offsets, current_offsets;
02418
02419 REQUIRE(rootp != NULL);
02420 REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
02421 RIGHT(node) == NULL);
02422 REQUIRE(current != NULL);
02423
02424 root = *rootp;
02425 if (root == NULL) {
02426
02427
02428
02429 MAKE_BLACK(node);
02430 node->is_root = 1;
02431 PARENT(node) = current;
02432 *rootp = node;
02433 return;
02434 }
02435
02436 child = root;
02437 POST(child);
02438
02439 dns_name_init(&add_name, add_offsets);
02440 NODENAME(node, &add_name);
02441
02442 dns_name_init(¤t_name, current_offsets);
02443 NODENAME(current, ¤t_name);
02444
02445 if (order < 0) {
02446 INSIST(LEFT(current) == NULL);
02447 LEFT(current) = node;
02448 } else {
02449 INSIST(RIGHT(current) == NULL);
02450 RIGHT(current) = node;
02451 }
02452
02453 INSIST(PARENT(node) == NULL);
02454 PARENT(node) = current;
02455
02456 MAKE_RED(node);
02457
02458 while (node != root && IS_RED(PARENT(node))) {
02459
02460
02461
02462
02463
02464
02465 parent = PARENT(node);
02466 grandparent = PARENT(parent);
02467
02468 if (parent == LEFT(grandparent)) {
02469 child = RIGHT(grandparent);
02470 if (child != NULL && IS_RED(child)) {
02471 MAKE_BLACK(parent);
02472 MAKE_BLACK(child);
02473 MAKE_RED(grandparent);
02474 node = grandparent;
02475 } else {
02476 if (node == RIGHT(parent)) {
02477 rotate_left(parent, &root);
02478 node = parent;
02479 parent = PARENT(node);
02480 grandparent = PARENT(parent);
02481 }
02482 MAKE_BLACK(parent);
02483 MAKE_RED(grandparent);
02484 rotate_right(grandparent, &root);
02485 }
02486 } else {
02487 child = LEFT(grandparent);
02488 if (child != NULL && IS_RED(child)) {
02489 MAKE_BLACK(parent);
02490 MAKE_BLACK(child);
02491 MAKE_RED(grandparent);
02492 node = grandparent;
02493 } else {
02494 if (node == LEFT(parent)) {
02495 rotate_right(parent, &root);
02496 node = parent;
02497 parent = PARENT(node);
02498 grandparent = PARENT(parent);
02499 }
02500 MAKE_BLACK(parent);
02501 MAKE_RED(grandparent);
02502 rotate_left(grandparent, &root);
02503 }
02504 }
02505 }
02506
02507 MAKE_BLACK(root);
02508 ENSURE(IS_ROOT(root));
02509 *rootp = root;
02510
02511 return;
02512 }
02513
02514
02515
02516
02517
02518 static void
02519 deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
02520 dns_rbtnode_t *child, *sibling, *parent;
02521 dns_rbtnode_t *successor;
02522
02523 REQUIRE(delete != NULL);
02524
02525
02526
02527
02528 INSIST((IS_ROOT(delete) && *rootp == delete) ||
02529 (! IS_ROOT(delete) &&
02530 (LEFT(PARENT(delete)) == delete ||
02531 RIGHT(PARENT(delete)) == delete)));
02532
02533 child = NULL;
02534
02535 if (LEFT(delete) == NULL) {
02536 if (RIGHT(delete) == NULL) {
02537 if (IS_ROOT(delete)) {
02538
02539
02540
02541 *rootp = NULL;
02542 return;
02543 }
02544 } else
02545
02546
02547
02548 child = RIGHT(delete);
02549
02550 } else if (RIGHT(delete) == NULL)
02551
02552
02553
02554 child = LEFT(delete);
02555 else {
02556 dns_rbtnode_t holder, *tmp = &holder;
02557
02558
02559
02560
02561
02562
02563
02564 successor = RIGHT(delete);
02565 while (LEFT(successor) != NULL)
02566 successor = LEFT(successor);
02567
02568
02569
02570
02571
02572 if (RIGHT(successor) != NULL)
02573 child = RIGHT(successor);
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590 memmove(tmp, successor, sizeof(dns_rbtnode_t));
02591
02592 if (IS_ROOT(delete)) {
02593 *rootp = successor;
02594 successor->is_root = ISC_TRUE;
02595 delete->is_root = ISC_FALSE;
02596
02597 } else
02598 if (LEFT(PARENT(delete)) == delete)
02599 LEFT(PARENT(delete)) = successor;
02600 else
02601 RIGHT(PARENT(delete)) = successor;
02602
02603 PARENT(successor) = PARENT(delete);
02604 LEFT(successor) = LEFT(delete);
02605 RIGHT(successor) = RIGHT(delete);
02606 COLOR(successor) = COLOR(delete);
02607
02608 if (LEFT(successor) != NULL)
02609 PARENT(LEFT(successor)) = successor;
02610 if (RIGHT(successor) != successor)
02611 PARENT(RIGHT(successor)) = successor;
02612
02613
02614
02615
02616
02617
02618 INSIST(! IS_ROOT(delete));
02619
02620 if (PARENT(tmp) == delete) {
02621
02622
02623
02624 RIGHT(successor) = delete;
02625 PARENT(delete) = successor;
02626
02627 } else {
02628 LEFT(PARENT(tmp)) = delete;
02629 PARENT(delete) = PARENT(tmp);
02630 }
02631
02632
02633
02634
02635 LEFT(delete) = NULL;
02636 RIGHT(delete) = RIGHT(tmp);
02637 COLOR(delete) = COLOR(tmp);
02638 }
02639
02640
02641
02642
02643 if (! IS_ROOT(delete)) {
02644 if (LEFT(PARENT(delete)) == delete)
02645 LEFT(PARENT(delete)) = child;
02646 else
02647 RIGHT(PARENT(delete)) = child;
02648
02649 if (child != NULL)
02650 PARENT(child) = PARENT(delete);
02651
02652 } else {
02653
02654
02655
02656
02657 *rootp = child;
02658 child->is_root = 1;
02659 PARENT(child) = PARENT(delete);
02660 }
02661
02662
02663
02664
02665 if (IS_BLACK(delete)) {
02666 parent = PARENT(delete);
02667
02668 while (child != *rootp && IS_BLACK(child)) {
02669 INSIST(child == NULL || ! IS_ROOT(child));
02670
02671 if (LEFT(parent) == child) {
02672 sibling = RIGHT(parent);
02673
02674 if (IS_RED(sibling)) {
02675 MAKE_BLACK(sibling);
02676 MAKE_RED(parent);
02677 rotate_left(parent, rootp);
02678 sibling = RIGHT(parent);
02679 }
02680
02681 INSIST(sibling != NULL);
02682
02683 if (IS_BLACK(LEFT(sibling)) &&
02684 IS_BLACK(RIGHT(sibling))) {
02685 MAKE_RED(sibling);
02686 child = parent;
02687
02688 } else {
02689
02690 if (IS_BLACK(RIGHT(sibling))) {
02691 MAKE_BLACK(LEFT(sibling));
02692 MAKE_RED(sibling);
02693 rotate_right(sibling, rootp);
02694 sibling = RIGHT(parent);
02695 }
02696
02697 COLOR(sibling) = COLOR(parent);
02698 MAKE_BLACK(parent);
02699 INSIST(RIGHT(sibling) != NULL);
02700 MAKE_BLACK(RIGHT(sibling));
02701 rotate_left(parent, rootp);
02702 child = *rootp;
02703 }
02704
02705 } else {
02706
02707
02708
02709
02710
02711 sibling = LEFT(parent);
02712
02713 if (IS_RED(sibling)) {
02714 MAKE_BLACK(sibling);
02715 MAKE_RED(parent);
02716 rotate_right(parent, rootp);
02717 sibling = LEFT(parent);
02718 }
02719
02720 INSIST(sibling != NULL);
02721
02722 if (IS_BLACK(LEFT(sibling)) &&
02723 IS_BLACK(RIGHT(sibling))) {
02724 MAKE_RED(sibling);
02725 child = parent;
02726
02727 } else {
02728 if (IS_BLACK(LEFT(sibling))) {
02729 MAKE_BLACK(RIGHT(sibling));
02730 MAKE_RED(sibling);
02731 rotate_left(sibling, rootp);
02732 sibling = LEFT(parent);
02733 }
02734
02735 COLOR(sibling) = COLOR(parent);
02736 MAKE_BLACK(parent);
02737 INSIST(LEFT(sibling) != NULL);
02738 MAKE_BLACK(LEFT(sibling));
02739 rotate_right(parent, rootp);
02740 child = *rootp;
02741 }
02742 }
02743
02744 parent = PARENT(child);
02745 }
02746
02747 if (IS_RED(child))
02748 MAKE_BLACK(child);
02749 }
02750 }
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767 static isc_result_t
02768 deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
02769 isc_result_t result = ISC_R_SUCCESS;
02770
02771 REQUIRE(VALID_RBT(rbt));
02772
02773 if (node == NULL)
02774 return (result);
02775
02776 if (LEFT(node) != NULL) {
02777 result = deletetree(rbt, LEFT(node));
02778 if (result != ISC_R_SUCCESS)
02779 goto done;
02780 LEFT(node) = NULL;
02781 }
02782 if (RIGHT(node) != NULL) {
02783 result = deletetree(rbt, RIGHT(node));
02784 if (result != ISC_R_SUCCESS)
02785 goto done;
02786 RIGHT(node) = NULL;
02787 }
02788 if (DOWN(node) != NULL) {
02789 result = deletetree(rbt, DOWN(node));
02790 if (result != ISC_R_SUCCESS)
02791 goto done;
02792 DOWN(node) = NULL;
02793 }
02794 done:
02795 if (result != ISC_R_SUCCESS)
02796 return (result);
02797
02798 if (DATA(node) != NULL && rbt->data_deleter != NULL)
02799 rbt->data_deleter(DATA(node), rbt->deleter_arg);
02800
02801 unhash_node(rbt, node);
02802 #if DNS_RBT_USEMAGIC
02803 node->magic = 0;
02804 #endif
02805
02806 freenode(rbt, &node);
02807 return (result);
02808 }
02809
02810 static void
02811 freenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep) {
02812 dns_rbtnode_t *node = *nodep;
02813
02814 if (node->is_mmapped == 0) {
02815 isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
02816 }
02817 *nodep = NULL;
02818
02819 rbt->nodecount--;
02820 }
02821
02822 static void
02823 deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep) {
02824 dns_rbtnode_t *parent;
02825 dns_rbtnode_t *node = *nodep;
02826
02827 REQUIRE(VALID_RBT(rbt));
02828
02829 again:
02830 if (node == NULL) {
02831 *nodep = NULL;
02832 return;
02833 }
02834
02835 traverse:
02836 if (LEFT(node) != NULL) {
02837 node = LEFT(node);
02838 goto traverse;
02839 }
02840 if (DOWN(node) != NULL) {
02841 node = DOWN(node);
02842 goto traverse;
02843 }
02844
02845 if (DATA(node) != NULL && rbt->data_deleter != NULL)
02846 rbt->data_deleter(DATA(node), rbt->deleter_arg);
02847
02848
02849
02850
02851
02852 #if DNS_RBT_USEMAGIC
02853 node->magic = 0;
02854 #endif
02855 parent = PARENT(node);
02856 if (RIGHT(node) != NULL)
02857 PARENT(RIGHT(node)) = parent;
02858 if (parent != NULL) {
02859 if (LEFT(parent) == node)
02860 LEFT(parent) = RIGHT(node);
02861 else if (DOWN(parent) == node)
02862 DOWN(parent) = RIGHT(node);
02863 } else
02864 parent = RIGHT(node);
02865
02866 freenode(rbt, &node);
02867
02868 node = parent;
02869 if (quantum != 0 && --quantum == 0) {
02870 *nodep = node;
02871 return;
02872 }
02873 goto again;
02874 }
02875
02876 static size_t
02877 getheight_helper(dns_rbtnode_t *node) {
02878 size_t dl, dr;
02879 size_t this_height, down_height;
02880
02881 if (node == NULL)
02882 return (0);
02883
02884 dl = getheight_helper(LEFT(node));
02885 dr = getheight_helper(RIGHT(node));
02886
02887 this_height = ISC_MAX(dl + 1, dr + 1);
02888 down_height = getheight_helper(DOWN(node));
02889
02890 return (ISC_MAX(this_height, down_height));
02891 }
02892
02893 size_t
02894 dns__rbt_getheight(dns_rbt_t *rbt) {
02895 return (getheight_helper(rbt->root));
02896 }
02897
02898 static isc_boolean_t
02899 check_properties_helper(dns_rbtnode_t *node) {
02900 if (node == NULL)
02901 return (ISC_TRUE);
02902
02903 if (IS_RED(node)) {
02904
02905 if (IS_ROOT(node))
02906 return (ISC_FALSE);
02907
02908
02909 if (IS_RED(LEFT(node)) || IS_RED(RIGHT(node)))
02910 return (ISC_FALSE);
02911 }
02912
02913
02914
02915
02916 if (((!PARENT(node)) ||
02917 (DOWN(PARENT(node)) == node)) &&
02918 (!IS_ROOT(node)))
02919 {
02920 return (ISC_FALSE);
02921 }
02922
02923
02924 return (check_properties_helper(LEFT(node)) &&
02925 check_properties_helper(RIGHT(node)) &&
02926 check_properties_helper(DOWN(node)));
02927 }
02928
02929 static isc_boolean_t
02930 check_black_distance_helper(dns_rbtnode_t *node, size_t *distance) {
02931 size_t dl, dr, dd;
02932
02933 if (node == NULL) {
02934 *distance = 1;
02935 return (ISC_TRUE);
02936 }
02937
02938 if (!check_black_distance_helper(LEFT(node), &dl))
02939 return (ISC_FALSE);
02940
02941 if (!check_black_distance_helper(RIGHT(node), &dr))
02942 return (ISC_FALSE);
02943
02944 if (!check_black_distance_helper(DOWN(node), &dd))
02945 return (ISC_FALSE);
02946
02947
02948 if (dl != dr)
02949 return (ISC_FALSE);
02950
02951 if (IS_BLACK(node))
02952 dl++;
02953
02954 *distance = dl;
02955
02956 return (ISC_TRUE);
02957 }
02958
02959 isc_boolean_t
02960 dns__rbt_checkproperties(dns_rbt_t *rbt) {
02961 size_t dd;
02962
02963 if (!check_properties_helper(rbt->root))
02964 return (ISC_FALSE);
02965
02966
02967
02968
02969
02970
02971 return (check_black_distance_helper(rbt->root, &dd));
02972 }
02973
02974 static void
02975 dns_rbt_indent(FILE *f, int depth) {
02976 int i;
02977
02978 fprintf(f, "%4d ", depth);
02979
02980 for (i = 0; i < depth; i++)
02981 fprintf(f, "- ");
02982 }
02983
02984 void
02985 dns_rbt_printnodeinfo(dns_rbtnode_t *n, FILE *f) {
02986 fprintf(f, "Node info for nodename: ");
02987 printnodename(n, ISC_TRUE, f);
02988 fprintf(f, "\n");
02989
02990 fprintf(f, "n = %p\n", n);
02991
02992 fprintf(f, "Relative pointers: %s%s%s%s%s\n",
02993 (n->parent_is_relative == 1 ? " P" : ""),
02994 (n->right_is_relative == 1 ? " R" : ""),
02995 (n->left_is_relative == 1 ? " L" : ""),
02996 (n->down_is_relative == 1 ? " D" : ""),
02997 (n->data_is_relative == 1 ? " T" : ""));
02998
02999 fprintf(f, "node lock address = %d\n", n->locknum);
03000
03001 fprintf(f, "Parent: %p\n", n->parent);
03002 fprintf(f, "Right: %p\n", n->right);
03003 fprintf(f, "Left: %p\n", n->left);
03004 fprintf(f, "Down: %p\n", n->down);
03005 fprintf(f, "daTa: %p\n", n->data);
03006 }
03007
03008 static void
03009 printnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f) {
03010 isc_region_t r;
03011 dns_name_t name;
03012 char buffer[DNS_NAME_FORMATSIZE];
03013 dns_offsets_t offsets;
03014
03015 r.length = NAMELEN(node);
03016 r.base = NAME(node);
03017
03018 dns_name_init(&name, offsets);
03019 dns_name_fromregion(&name, &r);
03020
03021 dns_name_format(&name, buffer, sizeof(buffer));
03022
03023 if (quoted)
03024 fprintf(f, "\"%s\"", buffer);
03025 else
03026 fprintf(f, "%s", buffer);
03027 }
03028
03029 static void
03030 print_text_helper(dns_rbtnode_t *root, dns_rbtnode_t *parent,
03031 int depth, const char *direction,
03032 void (*data_printer)(FILE *, void *), FILE *f)
03033 {
03034 dns_rbt_indent(f, depth);
03035
03036 if (root != NULL) {
03037 printnodename(root, ISC_TRUE, f);
03038 fprintf(f, " (%s, %s", direction,
03039 IS_RED(root) ? "RED" : "BLACK");
03040
03041 if ((! IS_ROOT(root) && PARENT(root) != parent) ||
03042 ( IS_ROOT(root) && depth > 0 &&
03043 DOWN(PARENT(root)) != root)) {
03044
03045 fprintf(f, " (BAD parent pointer! -> ");
03046 if (PARENT(root) != NULL)
03047 printnodename(PARENT(root), ISC_TRUE, f);
03048 else
03049 fprintf(f, "NULL");
03050 fprintf(f, ")");
03051 }
03052
03053 fprintf(f, ")");
03054
03055 if (root->data != NULL && data_printer != NULL) {
03056 fprintf(f, " data@%p: ", root->data);
03057 data_printer(f, root->data);
03058 }
03059 fprintf(f, "\n");
03060
03061 depth++;
03062
03063 if (IS_RED(root) && IS_RED(LEFT(root)))
03064 fprintf(f, "** Red/Red color violation on left\n");
03065 print_text_helper(LEFT(root), root, depth, "left",
03066 data_printer, f);
03067
03068 if (IS_RED(root) && IS_RED(RIGHT(root)))
03069 fprintf(f, "** Red/Red color violation on right\n");
03070 print_text_helper(RIGHT(root), root, depth, "right",
03071 data_printer, f);
03072
03073 print_text_helper(DOWN(root), NULL, depth, "down",
03074 data_printer, f);
03075 } else {
03076 fprintf(f, "NULL (%s)\n", direction);
03077 }
03078 }
03079
03080 void
03081 dns_rbt_printtext(dns_rbt_t *rbt,
03082 void (*data_printer)(FILE *, void *), FILE *f)
03083 {
03084 REQUIRE(VALID_RBT(rbt));
03085
03086 print_text_helper(rbt->root, NULL, 0, "root", data_printer, f);
03087 }
03088
03089 static int
03090 print_dot_helper(dns_rbtnode_t *node, unsigned int *nodecount,
03091 isc_boolean_t show_pointers, FILE *f)
03092 {
03093 unsigned int l, r, d;
03094
03095 if (node == NULL)
03096 return (0);
03097
03098 l = print_dot_helper(LEFT(node), nodecount, show_pointers, f);
03099 r = print_dot_helper(RIGHT(node), nodecount, show_pointers, f);
03100 d = print_dot_helper(DOWN(node), nodecount, show_pointers, f);
03101
03102 *nodecount += 1;
03103
03104 fprintf(f, "node%u[label = \"<f0> |<f1> ", *nodecount);
03105 printnodename(node, ISC_FALSE, f);
03106 fprintf(f, "|<f2>");
03107
03108 if (show_pointers)
03109 fprintf(f, "|<f3> n=%p|<f4> p=%p", node, PARENT(node));
03110
03111 fprintf(f, "\"] [");
03112
03113 if (IS_RED(node))
03114 fprintf(f, "color=red");
03115 else
03116 fprintf(f, "color=black");
03117
03118
03119
03120
03121 if (IS_ROOT(node))
03122 fprintf(f, ",penwidth=3");
03123
03124 if (IS_EMPTY(node))
03125 fprintf(f, ",style=filled,fillcolor=lightgrey");
03126
03127 fprintf(f, "];\n");
03128
03129 if (LEFT(node) != NULL)
03130 fprintf(f, "\"node%u\":f0 -> \"node%u\":f1;\n", *nodecount, l);
03131
03132 if (DOWN(node) != NULL)
03133 fprintf(f, "\"node%u\":f1 -> \"node%u\":f1 [penwidth=5];\n",
03134 *nodecount, d);
03135
03136 if (RIGHT(node) != NULL)
03137 fprintf(f, "\"node%u\":f2 -> \"node%u\":f1;\n", *nodecount, r);
03138
03139 return (*nodecount);
03140 }
03141
03142 void
03143 dns_rbt_printdot(dns_rbt_t *rbt, isc_boolean_t show_pointers, FILE *f) {
03144 unsigned int nodecount = 0;
03145
03146 REQUIRE(VALID_RBT(rbt));
03147
03148 fprintf(f, "digraph g {\n");
03149 fprintf(f, "node [shape = record,height=.1];\n");
03150 print_dot_helper(rbt->root, &nodecount, show_pointers, f);
03151 fprintf(f, "}\n");
03152 }
03153
03154
03155
03156
03157
03158 void
03159 dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
03160
03161 REQUIRE(chain != NULL);
03162
03163
03164
03165
03166 chain->mctx = mctx;
03167 chain->end = NULL;
03168 chain->level_count = 0;
03169 chain->level_matches = 0;
03170 memset(chain->levels, 0, sizeof(chain->levels));
03171
03172 chain->magic = CHAIN_MAGIC;
03173 }
03174
03175 isc_result_t
03176 dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
03177 dns_name_t *origin, dns_rbtnode_t **node)
03178 {
03179 isc_result_t result = ISC_R_SUCCESS;
03180
03181 REQUIRE(VALID_CHAIN(chain));
03182
03183 if (node != NULL)
03184 *node = chain->end;
03185
03186 if (chain->end == NULL)
03187 return (ISC_R_NOTFOUND);
03188
03189 if (name != NULL) {
03190 NODENAME(chain->end, name);
03191
03192 if (chain->level_count == 0) {
03193
03194
03195
03196
03197 INSIST(dns_name_isabsolute(name));
03198
03199
03200
03201
03202 name->labels--;
03203 name->length--;
03204 name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
03205 }
03206 }
03207
03208 if (origin != NULL) {
03209 if (chain->level_count > 0)
03210 result = chain_name(chain, origin, ISC_FALSE);
03211 else
03212 result = dns_name_copy(dns_rootname, origin, NULL);
03213 }
03214
03215 return (result);
03216 }
03217
03218 isc_result_t
03219 dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
03220 dns_name_t *origin)
03221 {
03222 dns_rbtnode_t *current, *previous, *predecessor;
03223 isc_result_t result = ISC_R_SUCCESS;
03224 isc_boolean_t new_origin = ISC_FALSE;
03225
03226 REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
03227
03228 predecessor = NULL;
03229
03230 current = chain->end;
03231
03232 if (LEFT(current) != NULL) {
03233
03234
03235
03236
03237 current = LEFT(current);
03238
03239 while (RIGHT(current) != NULL)
03240 current = RIGHT(current);
03241
03242 predecessor = current;
03243
03244 } else {
03245
03246
03247
03248
03249
03250
03251 while (! IS_ROOT(current)) {
03252 previous = current;
03253 current = PARENT(current);
03254
03255 if (RIGHT(current) == previous) {
03256 predecessor = current;
03257 break;
03258 }
03259 }
03260 }
03261
03262 if (predecessor != NULL) {
03263
03264
03265
03266
03267 if (DOWN(predecessor) != NULL) {
03268
03269
03270
03271
03272
03273 do {
03274
03275
03276
03277
03278
03279
03280 ADD_LEVEL(chain, predecessor);
03281 predecessor = DOWN(predecessor);
03282
03283
03284
03285
03286 while (RIGHT(predecessor) != NULL)
03287 predecessor = RIGHT(predecessor);
03288 } while (DOWN(predecessor) != NULL);
03289
03290
03291 if (origin != NULL)
03292 new_origin = ISC_TRUE;
03293 }
03294
03295 } else if (chain->level_count > 0) {
03296
03297
03298
03299
03300
03301
03302 INSIST(chain->level_count > 0 && IS_ROOT(current));
03303 predecessor = chain->levels[--chain->level_count];
03304
03305
03306
03307
03308
03309
03310
03311 if (origin != NULL &&
03312 (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
03313 new_origin = ISC_TRUE;
03314 }
03315
03316 if (predecessor != NULL) {
03317 chain->end = predecessor;
03318
03319 if (new_origin) {
03320 result = dns_rbtnodechain_current(chain, name, origin,
03321 NULL);
03322 if (result == ISC_R_SUCCESS)
03323 result = DNS_R_NEWORIGIN;
03324
03325 } else
03326 result = dns_rbtnodechain_current(chain, name, NULL,
03327 NULL);
03328
03329 } else
03330 result = ISC_R_NOMORE;
03331
03332 return (result);
03333 }
03334
03335 isc_result_t
03336 dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
03337 dns_name_t *origin)
03338 {
03339 dns_rbtnode_t *current, *successor;
03340 isc_result_t result = ISC_R_SUCCESS;
03341 isc_boolean_t new_origin = ISC_FALSE;
03342
03343 REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
03344
03345 successor = NULL;
03346
03347 current = chain->end;
03348
03349 if (DOWN(current) != NULL) {
03350
03351
03352
03353
03354
03355 if (chain->level_count > 0 ||
03356 OFFSETLEN(current) > 1)
03357 new_origin = ISC_TRUE;
03358
03359 ADD_LEVEL(chain, current);
03360 current = DOWN(current);
03361
03362 while (LEFT(current) != NULL)
03363 current = LEFT(current);
03364
03365 successor = current;
03366 }
03367
03368 if (successor != NULL) {
03369 chain->end = successor;
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380 if (name != NULL)
03381 NODENAME(chain->end, name);
03382
03383 if (new_origin) {
03384 if (origin != NULL)
03385 result = chain_name(chain, origin, ISC_FALSE);
03386
03387 if (result == ISC_R_SUCCESS)
03388 result = DNS_R_NEWORIGIN;
03389
03390 } else
03391 result = ISC_R_SUCCESS;
03392
03393 } else
03394 result = ISC_R_NOMORE;
03395
03396 return (result);
03397 }
03398
03399 isc_result_t
03400 dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
03401 dns_rbtnode_t *current, *previous, *successor;
03402 isc_result_t result = ISC_R_SUCCESS;
03403
03404 REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
03405
03406 successor = NULL;
03407
03408 current = chain->end;
03409
03410 if (RIGHT(current) == NULL) {
03411 while (! IS_ROOT(current)) {
03412 previous = current;
03413 current = PARENT(current);
03414
03415 if (LEFT(current) == previous) {
03416 successor = current;
03417 break;
03418 }
03419 }
03420 } else {
03421 current = RIGHT(current);
03422
03423 while (LEFT(current) != NULL)
03424 current = LEFT(current);
03425
03426 successor = current;
03427 }
03428
03429 if (successor != NULL) {
03430 chain->end = successor;
03431
03432 if (name != NULL)
03433 NODENAME(chain->end, name);
03434
03435 result = ISC_R_SUCCESS;
03436 } else
03437 result = ISC_R_NOMORE;
03438
03439 return (result);
03440 }
03441
03442 isc_result_t
03443 dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
03444 dns_name_t *origin)
03445 {
03446 dns_rbtnode_t *current, *previous, *successor;
03447 isc_result_t result = ISC_R_SUCCESS;
03448 isc_boolean_t new_origin = ISC_FALSE;
03449
03450 REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
03451
03452 successor = NULL;
03453
03454 current = chain->end;
03455
03456
03457
03458
03459
03460 if (DOWN(current) != NULL) {
03461
03462
03463
03464
03465
03466 if (chain->level_count > 0 ||
03467 OFFSETLEN(current) > 1)
03468 new_origin = ISC_TRUE;
03469
03470 ADD_LEVEL(chain, current);
03471 current = DOWN(current);
03472
03473 while (LEFT(current) != NULL)
03474 current = LEFT(current);
03475
03476 successor = current;
03477
03478 } else if (RIGHT(current) == NULL) {
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489 do {
03490 while (! IS_ROOT(current)) {
03491 previous = current;
03492 current = PARENT(current);
03493
03494 if (LEFT(current) == previous) {
03495 successor = current;
03496 break;
03497 }
03498 }
03499
03500 if (successor == NULL) {
03501
03502
03503
03504
03505 if (chain->level_count == 0)
03506 break;
03507
03508 current = chain->levels[--chain->level_count];
03509 new_origin = ISC_TRUE;
03510
03511 if (RIGHT(current) != NULL)
03512 break;
03513 }
03514 } while (successor == NULL);
03515 }
03516
03517 if (successor == NULL && RIGHT(current) != NULL) {
03518 current = RIGHT(current);
03519
03520 while (LEFT(current) != NULL)
03521 current = LEFT(current);
03522
03523 successor = current;
03524 }
03525
03526 if (successor != NULL) {
03527 chain->end = successor;
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538 if (name != NULL)
03539 NODENAME(chain->end, name);
03540
03541 if (new_origin) {
03542 if (origin != NULL)
03543 result = chain_name(chain, origin, ISC_FALSE);
03544
03545 if (result == ISC_R_SUCCESS)
03546 result = DNS_R_NEWORIGIN;
03547
03548 } else
03549 result = ISC_R_SUCCESS;
03550
03551 } else
03552 result = ISC_R_NOMORE;
03553
03554 return (result);
03555 }
03556
03557 isc_result_t
03558 dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
03559 dns_name_t *name, dns_name_t *origin)
03560
03561 {
03562 isc_result_t result;
03563
03564 REQUIRE(VALID_RBT(rbt));
03565 REQUIRE(VALID_CHAIN(chain));
03566
03567 dns_rbtnodechain_reset(chain);
03568
03569 chain->end = rbt->root;
03570
03571 result = dns_rbtnodechain_current(chain, name, origin, NULL);
03572
03573 if (result == ISC_R_SUCCESS)
03574 result = DNS_R_NEWORIGIN;
03575
03576 return (result);
03577 }
03578
03579 isc_result_t
03580 dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
03581 dns_name_t *name, dns_name_t *origin)
03582
03583 {
03584 isc_result_t result;
03585
03586 REQUIRE(VALID_RBT(rbt));
03587 REQUIRE(VALID_CHAIN(chain));
03588
03589 dns_rbtnodechain_reset(chain);
03590
03591 result = move_chain_to_last(chain, rbt->root);
03592 if (result != ISC_R_SUCCESS)
03593 return (result);
03594
03595 result = dns_rbtnodechain_current(chain, name, origin, NULL);
03596
03597 if (result == ISC_R_SUCCESS)
03598 result = DNS_R_NEWORIGIN;
03599
03600 return (result);
03601 }
03602
03603
03604 void
03605 dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
03606
03607 REQUIRE(VALID_CHAIN(chain));
03608
03609
03610
03611
03612
03613 chain->end = NULL;
03614 chain->level_count = 0;
03615 chain->level_matches = 0;
03616 }
03617
03618 void
03619 dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
03620
03621
03622
03623
03624
03625 dns_rbtnodechain_reset(chain);
03626
03627 chain->magic = 0;
03628 }
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638