Coverage Report

Created: 2022-03-10 07:56

/src/bind9/lib/dns/rriterator.c
Line
Count
Source (jump to first uncovered line)
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
  isc_result_t result;
41
0
  it->magic = RRITERATOR_MAGIC;
42
0
  it->db = db;
43
0
  it->dbit = NULL;
44
0
  it->ver = ver;
45
0
  it->now = now;
46
0
  it->node = NULL;
47
0
  result = dns_db_createiterator(it->db, 0, &it->dbit);
48
0
  if (result != ISC_R_SUCCESS) {
49
0
    return (result);
50
0
  }
51
0
  it->rdatasetit = NULL;
52
0
  dns_rdata_init(&it->rdata);
53
0
  dns_rdataset_init(&it->rdataset);
54
0
  dns_fixedname_init(&it->fixedname);
55
0
  INSIST(!dns_rdataset_isassociated(&it->rdataset));
56
0
  it->result = ISC_R_SUCCESS;
57
0
  return (it->result);
58
0
}
59
60
isc_result_t
61
0
dns_rriterator_first(dns_rriterator_t *it) {
62
0
  REQUIRE(VALID_RRITERATOR(it));
63
  /* Reset state */
64
0
  if (dns_rdataset_isassociated(&it->rdataset)) {
65
0
    dns_rdataset_disassociate(&it->rdataset);
66
0
  }
67
0
  if (it->rdatasetit != NULL) {
68
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
69
0
  }
70
0
  if (it->node != NULL) {
71
0
    dns_db_detachnode(it->db, &it->node);
72
0
  }
73
0
  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
0
  while (it->result == ISC_R_SUCCESS) {
80
0
    it->result = dns_dbiterator_current(
81
0
      it->dbit, &it->node,
82
0
      dns_fixedname_name(&it->fixedname));
83
0
    if (it->result != ISC_R_SUCCESS) {
84
0
      return (it->result);
85
0
    }
86
87
0
    it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
88
0
             it->now, &it->rdatasetit);
89
0
    if (it->result != ISC_R_SUCCESS) {
90
0
      return (it->result);
91
0
    }
92
93
0
    it->result = dns_rdatasetiter_first(it->rdatasetit);
94
0
    if (it->result != ISC_R_SUCCESS) {
95
      /*
96
       * This node is empty. Try next node.
97
       */
98
0
      dns_rdatasetiter_destroy(&it->rdatasetit);
99
0
      dns_db_detachnode(it->db, &it->node);
100
0
      it->result = dns_dbiterator_next(it->dbit);
101
0
      continue;
102
0
    }
103
0
    dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
104
0
    dns_rdataset_getownercase(&it->rdataset,
105
0
            dns_fixedname_name(&it->fixedname));
106
0
    it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
107
0
    it->result = dns_rdataset_first(&it->rdataset);
108
0
    return (it->result);
109
0
  }
110
0
  return (it->result);
111
0
}
112
113
isc_result_t
114
0
dns_rriterator_nextrrset(dns_rriterator_t *it) {
115
0
  REQUIRE(VALID_RRITERATOR(it));
116
0
  if (dns_rdataset_isassociated(&it->rdataset)) {
117
0
    dns_rdataset_disassociate(&it->rdataset);
118
0
  }
119
0
  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
0
  while (it->result == ISC_R_NOMORE) {
125
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
126
0
    dns_db_detachnode(it->db, &it->node);
127
0
    it->result = dns_dbiterator_next(it->dbit);
128
0
    if (it->result == ISC_R_NOMORE) {
129
      /* We are at the end of the entire database. */
130
0
      return (it->result);
131
0
    }
132
0
    if (it->result != ISC_R_SUCCESS) {
133
0
      return (it->result);
134
0
    }
135
0
    it->result = dns_dbiterator_current(
136
0
      it->dbit, &it->node,
137
0
      dns_fixedname_name(&it->fixedname));
138
0
    if (it->result != ISC_R_SUCCESS) {
139
0
      return (it->result);
140
0
    }
141
0
    it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
142
0
             it->now, &it->rdatasetit);
143
0
    if (it->result != ISC_R_SUCCESS) {
144
0
      return (it->result);
145
0
    }
146
0
    it->result = dns_rdatasetiter_first(it->rdatasetit);
147
0
  }
148
0
  if (it->result != ISC_R_SUCCESS) {
149
0
    return (it->result);
150
0
  }
151
0
  dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
152
0
  dns_rdataset_getownercase(&it->rdataset,
153
0
          dns_fixedname_name(&it->fixedname));
154
0
  it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
155
0
  it->result = dns_rdataset_first(&it->rdataset);
156
0
  return (it->result);
157
0
}
158
159
isc_result_t
160
0
dns_rriterator_next(dns_rriterator_t *it) {
161
0
  REQUIRE(VALID_RRITERATOR(it));
162
0
  if (it->result != ISC_R_SUCCESS) {
163
0
    return (it->result);
164
0
  }
165
166
0
  INSIST(it->dbit != NULL);
167
0
  INSIST(it->node != NULL);
168
0
  INSIST(it->rdatasetit != NULL);
169
170
0
  it->result = dns_rdataset_next(&it->rdataset);
171
0
  if (it->result == ISC_R_NOMORE) {
172
0
    return (dns_rriterator_nextrrset(it));
173
0
  }
174
0
  return (it->result);
175
0
}
176
177
void
178
0
dns_rriterator_pause(dns_rriterator_t *it) {
179
0
  REQUIRE(VALID_RRITERATOR(it));
180
0
  RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
181
0
}
182
183
void
184
0
dns_rriterator_destroy(dns_rriterator_t *it) {
185
0
  REQUIRE(VALID_RRITERATOR(it));
186
0
  if (dns_rdataset_isassociated(&it->rdataset)) {
187
0
    dns_rdataset_disassociate(&it->rdataset);
188
0
  }
189
0
  if (it->rdatasetit != NULL) {
190
0
    dns_rdatasetiter_destroy(&it->rdatasetit);
191
0
  }
192
0
  if (it->node != NULL) {
193
0
    dns_db_detachnode(it->db, &it->node);
194
0
  }
195
0
  dns_dbiterator_destroy(&it->dbit);
196
0
}
197
198
void
199
dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name, uint32_t *ttl,
200
0
           dns_rdataset_t **rdataset, dns_rdata_t **rdata) {
201
0
  REQUIRE(name != NULL && *name == NULL);
202
0
  REQUIRE(VALID_RRITERATOR(it));
203
0
  REQUIRE(it->result == ISC_R_SUCCESS);
204
0
  REQUIRE(rdataset == NULL || *rdataset == NULL);
205
0
  REQUIRE(rdata == NULL || *rdata == NULL);
206
207
0
  *name = dns_fixedname_name(&it->fixedname);
208
0
  *ttl = it->rdataset.ttl;
209
210
0
  dns_rdata_reset(&it->rdata);
211
0
  dns_rdataset_current(&it->rdataset, &it->rdata);
212
213
0
  if (rdataset != NULL) {
214
0
    *rdataset = &it->rdataset;
215
0
  }
216
217
0
  if (rdata != NULL) {
218
0
    *rdata = &it->rdata;
219
0
  }
220
0
}