diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
commit | 45d6379135504814ab723b57f0eb8be23393a51d (patch) | |
tree | d4f2ec4acca824a8446387a758b0ce4238a4dffa /lib/dns/rriterator.c | |
parent | Initial commit. (diff) | |
download | bind9-45d6379135504814ab723b57f0eb8be23393a51d.tar.xz bind9-45d6379135504814ab723b57f0eb8be23393a51d.zip |
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/dns/rriterator.c')
-rw-r--r-- | lib/dns/rriterator.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/lib/dns/rriterator.c b/lib/dns/rriterator.c new file mode 100644 index 0000000..9b40597 --- /dev/null +++ b/lib/dns/rriterator.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/*** + *** Imports + ***/ + +#include <inttypes.h> + +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/dbiterator.h> +#include <dns/rdata.h> +#include <dns/rdataset.h> +#include <dns/rdatasetiter.h> +#include <dns/result.h> +#include <dns/rriterator.h> + +/*** + *** RRiterator methods + ***/ + +isc_result_t +dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, + isc_stdtime_t now) { + isc_result_t result; + it->magic = RRITERATOR_MAGIC; + it->db = db; + it->dbit = NULL; + it->ver = ver; + it->now = now; + it->node = NULL; + result = dns_db_createiterator(it->db, 0, &it->dbit); + if (result != ISC_R_SUCCESS) { + return (result); + } + it->rdatasetit = NULL; + dns_rdata_init(&it->rdata); + dns_rdataset_init(&it->rdataset); + dns_fixedname_init(&it->fixedname); + INSIST(!dns_rdataset_isassociated(&it->rdataset)); + it->result = ISC_R_SUCCESS; + return (it->result); +} + +isc_result_t +dns_rriterator_first(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + /* Reset state */ + if (dns_rdataset_isassociated(&it->rdataset)) { + dns_rdataset_disassociate(&it->rdataset); + } + if (it->rdatasetit != NULL) { + dns_rdatasetiter_destroy(&it->rdatasetit); + } + if (it->node != NULL) { + dns_db_detachnode(it->db, &it->node); + } + it->result = dns_dbiterator_first(it->dbit); + + /* + * The top node may be empty when out of zone glue exists. + * Walk the tree to find the first node with data. + */ + while (it->result == ISC_R_SUCCESS) { + it->result = dns_dbiterator_current( + it->dbit, &it->node, + dns_fixedname_name(&it->fixedname)); + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, + it->now, &it->rdatasetit); + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + + it->result = dns_rdatasetiter_first(it->rdatasetit); + if (it->result != ISC_R_SUCCESS) { + /* + * This node is empty. Try next node. + */ + dns_rdatasetiter_destroy(&it->rdatasetit); + dns_db_detachnode(it->db, &it->node); + it->result = dns_dbiterator_next(it->dbit); + continue; + } + dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); + dns_rdataset_getownercase(&it->rdataset, + dns_fixedname_name(&it->fixedname)); + it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; + it->result = dns_rdataset_first(&it->rdataset); + return (it->result); + } + return (it->result); +} + +isc_result_t +dns_rriterator_nextrrset(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (dns_rdataset_isassociated(&it->rdataset)) { + dns_rdataset_disassociate(&it->rdataset); + } + it->result = dns_rdatasetiter_next(it->rdatasetit); + /* + * The while loop body is executed more than once + * only when an empty dbnode needs to be skipped. + */ + while (it->result == ISC_R_NOMORE) { + dns_rdatasetiter_destroy(&it->rdatasetit); + dns_db_detachnode(it->db, &it->node); + it->result = dns_dbiterator_next(it->dbit); + if (it->result == ISC_R_NOMORE) { + /* We are at the end of the entire database. */ + return (it->result); + } + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + it->result = dns_dbiterator_current( + it->dbit, &it->node, + dns_fixedname_name(&it->fixedname)); + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, + it->now, &it->rdatasetit); + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + it->result = dns_rdatasetiter_first(it->rdatasetit); + } + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); + dns_rdataset_getownercase(&it->rdataset, + dns_fixedname_name(&it->fixedname)); + it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; + it->result = dns_rdataset_first(&it->rdataset); + return (it->result); +} + +isc_result_t +dns_rriterator_next(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (it->result != ISC_R_SUCCESS) { + return (it->result); + } + + INSIST(it->dbit != NULL); + INSIST(it->node != NULL); + INSIST(it->rdatasetit != NULL); + + it->result = dns_rdataset_next(&it->rdataset); + if (it->result == ISC_R_NOMORE) { + return (dns_rriterator_nextrrset(it)); + } + return (it->result); +} + +void +dns_rriterator_pause(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); +} + +void +dns_rriterator_destroy(dns_rriterator_t *it) { + REQUIRE(VALID_RRITERATOR(it)); + if (dns_rdataset_isassociated(&it->rdataset)) { + dns_rdataset_disassociate(&it->rdataset); + } + if (it->rdatasetit != NULL) { + dns_rdatasetiter_destroy(&it->rdatasetit); + } + if (it->node != NULL) { + dns_db_detachnode(it->db, &it->node); + } + dns_dbiterator_destroy(&it->dbit); +} + +void +dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, uint32_t *ttl, + dns_rdataset_t **rdataset, dns_rdata_t **rdata) { + REQUIRE(name != NULL && *name == NULL); + REQUIRE(VALID_RRITERATOR(it)); + REQUIRE(it->result == ISC_R_SUCCESS); + REQUIRE(rdataset == NULL || *rdataset == NULL); + REQUIRE(rdata == NULL || *rdata == NULL); + + *name = dns_fixedname_name(&it->fixedname); + *ttl = it->rdataset.ttl; + + dns_rdata_reset(&it->rdata); + dns_rdataset_current(&it->rdataset, &it->rdata); + + if (rdataset != NULL) { + *rdataset = &it->rdataset; + } + + if (rdata != NULL) { + *rdata = &it->rdata; + } +} |