9e6de65c57eddc3790badaad3b9481aaaed18e03Brian Wellington/*
6fb9b25791778f69002eb72be6235e20d98ec452Tinderbox User * Copyright (C) 1999-2005, 2007-2009, 2011-2017 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
d09197467bbb156dccf0cbe72bb5c63480d5cfdcDavid Lawrence
d09197467bbb156dccf0cbe72bb5c63480d5cfdcDavid Lawrence/* Principal Authors: DCL */
d09197467bbb156dccf0cbe72bb5c63480d5cfdcDavid Lawrence
64ba6e4cc3a0ccf8c8c6349fa75b937ca9bad9a6Michael Graff#include <config.h>
64ba6e4cc3a0ccf8c8c6349fa75b937ca9bad9a6Michael Graff
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <sys/stat.h>
62ac31d7fd09b0bf2231e5f55ed85aed39bc2df6Evan Hunt#ifdef HAVE_INTTYPES_H
62ac31d7fd09b0bf2231e5f55ed85aed39bc2df6Evan Hunt#include <inttypes.h> /* uintptr_t */
62ac31d7fd09b0bf2231e5f55ed85aed39bc2df6Evan Hunt#endif
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt#include <isc/crc64.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <isc/file.h>
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#include <isc/hex.h>
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence#include <isc/mem.h>
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt#include <isc/once.h>
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrews#include <isc/platform.h>
dd57718608494835363244429432599aa15124a3Andreas Gustafsson#include <isc/print.h>
5597be9bb88de138dfec9fa9176708443813925eTatuya JINMEI 神明達哉#include <isc/refcount.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <isc/socket.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <isc/stdio.h>
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrence#include <isc/string.h>
82a1986c04057804edf670bf5d59f716785af789Bob Halley#include <isc/util.h>
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence * This define is so dns/name.h (included by dns/fixedname.h) uses more
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence * efficient macro calls instead of functions for a few operations.
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence */
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence#define DNS_NAME_USEINLINE 1
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence
891a1bead8d02d29eb7b4993d7c0975047b0963dDavid Lawrence#include <dns/fixedname.h>
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#include <dns/log.h>
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrence#include <dns/rbt.h>
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrence#include <dns/result.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <dns/version.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#include <unistd.h>
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#define CHECK(x) \
7829fad4093f2c1985b1efb7cea00287ff015d2bckb do { \
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = (x); \
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (result != ISC_R_SUCCESS) \
7829fad4093f2c1985b1efb7cea00287ff015d2bckb goto cleanup; \
7829fad4093f2c1985b1efb7cea00287ff015d2bckb } while (0)
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
c80dde0676a7f36f65e0ad8d646bf505705fe64bDavid Lawrence/*
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * XXXDCL Since parent pointers were added in again, I could remove all of the
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * _lastnode. This would involve pretty major change to the API.
c80dde0676a7f36f65e0ad8d646bf505705fe64bDavid Lawrence */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define RBT_HASH_SIZE 64
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence#ifdef RBT_MEM_TEST
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence#undef RBT_HASH_SIZE
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence#endif
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencestruct dns_rbt {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman unsigned int magic;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman isc_mem_t * mctx;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t * root;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman void (*data_deleter)(void *, void *);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman void * deleter_arg;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman unsigned int nodecount;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman size_t hashsize;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t ** hashtable;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman void * mmap_location;
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence};
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence#define RED 0
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence#define BLACK 1
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/*
c9611b45736af157e2993c6ef852e55e8e24ca83Evan Hunt * This is the header for map-format RBT images. It is populated,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * and then written, as the LAST thing done to the file before returning.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * Writing this last (with zeros in the header area initially) will ensure
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * that the header is only valid when the RBT image is also valid.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckbtypedef struct file_header file_header_t;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/* Pad to 32 bytes */
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic char FILE_VERSION[32] = "\0";
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/* Header length, always the same size regardless of structure size */
b4a865ee130c8a1623a7060c27efec0c1f238403Francis Dupont#define HEADER_LENGTH 1024
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstruct file_header {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char version1[32];
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_uint64_t first_node_offset; /* usually 1024 */
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User /*
c9611b45736af157e2993c6ef852e55e8e24ca83Evan Hunt * information about the system on which the map file was generated
c9611b45736af157e2993c6ef852e55e8e24ca83Evan Hunt * will be used to tell if we can load the map file or not
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_uint32_t ptrsize;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb unsigned int bigendian:1; /* big or little endian system */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb unsigned int nodecount; /* shadow from rbt structure */
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_uint64_t crc;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char version2[32]; /* repeated; must match version1 */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb};
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/*
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * The following declarations are for the serialization of an RBT:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * step one: write out a zeroed header of 1024 bytes
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * step two: walk the tree in a depth-first, left-right-down order, writing
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * out the nodes, reserving space as we go, correcting addresses to point
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User * at the proper offset in the file, and setting a flag for each pointer to
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User * indicate that it is a reference to a location in the file, rather than in
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * memory.
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User * step three: write out the header, adding the information that will be
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * needed to re-create the tree object itself.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * The RBTDB object will do this three times, once for each of the three
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * RBT objects it contains.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * Note: 'file' must point an actual open file that can be mmapped
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * and fseeked, not to a pipe or stream
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic isc_result_t
7829fad4093f2c1985b1efb7cea00287ff015d2bckbdns_rbt_zero_header(FILE *file);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic isc_result_t
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Huntwrite_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_uint64_t crc);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntstatic isc_boolean_t
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntmatch_header_version(file_header_t *header);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic isc_result_t
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox Userserialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User uintptr_t right, uintptr_t down, uintptr_t parent,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt uintptr_t data, isc_uint64_t *crc);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic isc_result_t
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox Userserialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt dns_rbtdatawriter_t datawriter, void *writer_arg,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt uintptr_t *where, isc_uint64_t *crc);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/*
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User * The following functions allow you to get the actual address of a pointer
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User * without having to use an if statement to check to see if that address is
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * relative or not
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline dns_rbtnode_t *
7829fad4093f2c1985b1efb7cea00287ff015d2bckbgetparent(dns_rbtnode_t *node, file_header_t *header) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char *adjusted_address = (char *)(node->parent);
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User adjusted_address += node->parent_is_relative * (uintptr_t)header;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return ((dns_rbtnode_t *)adjusted_address);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline dns_rbtnode_t *
7829fad4093f2c1985b1efb7cea00287ff015d2bckbgetleft(dns_rbtnode_t *node, file_header_t *header) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char *adjusted_address = (char *)(node->left);
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User adjusted_address += node->left_is_relative * (uintptr_t)header;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return ((dns_rbtnode_t *)adjusted_address);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline dns_rbtnode_t *
7829fad4093f2c1985b1efb7cea00287ff015d2bckbgetright(dns_rbtnode_t *node, file_header_t *header) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char *adjusted_address = (char *)(node->right);
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User adjusted_address += node->right_is_relative * (uintptr_t)header;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return ((dns_rbtnode_t *)adjusted_address);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline dns_rbtnode_t *
7829fad4093f2c1985b1efb7cea00287ff015d2bckbgetdown(dns_rbtnode_t *node, file_header_t *header) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char *adjusted_address = (char *)(node->down);
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User adjusted_address += node->down_is_relative * (uintptr_t)header;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return ((dns_rbtnode_t *)adjusted_address);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline dns_rbtnode_t *
7829fad4093f2c1985b1efb7cea00287ff015d2bckbgetdata(dns_rbtnode_t *node, file_header_t *header) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char *adjusted_address = (char *)(node->data);
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User adjusted_address += node->data_is_relative * (uintptr_t)header;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return ((dns_rbtnode_t *)adjusted_address);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence * Elements of the rbtnode structure.
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define PARENT(node) ((node)->parent)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define LEFT(node) ((node)->left)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define RIGHT(node) ((node)->right)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define DOWN(node) ((node)->down)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#define UPPERNODE(node) ((node)->uppernode)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define DATA(node) ((node)->data)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman#define IS_EMPTY(node) ((node)->data == NULL)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define HASHNEXT(node) ((node)->hashnext)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define HASHVAL(node) ((node)->hashval)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define COLOR(node) ((node)->color)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define NAMELEN(node) ((node)->namelen)
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews#define OLDNAMELEN(node) ((node)->oldnamelen)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define OFFSETLEN(node) ((node)->offsetlen)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define ATTRS(node) ((node)->attributes)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define IS_ROOT(node) ISC_TF((node)->is_root == 1)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence * Structure elements from the rbtdb.c, not
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence * used as part of the rbt.c algorithms.
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define DIRTY(node) ((node)->dirty)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define WILD(node) ((node)->wild)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define LOCKNUM(node) ((node)->locknum)
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews * The variable length stuff stored after the node has the following
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews * structure.
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews *
ad9772c559c6aa42f8930f4acf1a2d833a08040aMichał Kępień * &lt;name_data&gt;{1..255}&lt;oldoffsetlen&gt;{1}&lt;offsets&gt;{1..128}
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews *
ad9772c559c6aa42f8930f4acf1a2d833a08040aMichał Kępień * &lt;name_data&gt; contains the name of the node when it was created.
ad9772c559c6aa42f8930f4acf1a2d833a08040aMichał Kępień * &lt;oldoffsetlen&gt; contains the length of &lt;offsets&gt; when the node was created.
ad9772c559c6aa42f8930f4acf1a2d833a08040aMichał Kępień * &lt;offsets&gt; contains the offets into name for each label when the node was
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews * created.
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence */
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define NAME(node) ((unsigned char *)((node) + 1))
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews#define OFFSETS(node) (NAME(node) + OLDNAMELEN(node) + 1)
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews#define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define NODE_SIZE(node) (sizeof(*node) + \
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence * Color management.
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define IS_RED(node) ((node) != NULL && (node)->color == RED)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define MAKE_RED(node) ((node)->color = RED)
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff#define MAKE_BLACK(node) ((node)->color = BLACK)
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence * Chain management.
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence *
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence * The "ancestors" member of chains were removed, with their job now
47b7dfffe5d806c6a5e99ef17f07bcde812c2132Francis Dupont * being wholly handled by parent pointers (which didn't exist, because
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence * of memory concerns, when chains were first implemented).
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence */
f036af2c718147408d738081cdb0a564b981b4cdDavid Lawrence#define ADD_LEVEL(chain, node) \
b16d99bac1d100735224ab3eaa84632537ff21b5Mark Andrews do { \
b16d99bac1d100735224ab3eaa84632537ff21b5Mark Andrews INSIST((chain)->level_count < DNS_RBT_LEVELBLOCK); \
b16d99bac1d100735224ab3eaa84632537ff21b5Mark Andrews (chain)->levels[(chain)->level_count++] = (node); \
b16d99bac1d100735224ab3eaa84632537ff21b5Mark Andrews } while (0)
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley * The following macros directly access normally private name variables.
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley * These macros are used to avoid a lot of function calls in the critical
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley * path of the tree traversal code.
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley */
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic inline void
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan HuntNODENAME(dns_rbtnode_t *node, dns_name_t *name) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->length = NAMELEN(node);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->labels = OFFSETLEN(node);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->ndata = NAME(node);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->offsets = OFFSETS(node);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->attributes = ATTRS(node);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb name->attributes |= DNS_NAMEATTR_READONLY;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanvoid
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbtnode_nodename(dns_rbtnode_t *node, dns_name_t *name) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->length = NAMELEN(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->labels = OFFSETLEN(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->ndata = NAME(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->offsets = OFFSETS(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->attributes = ATTRS(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman name->attributes |= DNS_NAMEATTR_READONLY;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbtnode_t *
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbt_root(dns_rbt_t *rbt) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return rbt->root;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#ifdef DNS_RBT_USEHASH
7554feaef6057f5ea2926076900ac7634b911456Mark Andrewsstatic isc_result_t
7554feaef6057f5ea2926076900ac7634b911456Mark Andrewsinithash(dns_rbt_t *rbt);
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#endif
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence#ifdef DEBUG
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence#define inline
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * A little something to help out in GDB.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrencedns_name_t Name(dns_rbtnode_t *node);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencedns_name_t
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid LawrenceName(dns_rbtnode_t *node) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t name;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(node, &name);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (name);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
401fc772b1bf058a981e3c474fa6502f6ee0e2bfDavid Lawrence
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Huntstatic void
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunthexdump(const char *desc, unsigned char *data, size_t size) {
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews char hexdump[BUFSIZ * 2 + 1];
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt isc_buffer_t b;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt isc_region_t r;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews isc_result_t result;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews size_t bytes;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews fprintf(stderr, "%s: ", desc);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews do {
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews isc_buffer_init(&b, hexdump, sizeof(hexdump));
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews r.base = data;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews r.length = bytes = (size > BUFSIZ) ? BUFSIZ : size;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews result = isc_hex_totext(&r, 0, "", &b);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews RUNTIME_CHECK(result == ISC_R_SUCCESS);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews isc_buffer_putuint8(&b, 0);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews fprintf(stderr, "%s", hexdump);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews data += bytes;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews size -= bytes;
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews } while (size > 0);
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews fprintf(stderr, "\n");
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman#endif /* DEBUG */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
f21d2ee372125a7d0648387581a6712e05feeb52Evan Hunt/*
f21d2ee372125a7d0648387581a6712e05feeb52Evan Hunt * Upper node is the parent of the root of the passed node's
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * subtree. The passed node must not be NULL.
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanstatic inline dns_rbtnode_t *
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanget_upper_node(dns_rbtnode_t *node) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman return (UPPERNODE(node));
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman}
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanstatic void
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanfixup_uppernodes_helper(dns_rbtnode_t *node, dns_rbtnode_t *uppernode) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (node == NULL)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman return;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman UPPERNODE(node) = uppernode;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman fixup_uppernodes_helper(LEFT(node), uppernode);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman fixup_uppernodes_helper(RIGHT(node), uppernode);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman fixup_uppernodes_helper(DOWN(node), node);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman}
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman/*
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * This function is used to fixup uppernode members of all dns_rbtnodes
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * after deserialization.
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanstatic void
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramanfixup_uppernodes(dns_rbt_t *rbt) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman fixup_uppernodes_helper(rbt->root, NULL);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman}
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#else
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman/* The passed node must not be NULL. */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanstatic inline dns_rbtnode_t *
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanget_subtree_root(dns_rbtnode_t *node) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman while (!IS_ROOT(node)) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman node = PARENT(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman/* Upper node is the parent of the root of the passed node's
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * subtree. The passed node must not be NULL.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrencestatic inline dns_rbtnode_t *
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanget_upper_node(dns_rbtnode_t *node) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman dns_rbtnode_t *root = get_subtree_root(node);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Return the node in the level above the argument node that points
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to the level the argument node is in. If the argument node is in
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the top level, the return value is NULL.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (PARENT(root));
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramansize_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns__rbtnode_getdistance(dns_rbtnode_t *node) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman size_t nodes = 1;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman while (node != NULL) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_ROOT(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman break;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman nodes++;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman node = PARENT(node);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (nodes);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * Forward declarations.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic isc_result_t
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencecreate_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
08e57545c2b1068080f5bf317224160426801406Brian Wellington#ifdef DNS_RBT_USEHASH
7554feaef6057f5ea2926076900ac7634b911456Mark Andrewsstatic inline void
40e7c805a8f38ad9b20dd6c688496fc09fc971c2Mark Andrewshash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic inline void
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrenceunhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Huntstatic void
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Huntrehash(dns_rbt_t *rbt, unsigned int newcount);
08e57545c2b1068080f5bf317224160426801406Brian Wellington#else
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#define hash_node(rbt, node, name)
08e57545c2b1068080f5bf317224160426801406Brian Wellington#define unhash_node(rbt, node)
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt#define rehash(rbt, newcount)
08e57545c2b1068080f5bf317224160426801406Brian Wellington#endif
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic inline void
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencerotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic inline void
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencerotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic void
7829fad4093f2c1985b1efb7cea00287ff015d2bckbaddonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtnode_t **rootp);
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrence
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencestatic void
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrewsdeletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Huntstatic isc_result_t
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunttreefix(dns_rbt_t *rbt, void *base, size_t size,
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt dns_rbtnode_t *n, dns_name_t *name,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt dns_rbtdatafixer_t datafixer, void *fixer_arg,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt isc_uint64_t *crc);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic void
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramandeletetreeflat(dns_rbt_t *rbt, unsigned int quantum, isc_boolean_t unhash,
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t **nodep);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic void
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanprintnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic void
7829fad4093f2c1985b1efb7cea00287ff015d2bckbfreenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
d27343c5544b0473679503d839a793a5b567b503Mark Andrewsstatic isc_result_t
7829fad4093f2c1985b1efb7cea00287ff015d2bckbdns_rbt_zero_header(FILE *file) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /*
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * Write out a zeroed header as a placeholder. Doing this ensures
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * that the file will not read while it is partially written, should
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * writing fail or be interrupted.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb char buffer[HEADER_LENGTH];
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb memset(buffer, 0, HEADER_LENGTH);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = isc_stdio_write(buffer, 1, HEADER_LENGTH, file, NULL);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (result != ISC_R_SUCCESS)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = fflush(file);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (result != ISC_R_SUCCESS)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntstatic isc_once_t once = ISC_ONCE_INIT;
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntstatic void
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntinit_file_version(void) {
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt int n;
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt n = snprintf(FILE_VERSION, sizeof(FILE_VERSION),
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt "RBT Image %s %s", dns_major, dns_mapapi);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt INSIST(n > 0 && (unsigned int)n < sizeof(FILE_VERSION));
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt}
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckb/*
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * Write out the real header, including NodeDump version information
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * and the offset of the first node.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * Any information stored in the rbt object itself should be stored
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * here.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox Userstatic isc_result_t
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Huntwrite_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_uint64_t crc)
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt{
7829fad4093f2c1985b1efb7cea00287ff015d2bckb file_header_t header;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t location;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb memset(&header, 0, sizeof(file_header_t));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(header.version1, FILE_VERSION, sizeof(header.version1));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(header.version2, FILE_VERSION, sizeof(header.version2));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.first_node_offset = first_node_offset;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.ptrsize = (isc_uint32_t) sizeof(void *);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.bigendian = (1 == htonl(1)) ? 1 : 0;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#ifdef DNS_RDATASET_FIXED
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.rdataset_fixed = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#else
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.rdataset_fixed = 0;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User#endif
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header.nodecount = rbt->nodecount;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt header.crc = crc;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &location));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt location = dns_rbt_serialize_align(location);
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(isc_stdio_seek(file, location, SEEK_SET));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_write(&header, 1, sizeof(file_header_t), file, NULL));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(fflush(file));
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Ensure we are always at the end of the file. */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, 0, SEEK_END));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb cleanup:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntstatic isc_boolean_t
e7c0f978425f45731b08be1363f20626b0344f23Evan Huntmatch_header_version(file_header_t *header) {
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt RUNTIME_CHECK(isc_once_do(&once, init_file_version) == ISC_R_SUCCESS);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt if (memcmp(header->version1, FILE_VERSION,
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt sizeof(header->version1)) != 0 ||
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt memcmp(header->version2, FILE_VERSION,
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt sizeof(header->version1)) != 0)
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt {
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt return (ISC_FALSE);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt }
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt return (ISC_TRUE);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt}
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox Userstatic isc_result_t
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox Userserialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User uintptr_t right, uintptr_t down, uintptr_t parent,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt uintptr_t data, isc_uint64_t *crc)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtnode_t temp_node;
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t file_position;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb unsigned char *node_data;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb size_t datasize;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#ifdef DEBUG
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt dns_name_t nodename;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#endif
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb INSIST(node != NULL);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &file_position));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb file_position = dns_rbt_serialize_align(file_position);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, file_position, SEEK_SET));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node = *node;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.down_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.left_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.right_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.parent_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.data_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.is_mmapped = 1;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /*
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * If the next node is not NULL, calculate the next node's location
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * in the file. Note that this will have to change when the data
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * structure changes, and it also assumes that we always write the
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * nodes out in list order (which we currently do.)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (temp_node.parent != NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.parent = (dns_rbtnode_t *)(parent);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.parent_is_relative = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (temp_node.left != NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.left = (dns_rbtnode_t *)(left);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.left_is_relative = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (temp_node.right != NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.right = (dns_rbtnode_t *)(right);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.right_is_relative = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (temp_node.down != NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.down = (dns_rbtnode_t *)(down);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.down_is_relative = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (temp_node.data != NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.data = (dns_rbtnode_t *)(data);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb temp_node.data_is_relative = 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node_data = (unsigned char *) node + sizeof(dns_rbtnode_t);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb datasize = NODE_SIZE(node) - sizeof(dns_rbtnode_t);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
7829fad4093f2c1985b1efb7cea00287ff015d2bckb file, NULL));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_write(node_data, 1, datasize, file, NULL));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#ifdef DEBUG
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt dns_name_init(&nodename, NULL);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt NODENAME(node, &nodename);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt fprintf(stderr, "serialize ");
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt dns_name_print(&nodename, stderr);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt fprintf(stderr, "\n");
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt hexdump("node header", (unsigned char*) &temp_node,
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt sizeof(dns_rbtnode_t));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt hexdump("node data", node_data, datasize);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#endif
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_update(crc, (const isc_uint8_t *) &temp_node,
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt sizeof(dns_rbtnode_t));
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_update(crc, (const isc_uint8_t *) node_data, datasize);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckb cleanup:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrewsstatic isc_result_t
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox Userserialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt dns_rbtdatawriter_t datawriter, void *writer_arg,
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt uintptr_t *where, isc_uint64_t *crc)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
620620df3a74a5a57dc25221aae5033568703eb2Tinderbox User uintptr_t left = 0, right = 0, down = 0, data = 0;
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t location = 0, offset_adjust;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (node == NULL) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (where != NULL)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *where = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /* Reserve space for current node. */
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &location));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt location = dns_rbt_serialize_align(location);
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(isc_stdio_seek(file, location, SEEK_SET));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET));
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /*
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt * Serialize the rest of the tree.
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt *
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt * WARNING: A change in the order (from left, right, down)
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt * will break the way the crc hash is computed.
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt */
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(serialize_nodes(file, getleft(node, NULL), location,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt datawriter, writer_arg, &left, crc));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(serialize_nodes(file, getright(node, NULL), location,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt datawriter, writer_arg, &right, crc));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(serialize_nodes(file, getdown(node, NULL), location,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt datawriter, writer_arg, &down, crc));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (node->data != NULL) {
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t ret;
a3fb84bd1b6a56585c0d8181f2ab0338b0cf852fTinderbox User
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &ret));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt ret = dns_rbt_serialize_align(ret);
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(isc_stdio_seek(file, ret, SEEK_SET));
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt data = ret;
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt datawriter(file, node->data, writer_arg, crc);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /* Seek back to reserved space. */
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt CHECK(isc_stdio_seek(file, location, SEEK_SET));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /* Serialize the current node. */
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt CHECK(serialize_node(file, node, left, right, down, parent, data, crc));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Ensure we are always at the end of the file. */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, 0, SEEK_END));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (where != NULL)
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt *where = (uintptr_t) location;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb cleanup:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Huntoff_t
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Huntdns_rbt_serialize_align(off_t target) {
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t offset = target % 8;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (offset == 0)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (target);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb else
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (target + 8 - offset);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox Userisc_result_t
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox Userdns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtdatawriter_t datawriter,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt void *writer_arg, off_t *offset)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_result_t result;
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt off_t header_position, node_position, end_position;
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_uint64_t crc;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb REQUIRE(file != NULL);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_file_isplainfilefd(fileno(file)));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_init(&crc);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &header_position));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Write dummy header */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(dns_rbt_zero_header(file));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Serialize nodes */
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &node_position));
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt CHECK(serialize_nodes(file, rbt->root, 0, datawriter,
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt writer_arg, NULL, &crc));
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
31707708c585c53b61ca1edb2e224e6bb1b985a5Evan Hunt CHECK(isc_stdio_tell(file, &end_position));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (node_position == end_position) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *offset = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_final(&crc);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#ifdef DEBUG
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews hexdump("serializing CRC", (unsigned char *)&crc, sizeof(crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#endif
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Serialize header */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt CHECK(write_header(file, rbt, HEADER_LENGTH, crc));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Ensure we are always at the end of the file. */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb CHECK(isc_stdio_seek(file, 0, SEEK_END));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *offset = dns_rbt_serialize_align(header_position);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb cleanup:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt#define CONFIRM(a) do { \
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (! (a)) { \
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt result = ISC_R_INVALIDFILE; \
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt goto cleanup; \
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } \
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt} while(0);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Huntstatic isc_result_t
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunttreefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt dns_name_t *name, dns_rbtdatafixer_t datafixer,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt void *fixer_arg, isc_uint64_t *crc)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt isc_result_t result = ISC_R_SUCCESS;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_fixedname_t fixed;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_name_t nodename, *fullname;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt unsigned char *node_data;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt dns_rbtnode_t header;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt size_t datasize, nodemax = filesize - sizeof(dns_rbtnode_t);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (n == NULL)
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt return (ISC_R_SUCCESS);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM((void *) n >= base);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM((char *) n - (char *) base <= (int) nodemax);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM(DNS_RBTNODE_VALID(n));
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_name_init(&nodename, NULL);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb NODENAME(n, &nodename);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb fullname = &nodename;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM(dns_name_isvalid(fullname));
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (!dns_name_isabsolute(&nodename)) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_fixedname_init(&fixed);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb fullname = dns_fixedname_name(&fixed);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(dns_name_concatenate(&nodename, name, fullname, NULL));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /* memorize header contents prior to fixup */
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&header, n, sizeof(header));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (n->left_is_relative) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->left <= (dns_rbtnode_t *) nodemax);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->left = getleft(n, rbt->mmap_location);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->left_is_relative = 0;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(DNS_RBTNODE_VALID(n->left));
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } else
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->left == NULL);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (n->right_is_relative) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->right <= (dns_rbtnode_t *) nodemax);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->right = getright(n, rbt->mmap_location);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->right_is_relative = 0;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(DNS_RBTNODE_VALID(n->right));
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } else
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->right == NULL);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (n->down_is_relative) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->down <= (dns_rbtnode_t *) nodemax);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->down = getdown(n, rbt->mmap_location);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->down_is_relative = 0;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM(n->down > (dns_rbtnode_t *) n);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(DNS_RBTNODE_VALID(n->down));
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } else
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->down == NULL);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (n->parent_is_relative) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->parent <= (dns_rbtnode_t *) nodemax);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->parent = getparent(n, rbt->mmap_location);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->parent_is_relative = 0;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM(n->parent < (dns_rbtnode_t *) n);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(DNS_RBTNODE_VALID(n->parent));
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } else
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->parent == NULL);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt if (n->data_is_relative) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->data <= (void *) filesize);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->data = getdata(n, rbt->mmap_location);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt n->data_is_relative = 0;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt CONFIRM(n->data > (void *) n);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt } else
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CONFIRM(n->data == NULL);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb hash_node(rbt, n, fullname);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /* a change in the order (from left, right, down) will break hashing*/
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (n->left != NULL)
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(treefix(rbt, base, filesize, n->left, name,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt datafixer, fixer_arg, crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt if (n->right != NULL)
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(treefix(rbt, base, filesize, n->right, name,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt datafixer, fixer_arg, crc));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (n->down != NULL)
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(treefix(rbt, base, filesize, n->down, fullname,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt datafixer, fixer_arg, crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt if (datafixer != NULL && n->data != NULL)
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt CHECK(datafixer(n, base, filesize, fixer_arg, crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt rbt->nodecount++;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt node_data = (unsigned char *) n + sizeof(dns_rbtnode_t);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt datasize = NODE_SIZE(n) - sizeof(dns_rbtnode_t);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#ifdef DEBUG
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt fprintf(stderr, "deserialize ");
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt dns_name_print(&nodename, stderr);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt fprintf(stderr, "\n");
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt hexdump("node header", (unsigned char *) &header,
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt sizeof(dns_rbtnode_t));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt hexdump("node data", node_data, datasize);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#endif
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_update(crc, (const isc_uint8_t *) &header,
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt sizeof(dns_rbtnode_t));
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_update(crc, (const isc_uint8_t *) node_data,
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt datasize);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt cleanup:
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox Userisc_result_t
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Huntdns_rbt_deserialize_tree(void *base_address, size_t filesize,
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt off_t header_offset, isc_mem_t *mctx,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt dns_rbtdeleter_t deleter, void *deleter_arg,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt dns_rbtdatafixer_t datafixer, void *fixer_arg,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtnode_t **originp, dns_rbt_t **rbtp)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt isc_result_t result = ISC_R_SUCCESS;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb file_header_t *header;
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt dns_rbt_t *rbt = NULL;
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_uint64_t crc;
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews unsigned int host_big_endian;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb REQUIRE(originp == NULL || *originp == NULL);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt REQUIRE(rbtp != NULL && *rbtp == NULL);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_init(&crc);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(dns_rbt_create(mctx, deleter, deleter_arg, &rbt));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt rbt->mmap_location = base_address;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header = (file_header_t *)((char *)base_address + header_offset);
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt if (!match_header_version(header)) {
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt result = ISC_R_INVALIDFILE;
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt goto cleanup;
e7c0f978425f45731b08be1363f20626b0344f23Evan Hunt }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#ifdef DNS_RDATASET_FIXED
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (header->rdataset_fixed != 1) {
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt result = ISC_R_INVALIDFILE;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt goto cleanup;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#else
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (header->rdataset_fixed != 0) {
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt result = ISC_R_INVALIDFILE;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt goto cleanup;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#endif
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (header->ptrsize != (isc_uint32_t) sizeof(void *)) {
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt result = ISC_R_INVALIDFILE;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt goto cleanup;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews host_big_endian = (1 == htonl(1));
c76e8412f4ff4f5945157410312df2a8950f942dMark Andrews if (header->bigendian != host_big_endian) {
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt result = ISC_R_INVALIDFILE;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt goto cleanup;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb /* Copy other data items from the header into our rbt. */
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt rbt->root = (dns_rbtnode_t *)((char *)base_address +
7829fad4093f2c1985b1efb7cea00287ff015d2bckb header_offset + header->first_node_offset);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt if ((header->nodecount * sizeof(dns_rbtnode_t)) > filesize) {
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt result = ISC_R_INVALIDFILE;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt goto cleanup;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt }
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt rehash(rbt, header->nodecount);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt CHECK(treefix(rbt, base_address, filesize, rbt->root,
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Hunt dns_rootname, datafixer, fixer_arg, &crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt isc_crc64_final(&crc);
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#ifdef DEBUG
3911e7610f29dc664cbe8336f35c0652cd74652eMark Andrews hexdump("deserializing CRC", (unsigned char *)&crc, sizeof(crc));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt#endif
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt /* Check file hash */
e59937c7283216ca22ce6e7937b06eab6d97f4acEvan Hunt if (header->crc != crc) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt result = ISC_R_INVALIDFILE;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt goto cleanup;
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (header->nodecount != rbt->nodecount) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman result = ISC_R_INVALIDFILE;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman goto cleanup;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman }
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman fixup_uppernodes(rbt);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt *rbtp = rbt;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (originp != NULL)
1a076410c260ff1d3124ce8b7e22ac111e9cf92aEvan Hunt *originp = rbt->root;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt cleanup:
adbb48b4a0c6216f96d8b40712f23da893444f1cMark Andrews if (result != ISC_R_SUCCESS && rbt != NULL) {
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt rbt->root = NULL;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt rbt->nodecount = 0;
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt dns_rbt_destroy(&rbt);
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt }
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt
d9f0c713fe1d50f1848ca827c5f31db79d904f04Evan Hunt return (result);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrews
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * Initialize a red/black tree of trees.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
b7e40659efd6cf6f5e6b3b1f904f16f74efb0d16Evan Huntdns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater void *deleter_arg, dns_rbt_t **rbtp)
1630fce031f7a3e33f0579e477a3e17d1993e1f9Bob Halley{
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#ifdef DNS_RBT_USEHASH
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#endif
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbt_t *rbt;
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(mctx != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(rbtp != NULL && *rbtp == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (rbt == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_NOMEMORY);
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt rbt->mctx = NULL;
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_attach(mctx, &rbt->mctx);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->data_deleter = deleter;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->deleter_arg = deleter_arg;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->root = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->nodecount = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashsize = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb rbt->mmap_location = NULL;
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#ifdef DNS_RBT_USEHASH
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = inithash(rbt);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS) {
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
7554feaef6057f5ea2926076900ac7634b911456Mark Andrews#endif
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->magic = RBT_MAGIC;
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rbtp = rbt;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence * Deallocate a red/black tree of trees.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencevoid
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencedns_rbt_destroy(dns_rbt_t **rbtp) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrews}
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrews
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrewsisc_result_t
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrewsdns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbt_t *rbt;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt = *rbtp;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman deletetreeflat(rbt, quantum, ISC_FALSE, &rbt->root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (rbt->root != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_QUOTA);
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(rbt->nodecount == 0);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb rbt->mmap_location = NULL;
83e6eb0dfe7d3525dcf093f440e04e8971c4c5d2Brian Wellington
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (rbt->hashtable != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_mem_put(rbt->mctx, rbt->hashtable,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashsize * sizeof(dns_rbtnode_t *));
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->magic = 0;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
df925e6c66d45d960fbac0383169763967d2111cEvan Hunt isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rbtp = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
83e6eb0dfe7d3525dcf093f440e04e8971c4c5d2Brian Wellingtonunsigned int
83e6eb0dfe7d3525dcf093f440e04e8971c4c5d2Brian Wellingtondns_rbt_nodecount(dns_rbt_t *rbt) {
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (rbt->nodecount);
83e6eb0dfe7d3525dcf093f440e04e8971c4c5d2Brian Wellington}
83e6eb0dfe7d3525dcf093f440e04e8971c4c5d2Brian Wellington
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramansize_t
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Huntdns_rbt_hashsize(dns_rbt_t *rbt) {
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt REQUIRE(VALID_RBT(rbt));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt return (rbt->hashsize);
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt}
dd2a0a6d2dec1c23787351e51b434a838dec5603Evan Hunt
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic inline isc_result_t
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrencechain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_boolean_t include_chain_end)
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t nodename;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater int i;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&nodename, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (include_chain_end && chain->end != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(chain->end, &nodename);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_name_copy(&nodename, name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_reset(name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater for (i = (int)chain->level_count - 1; i >= 0; i--) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(chain->levels[i], &nodename);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_name_concatenate(name, &nodename, name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence}
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic inline isc_result_t
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrencemove_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater do {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Go as far right and then down as much as possible,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * as long as the rightmost node has a down pointer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (RIGHT(node) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = RIGHT(node);
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DOWN(node) == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ADD_LEVEL(chain, node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = DOWN(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } while (1);
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = node;
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence}
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * Add 'name' to tree, initializing its data pointer with 'data'.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrencedns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Does this thing have too many variables or what?
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t **root, *parent, *child, *current, *new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_offsets_t current_offsets;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_namereln_t compared;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result = ISC_R_SUCCESS;
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman unsigned int level_count;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int common_labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int nlabels, hlabels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater int order;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(dns_name_isabsolute(name));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(nodep != NULL && *nodep == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman /*
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * Dear future BIND developer,
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * After you have tried attempting to optimize this routine by
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * using the hashtable and have realized your folly, please
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * append another cross ("X") below as a warning to the next
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * future BIND developer:
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * Number of victim developers: X
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * I wish the past developer had included such a notice.
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * Long form: Unlike dns_rbt_findnode(), this function does not
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * lend itself to be optimized using the hashtable:
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * 1. In the subtree where the insertion occurs, this function
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * needs to have the insertion point and the order where the
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * lookup terminated (i.e., at the insertion point where left or
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * right child is NULL). This cannot be determined from the
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * hashtable, so at least in that subtree, a BST O(log N) lookup
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * is necessary.
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman *
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * 2. Our RBT nodes contain not only single labels but label
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * sequences to optimize space usage. So at every level, we have
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * to look for a match in the hashtable for all superdomains in
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * the rest of the name we're searching. This is an O(N)
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * operation at least, here N being the label size of name, each
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * of which is a hashtable lookup involving dns_name_equal()
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * comparisons.
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman */
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Create a copy of the name so the original name structure is
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * not modified.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedcopy);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater add_name = dns_fixedname_name(&fixedcopy);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_clone(name, add_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_UNLIKELY(rbt->root == NULL)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = create_node(rbt->mctx, add_name, &new_current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->nodecount++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_current->is_root = 1;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman UPPERNODE(new_current) = NULL;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->root = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *nodep = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash_node(rbt, new_current, name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman level_count = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedprefix);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedsuffix);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater prefix = dns_fixedname_name(&fixedprefix);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater suffix = dns_fixedname_name(&fixedsuffix);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater root = &rbt->root;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(IS_ROOT(*root));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = *root;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&current_name, current_offsets);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fnewname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_name = dns_fixedname_name(&fnewname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater nlabels = dns_name_countlabels(name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hlabels = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater do {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(current, &current_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater compared = dns_name_fullcompare(add_name, &current_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &order, &common_labels);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_equal) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *nodep = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_EXISTS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_none) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (order < 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else if (order > 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This name has some suffix in common with the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * name at the current node. If the name at
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the current node is shorter, that means the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * new name should be in a subtree. If the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * name at the current node is longer, that means
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the down pointer to this tree should point
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to a new tree that has the common suffix, and
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the non-common parts of these two names should
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * start a new tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hlabels += common_labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_subdomain) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * All of the existing labels are in common,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * so the new name is in a subtree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Whack off the common labels for the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * not-in-common part to be searched for
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * in the next level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_split(add_name, common_labels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater add_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Follow the down pointer (possibly NULL).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater root = &DOWN(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(*root == NULL ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (IS_ROOT(*root) &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(*root) == current));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = DOWN(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman INSIST(level_count < DNS_RBT_LEVELBLOCK);
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman level_count++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The number of labels in common is fewer
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * than the number of labels at the current
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node, so the current node must be adjusted
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to have just the common suffix, and a down
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * pointer made to a new tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(compared == dns_namereln_commonancestor
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater || compared == dns_namereln_contains);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Ensure the number of levels in the tree
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * does not exceed the number of logical
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * levels allowed by DNSSEC.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * XXXDCL need a better error result?
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman if (level_count >= DNS_RBT_LEVELBLOCK) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOSPACE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Split the name into two parts, a prefix
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * which is the not-in-common parts of the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * two names and a suffix that is the common
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * parts of them.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_split(&current_name, common_labels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater prefix, suffix);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = create_node(rbt->mctx, suffix,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &new_current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Reproduce the tree attributes of the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * current node.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_current->is_root = current->is_root;
63d5a6f680864b58b8eddc58dfa9957e19abf084Mark Andrews if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
63d5a6f680864b58b8eddc58dfa9957e19abf084Mark Andrews new_current->nsec = DNS_RBT_NSEC_NORMAL;
63d5a6f680864b58b8eddc58dfa9957e19abf084Mark Andrews else
63d5a6f680864b58b8eddc58dfa9957e19abf084Mark Andrews new_current->nsec = current->nsec;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(new_current) = PARENT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(new_current) = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(new_current) = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater COLOR(new_current) = COLOR(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Fix pointers that were to the current node.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (parent != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(parent) == current)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(parent) = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(parent) = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(new_current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(LEFT(new_current)) =
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(new_current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(RIGHT(new_current)) =
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (*root == current)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *root = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NAMELEN(current) = prefix->length;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater OFFSETLEN(current) = prefix->labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Set up the new root of the next level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * By definition it will not be the top
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current->is_root = 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(current) = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DOWN(new_current) = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater root = &DOWN(new_current);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman UPPERNODE(new_current) = UPPERNODE(current);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman UPPERNODE(current) = new_current;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman INSIST(level_count < DNS_RBT_LEVELBLOCK);
9267cc8e83c4f3cf98cdebe6553143812250beccMukund Sivaraman level_count++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(current) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(current) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->nodecount++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_getlabelsequence(name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater nlabels - hlabels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hlabels, new_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash_node(rbt, new_current, new_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (common_labels ==
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_countlabels(add_name)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The name has been added by pushing
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the not-in-common parts down to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * a new level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *nodep = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The current node has no data,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * because it is just a placeholder.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Its data pointer is already NULL
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * from create_node()), so there's
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * nothing more to do to it.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The not-in-common parts of the new
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * name will be inserted into the new
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * level following this loop (unless
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * result != ISC_R_SUCCESS, which
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * is tested after the loop ends).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_split(add_name, common_labels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater add_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman } while (ISC_LIKELY(child != NULL));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_LIKELY(result == ISC_R_SUCCESS))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = create_node(rbt->mctx, add_name, &new_current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_LIKELY(result == ISC_R_SUCCESS)) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#ifdef DNS_RBT_USEHASH
2a3747006563cfa1c07516ec594cc6d1f0db7ff2Tinderbox User if (*root == NULL)
2a3747006563cfa1c07516ec594cc6d1f0db7ff2Tinderbox User UPPERNODE(new_current) = current;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman else
2a3747006563cfa1c07516ec594cc6d1f0db7ff2Tinderbox User UPPERNODE(new_current) = PARENT(*root);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb addonlevel(new_current, current, order, root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->nodecount++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *nodep = new_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash_node(rbt, new_current, name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence}
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence/*
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence * Add a name to the tree of trees, associating it with some data.
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrencedns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *node;
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(dns_name_isabsolute(name));
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = NULL;
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbt_addnode(rbt, name, &node);
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * dns_rbt_addnode will report the node exists even when
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * it does not have data associated with it, but the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * dns_rbt_*name functions all behave depending on whether
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * there is data associated with a node.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (result == ISC_R_EXISTS && DATA(node) == NULL)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DATA(node) = data;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * Find the node for "name" in the tree of trees.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecickidns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int options, dns_rbtfindcallback_t callback,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater void *callback_arg)
587fc7b519b0fed4e3dd234527edba1ca9334757David Lawrence{
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman dns_rbtnode_t *current, *last_compared;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_t localchain;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *search_name, current_name, *callback_name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_t fixedcallbackname, fixedsearchname;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_namereln_t compared;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result, saved_result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int common_labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int hlabels = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater int order;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(dns_name_isabsolute(name));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(node != NULL && *node == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater != (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * If there is a chain it needs to appear to be in a sane state,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * otherwise a chain is still needed to generate foundname and
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * callback_name.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (chain == NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater options |= DNS_RBTFIND_NOPREDECESSOR;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain = &localchain;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_init(chain, rbt->mctx);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_UNLIKELY(rbt->root == NULL))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_NOTFOUND);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * Appease GCC about variables it incorrectly thinks are
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * possibly used uninitialized.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman compared = dns_namereln_none;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman last_compared = NULL;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman order = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedcallbackname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater callback_name = dns_fixedname_name(&fixedcallbackname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * search_name is the name segment being sought in each tree level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * By using a fixedname, the search_name will definitely have offsets
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * for use by any splitting.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * By using dns_name_clone, no name data should be copied thanks to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the lack of bitstring labels.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedsearchname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater search_name = dns_fixedname_name(&fixedsearchname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_clone(name, search_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&current_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater saved_result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = rbt->root;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman while (ISC_LIKELY(current != NULL)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(current, &current_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater compared = dns_name_fullcompare(search_name, &current_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &order, &common_labels);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * last_compared is used as a shortcut to start (or
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * continue rather) finding the stop-node of the search
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * when hashing was used (see much below in this
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * function).
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater last_compared = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_equal)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_none) {
08e57545c2b1068080f5bf317224160426801406Brian Wellington#ifdef DNS_RBT_USEHASH
536da846f6cc03ad8abbb8bb9d5d8a6f607b8c33Mark Andrews /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * Here, current is pointing at a subtree root
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * node. We try to find a matching node using
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * the hashtable. We can get one of 3 results
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * here: (a) we locate the matching node, (b) we
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * find a node to which the current node has a
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * subdomain relation, (c) we fail to find (a)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * or (b).
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t hash_name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *hnode;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *up_current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int nlabels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int tlabels = 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int hash;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * The case of current not being a subtree root,
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * that means a left or right pointer was
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * followed, only happens when the algorithm
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * fell through to the traditional binary search
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * because of a bitstring label. Since we
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * dropped the bitstring support, this should
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * not happen.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman INSIST(IS_ROOT(current));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater nlabels = dns_name_countlabels(search_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman * current is the root of the current level, so
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * its parent is the same as its "up" pointer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
614ce1b65ff9ef158aa5a19a9acf2edb99170963Mukund Sivaraman up_current = PARENT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&hash_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hashagain:
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * Compute the hash over the full absolute
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * name. Look for the smallest suffix match at
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * this tree level (hlevel), and then at every
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * iteration, look for the next smallest suffix
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * match (add another subdomain label to the
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * absolute name being hashed).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_getlabelsequence(name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater nlabels - tlabels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hlabels + tlabels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &hash_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash = dns_name_fullhash(&hash_name, ISC_FALSE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_getlabelsequence(search_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater nlabels - tlabels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater tlabels, &hash_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * Walk all the nodes in the hash bucket pointed
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * by the computed hash value.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater for (hnode = rbt->hashtable[hash % rbt->hashsize];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hnode != NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hnode = hnode->hashnext)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t hnode_name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_LIKELY(hash != HASHVAL(hnode)))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater continue;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /*
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * This checks that the hashed label
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * sequence being looked up is at the
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * same tree level, so that we don't
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * match a labelsequence from some other
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * subdomain.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_LIKELY(get_upper_node(hnode) != up_current))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater continue;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&hnode_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(hnode, &hnode_name);
d1dbf6b20fdcfa95acd75cdb96fcd57067a31144Mukund Sivaraman if (ISC_LIKELY(dns_name_equal(&hnode_name, &hash_name)))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (hnode != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = hnode;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This is an optimization. If hashing found
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the right node, the next call to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * dns_name_fullcompare() would obviously
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * return _equal or _subdomain. Determine
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * which of those would be the case by
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * checking if the full name was hashed. Then
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * make it look like dns_name_fullcompare
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * was called and jump to the right place.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (tlabels == nlabels) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater compared = dns_namereln_equal;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater common_labels = tlabels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater compared = dns_namereln_subdomain;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater goto subdomain;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (tlabels++ < nlabels)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater goto hashagain;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * All of the labels have been tried against the hash
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * table. Since we dropped the support of bitstring
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * labels, the name isn't in the table.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater continue;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#else /* DNS_RBT_USEHASH */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Standard binary search tree movement.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (order < 0)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman#endif /* DNS_RBT_USEHASH */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The names have some common suffix labels.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * If the number in common are equal in length to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the current node's name length, then follow the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * down pointer and search in the new tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_subdomain) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#ifdef DNS_RBT_USEHASH
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater subdomain:
7829fad4093f2c1985b1efb7cea00287ff015d2bckb#endif
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Whack off the current node's common parts
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * for the name to search in the next level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_split(search_name, common_labels,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater search_name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hlabels += common_labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This might be the closest enclosing name.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DATA(current) != NULL ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (options & DNS_RBTFIND_EMPTYDATA) != 0)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *node = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Point the chain to the next level. This
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * needs to be done before 'current' is pointed
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * there because the callback in the next
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * block of code needs the current 'current',
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * but in the event the callback requests that
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the search be stopped then the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * DNS_R_PARTIALMATCH code at the end of this
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * function needs the chain pointed to the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * next level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ADD_LEVEL(chain, current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The caller may want to interrupt the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * downward search when certain special nodes
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * are traversed. If this is a special node,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the callback is used to learn what the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * caller wants to do.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (callback != NULL &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater FINDCALLBACK(current)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = chain_name(chain,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater callback_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ISC_FALSE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = (callback)(current,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater callback_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater callback_arg);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != DNS_R_CONTINUE) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater saved_result = result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Treat this node as if it
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * had no down pointer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Finally, head to the next tree level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = DOWN(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Though there are labels in common, the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * entire name at this node is not common
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * with the search name so the search
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * name does not exist in the tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(compared == dns_namereln_commonancestor
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater || compared == dns_namereln_contains);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * If current is not NULL, NOEXACT is not disallowing exact matches,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * and either the node has data or an empty node is ok, return
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * ISC_R_SUCCESS to indicate an exact match.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (DATA(current) != NULL ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Found an exact match.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_matches = chain->level_count;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (foundname != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = chain_name(chain, foundname, ISC_TRUE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *node = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = saved_result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *node = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Did not find an exact match (or did not want one).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (*node != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * ... but found a partially matching superdomain.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Unwind the chain to the partial match node
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to set level_matches to the level above the node,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * and then to derive the name.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * chain->level_count is guaranteed to be at least 1
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * here because by definition of finding a superdomain,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the chain is pointed to at least the first subtree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_matches = chain->level_count - 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (chain->levels[chain->level_matches] != *node) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(chain->level_matches > 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_matches--;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (foundname != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int saved_count = chain->level_count;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_count = chain->level_matches + 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = chain_name(chain, foundname,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ISC_FALSE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_count = saved_count;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = DNS_R_PARTIALMATCH;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOTFOUND;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (current != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * There was an exact match but either
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * DNS_RBTFIND_NOEXACT was set, or
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * DNS_RBTFIND_EMPTYDATA was set and the node had no
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * data. A policy decision was made to set the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * chain to the exact match, but this is subject
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to change if it becomes apparent that something
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * else would be more useful. It is important that
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * this case is handled here, because the predecessor
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * setting code below assumes the match was not exact.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DATA(current) == NULL));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Ensure the chain points nowhere.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Since there was no exact match, the chain argument
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * needs to be pointed at the DNSSEC predecessor of
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the search name.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_subdomain) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Attempted to follow a down pointer that was
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * NULL, which means the searched for name was
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * a subdomain of a terminal name in the tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Since there are no existing subdomains to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * order against, the terminal name is the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * predecessor.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(chain->level_count > 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(chain->level_matches <
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_count);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end =
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->levels[--chain->level_count];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result2;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Point current to the node that stopped
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the search.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * With the hashing modification that has been
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * added to the algorithm, the stop node of a
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * standard binary search is not known. So it
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * has to be found. There is probably a more
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * clever way of doing this.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The assignment of current to NULL when
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the relationship is *not* dns_namereln_none,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * even though it later gets set to the same
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * last_compared anyway, is simply to not push
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the while loop in one more level of
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * indentation.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (compared == dns_namereln_none)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = last_compared;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (current != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(current, &current_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater compared = dns_name_fullcompare(
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater search_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &current_name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &order,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater &common_labels);
0874abad14e3e9ecfc3dc1a1a2b9969f2f027724Mark Andrews POST(compared);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater last_compared = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Standard binary search movement.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (order < 0)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = last_compared;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Reached a point within a level tree that
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * positively indicates the name is not
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * present, but the stop node could be either
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * less than the desired name (order > 0) or
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * greater than the desired name (order < 0).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * If the stop node is less, it is not
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * necessarily the predecessor. If the stop
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node has a down pointer, then the real
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * predecessor is at the end of a level below
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * (not necessarily the next level).
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Move down levels until the rightmost node
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * does not have a down pointer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * When the stop node is greater, it is
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the successor. All the logic for finding
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the predecessor is handily encapsulated
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * in dns_rbtnodechain_prev. In the event
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * that the search name is less than anything
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * else in the tree, the chain is reset.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * XXX DCL What is the best way for the caller
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * to know that the search name has
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * no predecessor?
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (order > 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DOWN(current) != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ADD_LEVEL(chain, current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result2 =
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater move_chain_to_last(chain,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DOWN(current));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result2 != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = result2;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Ah, the pure and simple
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * case. The stop node is the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * predecessor.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(order < 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result2 = dns_rbtnodechain_prev(chain,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NULL,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result2 == ISC_R_SUCCESS ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result2 == DNS_R_NEWORIGIN)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ; /* Nothing. */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else if (result2 == ISC_R_NOMORE)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * There is no predecessor.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = result2;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence/*
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence * Get the data pointer associated with 'name'.
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecickidns_rbt_findname(dns_rbt_t *rbt, const dns_name_t *name, unsigned int options,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *foundname, void **data) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *node = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(data != NULL && *data == NULL);
c4c843edb3f4c609e3552ee77a43400852400467David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater options, NULL, NULL);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node != NULL &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *data = DATA(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOTFOUND;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence/*
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence * Delete a name from the tree of trees.
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrencedns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *node = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(dns_name_isabsolute(name));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * First, find the node.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * When searching, the name might not have an exact match:
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * elements of a tree, which would make layer 1 a single
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node tree of "b.a.com" and layer 2 a three node tree of
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * a, b, and c. Deleting a.com would find only a partial depth
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * match in the first layer. Should it be a requirement that
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * that the name to be deleted have data? For now, it is.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * ->dirty, ->locknum and ->references are ignored; they are
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * solely the province of rbtdb.c.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DNS_RBTFIND_NOOPTIONS, NULL, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DATA(node) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbt_deletenode(rbt, node, recurse);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOTFOUND;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else if (result == DNS_R_PARTIALMATCH)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOTFOUND;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
94231e22882a98a3805060b0a1322e96d8f57b41David Lawrence}
94231e22882a98a3805060b0a1322e96d8f57b41David Lawrence
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence/*
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * Remove a node from the tree of trees.
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence *
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * a sequence of additions to be deletions will not generally get the
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * tree back to the state it started in. For example, if the addition
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * restoring "a.b.c". The RBT *used* to do this kind of rejoining, but it
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * turned out to be a bad idea because it could corrupt an active nodechain
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * that had "b.c" as one of its levels -- and the RBT has no idea what
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * nodechains are in use by callers, so it can't even *try* to helpfully
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * fix them up (which would probably be doomed to failure anyway).
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence *
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * Similarly, it is possible to leave the tree in a state where a supposedly
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * deleted node still exists. The first case of this is obvious; take
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * the tree which has "b.c" on one level, pointing to "a". Now deleted "b.c".
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * It was just established in the previous paragraph why we can't pull "a"
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * back up to its parent level. But what happens when "a" then gets deleted?
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * "b.c" is left hanging around without data or children. This condition
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * is actually pretty easy to detect, but ... should it really be removed?
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * Is a chain pointing to it? An iterator? Who knows! (Note that the
b79e66b06d058ef3b9a26b71806ce67971cd3152David Lawrence * references structure member cannot be looked at because it is private to
b79e66b06d058ef3b9a26b71806ce67971cd3152David Lawrence * rbtdb.) This is ugly and makes me unhappy, but after hours of trying to
b79e66b06d058ef3b9a26b71806ce67971cd3152David Lawrence * make it more aesthetically proper and getting nowhere, this is the way it
b79e66b06d058ef3b9a26b71806ce67971cd3152David Lawrence * is going to stay until such time as it proves to be a *real* problem.
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence *
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * Finally, for reference, note that the original routine that did node
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * joining was called join_nodes(). It has been excised, living now only
b79e66b06d058ef3b9a26b71806ce67971cd3152David Lawrence * in the CVS history, but comments have been left behind that point to it just
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * in case someone wants to muck with this some more.
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence *
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * The one positive aspect of all of this is that joining used to have a
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence * case where it might fail. Without trying to join, now this function always
a571ebca8b8c472e775d518e82b7335f93ea25c4Andreas Gustafsson * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
a571ebca8b8c472e775d518e82b7335f93ea25c4Andreas Gustafsson */
510f4bdcb66acbec3f276efaacecbebea891c868David Lawrenceisc_result_t
510f4bdcb66acbec3f276efaacecbebea891c868David Lawrencedns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
510f4bdcb66acbec3f276efaacecbebea891c868David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb INSIST(rbt->nodecount != 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DOWN(node) != NULL) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (recurse) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman PARENT(DOWN(node)) = NULL;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman deletetreeflat(rbt, 0, ISC_TRUE, &DOWN(node));
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DATA(node) != NULL && rbt->data_deleter != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->data_deleter(DATA(node), rbt->deleter_arg);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DATA(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Since there is at least one node below this one and
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * no recursion was requested, the deletion is
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * complete. The down node from this node might be all
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * by itself on a single level, so join_nodes() could
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * be used to collapse the tree (with all the caveats
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * of the comment at the start of this function).
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * But join_nodes() function has now been removed.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews /*
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews * Note the node that points to the level of the node
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews * that is being deleted. If the deleted node is the
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews * top level, parent will be set to NULL.
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews */
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews parent = get_upper_node(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews /*
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews * This node now has no down pointer, so now it needs
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews * to be removed from this level.
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews */
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews deletefromlevel(node, parent == NULL ? &rbt->root : &DOWN(parent));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews if (DATA(node) != NULL && rbt->data_deleter != NULL)
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews rbt->data_deleter(DATA(node), rbt->deleter_arg);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews unhash_node(rbt, node);
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#if DNS_RBT_USEMAGIC
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews node->magic = 0;
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#endif
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews dns_rbtnode_refdestroy(node);
44c86318ed432af96848269250930297eea2bba3Evan Hunt
558278974eb4a1021943e6bbbc6c7d80dc3707fdMark Andrews freenode(rbt, &node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This function never fails.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencevoid
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrencedns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(name != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(name->offsets == NULL);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(node, name);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrenceisc_result_t
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrencedns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(name != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(name->buffer != NULL);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&current, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_reset(name);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater do {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(node != NULL);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(node, &current);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_name_concatenate(name, &current, name, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman node = get_upper_node(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } while (! dns_name_isabsolute(name));
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence}
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrencechar *
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrencedns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_t fixedname;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(printname != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_fixedname_init(&fixedname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater name = dns_fixedname_name(&fixedname);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbt_fullnamefromnode(node, name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_format(name, printname, size);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater snprintf(printname, size, "<error building name: %s>",
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_result_totext(result));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (printname);
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence}
a09c545af1ceb8eb6f3aa2bb6fae286208a72141David Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_result_t
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrencecreate_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_region_t region;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int labels;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb size_t nodelen;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(name->offsets != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_toregion(name, &region);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater labels = dns_name_countlabels(name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ENSURE(labels > 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Allocate space for the node structure, the name, and the offsets.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
7829fad4093f2c1985b1efb7cea00287ff015d2bckb nodelen = sizeof(dns_rbtnode_t) + region.length + labels + 1;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node = (dns_rbtnode_t *)isc_mem_get(mctx, nodelen);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_NOMEMORY);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb memset(node, 0, nodelen);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->is_root = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DOWN(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DATA(node) = NULL;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->is_mmapped = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->down_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->left_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->right_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->parent_is_relative = 0;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb node->data_is_relative = 0;
cc0a48a38173637f7a833e2da52bcfbcecb960b4Mark Andrews node->rpz = 0;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
08e57545c2b1068080f5bf317224160426801406Brian Wellington#ifdef DNS_RBT_USEHASH
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater HASHNEXT(node) = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater HASHVAL(node) = 0;
08e57545c2b1068080f5bf317224160426801406Brian Wellington#endif
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ISC_LINK_INIT(node, deadlink);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LOCKNUM(node) = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater WILD(node) = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DIRTY(node) = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_refinit(node, 0);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->find_callback = 0;
63d5a6f680864b58b8eddc58dfa9957e19abf084Mark Andrews node->nsec = DNS_RBT_NSEC_NORMAL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The following is stored to make reconstructing a name from the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * stored value in the node easy: the length of the name, the number
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * of labels, whether the name is absolute or not, the name itself,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * and the name's offsets table.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * XXX RTH
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The offsets table could be made smaller by eliminating the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * first offset, which is always 0. This requires changes to
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * lib/dns/name.c.
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews *
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews * as it uses OLDNAMELEN.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews OLDNAMELEN(node) = NAMELEN(node) = region.length;
7704a47aec081144bdb7a0218d5e2dd5296b6b08Mark Andrews OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ATTRS(node) = name->attributes;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(NAME(node), region.base, region.length);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(OFFSETS(node), name->offsets, labels);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#if DNS_RBT_USEMAGIC
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->magic = DNS_RBTNODE_MAGIC;
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#endif
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *nodep = node;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
08e57545c2b1068080f5bf317224160426801406Brian Wellington#ifdef DNS_RBT_USEHASH
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrencestatic inline void
40e7c805a8f38ad9b20dd6c688496fc09fc971c2Mark Andrewshash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int hash;
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
7829fad4093f2c1985b1efb7cea00287ff015d2bckb REQUIRE(name != NULL);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash = HASHVAL(node) % rbt->hashsize;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater HASHNEXT(node) = rbt->hashtable[hash];
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable[hash] = node;
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrencestatic isc_result_t
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrenceinithash(dns_rbt_t *rbt) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int bytes;
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashsize = RBT_HASH_SIZE;
f2453ece5b6f7c0a5c446b357e3ea26ee5736e02Francis Dupont bytes = (unsigned int)rbt->hashsize * sizeof(dns_rbtnode_t *);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (rbt->hashtable == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_NOMEMORY);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater memset(rbt->hashtable, 0, bytes);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_SUCCESS);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
7554feaef6057f5ea2926076900ac7634b911456Mark Andrewsstatic void
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Huntrehash(dns_rbt_t *rbt, unsigned int newcount) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int oldsize;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t **oldtable;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *node;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *nextnode;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int hash;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int i;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f2453ece5b6f7c0a5c446b357e3ea26ee5736e02Francis Dupont oldsize = (unsigned int)rbt->hashsize;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater oldtable = rbt->hashtable;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt do {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman INSIST((rbt->hashsize * 2 + 1) > rbt->hashsize);
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt rbt->hashsize = rbt->hashsize * 2 + 1;
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt } while (newcount >= (rbt->hashsize * 3));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable = isc_mem_get(rbt->mctx,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashsize * sizeof(dns_rbtnode_t *));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (rbt->hashtable == NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable = oldtable;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashsize = oldsize;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater for (i = 0; i < rbt->hashsize; i++)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable[i] = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater for (i = 0; i < oldsize; i++) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman for (node = oldtable[i]; node != NULL; node = nextnode) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash = HASHVAL(node) % rbt->hashsize;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman nextnode = HASHNEXT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater HASHNEXT(node) = rbt->hashtable[hash];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rbt->hashtable[hash] = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
7554feaef6057f5ea2926076900ac7634b911456Mark Andrewsstatic inline void
40e7c805a8f38ad9b20dd6c688496fc09fc971c2Mark Andrewshash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt if (rbt->nodecount >= (rbt->hashsize * 3))
127a4a90b0d03ebf55ad44d25f75b30c3a6fb728Evan Hunt rehash(rbt, rbt->nodecount);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater hash_add_node(rbt, node, name);
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrencestatic inline void
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrenceunhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater unsigned int bucket;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *bucket_node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman bucket = HASHVAL(node) % rbt->hashsize;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman bucket_node = rbt->hashtable[bucket];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (bucket_node == node) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman rbt->hashtable[bucket] = HASHNEXT(node);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman } else {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman while (HASHNEXT(bucket_node) != node) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman INSIST(HASHNEXT(bucket_node) != NULL);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman bucket_node = HASHNEXT(bucket_node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman HASHNEXT(bucket_node) = HASHNEXT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence}
08e57545c2b1068080f5bf317224160426801406Brian Wellington#endif /* DNS_RBT_USEHASH */
b65f2ab14abb4b6ef906d7d02064fba158f07b1eDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencestatic inline void
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencerotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *child;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(rootp != NULL);
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = RIGHT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(child != NULL);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(node) = LEFT(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(child) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(LEFT(child)) = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(child) = node;
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrence
e53e202ef3b51c58fb9abe0d15e3829a970b00e7Mark Andrews PARENT(child) = PARENT(node);
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_ROOT(node)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child->is_root = 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->is_root = 0;
510f4bdcb66acbec3f276efaacecbebea891c868David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(PARENT(node)) == node)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(PARENT(node)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(PARENT(node)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(node) = child;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrencestatic inline void
092b4e5359c5982a438e36ced3dbefc313f7fbfcDavid Lawrencerotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *child;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(rootp != NULL);
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = LEFT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(child != NULL);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(node) = RIGHT(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(child) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(RIGHT(child)) = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(child) = node;
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrence
e53e202ef3b51c58fb9abe0d15e3829a970b00e7Mark Andrews PARENT(child) = PARENT(node);
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_ROOT(node)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child->is_root = 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->is_root = 0;
510f4bdcb66acbec3f276efaacecbebea891c868David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(PARENT(node)) == node)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(PARENT(node)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(PARENT(node)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
5d4f11b265c396d71ec2162a632e620425481a9eDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(node) = child;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
c4c843edb3f4c609e3552ee77a43400852400467David Lawrence/*
c4c843edb3f4c609e3552ee77a43400852400467David Lawrence * This is the real workhorse of the insertion code, because it does the
c4c843edb3f4c609e3552ee77a43400852400467David Lawrence * true red/black tree on a single level.
c4c843edb3f4c609e3552ee77a43400852400467David Lawrence */
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrencestatic void
7829fad4093f2c1985b1efb7cea00287ff015d2bckbaddonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtnode_t **rootp)
005c7ad70f55a6e4333808cdf63811777254c339David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *child, *root, *parent, *grandparent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t add_name, current_name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_offsets_t add_offsets, current_offsets;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(rootp != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(node) == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(current != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater root = *rootp;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (root == NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * First node of a level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node->is_root = 1;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(node) = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = root;
0874abad14e3e9ecfc3dc1a1a2b9969f2f027724Mark Andrews POST(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&add_name, add_offsets);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(node, &add_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&current_name, current_offsets);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(current, &current_name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (order < 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(LEFT(current) == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater LEFT(current) = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(RIGHT(current) == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater RIGHT(current) = node;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(PARENT(node) == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(node) = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (node != root && IS_RED(PARENT(node))) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * XXXDCL could do away with separate parent and grandparent
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * variables. They are vestiges of the days before parent
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * pointers. However, they make the code a little clearer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = PARENT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater grandparent = PARENT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (parent == LEFT(grandparent)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = RIGHT(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (child != NULL && IS_RED(child)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = grandparent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node == RIGHT(parent)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_left(parent, &root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = PARENT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater grandparent = PARENT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_right(grandparent, &root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = LEFT(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (child != NULL && IS_RED(child)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = grandparent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node == LEFT(parent)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_right(parent, &root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater node = parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = PARENT(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater grandparent = PARENT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(grandparent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_left(grandparent, &root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ENSURE(IS_ROOT(root));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = root;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence/*
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence * This is the real workhorse of the deletion code, because it does the
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence * true red/black tree on a single level.
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrence */
0f5962ac3e4ef336faff68f1cb838505e64665e5David Lawrencestatic void
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrewsdeletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *child, *sibling, *parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews REQUIRE(item != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Verify that the parent history is (apparently) correct.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews INSIST((IS_ROOT(item) && *rootp == item) ||
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews (! IS_ROOT(item) &&
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews (LEFT(PARENT(item)) == item ||
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(PARENT(item)) == item)));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (LEFT(item) == NULL) {
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (RIGHT(item) == NULL) {
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (IS_ROOT(item)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This is the only item in the tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This node has one child, on the right.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews child = RIGHT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews } else if (RIGHT(item) == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This node has one child, on the left.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews child = LEFT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t holder, *tmp = &holder;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This node has two children, so it cannot be directly
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * deleted. Find its immediate in-order successor and
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * move it to this location, then do the deletion at the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * old site of the successor.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews successor = RIGHT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (LEFT(successor) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor = LEFT(successor);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The successor cannot possibly have a left child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * if there is any child, it is on the right.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(successor) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = RIGHT(successor);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Swap the two nodes; it would be simpler to just replace
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the value being deleted with that of the successor,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * but this rigamarole is done so the caller has complete
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * control over the pointers (and memory allocation) of
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * all of nodes. If just the key value were removed from
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the tree, the pointer to the node would be unchanged.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * First, put the successor in the tree location of the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node to be deleted. Save its existing tree pointer
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * information, which will be needed when linking up
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * delete to the successor's old location.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tmp, successor, sizeof(dns_rbtnode_t));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (IS_ROOT(item)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor->is_root = ISC_TRUE;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews item->is_root = ISC_FALSE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (LEFT(PARENT(item)) == item)
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews LEFT(PARENT(item)) = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(PARENT(item)) = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews PARENT(successor) = PARENT(item);
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews LEFT(successor) = LEFT(item);
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(successor) = RIGHT(item);
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews COLOR(successor) = COLOR(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(successor) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(LEFT(successor)) = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(successor) != successor)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater PARENT(RIGHT(successor)) = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Now relink the node to be deleted into the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * successor's previous tree location. PARENT(tmp)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * is the successor's original parent.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews INSIST(! IS_ROOT(item));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (PARENT(tmp) == item) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Node being deleted was successor's parent.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(successor) = item;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews PARENT(item) = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews LEFT(PARENT(tmp)) = item;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews PARENT(item) = PARENT(tmp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Original location of successor node has no left.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews LEFT(item) = NULL;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(item) = RIGHT(tmp);
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews COLOR(item) = COLOR(tmp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Remove the node by removing the links from its parent.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (! IS_ROOT(item)) {
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (LEFT(PARENT(item)) == item)
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews LEFT(PARENT(item)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews RIGHT(PARENT(item)) = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (child != NULL)
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews PARENT(child) = PARENT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This is the root being deleted, and at this point
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * it is known to have just one child.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *rootp = child;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child->is_root = 1;
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews PARENT(child) = PARENT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Fix color violations.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews if (IS_BLACK(item)) {
bfde61d5194a534d800f3b90008d1f52261922c5Mark Andrews parent = PARENT(item);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (child != *rootp && IS_BLACK(child)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(child == NULL || ! IS_ROOT(child));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(parent) == child) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = RIGHT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_RED(sibling)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_left(parent, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = RIGHT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
8f1c29d73f605d020824b9b10257de013917530fMark Andrews INSIST(sibling != NULL);
8f1c29d73f605d020824b9b10257de013917530fMark Andrews
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_BLACK(LEFT(sibling)) &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater IS_BLACK(RIGHT(sibling))) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_BLACK(RIGHT(sibling))) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(LEFT(sibling));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_right(sibling, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = RIGHT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater COLOR(sibling) = COLOR(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
4151109b94d197eb568b279b73022901c20e21b6Mark Andrews INSIST(RIGHT(sibling) != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(RIGHT(sibling));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_left(parent, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = *rootp;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Child is parent's right child.
47b7dfffe5d806c6a5e99ef17f07bcde812c2132Francis Dupont * Everything is done the same as above,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * except mirrored.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = LEFT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_RED(sibling)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_right(parent, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = LEFT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
8f1c29d73f605d020824b9b10257de013917530fMark Andrews INSIST(sibling != NULL);
8f1c29d73f605d020824b9b10257de013917530fMark Andrews
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_BLACK(LEFT(sibling)) &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater IS_BLACK(RIGHT(sibling))) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = parent;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_BLACK(LEFT(sibling))) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(RIGHT(sibling));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_RED(sibling);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_left(sibling, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater sibling = LEFT(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater COLOR(sibling) = COLOR(parent);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(parent);
4151109b94d197eb568b279b73022901c20e21b6Mark Andrews INSIST(LEFT(sibling) != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(LEFT(sibling));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater rotate_right(parent, rootp);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater child = *rootp;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater parent = PARENT(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_RED(child))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater MAKE_BLACK(child);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
a03848252fa85734ca75beae3d0b01bb503c0a8bMark Andrewsstatic void
7829fad4093f2c1985b1efb7cea00287ff015d2bckbfreenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb dns_rbtnode_t *node = *nodep;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (node->is_mmapped == 0) {
7829fad4093f2c1985b1efb7cea00287ff015d2bckb isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
7829fad4093f2c1985b1efb7cea00287ff015d2bckb *nodep = NULL;
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb rbt->nodecount--;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbstatic void
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaramandeletetreeflat(dns_rbt_t *rbt, unsigned int quantum, isc_boolean_t unhash,
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t **nodep)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman{
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *root = *nodep;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman while (root != NULL) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman /*
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * If there is a left, right or down node, walk into it
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * and iterate.
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (LEFT(root) != NULL) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *node = root;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman root = LEFT(root);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman LEFT(node) = NULL;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman } else if (RIGHT(root) != NULL) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *node = root;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman root = RIGHT(root);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman RIGHT(node) = NULL;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman } else if (DOWN(root) != NULL) {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *node = root;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman root = DOWN(root);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman DOWN(node) = NULL;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman } else {
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman /*
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * There are no left, right or down nodes, so we
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * can free this one and go back to its parent.
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman */
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman dns_rbtnode_t *node = root;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman root = PARENT(root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (DATA(node) != NULL && rbt->data_deleter != NULL)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman rbt->data_deleter(DATA(node),
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman rbt->deleter_arg);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (unhash)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman unhash_node(rbt, node);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman /*
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * Note: we don't call unhash_node() here as we
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman * are destroying the complete RBT tree.
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman */
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#if DNS_RBT_USEMAGIC
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman node->magic = 0;
c0bf2b179a199c50d2b50d43b18302ee5c3af6baAndreas Gustafsson#endif
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman freenode(rbt, &node);
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman if (quantum != 0 && --quantum == 0)
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman break;
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman
5d79b60fc5e4dad4f04da39570517d20a2425f8bMukund Sivaraman *nodep = root;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanstatic size_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramangetheight_helper(dns_rbtnode_t *node) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman size_t dl, dr;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman size_t this_height, down_height;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (node == NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (0);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman dl = getheight_helper(LEFT(node));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman dr = getheight_helper(RIGHT(node));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman this_height = ISC_MAX(dl + 1, dr + 1);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman down_height = getheight_helper(DOWN(node));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_MAX(this_height, down_height));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramansize_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns__rbt_getheight(dns_rbt_t *rbt) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (getheight_helper(rbt->root));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanstatic isc_boolean_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramancheck_properties_helper(dns_rbtnode_t *node) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (node == NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_TRUE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_RED(node)) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* Root nodes must be BLACK. */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_ROOT(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* Both children of RED nodes must be BLACK. */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_RED(LEFT(node)) || IS_RED(RIGHT(node)))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews if ((DOWN(node) != NULL) && (!IS_ROOT(DOWN(node))))
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews return (ISC_FALSE);
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews if (IS_ROOT(node)) {
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews if ((PARENT(node) != NULL) &&
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews (DOWN(PARENT(node)) != node))
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews return (ISC_FALSE);
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews if (get_upper_node(node) != PARENT(node))
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews return (ISC_FALSE);
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews }
e2047969decfc0c3fc1a946ccade993cab9c9315Mark Andrews
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* If node is assigned to the down_ pointer of its parent, it is
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * a subtree root and must have the flag set.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (((!PARENT(node)) ||
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman (DOWN(PARENT(node)) == node)) &&
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman (!IS_ROOT(node)))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* Repeat tests with this node's children. */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (check_properties_helper(LEFT(node)) &&
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman check_properties_helper(RIGHT(node)) &&
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman check_properties_helper(DOWN(node)));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanstatic isc_boolean_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramancheck_black_distance_helper(dns_rbtnode_t *node, size_t *distance) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman size_t dl, dr, dd;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (node == NULL) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman *distance = 1;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_TRUE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (!check_black_distance_helper(LEFT(node), &dl))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (!check_black_distance_helper(RIGHT(node), &dr))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (!check_black_distance_helper(DOWN(node), &dd))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* Left and right side black node counts must match. */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (dl != dr)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_BLACK(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman dl++;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman *distance = dl;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_TRUE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanisc_boolean_t
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns__rbt_checkproperties(dns_rbt_t *rbt) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman size_t dd;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (!check_properties_helper(rbt->root))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (ISC_FALSE);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* Path from a given node to all its leaves must contain the
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * same number of BLACK child nodes. This is done separately
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * here instead of inside check_properties_helper() as
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * it would take (n log n) complexity otherwise.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (check_black_distance_helper(rbt->root, &dd));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrencestatic void
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbt_indent(FILE *f, int depth) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater int i;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "%4d ", depth);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater for (i = 0; i < depth; i++)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "- ");
7829fad4093f2c1985b1efb7cea00287ff015d2bckb}
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckbvoid
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbt_printnodeinfo(dns_rbtnode_t *n, FILE *f) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Node info for nodename: ");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman printnodename(n, ISC_TRUE, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\n");
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "n = %p\n", n);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Relative pointers: %s%s%s%s%s\n",
7829fad4093f2c1985b1efb7cea00287ff015d2bckb (n->parent_is_relative == 1 ? " P" : ""),
7829fad4093f2c1985b1efb7cea00287ff015d2bckb (n->right_is_relative == 1 ? " R" : ""),
7829fad4093f2c1985b1efb7cea00287ff015d2bckb (n->left_is_relative == 1 ? " L" : ""),
7829fad4093f2c1985b1efb7cea00287ff015d2bckb (n->down_is_relative == 1 ? " D" : ""),
7829fad4093f2c1985b1efb7cea00287ff015d2bckb (n->data_is_relative == 1 ? " T" : ""));
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "node lock address = %d\n", n->locknum);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Parent: %p\n", n->parent);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Right: %p\n", n->right);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Left: %p\n", n->left);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "Down: %p\n", n->down);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "daTa: %p\n", n->data);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrencestatic void
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanprintnodename(dns_rbtnode_t *node, isc_boolean_t quoted, FILE *f) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_region_t r;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t name;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater char buffer[DNS_NAME_FORMATSIZE];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_offsets_t offsets;
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater r.length = NAMELEN(node);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater r.base = NAME(node);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_init(&name, offsets);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_fromregion(&name, &r);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_format(&name, buffer, sizeof(buffer));
9658892dbcf34d7afa8d1ca0400551a8b6ce8394David Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (quoted)
536da846f6cc03ad8abbb8bb9d5d8a6f607b8c33Mark Andrews fprintf(f, "\"%s\"", buffer);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman else
536da846f6cc03ad8abbb8bb9d5d8a6f607b8c33Mark Andrews fprintf(f, "%s", buffer);
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrencestatic void
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanprint_text_helper(dns_rbtnode_t *root, dns_rbtnode_t *parent,
7829fad4093f2c1985b1efb7cea00287ff015d2bckb int depth, const char *direction,
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman void (*data_printer)(FILE *, void *), FILE *f)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb{
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman dns_rbt_indent(f, depth);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (root != NULL) {
536da846f6cc03ad8abbb8bb9d5d8a6f607b8c33Mark Andrews printnodename(root, ISC_TRUE, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, " (%s, %s", direction,
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman IS_RED(root) ? "RED" : "BLACK");
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if ((! IS_ROOT(root) && PARENT(root) != parent) ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ( IS_ROOT(root) && depth > 0 &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater DOWN(PARENT(root)) != root)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, " (BAD parent pointer! -> ");
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (PARENT(root) != NULL)
536da846f6cc03ad8abbb8bb9d5d8a6f607b8c33Mark Andrews printnodename(PARENT(root), ISC_TRUE, f);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "NULL");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, ")");
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, ")");
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (root->data != NULL && data_printer != NULL) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, " data@%p: ", root->data);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman data_printer(f, root->data);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\n");
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater depth++;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_RED(root) && IS_RED(LEFT(root)))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "** Red/Red color violation on left\n");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman print_text_helper(LEFT(root), root, depth, "left",
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman data_printer, f);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (IS_RED(root) && IS_RED(RIGHT(root)))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "** Red/Red color violation on right\n");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman print_text_helper(RIGHT(root), root, depth, "right",
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman data_printer, f);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman print_text_helper(DOWN(root), NULL, depth, "down",
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman data_printer, f);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb } else {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "NULL (%s)\n", direction);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb }
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence
73d62a89f1493865c33c689b3ee3de91c74ad58eDavid Lawrencevoid
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbt_printtext(dns_rbt_t *rbt,
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman void (*data_printer)(FILE *, void *), FILE *f)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman{
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman REQUIRE(VALID_RBT(rbt));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman print_text_helper(rbt->root, NULL, 0, "root", data_printer, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanstatic int
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanprint_dot_helper(dns_rbtnode_t *node, unsigned int *nodecount,
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman isc_boolean_t show_pointers, FILE *f)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman{
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman unsigned int l, r, d;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (node == NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (0);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman l = print_dot_helper(LEFT(node), nodecount, show_pointers, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman r = print_dot_helper(RIGHT(node), nodecount, show_pointers, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman d = print_dot_helper(DOWN(node), nodecount, show_pointers, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman *nodecount += 1;
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "node%u[label = \"<f0> |<f1> ", *nodecount);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman printnodename(node, ISC_FALSE, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "|<f2>");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (show_pointers)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "|<f3> n=%p|<f4> p=%p", node, PARENT(node));
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\"] [");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_RED(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "color=red");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman else
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "color=black");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman /* XXXMUKS: verify that IS_ROOT() indicates subtree root and not
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * forest root.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_ROOT(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, ",penwidth=3");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (IS_EMPTY(node))
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, ",style=filled,fillcolor=lightgrey");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "];\n");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (LEFT(node) != NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\"node%u\":f0 -> \"node%u\":f1;\n", *nodecount, l);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (DOWN(node) != NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\"node%u\":f1 -> \"node%u\":f1 [penwidth=5];\n",
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman *nodecount, d);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman if (RIGHT(node) != NULL)
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "\"node%u\":f2 -> \"node%u\":f1;\n", *nodecount, r);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman return (*nodecount);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramanvoid
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaramandns_rbt_printdot(dns_rbt_t *rbt, isc_boolean_t show_pointers, FILE *f) {
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman unsigned int nodecount = 0;
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
bd1190c84b08e61a12789c54f083318c36449e5eDavid Lawrence
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "digraph g {\n");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "node [shape = record,height=.1];\n");
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman print_dot_helper(rbt->root, &nodecount, show_pointers, f);
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman fprintf(f, "}\n");
f389bc2c9e9e434380e10221778b7b548612a67fDavid Lawrence}
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence/*
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence * Chain Functions
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence */
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrencevoid
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrencedns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews REQUIRE(chain != NULL);
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt /*
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt * Initialize 'chain'.
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt */
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews chain->mctx = mctx;
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews chain->end = NULL;
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews chain->level_count = 0;
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews chain->level_matches = 0;
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews memset(chain->levels, 0, sizeof(chain->levels));
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
5497de6931b5ac26f65c2343b0318614f73933baMark Andrews chain->magic = CHAIN_MAGIC;
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
ec80744ad68b97f15657b1fdf5591c30b559b57dDavid Lawrencedns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *origin, dns_rbtnode_t **node)
c5944292e9ebee4a39fe939b9a16fe5596808556David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_CHAIN(chain));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (node != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater *node = chain->end;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (chain->end == NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (ISC_R_NOTFOUND);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (name != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(chain->end, name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (chain->level_count == 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Names in the top level tree are all absolute.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Always make 'name' relative.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(dns_name_isabsolute(name));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * This is cheaper than dns_name_getlabelsequence().
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater name->labels--;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater name->length--;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (origin != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (chain->level_count > 0)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = chain_name(chain, origin, ISC_FALSE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_name_copy(dns_rootname, origin, NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencedns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *origin)
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *current, *previous, *predecessor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_boolean_t new_origin = ISC_FALSE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = chain->end;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(current) != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Moving left one then right as far as possible is the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * previous node, at least for this level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (RIGHT(current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * No left links, so move toward the root. If at any point on
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the way there the link from parent to child is a right
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * link, then the parent is the previous node, at least
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * for this level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (! IS_ROOT(current)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater previous = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = PARENT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(current) == previous) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (predecessor != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Found a predecessor node in this level. It might not
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * really be the predecessor, however.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DOWN(predecessor) != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The predecessor is really down at least one level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Go down and as far right as possible, and repeat
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * as long as the rightmost node has a down pointer.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater do {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * XXX DCL Need to do something about origins
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * here. See whether to go down, and if so
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * whether it is truly what Bob calls a
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * new origin.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ADD_LEVEL(chain, predecessor);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = DOWN(predecessor);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /* XXX DCL duplicated from above; clever
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * way to unduplicate? */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (RIGHT(predecessor) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = RIGHT(predecessor);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } while (DOWN(predecessor) != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /* XXX DCL probably needs work on the concept */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (origin != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_origin = ISC_TRUE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else if (chain->level_count > 0) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Dang, didn't find a predecessor in this level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Got to the root of this level without having traversed
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * any right links. Ascend the tree one level; the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node that points to this tree is the predecessor.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater INSIST(chain->level_count > 0 && IS_ROOT(current));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater predecessor = chain->levels[--chain->level_count];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /* XXX DCL probably needs work on the concept */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Don't declare an origin change when the new origin is "."
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * at the top level tree, because "." is declared as the origin
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * for the second level tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (origin != NULL &&
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_origin = ISC_TRUE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (predecessor != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = predecessor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (new_origin) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbtnodechain_current(chain, name, origin,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = DNS_R_NEWORIGIN;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbtnodechain_current(chain, name, NULL,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOMORE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_result_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_name_t *origin)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews{
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_rbtnode_t *current, *successor;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_result_t result = ISC_R_SUCCESS;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_boolean_t new_origin = ISC_FALSE;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews successor = NULL;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = chain->end;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (DOWN(current) != NULL) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews /*
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Don't declare an origin change when the new origin is "."
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * at the second level tree, because "." is already declared
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * as the origin for the top level tree.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews */
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (chain->level_count > 0 ||
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews OFFSETLEN(current) > 1)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews new_origin = ISC_TRUE;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews ADD_LEVEL(chain, current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = DOWN(current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews while (LEFT(current) != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = LEFT(current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews successor = current;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews }
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (successor != NULL) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews chain->end = successor;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews /*
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * It is not necessary to use dns_rbtnodechain_current like
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * the other functions because this function will never
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * find a node in the topmost level. This is because the
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * root level will never be more than one name, and everything
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * in the megatree is a successor to that node, down at
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * the second level or below.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews */
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (name != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews NODENAME(chain->end, name);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (new_origin) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (origin != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = chain_name(chain, origin, ISC_FALSE);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (result == ISC_R_SUCCESS)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = DNS_R_NEWORIGIN;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews } else
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = ISC_R_SUCCESS;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews } else
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = ISC_R_NOMORE;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (result);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_result_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dns_rbtnode_t *current, *previous, *successor;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_result_t result = ISC_R_SUCCESS;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews successor = NULL;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = chain->end;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (RIGHT(current) == NULL) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews while (! IS_ROOT(current)) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews previous = current;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = PARENT(current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (LEFT(current) == previous) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews successor = current;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews break;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews }
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews }
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews } else {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = RIGHT(current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews while (LEFT(current) != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews current = LEFT(current);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews successor = current;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews }
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (successor != NULL) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews chain->end = successor;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (name != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews NODENAME(chain->end, name);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = ISC_R_SUCCESS;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews } else
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews result = ISC_R_NOMORE;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (result);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencedns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *origin)
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnode_t *current, *previous, *successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_boolean_t new_origin = ISC_FALSE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = chain->end;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * If there is a level below this node, the next node is the leftmost
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * node of the next level.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (DOWN(current) != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Don't declare an origin change when the new origin is "."
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * at the second level tree, because "." is already declared
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * as the origin for the top level tree.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (chain->level_count > 0 ||
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater OFFSETLEN(current) > 1)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_origin = ISC_TRUE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater ADD_LEVEL(chain, current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = DOWN(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (LEFT(current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else if (RIGHT(current) == NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * The successor is up, either in this level or a previous one.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Head back toward the root of the tree, looking for any path
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * that was via a left link; the successor is the node that has
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * that left link. In the event the root of the level is
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * reached without having traversed any left links, ascend one
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * level and look for either a right link off the point of
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * ascent, or search for a left link upward again, repeating
47b7dfffe5d806c6a5e99ef17f07bcde812c2132Francis Dupont * ascends until either case is true.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater do {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (! IS_ROOT(current)) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater previous = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = PARENT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (LEFT(current) == previous) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (successor == NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Reached the root without having traversed
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * any left pointers, so this level is done.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień if (chain->level_count == 0) {
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień /*
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * If the tree we are iterating over
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * was modified since this chain was
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * initialized in a way that caused
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * node splits to occur, "current" may
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * now be pointing to a root node which
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * appears to be at level 0, but still
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * has a parent. If that happens,
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * abort. Otherwise, we are done
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * looking for a successor as we really
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * reached the root node on level 0.
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień */
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień INSIST(PARENT(current) == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = chain->levels[--chain->level_count];
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater new_origin = ISC_TRUE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (RIGHT(current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater break;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } while (successor == NULL);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (successor == NULL && RIGHT(current) != NULL) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = RIGHT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater while (LEFT(current) != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater current = LEFT(current);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater successor = current;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater }
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (successor != NULL) {
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień /*
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * If we determine that the current node is the successor to
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień * itself, we will run into an infinite loop, so abort instead.
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień */
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień INSIST(chain->end != successor);
62f2fefaec754e6a4841ff0e72726e6c0cd89c86Michał Kępień
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = successor;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * It is not necessary to use dns_rbtnodechain_current like
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the other functions because this function will never
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * find a node in the topmost level. This is because the
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * root level will never be more than one name, and everything
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * in the megatree is a successor to that node, down at
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * the second level or below.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (name != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater NODENAME(chain->end, name);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (new_origin) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (origin != NULL)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = chain_name(chain, origin, ISC_FALSE);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = DNS_R_NEWORIGIN;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_SUCCESS;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater } else
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = ISC_R_NOMORE;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencedns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *name, dns_name_t *origin)
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_CHAIN(chain));
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = rbt->root;
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbtnodechain_current(chain, name, origin, NULL);
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = DNS_R_NEWORIGIN;
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence}
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencedns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_name_t *name, dns_name_t *origin)
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence{
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater isc_result_t result;
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_RBT(rbt));
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater REQUIRE(VALID_CHAIN(chain));
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = move_chain_to_last(chain, rbt->root);
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result != ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = dns_rbtnodechain_current(chain, name, origin, NULL);
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater if (result == ISC_R_SUCCESS)
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater result = DNS_R_NEWORIGIN;
1adfd0a9119434de35e1a6b6ddc65b28dd608308David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater return (result);
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrencevoid
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrencedns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt REQUIRE(VALID_CHAIN(chain));
03b5d2689df73fa9a50ff684511fa9d81f317e6cEvan Hunt
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Free any dynamic storage associated with 'chain', and then
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * reinitialize 'chain'.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->end = NULL;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_count = 0;
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->level_matches = 0;
5f50687f61057f7f0acb161d5803f4a48e40b3a8David Lawrence}
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencevoid
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrencedns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater /*
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * Free any dynamic storage associated with 'chain', and then
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater * invalidate 'chain'.
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater */
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater dns_rbtnodechain_reset(chain);
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence
f731b5d665e484c9b9634531c791cee9d87ab7a0Automatic Updater chain->magic = 0;
33950f0a0262f4d49528c4adcf8be42807fa2576David Lawrence}
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman/* XXXMUKS:
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman *
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * - worth removing inline as static functions are inlined automatically
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * where suitable by modern compilers.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * - bump the size of dns_rbt.nodecount to size_t.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * - the dumpfile header also contains a nodecount that is unsigned
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * int. If large files (> 2^32 nodes) are to be supported, the
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman * allocation for this field should be increased.
ce376a81fa674d240197628ceb6113a4fa5a1ab3Mukund Sivaraman */