Coverage Report

Created: 2026-06-07 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rriterator.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
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/result.h>
23
#include <isc/string.h>
24
#include <isc/util.h>
25
26
#include <dns/db.h>
27
#include <dns/dbiterator.h>
28
#include <dns/rdata.h>
29
#include <dns/rdataset.h>
30
#include <dns/rdatasetiter.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
0
        isc_stdtime_t now) {
40
0
  it->magic = RRITERATOR_MAGIC;
41
0
  it->db = db;
42
0
  it->dbit = NULL;
43
0
  it->ver = ver;
44
0
  it->now = now;
45
0
  it->node = NULL;
46
0
  RETERR(dns_db_createiterator(it->db, 0, &it->dbit));
47
0
  it->rdatasetit = NULL;
48
0
  dns_rdata_init(&it->rdata);
49
0
  dns_rdataset_init(&it->rdataset);
50
0
  dns_fixedname_init(&it->fixedname);
51
0
  INSIST(!dns_rdataset_isassociated(&it->rdataset));
52
0
  it->result = ISC_R_SUCCESS;
53
0
  return it->result;
54
0
}
55
56
isc_result_t
57
0
dns_rriterator_first(dns_rriterator_t *it) {
58
0
  REQUIRE(VALID_RRITERATOR(it));
59
  /* Reset state */
60
0
  dns_rdataset_cleanup(&it->rdataset);
61
0
  if (it->rdatasetit != NULL) {
62
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
63
0
  }
64
0
  if (it->node != NULL) {
65
0
    dns_db_detachnode(&it->node);
66
0
  }
67
0
  it->result = dns_dbiterator_first(it->dbit);
68
69
  /*
70
   * The top node may be empty when out of zone glue exists.
71
   * Walk the tree to find the first node with data.
72
   */
73
0
  while (it->result == ISC_R_SUCCESS) {
74
0
    it->result = dns_dbiterator_current(
75
0
      it->dbit, &it->node,
76
0
      dns_fixedname_name(&it->fixedname));
77
0
    if (it->result != ISC_R_SUCCESS) {
78
0
      return it->result;
79
0
    }
80
81
0
    it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0,
82
0
             it->now, &it->rdatasetit);
83
0
    if (it->result != ISC_R_SUCCESS) {
84
0
      return it->result;
85
0
    }
86
87
0
    it->result = dns_rdatasetiter_first(it->rdatasetit);
88
0
    if (it->result != ISC_R_SUCCESS) {
89
      /*
90
       * This node is empty. Try next node.
91
       */
92
0
      dns_rdatasetiter_destroy(&it->rdatasetit);
93
0
      dns_db_detachnode(&it->node);
94
0
      it->result = dns_dbiterator_next(it->dbit);
95
0
      continue;
96
0
    }
97
0
    dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
98
0
    dns_rdataset_getownercase(&it->rdataset,
99
0
            dns_fixedname_name(&it->fixedname));
100
0
    it->result = dns_rdataset_first(&it->rdataset);
101
0
    return it->result;
102
0
  }
103
0
  return it->result;
104
0
}
105
106
isc_result_t
107
0
dns_rriterator_nextrrset(dns_rriterator_t *it) {
108
0
  REQUIRE(VALID_RRITERATOR(it));
109
0
  dns_rdataset_cleanup(&it->rdataset);
110
0
  it->result = dns_rdatasetiter_next(it->rdatasetit);
111
  /*
112
   * The while loop body is executed more than once
113
   * only when an empty dbnode needs to be skipped.
114
   */
115
0
  while (it->result == ISC_R_NOMORE) {
116
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
117
0
    dns_db_detachnode(&it->node);
118
0
    it->result = dns_dbiterator_next(it->dbit);
119
0
    if (it->result == ISC_R_NOMORE) {
120
      /* We are at the end of the entire database. */
121
0
      return it->result;
122
0
    }
123
0
    if (it->result != ISC_R_SUCCESS) {
124
0
      return it->result;
125
0
    }
126
0
    it->result = dns_dbiterator_current(
127
0
      it->dbit, &it->node,
128
0
      dns_fixedname_name(&it->fixedname));
129
0
    if (it->result != ISC_R_SUCCESS) {
130
0
      return it->result;
131
0
    }
132
0
    it->result = dns_db_allrdatasets(it->db, it->node, it->ver, 0,
133
0
             it->now, &it->rdatasetit);
134
0
    if (it->result != ISC_R_SUCCESS) {
135
0
      return it->result;
136
0
    }
137
0
    it->result = dns_rdatasetiter_first(it->rdatasetit);
138
0
  }
139
0
  if (it->result != ISC_R_SUCCESS) {
140
0
    return it->result;
141
0
  }
142
0
  dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
143
0
  dns_rdataset_getownercase(&it->rdataset,
144
0
          dns_fixedname_name(&it->fixedname));
145
0
  it->result = dns_rdataset_first(&it->rdataset);
146
0
  return it->result;
147
0
}
148
149
isc_result_t
150
0
dns_rriterator_next(dns_rriterator_t *it) {
151
0
  REQUIRE(VALID_RRITERATOR(it));
152
0
  if (it->result != ISC_R_SUCCESS) {
153
0
    return it->result;
154
0
  }
155
156
0
  INSIST(it->dbit != NULL);
157
0
  INSIST(it->node != NULL);
158
0
  INSIST(it->rdatasetit != NULL);
159
160
0
  it->result = dns_rdataset_next(&it->rdataset);
161
0
  if (it->result == ISC_R_NOMORE) {
162
0
    return dns_rriterator_nextrrset(it);
163
0
  }
164
0
  return it->result;
165
0
}
166
167
void
168
0
dns_rriterator_pause(dns_rriterator_t *it) {
169
0
  REQUIRE(VALID_RRITERATOR(it));
170
0
  RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
171
0
}
172
173
void
174
0
dns_rriterator_destroy(dns_rriterator_t *it) {
175
0
  REQUIRE(VALID_RRITERATOR(it));
176
0
  dns_rdataset_cleanup(&it->rdataset);
177
0
  if (it->rdatasetit != NULL) {
178
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
179
0
  }
180
0
  if (it->node != NULL) {
181
0
    dns_db_detachnode(&it->node);
182
0
  }
183
0
  dns_dbiterator_destroy(&it->dbit);
184
0
}
185
186
void
187
dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, uint32_t *ttl,
188
0
           dns_rdataset_t **rdataset, dns_rdata_t **rdata) {
189
0
  REQUIRE(name != NULL && *name == NULL);
190
0
  REQUIRE(VALID_RRITERATOR(it));
191
0
  REQUIRE(it->result == ISC_R_SUCCESS);
192
0
  REQUIRE(rdataset == NULL || *rdataset == NULL);
193
0
  REQUIRE(rdata == NULL || *rdata == NULL);
194
195
0
  *name = dns_fixedname_name(&it->fixedname);
196
0
  *ttl = it->rdataset.ttl;
197
198
0
  dns_rdata_reset(&it->rdata);
199
0
  dns_rdataset_current(&it->rdataset, &it->rdata);
200
201
0
  SET_IF_NOT_NULL(rdataset, &it->rdataset);
202
203
  SET_IF_NOT_NULL(rdata, &it->rdata);
204
0
}