Coverage Report

Created: 2026-09-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdatalist.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
#include <stddef.h>
17
#include <string.h>
18
19
#include <isc/util.h>
20
21
#include <dns/name.h>
22
#include <dns/nsec3.h>
23
#include <dns/rdata.h>
24
#include <dns/rdatalist.h>
25
#include <dns/rdataset.h>
26
27
static dns_rdatasetmethods_t methods = {
28
  .disassociate = dns_rdatalist_disassociate,
29
  .first = dns__rdatalist_first,
30
  .next = dns__rdatalist_next,
31
  .current = dns__rdatalist_current,
32
  .clone = dns__rdatalist_clone,
33
  .count = dns__rdatalist_count,
34
  .addnoqname = dns__rdatalist_addnoqname,
35
  .getnoqname = dns__rdatalist_getnoqname,
36
  .setownercase = dns__rdatalist_setownercase,
37
  .getownercase = dns__rdatalist_getownercase,
38
};
39
40
void
41
7.70M
dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
42
7.70M
  REQUIRE(rdatalist != NULL);
43
44
  /*
45
   * Initialize rdatalist.
46
   */
47
7.70M
  *rdatalist = (dns_rdatalist_t){
48
7.70M
    .rdata = ISC_LIST_INITIALIZER,
49
7.70M
    .link = ISC_LINK_INITIALIZER,
50
7.70M
  };
51
7.70M
  memset(rdatalist->upper, 0xeb, sizeof(rdatalist->upper));
52
53
  /*
54
   * Clear upper set bit.
55
   */
56
7.70M
  rdatalist->upper[0] &= ~0x01;
57
7.70M
}
58
59
void
60
7.69M
dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist, dns_rdataset_t *rdataset) {
61
  /*
62
   * Make 'rdataset' refer to the rdata in 'rdatalist'.
63
   */
64
65
7.69M
  REQUIRE(rdatalist != NULL);
66
7.69M
  REQUIRE(DNS_RDATASET_VALID(rdataset));
67
7.69M
  REQUIRE(!dns_rdataset_isassociated(rdataset));
68
69
  /* Check if dns_rdatalist_init has was called. */
70
7.69M
  REQUIRE(rdatalist->upper[0] == 0xea);
71
72
7.69M
  *rdataset = (dns_rdataset_t){
73
7.69M
    .methods = &methods,
74
7.69M
    .rdclass = rdatalist->rdclass,
75
7.69M
    .type = rdatalist->type,
76
7.69M
    .covers = rdatalist->covers,
77
7.69M
    .ttl = rdatalist->ttl,
78
7.69M
    .rdlist.list = rdatalist,
79
80
7.69M
    .link = rdataset->link,
81
7.69M
    .attributes = rdataset->attributes,
82
7.69M
    .magic = rdataset->magic,
83
7.69M
  };
84
7.69M
}
85
86
void
87
dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
88
294k
         dns_rdatalist_t **rdatalist) {
89
294k
  REQUIRE(rdatalist != NULL && rdataset != NULL);
90
294k
  REQUIRE(rdataset->methods == &methods);
91
92
294k
  *rdatalist = rdataset->rdlist.list;
93
294k
}
94
95
void
96
389k
dns_rdatalist_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
97
389k
  UNUSED(rdataset);
98
389k
}
99
100
isc_result_t
101
7.66M
dns__rdatalist_first(dns_rdataset_t *rdataset) {
102
7.66M
  dns_rdatalist_t *rdatalist = NULL;
103
104
7.66M
  rdatalist = rdataset->rdlist.list;
105
7.66M
  rdataset->rdlist.iter = ISC_LIST_HEAD(rdatalist->rdata);
106
107
7.66M
  if (rdataset->rdlist.iter == NULL) {
108
175k
    return ISC_R_NOMORE;
109
175k
  }
110
111
7.48M
  return ISC_R_SUCCESS;
112
7.66M
}
113
114
isc_result_t
115
7.76M
dns__rdatalist_next(dns_rdataset_t *rdataset) {
116
7.76M
  dns_rdata_t *rdata;
117
118
7.76M
  rdata = rdataset->rdlist.iter;
119
7.76M
  if (rdata == NULL) {
120
0
    return ISC_R_NOMORE;
121
0
  }
122
123
7.76M
  rdataset->rdlist.iter = ISC_LIST_NEXT(rdata, link);
124
125
7.76M
  if (rdataset->rdlist.iter == NULL) {
126
7.48M
    return ISC_R_NOMORE;
127
7.48M
  }
128
129
279k
  return ISC_R_SUCCESS;
130
7.76M
}
131
132
void
133
7.76M
dns__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
134
7.76M
  dns_rdata_t *list_rdata;
135
136
7.76M
  list_rdata = rdataset->rdlist.iter;
137
7.76M
  INSIST(list_rdata != NULL);
138
139
7.76M
  dns_rdata_clone(list_rdata, rdata);
140
7.76M
}
141
142
void
143
dns__rdatalist_clone(const dns_rdataset_t *source,
144
0
         dns_rdataset_t *target DNS__DB_FLARG) {
145
0
  REQUIRE(source != NULL);
146
0
  REQUIRE(target != NULL);
147
148
0
  *target = *source;
149
150
0
  target->rdlist.iter = NULL;
151
0
}
152
153
unsigned int
154
7.36M
dns__rdatalist_count(dns_rdataset_t *rdataset) {
155
7.36M
  dns_rdatalist_t *rdatalist = NULL;
156
7.36M
  unsigned int count;
157
158
7.36M
  REQUIRE(rdataset != NULL);
159
160
7.36M
  rdatalist = rdataset->rdlist.list;
161
162
7.36M
  count = 0;
163
7.52M
  ISC_LIST_FOREACH(rdatalist->rdata, rdata, link) {
164
7.52M
    count++;
165
7.52M
  }
166
167
7.36M
  return count;
168
7.36M
}
169
170
isc_result_t
171
0
dns__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
172
0
  dns_rdataset_t *neg = NULL;
173
0
  dns_rdataset_t *negsig = NULL;
174
0
  dns_ttl_t ttl;
175
176
0
  REQUIRE(rdataset != NULL);
177
178
0
  ISC_LIST_FOREACH(name->list, rdset, link) {
179
0
    if (rdset->rdclass != rdataset->rdclass ||
180
0
        !dns_rdatatype_isnsec(rdset->type))
181
0
    {
182
0
      continue;
183
0
    }
184
185
0
    ISC_LIST_FOREACH(name->list, sigset, link) {
186
0
      if (sigset->type == dns_rdatatype_rrsig &&
187
0
          sigset->covers == rdset->type)
188
0
      {
189
0
        neg = rdset;
190
0
        negsig = sigset;
191
0
        break;
192
0
      }
193
0
    }
194
0
  }
195
196
0
  if (neg == NULL || negsig == NULL) {
197
0
    return ISC_R_NOTFOUND;
198
0
  }
199
200
  /*
201
   * Minimise ttl.
202
   */
203
0
  ttl = rdataset->ttl;
204
0
  if (neg->ttl < ttl) {
205
0
    ttl = neg->ttl;
206
0
  }
207
0
  if (negsig->ttl < ttl) {
208
0
    ttl = negsig->ttl;
209
0
  }
210
0
  rdataset->ttl = neg->ttl = negsig->ttl = ttl;
211
0
  rdataset->attributes.noqname = true;
212
0
  rdataset->rdlist.noqname = name;
213
214
0
  return ISC_R_SUCCESS;
215
0
}
216
217
isc_result_t
218
dns__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
219
        dns_rdataset_t *neg,
220
0
        dns_rdataset_t *negsig DNS__DB_FLARG) {
221
0
  dns_rdataclass_t rdclass;
222
0
  dns_rdataset_t *tneg = NULL;
223
0
  dns_rdataset_t *tnegsig = NULL;
224
0
  dns_name_t *noqname = NULL;
225
226
0
  REQUIRE(rdataset != NULL);
227
0
  REQUIRE(rdataset->attributes.noqname);
228
229
0
  rdclass = rdataset->rdclass;
230
0
  noqname = rdataset->rdlist.noqname;
231
232
0
  (void)dns_name_dynamic(noqname); /* Sanity Check. */
233
234
0
  ISC_LIST_FOREACH(noqname->list, rdset, link) {
235
0
    if (rdset->rdclass != rdclass) {
236
0
      continue;
237
0
    }
238
0
    if (dns_rdatatype_isnsec(rdset->type)) {
239
0
      tneg = rdset;
240
0
    }
241
0
  }
242
0
  if (tneg == NULL) {
243
0
    return ISC_R_NOTFOUND;
244
0
  }
245
246
0
  ISC_LIST_FOREACH(noqname->list, rdset, link) {
247
0
    if (rdset->type == dns_rdatatype_rrsig &&
248
0
        rdset->covers == tneg->type)
249
0
    {
250
0
      tnegsig = rdset;
251
0
    }
252
0
  }
253
0
  if (tnegsig == NULL) {
254
0
    return ISC_R_NOTFOUND;
255
0
  }
256
257
0
  dns_name_clone(noqname, name);
258
0
  dns_rdataset_clone(tneg, neg);
259
0
  dns_rdataset_clone(tnegsig, negsig);
260
0
  return ISC_R_SUCCESS;
261
0
}
262
263
void
264
283k
dns__rdatalist_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
265
283k
  dns_rdatalist_t *rdatalist;
266
283k
  unsigned int i;
267
268
  /*
269
   * We do not need to worry about label lengths as they are all
270
   * less than or equal to 63.
271
   */
272
283k
  rdatalist = rdataset->rdlist.list;
273
283k
  memset(rdatalist->upper, 0, sizeof(rdatalist->upper));
274
2.36M
  for (i = 1; i < name->length; i++) {
275
2.07M
    if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) {
276
40.2k
      rdatalist->upper[i / 8] |= 1 << (i % 8);
277
40.2k
    }
278
2.07M
  }
279
  /*
280
   * Record that upper has been set.
281
   */
282
283k
  rdatalist->upper[0] |= 0x01;
283
283k
}
284
285
void
286
246k
dns__rdatalist_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
287
246k
  dns_rdatalist_t *rdatalist;
288
246k
  unsigned int i;
289
290
246k
  rdatalist = rdataset->rdlist.list;
291
246k
  if ((rdatalist->upper[0] & 0x01) == 0) {
292
74.8k
    return;
293
74.8k
  }
294
1.89M
  for (i = 0; i < name->length; i++) {
295
    /*
296
     * Set the case bit if it does not match the recorded bit.
297
     */
298
1.71M
    if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a &&
299
50.5k
        (rdatalist->upper[i / 8] & (1 << (i % 8))) != 0)
300
0
    {
301
0
      name->ndata[i] &= ~0x20; /* clear the lower case bit */
302
1.71M
    } else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a &&
303
42.1k
         (rdatalist->upper[i / 8] & (1 << (i % 8))) == 0)
304
0
    {
305
0
      name->ndata[i] |= 0x20; /* set the lower case bit */
306
0
    }
307
1.71M
  }
308
171k
}