1 /* $NetBSD: rriterator.c,v 1.5 2021/02/19 16:42:16 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 /*! \file */ 15 16 /*** 17 *** Imports 18 ***/ 19 20 #include <inttypes.h> 21 22 #include <isc/string.h> 23 #include <isc/util.h> 24 25 #include <dns/db.h> 26 #include <dns/dbiterator.h> 27 #include <dns/rdata.h> 28 #include <dns/rdataset.h> 29 #include <dns/rdatasetiter.h> 30 #include <dns/result.h> 31 #include <dns/rriterator.h> 32 33 /*** 34 *** RRiterator methods 35 ***/ 36 37 isc_result_t 38 dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 39 isc_stdtime_t now) { 40 isc_result_t result; 41 it->magic = RRITERATOR_MAGIC; 42 it->db = db; 43 it->dbit = NULL; 44 it->ver = ver; 45 it->now = now; 46 it->node = NULL; 47 result = dns_db_createiterator(it->db, 0, &it->dbit); 48 if (result != ISC_R_SUCCESS) { 49 return (result); 50 } 51 it->rdatasetit = NULL; 52 dns_rdata_init(&it->rdata); 53 dns_rdataset_init(&it->rdataset); 54 dns_fixedname_init(&it->fixedname); 55 INSIST(!dns_rdataset_isassociated(&it->rdataset)); 56 it->result = ISC_R_SUCCESS; 57 return (it->result); 58 } 59 60 isc_result_t 61 dns_rriterator_first(dns_rriterator_t *it) { 62 REQUIRE(VALID_RRITERATOR(it)); 63 /* Reset state */ 64 if (dns_rdataset_isassociated(&it->rdataset)) { 65 dns_rdataset_disassociate(&it->rdataset); 66 } 67 if (it->rdatasetit != NULL) { 68 dns_rdatasetiter_destroy(&it->rdatasetit); 69 } 70 if (it->node != NULL) { 71 dns_db_detachnode(it->db, &it->node); 72 } 73 it->result = dns_dbiterator_first(it->dbit); 74 75 /* 76 * The top node may be empty when out of zone glue exists. 77 * Walk the tree to find the first node with data. 78 */ 79 while (it->result == ISC_R_SUCCESS) { 80 it->result = dns_dbiterator_current( 81 it->dbit, &it->node, 82 dns_fixedname_name(&it->fixedname)); 83 if (it->result != ISC_R_SUCCESS) { 84 return (it->result); 85 } 86 87 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 88 it->now, &it->rdatasetit); 89 if (it->result != ISC_R_SUCCESS) { 90 return (it->result); 91 } 92 93 it->result = dns_rdatasetiter_first(it->rdatasetit); 94 if (it->result != ISC_R_SUCCESS) { 95 /* 96 * This node is empty. Try next node. 97 */ 98 dns_rdatasetiter_destroy(&it->rdatasetit); 99 dns_db_detachnode(it->db, &it->node); 100 it->result = dns_dbiterator_next(it->dbit); 101 continue; 102 } 103 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 104 dns_rdataset_getownercase(&it->rdataset, 105 dns_fixedname_name(&it->fixedname)); 106 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 107 it->result = dns_rdataset_first(&it->rdataset); 108 return (it->result); 109 } 110 return (it->result); 111 } 112 113 isc_result_t 114 dns_rriterator_nextrrset(dns_rriterator_t *it) { 115 REQUIRE(VALID_RRITERATOR(it)); 116 if (dns_rdataset_isassociated(&it->rdataset)) { 117 dns_rdataset_disassociate(&it->rdataset); 118 } 119 it->result = dns_rdatasetiter_next(it->rdatasetit); 120 /* 121 * The while loop body is executed more than once 122 * only when an empty dbnode needs to be skipped. 123 */ 124 while (it->result == ISC_R_NOMORE) { 125 dns_rdatasetiter_destroy(&it->rdatasetit); 126 dns_db_detachnode(it->db, &it->node); 127 it->result = dns_dbiterator_next(it->dbit); 128 if (it->result == ISC_R_NOMORE) { 129 /* We are at the end of the entire database. */ 130 return (it->result); 131 } 132 if (it->result != ISC_R_SUCCESS) { 133 return (it->result); 134 } 135 it->result = dns_dbiterator_current( 136 it->dbit, &it->node, 137 dns_fixedname_name(&it->fixedname)); 138 if (it->result != ISC_R_SUCCESS) { 139 return (it->result); 140 } 141 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 142 it->now, &it->rdatasetit); 143 if (it->result != ISC_R_SUCCESS) { 144 return (it->result); 145 } 146 it->result = dns_rdatasetiter_first(it->rdatasetit); 147 } 148 if (it->result != ISC_R_SUCCESS) { 149 return (it->result); 150 } 151 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 152 dns_rdataset_getownercase(&it->rdataset, 153 dns_fixedname_name(&it->fixedname)); 154 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 155 it->result = dns_rdataset_first(&it->rdataset); 156 return (it->result); 157 } 158 159 isc_result_t 160 dns_rriterator_next(dns_rriterator_t *it) { 161 REQUIRE(VALID_RRITERATOR(it)); 162 if (it->result != ISC_R_SUCCESS) { 163 return (it->result); 164 } 165 166 INSIST(it->dbit != NULL); 167 INSIST(it->node != NULL); 168 INSIST(it->rdatasetit != NULL); 169 170 it->result = dns_rdataset_next(&it->rdataset); 171 if (it->result == ISC_R_NOMORE) { 172 return (dns_rriterator_nextrrset(it)); 173 } 174 return (it->result); 175 } 176 177 void 178 dns_rriterator_pause(dns_rriterator_t *it) { 179 REQUIRE(VALID_RRITERATOR(it)); 180 RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); 181 } 182 183 void 184 dns_rriterator_destroy(dns_rriterator_t *it) { 185 REQUIRE(VALID_RRITERATOR(it)); 186 if (dns_rdataset_isassociated(&it->rdataset)) { 187 dns_rdataset_disassociate(&it->rdataset); 188 } 189 if (it->rdatasetit != NULL) { 190 dns_rdatasetiter_destroy(&it->rdatasetit); 191 } 192 if (it->node != NULL) { 193 dns_db_detachnode(it->db, &it->node); 194 } 195 dns_dbiterator_destroy(&it->dbit); 196 } 197 198 void 199 dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, uint32_t *ttl, 200 dns_rdataset_t **rdataset, dns_rdata_t **rdata) { 201 REQUIRE(name != NULL && *name == NULL); 202 REQUIRE(VALID_RRITERATOR(it)); 203 REQUIRE(it->result == ISC_R_SUCCESS); 204 REQUIRE(rdataset == NULL || *rdataset == NULL); 205 REQUIRE(rdata == NULL || *rdata == NULL); 206 207 *name = dns_fixedname_name(&it->fixedname); 208 *ttl = it->rdataset.ttl; 209 210 dns_rdata_reset(&it->rdata); 211 dns_rdataset_current(&it->rdataset, &it->rdata); 212 213 if (rdataset != NULL) { 214 *rdataset = &it->rdataset; 215 } 216 217 if (rdata != NULL) { 218 *rdata = &it->rdata; 219 } 220 } 221