#define QPDB_ATTR_LOADED 0x01
#define QPDB_ATTR_LOADING 0x02
-#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \
- ((iterator)->current == &(iterator)->nsec3iter && \
- (iterator)->node == (qpdb)->nsec3_origin)
+#define QPDBITER_ORIGIN_NODE(qpdb, iterator) \
+ ((iterator)->node == (qpdb)->origin)
+#define QPDBITER_NSEC_ORIGIN_NODE(qpdb, iterator) \
+ ((iterator)->node == (qpdb)->nsec_origin)
+#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \
+ ((iterator)->node == (qpdb)->nsec3_origin)
/*%
* Note that "impmagic" is not the first four bytes of the struct, so
isc_refcount_t references;
qpznode_t *origin;
+ qpznode_t *nsec_origin;
qpznode_t *nsec3_origin;
isc_stats_t *gluecachestats;
/* Locked by lock. */
qpz_heap_t *heap; /* Resigning heap */
- dns_qpmulti_t *tree; /* Main QP trie for data storage */
- dns_qpmulti_t *nsec; /* NSEC nodes only */
- dns_qpmulti_t *nsec3; /* NSEC3 nodes only */
+ dns_qpmulti_t *tree; /* QP trie for data storage */
};
#ifdef DNS_DB_NODETRACE
typedef struct {
dns_db_t *db;
dns_qp_t *tree;
- dns_qp_t *nsec;
- dns_qp_t *nsec3;
} qpz_load_t;
static dns_dbmethods_t qpdb_zonemethods;
* or DNS_DB_NONSEC3, will transparently move between the last node of the
* "regular" QP trie and the root node of the NSEC3 QP trie of the database
* in question, as if the latter was a successor to the former in lexical
- * order. The "current" field always holds the address of either
- * "mainiter" or "nsec3iter", depending on which trie is being traversed
- * at given time.
+ * order. The "current" field always holds the address of either "iter".
*/
static void
dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG);
typedef struct qpdb_dbiterator {
dns_dbiterator_t common;
isc_result_t result;
- dns_qpsnap_t *tsnap; /* main tree snapshot */
- dns_qpsnap_t *nsnap; /* nsec3 tree snapshot */
- dns_qpiter_t *current; /* current iterator, which is one of: */
- dns_qpiter_t mainiter; /* - main tree iterator */
- dns_qpiter_t nsec3iter; /* - nsec3 tree iterator */
+ dns_qpsnap_t *snap; /* tree snapshot */
+ dns_qpiter_t iter; /* tree iterator */
qpznode_t *node;
enum { full, nonsec3, nsec3only } nsec3mode;
} qpdb_dbiterator_t;
sizeof(*qpdb->current_version));
dns_qpmulti_destroy(&qpdb->tree);
- dns_qpmulti_destroy(&qpdb->nsec);
- dns_qpmulti_destroy(&qpdb->nsec3);
char buf[DNS_NAME_FORMATSIZE];
if (dns_name_dynamic(&qpdb->common.origin)) {
if (qpdb->origin != NULL) {
qpznode_detach(&qpdb->origin);
}
+ if (qpdb->nsec_origin != NULL) {
+ qpznode_detach(&qpdb->nsec_origin);
+ }
if (qpdb->nsec3_origin != NULL) {
qpznode_detach(&qpdb->nsec3_origin);
}
dns_name_dup(origin, mctx, &qpdb->common.origin);
dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->tree);
- dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec);
- dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec3);
/*
* Version initialization.
qpdb->current_version = allocate_version(mctx, 1, 1, false);
qpdb->current_version->qpdb = qpdb;
+ dns_qpmulti_write(qpdb->tree, &qp);
+
/*
* In order to set the node callback bit correctly in zone databases,
* we need to know if the node has the origin name of the zone.
* We now explicitly create a node for the zone's origin, and then
* we simply remember the node data's address.
*/
-
- dns_qpmulti_write(qpdb->tree, &qp);
qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin);
qpdb->origin->nsec = DNS_DB_NSEC_NORMAL;
result = dns_qp_insert(qp, qpdb->origin, 0);
INSIST(result == ISC_R_SUCCESS);
- dns_qpmulti_commit(qpdb->tree, &qp);
+
+ /*
+ * Add an apex node to the NSEC tree so that we can quickly skip over
+ * the NSEC nodes while iterating over the full tree.
+ */
+ qpdb->nsec_origin = new_qpznode(qpdb, &qpdb->common.origin);
+ qpdb->nsec_origin->nsec = DNS_DB_NSEC_NSEC;
+ result = dns_qp_insert(qp, qpdb->nsec_origin, 0);
+ INSIST(result == ISC_R_SUCCESS);
/*
* Add an apex node to the NSEC3 tree so that NSEC3 searches
* return partial matches when there is only a single NSEC3
* record in the tree.
*/
- dns_qpmulti_write(qpdb->nsec3, &qp);
qpdb->nsec3_origin = new_qpznode(qpdb, &qpdb->common.origin);
qpdb->nsec3_origin->nsec = DNS_DB_NSEC_NSEC3;
result = dns_qp_insert(qp, qpdb->nsec3_origin, 0);
INSIST(result == ISC_R_SUCCESS);
- dns_qpmulti_commit(qpdb->nsec3, &qp);
+
+ dns_qpmulti_commit(qpdb->tree, &qp);
/*
* Keep the current version in the open list so that list operation
}
/* Handle easy and typical case first. */
- if (!node->dirty && (node->data != NULL || node == qpdb->origin ||
- node == qpdb->nsec3_origin))
+ if (!node->dirty &&
+ (node->data != NULL || node == qpdb->origin ||
+ node == qpdb->nsec_origin || node == qpdb->nsec3_origin))
{
goto unref;
}
qpznode_t *node = NULL, *nsecnode = NULL;
if (type == dns_rdatatype_nsec3 || covers == dns_rdatatype_nsec3) {
- result = dns_qp_getname(loadctx->nsec3, name, DNS_DB_NSEC_NSEC3,
+ result = dns_qp_getname(loadctx->tree, name, DNS_DB_NSEC_NSEC3,
(void **)&node, NULL);
if (result == ISC_R_SUCCESS) {
*nodep = node;
} else {
node = new_qpznode(qpdb, name);
node->nsec = DNS_DB_NSEC_NSEC3;
- result = dns_qp_insert(loadctx->nsec3, node, 0);
+ result = dns_qp_insert(loadctx->tree, node, 0);
INSIST(result == ISC_R_SUCCESS);
*nodep = node;
qpznode_detach(&node);
node->havensec = true;
nsecnode = new_qpznode(qpdb, name);
nsecnode->nsec = DNS_DB_NSEC_NSEC;
- (void)dns_qp_insert(loadctx->nsec, nsecnode, 0);
+ (void)dns_qp_insert(loadctx->tree, nsecnode, 0);
qpznode_detach(&nsecnode);
done:
qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db;
dns_qpmulti_write(qpdb->tree, &loadctx->tree);
- dns_qpmulti_write(qpdb->nsec, &loadctx->nsec);
- dns_qpmulti_write(qpdb->nsec3, &loadctx->nsec3);
}
static void
dns_qp_compact(loadctx->tree, DNS_QPGC_MAYBE);
dns_qpmulti_commit(qpdb->tree, &loadctx->tree);
}
- if (loadctx->nsec != NULL) {
- dns_qp_compact(loadctx->nsec, DNS_QPGC_MAYBE);
- dns_qpmulti_commit(qpdb->nsec, &loadctx->nsec);
- }
- if (loadctx->nsec3 != NULL) {
- dns_qp_compact(loadctx->nsec3, DNS_QPGC_MAYBE);
- dns_qpmulti_commit(qpdb->nsec3, &loadctx->nsec3);
- }
}
static isc_result_t
isc_result_t result;
qpznode_t *node = NULL;
uint8_t denial = nsec3 ? DNS_DB_NSEC_NSEC3 : DNS_DB_NSEC_NORMAL;
- dns_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree;
dns_qpread_t qpr = { 0 };
dns_qp_t *qp = NULL;
if (create) {
- dns_qpmulti_write(dbtree, &qp);
+ dns_qpmulti_write(qpdb->tree, &qp);
} else {
- dns_qpmulti_query(dbtree, &qpr);
+ dns_qpmulti_query(qpdb->tree, &qpr);
qp = (dns_qp_t *)&qpr;
}
result = dns_qp_getname(qp, name, denial, (void **)&node, NULL);
if (result != ISC_R_SUCCESS) {
if (!create) {
- dns_qpread_destroy(dbtree, &qpr);
+ dns_qpread_destroy(qpdb->tree, &qpr);
return result;
}
if (create) {
dns_qp_compact(qp, DNS_QPGC_MAYBE);
- dns_qpmulti_commit(dbtree, &qp);
+ dns_qpmulti_commit(qpdb->tree, &qp);
} else {
- dns_qpread_destroy(dbtree, &qpr);
+ dns_qpread_destroy(qpdb->tree, &qpr);
}
*nodep = (dns_dbnode_t *)node;
return result;
}
- dns_qpmulti_query(search->qpdb->nsec, &qpr);
+ dns_qpmulti_query(search->qpdb->tree, &qpr);
for (;;) {
if (*firstp) {
}
}
- dns_qpread_destroy(search->qpdb->nsec, &qpr);
+ dns_qpread_destroy(search->qpdb->tree, &qpr);
return result;
}
options);
if ((options & DNS_DBFIND_FORCENSEC3) != 0) {
- dns_qpmulti_query(qpdb->nsec3, &search.qpr);
nsec3 = true;
denial = DNS_DB_NSEC_NSEC3;
} else {
- dns_qpmulti_query(qpdb->tree, &search.qpr);
denial = DNS_DB_NSEC_NORMAL;
}
+ dns_qpmulti_query(qpdb->tree, &search.qpr);
/*
* Search down from the root of the tree.
NODE_UNLOCK(nlock, &nlocktype);
tree_exit:
- if (nsec3) {
- dns_qpread_destroy(qpdb->nsec3, &search.qpr);
- } else {
- dns_qpread_destroy(qpdb->tree, &search.qpr);
- }
+ dns_qpread_destroy(qpdb->tree, &search.qpr);
/*
* If we found a zonecut but aren't going to use it, we have to
}
static unsigned int
-nodecount(dns_db_t *db, dns_dbtree_t tree) {
+nodecount(dns_db_t *db, dns_dbtree_t tree ISC_ATTR_UNUSED) {
qpzonedb_t *qpdb = NULL;
dns_qp_memusage_t mu;
REQUIRE(VALID_QPZONE(qpdb));
- switch (tree) {
- case dns_dbtree_main:
- mu = dns_qpmulti_memusage(qpdb->tree);
- break;
- case dns_dbtree_nsec:
- mu = dns_qpmulti_memusage(qpdb->nsec);
- break;
- case dns_dbtree_nsec3:
- mu = dns_qpmulti_memusage(qpdb->nsec3);
- break;
- default:
- UNREACHABLE();
- }
+ mu = dns_qpmulti_memusage(qpdb->tree);
return mu.leaves;
}
dns_db_detach(&iter->common.db);
qpzonedb_t *qpdb = (qpzonedb_t *)db;
- dns_qpsnap_destroy(qpdb->tree, &iter->tsnap);
- dns_qpsnap_destroy(qpdb->nsec3, &iter->nsnap);
+ dns_qpsnap_destroy(qpdb->tree, &iter->snap);
isc_mem_put(db->mctx, iter, sizeof(*iter));
dns_db_detach(&db);
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
+ dns_qpiter_init(qpdbiter->snap, &qpdbiter->iter);
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node, NULL);
+
switch (qpdbiter->nsec3mode) {
- case nsec3only:
- qpdbiter->current = &qpdbiter->nsec3iter;
- dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
- result = dns_qpiter_next(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
- /* If we're in the NSEC3 tree, skip the origin */
- if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
- result = dns_qpiter_next(
- qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
+ case nonsec3:
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * If we immediately hit an NSEC/NSEC3 node,
+ * we don't have any non-nsec nodes.
+ */
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NORMAL) {
+ qpdbiter->node = NULL;
+ result = ISC_R_NOMORE;
}
}
break;
- case nonsec3:
- qpdbiter->current = &qpdbiter->mainiter;
- dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
- result = dns_qpiter_next(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- break;
case full:
- qpdbiter->current = &qpdbiter->mainiter;
- dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
- result = dns_qpiter_next(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- if (result == ISC_R_NOMORE) {
- qpdbiter->current = &qpdbiter->nsec3iter;
- dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
- result = dns_qpiter_next(qpdbiter->current, NULL,
+ /* skip the NSEC3 origin node. */
+ if (result == ISC_R_SUCCESS &&
+ QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
+ {
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ qpdbiter->node = NULL;
+ break;
+ }
+
+ /*
+ * If we hit an NSEC node, we need to start at the NSEC3 part of
+ * the tree.
+ */
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC) {
+ break;
+ }
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NSEC);
+
+ /* FALLTHROUGH */
+ case nsec3only:
+ /*
+ * NSEC3 follows after all non-nsec3 nodes, seek the NSEC3
+ * origin node.
+ */
+ result = dns_qp_lookup2(qpdbiter->snap, &qpdb->common.origin,
+ DNS_DB_NSEC_NSEC3, NULL,
+ &qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node, NULL);
+ if (result != ISC_R_SUCCESS ||
+ QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
+ {
+ /* skip the NSEC3 origin node (or its predecessor) */
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node,
NULL);
}
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
+ dns_qpiter_init(qpdbiter->snap, &qpdbiter->iter);
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node, NULL);
+
switch (qpdbiter->nsec3mode) {
case nsec3only:
- qpdbiter->current = &qpdbiter->nsec3iter;
- dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) &&
- QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
- {
- /*
- * NSEC3 tree only has an origin node.
- */
- qpdbiter->node = NULL;
- result = ISC_R_NOMORE;
+ if (result == ISC_R_SUCCESS) {
+ if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
+ /* tree only has NSEC3 origin node. */
+ qpdbiter->node = NULL;
+ result = ISC_R_NOMORE;
+ } else if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC3) {
+ /* tree has no NSEC3 nodes at all. */
+ qpdbiter->node = NULL;
+ result = ISC_R_NOMORE;
+ }
}
break;
- case nonsec3:
- qpdbiter->current = &qpdbiter->mainiter;
- dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- break;
case full:
- qpdbiter->current = &qpdbiter->nsec3iter;
- dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) &&
+ /* skip the NSEC3 origin node. */
+ if (result == ISC_R_SUCCESS &&
QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
{
- /*
- * NSEC3 tree only has an origin node.
- */
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
qpdbiter->node = NULL;
- result = ISC_R_NOMORE;
+ break;
}
- if (result == ISC_R_NOMORE) {
- qpdbiter->current = &qpdbiter->mainiter;
- dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
+
+ /*
+ * If we hit an NSEC node, we need to seek the final normal node
+ * of the tree.
+ */
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC) {
+ break;
+ }
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NSEC);
+
+ /* FALLTHROUGH */
+ case nonsec3:
+ /*
+ * The final non-nsec node is before the the NSEC origin node.
+ */
+ result = dns_qp_lookup2(qpdbiter->snap, &qpdb->common.origin,
+ DNS_DB_NSEC_NSEC, NULL, &qpdbiter->iter,
+ NULL, (void **)&qpdbiter->node, NULL);
+ if (result == ISC_R_SUCCESS) {
+ INSIST(QPDBITER_NSEC_ORIGIN_NODE(qpdb, qpdbiter));
+ /* skip the NSEC origin node */
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node,
NULL);
+ } else {
+ /*
+ * The NSEC origin node was not found, but the iterator
+ * should point to its predecessor, which is the node we
+ * want.
+ */
+ result = dns_qpiter_current(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NORMAL);
}
break;
default:
switch (qpdbiter->nsec3mode) {
case nsec3only:
- qpdbiter->current = &qpdbiter->nsec3iter;
- result = dns_qp_lookup2(qpdbiter->nsnap, name,
- DNS_DB_NSEC_NSEC3, NULL,
- qpdbiter->current, NULL,
+ result = dns_qp_lookup2(qpdbiter->snap, name, DNS_DB_NSEC_NSEC3,
+ NULL, &qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
break;
case nonsec3:
- qpdbiter->current = &qpdbiter->mainiter;
- result = dns_qp_lookup(qpdbiter->tsnap, name, NULL,
- qpdbiter->current, NULL,
+ result = dns_qp_lookup(qpdbiter->snap, name, NULL,
+ &qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
break;
case full:
- /*
- * Stay on main chain if not found on
- * either iterator.
- */
- qpdbiter->current = &qpdbiter->mainiter;
- result = dns_qp_lookup(qpdbiter->tsnap, name, NULL,
- qpdbiter->current, NULL,
+ result = dns_qp_lookup(qpdbiter->snap, name, NULL,
+ &qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- if (result == DNS_R_PARTIALMATCH) {
+ if (result != ISC_R_SUCCESS) {
tresult = dns_qp_lookup2(
- qpdbiter->nsnap, name, DNS_DB_NSEC_NSEC3, NULL,
- &qpdbiter->nsec3iter, NULL, NULL, NULL);
+ qpdbiter->snap, name, DNS_DB_NSEC_NSEC3, NULL,
+ &qpdbiter->iter, NULL, (void **)&qpdbiter->node,
+ NULL);
if (tresult == ISC_R_SUCCESS) {
- qpdbiter->current = &qpdbiter->nsec3iter;
result = tresult;
}
}
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- if (qpdbiter->current == &qpdbiter->nsec3iter) {
- if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
- /*
- * If we're in the NSEC3 tree, it's empty or
- * we've reached the origin, then we're done
- * with it.
- */
+ switch (qpdbiter->nsec3mode) {
+ case nsec3only:
+ if (result == ISC_R_SUCCESS) {
if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
+ /* we hit the NSEC3 origin node. */
+ qpdbiter->node = NULL;
+ result = ISC_R_NOMORE;
+ } else if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC3) {
+ /* we hit a non-NSEC3 node. */
qpdbiter->node = NULL;
result = ISC_R_NOMORE;
}
}
- if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full) {
- qpdbiter->current = &qpdbiter->mainiter;
- dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
- result = dns_qpiter_prev(qpdbiter->current, NULL,
+ break;
+ case full:
+ /* skip the NSEC3 origin node. */
+ if (result == ISC_R_SUCCESS &&
+ QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
+ {
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ qpdbiter->node = NULL;
+ break;
+ }
+
+ /*
+ * If we hit an NSEC node, we need to seek the final normal node
+ * of the tree.
+ */
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC) {
+ break;
+ }
+
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NSEC);
+ result = dns_qp_lookup2(qpdbiter->snap, &qpdb->common.origin,
+ DNS_DB_NSEC_NSEC, NULL, &qpdbiter->iter,
+ NULL, (void **)&qpdbiter->node, NULL);
+
+ if (result == ISC_R_SUCCESS) {
+ INSIST(QPDBITER_NSEC_ORIGIN_NODE(qpdb, qpdbiter));
+ /* skip the NSEC origin node */
+ result = dns_qpiter_prev(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node,
NULL);
+ } else {
+ /*
+ * The NSEC origin node was not found, but the iterator
+ * should point to its predecessor, which is the node we
+ * want.
+ */
+ result = dns_qpiter_current(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NORMAL);
}
+ break;
+ case nonsec3:
+ break;
+ default:
+ UNREACHABLE();
}
if (result == ISC_R_SUCCESS) {
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
- result = dns_qpiter_next(qpdbiter->current, NULL,
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full &&
- qpdbiter->current == &qpdbiter->mainiter)
- {
- qpdbiter->current = &qpdbiter->nsec3iter;
- dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
- result = dns_qpiter_next(qpdbiter->current, NULL,
- (void **)&qpdbiter->node, NULL);
- }
+ switch (qpdbiter->nsec3mode) {
+ case nonsec3:
+ if (result == ISC_R_SUCCESS) {
+ /* we hit an NSEC or NSEC3 node. */
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NORMAL) {
+ qpdbiter->node = NULL;
+ result = ISC_R_NOMORE;
+ }
+ }
+ break;
+ case full:
+ /* skip the NSEC3 origin node. */
+ if (result == ISC_R_SUCCESS &&
+ QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
+ {
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ qpdbiter->node = NULL;
+ break;
+ }
- if (result == ISC_R_SUCCESS) {
/*
- * If we've just started the NSEC3 tree,
- * skip over the origin.
+ * If we hit an NSEC node, we need to start at the NSEC3 part of
+ * the tree.
*/
- if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
- switch (qpdbiter->nsec3mode) {
- case nsec3only:
- case full:
- result = dns_qpiter_next(
- qpdbiter->current, NULL,
+ if (qpdbiter->node->nsec != DNS_DB_NSEC_NSEC) {
+ break;
+ }
+ INSIST(qpdbiter->node->nsec == DNS_DB_NSEC_NSEC);
+
+ result = dns_qp_lookup2(qpdbiter->snap, &qpdb->common.origin,
+ DNS_DB_NSEC_NSEC3, NULL,
+ &qpdbiter->iter, NULL,
(void **)&qpdbiter->node, NULL);
- break;
- case nonsec3:
- result = ISC_R_NOMORE;
- qpdbiter->node = NULL;
- break;
- default:
- UNREACHABLE();
- }
+ if (result != ISC_R_SUCCESS ||
+ QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
+ {
+ /* skip the NSEC3 origin node (or its predecessor). */
+ result = dns_qpiter_next(&qpdbiter->iter, NULL,
+ (void **)&qpdbiter->node,
+ NULL);
}
+ break;
+ case nsec3only:
+ break;
+ default:
+ UNREACHABLE();
}
if (result == ISC_R_SUCCESS) {
dns_dbiterator_t **iteratorp) {
qpzonedb_t *qpdb = (qpzonedb_t *)db;
qpdb_dbiterator_t *iter = NULL;
+ isc_result_t result;
REQUIRE(VALID_QPZONE(qpdb));
if ((options & DNS_DB_NSEC3ONLY) != 0) {
iter->nsec3mode = nsec3only;
- iter->current = &iter->nsec3iter;
} else if ((options & DNS_DB_NONSEC3) != 0) {
iter->nsec3mode = nonsec3;
- iter->current = &iter->mainiter;
} else {
iter->nsec3mode = full;
- iter->current = &iter->mainiter;
}
dns_db_attach(db, &iter->common.db);
- dns_qpmulti_snapshot(qpdb->tree, &iter->tsnap);
- dns_qpiter_init(iter->tsnap, &iter->mainiter);
+ dns_qpmulti_snapshot(qpdb->tree, &iter->snap);
- dns_qpmulti_snapshot(qpdb->nsec3, &iter->nsnap);
- dns_qpiter_init(iter->nsnap, &iter->nsec3iter);
+ switch (iter->nsec3mode) {
+ case nonsec3:
+ case full:
+ dns_qpiter_init(iter->snap, &iter->iter);
+ break;
+ case nsec3only:
+ /*
+ * NSEC3 follows after all non-nsec3 nodes,
+ * seek the NSEC3 origin node.
+ */
+ result = dns_qp_lookup2(iter->snap, &qpdb->common.origin,
+ DNS_DB_NSEC_NSEC3, NULL, &iter->iter,
+ NULL, NULL, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ default:
+ UNREACHABLE();
+ }
*iteratorp = (dns_dbiterator_t *)iter;
return ISC_R_SUCCESS;
* Add to the auxiliary NSEC tree if we're adding an NSEC record.
*/
if (!node->havensec && rdataset->type == dns_rdatatype_nsec) {
- dns_qpmulti_write(qpdb->nsec, &nsec);
+ dns_qpmulti_write(qpdb->tree, &nsec);
}
/*
NODE_UNLOCK(nlock, &nlocktype);
if (nsec != NULL) {
- dns_qpmulti_commit(qpdb->nsec, &nsec);
+ dns_qpmulti_commit(qpdb->tree, &nsec);
}
return result;