1 /* $NetBSD: rriterator.c,v 1.3 2019/01/09 16:55:12 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 http://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 15 /*! \file */ 16 17 /*** 18 *** Imports 19 ***/ 20 21 #include <config.h> 22 23 #include <inttypes.h> 24 25 #include <isc/string.h> 26 #include <isc/util.h> 27 28 #include <dns/db.h> 29 #include <dns/dbiterator.h> 30 #include <dns/rdata.h> 31 #include <dns/rdataset.h> 32 #include <dns/rdatasetiter.h> 33 #include <dns/result.h> 34 #include <dns/rriterator.h> 35 36 /*** 37 *** RRiterator methods 38 ***/ 39 40 isc_result_t 41 dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 42 isc_stdtime_t now) 43 { 44 isc_result_t result; 45 it->magic = RRITERATOR_MAGIC; 46 it->db = db; 47 it->dbit = NULL; 48 it->ver = ver; 49 it->now = now; 50 it->node = NULL; 51 result = dns_db_createiterator(it->db, 0, &it->dbit); 52 if (result != ISC_R_SUCCESS) 53 return (result); 54 it->rdatasetit = NULL; 55 dns_rdata_init(&it->rdata); 56 dns_rdataset_init(&it->rdataset); 57 dns_fixedname_init(&it->fixedname); 58 INSIST(! dns_rdataset_isassociated(&it->rdataset)); 59 it->result = ISC_R_SUCCESS; 60 return (it->result); 61 } 62 63 isc_result_t 64 dns_rriterator_first(dns_rriterator_t *it) { 65 REQUIRE(VALID_RRITERATOR(it)); 66 /* Reset state */ 67 if (dns_rdataset_isassociated(&it->rdataset)) 68 dns_rdataset_disassociate(&it->rdataset); 69 if (it->rdatasetit != NULL) 70 dns_rdatasetiter_destroy(&it->rdatasetit); 71 if (it->node != NULL) 72 dns_db_detachnode(it->db, &it->node); 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(it->dbit, &it->node, 81 dns_fixedname_name(&it->fixedname)); 82 if (it->result != ISC_R_SUCCESS) 83 return (it->result); 84 85 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 86 it->now, &it->rdatasetit); 87 if (it->result != ISC_R_SUCCESS) 88 return (it->result); 89 90 it->result = dns_rdatasetiter_first(it->rdatasetit); 91 if (it->result != ISC_R_SUCCESS) { 92 /* 93 * This node is empty. Try next node. 94 */ 95 dns_rdatasetiter_destroy(&it->rdatasetit); 96 dns_db_detachnode(it->db, &it->node); 97 it->result = dns_dbiterator_next(it->dbit); 98 continue; 99 } 100 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 101 dns_rdataset_getownercase(&it->rdataset, 102 dns_fixedname_name(&it->fixedname)); 103 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 104 it->result = dns_rdataset_first(&it->rdataset); 105 return (it->result); 106 } 107 return (it->result); 108 } 109 110 isc_result_t 111 dns_rriterator_nextrrset(dns_rriterator_t *it) { 112 REQUIRE(VALID_RRITERATOR(it)); 113 if (dns_rdataset_isassociated(&it->rdataset)) 114 dns_rdataset_disassociate(&it->rdataset); 115 it->result = dns_rdatasetiter_next(it->rdatasetit); 116 /* 117 * The while loop body is executed more than once 118 * only when an empty dbnode needs to be skipped. 119 */ 120 while (it->result == ISC_R_NOMORE) { 121 dns_rdatasetiter_destroy(&it->rdatasetit); 122 dns_db_detachnode(it->db, &it->node); 123 it->result = dns_dbiterator_next(it->dbit); 124 if (it->result == ISC_R_NOMORE) { 125 /* We are at the end of the entire database. */ 126 return (it->result); 127 } 128 if (it->result != ISC_R_SUCCESS) 129 return (it->result); 130 it->result = dns_dbiterator_current(it->dbit, &it->node, 131 dns_fixedname_name(&it->fixedname)); 132 if (it->result != ISC_R_SUCCESS) 133 return (it->result); 134 it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 135 it->now, &it->rdatasetit); 136 if (it->result != ISC_R_SUCCESS) 137 return (it->result); 138 it->result = dns_rdatasetiter_first(it->rdatasetit); 139 } 140 if (it->result != ISC_R_SUCCESS) 141 return (it->result); 142 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 143 dns_rdataset_getownercase(&it->rdataset, 144 dns_fixedname_name(&it->fixedname)); 145 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; 146 it->result = dns_rdataset_first(&it->rdataset); 147 return (it->result); 148 } 149 150 isc_result_t 151 dns_rriterator_next(dns_rriterator_t *it) { 152 REQUIRE(VALID_RRITERATOR(it)); 153 if (it->result != ISC_R_SUCCESS) 154 return (it->result); 155 156 INSIST(it->dbit != NULL); 157 INSIST(it->node != NULL); 158 INSIST(it->rdatasetit != NULL); 159 160 it->result = dns_rdataset_next(&it->rdataset); 161 if (it->result == ISC_R_NOMORE) 162 return (dns_rriterator_nextrrset(it)); 163 return (it->result); 164 } 165 166 void 167 dns_rriterator_pause(dns_rriterator_t *it) { 168 REQUIRE(VALID_RRITERATOR(it)); 169 RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); 170 } 171 172 void 173 dns_rriterator_destroy(dns_rriterator_t *it) { 174 REQUIRE(VALID_RRITERATOR(it)); 175 if (dns_rdataset_isassociated(&it->rdataset)) 176 dns_rdataset_disassociate(&it->rdataset); 177 if (it->rdatasetit != NULL) 178 dns_rdatasetiter_destroy(&it->rdatasetit); 179 if (it->node != NULL) 180 dns_db_detachnode(it->db, &it->node); 181 dns_dbiterator_destroy(&it->dbit); 182 } 183 184 void 185 dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, 186 uint32_t *ttl, dns_rdataset_t **rdataset, 187 dns_rdata_t **rdata) 188 { 189 REQUIRE(name != NULL && *name == NULL); 190 REQUIRE(VALID_RRITERATOR(it)); 191 REQUIRE(it->result == ISC_R_SUCCESS); 192 REQUIRE(rdataset == NULL || *rdataset == NULL); 193 REQUIRE(rdata == NULL || *rdata == NULL); 194 195 *name = dns_fixedname_name(&it->fixedname); 196 *ttl = it->rdataset.ttl; 197 198 dns_rdata_reset(&it->rdata); 199 dns_rdataset_current(&it->rdataset, &it->rdata); 200 201 if (rdataset != NULL) 202 *rdataset = &it->rdataset; 203 204 if (rdata != NULL) 205 *rdata = &it->rdata; 206 } 207