/** * Find closest existing parent data for the given name. * @param zone: to look in. * @param nm: name to look for * @param nm_len: length of nm * @param labs: labelcount of nm. * @return the data or NULL if none found. */ static struct val_neg_data* neg_closest_data_parent( struct val_neg_zone* zone, uint8_t* nm, size_t nm_len, int labs) { struct val_neg_data key; struct val_neg_data* result; rbnode_t* res = NULL; key.node.key = &key; key.name = nm; key.len = nm_len; key.labs = labs; if(rbtree_find_less_equal(&zone->tree, &key, &res)) { /* exact match */ result = (struct val_neg_data*)res; } else { /* smaller element (or no element) */ int m; result = (struct val_neg_data*)res; if(!result) return NULL; /* count number of labels matched */ (void)dname_lab_cmp(result->name, result->labs, key.name, key.labs, &m); while(result) { /* go up until qname is subdomain of stub */ if(result->labs <= m) break; result = result->parent; } } return result; }
static void test6_check_le(CuTest *tc, rbtree_t *tree, int val) { rbnode_t *node = 0; if(rbtree_find_less_equal(tree, &val, &node)) { CuAssert(tc, "test6_in_tree(tree->root, val)", test6_in_tree(tree->root, val)); CuAssert(tc, "node != 0", (node != 0)); CuAssert(tc, "val == *(int*)node->key", (val == *(int*)node->key)); } else { CuAssert(tc, "!test6_in_tree(tree->root, val)", (!test6_in_tree(tree->root, val))); if(node != 0) { int smallval=*(int*)node->key; int k; CuAssert(tc, "smallval < val", (smallval < val)); for(k=smallval+1; k < val; ++k) CuAssert(tc, "!test6_in_tree(tree->root, k)", (!test6_in_tree(tree->root, k))); } else { rbnode_t* smallest = findsmallest(tree->root); if(smallest) CuAssert(tc, "val < *(int*)smallest->key", (val < *(int*)smallest->key)); } } }
struct local_zone* local_zones_tags_lookup(struct local_zones* zones, uint8_t* name, size_t len, int labs, uint16_t dclass, uint8_t* taglist, size_t taglen, int ignoretags) { rbnode_t* res = NULL; struct local_zone *result; struct local_zone key; int m; key.node.key = &key; key.dclass = dclass; key.name = name; key.namelen = len; key.namelabs = labs; rbtree_find_less_equal(&zones->ztree, &key, &res); result = (struct local_zone*)res; /* exact or smaller element (or no element) */ if(!result || result->dclass != dclass) return NULL; /* count number of labels matched */ (void)dname_lab_cmp(result->name, result->namelabs, key.name, key.namelabs, &m); while(result) { /* go up until qname is zone or subdomain of zone */ if(result->namelabs <= m) if(ignoretags || !result->taglist || taglist_intersect(result->taglist, result->taglen, taglist, taglen)) break; result = result->parent; } return result; }
struct delegpt* forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) { /* lookup the forward zone in the tree */ rbnode_t* res = NULL; struct iter_forward_zone *result; struct iter_forward_zone key; key.node.key = &key; key.dclass = qclass; key.name = qname; key.namelabs = dname_count_size_labels(qname, &key.namelen); if(rbtree_find_less_equal(fwd->tree, &key, &res)) { /* exact */ result = (struct iter_forward_zone*)res; } else { /* smaller element (or no element) */ int m; result = (struct iter_forward_zone*)res; if(!result || result->dclass != qclass) return NULL; /* count number of labels matched */ (void)dname_lab_cmp(result->name, result->namelabs, key.name, key.namelabs, &m); while(result) { /* go up until qname is subdomain of stub */ if(result->namelabs <= m) break; result = result->parent; } } if(result) return result->dp; return NULL; }
/* * Searches the red black tree, returns the data if key is found or NULL otherwise. * */ rbnode_t * rbtree_search (rbtree_t *rbtree, const void *key) { rbnode_t *node; if (rbtree_find_less_equal(rbtree, key, &node)) { return node; } else { return NULL; } }
int forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) { struct iter_forward_zone key; rbnode_t* n; struct iter_forward_zone* p; if(*dclass == 0) { /* first root item is first item in tree */ n = rbtree_first(fwd->tree); if(n == RBTREE_NULL) return 0; p = (struct iter_forward_zone*)n; if(dname_is_root(p->name)) { *dclass = p->dclass; return 1; } /* root not first item? search for higher items */ *dclass = p->dclass + 1; return forwards_next_root(fwd, dclass); } /* find class n in tree, we may get a direct hit, or if we don't * this is the last item of the previous class so rbtree_next() takes * us to the next root (if any) */ key.node.key = &key; key.name = (uint8_t*)"\000"; key.namelen = 1; key.namelabs = 0; key.dclass = *dclass; n = NULL; if(rbtree_find_less_equal(fwd->tree, &key, &n)) { /* exact */ return 1; } else { /* smaller element */ if(!n || n == RBTREE_NULL) return 0; /* nothing found */ n = rbtree_next(n); if(n == RBTREE_NULL) return 0; /* no higher */ p = (struct iter_forward_zone*)n; if(dname_is_root(p->name)) { *dclass = p->dclass; return 1; } /* not a root node, return next higher item */ *dclass = p->dclass+1; return forwards_next_root(fwd, dclass); } }
/** * Lookup closest data record. For NSEC denial. * @param zone: zone to look in * @param qname: name to look for. * @param len: length of name * @param labs: labels in name * @param data: data element, exact or smaller or NULL * @return true if exact match. */ static int neg_closest_data(struct val_neg_zone* zone, uint8_t* qname, size_t len, int labs, struct val_neg_data** data) { struct val_neg_data key; rbnode_t* r; key.node.key = &key; key.name = qname; key.len = len; key.labs = labs; if(rbtree_find_less_equal(&zone->tree, &key, &r)) { /* exact match */ *data = (struct val_neg_data*)r; return 1; } else { /* smaller match */ *data = (struct val_neg_data*)r; return 0; } }
struct trust_anchor* anchors_lookup(struct val_anchors* anchors, uint8_t* qname, size_t qname_len, uint16_t qclass) { struct trust_anchor key; struct trust_anchor* result; rbnode_t* res = NULL; key.node.key = &key; key.name = qname; key.namelabs = dname_count_labels(qname); key.namelen = qname_len; key.dclass = qclass; lock_basic_lock(&anchors->lock); if(rbtree_find_less_equal(anchors->tree, &key, &res)) { /* exact */ result = (struct trust_anchor*)res; } else { /* smaller element (or no element) */ int m; result = (struct trust_anchor*)res; if(!result || result->dclass != qclass) { lock_basic_unlock(&anchors->lock); return NULL; } /* count number of labels matched */ (void)dname_lab_cmp(result->name, result->namelabs, key.name, key.namelabs, &m); while(result) { /* go up until qname is subdomain of stub */ if(result->namelabs <= m) break; result = result->parent; } } if(result) { lock_basic_lock(&result->lock); } lock_basic_unlock(&anchors->lock); return result; }