mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-15 22:09:31 -04:00
Support for bitstring labels.
This commit is contained in:
parent
605ae28c5a
commit
93b01c7295
1 changed files with 147 additions and 148 deletions
295
lib/dns/rbt.c
295
lib/dns/rbt.c
|
|
@ -15,7 +15,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbt.c,v 1.47 1999/04/22 14:36:30 tale Exp $ */
|
||||
/* $Id: rbt.c,v 1.48 1999/04/23 04:59:41 tale Exp $ */
|
||||
|
||||
/* Principal Authors: DCL */
|
||||
|
||||
|
|
@ -351,14 +351,13 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
* Does this thing have too many variables or what?
|
||||
*/
|
||||
dns_rbtnode_t **root, *parent, *child, *current, *new_current;
|
||||
dns_name_t add_name, current_name, new_name, tmp_name;
|
||||
dns_offsets_t add_offsets, current_offsets, new_offsets, tmp_offsets;
|
||||
dns_name_t *add_name, current_name, *prefix, *suffix;
|
||||
dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix;
|
||||
dns_offsets_t current_offsets;
|
||||
dns_namereln_t compared;
|
||||
dns_result_t result;
|
||||
dns_result_t result = DNS_R_SUCCESS;
|
||||
dns_rbtnodechain_t chain;
|
||||
isc_region_t r;
|
||||
unsigned int add_labels, current_labels, keep_labels, start_label;
|
||||
unsigned int common_labels, common_bits;
|
||||
unsigned int common_labels, common_bits, add_bits;
|
||||
int order;
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
|
@ -367,14 +366,15 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
|
||||
/*
|
||||
* Create a copy of the name so the original name structure is
|
||||
* not modified.
|
||||
* not modified. The name data needs to be modifiable when
|
||||
* a node is split on a bitstring label.
|
||||
*/
|
||||
dns_name_init(&add_name, add_offsets);
|
||||
dns_name_toregion(name, &r);
|
||||
dns_name_fromregion(&add_name, &r);
|
||||
dns_fixedname_init(&fixedcopy);
|
||||
add_name = dns_fixedname_name(&fixedcopy);
|
||||
dns_name_concatenate(name, NULL, add_name, NULL);
|
||||
|
||||
if (rbt->root == NULL) {
|
||||
result = create_node(rbt->mctx, &add_name, &new_current);
|
||||
result = create_node(rbt->mctx, add_name, &new_current);
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
rbt->root = new_current;
|
||||
*nodep = new_current;
|
||||
|
|
@ -385,6 +385,11 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
dns_rbtnodechain_init(&chain, rbt->mctx);
|
||||
ADD_ANCESTOR(&chain, NULL);
|
||||
|
||||
dns_fixedname_init(&fixedprefix);
|
||||
dns_fixedname_init(&fixedsuffix);
|
||||
prefix = dns_fixedname_name(&fixedprefix);
|
||||
suffix = dns_fixedname_name(&fixedsuffix);
|
||||
|
||||
root = &rbt->root;
|
||||
parent = NULL;
|
||||
current = NULL;
|
||||
|
|
@ -394,14 +399,14 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
current = child;
|
||||
|
||||
NODENAME(current, ¤t_name);
|
||||
compared = dns_name_fullcompare(&add_name, ¤t_name,
|
||||
compared = dns_name_fullcompare(add_name, ¤t_name,
|
||||
&order,
|
||||
&common_labels, &common_bits);
|
||||
|
||||
if (compared == dns_namereln_equal) {
|
||||
*nodep = current;
|
||||
put_ancestor_mem(&chain);
|
||||
return (DNS_R_EXISTS);
|
||||
result = DNS_R_EXISTS;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -431,28 +436,22 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
* start a new tree.
|
||||
*/
|
||||
|
||||
add_labels = FAST_COUNTLABELS(&add_name);
|
||||
current_labels = FAST_COUNTLABELS(¤t_name);
|
||||
|
||||
if (compared == dns_namereln_subdomain &&
|
||||
common_bits == 0) {
|
||||
if (compared == dns_namereln_subdomain) {
|
||||
/*
|
||||
* All of the exising labels are in common,
|
||||
* so the new name is in a subtree.
|
||||
* First, turn the non-in-common part of
|
||||
* &add_name into its own dns_name_t to be
|
||||
* searched for in the downtree.
|
||||
* Whack off the common labels for the
|
||||
* not-in-common part to be searched for
|
||||
* in the next level.
|
||||
*/
|
||||
result = dns_name_split(add_name,
|
||||
common_labels,
|
||||
common_bits,
|
||||
add_name, NULL);
|
||||
|
||||
start_label = 0;
|
||||
|
||||
keep_labels = add_labels - common_labels;
|
||||
|
||||
dns_name_getlabelsequence(&add_name,
|
||||
start_label,
|
||||
keep_labels,
|
||||
&add_name);
|
||||
|
||||
if (result != DNS_R_SUCCESS)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Follow the down pointer (possibly NULL).
|
||||
*/
|
||||
|
|
@ -472,9 +471,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
*/
|
||||
|
||||
INSIST(compared == dns_namereln_commonancestor
|
||||
|| compared == dns_namereln_contains
|
||||
|| (compared == dns_namereln_subdomain
|
||||
&& common_bits > 0));
|
||||
|| compared == dns_namereln_contains);
|
||||
|
||||
/*
|
||||
* Ensure the number of levels in the tree
|
||||
|
|
@ -485,42 +482,28 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
*/
|
||||
if (chain.level_count ==
|
||||
(sizeof(chain.levels) /
|
||||
sizeof(*chain.levels)))
|
||||
return (DNS_R_NOSPACE);
|
||||
|
||||
/* XXX DCL handle bitstrings.
|
||||
* When common_bits is non-zero, the last label
|
||||
* in common (eg, vix in a.vix.com vs
|
||||
* b.vix.com) is a bit label and common_bits is
|
||||
* how many are in common. To split the node,
|
||||
* the node in question will have to split into
|
||||
* two bitstrings. A comment in name.h says,
|
||||
* "Some provision still needs to be made for
|
||||
* splitting bitstring labels," and Bob has
|
||||
* pushed this down on the priority list,
|
||||
* so for now splitting on bitstrings does not
|
||||
* work.
|
||||
*/
|
||||
sizeof(*chain.levels))) {
|
||||
result = DNS_R_NOSPACE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the common labels of the current name.
|
||||
* Split the name into two parts, a prefix
|
||||
* which is the not-in-common parts of the
|
||||
* two names and a suffix that is the common
|
||||
* parts of them.
|
||||
*/
|
||||
|
||||
start_label = current_labels - common_labels;
|
||||
keep_labels = common_labels;
|
||||
result = dns_name_split(¤t_name,
|
||||
common_labels,
|
||||
common_bits,
|
||||
prefix, suffix);
|
||||
|
||||
dns_name_init(&tmp_name, tmp_offsets);
|
||||
dns_name_getlabelsequence(¤t_name,
|
||||
start_label,
|
||||
keep_labels,
|
||||
&tmp_name);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
result = create_node(rbt->mctx, suffix,
|
||||
&new_current);
|
||||
|
||||
result = create_node(rbt->mctx,
|
||||
&tmp_name, &new_current);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
put_ancestor_mem(&chain);
|
||||
return (result);
|
||||
}
|
||||
if (result != DNS_R_SUCCESS)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Reproduce the tree attributes of the
|
||||
|
|
@ -542,7 +525,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
*root = new_current;
|
||||
|
||||
/*
|
||||
* Now create the new root of the subtree
|
||||
* Now make the new root of the subtree
|
||||
* as the not-in-common labels of the current
|
||||
* node, keeping the same memory location so
|
||||
* as not to break any external references to
|
||||
|
|
@ -550,32 +533,57 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
* are preserved, while left and right
|
||||
* pointers are nullified when the node is
|
||||
* established as the start of the next level.
|
||||
*/
|
||||
|
||||
start_label = 0;
|
||||
keep_labels = current_labels - common_labels;
|
||||
|
||||
dns_name_init(&new_name, new_offsets);
|
||||
dns_name_getlabelsequence(¤t_name,
|
||||
start_label,
|
||||
keep_labels,
|
||||
&new_name);
|
||||
|
||||
/*
|
||||
*
|
||||
* The name stored at the node is effectively
|
||||
* truncated in place by setting the shorter
|
||||
* name length, moving the offsets to the
|
||||
* end of the truncated name, and then
|
||||
* updating PADBYTES to reflect the truncation.
|
||||
*
|
||||
* When bitstring labels are involved, things
|
||||
* are just a tad more complicated (aren't
|
||||
* they always?) because the splitting
|
||||
* has shifted the bits that this name needs,
|
||||
* as well as adjusted the bit count.
|
||||
* So there are convolutions to deal with it.
|
||||
* There are compromises here between
|
||||
* abstraction and efficiency.
|
||||
*/
|
||||
|
||||
NAMELEN(current) = new_name.length;
|
||||
OFFSETLEN(current) = keep_labels;
|
||||
memcpy(OFFSETS(current), new_name.offsets,
|
||||
keep_labels);
|
||||
if (common_bits > 0) {
|
||||
dns_label_t label;
|
||||
|
||||
dns_name_getlabel(prefix,
|
||||
FAST_COUNTLABELS(¤t_name) -
|
||||
common_labels,
|
||||
&label);
|
||||
|
||||
INSIST(dns_label_type(&label) ==
|
||||
dns_labeltype_bitstring);
|
||||
|
||||
memcpy(NAME(current) +
|
||||
(label.base - prefix->ndata),
|
||||
label.base,
|
||||
label.length);
|
||||
|
||||
dns_name_getlabel(add_name,
|
||||
FAST_COUNTLABELS(add_name) -
|
||||
common_labels,
|
||||
&label);
|
||||
INSIST(dns_label_type(&label) ==
|
||||
dns_labeltype_bitstring);
|
||||
|
||||
add_bits = dns_label_countbits(&label);
|
||||
} else
|
||||
add_bits = 0;
|
||||
|
||||
NAMELEN(current) = prefix->length;
|
||||
OFFSETLEN(current) = prefix->labels;
|
||||
memcpy(OFFSETS(current), prefix->offsets,
|
||||
prefix->labels);
|
||||
PADBYTES(current) +=
|
||||
(current_name.length - new_name.length)
|
||||
+ (current_labels - keep_labels);
|
||||
(current_name.length - prefix->length) +
|
||||
(current_name.labels - prefix->labels);
|
||||
|
||||
/*
|
||||
* Set up the new root of the next level.
|
||||
|
|
@ -593,7 +601,9 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
MAKE_BLACK(current);
|
||||
ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
|
||||
|
||||
if (common_labels == add_labels) {
|
||||
if (common_labels ==
|
||||
FAST_COUNTLABELS(add_name) &&
|
||||
common_bits == add_bits) {
|
||||
/*
|
||||
* The name has been added by pushing
|
||||
* the not-in-common parts down to
|
||||
|
|
@ -608,24 +618,27 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
* The current node has no data,
|
||||
* because it is just a placeholder.
|
||||
* Its data pointer is already NULL
|
||||
* from create_node()).
|
||||
* from create_node()), so there's
|
||||
* nothing more to do to but add it to
|
||||
* the ancestor chain, because it will
|
||||
* be the parent node of the new node.
|
||||
*/
|
||||
ADD_ANCESTOR(&chain, current);
|
||||
|
||||
/* The not-in-common parts of the new
|
||||
* name will be inserted into the new
|
||||
* level following this loop.
|
||||
* level following this loop (unless
|
||||
* result != DNS_R_SUCCESS, which
|
||||
* is tested after the loop ends).
|
||||
*/
|
||||
start_label = 0;
|
||||
keep_labels =
|
||||
add_labels - common_labels;
|
||||
result = dns_name_split(add_name,
|
||||
common_labels,
|
||||
common_bits,
|
||||
add_name,
|
||||
NULL);
|
||||
|
||||
dns_name_getlabelsequence(&add_name,
|
||||
start_label,
|
||||
keep_labels,
|
||||
&add_name);
|
||||
|
||||
child = NULL;
|
||||
ADD_ANCESTOR(&chain, current);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -634,7 +647,8 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
|
||||
} while (child != NULL);
|
||||
|
||||
result = create_node(rbt->mctx, &add_name, &new_current);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
result = create_node(rbt->mctx, add_name, &new_current);
|
||||
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
dns_rbt_addonlevel(new_current, current, order, root, &chain);
|
||||
|
|
@ -687,15 +701,15 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
|||
{
|
||||
dns_rbtnode_t *current;
|
||||
dns_rbtnodechain_t localchain;
|
||||
dns_name_t *search_name, *current_name, *tmp_name, *callback_name;
|
||||
dns_name_t name1, name2;
|
||||
dns_offsets_t name1_offsets, name2_offsets;
|
||||
dns_name_t *search_name, current_name, *callback_name, tmp_name;
|
||||
dns_offsets_t tmp_offsets;
|
||||
dns_fixedname_t fixedcallbackname;
|
||||
dns_namereln_t compared;
|
||||
dns_result_t result, saved_result;
|
||||
isc_region_t r;
|
||||
isc_region_t region;
|
||||
isc_buffer_t buffer;
|
||||
unsigned char data[255];
|
||||
unsigned int common_labels, common_bits;
|
||||
unsigned int first_common_label;
|
||||
int order;
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
|
@ -716,30 +730,34 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
|||
dns_fixedname_init(&fixedcallbackname);
|
||||
callback_name = dns_fixedname_name(&fixedcallbackname);
|
||||
|
||||
dns_name_init(&name1, name1_offsets);
|
||||
dns_name_init(&name2, name2_offsets);
|
||||
|
||||
/*
|
||||
* search_name is the name segment being sought in each tree level.
|
||||
* Ensure that it has offsets by making a copy into a structure
|
||||
* that has offsets.
|
||||
* that has offsets. Since weird juju happens when splitting bitstring
|
||||
* labels, a buffer is provided for the bitfiddling to use; however,
|
||||
* the input name's data is used to avoid unnecessary copying.
|
||||
*/
|
||||
search_name = &tmp_name;
|
||||
if (name->offsets == NULL) {
|
||||
search_name = &name1;
|
||||
dns_name_toregion(name, &r);
|
||||
dns_name_fromregion(search_name, &r);
|
||||
} else
|
||||
search_name = name;
|
||||
dns_name_init(search_name, tmp_offsets);
|
||||
dns_name_toregion(name, ®ion);
|
||||
dns_name_fromregion(search_name, ®ion);
|
||||
}
|
||||
|
||||
current_name = &name2;
|
||||
isc_buffer_init(&buffer, data, 255, ISC_BUFFERTYPE_BINARY);
|
||||
dns_name_setbuffer(search_name, &buffer);
|
||||
|
||||
search_name->ndata = name->ndata;
|
||||
|
||||
dns_name_init(¤t_name, NULL);
|
||||
|
||||
ADD_ANCESTOR(chain, NULL);
|
||||
|
||||
saved_result = DNS_R_SUCCESS;
|
||||
current = rbt->root;
|
||||
while (current != NULL) {
|
||||
NODENAME(current, current_name);
|
||||
compared = dns_name_fullcompare(search_name, current_name,
|
||||
NODENAME(current, ¤t_name);
|
||||
compared = dns_name_fullcompare(search_name, ¤t_name,
|
||||
&order,
|
||||
&common_labels, &common_bits);
|
||||
|
||||
|
|
@ -765,36 +783,19 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
|||
* the current node's name length, then follow the
|
||||
* down pointer and search in the new tree.
|
||||
*/
|
||||
if (compared == dns_namereln_subdomain &&
|
||||
common_bits == 0) {
|
||||
if (compared == dns_namereln_subdomain) {
|
||||
/*
|
||||
* Set up new name to search for as
|
||||
* the not-in-common part.
|
||||
*/
|
||||
if (search_name == &name2) {
|
||||
current_name = &name2;
|
||||
tmp_name = &name1;
|
||||
dns_name_init(tmp_name, name1_offsets);
|
||||
|
||||
} else {
|
||||
current_name = &name1;
|
||||
tmp_name = &name2;
|
||||
dns_name_init(tmp_name, name2_offsets);
|
||||
}
|
||||
|
||||
first_common_label =
|
||||
FAST_COUNTLABELS(search_name)
|
||||
- common_labels;
|
||||
|
||||
/*
|
||||
* Whack off the current node's common labels
|
||||
* Whack off the current node's common parts
|
||||
* for the name to search in the next level.
|
||||
*/
|
||||
dns_name_getlabelsequence(search_name, 0,
|
||||
first_common_label,
|
||||
tmp_name);
|
||||
|
||||
search_name = tmp_name;
|
||||
result = dns_name_split(search_name,
|
||||
common_labels,
|
||||
common_bits,
|
||||
search_name, NULL);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
dns_rbtnodechain_reset(chain);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* This might be the closest enclosing name.
|
||||
|
|
@ -813,7 +814,6 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
|||
* function needs the chain pointed to the
|
||||
* next level.
|
||||
*/
|
||||
|
||||
ADD_ANCESTOR(chain, NULL);
|
||||
ADD_LEVEL(chain, current);
|
||||
chain->level_matches++;
|
||||
|
|
@ -864,9 +864,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
|
|||
* logic below then end the loop.
|
||||
*/
|
||||
INSIST(compared == dns_namereln_commonancestor
|
||||
|| compared == dns_namereln_contains
|
||||
|| (compared == dns_namereln_subdomain
|
||||
&& common_bits > 0));
|
||||
|| compared == dns_namereln_contains);
|
||||
|
||||
ADD_ANCESTOR(chain, current);
|
||||
current = NULL;
|
||||
|
|
@ -1263,7 +1261,8 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
|
|||
|
||||
static dns_result_t
|
||||
join_nodes(dns_rbt_t *rbt,
|
||||
dns_rbtnode_t *node, dns_rbtnode_t *parent, dns_rbtnode_t **rootp) {
|
||||
dns_rbtnode_t *node, dns_rbtnode_t *parent, dns_rbtnode_t **rootp)
|
||||
{
|
||||
dns_rbtnode_t *down, *newnode;
|
||||
dns_result_t result;
|
||||
dns_name_t newname;
|
||||
|
|
|
|||
Loading…
Reference in a new issue