mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +00:00
make the qpzone database dumpable
add database API method implementations needed to iterate and dump a qpzone database to a file (createiterator, allrdatasets and attachversion, plus dbiterator and rdatasetiter methods). named-checkzone -D can now dump the contents of most zones, but zone cuts are not correctly detected.
This commit is contained in:
@@ -236,12 +236,11 @@ dns__dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
|||||||
* Returns:
|
* Returns:
|
||||||
*
|
*
|
||||||
*\li #ISC_R_SUCCESS
|
*\li #ISC_R_SUCCESS
|
||||||
*\li #DNS_R_NEWORIGIN If this iterator was created
|
*\li #DNS_R_NEWORIGIN
|
||||||
* with 'relative_names' set to true, then #DNS_R_NEWORIGIN will be returned
|
* If this iterator was created with 'relative_names' set to true,
|
||||||
*when
|
* then #DNS_R_NEWORIGIN will be returned when there is a change in
|
||||||
* the origin the names are relative to changes. This result can occur only
|
* origin to which the names are relative. This result can occur only
|
||||||
*when
|
* when 'name' is not NULL. This is also a successful result.
|
||||||
*'name' is not NULL. This is also a successful result.
|
|
||||||
*
|
*
|
||||||
*\li Other results are possible, depending on the DB implementation.
|
*\li Other results are possible, depending on the DB implementation.
|
||||||
*/
|
*/
|
||||||
|
741
lib/dns/qpzone.c
741
lib/dns/qpzone.c
@@ -92,6 +92,12 @@
|
|||||||
|
|
||||||
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
|
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
|
||||||
|
|
||||||
|
#define HEADERNODE(h) ((qpdata_t *)((h)->node))
|
||||||
|
|
||||||
|
#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \
|
||||||
|
((iterator)->current == &(iterator)->nsec3iter && \
|
||||||
|
(iterator)->node == (qpdb)->nsec3_origin)
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Note that "impmagic" is not the first four bytes of the struct, so
|
* Note that "impmagic" is not the first four bytes of the struct, so
|
||||||
* ISC_MAGIC_VALID cannot be used.
|
* ISC_MAGIC_VALID cannot be used.
|
||||||
@@ -252,6 +258,74 @@ static dns_qpmethods_t qpmethods = {
|
|||||||
qp_triename,
|
qp_triename,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG);
|
||||||
|
static void
|
||||||
|
rdatasetiter_current(dns_rdatasetiter_t *iterator,
|
||||||
|
dns_rdataset_t *rdataset DNS__DB_FLARG);
|
||||||
|
|
||||||
|
static dns_rdatasetitermethods_t rdatasetiter_methods = {
|
||||||
|
rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
|
||||||
|
rdatasetiter_current
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct qpdb_rdatasetiter {
|
||||||
|
dns_rdatasetiter_t common;
|
||||||
|
dns_slabheader_t *current;
|
||||||
|
} qpdb_rdatasetiter_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that these iterators, unless created with either DNS_DB_NSEC3ONLY
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_seek(dns_dbiterator_t *iterator,
|
||||||
|
const dns_name_t *name DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
||||||
|
dns_name_t *name DNS__DB_FLARG);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_pause(dns_dbiterator_t *iterator);
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
|
||||||
|
|
||||||
|
static dns_dbiteratormethods_t dbiterator_methods = {
|
||||||
|
dbiterator_destroy, dbiterator_first, dbiterator_last,
|
||||||
|
dbiterator_seek, dbiterator_prev, dbiterator_next,
|
||||||
|
dbiterator_current, dbiterator_pause, dbiterator_origin
|
||||||
|
};
|
||||||
|
|
||||||
|
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 */
|
||||||
|
qpdata_t *node;
|
||||||
|
enum { full, nonsec3, nsec3only } nsec3mode;
|
||||||
|
} qpdb_dbiterator_t;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
prio_type(dns_typepair_t type) {
|
prio_type(dns_typepair_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -1023,6 +1097,20 @@ currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
|
|||||||
*versionp = (dns_dbversion_t *)version;
|
*versionp = (dns_dbversion_t *)version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
attachversion(dns_db_t *db, dns_dbversion_t *source,
|
||||||
|
dns_dbversion_t **targetp) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||||
|
qpdb_version_t *version = source;
|
||||||
|
|
||||||
|
REQUIRE(VALID_QPZONE(qpdb));
|
||||||
|
INSIST(version != NULL && version->qpdb == qpdb);
|
||||||
|
|
||||||
|
isc_refcount_increment(&version->references);
|
||||||
|
|
||||||
|
*targetp = version;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
||||||
bool commit ISC_ATTR_UNUSED DNS__DB_FLARG) {
|
bool commit ISC_ATTR_UNUSED DNS__DB_FLARG) {
|
||||||
@@ -3282,6 +3370,60 @@ tree_exit:
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
allrdatasets(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
|
||||||
|
unsigned int options, isc_stdtime_t now,
|
||||||
|
dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||||
|
qpdata_t *node = (qpdata_t *)dbnode;
|
||||||
|
qpdb_version_t *version = dbversion;
|
||||||
|
qpdb_rdatasetiter_t *iterator = NULL;
|
||||||
|
uint_fast32_t refs;
|
||||||
|
|
||||||
|
REQUIRE(VALID_QPZONE(qpdb));
|
||||||
|
|
||||||
|
iterator = isc_mem_get(qpdb->common.mctx, sizeof(*iterator));
|
||||||
|
|
||||||
|
if ((db->attributes & DNS_DBATTR_CACHE) == 0) {
|
||||||
|
now = 0;
|
||||||
|
if (version == NULL) {
|
||||||
|
currentversion(db,
|
||||||
|
(dns_dbversion_t **)(void *)(&version));
|
||||||
|
} else {
|
||||||
|
INSIST(version->qpdb == qpdb);
|
||||||
|
|
||||||
|
(void)isc_refcount_increment(&version->references);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (now == 0) {
|
||||||
|
now = isc_stdtime_now();
|
||||||
|
}
|
||||||
|
version = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator->common.magic = DNS_RDATASETITER_MAGIC;
|
||||||
|
iterator->common.methods = &rdatasetiter_methods;
|
||||||
|
iterator->common.db = db;
|
||||||
|
iterator->common.node = node;
|
||||||
|
iterator->common.version = (dns_dbversion_t *)version;
|
||||||
|
iterator->common.options = options;
|
||||||
|
iterator->common.now = now;
|
||||||
|
|
||||||
|
refs = isc_refcount_increment(&node->references);
|
||||||
|
#if DNS_DB_NODETRACE
|
||||||
|
fprintf(stderr, "incr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n",
|
||||||
|
func, file, line, node, refs + 1);
|
||||||
|
#else
|
||||||
|
UNUSED(refs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
iterator->current = NULL;
|
||||||
|
|
||||||
|
*iteratorp = (dns_rdatasetiter_t *)iterator;
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
attachnode(dns_db_t *db, dns_dbnode_t *source,
|
attachnode(dns_db_t *db, dns_dbnode_t *source,
|
||||||
dns_dbnode_t **targetp DNS__DB_FLARG) {
|
dns_dbnode_t **targetp DNS__DB_FLARG) {
|
||||||
@@ -3401,6 +3543,602 @@ deletedata(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *node ISC_ATTR_UNUSED,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rdataset Iterator Methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
|
||||||
|
qpdb_rdatasetiter_t *qrditer = NULL;
|
||||||
|
|
||||||
|
qrditer = (qpdb_rdatasetiter_t *)(*iteratorp);
|
||||||
|
|
||||||
|
if (qrditer->common.version != NULL) {
|
||||||
|
closeversion(qrditer->common.db, &qrditer->common.version,
|
||||||
|
false DNS__DB_FLARG_PASS);
|
||||||
|
}
|
||||||
|
dns__db_detachnode(qrditer->common.db,
|
||||||
|
&qrditer->common.node DNS__DB_FLARG_PASS);
|
||||||
|
isc_mem_put(qrditer->common.db->mctx, qrditer, sizeof(*qrditer));
|
||||||
|
|
||||||
|
*iteratorp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
iterator_active(qpzonedb_t *qpdb ISC_ATTR_UNUSED,
|
||||||
|
qpdb_rdatasetiter_t *qrditer ISC_ATTR_UNUSED,
|
||||||
|
dns_slabheader_t *header ISC_ATTR_UNUSED) {
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
|
||||||
|
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
|
||||||
|
qpdata_t *node = qrditer->common.node;
|
||||||
|
dns_slabheader_t *header = NULL, *top_next = NULL;
|
||||||
|
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||||
|
|
||||||
|
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
|
||||||
|
for (header = node->data; header != NULL; header = top_next) {
|
||||||
|
top_next = header->next;
|
||||||
|
do {
|
||||||
|
if (header->serial <= 1 && !IGNORE(header)) {
|
||||||
|
if (!iterator_active(qpdb, qrditer, header)) {
|
||||||
|
header = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
header = header->down;
|
||||||
|
}
|
||||||
|
} while (header != NULL);
|
||||||
|
if (header != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
|
||||||
|
qrditer->current = header;
|
||||||
|
|
||||||
|
if (header == NULL) {
|
||||||
|
return (ISC_R_NOMORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
|
||||||
|
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
|
||||||
|
qpdata_t *node = qrditer->common.node;
|
||||||
|
dns_slabheader_t *header = NULL, *top_next = NULL;
|
||||||
|
dns_typepair_t type, negtype;
|
||||||
|
dns_rdatatype_t rdtype, covers;
|
||||||
|
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||||
|
|
||||||
|
header = qrditer->current;
|
||||||
|
if (header == NULL) {
|
||||||
|
return (ISC_R_NOMORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
|
||||||
|
type = header->type;
|
||||||
|
rdtype = DNS_TYPEPAIR_TYPE(header->type);
|
||||||
|
if (NEGATIVE(header)) {
|
||||||
|
covers = DNS_TYPEPAIR_COVERS(header->type);
|
||||||
|
negtype = DNS_TYPEPAIR_VALUE(covers, 0);
|
||||||
|
} else {
|
||||||
|
negtype = DNS_TYPEPAIR_VALUE(0, rdtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the start of the header chain for the next type
|
||||||
|
* by walking back up the list.
|
||||||
|
*/
|
||||||
|
top_next = header->next;
|
||||||
|
while (top_next != NULL &&
|
||||||
|
(top_next->type == type || top_next->type == negtype))
|
||||||
|
{
|
||||||
|
top_next = top_next->next;
|
||||||
|
}
|
||||||
|
for (header = top_next; header != NULL; header = top_next) {
|
||||||
|
top_next = header->next;
|
||||||
|
do {
|
||||||
|
if (header->serial <= 1 && !IGNORE(header)) {
|
||||||
|
if (!iterator_active(qpdb, qrditer, header)) {
|
||||||
|
header = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
header = header->down;
|
||||||
|
}
|
||||||
|
} while (header != NULL);
|
||||||
|
if (header != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Find the start of the header chain for the next type
|
||||||
|
* by walking back up the list.
|
||||||
|
*/
|
||||||
|
while (top_next != NULL &&
|
||||||
|
(top_next->type == type || top_next->type == negtype))
|
||||||
|
{
|
||||||
|
top_next = top_next->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
|
||||||
|
qrditer->current = header;
|
||||||
|
|
||||||
|
if (header == NULL) {
|
||||||
|
return (ISC_R_NOMORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdatasetiter_current(dns_rdatasetiter_t *iterator,
|
||||||
|
dns_rdataset_t *rdataset DNS__DB_FLARG) {
|
||||||
|
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
|
||||||
|
qpdata_t *node = qrditer->common.node;
|
||||||
|
dns_slabheader_t *header = NULL;
|
||||||
|
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||||
|
|
||||||
|
header = qrditer->current;
|
||||||
|
REQUIRE(header != NULL);
|
||||||
|
|
||||||
|
NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
|
||||||
|
bindrdataset(qpdb, node, header, qrditer->common.now,
|
||||||
|
rdataset DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Database Iterator Methods
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
reference_iter_node(qpdb_dbiterator_t *iter DNS__DB_FLARG) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iter->common.db;
|
||||||
|
qpdata_t *node = iter->node;
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
newref(qpdb, node DNS__DB_FLARG_PASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dereference_iter_node(qpdb_dbiterator_t *iter DNS__DB_FLARG) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iter->common.db;
|
||||||
|
qpdata_t *node = iter->node;
|
||||||
|
isc_rwlock_t *lock = NULL;
|
||||||
|
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock = &qpdb->node_locks[node->locknum].lock;
|
||||||
|
NODE_RDLOCK(lock, &nlocktype);
|
||||||
|
decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
|
||||||
|
NODE_UNLOCK(lock, &nlocktype);
|
||||||
|
iter->node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) {
|
||||||
|
qpdb_dbiterator_t *iter = (qpdb_dbiterator_t *)(*iteratorp);
|
||||||
|
dns_db_t *db = NULL;
|
||||||
|
|
||||||
|
dereference_iter_node(iter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
dns_db_attach(iter->common.db, &db);
|
||||||
|
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);
|
||||||
|
|
||||||
|
isc_mem_put(db->mctx, iter, sizeof(*iter));
|
||||||
|
dns_db_detach(&db);
|
||||||
|
|
||||||
|
*iteratorp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) {
|
||||||
|
isc_result_t result;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS &&
|
||||||
|
qpdbiter->result != ISC_R_NOTFOUND &&
|
||||||
|
qpdbiter->result != DNS_R_PARTIALMATCH &&
|
||||||
|
qpdbiter->result != ISC_R_NOMORE)
|
||||||
|
{
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
(void **)&qpdbiter->node,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
} else {
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
}
|
||||||
|
qpdbiter->result = result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) {
|
||||||
|
isc_result_t result;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS &&
|
||||||
|
qpdbiter->result != ISC_R_NOTFOUND &&
|
||||||
|
qpdbiter->result != DNS_R_PARTIALMATCH &&
|
||||||
|
qpdbiter->result != ISC_R_NOMORE)
|
||||||
|
{
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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) &&
|
||||||
|
QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* NSEC3 tree only has an origin node.
|
||||||
|
*/
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
result = ISC_R_NOMORE;
|
||||||
|
}
|
||||||
|
if (result == ISC_R_NOMORE) {
|
||||||
|
qpdbiter->current = &qpdbiter->mainiter;
|
||||||
|
dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
|
||||||
|
result = dns_qpiter_prev(qpdbiter->current, NULL,
|
||||||
|
(void **)&qpdbiter->node,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
} else {
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
}
|
||||||
|
qpdbiter->result = result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_seek(dns_dbiterator_t *iterator,
|
||||||
|
const dns_name_t *name DNS__DB_FLARG) {
|
||||||
|
isc_result_t result, tresult;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS &&
|
||||||
|
qpdbiter->result != ISC_R_NOTFOUND &&
|
||||||
|
qpdbiter->result != DNS_R_PARTIALMATCH &&
|
||||||
|
qpdbiter->result != ISC_R_NOMORE)
|
||||||
|
{
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
switch (qpdbiter->nsec3mode) {
|
||||||
|
case nsec3only:
|
||||||
|
qpdbiter->current = &qpdbiter->nsec3iter;
|
||||||
|
result = dns_qp_lookup(qpdbiter->nsnap, name, NULL,
|
||||||
|
qpdbiter->current, NULL,
|
||||||
|
(void **)&qpdbiter->node, NULL);
|
||||||
|
break;
|
||||||
|
case nonsec3:
|
||||||
|
qpdbiter->current = &qpdbiter->mainiter;
|
||||||
|
result = dns_qp_lookup(qpdbiter->tsnap, name, NULL,
|
||||||
|
qpdbiter->current, 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,
|
||||||
|
(void **)&qpdbiter->node, NULL);
|
||||||
|
if (result == DNS_R_PARTIALMATCH) {
|
||||||
|
dns_qpdata_t *node = NULL;
|
||||||
|
tresult = dns_qp_lookup(qpdbiter->nsnap, name, NULL,
|
||||||
|
&qpdbiter->nsec3iter, NULL,
|
||||||
|
(void **)&node, NULL);
|
||||||
|
if (tresult == ISC_R_SUCCESS) {
|
||||||
|
qpdbiter->current = &qpdbiter->nsec3iter;
|
||||||
|
result = tresult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
||||||
|
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
} else {
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qpdbiter->result = (result == DNS_R_PARTIALMATCH) ? ISC_R_SUCCESS
|
||||||
|
: result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) {
|
||||||
|
isc_result_t result;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
|
||||||
|
|
||||||
|
REQUIRE(qpdbiter->node != NULL);
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS) {
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
result = dns_qpiter_prev(qpdbiter->current, 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.
|
||||||
|
*/
|
||||||
|
if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
|
||||||
|
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,
|
||||||
|
(void **)&qpdbiter->node,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
} else {
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qpdbiter->result = result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) {
|
||||||
|
isc_result_t result;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
|
||||||
|
|
||||||
|
REQUIRE(qpdbiter->node != NULL);
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS) {
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
result = dns_qpiter_next(qpdbiter->current, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
/*
|
||||||
|
* If we've just started the NSEC3 tree,
|
||||||
|
* skip over the origin.
|
||||||
|
*/
|
||||||
|
if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
|
||||||
|
switch (qpdbiter->nsec3mode) {
|
||||||
|
case nsec3only:
|
||||||
|
case full:
|
||||||
|
result = dns_qpiter_next(
|
||||||
|
qpdbiter->current, NULL,
|
||||||
|
(void **)&qpdbiter->node, NULL);
|
||||||
|
break;
|
||||||
|
case nonsec3:
|
||||||
|
result = ISC_R_NOMORE;
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
|
||||||
|
} else {
|
||||||
|
qpdbiter->node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qpdbiter->result = result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
|
||||||
|
dns_name_t *name DNS__DB_FLARG) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
qpdata_t *node = qpdbiter->node;
|
||||||
|
|
||||||
|
REQUIRE(qpdbiter->result == ISC_R_SUCCESS);
|
||||||
|
REQUIRE(qpdbiter->node != NULL);
|
||||||
|
|
||||||
|
if (name != NULL) {
|
||||||
|
dns_name_copy(qpdbiter->node->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
newref(qpdb, node DNS__DB_FLARG_PASS);
|
||||||
|
|
||||||
|
*nodep = qpdbiter->node;
|
||||||
|
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_pause(dns_dbiterator_t *iterator ISC_ATTR_UNUSED) {
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
|
||||||
|
qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
|
||||||
|
|
||||||
|
if (qpdbiter->result != ISC_R_SUCCESS) {
|
||||||
|
return (qpdbiter->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_name_copy(dns_rootname, name);
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
createiterator(dns_db_t *db, unsigned int options,
|
||||||
|
dns_dbiterator_t **iteratorp) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||||
|
qpdb_dbiterator_t *iter = NULL;
|
||||||
|
|
||||||
|
REQUIRE(VALID_QPZONE(qpdb));
|
||||||
|
|
||||||
|
iter = isc_mem_get(qpdb->common.mctx, sizeof(*iter));
|
||||||
|
*iter = (qpdb_dbiterator_t){
|
||||||
|
.common.magic = DNS_DBITERATOR_MAGIC,
|
||||||
|
.common.methods = &dbiterator_methods,
|
||||||
|
.common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
|
||||||
|
0),
|
||||||
|
};
|
||||||
|
|
||||||
|
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->nsec3, &iter->nsnap);
|
||||||
|
dns_qpiter_init(iter->nsnap, &iter->nsec3iter);
|
||||||
|
|
||||||
|
*iteratorp = (dns_dbiterator_t *)iter;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
static dns_dbmethods_t qpdb_zonemethods = {
|
static dns_dbmethods_t qpdb_zonemethods = {
|
||||||
.destroy = qpdb_destroy,
|
.destroy = qpdb_destroy,
|
||||||
.beginload = beginload,
|
.beginload = beginload,
|
||||||
@@ -3408,12 +4146,15 @@ static dns_dbmethods_t qpdb_zonemethods = {
|
|||||||
.setloop = setloop,
|
.setloop = setloop,
|
||||||
.currentversion = currentversion,
|
.currentversion = currentversion,
|
||||||
.closeversion = closeversion,
|
.closeversion = closeversion,
|
||||||
|
.attachversion = attachversion,
|
||||||
.findrdataset = findrdataset,
|
.findrdataset = findrdataset,
|
||||||
.findnode = findnode,
|
.findnode = findnode,
|
||||||
.find = find,
|
.find = find,
|
||||||
.attachnode = attachnode,
|
.attachnode = attachnode,
|
||||||
.detachnode = detachnode,
|
.detachnode = detachnode,
|
||||||
|
.createiterator = createiterator,
|
||||||
.getoriginnode = getoriginnode,
|
.getoriginnode = getoriginnode,
|
||||||
|
.allrdatasets = allrdatasets,
|
||||||
.deletedata = deletedata,
|
.deletedata = deletedata,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -95,9 +95,6 @@ test_walk(const char *filename, int flags, int nodes) {
|
|||||||
result = dns_dbiterator_next(iter))
|
result = dns_dbiterator_next(iter))
|
||||||
{
|
{
|
||||||
result = dns_dbiterator_current(iter, &node, name);
|
result = dns_dbiterator_current(iter, &node, name);
|
||||||
if (result == DNS_R_NEWORIGIN) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
dns_db_detachnode(db, &node);
|
dns_db_detachnode(db, &node);
|
||||||
i++;
|
i++;
|
||||||
@@ -152,9 +149,6 @@ test_reverse(const char *filename, int flags, int nodes) {
|
|||||||
result = dns_dbiterator_prev(iter))
|
result = dns_dbiterator_prev(iter))
|
||||||
{
|
{
|
||||||
result = dns_dbiterator_current(iter, &node, name);
|
result = dns_dbiterator_current(iter, &node, name);
|
||||||
if (result == DNS_R_NEWORIGIN) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
dns_db_detachnode(db, &node);
|
dns_db_detachnode(db, &node);
|
||||||
i++;
|
i++;
|
||||||
@@ -219,9 +213,6 @@ test_seek_node(const char *filename, int flags, int nodes) {
|
|||||||
|
|
||||||
while (result == ISC_R_SUCCESS) {
|
while (result == ISC_R_SUCCESS) {
|
||||||
result = dns_dbiterator_current(iter, &node, name);
|
result = dns_dbiterator_current(iter, &node, name);
|
||||||
if (result == DNS_R_NEWORIGIN) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
dns_db_detachnode(db, &node);
|
dns_db_detachnode(db, &node);
|
||||||
result = dns_dbiterator_next(iter);
|
result = dns_dbiterator_next(iter);
|
||||||
@@ -244,9 +235,6 @@ test_seek_node(const char *filename, int flags, int nodes) {
|
|||||||
|
|
||||||
while (result == ISC_R_SUCCESS) {
|
while (result == ISC_R_SUCCESS) {
|
||||||
result = dns_dbiterator_current(iter, &node, name);
|
result = dns_dbiterator_current(iter, &node, name);
|
||||||
if (result == DNS_R_NEWORIGIN) {
|
|
||||||
result = ISC_R_SUCCESS;
|
|
||||||
}
|
|
||||||
assert_int_equal(result, ISC_R_SUCCESS);
|
assert_int_equal(result, ISC_R_SUCCESS);
|
||||||
dns_db_detachnode(db, &node);
|
dns_db_detachnode(db, &node);
|
||||||
result = dns_dbiterator_prev(iter);
|
result = dns_dbiterator_prev(iter);
|
||||||
|
Reference in New Issue
Block a user