xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rriterator.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
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