rbt.c revision d9f0c713fe1d50f1848ca827c5f31db79d904f04
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley/*
9d5ed744c46ef241b9d3ba134bf3155e0b62ac9eAutomatic Updater * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1999-2003 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and/or distribute this software for any
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * purpose with or without fee is hereby granted, provided that the above
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley */
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley
e4d304b70b81ca9956c2eff7c24aacf4dd00266eEvan Hunt/* $Id$ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
e419f613d8591885df608cb73065921be07dd12eBob Halley/*! \file */
e419f613d8591885df608cb73065921be07dd12eBob Halley
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence/* Principal Authors: DCL */
fca5f81ad69098ea8abba130c7f841c951ef91c2Bob Halley
519b239fc4ef1e070e2da182a4ea559ae0152151Mark Andrews#include <config.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <sys/stat.h>
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews#ifdef HAVE_INTTYPES_H
9695ae1c24b168996e3a267855dc754971ccb32cBob Halley#include <inttypes.h> /* uintptr_t */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
1c776a2909632bc755f3fddd3b53addd792ab4d0Brian Wellington#include <isc/file.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <isc/hex.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <isc/mem.h>
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson#include <isc/platform.h>
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington#include <isc/print.h>
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#include <isc/refcount.h>
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews#include <isc/sha1.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <isc/socket.h>
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#include <isc/stdio.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <isc/string.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <isc/util.h>
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence/*%
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence * This define is so dns/name.h (included by dns/fixedname.h) uses more
e419f613d8591885df608cb73065921be07dd12eBob Halley * efficient macro calls instead of functions for a few operations.
e419f613d8591885df608cb73065921be07dd12eBob Halley */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define DNS_NAME_USEINLINE 1
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <dns/fixedname.h>
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <dns/log.h>
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <dns/rbt.h>
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <dns/result.h>
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <dns/version.h>
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#include <unistd.h>
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define CHECK(x) \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews do { \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews result = (x); \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (result != ISC_R_SUCCESS) \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews goto cleanup; \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews } while (0)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews/*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * XXXDCL Since parent pointers were added in again, I could remove all of the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * _lastnode. This would involve pretty major change to the API.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews#define RBT_HASH_SIZE 64
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#ifdef RBT_MEM_TEST
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#undef RBT_HASH_SIZE
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#endif
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstruct dns_rbt {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews unsigned int magic;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews isc_mem_t * mctx;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_rbtnode_t * root;
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence void (*data_deleter)(void *, void *);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews void * deleter_arg;
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley unsigned int nodecount;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews unsigned int hashsize;
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews dns_rbtnode_t ** hashtable;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews void * mmap_location;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews};
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define RED 0
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#define BLACK 1
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews/*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * This is the header for map-format RBT images. It is populated,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * and then written, as the LAST thing done to the file before returning.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * Writing this last (with zeros in the header area initially) will ensure
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * that the header is only valid when the RBT image is also valid.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewstypedef struct file_header file_header_t;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews/* Pad to 32 bytes */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsstatic char FILE_VERSION[32] = "\0";
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews/* Header length, always the same size regardless of structure size */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsconst unsigned int HEADER_LENGTH = 1024;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsstruct file_header {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews char version1[32];
50105afc551903541608b11851d73278b23579a3Mark Andrews isc_uint64_t first_node_offset; /* usually 1024 */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * information about the system on which the map file was generated
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews * will be used to tell if we can load the map file or not
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence isc_uint32_t ptrsize;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int bigendian:1; /* big or little endian system */
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington unsigned int nodecount; /* shadow from rbt structure */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews unsigned char digest[ISC_SHA1_DIGESTLENGTH];
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence char version2[32]; /* repeated; must match version1 */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington};
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence/*
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence * The following declarations are for the serialization of an RBT:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
50105afc551903541608b11851d73278b23579a3Mark Andrews * step one: write out a zeroed header of 1024 bytes
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * step two: walk the tree in a depth-first, left-right-down order, writing
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * out the nodes, reserving space as we go, correcting addresses to point
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * at the proper offset in the file, and setting a flag for each pointer to
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence * indicate that it is a reference to a location in the file, rather than in
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * memory.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * step three: write out the header, adding the information that will be
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * needed to re-create the tree object itself.
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence *
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * The RBTDB object will do this three times, once for each of the three
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * RBT objects it contains.
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington *
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * Note: 'file' must point an actual open file that can be mmapped
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * and fseeked, not to a pipe or stream
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence */
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssonstatic isc_result_t
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafssondns_rbt_zero_header(FILE *file);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewswrite_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned char *digest);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrewsstatic isc_result_t
50105afc551903541608b11851d73278b23579a3Mark Andrewsserialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
50105afc551903541608b11851d73278b23579a3Mark Andrews uintptr_t right, uintptr_t down, uintptr_t parent,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews uintptr_t data, isc_sha1_t *sha1);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstatic isc_result_t
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsserialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbtdatawriter_t datawriter, isc_uint32_t serial,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews uintptr_t *where, isc_sha1_t *sha1);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews/*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * The following functions allow you to get the actual address of a pointer
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * without having to use an if statement to check to see if that address is
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * relative or not
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstatic inline dns_rbtnode_t *
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsgetparent(dns_rbtnode_t *node, file_header_t *header) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews char *adjusted_address = (char *)(node->parent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews adjusted_address += node->parent_is_relative * (uintptr_t)header;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews return ((dns_rbtnode_t *)adjusted_address);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews}
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstatic inline dns_rbtnode_t *
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsgetleft(dns_rbtnode_t *node, file_header_t *header) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char *adjusted_address = (char *)(node->left);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley adjusted_address += node->left_is_relative * (uintptr_t)header;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley return ((dns_rbtnode_t *)adjusted_address);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington}
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleystatic inline dns_rbtnode_t *
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleygetright(dns_rbtnode_t *node, file_header_t *header) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char *adjusted_address = (char *)(node->right);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley adjusted_address += node->right_is_relative * (uintptr_t)header;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington return ((dns_rbtnode_t *)adjusted_address);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff}
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graffstatic inline dns_rbtnode_t *
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graffgetdown(dns_rbtnode_t *node, file_header_t *header) {
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff char *adjusted_address = (char *)(node->down);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley adjusted_address += node->down_is_relative * (uintptr_t)header;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley return ((dns_rbtnode_t *)adjusted_address);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic inline dns_rbtnode_t *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsgetdata(dns_rbtnode_t *node, file_header_t *header) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char *adjusted_address = (char *)(node->data);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews adjusted_address += node->data_is_relative * (uintptr_t)header;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return ((dns_rbtnode_t *)adjusted_address);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*%
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Elements of the rbtnode structure.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define PARENT(node) ((node)->parent)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define LEFT(node) ((node)->left)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define RIGHT(node) ((node)->right)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define DOWN(node) ((node)->down)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define DATA(node) ((node)->data)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define HASHNEXT(node) ((node)->hashnext)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#define HASHVAL(node) ((node)->hashval)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define COLOR(node) ((node)->color)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define NAMELEN(node) ((node)->namelen)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define OLDNAMELEN(node) ((node)->oldnamelen)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define OFFSETLEN(node) ((node)->offsetlen)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define ATTRS(node) ((node)->attributes)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define IS_ROOT(node) ISC_TF((node)->is_root == 1)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/*%
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Structure elements from the rbtdb.c, not
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * used as part of the rbt.c algorithms.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define DIRTY(node) ((node)->dirty)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define WILD(node) ((node)->wild)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define LOCKNUM(node) ((node)->locknum)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews/*%
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * The variable length stuff stored after the node has the following
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * structure.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews *
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * <name_data>{1..255}<oldoffsetlen>{1}<offsets>{1..128}
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews *
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * <name_data> contains the name of the node when it was created.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * <oldoffsetlen> contains the length of <offsets> when the node was created.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * <offsets> contains the offets into name for each label when the node was
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * created.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define NAME(node) ((unsigned char *)((node) + 1))
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define OFFSETS(node) (NAME(node) + OLDNAMELEN(node) + 1)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define OLDOFFSETLEN(node) (OFFSETS(node)[-1])
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#define NODE_SIZE(node) (sizeof(*node) + \
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews/*%
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Color management.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington#define IS_RED(node) ((node) != NULL && (node)->color == RED)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington#define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington#define MAKE_RED(node) ((node)->color = RED)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington#define MAKE_BLACK(node) ((node)->color = BLACK)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*%
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * Chain management.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington *
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * The "ancestors" member of chains were removed, with their job now
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * being wholly handled by parent pointers (which didn't exist, because
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff * of memory concerns, when chains were first implemented).
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington */
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff#define ADD_LEVEL(chain, node) \
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington (chain)->levels[(chain)->level_count++] = (node)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/*%
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * The following macros directly access normally private name variables.
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * These macros are used to avoid a lot of function calls in the critical
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * path of the tree traversal code.
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrewsstatic inline void
7d116211ec7b063891130f191e3ed437b45dba70Mark AndrewsNODENAME(dns_rbtnode_t *node, dns_name_t *name)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington{
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington name->length = NAMELEN(node);
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington name->labels = OFFSETLEN(node);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington name->ndata = NAME(node);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington name->offsets = OFFSETS(node);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson name->attributes = ATTRS(node);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington name->attributes |= DNS_NAMEATTR_READONLY;
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews}
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews#ifdef DNS_RBT_USEHASH
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonstatic isc_result_t
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellingtoninithash(dns_rbt_t *rbt);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#endif
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#ifdef DEBUG
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#define inline
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * A little something to help out in GDB.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington */
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtondns_name_t Name(dns_rbtnode_t *node);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtondns_name_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark AndrewsName(dns_rbtnode_t *node) {
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington dns_name_t name;
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_name_init(&name, NULL);
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson if (node != NULL)
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington NODENAME(node, &name);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington return (name);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington}
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellingtonstatic void printnodename(dns_rbtnode_t *node);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewshexdump(const char *desc, unsigned char *data, size_t size) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char hexdump[BUFSIZ];
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington isc_buffer_t b;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington isc_region_t r;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews isc_buffer_init(&b, hexdump, sizeof(hexdump));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews r.base = data;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews r.length = size;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews isc_hex_totext(&r, 0, "", &b);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington isc_buffer_putuint8(&b, 0);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews fprintf(stderr, "%s: %s\n", desc, hexdump);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington}
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic inline dns_rbtnode_t *
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellingtonfind_up(dns_rbtnode_t *node) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rbtnode_t *root;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington /*
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington * Return the node in the level above the argument node that points
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington * to the level the argument node is in. If the argument node is in
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington * the top level, the return value is NULL.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington for (root = node; ! IS_ROOT(root); root = PARENT(root))
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington ; /* Nothing. */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews return (PARENT(root));
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews}
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews/*
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * Forward declarations.
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellingtoncreate_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington#ifdef DNS_RBT_USEHASH
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellingtonstatic inline void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewshash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic inline void
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrewsunhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews#else
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews#define hash_node(rbt, node, name)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define unhash_node(rbt, node)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrewsstatic inline void
50105afc551903541608b11851d73278b23579a3Mark Andrewsrotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
50105afc551903541608b11851d73278b23579a3Mark Andrewsstatic inline void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsrotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
a05f23d07e1b60a1d88119678111a47014480611Mark Andrews
a05f23d07e1b60a1d88119678111a47014480611Mark Andrewsstatic void
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellingtonaddonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_t **rootp);
a05f23d07e1b60a1d88119678111a47014480611Mark Andrews
a05f23d07e1b60a1d88119678111a47014480611Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdeletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellingtonstatic isc_result_t
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellingtontreefix(dns_rbt_t *rbt, void *base, size_t size,
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington dns_rbtnode_t *n, dns_name_t *name,
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellingtonstatic isc_result_t
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellingtondeletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdeletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep);
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonprintnodename(dns_rbtnode_t *node);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsfreenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstatic isc_result_t
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsdns_rbt_zero_header(FILE *file) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Write out a zeroed header as a placeholder. Doing this ensures
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * that the file will not read while it is partially written, should
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * writing fail or be interrupted.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews char buffer[HEADER_LENGTH];
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews isc_result_t result;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews memset(buffer, 0, HEADER_LENGTH);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = isc_stdio_write(buffer, 1, HEADER_LENGTH, file, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews result = fflush(file);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Write out the real header, including NodeDump version information
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * and the offset of the first node.
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington *
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * Any information stored in the rbt object itself should be stored
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews * here.
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews */
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrewsstatic isc_result_t
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrewswrite_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews unsigned char *digest)
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews file_header_t header;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews long location;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (FILE_VERSION[0] == '\0') {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews memset(FILE_VERSION, 0, sizeof(FILE_VERSION));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews snprintf(FILE_VERSION, sizeof(FILE_VERSION),
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews "RBT Image %s %s", dns_major, dns_mapapi);
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews }
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews memset(&header, 0, sizeof(file_header_t));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews memcpy(header.version1, FILE_VERSION, sizeof(header.version1));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews memcpy(header.version2, FILE_VERSION, sizeof(header.version2));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews header.first_node_offset = first_node_offset;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews header.ptrsize = (isc_uint32_t) sizeof(void *);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews header.bigendian = (1 == htonl(1)) ? 1 : 0;
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews#ifdef DNS_RDATASET_FIXED
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews header.rdataset_fixed = 1;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#else
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews header.rdataset_fixed = 0;
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews#endif
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews header.nodecount = rbt->nodecount;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews memcpy(header.digest, digest, sizeof(header.digest));
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews location = ftell(file);
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews if (location < 0)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_FAILURE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews location = dns_rbt_serialize_align(location);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews CHECK(isc_stdio_seek(file, location, SEEK_SET));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(isc_stdio_write(&header, 1, sizeof(file_header_t), file, NULL));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(fflush(file));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Ensure we are always at the end of the file. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(isc_stdio_seek(file, 0, SEEK_END));
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews cleanup:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsserialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews uintptr_t right, uintptr_t down, uintptr_t parent,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews uintptr_t data, isc_sha1_t *sha1)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_t temp_node;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews long file_position;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned char *node_data;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews size_t datasize;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#ifdef DEBUG
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t nodename;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington INSIST(node != NULL);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews file_position = ftell(file);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (file_position < 0)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (ISC_R_FAILURE);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews file_position = dns_rbt_serialize_align(file_position);
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington CHECK(isc_stdio_seek(file, file_position, SEEK_SET));
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node = *node;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node.down_is_relative = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews temp_node.left_is_relative = 0;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node.right_is_relative = 0;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington temp_node.parent_is_relative = 0;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node.data_is_relative = 0;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node.is_mmapped = 1;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington /*
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * If the next node is not NULL, calculate the next node's location
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * in the file. Note that this will have to change when the data
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * structure changes, and it also assumes that we always write the
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * nodes out in list order (which we currently do.)
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (temp_node.parent != NULL) {
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington temp_node.parent = (dns_rbtnode_t *)(parent);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington temp_node.parent_is_relative = 1;
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington }
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (temp_node.left != NULL) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington temp_node.left = (dns_rbtnode_t *)(left);
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews temp_node.left_is_relative = 1;
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews }
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews if (temp_node.right != NULL) {
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson temp_node.right = (dns_rbtnode_t *)(right);
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson temp_node.right_is_relative = 1;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (temp_node.down != NULL) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington temp_node.down = (dns_rbtnode_t *)(down);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington temp_node.down_is_relative = 1;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (temp_node.data != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews temp_node.data = (dns_rbtnode_t *)(data);
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington temp_node.data_is_relative = 1;
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington }
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson node_data = (unsigned char *) node + sizeof(dns_rbtnode_t);
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington datasize = NODE_SIZE(node) - sizeof(dns_rbtnode_t);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews file, NULL));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(isc_stdio_write(node_data, 1, datasize, file, NULL));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#ifdef DEBUG
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_init(&nodename, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NODENAME(node, &nodename);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews fprintf(stderr, "serialize ");
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_print(&nodename, stderr);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews fprintf(stderr, "\n");
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews hexdump("node header", (unsigned char*) &temp_node,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews sizeof(dns_rbtnode_t));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews hexdump("node data", node_data, datasize);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_sha1_update(sha1, (const isc_uint8_t *) &temp_node,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews sizeof(dns_rbtnode_t));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_sha1_update(sha1, (const isc_uint8_t *) node_data, datasize);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews cleanup:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsserialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtdatawriter_t datawriter, isc_uint32_t serial,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews uintptr_t *where, isc_sha1_t *sha1)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews uintptr_t left = 0, right = 0, down = 0, data = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews long location = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_uint64_t offset_adjust;
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (node == NULL) {
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews if (where != NULL)
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews *where = 0;
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews return (ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Reserve space for current node. */
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews location = ftell(file);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (location < 0)
50105afc551903541608b11851d73278b23579a3Mark Andrews return (ISC_R_FAILURE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews location = dns_rbt_serialize_align(location);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(isc_stdio_seek(file, location, SEEK_SET));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews location = ftell(file);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (location < 0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_FAILURE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Serialize the rest of the tree.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * WARNING: A change in the order (from left, right, down)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * will break the way the sha1 hash is computed.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(serialize_nodes(file, getleft(node, NULL), location,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews datawriter, serial, &left, sha1));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(serialize_nodes(file, getright(node, NULL), location,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews datawriter, serial, &right, sha1));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews CHECK(serialize_nodes(file, getdown(node, NULL), location,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews datawriter, serial, &down, sha1));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (node->data != NULL) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews long ret;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington ret = ftell(file);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (ret < 0)
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews return (ISC_R_FAILURE);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington ret = dns_rbt_serialize_align(ret);
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 CHECK(isc_stdio_seek(file, ret, SEEK_SET));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews ret = ftell(file);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (ret < 0)
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews return (ISC_R_FAILURE);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington data = ret;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews datawriter(file, node->data, serial, sha1);
4e259c5a2321e994708fb1fe04cd4da30aa3b612Mark Andrews }
4e259c5a2321e994708fb1fe04cd4da30aa3b612Mark Andrews
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews /* Seek back to reserved space. */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(isc_stdio_seek(file, location, SEEK_SET));
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson /* Serialize the current node. */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(serialize_node(file, node, left, right, down, parent, data,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews sha1));
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews /* Ensure we are always at the end of the file. */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington CHECK(isc_stdio_seek(file, 0, SEEK_END));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (where != NULL)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews *where = location;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington cleanup:
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (result);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewslong
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsdns_rbt_serialize_align(long target) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews long offset = target % 8;
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (offset == 0)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (target);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews else
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (target + 8 - offset);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrewsisc_result_t
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrewsdns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtdatawriter_t datawriter,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_uint32_t serial, long *offset)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews{
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews long header_position, node_position, end_position;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned char digest[ISC_SHA1_DIGESTLENGTH];
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_sha1_t sha1;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(file != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews CHECK(isc_file_isplainfilefd(fileno(file)));
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_sha1_init(&sha1);
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews header_position = ftell(file);
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews if (header_position < 0)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_FAILURE);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington /* Write dummy header */
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews CHECK(dns_rbt_zero_header(file));
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews /* Serialize nodes */
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews node_position = ftell(file);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (node_position < 0)
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews return (ISC_R_FAILURE);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews CHECK(serialize_nodes(file, rbt->root, 0, datawriter, serial, NULL,
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews &sha1));
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews end_position = ftell(file);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (end_position < 0)
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews return (ISC_R_FAILURE);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (node_position == end_position) {
676619a22fbc760875adb00b58aaef6a22ced18aMark Andrews CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews *offset = 0;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_SUCCESS);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_sha1_final(&sha1, digest);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#ifdef DEBUG
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hexdump("serializing digest", digest, sizeof(digest));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#endif
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews /* Serialize header */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(write_header(file, rbt, HEADER_LENGTH, digest));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews /* Ensure we are always at the end of the file. */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(isc_stdio_seek(file, 0, SEEK_END));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews *offset = dns_rbt_serialize_align(header_position);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews cleanup:
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (result);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews}
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#define CONFIRM(a) do { \
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (! (a)) { \
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews result = ISC_R_INVALIDFILE; \
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews goto cleanup; \
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews } \
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington} while(0);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewstreefix(dns_rbt_t *rbt, void *base, size_t filesize, dns_rbtnode_t *n,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_t *name, dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews{
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result = ISC_R_SUCCESS;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_fixedname_t fixed;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_t nodename, *fullname;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned char *node_data;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t header;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews size_t datasize, nodemax = filesize - sizeof(dns_rbtnode_t);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (n == NULL)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_SUCCESS);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_init(&nodename, NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews NODENAME(n, &nodename);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews fullname = &nodename;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (!dns_name_isabsolute(&nodename)) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_fixedname_init(&fixed);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews fullname = dns_fixedname_name(&fixed);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CHECK(dns_name_concatenate(&nodename, name, fullname, NULL));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews /* memorize header contents prior to fixup */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews memcpy(&header, n, sizeof(header));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (n->left_is_relative) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CONFIRM(n->left <= (dns_rbtnode_t *) nodemax);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews n->left = getleft(n, rbt->mmap_location);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews n->left_is_relative = 0;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CONFIRM(DNS_RBTNODE_VALID(n->left));
95b484c9580d06eb2f9735a22e9841389c2859baMark Andrews } else
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CONFIRM(n->left == NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (n->right_is_relative) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CONFIRM(n->right <= (dns_rbtnode_t *) nodemax);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews n->right = getright(n, rbt->mmap_location);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews n->right_is_relative = 0;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews CONFIRM(DNS_RBTNODE_VALID(n->right));
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington } else
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington CONFIRM(n->right == NULL);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (n->down_is_relative) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews CONFIRM(n->down <= (dns_rbtnode_t *) nodemax);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews n->down = getdown(n, rbt->mmap_location);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews n->down_is_relative = 0;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews CONFIRM(DNS_RBTNODE_VALID(n->down));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews } else
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CONFIRM(n->down == NULL);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (n->parent_is_relative) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CONFIRM(n->parent <= (dns_rbtnode_t *) nodemax);
216030f2849b0812910fbc1817ca17208a112663Mark Andrews n->parent = getparent(n, rbt->mmap_location);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews n->parent_is_relative = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CONFIRM(DNS_RBTNODE_VALID(n->parent));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews } else
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CONFIRM(n->parent == NULL);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (n->data_is_relative) {
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington CONFIRM(n->data <= (void *) filesize);
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington n->data = getdata(n, rbt->mmap_location);
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington n->data_is_relative = 0;
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington } else
b0d31c78bc24080d4c470a8bd98862375f6e3055Mark Andrews CONFIRM(n->data == NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington hash_node(rbt, n, fullname);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington /* a change in the order (from left, right, down) will break hashing*/
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (n->left != NULL)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington CHECK(treefix(rbt, base, filesize, n->left, name,
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews datafixer, sha1));
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews if (n->right != NULL)
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews CHECK(treefix(rbt, base, filesize, n->right, name,
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson datafixer, sha1));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (n->down != NULL)
b0d31c78bc24080d4c470a8bd98862375f6e3055Mark Andrews CHECK(treefix(rbt, base, filesize, n->down, fullname,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews datafixer, sha1));
f15af68028adc665d3bdddf955fc52bad83f0514Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (datafixer != NULL && n->data != NULL)
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(datafixer(n, base, filesize, sha1));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews node_data = (unsigned char *) n + sizeof(dns_rbtnode_t);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews datasize = NODE_SIZE(n) - sizeof(dns_rbtnode_t);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#ifdef DEBUG
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews fprintf(stderr, "deserialize ");
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater dns_name_print(&nodename, stderr);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews fprintf(stderr, "\n");
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hexdump("node header", (unsigned char *) &header,
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington sizeof(dns_rbtnode_t));
4e259c5a2321e994708fb1fe04cd4da30aa3b612Mark Andrews hexdump("node data", node_data, datasize);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews#endif
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_sha1_update(sha1, (const isc_uint8_t *) &header,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews sizeof(dns_rbtnode_t));
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater isc_sha1_update(sha1, (const isc_uint8_t *) node_data,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews datasize);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews cleanup:
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (result);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsisc_result_t
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsdns_rbt_deserialize_tree(void *base_address, size_t filesize,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews off_t header_offset, isc_mem_t *mctx,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews void (*deleter)(void *, void *),
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews void *deleter_arg,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtdatafixer_t datafixer,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t **originp, dns_rbt_t **rbtp)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews{
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result = ISC_R_SUCCESS;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews file_header_t *header;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned char digest[ISC_SHA1_DIGESTLENGTH];
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbt_t *rbt = NULL;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews isc_sha1_t sha1;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington REQUIRE(originp == NULL || *originp == NULL);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_sha1_init(&sha1);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_rbt_create(mctx, deleter, deleter_arg, &rbt));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington rbt->mmap_location = base_address;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington header = (file_header_t *)((char *)base_address + header_offset);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington#ifdef DNS_RDATASET_FIXED
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington if (header->rdataset_fixed != 1) {
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington return (ISC_R_INVALIDFILE);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#else
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (header->rdataset_fixed != 0) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (ISC_R_INVALIDFILE);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#endif
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (header->ptrsize != (isc_uint32_t) sizeof(void *)) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (ISC_R_INVALIDFILE);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (header->bigendian != (1 == htonl(1)) ? 1 : 0) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (ISC_R_INVALIDFILE);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Copy other data items from the header into our rbt. */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->root = (dns_rbtnode_t *)((char *)base_address +
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews header_offset + header->first_node_offset);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->nodecount = header->nodecount;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews CHECK(treefix(rbt, base_address, filesize, rbt->root,
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rootname, datafixer, &sha1));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews isc_sha1_final(&sha1, digest);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews#ifdef DEBUG
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews hexdump("deserializing digest", digest, sizeof(digest));
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#endif
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Check file hash */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (memcmp(header->digest, digest, sizeof(digest)) != 0) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington result = ISC_R_INVALIDFILE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto cleanup;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews *rbtp = rbt;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (originp != NULL)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews *originp = rbt->root;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews cleanup:
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (result != ISC_R_SUCCESS) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->root = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->nodecount = 0;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbt_destroy(&rbt);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (result);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews/*
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * Initialize a red/black tree of trees.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsisc_result_t
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsdns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews void *deleter_arg, dns_rbt_t **rbtp)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews{
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews#ifdef DNS_RBT_USEHASH
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews isc_result_t result;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews#endif
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbt_t *rbt;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(mctx != NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(rbtp != NULL && *rbtp == NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (rbt == NULL)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (ISC_R_NOMEMORY);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->mctx = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews isc_mem_attach(mctx, &rbt->mctx);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->data_deleter = deleter;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->deleter_arg = deleter_arg;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->root = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->nodecount = 0;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->hashtable = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->hashsize = 0;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->mmap_location = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews#ifdef DNS_RBT_USEHASH
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater result = inithash(rbt);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (result != ISC_R_SUCCESS) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (result);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews#endif
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->magic = RBT_MAGIC;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews *rbtp = rbt;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (ISC_R_SUCCESS);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews/*
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * Deallocate a red/black tree of trees.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsvoid
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsdns_rbt_destroy(dns_rbt_t **rbtp) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsisc_result_t
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsdns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbt_t *rbt;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt = *rbtp;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews deletetreeflat(rbt, quantum, &rbt->root);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (rbt->root != NULL)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (ISC_R_QUOTA);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews INSIST(rbt->nodecount == 0);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->mmap_location = NULL;
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater if (rbt->hashtable != NULL)
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater isc_mem_put(rbt->mctx, rbt->hashtable,
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater rbt->hashsize * sizeof(dns_rbtnode_t *));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rbt->magic = 0;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews isc_mem_putanddetach(&rbt->mctx, rbt, sizeof(*rbt));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews *rbtp = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return (ISC_R_SUCCESS);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsunsigned int
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsdns_rbt_nodecount(dns_rbt_t *rbt) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington REQUIRE(VALID_RBT(rbt));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (rbt->nodecount);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews}
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsunsigned int
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_rbt_hashsize(dns_rbt_t *rbt) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington REQUIRE(VALID_RBT(rbt));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (rbt->hashsize);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic inline isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewschain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t include_chain_end)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t nodename;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result = ISC_R_SUCCESS;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington int i;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_init(&nodename, NULL);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (include_chain_end && chain->end != NULL) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews NODENAME(chain->end, &nodename);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews result = dns_name_copy(&nodename, name, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_reset(name);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington for (i = (int)chain->level_count - 1; i >= 0; i--) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington NODENAME(chain->levels[i], &nodename);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington result = dns_name_concatenate(name, &nodename, name, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic inline isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsmove_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews do {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Go as far right and then down as much as possible,
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * as long as the rightmost node has a down pointer.
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews while (RIGHT(node) != NULL)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews node = RIGHT(node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DOWN(node) == NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews break;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ADD_LEVEL(chain, node);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews node = DOWN(node);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington } while (1);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->end = node;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Add 'name' to tree, initializing its data pointer with 'data'.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsisc_result_t
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsdns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Does this thing have too many variables or what?
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington */
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington dns_rbtnode_t **root, *parent, *child, *current, *new_current;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_offsets_t current_offsets;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_namereln_t compared;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson isc_result_t result = ISC_R_SUCCESS;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_rbtnodechain_t chain;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson unsigned int common_labels;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington unsigned int nlabels, hlabels;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews int order;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley REQUIRE(VALID_RBT(rbt));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley REQUIRE(dns_name_isabsolute(name));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley REQUIRE(nodep != NULL && *nodep == NULL);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Create a copy of the name so the original name structure is
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * not modified.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington */
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_fixedname_init(&fixedcopy);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington add_name = dns_fixedname_name(&fixedcopy);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_name_clone(name, add_name);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (rbt->root == NULL) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = create_node(rbt->mctx, add_name, &new_current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result == ISC_R_SUCCESS) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley rbt->nodecount++;
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington new_current->is_root = 1;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley rbt->root = new_current;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley *nodep = new_current;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley hash_node(rbt, new_current, name);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley return (result);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
5c29047792191d6141f69b2684314d0b762fedebBrian Wellington
5c29047792191d6141f69b2684314d0b762fedebBrian Wellington dns_rbtnodechain_init(&chain, rbt->mctx);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_fixedname_init(&fixedprefix);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_fixedname_init(&fixedsuffix);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley prefix = dns_fixedname_name(&fixedprefix);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington suffix = dns_fixedname_name(&fixedsuffix);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
63bf060be4ff2a7ade02fd86abb98694a5afc250Brian Wellington root = &rbt->root;
63bf060be4ff2a7ade02fd86abb98694a5afc250Brian Wellington INSIST(IS_ROOT(*root));
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington parent = NULL;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington current = NULL;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington child = *root;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_name_init(&current_name, current_offsets);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_fixedname_init(&fnewname);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington new_name = dns_fixedname_name(&fnewname);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington nlabels = dns_name_countlabels(name);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington hlabels = 0;
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington do {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley current = child;
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews NODENAME(current, &current_name);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley compared = dns_name_fullcompare(add_name, &current_name,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley &order, &common_labels);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (compared == dns_namereln_equal) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley *nodep = current;
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington result = ISC_R_EXISTS;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington break;
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (compared == dns_namereln_none) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (order < 0) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews parent = current;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews child = LEFT(current);
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews } else if (order > 0) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley parent = current;
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 child = RIGHT(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley } else {
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington /*
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * This name has some suffix in common with the
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * name at the current node. If the name at
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * the current node is shorter, that means the
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * new name should be in a subtree. If the
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * name at the current node is longer, that means
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 * the down pointer to this tree should point
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington * to a new tree that has the common suffix, and
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * the non-common parts of these two names should
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * start a new tree.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews hlabels += common_labels;
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson if (compared == dns_namereln_subdomain) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * All of the existing labels are in common,
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson * so the new name is in a subtree.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * Whack off the common labels for the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not-in-common part to be searched for
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson * in the next level.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_split(add_name, common_labels,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews add_name, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Follow the down pointer (possibly NULL).
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington */
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington root = &DOWN(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley INSIST(*root == NULL ||
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley (IS_ROOT(*root) &&
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews PARENT(*root) == current));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley parent = NULL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley child = DOWN(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley ADD_LEVEL(&chain, current);
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington } else {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * The number of labels in common is fewer
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * than the number of labels at the current
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * node, so the current node must be adjusted
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * to have just the common suffix, and a down
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * pointer made to a new tree.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(compared == dns_namereln_commonancestor
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews || compared == dns_namereln_contains);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington /*
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington * Ensure the number of levels in the tree
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington * does not exceed the number of logical
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * levels allowed by DNSSEC.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley *
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * XXXDCL need a better error result?
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington *
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * XXXDCL Since chain ancestors were removed,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * no longer used by addonlevel(),
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * this is the only real use of chains in the
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * function. It could be done instead with
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * a simple integer variable, but I am pressed
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * for time.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington */
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (chain.level_count ==
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington (sizeof(chain.levels) /
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington sizeof(*chain.levels))) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = ISC_R_NOSPACE;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley break;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington /*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Split the name into two parts, a prefix
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington * which is the not-in-common parts of the
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * two names and a suffix that is the common
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * parts of them.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_name_split(&current_name, common_labels,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley prefix, suffix);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = create_node(rbt->mctx, suffix,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley &new_current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_SUCCESS)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley break;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Reproduce the tree attributes of the
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * current node.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington new_current->is_root = current->is_root;
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington if (current->nsec == DNS_RBT_NSEC_HAS_NSEC)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington new_current->nsec = DNS_RBT_NSEC_NORMAL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley else
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley new_current->nsec = current->nsec;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley PARENT(new_current) = PARENT(current);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington LEFT(new_current) = LEFT(current);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington RIGHT(new_current) = RIGHT(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley COLOR(new_current) = COLOR(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Fix pointers that were to the current node.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (parent != NULL) {
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington if (LEFT(parent) == current)
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington LEFT(parent) = new_current;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington else
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington RIGHT(parent) = new_current;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (LEFT(new_current) != NULL)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley PARENT(LEFT(new_current)) =
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley new_current;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (RIGHT(new_current) != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PARENT(RIGHT(new_current)) =
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews new_current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (*root == current)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *root = new_current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NAMELEN(current) = prefix->length;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews OFFSETLEN(current) = prefix->labels;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Set up the new root of the next level.
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * By definition it will not be the top
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews current->is_root = 1;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews PARENT(current) = new_current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DOWN(new_current) = current;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews root = &DOWN(new_current);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ADD_LEVEL(&chain, new_current);
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington LEFT(current) = NULL;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington RIGHT(current) = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews MAKE_BLACK(current);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington rbt->nodecount++;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington dns_name_getlabelsequence(name,
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington nlabels - hlabels,
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington hlabels, new_name);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews hash_node(rbt, new_current, new_name);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews if (common_labels ==
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews dns_name_countlabels(add_name)) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The name has been added by pushing
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the not-in-common parts down to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * a new level.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *nodep = new_current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_SUCCESS);
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews } else {
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The current node has no data,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * because it is just a placeholder.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Its data pointer is already NULL
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * from create_node()), so there's
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * nothing more to do to it.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * The not-in-common parts of the new
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * name will be inserted into the new
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * level following this loop (unless
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * result != ISC_R_SUCCESS, which
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * is tested after the loop ends).
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_split(add_name, common_labels,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews add_name, NULL);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews break;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } while (child != NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (result == ISC_R_SUCCESS)
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews result = create_node(rbt->mctx, add_name, &new_current);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews if (result == ISC_R_SUCCESS) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews addonlevel(new_current, current, order, root);
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews rbt->nodecount++;
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews *nodep = new_current;
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews hash_node(rbt, new_current, name);
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews }
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews return (result);
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews}
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews
cc7d91bd5c6b9be5a3c67a99112b885602c24873Mark Andrews/*
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews * Add a name to the tree of trees, associating it with some data.
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrews */
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrewsisc_result_t
fabf2ee6b01ee06a0de940b83d53cf57f9f79265Mark Andrewsdns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t *node;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(VALID_RBT(rbt));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(dns_name_isabsolute(name));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews node = NULL;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington result = dns_rbt_addnode(rbt, name, &node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson * dns_rbt_addnode will report the node exists even when
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson * it does not have data associated with it, but the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * dns_rbt_*name functions all behave depending on whether
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * there is data associated with a node.
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (result == ISC_R_SUCCESS ||
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson (result == ISC_R_EXISTS && DATA(node) == NULL)) {
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington DATA(node) = data;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = ISC_R_SUCCESS;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews return (result);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley}
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley/*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Find the node for "name" in the tree of trees.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleyisc_result_t
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleydns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence unsigned int options, dns_rbtfindcallback_t callback,
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson void *callback_arg)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence{
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_rbtnode_t *current, *last_compared, *current_root;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_rbtnodechain_t localchain;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_name_t *search_name, current_name, *callback_name;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_fixedname_t fixedcallbackname, fixedsearchname;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_namereln_t compared;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson isc_result_t result, saved_result;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson unsigned int common_labels;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson unsigned int hlabels = 0;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson int order;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews REQUIRE(VALID_RBT(rbt));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley REQUIRE(dns_name_isabsolute(name));
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington REQUIRE(node != NULL && *node == NULL);
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington != (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington /*
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * If there is a chain it needs to appear to be in a sane state,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * otherwise a chain is still needed to generate foundname and
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson * callback_name.
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (chain == NULL) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley options |= DNS_RBTFIND_NOPREDECESSOR;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley chain = &localchain;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnodechain_init(chain, rbt->mctx);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley } else
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnodechain_reset(chain);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (rbt->root == NULL)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_NOTFOUND);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence else {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * Appease GCC about variables it incorrectly thinks are
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * possibly used uninitialized.
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson */
0a3e2e1d590dac7fb011e72bd3a4982c179d8e68Brian Wellington compared = dns_namereln_none;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley last_compared = NULL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley order = 0;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington dns_fixedname_init(&fixedcallbackname);
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington callback_name = dns_fixedname_name(&fixedcallbackname);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews /*
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * search_name is the name segment being sought in each tree level.
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * By using a fixedname, the search_name will definitely have offsets
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * for use by any splitting.
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * By using dns_name_clone, no name data should be copied thanks to
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * the lack of bitstring labels.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington */
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington dns_fixedname_init(&fixedsearchname);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington search_name = dns_fixedname_name(&fixedsearchname);
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington dns_name_clone(name, search_name);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_init(&current_name, NULL);
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington saved_result = ISC_R_SUCCESS;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington current = rbt->root;
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington current_root = rbt->root;
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington while (current != NULL) {
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington NODENAME(current, &current_name);
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington compared = dns_name_fullcompare(search_name, &current_name,
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington &order, &common_labels);
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington last_compared = current;
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington if (compared == dns_namereln_equal)
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington break;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington if (compared == dns_namereln_none) {
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington#ifdef DNS_RBT_USEHASH
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_name_t hash_name;
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_rbtnode_t *hnode;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington dns_rbtnode_t *up_current;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington unsigned int nlabels;
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington unsigned int tlabels = 1;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington unsigned int hash;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * If there is no hash table, hashing can't be done.
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington */
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (rbt->hashtable == NULL)
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington goto nohash;
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington /*
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * The case of current != current_root, that
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * means a left or right pointer was followed,
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * only happens when the algorithm fell through to
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * the traditional binary search because of a
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * bitstring label. Since we dropped the bitstring
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington * support, this should not happen.
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington */
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington INSIST(current == current_root);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington nlabels = dns_name_countlabels(search_name);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington /*
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington * current_root is the root of the current level, so
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington * it's parent is the same as it's "up" pointer.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington up_current = PARENT(current_root);
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_name_init(&hash_name, NULL);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington hashagain:
187604c1adfe841d909d4a8453b6900e652f7f6dBrian Wellington /*
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * Hash includes tail.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_getlabelsequence(name,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews nlabels - tlabels,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hlabels + tlabels,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews &hash_name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hash = dns_name_fullhash(&hash_name, ISC_FALSE);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_getlabelsequence(search_name,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews nlabels - tlabels,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews tlabels, &hash_name);
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington for (hnode = rbt->hashtable[hash % rbt->hashsize];
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson hnode != NULL;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington hnode = hnode->hashnext)
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington {
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews dns_name_t hnode_name;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington if (hash != HASHVAL(hnode))
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington continue;
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews if (find_up(hnode) != up_current)
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews continue;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_name_init(&hnode_name, NULL);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington NODENAME(hnode, &hnode_name);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (dns_name_equal(&hnode_name, &hash_name))
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington break;
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington }
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington if (hnode != NULL) {
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson current = hnode;
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson /*
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson * This is an optimization. If hashing found
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * the right node, the next call to
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * dns_name_fullcompare() would obviously
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * return _equal or _subdomain. Determine
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * which of those would be the case by
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * checking if the full name was hashed. Then
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * make it look like dns_name_fullcompare
50105afc551903541608b11851d73278b23579a3Mark Andrews * was called and jump to the right place.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews if (tlabels == nlabels) {
50105afc551903541608b11851d73278b23579a3Mark Andrews compared = dns_namereln_equal;
50105afc551903541608b11851d73278b23579a3Mark Andrews break;
50105afc551903541608b11851d73278b23579a3Mark Andrews } else {
50105afc551903541608b11851d73278b23579a3Mark Andrews common_labels = tlabels;
50105afc551903541608b11851d73278b23579a3Mark Andrews compared = dns_namereln_subdomain;
50105afc551903541608b11851d73278b23579a3Mark Andrews goto subdomain;
50105afc551903541608b11851d73278b23579a3Mark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews if (tlabels++ < nlabels)
50105afc551903541608b11851d73278b23579a3Mark Andrews goto hashagain;
50105afc551903541608b11851d73278b23579a3Mark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * All of the labels have been tried against the hash
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * table. Since we dropped the support of bitstring
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * labels, the name isn't in the table.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews current = NULL;
50105afc551903541608b11851d73278b23579a3Mark Andrews continue;
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews nohash:
50105afc551903541608b11851d73278b23579a3Mark Andrews#endif /* DNS_RBT_USEHASH */
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * Standard binary search tree movement.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews */
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (order < 0)
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews current = LEFT(current);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews else
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews current = RIGHT(current);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
fcbc5d2353971f65726a9e86c1f37c813f9c2176Mark Andrews } else {
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews /*
fcbc5d2353971f65726a9e86c1f37c813f9c2176Mark Andrews * The names have some common suffix labels.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews *
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * If the number in common are equal in length to
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * the current node's name length, then follow the
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * down pointer and search in the new tree.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews */
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (compared == dns_namereln_subdomain) {
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews#ifdef DNS_RBT_USEHASH
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews subdomain:
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews#endif
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews /*
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews * Whack off the current node's common parts
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews * for the name to search in the next level.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews */
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_name_split(search_name, common_labels,
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews search_name, NULL);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews hlabels += common_labels;
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * This might be the closest enclosing name.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (DATA(current) != NULL ||
50105afc551903541608b11851d73278b23579a3Mark Andrews (options & DNS_RBTFIND_EMPTYDATA) != 0)
50105afc551903541608b11851d73278b23579a3Mark Andrews *node = current;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews /*
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * Point the chain to the next level. This
50105afc551903541608b11851d73278b23579a3Mark Andrews * needs to be done before 'current' is pointed
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews * there because the callback in the next
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews * block of code needs the current 'current',
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews * but in the event the callback requests that
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * the search be stopped then the
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * DNS_R_PARTIALMATCH code at the end of this
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * function needs the chain pointed to the
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * next level.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews ADD_LEVEL(chain, current);
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * The caller may want to interrupt the
50105afc551903541608b11851d73278b23579a3Mark Andrews * downward search when certain special nodes
50105afc551903541608b11851d73278b23579a3Mark Andrews * are traversed. If this is a special node,
50105afc551903541608b11851d73278b23579a3Mark Andrews * the callback is used to learn what the
50105afc551903541608b11851d73278b23579a3Mark Andrews * caller wants to do.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews if (callback != NULL &&
50105afc551903541608b11851d73278b23579a3Mark Andrews FINDCALLBACK(current)) {
50105afc551903541608b11851d73278b23579a3Mark Andrews result = chain_name(chain,
50105afc551903541608b11851d73278b23579a3Mark Andrews callback_name,
50105afc551903541608b11851d73278b23579a3Mark Andrews ISC_FALSE);
50105afc551903541608b11851d73278b23579a3Mark Andrews if (result != ISC_R_SUCCESS) {
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews dns_rbtnodechain_reset(chain);
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews return (result);
50105afc551903541608b11851d73278b23579a3Mark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews result = (callback)(current,
50105afc551903541608b11851d73278b23579a3Mark Andrews callback_name,
50105afc551903541608b11851d73278b23579a3Mark Andrews callback_arg);
50105afc551903541608b11851d73278b23579a3Mark Andrews if (result != DNS_R_CONTINUE) {
50105afc551903541608b11851d73278b23579a3Mark Andrews saved_result = result;
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * Treat this node as if it
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * had no down pointer.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews current = NULL;
50105afc551903541608b11851d73278b23579a3Mark Andrews break;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * Finally, head to the next tree level.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews current = DOWN(current);
50105afc551903541608b11851d73278b23579a3Mark Andrews current_root = current;
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews } else {
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * Though there are labels in common, the
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * entire name at this node is not common
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * with the search name so the search
50105afc551903541608b11851d73278b23579a3Mark Andrews * name does not exist in the tree.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews INSIST(compared == dns_namereln_commonancestor
50105afc551903541608b11851d73278b23579a3Mark Andrews || compared == dns_namereln_contains);
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews current = NULL;
50105afc551903541608b11851d73278b23579a3Mark Andrews }
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews }
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews }
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * If current is not NULL, NOEXACT is not disallowing exact matches,
50105afc551903541608b11851d73278b23579a3Mark Andrews * and either the node has data or an empty node is ok, return
50105afc551903541608b11851d73278b23579a3Mark Andrews * ISC_R_SUCCESS to indicate an exact match.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
50105afc551903541608b11851d73278b23579a3Mark Andrews (DATA(current) != NULL ||
50105afc551903541608b11851d73278b23579a3Mark Andrews (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * Found an exact match.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews chain->end = current;
50105afc551903541608b11851d73278b23579a3Mark Andrews chain->level_matches = chain->level_count;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews if (foundname != NULL)
50105afc551903541608b11851d73278b23579a3Mark Andrews result = chain_name(chain, foundname, ISC_TRUE);
50105afc551903541608b11851d73278b23579a3Mark Andrews else
50105afc551903541608b11851d73278b23579a3Mark Andrews result = ISC_R_SUCCESS;
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews if (result == ISC_R_SUCCESS) {
50105afc551903541608b11851d73278b23579a3Mark Andrews *node = current;
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews result = saved_result;
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews } else
50105afc551903541608b11851d73278b23579a3Mark Andrews *node = NULL;
50105afc551903541608b11851d73278b23579a3Mark Andrews } else {
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
50105afc551903541608b11851d73278b23579a3Mark Andrews * Did not find an exact match (or did not want one).
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews if (*node != NULL) {
50105afc551903541608b11851d73278b23579a3Mark Andrews /*
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * ... but found a partially matching superdomain.
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * Unwind the chain to the partial match node
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * to set level_matches to the level above the node,
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * and then to derive the name.
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews *
50105afc551903541608b11851d73278b23579a3Mark Andrews * chain->level_count is guaranteed to be at least 1
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews * here because by definition of finding a superdomain,
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * the chain is pointed to at least the first subtree.
50105afc551903541608b11851d73278b23579a3Mark Andrews */
50105afc551903541608b11851d73278b23579a3Mark Andrews chain->level_matches = chain->level_count - 1;
50105afc551903541608b11851d73278b23579a3Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews while (chain->levels[chain->level_matches] != *node) {
50105afc551903541608b11851d73278b23579a3Mark Andrews INSIST(chain->level_matches > 0);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews chain->level_matches--;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (foundname != NULL) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews unsigned int saved_count = chain->level_count;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->level_count = chain->level_matches + 1;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = chain_name(chain, foundname,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_FALSE);
50105afc551903541608b11851d73278b23579a3Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->level_count = saved_count;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = ISC_R_SUCCESS;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result == ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = DNS_R_PARTIALMATCH;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews result = ISC_R_NOTFOUND;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (current != NULL) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews /*
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * There was an exact match but either
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * DNS_RBTFIND_NOEXACT was set, or
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * DNS_RBTFIND_EMPTYDATA was set and the node had no
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * data. A policy decision was made to set the
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * chain to the exact match, but this is subject
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * to change if it becomes apparent that something
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * else would be more useful. It is important that
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * this case is handled here, because the predecessor
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * setting code below assumes the match was not exact.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews DATA(current) == NULL));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews chain->end = current;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Ensure the chain points nowhere.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->end = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Since there was no exact match, the chain argument
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * needs to be pointed at the DNSSEC predecessor of
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the search name.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (compared == dns_namereln_subdomain) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * Attempted to follow a down pointer that was
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * NULL, which means the searched for name was
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * a subdomain of a terminal name in the tree.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Since there are no existing subdomains to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * order against, the terminal name is the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * predecessor.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews INSIST(chain->level_count > 0);
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews INSIST(chain->level_matches <
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews chain->level_count);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->end =
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->levels[--chain->level_count];
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result2;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Point current to the node that stopped
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the search.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * With the hashing modification that has been
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * added to the algorithm, the stop node of a
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * standard binary search is not known. So it
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * has to be found. There is probably a more
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * clever way of doing this.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The assignment of current to NULL when
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the relationship is *not* dns_namereln_none,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * even though it later gets set to the same
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * last_compared anyway, is simply to not push
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the while loop in one more level of
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * indentation.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (compared == dns_namereln_none)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews current = last_compared;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews current = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews while (current != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NODENAME(current, &current_name);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews compared = dns_name_fullcompare(
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews search_name,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &current_name,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &order,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &common_labels);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews POST(compared);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews last_compared = current;
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews /*
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * Standard binary search movement.
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews */
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews if (order < 0)
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews current = LEFT(current);
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews else
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater current = RIGHT(current);
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews }
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews current = last_compared;
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews /*
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * Reached a point within a level tree that
cf224bbf7bab87bc28b12f5b30f5ca3f3e5bf604Mark Andrews * positively indicates the name is not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * present, but the stop node could be either
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * less than the desired name (order > 0) or
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * greater than the desired name (order < 0).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * If the stop node is less, it is not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * necessarily the predecessor. If the stop
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * node has a down pointer, then the real
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * predecessor is at the end of a level below
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * (not necessarily the next level).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Move down levels until the rightmost node
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * does not have a down pointer.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * When the stop node is greater, it is
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the successor. All the logic for finding
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the predecessor is handily encapsulated
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in dns_rbtnodechain_prev. In the event
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * that the search name is less than anything
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * else in the tree, the chain is reset.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * XXX DCL What is the best way for the caller
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * to know that the search name has
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * no predecessor?
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (order > 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DOWN(current) != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ADD_LEVEL(chain, current);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result2 =
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews move_chain_to_last(chain,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DOWN(current));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result2 != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = result2;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Ah, the pure and simple
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * case. The stop node is the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * predecessor.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->end = current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
50105afc551903541608b11851d73278b23579a3Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(order < 0);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews chain->end = current;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result2 = dns_rbtnodechain_prev(chain,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NULL,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result2 == ISC_R_SUCCESS ||
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result2 == DNS_R_NEWORIGIN)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ; /* Nothing. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else if (result2 == ISC_R_NOMORE)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * There is no predecessor.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnodechain_reset(chain);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = result2;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews return (result);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews}
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Get the data pointer associated with 'name'.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsisc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *foundname, void **data) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_t *node = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(data != NULL && *data == NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews options, NULL, NULL);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (node != NULL &&
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews *data = DATA(node);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews else
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews result = ISC_R_NOTFOUND;
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews return (result);
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews}
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews/*
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * Delete a name from the tree of trees.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews */
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrewsisc_result_t
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrewsdns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews dns_rbtnode_t *node = NULL;
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews isc_result_t result;
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews REQUIRE(VALID_RBT(rbt));
394f4aec2189750d7f861d00f97fe28ffcd9f659Mark Andrews REQUIRE(dns_name_isabsolute(name));
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews /*
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * First, find the node.
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews *
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews * When searching, the name might not have an exact match:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * elements of a tree, which would make layer 1 a single
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * node tree of "b.a.com" and layer 2 a three node tree of
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * a, b, and c. Deleting a.com would find only a partial depth
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * match in the first layer. Should it be a requirement that
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * that the name to be deleted have data? For now, it is.
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews *
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * ->dirty, ->locknum and ->references are ignored; they are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * solely the province of rbtdb.c.
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews */
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews DNS_RBTFIND_NOOPTIONS, NULL, NULL);
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (result == ISC_R_SUCCESS) {
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews if (DATA(node) != NULL)
c5387e694299c41361660e54f23e89c7da3ede1dMark Andrews result = dns_rbt_deletenode(rbt, node, recurse);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews else
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews result = ISC_R_NOTFOUND;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews } else if (result == DNS_R_PARTIALMATCH)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews result = ISC_R_NOTFOUND;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Remove a node from the tree of trees.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews *
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * a sequence of additions to be deletions will not generally get the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * tree back to the state it started in. For example, if the addition
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * restoring "a.b.c". The RBT *used* to do this kind of rejoining, but it
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * turned out to be a bad idea because it could corrupt an active nodechain
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * that had "b.c" as one of its levels -- and the RBT has no idea what
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews * nodechains are in use by callers, so it can't even *try* to helpfully
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * fix them up (which would probably be doomed to failure anyway).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Similarly, it is possible to leave the tree in a state where a supposedly
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * deleted node still exists. The first case of this is obvious; take
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the tree which has "b.c" on one level, pointing to "a". Now deleted "b.c".
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * It was just established in the previous paragraph why we can't pull "a"
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * back up to its parent level. But what happens when "a" then gets deleted?
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * "b.c" is left hanging around without data or children. This condition
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * is actually pretty easy to detect, but ... should it really be removed?
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Is a chain pointing to it? An iterator? Who knows! (Note that the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * references structure member cannot be looked at because it is private to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * rbtdb.) This is ugly and makes me unhappy, but after hours of trying to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * make it more aesthetically proper and getting nowhere, this is the way it
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * is going to stay until such time as it proves to be a *real* problem.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews * Finally, for reference, note that the original routine that did node
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * joining was called join_nodes(). It has been excised, living now only
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in the CVS history, but comments have been left behind that point to it just
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * in case someone wants to muck with this some more.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The one positive aspect of all of this is that joining used to have a
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * case where it might fail. Without trying to join, now this function always
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsisc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews{
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews dns_rbtnode_t *parent;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(VALID_RBT(rbt));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(rbt->nodecount != 0);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (DOWN(node) != NULL) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (recurse)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews RUNTIME_CHECK(deletetree(rbt, DOWN(node))
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews == ISC_R_SUCCESS);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews else {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (DATA(node) != NULL && rbt->data_deleter != NULL)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->data_deleter(DATA(node), rbt->deleter_arg);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews DATA(node) = NULL;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * Since there is at least one node below this one and
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * no recursion was requested, the deletion is
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * complete. The down node from this node might be all
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * by itself on a single level, so join_nodes() could
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * be used to collapse the tree (with all the caveats
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * of the comment at the start of this function).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews return (ISC_R_SUCCESS);
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Note the node that points to the level of the node that is being
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * deleted. If the deleted node is the top level, parent will be set
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * to NULL.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews */
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews parent = find_up(node);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews /*
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * This node now has no down pointer (either because it didn't
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * have one to start, or because it was recursively removed).
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * So now the node needs to be removed from this level.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews deletefromlevel(node, parent == NULL ? &rbt->root : &DOWN(parent));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DATA(node) != NULL && rbt->data_deleter != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rbt->data_deleter(DATA(node), rbt->deleter_arg);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unhash_node(rbt, node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#if DNS_RBT_USEMAGIC
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews node->magic = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#endif
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_refdestroy(node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews freenode(rbt, &node);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * There are now two special cases that can exist that would
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not have existed if the tree had been created using only
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the names that now exist in it. (This is all related to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * join_nodes() as described in this function's introductory comment.)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Both cases exist when the deleted node's parent (the node
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * that pointed to the deleted node's level) is not null but
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * it has no data: parent != NULL && DATA(parent) == NULL.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The first case is that the deleted node was the last on its level:
50105afc551903541608b11851d73278b23579a3Mark Andrews * DOWN(parent) == NULL. This case can only exist if the parent was
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * previously deleted -- and so now, apparently, the parent should go
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington * away. That can't be done though because there might be external
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * references to it, such as through a nodechain.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews *
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * The other case also involves a parent with no data, but with the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * deleted node being the next-to-last node instead of the last:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * LEFT(DOWN(parent)) == NULL && RIGHT(DOWN(parent)) == NULL.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Presumably now the remaining node on the level should be joined
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater * with the parent, but it's already been described why that can't be
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * done.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews /*
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews * This function never fails.
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_SUCCESS);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsvoid
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsdns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(name != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(name->offsets == NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews NODENAME(node, name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsisc_result_t
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsdns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_t current;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(name != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(name->buffer != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_init(&current, NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_reset(name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews do {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews INSIST(node != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews NODENAME(node, &current);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews result = dns_name_concatenate(name, &current, name, NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (result != ISC_R_SUCCESS)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews break;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews node = find_up(node);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews } while (! dns_name_isabsolute(name));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (result);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewschar *
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsdns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews{
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_fixedname_t fixedname;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_t *name;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_result_t result;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(printname != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_fixedname_init(&fixedname);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews name = dns_fixedname_name(&fixedname);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews result = dns_rbt_fullnamefromnode(node, name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (result == ISC_R_SUCCESS)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_format(name, printname, size);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews else
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews snprintf(printname, size, "<error building name: %s>",
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_result_totext(result));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (printname);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsstatic isc_result_t
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewscreate_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t *node;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_region_t region;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned int labels;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews size_t nodelen;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews REQUIRE(name->offsets != NULL);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_toregion(name, &region);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews labels = dns_name_countlabels(name);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews ENSURE(labels > 0);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Allocate space for the node structure, the name, and the offsets.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews nodelen = sizeof(dns_rbtnode_t) + region.length + labels + 1;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington node = (dns_rbtnode_t *)isc_mem_get(mctx, nodelen);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (node == NULL)
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington return (ISC_R_NOMEMORY);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington memset(node, 0, nodelen);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->is_root = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews PARENT(node) = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington RIGHT(node) = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LEFT(node) = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington DOWN(node) = NULL;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews DATA(node) = NULL;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington node->is_mmapped = 0;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->down_is_relative = 0;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->left_is_relative = 0;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->right_is_relative = 0;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->parent_is_relative = 0;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington node->data_is_relative = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington#ifdef DNS_RBT_USEHASH
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington HASHNEXT(node) = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington HASHVAL(node) = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington#endif
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ISC_LINK_INIT(node, deadlink);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews LOCKNUM(node) = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington WILD(node) = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington DIRTY(node) = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_rbtnode_refinit(node, 0);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington node->find_callback = 0;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington node->nsec = DNS_RBT_NSEC_NORMAL;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews MAKE_BLACK(node);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington /*
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * The following is stored to make reconstructing a name from the
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * stored value in the node easy: the length of the name, the number
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * of labels, whether the name is absolute or not, the name itself,
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * and the name's offsets table.
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington *
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * XXX RTH
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * The offsets table could be made smaller by eliminating the
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * first offset, which is always 0. This requires changes to
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington * lib/dns/name.c.
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington *
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington * as it uses OLDNAMELEN.
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington */
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington OLDNAMELEN(node) = NAMELEN(node) = region.length;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews OLDOFFSETLEN(node) = OFFSETLEN(node) = labels;
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews ATTRS(node) = name->attributes;
cc3aafe737334d444781f8a34ffaf459e075bb9aMark Andrews
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington memcpy(NAME(node), region.base, region.length);
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington memcpy(OFFSETS(node), name->offsets, labels);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington#if DNS_RBT_USEMAGIC
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington node->magic = DNS_RBTNODE_MAGIC;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews#endif
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington *nodep = node;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington return (ISC_R_SUCCESS);
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington}
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington#ifdef DNS_RBT_USEHASH
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellingtonstatic inline void
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewshash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews unsigned int hash;
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington REQUIRE(name != NULL);
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews hash = HASHVAL(node) % rbt->hashsize;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews HASHNEXT(node) = rbt->hashtable[hash];
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington rbt->hashtable[hash] = node;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington}
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic isc_result_t
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellingtoninithash(dns_rbt_t *rbt) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington unsigned int bytes;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington rbt->hashsize = RBT_HASH_SIZE;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (rbt->hashtable == NULL)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return (ISC_R_NOMEMORY);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews memset(rbt->hashtable, 0, bytes);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return (ISC_R_SUCCESS);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsstatic void
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsrehash(dns_rbt_t *rbt) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned int oldsize;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t **oldtable;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_rbtnode_t *node;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned int hash;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned int i;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews oldsize = rbt->hashsize;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews oldtable = rbt->hashtable;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashsize = rbt->hashsize * 2 + 1;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashtable = isc_mem_get(rbt->mctx,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashsize * sizeof(dns_rbtnode_t *));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (rbt->hashtable == NULL) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashtable = oldtable;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashsize = oldsize;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews return;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews INSIST(rbt->hashsize > 0);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews for (i = 0; i < rbt->hashsize; i++)
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rbt->hashtable[i] = NULL;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews for (i = 0; i < oldsize; i++) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews node = oldtable[i];
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews while (node != NULL) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hash = HASHVAL(node) % rbt->hashsize;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews oldtable[i] = HASHNEXT(node);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews HASHNEXT(node) = rbt->hashtable[hash];
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews rbt->hashtable[hash] = node;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson node = oldtable[i];
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington }
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews}
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstatic inline void
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrewshash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington REQUIRE(DNS_RBTNODE_VALID(node));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (rbt->nodecount >= (rbt->hashsize *3))
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rehash(rbt);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews hash_add_node(rbt, node, name);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsstatic inline void
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsunhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews unsigned int bucket;
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews dns_rbtnode_t *bucket_node;
f1263d2aa405087e74caf001cd443079f50ee903Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews if (rbt->hashtable != NULL) {
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews bucket = HASHVAL(node) % rbt->hashsize;
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews bucket_node = rbt->hashtable[bucket];
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (bucket_node == node)
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews rbt->hashtable[bucket] = HASHNEXT(node);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews else {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews while (HASHNEXT(bucket_node) != node) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews INSIST(HASHNEXT(bucket_node) != NULL);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews bucket_node = HASHNEXT(bucket_node);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews HASHNEXT(bucket_node) = HASHNEXT(node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews}
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews#endif /* DNS_RBT_USEHASH */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstatic inline void
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsrotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbtnode_t *child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(rootp != NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews child = RIGHT(node);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews INSIST(child != NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews RIGHT(node) = LEFT(child);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (LEFT(child) != NULL)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews PARENT(LEFT(child)) = node;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(child) = node;
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (child != NULL)
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews PARENT(child) = PARENT(node);
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (IS_ROOT(node)) {
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews *rootp = child;
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews child->is_root = 1;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews node->is_root = 0;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (LEFT(PARENT(node)) == node)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(PARENT(node)) = child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews else
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews RIGHT(PARENT(node)) = child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(node) = child;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews}
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsstatic inline void
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsrotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_rbtnode_t *child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(DNS_RBTNODE_VALID(node));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews REQUIRE(rootp != NULL);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews child = LEFT(node);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews INSIST(child != NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(node) = RIGHT(child);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (RIGHT(child) != NULL)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(RIGHT(child)) = node;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews RIGHT(child) = node;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (child != NULL)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(child) = PARENT(node);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (IS_ROOT(node)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews *rootp = child;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews child->is_root = 1;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node->is_root = 0;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (LEFT(PARENT(node)) == node)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(PARENT(node)) = child;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews else
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews RIGHT(PARENT(node)) = child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews PARENT(node) = child;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews/*
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * This is the real workhorse of the insertion code, because it does the
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * true red/black tree on a single level.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updaterstatic void
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsaddonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_rbtnode_t **rootp)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews{
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_rbtnode_t *child, *root, *parent, *grandparent;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews dns_name_t add_name, current_name;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_offsets_t add_offsets, current_offsets;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews REQUIRE(rootp != NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews RIGHT(node) == NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews REQUIRE(current != NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews root = *rootp;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (root == NULL) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * First node of a level.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node->is_root = 1;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(node) = current;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews *rootp = node;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews return;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews child = root;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews POST(child);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_init(&add_name, add_offsets);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews NODENAME(node, &add_name);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_name_init(&current_name, current_offsets);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews NODENAME(current, &current_name);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (order < 0) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews INSIST(LEFT(current) == NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(current) = node;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews INSIST(RIGHT(current) == NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews RIGHT(current) = node;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews INSIST(PARENT(node) == NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(node) = current;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews MAKE_RED(node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews while (node != root && IS_RED(PARENT(node))) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * XXXDCL could do away with separate parent and grandparent
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * variables. They are vestiges of the days before parent
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * pointers. However, they make the code a little clearer.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews parent = PARENT(node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews grandparent = PARENT(parent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (parent == LEFT(grandparent)) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews child = RIGHT(grandparent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (child != NULL && IS_RED(child)) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews MAKE_BLACK(parent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews MAKE_BLACK(child);
676619a22fbc760875adb00b58aaef6a22ced18aMark Andrews MAKE_RED(grandparent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node = grandparent;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews } else {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (node == RIGHT(parent)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews rotate_left(parent, &root);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node = parent;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews parent = PARENT(node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews grandparent = PARENT(parent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(parent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_RED(grandparent);
676619a22fbc760875adb00b58aaef6a22ced18aMark Andrews rotate_right(grandparent, &root);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews } else {
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews child = LEFT(grandparent);
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews if (child != NULL && IS_RED(child)) {
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews MAKE_BLACK(parent);
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews MAKE_BLACK(child);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_RED(grandparent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node = grandparent;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (node == LEFT(parent)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews rotate_right(parent, &root);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews node = parent;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews parent = PARENT(node);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews grandparent = PARENT(parent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews MAKE_BLACK(parent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews MAKE_RED(grandparent);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews rotate_left(grandparent, &root);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(root);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews ENSURE(IS_ROOT(root));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews *rootp = root;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews}
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews/*
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * This is the real workhorse of the deletion code, because it does the
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * true red/black tree on a single level.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsstatic void
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrewsdeletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbtnode_t *child, *sibling, *parent;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbtnode_t *successor;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews REQUIRE(delete != NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * Verify that the parent history is (apparently) correct.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews INSIST((IS_ROOT(delete) && *rootp == delete) ||
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews (! IS_ROOT(delete) &&
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews (LEFT(PARENT(delete)) == delete ||
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews RIGHT(PARENT(delete)) == delete)));
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews child = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (LEFT(delete) == NULL) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews if (RIGHT(delete) == NULL) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (IS_ROOT(delete)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * This is the only item in the tree.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews *rootp = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews return;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews }
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews } else
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * This node has one child, on the right.
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews child = RIGHT(delete);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews } else if (RIGHT(delete) == NULL)
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * This node has one child, on the left.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews child = LEFT(delete);
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews else {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews dns_rbtnode_t holder, *tmp = &holder;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /*
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * This node has two children, so it cannot be directly
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews * deleted. Find its immediate in-order successor and
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * move it to this location, then do the deletion at the
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * old site of the successor.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews successor = RIGHT(delete);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews while (LEFT(successor) != NULL)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews successor = LEFT(successor);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * The successor cannot possibly have a left child;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * if there is any child, it is on the right.
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews */
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (RIGHT(successor) != NULL)
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews child = RIGHT(successor);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews /*
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * Swap the two nodes; it would be simpler to just replace
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * the value being deleted with that of the successor,
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * but this rigamarole is done so the caller has complete
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * control over the pointers (and memory allocation) of
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * all of nodes. If just the key value were removed from
e4d304b70b81ca9956c2eff7c24aacf4dd00266eEvan Hunt * the tree, the pointer to the node would be unchanged.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews */
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * First, put the successor in the tree location of the
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * node to be deleted. Save its existing tree pointer
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * information, which will be needed when linking up
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * delete to the successor's old location.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews memcpy(tmp, successor, sizeof(dns_rbtnode_t));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (IS_ROOT(delete)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews *rootp = successor;
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews successor->is_root = ISC_TRUE;
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews delete->is_root = ISC_FALSE;
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews } else
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews if (LEFT(PARENT(delete)) == delete)
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews LEFT(PARENT(delete)) = successor;
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews else
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews RIGHT(PARENT(delete)) = successor;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
8bedd9647f4d6894e12a8c94d3ccc624dddcee50Mark Andrews PARENT(successor) = PARENT(delete);
2f012d936b5ccdf6520c96a4de23721dc58a2221Automatic Updater LEFT(successor) = LEFT(delete);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews RIGHT(successor) = RIGHT(delete);
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews COLOR(successor) = COLOR(delete);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews if (LEFT(successor) != NULL)
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews PARENT(LEFT(successor)) = successor;
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews if (RIGHT(successor) != successor)
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews PARENT(RIGHT(successor)) = successor;
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews
0ad024cc4272894e877e3a7896f80a2892bc703cMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * Now relink the node to be deleted into the
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * successor's previous tree location. PARENT(tmp)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * is the successor's original parent.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews INSIST(! IS_ROOT(delete));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (PARENT(tmp) == delete) {
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews /*
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * Node being deleted was successor's parent.
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews RIGHT(successor) = delete;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(delete) = successor;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 LEFT(PARENT(tmp)) = delete;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson PARENT(delete) = PARENT(tmp);
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews }
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews /*
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * Original location of successor node has no left.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews */
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews LEFT(delete) = NULL;
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews RIGHT(delete) = RIGHT(tmp);
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews COLOR(delete) = COLOR(tmp);
676619a22fbc760875adb00b58aaef6a22ced18aMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews * Remove the node by removing the links from its parent.
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews */
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews if (! IS_ROOT(delete)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (LEFT(PARENT(delete)) == delete)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews LEFT(PARENT(delete)) = child;
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews else
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews RIGHT(PARENT(delete)) = child;
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (child != NULL)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(child) = PARENT(delete);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * This is the root being deleted, and at this point
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * it is known to have just one child.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
676619a22fbc760875adb00b58aaef6a22ced18aMark Andrews *rootp = child;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews child->is_root = 1;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews PARENT(child) = PARENT(delete);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington /*
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * Fix color violations.
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington */
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 if (IS_BLACK(delete)) {
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington parent = PARENT(delete);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson while (child != *rootp && IS_BLACK(child)) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews INSIST(child == NULL || ! IS_ROOT(child));
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (LEFT(parent) == child) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews sibling = RIGHT(parent);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 if (IS_RED(sibling)) {
e407562a75eb93073bb72089cced150d7ffe4d4fTatuya JINMEI 神明達哉 MAKE_BLACK(sibling);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington MAKE_RED(parent);
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson rotate_left(parent, rootp);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson sibling = RIGHT(parent);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson INSIST(sibling != NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (IS_BLACK(LEFT(sibling)) &&
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews IS_BLACK(RIGHT(sibling))) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews MAKE_RED(sibling);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews child = parent;
9840a0767d02f6c6b9d1f73d54e0cab2e8192a93Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews if (IS_BLACK(RIGHT(sibling))) {
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews MAKE_BLACK(LEFT(sibling));
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews MAKE_RED(sibling);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews rotate_right(sibling, rootp);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews sibling = RIGHT(parent);
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews }
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews
1ea2595e1b33cc63ea73ee1d54b580b717d7d155Mark Andrews COLOR(sibling) = COLOR(parent);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews MAKE_BLACK(parent);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(RIGHT(sibling) != NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews MAKE_BLACK(RIGHT(sibling));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rotate_left(parent, rootp);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews child = *rootp;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington /*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Child is parent's right child.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Everything is done the same as above,
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews * except mirrored.
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews */
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews sibling = LEFT(parent);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews if (IS_RED(sibling)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(sibling);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_RED(parent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews rotate_right(parent, rootp);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews sibling = LEFT(parent);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(sibling != NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (IS_BLACK(LEFT(sibling)) &&
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews IS_BLACK(RIGHT(sibling))) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews MAKE_RED(sibling);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews child = parent;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
c941e32d221fbb0cb760e3bc24c7f221c0cf8b97Mark Andrews } else {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews if (IS_BLACK(LEFT(sibling))) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(RIGHT(sibling));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_RED(sibling);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews rotate_left(sibling, rootp);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews sibling = LEFT(parent);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews }
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews COLOR(sibling) = COLOR(parent);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews MAKE_BLACK(parent);
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews INSIST(LEFT(sibling) != NULL);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews MAKE_BLACK(LEFT(sibling));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews rotate_right(parent, rootp);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews child = *rootp;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews parent = PARENT(child);
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews }
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington if (IS_RED(child))
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews MAKE_BLACK(child);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/*
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * This should only be used on the root of a tree, because no color fixup
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * is done at all.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * NOTE: No root pointer maintenance is done, because the function is only
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * used for two cases:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * + deleting everything DOWN from a node that is itself being deleted, and
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * + deleting the entire tree of trees from dns_rbt_destroy.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * In each case, the root pointer is no longer relevant, so there
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * is no need for a root parameter to this function.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews * If the function is ever intended to be used to delete something where
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * a pointer needs to be told that this tree no longer exists,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * this function would need to adjusted accordingly.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdeletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result = ISC_R_SUCCESS;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews REQUIRE(VALID_RBT(rbt));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (node == NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (LEFT(node) != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = deletetree(rbt, LEFT(node));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto done;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews LEFT(node) = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (RIGHT(node) != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = deletetree(rbt, RIGHT(node));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto done;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington RIGHT(node) = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DOWN(node) != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = deletetree(rbt, DOWN(node));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto done;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington DOWN(node) = NULL;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington done:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington return (result);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DATA(node) != NULL && rbt->data_deleter != NULL)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington rbt->data_deleter(DATA(node), rbt->deleter_arg);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington unhash_node(rbt, node);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#if DNS_RBT_USEMAGIC
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington node->magic = 0;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#endif
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington freenode(rbt, &node);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington return (result);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews}
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsstatic void
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrewsfreenode(dns_rbt_t *rbt, dns_rbtnode_t **nodep) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_rbtnode_t *node = *nodep;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (node->is_mmapped == 0) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews *nodep = NULL;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews rbt->nodecount--;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews}
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsstatic void
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrewsdeletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_rbtnode_t *parent;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews dns_rbtnode_t *node = *nodep;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews REQUIRE(VALID_RBT(rbt));
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews again:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (node == NULL) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews *nodep = NULL;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews return;
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews }
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews traverse:
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews if (LEFT(node) != NULL) {
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews node = LEFT(node);
60ab03125c137c48a6b2ed6df1d2c8657757e09dMark Andrews goto traverse;
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington }
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington if (DOWN(node) != NULL) {
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington node = DOWN(node);
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington goto traverse;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (DATA(node) != NULL && rbt->data_deleter != NULL)
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington rbt->data_deleter(DATA(node), rbt->deleter_arg);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff
115635379a2baf2100695018109ad39e0dac349dAndreas Gustafsson /*
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * Note: we don't call unhash_node() here as we are destroying
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * the complete rbt tree.
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington */
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington#if DNS_RBT_USEMAGIC
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington node->magic = 0;
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington#endif
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews parent = PARENT(node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (RIGHT(node) != NULL)
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews PARENT(RIGHT(node)) = parent;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (parent != NULL) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (LEFT(parent) == node)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley LEFT(parent) = RIGHT(node);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley else if (DOWN(parent) == node)
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews DOWN(parent) = RIGHT(node);
d2ef84e07b67e72a4bd9c729c6b8228067d17584Mark Andrews } else
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews parent = RIGHT(node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews freenode(rbt, &node);
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
60783293cc27f74a84ec93c95c5d46edd30bd8e0Brian Wellington node = parent;
60783293cc27f74a84ec93c95c5d46edd30bd8e0Brian Wellington if (quantum != 0 && --quantum == 0) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley *nodep = node;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley return;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley goto again;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson}
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_rbt_indent(int depth) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int i;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington printf("%4d ", depth);
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington for (i = 0; i < depth; i++)
60783293cc27f74a84ec93c95c5d46edd30bd8e0Brian Wellington printf("- ");
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson}
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsvoid
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrewsdns_rbt_printnodeinfo(dns_rbtnode_t *n) {
60783293cc27f74a84ec93c95c5d46edd30bd8e0Brian Wellington printf("Node info for nodename: ");
60783293cc27f74a84ec93c95c5d46edd30bd8e0Brian Wellington printnodename(n);
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington printf("\n");
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington printf("n = %p\n", n);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson printf("Relative pointers: %s%s%s%s%s\n",
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington (n->parent_is_relative == 1 ? " P" : ""),
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (n->right_is_relative == 1 ? " R" : ""),
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson (n->left_is_relative == 1 ? " L" : ""),
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington (n->down_is_relative == 1 ? " D" : ""),
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence (n->data_is_relative == 1 ? " T" : ""));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
664e11f0b14c78cef7cf6b8c70323a1da494e351Mark Andrews printf("node lock address = %d\n", n->locknum);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington printf("Parent: %p\n", n->parent);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington printf("Right: %p\n", n->right);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley printf("Left: %p\n", n->left);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley printf("Down: %p\n", n->down);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley printf("daTa: %p\n", n->data);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson}
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic void
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsprintnodename(dns_rbtnode_t *node) {
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews isc_region_t r;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_name_t name;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews char buffer[DNS_NAME_FORMATSIZE];
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews dns_offsets_t offsets;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington r.length = NAMELEN(node);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence r.base = NAME(node);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence dns_name_init(&name, offsets);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington dns_name_fromregion(&name, &r);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_name_format(&name, buffer, sizeof(buffer));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews printf("\"%s\"", buffer);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleystatic void
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halleydns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int depth, const char *direction,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews void (*data_printer)(FILE *, void *))
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley{
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_rbt_indent(depth);
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington if (root != NULL) {
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley printnodename(root);
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley printf(" (%s, %s", direction, IS_RED(root) ? "RED" : "BLACK");
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley if ((! IS_ROOT(root) && PARENT(root) != parent) ||
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley ( IS_ROOT(root) && depth > 0 &&
e419f613d8591885df608cb73065921be07dd12eBob Halley DOWN(PARENT(root)) != root)) {
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley printf(" (BAD parent pointer! -> ");
e419f613d8591885df608cb73065921be07dd12eBob Halley if (PARENT(root) != NULL)
e419f613d8591885df608cb73065921be07dd12eBob Halley printnodename(PARENT(root));
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington else
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington printf("NULL");
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington printf(")");
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley }
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley printf(")");
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley if (root->data != NULL && data_printer != NULL) {
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson printf(" data@%p: ", root->data);
e419f613d8591885df608cb73065921be07dd12eBob Halley data_printer(stdout, root->data);
e419f613d8591885df608cb73065921be07dd12eBob Halley }
62a84c4a27033bb0e7316256964a6950b1e230bdAndreas Gustafsson printf("\n");
ef97e09e20da2133adc731cf7e29e72d04dfc93fAndreas Gustafsson
e419f613d8591885df608cb73065921be07dd12eBob Halley depth++;
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington if (IS_RED(root) && IS_RED(LEFT(root)))
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington printf("** Red/Red color violation on left\n");
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson dns_rbt_printtree(LEFT(root), root, depth, "left",
e419f613d8591885df608cb73065921be07dd12eBob Halley data_printer);
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley if (IS_RED(root) && IS_RED(RIGHT(root)))
e419f613d8591885df608cb73065921be07dd12eBob Halley printf("** Red/Red color violation on right\n");
e419f613d8591885df608cb73065921be07dd12eBob Halley dns_rbt_printtree(RIGHT(root), root, depth, "right",
e419f613d8591885df608cb73065921be07dd12eBob Halley data_printer);
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley dns_rbt_printtree(DOWN(root), NULL, depth, "down",
ec371edc34e2adb9e337b774d1a6e613f5863655Brian Wellington data_printer);
e419f613d8591885df608cb73065921be07dd12eBob Halley } else {
e419f613d8591885df608cb73065921be07dd12eBob Halley printf("NULL (%s)\n", direction);
e419f613d8591885df608cb73065921be07dd12eBob Halley }
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halleyvoid
e419f613d8591885df608cb73065921be07dd12eBob Halleydns_rbt_printall(dns_rbt_t *rbt, void (*data_printer)(FILE *, void *)) {
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley REQUIRE(VALID_RBT(rbt));
e419f613d8591885df608cb73065921be07dd12eBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_rbt_printtree(rbt->root, NULL, 0, "root", data_printer);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington/*
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * Chain Functions
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington
fe5ba8ddb55b2b3ee139e13b7891817117ad4e63Brian Wellingtonvoid
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellingtondns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington REQUIRE(chain != NULL);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington /*
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington * Initialize 'chain'.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews chain->mctx = mctx;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington chain->end = NULL;
6fac7ff1f9ec9c3873d3b55c5079fa79aba1f146Mark Andrews chain->level_count = 0;
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews chain->level_matches = 0;
8d414d155953f89a4eff40f16878438a8c9228f3Mark Andrews memset(chain->levels, 0, sizeof(chain->levels));
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington chain->magic = CHAIN_MAGIC;
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews}
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington
e419f613d8591885df608cb73065921be07dd12eBob Halleyisc_result_t
e419f613d8591885df608cb73065921be07dd12eBob Halleydns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews dns_name_t *origin, dns_rbtnode_t **node)
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews{
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley isc_result_t result = ISC_R_SUCCESS;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley REQUIRE(VALID_CHAIN(chain));
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley if (node != NULL)
e419f613d8591885df608cb73065921be07dd12eBob Halley *node = chain->end;
e419f613d8591885df608cb73065921be07dd12eBob Halley
470c726bc894b1c528cb84e7e1f7e44770ffc485Mark Andrews if (chain->end == NULL)
e419f613d8591885df608cb73065921be07dd12eBob Halley return (ISC_R_NOTFOUND);
e419f613d8591885df608cb73065921be07dd12eBob Halley
ef97e09e20da2133adc731cf7e29e72d04dfc93fAndreas Gustafsson if (name != NULL) {
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson NODENAME(chain->end, name);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
e419f613d8591885df608cb73065921be07dd12eBob Halley if (chain->level_count == 0) {
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley /*
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * Names in the top level tree are all absolute.
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews * Always make 'name' relative.
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews */
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews INSIST(dns_name_isabsolute(name));
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews /*
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews * This is cheaper than dns_name_getlabelsequence().
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews */
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews name->labels--;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews name->length--;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews }
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews }
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews if (origin != NULL) {
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews if (chain->level_count > 0)
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley result = chain_name(chain, origin, ISC_FALSE);
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley else
e419f613d8591885df608cb73065921be07dd12eBob Halley result = dns_name_copy(dns_rootname, origin, NULL);
e419f613d8591885df608cb73065921be07dd12eBob Halley }
e419f613d8591885df608cb73065921be07dd12eBob Halley
264fd373f3f6cc7f271bdff14a020385620015f1Andreas Gustafsson return (result);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson}
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington
e419f613d8591885df608cb73065921be07dd12eBob Halleyisc_result_t
264fd373f3f6cc7f271bdff14a020385620015f1Andreas Gustafssondns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
264fd373f3f6cc7f271bdff14a020385620015f1Andreas Gustafsson dns_name_t *origin)
264fd373f3f6cc7f271bdff14a020385620015f1Andreas Gustafsson{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_t *current, *previous, *predecessor;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result = ISC_R_SUCCESS;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews isc_boolean_t new_origin = ISC_FALSE;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews predecessor = NULL;
305227476756aecb11cebbc811dba88a2d147b34Mark Andrews
e2c3f8059e77a8e11c4378d22e5d8e78b423a28fMark Andrews current = chain->end;
e419f613d8591885df608cb73065921be07dd12eBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley if (LEFT(current) != NULL) {
e419f613d8591885df608cb73065921be07dd12eBob Halley /*
e419f613d8591885df608cb73065921be07dd12eBob Halley * Moving left one then right as far as possible is the
e419f613d8591885df608cb73065921be07dd12eBob Halley * previous node, at least for this level.
e419f613d8591885df608cb73065921be07dd12eBob Halley */
1872808932603066d401d3de97db11af8ffee78aAndreas Gustafsson current = LEFT(current);
e419f613d8591885df608cb73065921be07dd12eBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley while (RIGHT(current) != NULL)
e419f613d8591885df608cb73065921be07dd12eBob Halley current = RIGHT(current);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
e419f613d8591885df608cb73065921be07dd12eBob Halley predecessor = current;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley } else {
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington /*
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington * No left links, so move toward the root. If at any point on
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * the way there the link from parent to child is a right
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * link, then the parent is the previous node, at least
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * for this level.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews while (! IS_ROOT(current)) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews previous = current;
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews current = PARENT(current);
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews if (RIGHT(current) == previous) {
7d116211ec7b063891130f191e3ed437b45dba70Mark Andrews predecessor = current;
1872808932603066d401d3de97db11af8ffee78aAndreas Gustafsson break;
fe5ba8ddb55b2b3ee139e13b7891817117ad4e63Brian Wellington }
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson }
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington }
ef97e09e20da2133adc731cf7e29e72d04dfc93fAndreas Gustafsson
1872808932603066d401d3de97db11af8ffee78aAndreas Gustafsson if (predecessor != NULL) {
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson /*
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * Found a predecessor node in this level. It might not
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * really be the predecessor, however.
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley */
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley if (DOWN(predecessor) != NULL) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * The predecessor is really down at least one level.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Go down and as far right as possible, and repeat
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * as long as the rightmost node has a down pointer.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley do {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * XXX DCL Need to do something about origins
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * here. See whether to go down, and if so
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * whether it is truly what Bob calls a
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson * new origin.
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ADD_LEVEL(chain, predecessor);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley predecessor = DOWN(predecessor);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /* XXX DCL duplicated from above; clever
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * way to unduplicate? */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley while (RIGHT(predecessor) != NULL)
e419f613d8591885df608cb73065921be07dd12eBob Halley predecessor = RIGHT(predecessor);
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley } while (DOWN(predecessor) != NULL);
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson /* XXX DCL probably needs work on the concept */
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson if (origin != NULL)
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington new_origin = ISC_TRUE;
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson }
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews } else if (chain->level_count > 0) {
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews /*
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson * Dang, didn't find a predecessor in this level.
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson * Got to the root of this level without having traversed
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson * any right links. Ascend the tree one level; the
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews * node that points to this tree is the predecessor.
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews INSIST(chain->level_count > 0 && IS_ROOT(current));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington predecessor = chain->levels[--chain->level_count];
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington /* XXX DCL probably needs work on the concept */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence /*
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson * Don't declare an origin change when the new origin is "."
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington * at the top level tree, because "." is declared as the origin
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington * for the second level tree.
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson */
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (origin != NULL &&
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson new_origin = ISC_TRUE;
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson }
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews
5be3685b0e57677c0cc03113099cb8f99f9a070bMark Andrews if (predecessor != NULL) {
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson chain->end = predecessor;
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson if (new_origin) {
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson result = dns_rbtnodechain_current(chain, name, origin,
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington NULL);
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington if (result == ISC_R_SUCCESS)
5b0413f993b1c1ed837d23641e9f696cda1ee293Brian Wellington result = DNS_R_NEWORIGIN;
5b0413f993b1c1ed837d23641e9f696cda1ee293Brian Wellington
5b0413f993b1c1ed837d23641e9f696cda1ee293Brian Wellington } else
5b0413f993b1c1ed837d23641e9f696cda1ee293Brian Wellington result = dns_rbtnodechain_current(chain, name, NULL,
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson NULL);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson } else
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson result = ISC_R_NOMORE;
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsisc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsdns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *origin)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rbtnode_t *current, *successor;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result = ISC_R_SUCCESS;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t new_origin = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews successor = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
current = chain->end;
if (DOWN(current) != NULL) {
/*
* Don't declare an origin change when the new origin is "."
* at the second level tree, because "." is already declared
* as the origin for the top level tree.
*/
if (chain->level_count > 0 ||
OFFSETLEN(current) > 1)
new_origin = ISC_TRUE;
ADD_LEVEL(chain, current);
current = DOWN(current);
while (LEFT(current) != NULL)
current = LEFT(current);
successor = current;
}
if (successor != NULL) {
chain->end = successor;
/*
* It is not necessary to use dns_rbtnodechain_current like
* the other functions because this function will never
* find a node in the topmost level. This is because the
* root level will never be more than one name, and everything
* in the megatree is a successor to that node, down at
* the second level or below.
*/
if (name != NULL)
NODENAME(chain->end, name);
if (new_origin) {
if (origin != NULL)
result = chain_name(chain, origin, ISC_FALSE);
if (result == ISC_R_SUCCESS)
result = DNS_R_NEWORIGIN;
} else
result = ISC_R_SUCCESS;
} else
result = ISC_R_NOMORE;
return (result);
}
isc_result_t
dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
dns_rbtnode_t *current, *previous, *successor;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
successor = NULL;
current = chain->end;
if (RIGHT(current) == NULL) {
while (! IS_ROOT(current)) {
previous = current;
current = PARENT(current);
if (LEFT(current) == previous) {
successor = current;
break;
}
}
} else {
current = RIGHT(current);
while (LEFT(current) != NULL)
current = LEFT(current);
successor = current;
}
if (successor != NULL) {
chain->end = successor;
if (name != NULL)
NODENAME(chain->end, name);
result = ISC_R_SUCCESS;
} else
result = ISC_R_NOMORE;
return (result);
}
isc_result_t
dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
dns_name_t *origin)
{
dns_rbtnode_t *current, *previous, *successor;
isc_result_t result = ISC_R_SUCCESS;
isc_boolean_t new_origin = ISC_FALSE;
REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
successor = NULL;
current = chain->end;
/*
* If there is a level below this node, the next node is the leftmost
* node of the next level.
*/
if (DOWN(current) != NULL) {
/*
* Don't declare an origin change when the new origin is "."
* at the second level tree, because "." is already declared
* as the origin for the top level tree.
*/
if (chain->level_count > 0 ||
OFFSETLEN(current) > 1)
new_origin = ISC_TRUE;
ADD_LEVEL(chain, current);
current = DOWN(current);
while (LEFT(current) != NULL)
current = LEFT(current);
successor = current;
} else if (RIGHT(current) == NULL) {
/*
* The successor is up, either in this level or a previous one.
* Head back toward the root of the tree, looking for any path
* that was via a left link; the successor is the node that has
* that left link. In the event the root of the level is
* reached without having traversed any left links, ascend one
* level and look for either a right link off the point of
* ascent, or search for a left link upward again, repeating
* ascends until either case is true.
*/
do {
while (! IS_ROOT(current)) {
previous = current;
current = PARENT(current);
if (LEFT(current) == previous) {
successor = current;
break;
}
}
if (successor == NULL) {
/*
* Reached the root without having traversed
* any left pointers, so this level is done.
*/
if (chain->level_count == 0)
break;
current = chain->levels[--chain->level_count];
new_origin = ISC_TRUE;
if (RIGHT(current) != NULL)
break;
}
} while (successor == NULL);
}
if (successor == NULL && RIGHT(current) != NULL) {
current = RIGHT(current);
while (LEFT(current) != NULL)
current = LEFT(current);
successor = current;
}
if (successor != NULL) {
chain->end = successor;
/*
* It is not necessary to use dns_rbtnodechain_current like
* the other functions because this function will never
* find a node in the topmost level. This is because the
* root level will never be more than one name, and everything
* in the megatree is a successor to that node, down at
* the second level or below.
*/
if (name != NULL)
NODENAME(chain->end, name);
if (new_origin) {
if (origin != NULL)
result = chain_name(chain, origin, ISC_FALSE);
if (result == ISC_R_SUCCESS)
result = DNS_R_NEWORIGIN;
} else
result = ISC_R_SUCCESS;
} else
result = ISC_R_NOMORE;
return (result);
}
isc_result_t
dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
dns_name_t *name, dns_name_t *origin)
{
isc_result_t result;
REQUIRE(VALID_RBT(rbt));
REQUIRE(VALID_CHAIN(chain));
dns_rbtnodechain_reset(chain);
chain->end = rbt->root;
result = dns_rbtnodechain_current(chain, name, origin, NULL);
if (result == ISC_R_SUCCESS)
result = DNS_R_NEWORIGIN;
return (result);
}
isc_result_t
dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
dns_name_t *name, dns_name_t *origin)
{
isc_result_t result;
REQUIRE(VALID_RBT(rbt));
REQUIRE(VALID_CHAIN(chain));
dns_rbtnodechain_reset(chain);
result = move_chain_to_last(chain, rbt->root);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_rbtnodechain_current(chain, name, origin, NULL);
if (result == ISC_R_SUCCESS)
result = DNS_R_NEWORIGIN;
return (result);
}
void
dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
REQUIRE(VALID_CHAIN(chain));
/*
* Free any dynamic storage associated with 'chain', and then
* reinitialize 'chain'.
*/
chain->end = NULL;
chain->level_count = 0;
chain->level_matches = 0;
}
void
dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
/*
* Free any dynamic storage associated with 'chain', and then
* invalidate 'chain'.
*/
dns_rbtnodechain_reset(chain);
chain->magic = 0;
}