xref: /minix/external/bsd/bind/dist/lib/dns/rriterator.c (revision 00b67f09)
1 /*	$NetBSD: rriterator.c,v 1.4 2014/12/10 04:37:58 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id */
20 
21 /*! \file */
22 
23 /***
24  *** Imports
25  ***/
26 
27 #include <config.h>
28 
29 #include <isc/string.h>
30 #include <isc/util.h>
31 
32 #include <dns/db.h>
33 #include <dns/dbiterator.h>
34 #include <dns/rdata.h>
35 #include <dns/rdataset.h>
36 #include <dns/rdatasetiter.h>
37 #include <dns/result.h>
38 #include <dns/rriterator.h>
39 
40 /***
41  *** RRiterator methods
42  ***/
43 
44 isc_result_t
dns_rriterator_init(dns_rriterator_t * it,dns_db_t * db,dns_dbversion_t * ver,isc_stdtime_t now)45 dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
46 		    isc_stdtime_t now)
47 {
48 	isc_result_t result;
49 	it->magic = RRITERATOR_MAGIC;
50 	it->db = db;
51 	it->dbit = NULL;
52 	it->ver = ver;
53 	it->now = now;
54 	it->node = NULL;
55 	result = dns_db_createiterator(it->db, 0, &it->dbit);
56 	if (result != ISC_R_SUCCESS)
57 		return (result);
58 	it->rdatasetit = NULL;
59 	dns_rdata_init(&it->rdata);
60 	dns_rdataset_init(&it->rdataset);
61 	dns_fixedname_init(&it->fixedname);
62 	INSIST(! dns_rdataset_isassociated(&it->rdataset));
63 	it->result = ISC_R_SUCCESS;
64 	return (it->result);
65 }
66 
67 isc_result_t
dns_rriterator_first(dns_rriterator_t * it)68 dns_rriterator_first(dns_rriterator_t *it) {
69 	REQUIRE(VALID_RRITERATOR(it));
70 	/* Reset state */
71 	if (dns_rdataset_isassociated(&it->rdataset))
72 		dns_rdataset_disassociate(&it->rdataset);
73 	if (it->rdatasetit != NULL)
74 		dns_rdatasetiter_destroy(&it->rdatasetit);
75 	if (it->node != NULL)
76 		dns_db_detachnode(it->db, &it->node);
77 	it->result = dns_dbiterator_first(it->dbit);
78 
79 	/*
80 	 * The top node may be empty when out of zone glue exists.
81 	 * Walk the tree to find the first node with data.
82 	 */
83 	while (it->result == ISC_R_SUCCESS) {
84 		it->result = dns_dbiterator_current(it->dbit, &it->node,
85 					   dns_fixedname_name(&it->fixedname));
86 		if (it->result != ISC_R_SUCCESS)
87 			return (it->result);
88 
89 		it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
90 						 it->now, &it->rdatasetit);
91 		if (it->result != ISC_R_SUCCESS)
92 			return (it->result);
93 
94 		it->result = dns_rdatasetiter_first(it->rdatasetit);
95 		if (it->result != ISC_R_SUCCESS) {
96 			/*
97 			 * This node is empty. Try next node.
98 			 */
99 			dns_rdatasetiter_destroy(&it->rdatasetit);
100 			dns_db_detachnode(it->db, &it->node);
101 			it->result = dns_dbiterator_next(it->dbit);
102 			continue;
103 		}
104 		dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
105 		it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
106 		it->result = dns_rdataset_first(&it->rdataset);
107 		return (it->result);
108 	}
109 	return (it->result);
110 }
111 
112 isc_result_t
dns_rriterator_nextrrset(dns_rriterator_t * it)113 dns_rriterator_nextrrset(dns_rriterator_t *it) {
114 	REQUIRE(VALID_RRITERATOR(it));
115 	if (dns_rdataset_isassociated(&it->rdataset))
116 		dns_rdataset_disassociate(&it->rdataset);
117 	it->result = dns_rdatasetiter_next(it->rdatasetit);
118 	/*
119 	 * The while loop body is executed more than once
120 	 * only when an empty dbnode needs to be skipped.
121 	 */
122 	while (it->result == ISC_R_NOMORE) {
123 		dns_rdatasetiter_destroy(&it->rdatasetit);
124 		dns_db_detachnode(it->db, &it->node);
125 		it->result = dns_dbiterator_next(it->dbit);
126 		if (it->result == ISC_R_NOMORE) {
127 			/* We are at the end of the entire database. */
128 			return (it->result);
129 		}
130 		if (it->result != ISC_R_SUCCESS)
131 			return (it->result);
132 		it->result = dns_dbiterator_current(it->dbit, &it->node,
133 					   dns_fixedname_name(&it->fixedname));
134 		if (it->result != ISC_R_SUCCESS)
135 			return (it->result);
136 		it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
137 						 it->now, &it->rdatasetit);
138 		if (it->result != ISC_R_SUCCESS)
139 			return (it->result);
140 		it->result = dns_rdatasetiter_first(it->rdatasetit);
141 	}
142 	if (it->result != ISC_R_SUCCESS)
143 		return (it->result);
144 	dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
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
dns_rriterator_next(dns_rriterator_t * it)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
dns_rriterator_pause(dns_rriterator_t * it)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
dns_rriterator_destroy(dns_rriterator_t * it)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
dns_rriterator_current(dns_rriterator_t * it,dns_name_t ** name,isc_uint32_t * ttl,dns_rdataset_t ** rdataset,dns_rdata_t ** rdata)185 dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
186 		       isc_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