diff --git a/lib/dns/qp-cachedb.c b/lib/dns/qp-cachedb.c index 8e55b7d1f2..b063ad7a2a 100644 --- a/lib/dns/qp-cachedb.c +++ b/lib/dns/qp-cachedb.c @@ -497,26 +497,25 @@ find_deepest_zonecut(qpdb_search_t *search, dns_rbtnode_t *node, dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset DNS__DB_FLARG) { - unsigned int i; isc_result_t result = ISC_R_NOTFOUND; - dns_name_t name; dns_qpdb_t *qpdb = NULL; - bool done; /* * Caller must be holding the tree lock. */ qpdb = search->qpdb; - i = search->chain.level_matches; - done = false; - do { + + for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) { dns_slabheader_t *header = NULL; dns_slabheader_t *header_prev = NULL, *header_next = NULL; dns_slabheader_t *found = NULL, *foundsig = NULL; - isc_rwlock_t *lock = &qpdb->node_locks[node->locknum].lock; + isc_rwlock_t *lock = NULL; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; + dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL); + lock = &qpdb->node_locks[node->locknum].lock; + NODE_RDLOCK(lock, &nlocktype); /* @@ -556,31 +555,10 @@ find_deepest_zonecut(qpdb_search_t *search, dns_rbtnode_t *node, if (found != NULL) { /* * If we have to set foundname, we do it before - * anything else. If we were to set foundname after - * we had set nodep or bound the rdataset, then we'd - * have to undo that work if dns_name_concatenate() - * failed. By setting foundname first, there's - * nothing to undo if we have trouble. + * anything else. */ if (foundname != NULL) { - dns_name_init(&name, NULL); - dns_rbt_namefromnode(node, &name); - dns_name_copy(&name, foundname); - while (i > 0) { - dns_rbtnode_t *level_node = - search->chain.levels[--i]; - dns_name_init(&name, NULL); - dns_rbt_namefromnode(level_node, &name); - result = dns_name_concatenate( - foundname, &name, foundname, - NULL); - if (result != ISC_R_SUCCESS) { - if (nodep != NULL) { - *nodep = NULL; - } - goto node_exit; - } - } + dns_name_copy(node->name, foundname); } result = DNS_R_DELEGATION; if (nodep != NULL) { @@ -618,16 +596,12 @@ find_deepest_zonecut(qpdb_search_t *search, dns_rbtnode_t *node, } } - node_exit: NODE_UNLOCK(lock, &nlocktype); - if (found == NULL && i > 0) { - i--; - node = search->chain.levels[i]; - } else { - done = true; + if (found != NULL) { + break; } - } while (!done); + } return (result); } @@ -644,11 +618,10 @@ find_coveringnsec(qpdb_search_t *search, const dns_name_t *name, dns_dbnode_t **nodep, isc_stdtime_t now, dns_name_t *foundname, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset DNS__DB_FLARG) { - dns_fixedname_t fprefix, forigin, ftarget, fixed; - dns_name_t *prefix = NULL, *origin = NULL; - dns_name_t *target = NULL, *fname = NULL; + dns_fixedname_t fpredecessor, fixed; + dns_name_t *predecessor = NULL, *fname = NULL; dns_rbtnode_t *node = NULL; - dns_rbtnodechain_t chain; + dns_qpiter_t iter; isc_result_t result; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; isc_rwlock_t *lock = NULL; @@ -660,43 +633,31 @@ find_coveringnsec(qpdb_search_t *search, const dns_name_t *name, /* * Look for the node in the auxilary tree. */ - dns_rbtnodechain_init(&chain); - target = dns_fixedname_initname(&ftarget); - result = dns_qp_lookup(search->qpdb->nsec, name, target, NULL, &chain, + result = dns_qp_lookup(search->qpdb->nsec, name, NULL, &iter, NULL, (void **)&node, NULL); if (result != DNS_R_PARTIALMATCH) { - dns_rbtnodechain_reset(&chain); return (ISC_R_NOTFOUND); } - prefix = dns_fixedname_initname(&fprefix); - origin = dns_fixedname_initname(&forigin); - target = dns_fixedname_initname(&ftarget); fname = dns_fixedname_initname(&fixed); - + predecessor = dns_fixedname_initname(&fpredecessor); matchtype = DNS_TYPEPAIR_VALUE(dns_rdatatype_nsec, 0); sigmatchtype = DNS_SIGTYPE(dns_rdatatype_nsec); /* - * Extract predecessor from chain. + * Extract predecessor from iterator. */ - result = dns_rbtnodechain_current(&chain, prefix, origin, NULL); - dns_rbtnodechain_reset(&chain); + result = dns_qpiter_current(&iter, predecessor, NULL, NULL); if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { return (ISC_R_NOTFOUND); } - result = dns_name_concatenate(prefix, origin, target, NULL); - if (result != ISC_R_SUCCESS) { - return (ISC_R_NOTFOUND); - } - /* * Lookup the predecessor in the main tree. */ node = NULL; - result = dns_qp_lookup(search->qpdb->tree, target, fname, NULL, NULL, - (void **)&node, NULL); + result = dns_qp_lookup(search->qpdb->tree, predecessor, fname, NULL, + NULL, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { return (ISC_R_NOTFOUND); } @@ -790,7 +751,6 @@ cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, .now = now, }; dns_fixedname_init(&search.zonecut_name); - dns_rbtnodechain_init(&search.chain); TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype); @@ -1193,8 +1153,6 @@ tree_exit: INSIST(tlocktype == isc_rwlocktype_none); } - dns_rbtnodechain_reset(&search.chain); - update_cachestats(search.qpdb, result); return (result); } @@ -1229,7 +1187,6 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, .now = now, }; dns_fixedname_init(&search.zonecut_name); - dns_rbtnodechain_init(&search.chain); if (dcnull) { dcname = foundname; @@ -1369,8 +1326,6 @@ tree_exit: INSIST(!search.need_cleanup); - dns_rbtnodechain_reset(&search.chain); - if (result == DNS_R_DELEGATION) { result = ISC_R_SUCCESS; } diff --git a/lib/dns/qp-zonedb.c b/lib/dns/qp-zonedb.c index e70a05ca28..e9f77f9f88 100644 --- a/lib/dns/qp-zonedb.c +++ b/lib/dns/qp-zonedb.c @@ -321,11 +321,10 @@ typedef enum { FORWARD, BACK } direction_t; * Return true if we found a predecessor or successor. */ static bool -step(qpdb_search_t *search, dns_rbtnodechain_t *chain, direction_t direction, +step(qpdb_search_t *search, dns_qpiter_t *iter, direction_t direction, dns_name_t *nextname) { - dns_fixedname_t forigin; - dns_name_t *origin = NULL; - dns_name_t prefix; + dns_fixedname_t fnodename; + dns_name_t *nodename = dns_fixedname_initname(&fnodename); dns_qpdb_t *qpdb = NULL; dns_rbtnode_t *node = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -333,17 +332,11 @@ step(qpdb_search_t *search, dns_rbtnodechain_t *chain, direction_t direction, qpdb = search->qpdb; - dns_name_init(&prefix, NULL); - origin = dns_fixedname_initname(&forigin); + result = dns_qpiter_current(iter, nodename, (void **)&node, NULL); while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { isc_rwlocktype_t nlocktype = isc_rwlocktype_none; - node = NULL; - result = dns_rbtnodechain_current(chain, &prefix, origin, - &node); - if (result != ISC_R_SUCCESS) { - break; - } + NODE_RDLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype); for (header = node->data; header != NULL; header = header->next) @@ -359,16 +352,19 @@ step(qpdb_search_t *search, dns_rbtnodechain_t *chain, direction_t direction, if (header != NULL) { break; } + if (direction == FORWARD) { - result = dns_rbtnodechain_next(chain, NULL, NULL); + result = dns_qpiter_next(iter, nodename, (void **)&node, + NULL); } else { - result = dns_rbtnodechain_prev(chain, NULL, NULL); + result = dns_qpiter_prev(iter, nodename, (void **)&node, + NULL); } }; if (result == ISC_R_SUCCESS) { - result = dns_name_concatenate(&prefix, origin, nextname, NULL); - } - if (result == ISC_R_SUCCESS) { + if (nextname != NULL) { + dns_name_copy(nodename, nextname); + } return (true); } return (false); @@ -381,17 +377,17 @@ step(qpdb_search_t *search, dns_rbtnodechain_t *chain, direction_t direction, * of the database. */ static bool -activeempty(qpdb_search_t *search, dns_rbtnodechain_t *chain, +activeempty(qpdb_search_t *search, dns_qpiter_t *iter, const dns_name_t *current) { isc_result_t result; dns_fixedname_t fnext; dns_name_t *next = dns_fixedname_initname(&fnext); - result = dns_rbtnodechain_next(chain, NULL, NULL); + result = dns_qpiter_next(iter, NULL, NULL, NULL); if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { return (false); } - return (step(search, chain, FORWARD, next) && + return (step(search, iter, FORWARD, next) && dns_name_issubdomain(next, current)); } @@ -405,7 +401,7 @@ wildcard_blocked(qpdb_search_t *search, const dns_name_t *qname, dns_name_t name; dns_name_t rname; dns_name_t tname; - dns_rbtnodechain_t chain; + dns_qpiter_t iter; bool check_next = false; bool check_prev = false; unsigned int n; @@ -421,20 +417,20 @@ wildcard_blocked(qpdb_search_t *search, const dns_name_t *qname, * need to find out if there's an empty nonterminal node * between the wildcard level and the qname. * - * search->chain should now be pointing at the predecessor + * search->iter should now be pointing at the predecessor * of the searched-for name. We are using a local copy of the - * chain so as not to change the state of search->chain. + * iterator so as not to change the state of search->iter. * step() will walk backward until we find a predecessor with * data. */ - chain = search->chain; - check_prev = step(search, &chain, BACK, prev); + iter = search->iter; + check_prev = step(search, &iter, BACK, prev); - /* Now reset the chain and look for a successor with data. */ - chain = search->chain; - result = dns_rbtnodechain_next(&chain, NULL, NULL); + /* Now reset the iterator and look for a successor with data. */ + iter = search->iter; + result = dns_qpiter_next(&iter, NULL, NULL, NULL); if (result == ISC_R_SUCCESS) { - check_next = step(search, &chain, FORWARD, next); + check_next = step(search, &iter, FORWARD, next); } if (!check_prev && !check_next) { @@ -470,12 +466,10 @@ wildcard_blocked(qpdb_search_t *search, const dns_name_t *qname, static isc_result_t find_wildcard(qpdb_search_t *search, dns_rbtnode_t **nodep, const dns_name_t *qname) { - unsigned int i, j; - dns_rbtnode_t *node = NULL, *level_node = NULL; dns_slabheader_t *header = NULL; isc_result_t result = ISC_R_NOTFOUND; dns_qpdb_t *qpdb = NULL; - bool done, wild, active; + bool wild, active; /* * Caller must be holding the tree lock and MUST NOT be holding @@ -493,14 +487,15 @@ find_wildcard(qpdb_search_t *search, dns_rbtnode_t **nodep, */ qpdb = search->qpdb; - i = search->chain.level_matches; - done = false; - node = *nodep; - do { - isc_rwlock_t *lock = &qpdb->node_locks[node->locknum].lock; + for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) { + dns_rbtnode_t *node = NULL; + isc_rwlock_t *lock = NULL; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; - NODE_RDLOCK(lock, &nlocktype); + dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL); + lock = &qpdb->node_locks[node->locknum].lock; + + NODE_RDLOCK(lock, &nlocktype); /* * First we try to figure out if this node is active in * the search's version. We do this now, even though we @@ -516,52 +511,29 @@ find_wildcard(qpdb_search_t *search, dns_rbtnode_t **nodep, break; } } - if (header != NULL) { - active = true; - } else { - active = false; - } - - if (node->wild) { - wild = true; - } else { - wild = false; - } - + active = (header != NULL); + wild = node->wild; NODE_UNLOCK(lock, &nlocktype); if (wild) { - dns_name_t *wname = NULL; - dns_fixedname_t fwname; dns_rbtnode_t *wnode = NULL; - dns_qpiter_t wchain; + dns_fixedname_t fwname; + dns_name_t *wname = NULL; + dns_qpiter_t witer; /* * Construct the wildcard name for this level. */ - dns_name_init(&name, NULL); - dns_rbt_namefromnode(node, &name); wname = dns_fixedname_initname(&fwname); - result = dns_name_concatenate(dns_wildcardname, &name, - wname, NULL); - j = i; - while (result == ISC_R_SUCCESS && j != 0) { - j--; - level_node = search->chain.levels[j]; - dns_name_init(&name, NULL); - dns_rbt_namefromnode(level_node, &name); - result = dns_name_concatenate(wname, &name, - wname, NULL); - } + result = dns_name_concatenate(dns_wildcardname, + node->name, wname, NULL); if (result != ISC_R_SUCCESS) { break; } wnode = NULL; - dns_rbtnodechain_init(&wchain); - - result = dns_qp_lookup(qpdb->tree, wname, NULL, NULL, - &wchain, (void **)&wnode, NULL); + result = dns_qp_lookup(qpdb->tree, wname, NULL, &witer, + NULL, (void **)&wnode, NULL); if (result == ISC_R_SUCCESS) { /* * We have found the wildcard node. If it @@ -582,7 +554,7 @@ find_wildcard(qpdb_search_t *search, dns_rbtnode_t **nodep, } NODE_UNLOCK(lock, &nlocktype); if (header != NULL || - activeempty(search, &wchain, wname)) + activeempty(search, &witer, wname)) { if (wildcard_blocked(search, qname, wname)) @@ -617,14 +589,7 @@ find_wildcard(qpdb_search_t *search, dns_rbtnode_t **nodep, result = ISC_R_NOTFOUND; break; } - - if (i > 0) { - i--; - node = search->chain.levels[i]; - } else { - done = true; - } - } while (!done); + } return (result); } @@ -673,7 +638,7 @@ matchparams(dns_slabheader_t *header, qpdb_search_t *search) { static isc_result_t previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, dns_name_t *name, dns_name_t *origin, - dns_rbtnode_t **nodep, dns_rbtnodechain_t *nsecchain, + dns_rbtnode_t **nodep, dns_qpiter_t *nseciter, bool *firstp) { dns_fixedname_t ftarget; dns_name_t *target = NULL; @@ -684,13 +649,8 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, REQUIRE(type == dns_rdatatype_nsec3 || firstp != NULL); if (type == dns_rdatatype_nsec3) { - result = dns_rbtnodechain_prev(&search->chain, NULL, NULL); - if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { - return (result); - } - result = dns_rbtnodechain_current(&search->chain, name, origin, - nodep); - return (result); + return (dns_qpiter_prev(&search->iter, name, (void **)nodep, + NULL)); } target = dns_fixedname_initname(&ftarget); @@ -702,7 +662,6 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, * It is the first node sought in the NSEC tree. */ *firstp = false; - dns_rbtnodechain_init(nsecchain); result = dns_name_concatenate(name, origin, target, NULL); if (result != ISC_R_SUCCESS) { @@ -710,7 +669,7 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, } nsecnode = NULL; result = dns_qp_lookup(search->qpdb->nsec, name, NULL, - NULL, nsecchain, + nseciter, NULL, (void **)&nsecnode, NULL); if (result == ISC_R_SUCCESS) { /* @@ -720,8 +679,8 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, * unacceptable NSEC record. * Try the previous node in the NSEC tree. */ - result = dns_rbtnodechain_prev(nsecchain, name, - origin); + result = dns_qpiter_prev(nseciter, name, NULL, + NULL); if (result == DNS_R_NEWORIGIN) { result = ISC_R_SUCCESS; } @@ -729,11 +688,8 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, result == DNS_R_PARTIALMATCH) { /* The iterator is already where we want it */ - result = dns_rbtnodechain_current( - nsecchain, name, origin, NULL); - if (result == ISC_R_NOTFOUND) { - result = ISC_R_NOMORE; - } + result = dns_qpiter_current(nseciter, name, + NULL, NULL); } } else { /* @@ -743,7 +699,7 @@ previous_closest_nsec(dns_rdatatype_t type, qpdb_search_t *search, * must have found nodes in the main tree with NSEC * records. Perhaps they lacked signature records. */ - result = dns_rbtnodechain_prev(nsecchain, name, origin); + result = dns_qpiter_prev(nseciter, name, NULL, NULL); if (result == DNS_R_NEWORIGIN) { result = ISC_R_SUCCESS; } @@ -787,7 +743,7 @@ find_closest_nsec(qpdb_search_t *search, dns_dbnode_t **nodep, bool secure DNS__DB_FLARG) { dns_rbtnode_t *node = NULL, *prevnode = NULL; dns_slabheader_t *header = NULL, *header_next = NULL; - dns_rbtnodechain_t nsecchain; + dns_qpiter_t nseciter; bool empty_node; isc_result_t result; dns_fixedname_t fname, forigin; @@ -814,13 +770,13 @@ find_closest_nsec(qpdb_search_t *search, dns_dbnode_t **nodep, */ name = dns_fixedname_initname(&fname); origin = dns_fixedname_initname(&forigin); -again: - node = NULL; - prevnode = NULL; - result = dns_rbtnodechain_current(&search->chain, name, origin, &node); + + result = dns_qpiter_current(&search->iter, name, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { return (result); } + +again: do { dns_slabheader_t *found = NULL, *foundsig = NULL; isc_rwlocktype_t nlocktype = isc_rwlocktype_none; @@ -926,7 +882,7 @@ again: empty_node = true; result = previous_closest_nsec( type, search, name, origin, &prevnode, - &nsecchain, &first); + &nseciter, &first); } else { /* * We found an active node, but either the @@ -942,7 +898,7 @@ again: */ result = previous_closest_nsec(type, search, name, origin, &prevnode, - &nsecchain, &first); + &nseciter, &first); } NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock), &nlocktype); @@ -950,13 +906,9 @@ again: prevnode = NULL; } while (empty_node && result == ISC_R_SUCCESS); - if (!first) { - dns_rbtnodechain_invalidate(&nsecchain); - } - if (result == ISC_R_NOMORE && wraps) { - result = dns_rbtnodechain_last(&search->chain, tree, NULL, - NULL); + result = dns_qpiter_prev(&search->iter, name, (void **)&node, + NULL); if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { wraps = false; goto again; @@ -1020,7 +972,6 @@ zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, .options = options, }; dns_fixedname_init(&search.zonecut_name); - dns_rbtnodechain_init(&search.chain); TREE_RDLOCK(&search.qpdb->tree_lock, &tlocktype); @@ -1095,8 +1046,8 @@ zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, * The NSEC3 tree won't have empty nodes, * so it isn't necessary to check for them. */ - dns_rbtnodechain_t chain = search.chain; - active = activeempty(&search, &chain, name); + dns_qpiter_t iter = search.iter; + active = activeempty(&search, &iter, name); } /* @@ -1511,8 +1462,6 @@ tree_exit: dns__qpdb_closeversion(db, &version, false DNS__DB_FLARG_PASS); } - dns_rbtnodechain_reset(&search.chain); - return (result); } diff --git a/lib/dns/qpdb.c b/lib/dns/qpdb.c index f0a43b54d9..40991dcaa8 100644 --- a/lib/dns/qpdb.c +++ b/lib/dns/qpdb.c @@ -131,8 +131,8 @@ #define KEEPSTALE(qpdb) ((qpdb)->common.serve_stale_ttl > 0) -#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \ - ((iterator)->current == &(iterator)->nsec3chain && \ +#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \ + ((iterator)->current == &(iterator)->nsec3iter && \ (iterator)->node == (qpdb)->nsec3_origin_node) /*% @@ -235,10 +235,10 @@ typedef struct qpdb_rdatasetiter { /* * 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" RBT ("chain" field) and the root node of the NSEC3 RBT - * ("nsec3chain" field) of the database in question, as if the latter was a + * "regular" QP ("iter" field) and the root node of the NSEC3 QP + * ("nsec3iter" field) 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 "chain" or "nsec3chain", depending on which RBT is + * the address of either "iter" or "nsec3iter", depending on which QP is * being traversed at given time. */ static void @@ -279,9 +279,9 @@ typedef struct qpdb_dbiterator { isc_result_t result; dns_fixedname_t name; dns_fixedname_t origin; - dns_rbtnodechain_t chain; - dns_rbtnodechain_t nsec3chain; - dns_rbtnodechain_t *current; + dns_qpiter_t iter; + dns_qpiter_t nsec3iter; + dns_qpiter_t *current; dns_rbtnode_t *node; enum { full, nonsec3, nsec3only } nsec3mode; } qpdb_dbiterator_t; @@ -2247,6 +2247,7 @@ dns__qpdb_createiterator(dns_db_t *db, unsigned int options, dns_fixedname_init(&qpdbiter->name); dns_fixedname_init(&qpdbiter->origin); qpdbiter->node = NULL; + if ((options & DNS_DB_NSEC3ONLY) != 0) { qpdbiter->nsec3mode = nsec3only; } else if ((options & DNS_DB_NONSEC3) != 0) { @@ -2254,16 +2255,15 @@ dns__qpdb_createiterator(dns_db_t *db, unsigned int options, } else { qpdbiter->nsec3mode = full; } - dns_rbtnodechain_init(&qpdbiter->chain); - dns_rbtnodechain_init(&qpdbiter->nsec3chain); + dns_qpiter_init(qpdb->tree, &qpdbiter->iter); + dns_qpiter_init(qpdb->nsec3, &qpdbiter->nsec3iter); if (qpdbiter->nsec3mode == nsec3only) { - qpdbiter->current = &qpdbiter->nsec3chain; + qpdbiter->current = &qpdbiter->nsec3iter; } else { - qpdbiter->current = &qpdbiter->chain; + qpdbiter->current = &qpdbiter->iter; } *iteratorp = (dns_dbiterator_t *)qpdbiter; - return (ISC_R_SUCCESS); } @@ -4193,8 +4193,6 @@ dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) { dns_db_attach(qpdbiter->common.db, &db); dns_db_detach(&qpdbiter->common.db); - dns_rbtnodechain_reset(&qpdbiter->chain); - dns_rbtnodechain_reset(&qpdbiter->nsec3chain); isc_mem_put(db->mctx, qpdbiter, sizeof(*qpdbiter)); dns_db_detach(&db); @@ -4206,7 +4204,6 @@ dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { isc_result_t result; qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator; dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; - dns_name_t *name = NULL, *origin = NULL; if (qpdbiter->result != ISC_R_SUCCESS && qpdbiter->result != ISC_R_NOTFOUND && @@ -4222,30 +4219,38 @@ dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - name = dns_fixedname_name(&qpdbiter->name); - origin = dns_fixedname_name(&qpdbiter->origin); - dns_rbtnodechain_reset(&qpdbiter->chain); - dns_rbtnodechain_reset(&qpdbiter->nsec3chain); - switch (qpdbiter->nsec3mode) { case nsec3only: - qpdbiter->current = &qpdbiter->nsec3chain; - result = dns_rbtnodechain_first(qpdbiter->current, qpdb->nsec3, - name, origin); + qpdbiter->current = &qpdbiter->nsec3iter; + dns_qpiter_init(qpdb->nsec3, 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->chain; - result = dns_rbtnodechain_first(qpdbiter->current, qpdb->tree, - name, origin); + qpdbiter->current = &qpdbiter->iter; + dns_qpiter_init(qpdb->tree, qpdbiter->current); + result = dns_qpiter_next(qpdbiter->current, NULL, + (void **)&qpdbiter->node, NULL); break; case full: - qpdbiter->current = &qpdbiter->chain; - result = dns_rbtnodechain_first(qpdbiter->current, qpdb->tree, - name, origin); - if (result == ISC_R_NOTFOUND) { - qpdbiter->current = &qpdbiter->nsec3chain; - result = dns_rbtnodechain_first( - qpdbiter->current, qpdb->nsec3, name, origin); + qpdbiter->current = &qpdbiter->iter; + dns_qpiter_init(qpdb->tree, 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(qpdb->nsec3, qpdbiter->current); + result = dns_qpiter_next(qpdbiter->current, NULL, + (void **)&qpdbiter->node, + NULL); } break; default: @@ -4253,29 +4258,10 @@ dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { } if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { - result = dns_rbtnodechain_current(qpdbiter->current, NULL, NULL, - &qpdbiter->node); - - /* If we're in the NSEC3 tree, skip the origin */ - if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - qpdbiter->node = NULL; - result = dns_rbtnodechain_next(qpdbiter->current, name, - origin); - if (result == ISC_R_SUCCESS || - result == DNS_R_NEWORIGIN) - { - result = dns_rbtnodechain_current( - qpdbiter->current, NULL, NULL, - &qpdbiter->node); - } - } - if (result == ISC_R_SUCCESS) { - qpdbiter->new_origin = true; - reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - } + qpdbiter->new_origin = true; + reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); } else { - INSIST(result == ISC_R_NOTFOUND); - result = ISC_R_NOMORE; /* The tree is empty. */ + INSIST(result == ISC_R_NOMORE); /* The tree is empty. */ } qpdbiter->result = result; @@ -4292,7 +4278,6 @@ dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { isc_result_t result; qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator; dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; - dns_name_t *name = NULL, *origin = NULL; if (qpdbiter->result != ISC_R_SUCCESS && qpdbiter->result != ISC_R_NOTFOUND && @@ -4308,30 +4293,48 @@ dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - name = dns_fixedname_name(&qpdbiter->name); - origin = dns_fixedname_name(&qpdbiter->origin); - dns_rbtnodechain_reset(&qpdbiter->chain); - dns_rbtnodechain_reset(&qpdbiter->nsec3chain); - switch (qpdbiter->nsec3mode) { case nsec3only: - qpdbiter->current = &qpdbiter->nsec3chain; - result = dns_rbtnodechain_last(qpdbiter->current, qpdb->nsec3, - name, origin); + qpdbiter->current = &qpdbiter->nsec3iter; + dns_qpiter_init(qpdb->nsec3, 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->chain; - result = dns_rbtnodechain_last(qpdbiter->current, qpdb->tree, - name, origin); + qpdbiter->current = &qpdbiter->iter; + dns_qpiter_init(qpdb->tree, qpdbiter->current); + result = dns_qpiter_prev(qpdbiter->current, NULL, + (void **)&qpdbiter->node, NULL); break; case full: - qpdbiter->current = &qpdbiter->nsec3chain; - result = dns_rbtnodechain_last(qpdbiter->current, qpdb->nsec3, - name, origin); - if (result == ISC_R_NOTFOUND) { - qpdbiter->current = &qpdbiter->chain; - result = dns_rbtnodechain_last( - qpdbiter->current, qpdb->tree, name, origin); + qpdbiter->current = &qpdbiter->nsec3iter; + dns_qpiter_init(qpdb->nsec3, 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->iter; + dns_qpiter_init(qpdb->tree, qpdbiter->current); + result = dns_qpiter_prev(qpdbiter->current, NULL, + (void **)&qpdbiter->node, + NULL); } break; default: @@ -4339,42 +4342,10 @@ dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { } if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) { - result = dns_rbtnodechain_current(qpdbiter->current, NULL, NULL, - &qpdbiter->node); - if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - /* - * NSEC3 tree only has an origin node. - */ - qpdbiter->node = NULL; - switch (qpdbiter->nsec3mode) { - case nsec3only: - result = ISC_R_NOMORE; - break; - case nonsec3: - case full: - qpdbiter->current = &qpdbiter->chain; - result = dns_rbtnodechain_last( - qpdbiter->current, qpdb->tree, name, - origin); - if (result == ISC_R_SUCCESS || - result == DNS_R_NEWORIGIN) - { - result = dns_rbtnodechain_current( - qpdbiter->current, NULL, NULL, - &qpdbiter->node); - } - break; - default: - UNREACHABLE(); - } - } - if (result == ISC_R_SUCCESS) { - qpdbiter->new_origin = true; - reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - } + qpdbiter->new_origin = true; + reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); } else { - INSIST(result == ISC_R_NOTFOUND); - result = ISC_R_NOMORE; /* The tree is empty. */ + INSIST(result == ISC_R_NOMORE); /* The tree is empty. */ } qpdbiter->result = result; @@ -4388,7 +4359,6 @@ dbiterator_seek(dns_dbiterator_t *iterator, isc_result_t result, tresult; qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator; dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; - dns_name_t *iname = NULL, *origin = NULL; if (qpdbiter->result != ISC_R_SUCCESS && qpdbiter->result != ISC_R_NOTFOUND && @@ -4404,20 +4374,15 @@ dbiterator_seek(dns_dbiterator_t *iterator, dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - iname = dns_fixedname_name(&qpdbiter->name); - origin = dns_fixedname_name(&qpdbiter->origin); - dns_rbtnodechain_reset(&qpdbiter->chain); - dns_rbtnodechain_reset(&qpdbiter->nsec3chain); - switch (qpdbiter->nsec3mode) { case nsec3only: - qpdbiter->current = &qpdbiter->nsec3chain; + qpdbiter->current = &qpdbiter->nsec3iter; result = dns_qp_lookup(qpdb->nsec3, name, NULL, qpdbiter->current, NULL, (void **)&qpdbiter->node, NULL); break; case nonsec3: - qpdbiter->current = &qpdbiter->chain; + qpdbiter->current = &qpdbiter->iter; result = dns_qp_lookup(qpdb->tree, name, NULL, qpdbiter->current, NULL, (void **)&qpdbiter->node, NULL); @@ -4425,20 +4390,20 @@ dbiterator_seek(dns_dbiterator_t *iterator, case full: /* * Stay on main chain if not found on - * either chain. + * either iterator. */ - qpdbiter->current = &qpdbiter->chain; + qpdbiter->current = &qpdbiter->iter; result = dns_qp_lookup(qpdb->tree, name, NULL, qpdbiter->current, NULL, (void **)&qpdbiter->node, NULL); if (result == DNS_R_PARTIALMATCH) { dns_rbtnode_t *node = NULL; tresult = dns_qp_lookup(qpdb->nsec3, name, NULL, - &qpdbiter->nsec3chain, NULL, + &qpdbiter->nsec3iter, NULL, (void **)&node, NULL); if (tresult == ISC_R_SUCCESS) { qpdbiter->node = node; - qpdbiter->current = &qpdbiter->nsec3chain; + qpdbiter->current = &qpdbiter->nsec3iter; result = tresult; } } @@ -4448,15 +4413,8 @@ dbiterator_seek(dns_dbiterator_t *iterator, } if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { - tresult = dns_rbtnodechain_current(qpdbiter->current, iname, - origin, NULL); - if (tresult == ISC_R_SUCCESS) { - qpdbiter->new_origin = true; - reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - } else { - result = tresult; - qpdbiter->node = NULL; - } + qpdbiter->new_origin = true; + reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); } else { qpdbiter->node = NULL; } @@ -4471,7 +4429,6 @@ 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; - dns_name_t *name = NULL, *origin = NULL; dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; REQUIRE(qpdbiter->node != NULL); @@ -4486,42 +4443,31 @@ dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) { dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS); - name = dns_fixedname_name(&qpdbiter->name); - origin = dns_fixedname_name(&qpdbiter->origin); - result = dns_rbtnodechain_prev(qpdbiter->current, name, origin); - if (qpdbiter->current == &qpdbiter->nsec3chain && - (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. - */ - result = dns_rbtnodechain_current(qpdbiter->current, NULL, NULL, - &qpdbiter->node); - if (result == ISC_R_NOTFOUND || - QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) - { - qpdbiter->node = NULL; - result = ISC_R_NOMORE; + 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 != nsec3only && - &qpdbiter->nsec3chain == qpdbiter->current) - { - qpdbiter->current = &qpdbiter->chain; - dns_rbtnodechain_reset(qpdbiter->current); - result = dns_rbtnodechain_last(qpdbiter->current, qpdb->tree, - name, origin); - if (result == ISC_R_NOTFOUND) { - result = ISC_R_NOMORE; + if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full) { + qpdbiter->current = &qpdbiter->iter; + dns_qpiter_init(qpdb->tree, qpdbiter->current); + result = dns_qpiter_prev(qpdbiter->current, NULL, + (void **)&qpdbiter->node, + NULL); } } - if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { - qpdbiter->new_origin = (result == DNS_R_NEWORIGIN); - result = dns_rbtnodechain_current(qpdbiter->current, NULL, NULL, - &qpdbiter->node); - } + qpdbiter->new_origin = (result == DNS_R_NEWORIGIN); if (result == ISC_R_SUCCESS) { reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); @@ -4536,7 +4482,6 @@ 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; - dns_name_t *name = NULL, *origin = NULL; dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; REQUIRE(qpdbiter->node != NULL); @@ -4549,44 +4494,45 @@ dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) { resume_iteration(qpdbiter); } - name = dns_fixedname_name(&qpdbiter->name); - origin = dns_fixedname_name(&qpdbiter->origin); - result = dns_rbtnodechain_next(qpdbiter->current, name, origin); - if (result == ISC_R_NOMORE && qpdbiter->nsec3mode != nonsec3 && - &qpdbiter->chain == qpdbiter->current) - { - qpdbiter->current = &qpdbiter->nsec3chain; - dns_rbtnodechain_reset(qpdbiter->current); - result = dns_rbtnodechain_first(qpdbiter->current, qpdb->nsec3, - name, origin); - if (result == ISC_R_NOTFOUND) { - result = ISC_R_NOMORE; - } - } - 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->iter) + { + qpdbiter->current = &qpdbiter->nsec3iter; + dns_qpiter_init(qpdb->nsec3, qpdbiter->current); + result = dns_qpiter_next(qpdbiter->current, NULL, + (void **)&qpdbiter->node, NULL); + } + if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { /* * If we've just started the NSEC3 tree, * skip over the origin. */ - qpdbiter->new_origin = (result == DNS_R_NEWORIGIN); - result = dns_rbtnodechain_current(qpdbiter->current, NULL, NULL, - &qpdbiter->node); if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) { - qpdbiter->node = NULL; - result = dns_rbtnodechain_next(qpdbiter->current, name, - origin); - if (result == ISC_R_SUCCESS || - result == DNS_R_NEWORIGIN) - { - result = dns_rbtnodechain_current( - qpdbiter->current, NULL, NULL, - &qpdbiter->node); + 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(); } } } + + qpdbiter->new_origin = (result == DNS_R_NEWORIGIN); + if (result == ISC_R_SUCCESS) { reference_iter_node(qpdbiter DNS__DB_FLARG_PASS); } @@ -4602,9 +4548,7 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, dns_qpdb_t *qpdb = (dns_qpdb_t *)iterator->db; qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator; dns_rbtnode_t *node = qpdbiter->node; - isc_result_t result; - dns_name_t *nodename = dns_fixedname_name(&qpdbiter->name); - dns_name_t *origin = dns_fixedname_name(&qpdbiter->origin); + isc_result_t result = ISC_R_SUCCESS; REQUIRE(qpdbiter->result == ISC_R_SUCCESS); REQUIRE(qpdbiter->node != NULL); @@ -4614,13 +4558,8 @@ dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, } if (name != NULL) { - if (qpdbiter->common.relative_names) { - origin = NULL; - } - result = dns_name_concatenate(nodename, origin, name, NULL); - if (result != ISC_R_SUCCESS) { - return (result); - } + dns_name_copy(qpdbiter->node->name, name); + if (qpdbiter->common.relative_names && qpdbiter->new_origin) { result = DNS_R_NEWORIGIN; } diff --git a/lib/dns/qpdb_p.h b/lib/dns/qpdb_p.h index ca481d8870..4d87dd440a 100644 --- a/lib/dns/qpdb_p.h +++ b/lib/dns/qpdb_p.h @@ -269,7 +269,8 @@ typedef struct { dns_qpdb_version_t *rbtversion; uint32_t serial; unsigned int options; - dns_rbtnodechain_t chain; + dns_qpchain_t chain; + dns_qpiter_t iter; bool copy_name; bool need_cleanup; bool wild;