1*bcda20f6Schristos /* $NetBSD: rriterator.c,v 1.9 2025/01/26 16:25:25 christos Exp $ */ 2d68c78b8Schristos 3d68c78b8Schristos /* 4d68c78b8Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5d68c78b8Schristos * 68596601aSchristos * SPDX-License-Identifier: MPL-2.0 78596601aSchristos * 8d68c78b8Schristos * This Source Code Form is subject to the terms of the Mozilla Public 9d68c78b8Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this 10fce770bdSchristos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11d68c78b8Schristos * 12d68c78b8Schristos * See the COPYRIGHT file distributed with this work for additional 13d68c78b8Schristos * information regarding copyright ownership. 14d68c78b8Schristos */ 15d68c78b8Schristos 16d68c78b8Schristos /*! \file */ 17d68c78b8Schristos 18d68c78b8Schristos /*** 19d68c78b8Schristos *** Imports 20d68c78b8Schristos ***/ 21d68c78b8Schristos 22d4a20c3eSchristos #include <inttypes.h> 23d4a20c3eSchristos 24bb5aa156Schristos #include <isc/result.h> 25d68c78b8Schristos #include <isc/string.h> 26d68c78b8Schristos #include <isc/util.h> 27d68c78b8Schristos 28d68c78b8Schristos #include <dns/db.h> 29d68c78b8Schristos #include <dns/dbiterator.h> 30d68c78b8Schristos #include <dns/rdata.h> 31d68c78b8Schristos #include <dns/rdataset.h> 32d68c78b8Schristos #include <dns/rdatasetiter.h> 33d68c78b8Schristos #include <dns/rriterator.h> 34d68c78b8Schristos 35d68c78b8Schristos /*** 36d68c78b8Schristos *** RRiterator methods 37d68c78b8Schristos ***/ 38d68c78b8Schristos 39d68c78b8Schristos isc_result_t 40d68c78b8Schristos dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 415606745fSchristos isc_stdtime_t now) { 42d68c78b8Schristos isc_result_t result; 43d68c78b8Schristos it->magic = RRITERATOR_MAGIC; 44d68c78b8Schristos it->db = db; 45d68c78b8Schristos it->dbit = NULL; 46d68c78b8Schristos it->ver = ver; 47d68c78b8Schristos it->now = now; 48d68c78b8Schristos it->node = NULL; 49d68c78b8Schristos result = dns_db_createiterator(it->db, 0, &it->dbit); 505606745fSchristos if (result != ISC_R_SUCCESS) { 51*bcda20f6Schristos return result; 525606745fSchristos } 53d68c78b8Schristos it->rdatasetit = NULL; 54d68c78b8Schristos dns_rdata_init(&it->rdata); 55d68c78b8Schristos dns_rdataset_init(&it->rdataset); 56d68c78b8Schristos dns_fixedname_init(&it->fixedname); 57d68c78b8Schristos INSIST(!dns_rdataset_isassociated(&it->rdataset)); 58d68c78b8Schristos it->result = ISC_R_SUCCESS; 59*bcda20f6Schristos return it->result; 60d68c78b8Schristos } 61d68c78b8Schristos 62d68c78b8Schristos isc_result_t 63d68c78b8Schristos dns_rriterator_first(dns_rriterator_t *it) { 64d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 65d68c78b8Schristos /* Reset state */ 665606745fSchristos if (dns_rdataset_isassociated(&it->rdataset)) { 67d68c78b8Schristos dns_rdataset_disassociate(&it->rdataset); 685606745fSchristos } 695606745fSchristos if (it->rdatasetit != NULL) { 70d68c78b8Schristos dns_rdatasetiter_destroy(&it->rdatasetit); 715606745fSchristos } 725606745fSchristos if (it->node != NULL) { 73d68c78b8Schristos dns_db_detachnode(it->db, &it->node); 745606745fSchristos } 75d68c78b8Schristos it->result = dns_dbiterator_first(it->dbit); 76d68c78b8Schristos 77d68c78b8Schristos /* 78d68c78b8Schristos * The top node may be empty when out of zone glue exists. 79d68c78b8Schristos * Walk the tree to find the first node with data. 80d68c78b8Schristos */ 81d68c78b8Schristos while (it->result == ISC_R_SUCCESS) { 825606745fSchristos it->result = dns_dbiterator_current( 835606745fSchristos it->dbit, &it->node, 84d68c78b8Schristos dns_fixedname_name(&it->fixedname)); 855606745fSchristos if (it->result != ISC_R_SUCCESS) { 86*bcda20f6Schristos return it->result; 875606745fSchristos } 88d68c78b8Schristos 89903adeddSchristos it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, 90d68c78b8Schristos it->now, &it->rdatasetit); 915606745fSchristos if (it->result != ISC_R_SUCCESS) { 92*bcda20f6Schristos return it->result; 935606745fSchristos } 94d68c78b8Schristos 95d68c78b8Schristos it->result = dns_rdatasetiter_first(it->rdatasetit); 96d68c78b8Schristos if (it->result != ISC_R_SUCCESS) { 97d68c78b8Schristos /* 98d68c78b8Schristos * This node is empty. Try next node. 99d68c78b8Schristos */ 100d68c78b8Schristos dns_rdatasetiter_destroy(&it->rdatasetit); 101d68c78b8Schristos dns_db_detachnode(it->db, &it->node); 102d68c78b8Schristos it->result = dns_dbiterator_next(it->dbit); 103d68c78b8Schristos continue; 104d68c78b8Schristos } 105d68c78b8Schristos dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 106d68c78b8Schristos dns_rdataset_getownercase(&it->rdataset, 107d68c78b8Schristos dns_fixedname_name(&it->fixedname)); 108d68c78b8Schristos it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 109d68c78b8Schristos it->result = dns_rdataset_first(&it->rdataset); 110*bcda20f6Schristos return it->result; 111d68c78b8Schristos } 112*bcda20f6Schristos return it->result; 113d68c78b8Schristos } 114d68c78b8Schristos 115d68c78b8Schristos isc_result_t 116d68c78b8Schristos dns_rriterator_nextrrset(dns_rriterator_t *it) { 117d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 1185606745fSchristos if (dns_rdataset_isassociated(&it->rdataset)) { 119d68c78b8Schristos dns_rdataset_disassociate(&it->rdataset); 1205606745fSchristos } 121d68c78b8Schristos it->result = dns_rdatasetiter_next(it->rdatasetit); 122d68c78b8Schristos /* 123d68c78b8Schristos * The while loop body is executed more than once 124d68c78b8Schristos * only when an empty dbnode needs to be skipped. 125d68c78b8Schristos */ 126d68c78b8Schristos while (it->result == ISC_R_NOMORE) { 127d68c78b8Schristos dns_rdatasetiter_destroy(&it->rdatasetit); 128d68c78b8Schristos dns_db_detachnode(it->db, &it->node); 129d68c78b8Schristos it->result = dns_dbiterator_next(it->dbit); 130d68c78b8Schristos if (it->result == ISC_R_NOMORE) { 131d68c78b8Schristos /* We are at the end of the entire database. */ 132*bcda20f6Schristos return it->result; 133d68c78b8Schristos } 1345606745fSchristos if (it->result != ISC_R_SUCCESS) { 135*bcda20f6Schristos return it->result; 1365606745fSchristos } 1375606745fSchristos it->result = dns_dbiterator_current( 1385606745fSchristos it->dbit, &it->node, 139d68c78b8Schristos dns_fixedname_name(&it->fixedname)); 1405606745fSchristos if (it->result != ISC_R_SUCCESS) { 141*bcda20f6Schristos return it->result; 1425606745fSchristos } 143903adeddSchristos it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0, 144d68c78b8Schristos it->now, &it->rdatasetit); 1455606745fSchristos if (it->result != ISC_R_SUCCESS) { 146*bcda20f6Schristos return it->result; 1475606745fSchristos } 148d68c78b8Schristos it->result = dns_rdatasetiter_first(it->rdatasetit); 149d68c78b8Schristos } 1505606745fSchristos if (it->result != ISC_R_SUCCESS) { 151*bcda20f6Schristos return it->result; 1525606745fSchristos } 153d68c78b8Schristos dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 154d68c78b8Schristos dns_rdataset_getownercase(&it->rdataset, 155d68c78b8Schristos dns_fixedname_name(&it->fixedname)); 156d68c78b8Schristos it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 157d68c78b8Schristos it->result = dns_rdataset_first(&it->rdataset); 158*bcda20f6Schristos return it->result; 159d68c78b8Schristos } 160d68c78b8Schristos 161d68c78b8Schristos isc_result_t 162d68c78b8Schristos dns_rriterator_next(dns_rriterator_t *it) { 163d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 1645606745fSchristos if (it->result != ISC_R_SUCCESS) { 165*bcda20f6Schristos return it->result; 1665606745fSchristos } 167d68c78b8Schristos 168d68c78b8Schristos INSIST(it->dbit != NULL); 169d68c78b8Schristos INSIST(it->node != NULL); 170d68c78b8Schristos INSIST(it->rdatasetit != NULL); 171d68c78b8Schristos 172d68c78b8Schristos it->result = dns_rdataset_next(&it->rdataset); 1735606745fSchristos if (it->result == ISC_R_NOMORE) { 174*bcda20f6Schristos return dns_rriterator_nextrrset(it); 1755606745fSchristos } 176*bcda20f6Schristos return it->result; 177d68c78b8Schristos } 178d68c78b8Schristos 179d68c78b8Schristos void 180d68c78b8Schristos dns_rriterator_pause(dns_rriterator_t *it) { 181d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 182d68c78b8Schristos RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); 183d68c78b8Schristos } 184d68c78b8Schristos 185d68c78b8Schristos void 186d68c78b8Schristos dns_rriterator_destroy(dns_rriterator_t *it) { 187d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 1885606745fSchristos if (dns_rdataset_isassociated(&it->rdataset)) { 189d68c78b8Schristos dns_rdataset_disassociate(&it->rdataset); 1905606745fSchristos } 1915606745fSchristos if (it->rdatasetit != NULL) { 192d68c78b8Schristos dns_rdatasetiter_destroy(&it->rdatasetit); 1935606745fSchristos } 1945606745fSchristos if (it->node != NULL) { 195d68c78b8Schristos dns_db_detachnode(it->db, &it->node); 1965606745fSchristos } 197d68c78b8Schristos dns_dbiterator_destroy(&it->dbit); 198d68c78b8Schristos } 199d68c78b8Schristos 200d68c78b8Schristos void 2015606745fSchristos dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, uint32_t *ttl, 2025606745fSchristos dns_rdataset_t **rdataset, dns_rdata_t **rdata) { 203d68c78b8Schristos REQUIRE(name != NULL && *name == NULL); 204d68c78b8Schristos REQUIRE(VALID_RRITERATOR(it)); 205d68c78b8Schristos REQUIRE(it->result == ISC_R_SUCCESS); 206d68c78b8Schristos REQUIRE(rdataset == NULL || *rdataset == NULL); 207d68c78b8Schristos REQUIRE(rdata == NULL || *rdata == NULL); 208d68c78b8Schristos 209d68c78b8Schristos *name = dns_fixedname_name(&it->fixedname); 210d68c78b8Schristos *ttl = it->rdataset.ttl; 211d68c78b8Schristos 212d68c78b8Schristos dns_rdata_reset(&it->rdata); 213d68c78b8Schristos dns_rdataset_current(&it->rdataset, &it->rdata); 214d68c78b8Schristos 215*bcda20f6Schristos SET_IF_NOT_NULL(rdataset, &it->rdataset); 216d68c78b8Schristos 217*bcda20f6Schristos SET_IF_NOT_NULL(rdata, &it->rdata); 2185606745fSchristos } 219