Coverage Report

Created: 2025-08-03 06:33

/src/bind9/lib/dns/rdataslab.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
#include <ctype.h>
17
#include <stdbool.h>
18
#include <stdlib.h>
19
20
#include <isc/ascii.h>
21
#include <isc/mem.h>
22
#include <isc/region.h>
23
#include <isc/result.h>
24
#include <isc/string.h>
25
#include <isc/util.h>
26
27
#include <dns/db.h>
28
#include <dns/rdata.h>
29
#include <dns/rdataset.h>
30
#include <dns/rdataslab.h>
31
#include <dns/stats.h>
32
33
#define CASESET(header)                                \
34
76.9k
  ((atomic_load_acquire(&(header)->attributes) & \
35
76.9k
    DNS_SLABHEADERATTR_CASESET) != 0)
36
#define CASEFULLYLOWER(header)                         \
37
0
  ((atomic_load_acquire(&(header)->attributes) & \
38
0
    DNS_SLABHEADERATTR_CASEFULLYLOWER) != 0)
39
#define NONEXISTENT(header)                            \
40
5.98M
  ((atomic_load_acquire(&(header)->attributes) & \
41
5.98M
    DNS_SLABHEADERATTR_NONEXISTENT) != 0)
42
#define NEGATIVE(header)                               \
43
0
  ((atomic_load_acquire(&(header)->attributes) & \
44
0
    DNS_SLABHEADERATTR_NEGATIVE) != 0)
45
46
/*
47
 * The rdataslab structure allows iteration to occur in both load order
48
 * and DNSSEC order.  The structure is as follows:
49
 *
50
 *  header    (dns_slabheader_t)
51
 *  record count  (2 bytes)
52
 *  offset table  (4 x record count bytes in load order)
53
 *  data records
54
 *    data length (2 bytes)
55
 *    order   (2 bytes)
56
 *    meta data (1 byte for RRSIG's)
57
 *    data    (data length bytes)
58
 *
59
 * A "raw" rdataslab is the same but without the header.
60
 *
61
 * DNSSEC order traversal is performed by walking the data records.
62
 *
63
 * The order is stored with record to allow for efficient reconstruction
64
 * of the offset table following a merge or subtraction.
65
 *
66
 * The iterator methods in rbtdb support both load order and DNSSEC order
67
 * iteration.
68
 *
69
 * WARNING:
70
 *  rbtdb.c directly interacts with the slab's raw structures.  If the
71
 *  structure changes then rbtdb.c also needs to be updated to reflect
72
 *  the changes.  See the areas tagged with "RDATASLAB".
73
 */
74
75
126M
#define peek_uint16(buffer) ({ ((uint16_t)*(buffer) << 8) | *((buffer) + 1); })
76
#define get_uint16(buffer)                            \
77
126M
  ({                                            \
78
126M
    uint16_t __ret = peek_uint16(buffer); \
79
126M
    buffer += sizeof(uint16_t);           \
80
126M
    __ret;                                \
81
126M
  })
82
#define put_uint16(buffer, val)                  \
83
35.6M
  ({                                       \
84
35.6M
    *buffer++ = (val & 0xff00) >> 8; \
85
35.6M
    *buffer++ = (val & 0x00ff);      \
86
35.6M
  })
87
88
static void
89
rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG);
90
static isc_result_t
91
rdataset_first(dns_rdataset_t *rdataset);
92
static isc_result_t
93
rdataset_next(dns_rdataset_t *rdataset);
94
static void
95
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
96
static void
97
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG);
98
static unsigned int
99
rdataset_count(dns_rdataset_t *rdataset);
100
static isc_result_t
101
rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
102
        dns_rdataset_t *neg, dns_rdataset_t *negsig DNS__DB_FLARG);
103
static isc_result_t
104
rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
105
        dns_rdataset_t *neg, dns_rdataset_t *negsig DNS__DB_FLARG);
106
static void
107
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
108
static void
109
rdataset_expire(dns_rdataset_t *rdataset DNS__DB_FLARG);
110
static void
111
rdataset_clearprefetch(dns_rdataset_t *rdataset);
112
static void
113
rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name);
114
static void
115
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
116
static dns_slabheader_t *
117
rdataset_getheader(const dns_rdataset_t *rdataset);
118
static bool
119
rdataset_equals(const dns_rdataset_t *rdataset1,
120
    const dns_rdataset_t *rdataset2);
121
122
dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods = {
123
  .disassociate = rdataset_disassociate,
124
  .first = rdataset_first,
125
  .next = rdataset_next,
126
  .current = rdataset_current,
127
  .clone = rdataset_clone,
128
  .count = rdataset_count,
129
  .getnoqname = rdataset_getnoqname,
130
  .getclosest = rdataset_getclosest,
131
  .settrust = rdataset_settrust,
132
  .expire = rdataset_expire,
133
  .clearprefetch = rdataset_clearprefetch,
134
  .setownercase = rdataset_setownercase,
135
  .getownercase = rdataset_getownercase,
136
  .getheader = rdataset_getheader,
137
  .equals = rdataset_equals,
138
};
139
140
/*% Note: the "const void *" are just to make qsort happy.  */
141
static int
142
679k
compare_rdata(const void *p1, const void *p2) {
143
679k
  return dns_rdata_compare(p1, p2);
144
679k
}
145
146
static isc_result_t
147
makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
148
5.91M
   uint32_t maxrrperset) {
149
  /*
150
   * Use &removed as a sentinel pointer for duplicate
151
   * rdata as rdata.data == NULL is valid.
152
   */
153
5.91M
  static unsigned char removed;
154
5.91M
  dns_rdata_t *rdata = NULL;
155
5.91M
  unsigned char *rawbuf = NULL;
156
5.91M
  unsigned int headerlen = sizeof(dns_slabheader_t);
157
5.91M
  unsigned int buflen = headerlen + 2;
158
5.91M
  isc_result_t result;
159
5.91M
  unsigned int nitems;
160
5.91M
  unsigned int nalloc;
161
5.91M
  unsigned int length;
162
5.91M
  size_t i;
163
5.91M
  size_t rdatasize;
164
165
  /*
166
   * If the source rdataset is also a slab, we don't need
167
   * to do anything special, just copy the whole slab to a
168
   * new buffer.
169
   */
170
5.91M
  if (rdataset->methods == &dns_rdataslab_rdatasetmethods) {
171
0
    dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
172
0
    buflen = dns_rdataslab_size(header);
173
174
0
    rawbuf = isc_mem_get(mctx, buflen);
175
0
    region->base = rawbuf;
176
0
    region->length = buflen;
177
178
0
    memmove(rawbuf, header, buflen);
179
0
    return ISC_R_SUCCESS;
180
0
  }
181
182
  /*
183
   * If there are no rdata then we just need to allocate a header
184
   * with a zero record count.
185
   */
186
5.91M
  nitems = dns_rdataset_count(rdataset);
187
5.91M
  if (nitems == 0) {
188
0
    if (rdataset->type != 0) {
189
0
      return ISC_R_FAILURE;
190
0
    }
191
0
    rawbuf = isc_mem_get(mctx, buflen);
192
0
    region->base = rawbuf;
193
0
    region->length = buflen;
194
0
    rawbuf += headerlen;
195
0
    put_uint16(rawbuf, 0);
196
0
    return ISC_R_SUCCESS;
197
0
  }
198
199
5.91M
  if (maxrrperset > 0 && nitems > maxrrperset) {
200
0
    return DNS_R_TOOMANYRECORDS;
201
0
  }
202
203
5.91M
  if (nitems > 0xffff) {
204
0
    return ISC_R_NOSPACE;
205
0
  }
206
207
  /*
208
   * Remember the original number of items.
209
   */
210
5.91M
  nalloc = nitems;
211
212
5.91M
  RUNTIME_CHECK(!ISC_OVERFLOW_MUL(nalloc, sizeof(rdata[0]), &rdatasize));
213
5.91M
  rdata = isc_mem_get(mctx, rdatasize);
214
215
  /*
216
   * Save all of the rdata members into an array.
217
   */
218
5.91M
  result = dns_rdataset_first(rdataset);
219
5.91M
  if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
220
0
    goto free_rdatas;
221
0
  }
222
11.9M
  for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
223
6.04M
    INSIST(result == ISC_R_SUCCESS);
224
6.04M
    dns_rdata_init(&rdata[i]);
225
6.04M
    dns_rdataset_current(rdataset, &rdata[i]);
226
6.04M
    INSIST(rdata[i].data != &removed);
227
6.04M
    result = dns_rdataset_next(rdataset);
228
6.04M
  }
229
5.91M
  if (i != nalloc || result != ISC_R_NOMORE) {
230
    /*
231
     * Somehow we iterated over fewer rdatas than
232
     * dns_rdataset_count() said there were or there
233
     * were more items than dns_rdataset_count said
234
     * there were.
235
     */
236
0
    result = ISC_R_FAILURE;
237
0
    goto free_rdatas;
238
0
  }
239
240
  /*
241
   * Put into DNSSEC order.
242
   */
243
5.91M
  if (nalloc > 1U) {
244
17.9k
    qsort(rdata, nalloc, sizeof(rdata[0]), compare_rdata);
245
17.9k
  }
246
247
  /*
248
   * Remove duplicates and compute the total storage required.
249
   *
250
   * If an rdata is not a duplicate, accumulate the storage size
251
   * required for the rdata.  We do not store the class, type, etc,
252
   * just the rdata, so our overhead is 2 bytes for the number of
253
   * records, and 8 for each rdata, (length(2), offset(4) and order(2))
254
   * and then the rdata itself.
255
   */
256
6.04M
  for (i = 1; i < nalloc; i++) {
257
127k
    if (compare_rdata(&rdata[i - 1], &rdata[i]) == 0) {
258
110k
      rdata[i - 1].data = &removed;
259
110k
      nitems--;
260
110k
    } else {
261
17.8k
      buflen += (2 + rdata[i - 1].length);
262
      /*
263
       * Provide space to store the per RR meta data.
264
       */
265
17.8k
      if (rdataset->type == dns_rdatatype_rrsig) {
266
2.28k
        buflen++;
267
2.28k
      }
268
17.8k
    }
269
127k
  }
270
271
  /*
272
   * Don't forget the last item!
273
   */
274
5.91M
  buflen += (2 + rdata[i - 1].length);
275
276
  /*
277
   * Provide space to store the per RR meta data.
278
   */
279
5.91M
  if (rdataset->type == dns_rdatatype_rrsig) {
280
12.6k
    buflen++;
281
12.6k
  }
282
283
  /*
284
   * Ensure that singleton types are actually singletons.
285
   */
286
5.91M
  if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
287
    /*
288
     * We have a singleton type, but there's more than one
289
     * RR in the rdataset.
290
     */
291
53
    result = DNS_R_SINGLETON;
292
53
    goto free_rdatas;
293
53
  }
294
295
  /*
296
   * Allocate the memory, set up a buffer, start copying in
297
   * data.
298
   */
299
5.91M
  rawbuf = isc_mem_get(mctx, buflen);
300
301
5.91M
  region->base = rawbuf;
302
5.91M
  region->length = buflen;
303
5.91M
  rawbuf += headerlen;
304
5.91M
  put_uint16(rawbuf, nitems);
305
306
11.9M
  for (i = 0; i < nalloc; i++) {
307
6.03M
    if (rdata[i].data == &removed) {
308
108k
      continue;
309
108k
    }
310
5.92M
    length = rdata[i].length;
311
5.92M
    if (rdataset->type == dns_rdatatype_rrsig) {
312
14.9k
      length++;
313
14.9k
    }
314
5.92M
    INSIST(length <= 0xffff);
315
316
5.92M
    put_uint16(rawbuf, length);
317
318
    /*
319
     * Store the per RR meta data.
320
     */
321
5.92M
    if (rdataset->type == dns_rdatatype_rrsig) {
322
14.9k
      *rawbuf++ = (rdata[i].flags & DNS_RDATA_OFFLINE)
323
14.9k
              ? DNS_RDATASLAB_OFFLINE
324
14.9k
              : 0;
325
14.9k
    }
326
5.92M
    if (rdata[i].length != 0) {
327
5.92M
      memmove(rawbuf, rdata[i].data, rdata[i].length);
328
5.92M
    }
329
5.92M
    rawbuf += rdata[i].length;
330
5.92M
  }
331
332
5.91M
  result = ISC_R_SUCCESS;
333
334
5.91M
free_rdatas:
335
5.91M
  isc_mem_put(mctx, rdata, rdatasize);
336
5.91M
  return result;
337
5.91M
}
338
339
isc_result_t
340
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
341
5.91M
         isc_region_t *region, uint32_t maxrrperset) {
342
5.91M
  isc_result_t result;
343
344
5.91M
  result = makeslab(rdataset, mctx, region, maxrrperset);
345
5.91M
  if (result == ISC_R_SUCCESS) {
346
5.91M
    dns_slabheader_t *new = (dns_slabheader_t *)region->base;
347
348
5.91M
    *new = (dns_slabheader_t){
349
5.91M
      .type = DNS_TYPEPAIR_VALUE(rdataset->type,
350
5.91M
               rdataset->covers),
351
5.91M
      .trust = rdataset->trust,
352
5.91M
      .ttl = rdataset->ttl,
353
5.91M
      .link = ISC_LINK_INITIALIZER,
354
5.91M
    };
355
5.91M
  }
356
357
5.91M
  return result;
358
5.91M
}
359
360
unsigned int
361
10.9M
dns_rdataslab_size(dns_slabheader_t *header) {
362
10.9M
  REQUIRE(header != NULL);
363
364
10.9M
  unsigned char *slab = (unsigned char *)header +
365
10.9M
            sizeof(dns_slabheader_t);
366
10.9M
  INSIST(slab != NULL);
367
368
10.9M
  unsigned char *current = slab;
369
10.9M
  uint16_t count = get_uint16(current);
370
371
92.5M
  while (count-- > 0) {
372
81.6M
    uint16_t length = get_uint16(current);
373
81.6M
    current += length;
374
81.6M
  }
375
376
10.9M
  return (unsigned int)(current - slab) + sizeof(dns_slabheader_t);
377
10.9M
}
378
379
unsigned int
380
4.94M
dns_rdataslab_count(dns_slabheader_t *header) {
381
4.94M
  REQUIRE(header != NULL);
382
383
4.94M
  unsigned char *current = (unsigned char *)header + sizeof(*header);
384
4.94M
  uint16_t count = get_uint16(current);
385
386
4.94M
  return count;
387
4.94M
}
388
389
/*
390
 * Make the dns_rdata_t 'rdata' refer to the slab item
391
 * beginning at '*current', which is part of a slab of type
392
 * 'type' and class 'rdclass', and advance '*current' to
393
 * point to the next item in the slab.
394
 */
395
static void
396
rdata_from_slabitem(unsigned char **current, dns_rdataclass_t rdclass,
397
26.8M
        dns_rdatatype_t type, dns_rdata_t *rdata) {
398
26.8M
  unsigned char *tcurrent = *current;
399
26.8M
  isc_region_t region;
400
26.8M
  bool offline = false;
401
26.8M
  uint16_t length = get_uint16(tcurrent);
402
403
26.8M
  if (type == dns_rdatatype_rrsig) {
404
29.8k
    if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0) {
405
0
      offline = true;
406
0
    }
407
29.8k
    length--;
408
29.8k
    tcurrent++;
409
29.8k
  }
410
26.8M
  region.length = length;
411
26.8M
  region.base = tcurrent;
412
26.8M
  tcurrent += region.length;
413
26.8M
  dns_rdata_fromregion(rdata, rdclass, type, &region);
414
26.8M
  if (offline) {
415
0
    rdata->flags |= DNS_RDATA_OFFLINE;
416
0
  }
417
26.8M
  *current = tcurrent;
418
26.8M
}
419
420
static void
421
rdata_to_slabitem(unsigned char **current, dns_rdatatype_t type,
422
23.6M
      dns_rdata_t *rdata) {
423
23.6M
  unsigned int length = rdata->length;
424
23.6M
  unsigned char *data = rdata->data;
425
23.6M
  unsigned char *p = *current;
426
427
23.6M
  if (type == dns_rdatatype_rrsig) {
428
5.51k
    length++;
429
5.51k
    data--;
430
5.51k
  }
431
432
23.6M
  put_uint16(p, length);
433
23.6M
  memmove(p, data, length);
434
23.6M
  p += length;
435
436
23.6M
  *current = p;
437
23.6M
}
438
439
typedef struct slabinfo {
440
  unsigned char *pos;
441
  dns_rdata_t rdata;
442
  bool dup;
443
} slabinfo_t;
444
445
isc_result_t
446
dns_rdataslab_merge(dns_slabheader_t *oheader, dns_slabheader_t *nheader,
447
        isc_mem_t *mctx, dns_rdataclass_t rdclass,
448
        dns_rdatatype_t type, unsigned int flags,
449
1.12M
        uint32_t maxrrperset, dns_slabheader_t **theaderp) {
450
1.12M
  isc_result_t result = ISC_R_SUCCESS;
451
1.12M
  unsigned char *ocurrent = NULL, *ncurrent = NULL, *tcurrent = NULL;
452
1.12M
  unsigned int ocount, ncount, tlength, tcount = 0;
453
1.12M
  slabinfo_t *oinfo = NULL, *ninfo = NULL;
454
1.12M
  size_t o = 0, n = 0;
455
456
1.12M
  REQUIRE(theaderp != NULL && *theaderp == NULL);
457
1.12M
  REQUIRE(oheader != NULL && nheader != NULL);
458
459
1.12M
  ocurrent = (unsigned char *)oheader + sizeof(dns_slabheader_t);
460
1.12M
  ocount = get_uint16(ocurrent);
461
462
1.12M
  ncurrent = (unsigned char *)nheader + sizeof(dns_slabheader_t);
463
1.12M
  ncount = get_uint16(ncurrent);
464
465
1.12M
  INSIST(ocount > 0 && ncount > 0);
466
467
1.12M
  if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
468
0
    return DNS_R_TOOMANYRECORDS;
469
0
  }
470
471
  /*
472
   * Figure out the target length. Start with the header,
473
   * plus 2 octets for the count.
474
   */
475
1.12M
  tlength = sizeof(dns_slabheader_t) + 2;
476
477
  /*
478
   * Gather the rdatas in the old slab and add their lengths to
479
   * the larget length.
480
   */
481
1.12M
  oinfo = isc_mem_cget(mctx, ocount, sizeof(struct slabinfo));
482
26.7M
  for (size_t i = 0; i < ocount; i++) {
483
25.6M
    oinfo[i].pos = ocurrent;
484
25.6M
    dns_rdata_init(&oinfo[i].rdata);
485
25.6M
    rdata_from_slabitem(&ocurrent, rdclass, type, &oinfo[i].rdata);
486
25.6M
    tlength += ocurrent - oinfo[i].pos;
487
25.6M
  }
488
489
  /*
490
   * Then add the length of rdatas in the new slab that aren't
491
   * duplicated in the old slab.
492
   */
493
1.12M
  ninfo = isc_mem_cget(mctx, ncount, sizeof(struct slabinfo));
494
2.25M
  for (size_t i = 0; i < ncount; i++) {
495
1.13M
    ninfo[i].pos = ncurrent;
496
1.13M
    dns_rdata_init(&ninfo[i].rdata);
497
1.13M
    rdata_from_slabitem(&ncurrent, rdclass, type, &ninfo[i].rdata);
498
499
25.2M
    for (size_t j = 0; j < ocount; j++) {
500
25.2M
      if (oinfo[j].dup) {
501
        /*
502
         * This was already found to be
503
         * duplicated; no need to compare
504
         * it again.
505
         */
506
18.1k
        continue;
507
18.1k
      }
508
509
25.1M
      if (dns_rdata_compare(&oinfo[j].rdata,
510
25.1M
                &ninfo[i].rdata) == 0)
511
1.05M
      {
512
        /*
513
         * Found a dup. Mark the old copy as a
514
         * duplicate so we don't check it again;
515
         * mark the new copy as a duplicate so we
516
         * don't copy it to the target.
517
         */
518
1.05M
        oinfo[j].dup = ninfo[i].dup = true;
519
1.05M
        break;
520
1.05M
      }
521
25.1M
    }
522
523
1.13M
    if (ninfo[i].dup) {
524
1.05M
      continue;
525
1.05M
    }
526
527
    /*
528
     * We will be copying this item to the target, so
529
     * add its length to tlength and increment tcount.
530
     */
531
72.3k
    tlength += ncurrent - ninfo[i].pos;
532
72.3k
    tcount++;
533
72.3k
  }
534
535
  /*
536
   * If the EXACT flag is set, there can't be any rdata in
537
   * the new slab that was also in the old. If tcount is less
538
   * than ncount, then we found such a duplicate.
539
   */
540
1.12M
  if (((flags & DNS_RDATASLAB_EXACT) != 0) && (tcount < ncount)) {
541
0
    result = DNS_R_NOTEXACT;
542
0
    goto cleanup;
543
0
  }
544
545
  /*
546
   * If nothing's being copied in from the new slab, and the
547
   * FORCE flag isn't set, we're done.
548
   */
549
1.12M
  if (tcount == 0 && (flags & DNS_RDATASLAB_FORCE) == 0) {
550
1.04M
    result = DNS_R_UNCHANGED;
551
1.04M
    goto cleanup;
552
1.04M
  }
553
554
  /* Add to tcount the total number of items from the old slab. */
555
77.0k
  tcount += ocount;
556
557
  /* Resposition ncurrent at the first item. */
558
77.0k
  ncurrent = (unsigned char *)nheader + sizeof(dns_slabheader_t) + 2;
559
560
  /* Single types can't have more than one RR. */
561
77.0k
  if (tcount > 1 && dns_rdatatype_issingleton(type)) {
562
16
    result = DNS_R_SINGLETON;
563
16
    goto cleanup;
564
16
  }
565
566
76.9k
  if (tcount > 0xffff) {
567
0
    result = ISC_R_NOSPACE;
568
0
    goto cleanup;
569
0
  }
570
571
  /* Allocate the target buffer and copy the new slab's header */
572
76.9k
  unsigned char *tstart = isc_mem_get(mctx, tlength);
573
574
76.9k
  memmove(tstart, nheader, sizeof(dns_slabheader_t));
575
76.9k
  tcurrent = tstart + sizeof(dns_slabheader_t);
576
577
  /* Write the new count, then start merging the slabs. */
578
76.9k
  put_uint16(tcurrent, tcount);
579
580
  /*
581
   * Now walk the sets together, adding each item in DNSSEC order,
582
   * and skipping over any more dups in the new slab.
583
   */
584
23.7M
  while (o < ocount || n < ncount) {
585
23.6M
    bool fromold;
586
587
    /* Skip to the next non-duplicate in the new slab. */
588
23.6M
    for (; n < ncount && ninfo[n].dup; n++)
589
9.48k
      ;
590
591
23.6M
    if (o == ocount) {
592
57.6k
      fromold = false;
593
23.6M
    } else if (n == ncount) {
594
717k
      fromold = true;
595
22.9M
    } else {
596
22.9M
      fromold = dns_rdata_compare(&oinfo[o].rdata,
597
22.9M
                &ninfo[n].rdata) < 0;
598
22.9M
    }
599
600
23.6M
    if (fromold) {
601
23.6M
      rdata_to_slabitem(&tcurrent, type, &oinfo[o].rdata);
602
23.6M
      if (++o < ocount) {
603
        /* Skip to the next rdata in the old slab */
604
23.5M
        continue;
605
23.5M
      }
606
23.6M
    } else {
607
72.3k
      rdata_to_slabitem(&tcurrent, type, &ninfo[n++].rdata);
608
72.3k
    }
609
23.6M
  }
610
611
76.9k
  INSIST(tcurrent == tstart + tlength);
612
613
76.9k
  *theaderp = (dns_slabheader_t *)tstart;
614
615
1.12M
cleanup:
616
1.12M
  isc_mem_cput(mctx, oinfo, ocount, sizeof(struct slabinfo));
617
1.12M
  isc_mem_cput(mctx, ninfo, ncount, sizeof(struct slabinfo));
618
619
1.12M
  return result;
620
76.9k
}
621
622
isc_result_t
623
dns_rdataslab_subtract(dns_slabheader_t *oheader, dns_slabheader_t *sheader,
624
           isc_mem_t *mctx, dns_rdataclass_t rdclass,
625
           dns_rdatatype_t type, unsigned int flags,
626
0
           dns_slabheader_t **theaderp) {
627
0
  isc_result_t result = ISC_R_SUCCESS;
628
0
  unsigned char *ocurrent = NULL, *scurrent = NULL;
629
0
  unsigned char *tstart = NULL, *tcurrent = NULL;
630
0
  unsigned int ocount, scount, tlength;
631
0
  unsigned int tcount = 0, rcount = 0;
632
0
  slabinfo_t *oinfo = NULL, *sinfo = NULL;
633
634
0
  REQUIRE(theaderp != NULL && *theaderp == NULL);
635
0
  REQUIRE(oheader != NULL && sheader != NULL);
636
637
0
  ocurrent = (unsigned char *)oheader + sizeof(dns_slabheader_t);
638
0
  ocount = get_uint16(ocurrent);
639
640
0
  scurrent = (unsigned char *)sheader + sizeof(dns_slabheader_t);
641
0
  scount = get_uint16(scurrent);
642
643
0
  INSIST(ocount > 0 && scount > 0);
644
645
  /* Get info about the rdatas being subtracted */
646
0
  sinfo = isc_mem_cget(mctx, scount, sizeof(struct slabinfo));
647
0
  for (size_t i = 0; i < scount; i++) {
648
0
    sinfo[i].pos = scurrent;
649
0
    dns_rdata_init(&sinfo[i].rdata);
650
0
    rdata_from_slabitem(&scurrent, rdclass, type, &sinfo[i].rdata);
651
0
  }
652
653
  /*
654
   * Figure out the target length. Start with the header,
655
   * plus 2 octets for the count.
656
   */
657
0
  tlength = sizeof(dns_slabheader_t) + 2;
658
659
  /*
660
   * Add the length of the rdatas in the old slab that
661
   * aren't being subtracted.
662
   */
663
0
  oinfo = isc_mem_cget(mctx, ocount, sizeof(struct slabinfo));
664
0
  for (size_t i = 0; i < ocount; i++) {
665
0
    bool matched = false;
666
667
0
    oinfo[i].pos = ocurrent;
668
0
    dns_rdata_init(&oinfo[i].rdata);
669
0
    rdata_from_slabitem(&ocurrent, rdclass, type, &oinfo[i].rdata);
670
671
0
    for (size_t j = 0; j < scount; j++) {
672
0
      if (sinfo[j].dup) {
673
0
        continue;
674
0
      } else if (dns_rdata_compare(&oinfo[i].rdata,
675
0
                 &sinfo[j].rdata) == 0)
676
0
      {
677
0
        matched = true;
678
0
        oinfo[i].dup = sinfo[j].dup = true;
679
0
        break;
680
0
      }
681
0
    }
682
683
0
    if (matched) {
684
      /* This item will be subtracted. */
685
0
      rcount++;
686
0
    } else {
687
      /*
688
       * This rdata wasn't in the slab to be subtracted,
689
       * so copy it to the target.  Add its length to
690
       * tlength and increment tcount.
691
       */
692
0
      tlength += ocurrent - oinfo[i].pos;
693
0
      tcount++;
694
0
    }
695
0
  }
696
697
  /*
698
   * If the EXACT flag wasn't set, check that all the records that
699
   * were to be subtracted actually did exist in the original slab.
700
   * (The numeric check works here because rdataslabs do not contain
701
   * duplicates.)
702
   */
703
0
  if ((flags & DNS_RDATASLAB_EXACT) != 0 && rcount != scount) {
704
0
    result = DNS_R_NOTEXACT;
705
0
    goto cleanup;
706
0
  }
707
708
  /*
709
   * If the resulting rdataslab would be empty, don't bother to
710
   * create a new buffer, just return.
711
   */
712
0
  if (tcount == 0) {
713
0
    result = DNS_R_NXRRSET;
714
0
    goto cleanup;
715
0
  }
716
717
  /*
718
   * If nothing is going to change, stop.
719
   */
720
0
  if (rcount == 0) {
721
0
    result = DNS_R_UNCHANGED;
722
0
    goto cleanup;
723
0
  }
724
725
  /*
726
   * Allocate the target buffer and copy the old slab's header.
727
   */
728
0
  tstart = isc_mem_get(mctx, tlength);
729
0
  memmove(tstart, oheader, sizeof(dns_slabheader_t));
730
0
  tcurrent = tstart + sizeof(dns_slabheader_t);
731
732
  /*
733
   * Write the new count.
734
   */
735
0
  put_uint16(tcurrent, tcount);
736
737
  /*
738
   * Copy the parts of the old slab that didn't have duplicates.
739
   */
740
0
  for (size_t i = 0; i < ocount; i++) {
741
0
    if (!oinfo[i].dup) {
742
0
      rdata_to_slabitem(&tcurrent, type, &oinfo[i].rdata);
743
0
    }
744
0
  }
745
746
0
  INSIST(tcurrent == tstart + tlength);
747
748
0
  *theaderp = (dns_slabheader_t *)tstart;
749
750
0
cleanup:
751
0
  isc_mem_cput(mctx, oinfo, ocount, sizeof(struct slabinfo));
752
0
  isc_mem_cput(mctx, sinfo, scount, sizeof(struct slabinfo));
753
754
0
  return result;
755
0
}
756
757
bool
758
0
dns_rdataslab_equal(dns_slabheader_t *slab1, dns_slabheader_t *slab2) {
759
0
  unsigned char *current1 = NULL, *current2 = NULL;
760
0
  unsigned int count1, count2;
761
762
0
  current1 = (unsigned char *)slab1 + sizeof(dns_slabheader_t);
763
0
  count1 = get_uint16(current1);
764
765
0
  current2 = (unsigned char *)slab2 + sizeof(dns_slabheader_t);
766
0
  count2 = get_uint16(current2);
767
768
0
  if (count1 != count2) {
769
0
    return false;
770
0
  } else if (count1 == 0) {
771
0
    return true;
772
0
  }
773
774
0
  while (count1-- > 0) {
775
0
    unsigned int length1 = get_uint16(current1);
776
0
    unsigned int length2 = get_uint16(current2);
777
778
0
    if (length1 != length2 ||
779
0
        memcmp(current1, current2, length1) != 0)
780
0
    {
781
0
      return false;
782
0
    }
783
784
0
    current1 += length1;
785
0
    current2 += length1;
786
0
  }
787
0
  return true;
788
0
}
789
790
bool
791
dns_rdataslab_equalx(dns_slabheader_t *slab1, dns_slabheader_t *slab2,
792
0
         dns_rdataclass_t rdclass, dns_rdatatype_t type) {
793
0
  unsigned char *current1 = NULL, *current2 = NULL;
794
0
  unsigned int count1, count2;
795
796
0
  current1 = (unsigned char *)slab1 + sizeof(dns_slabheader_t);
797
0
  count1 = get_uint16(current1);
798
799
0
  current2 = (unsigned char *)slab2 + sizeof(dns_slabheader_t);
800
0
  count2 = get_uint16(current2);
801
802
0
  if (count1 != count2) {
803
0
    return false;
804
0
  } else if (count1 == 0) {
805
0
    return true;
806
0
  }
807
808
0
  while (count1-- > 0) {
809
0
    dns_rdata_t rdata1 = DNS_RDATA_INIT;
810
0
    dns_rdata_t rdata2 = DNS_RDATA_INIT;
811
812
0
    rdata_from_slabitem(&current1, rdclass, type, &rdata1);
813
0
    rdata_from_slabitem(&current2, rdclass, type, &rdata2);
814
0
    if (dns_rdata_compare(&rdata1, &rdata2) != 0) {
815
0
      return false;
816
0
    }
817
0
  }
818
0
  return true;
819
0
}
820
821
void *
822
167
dns_slabheader_raw(dns_slabheader_t *header) {
823
167
  return header + 1;
824
167
}
825
826
void
827
5.91M
dns_slabheader_setownercase(dns_slabheader_t *header, const dns_name_t *name) {
828
5.91M
  unsigned int i;
829
5.91M
  bool fully_lower;
830
831
  /*
832
   * We do not need to worry about label lengths as they are all
833
   * less than or equal to 63.
834
   */
835
5.91M
  memset(header->upper, 0, sizeof(header->upper));
836
5.91M
  fully_lower = true;
837
131M
  for (i = 0; i < name->length; i++) {
838
125M
    if (isupper(name->ndata[i])) {
839
5.99M
      header->upper[i / 8] |= 1 << (i % 8);
840
5.99M
      fully_lower = false;
841
5.99M
    }
842
125M
  }
843
5.91M
  DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_CASESET);
844
5.91M
  if (fully_lower) {
845
3.73M
    DNS_SLABHEADER_SETATTR(header,
846
3.73M
               DNS_SLABHEADERATTR_CASEFULLYLOWER);
847
3.73M
  }
848
5.91M
}
849
850
void
851
76.9k
dns_slabheader_copycase(dns_slabheader_t *dest, dns_slabheader_t *src) {
852
76.9k
  if (CASESET(src)) {
853
76.9k
    uint_least16_t attr = DNS_SLABHEADER_GETATTR(
854
76.9k
      src, DNS_SLABHEADERATTR_CASESET |
855
76.9k
             DNS_SLABHEADERATTR_CASEFULLYLOWER);
856
76.9k
    DNS_SLABHEADER_SETATTR(dest, attr);
857
76.9k
    memmove(dest->upper, src->upper, sizeof(src->upper));
858
76.9k
  }
859
76.9k
}
860
861
void
862
5.98M
dns_slabheader_reset(dns_slabheader_t *h, dns_db_t *db, dns_dbnode_t *node) {
863
5.98M
  ISC_LINK_INIT(h, link);
864
5.98M
  h->heap_index = 0;
865
5.98M
  h->heap = NULL;
866
5.98M
  h->db = db;
867
5.98M
  h->node = node;
868
5.98M
  h->visited = false;
869
870
5.98M
  atomic_init(&h->attributes, 0);
871
5.98M
  atomic_init(&h->last_refresh_fail_ts, 0);
872
873
5.98M
  STATIC_ASSERT(sizeof(h->attributes) == 2,
874
5.98M
          "The .attributes field of dns_slabheader_t needs to be "
875
5.98M
          "16-bit int type exactly.");
876
5.98M
}
877
878
dns_slabheader_t *
879
0
dns_slabheader_new(dns_db_t *db, dns_dbnode_t *node) {
880
0
  dns_slabheader_t *h = NULL;
881
882
0
  h = isc_mem_get(db->mctx, sizeof(*h));
883
0
  *h = (dns_slabheader_t){
884
0
    .link = ISC_LINK_INITIALIZER,
885
0
  };
886
0
  dns_slabheader_reset(h, db, node);
887
0
  return h;
888
0
}
889
890
void
891
5.98M
dns_slabheader_destroy(dns_slabheader_t **headerp) {
892
5.98M
  unsigned int size;
893
5.98M
  dns_slabheader_t *header = *headerp;
894
895
5.98M
  *headerp = NULL;
896
897
5.98M
  isc_mem_t *mctx = header->db->mctx;
898
899
5.98M
  dns_db_deletedata(header->db, header->node, header);
900
901
5.98M
  if (NONEXISTENT(header)) {
902
0
    size = sizeof(*header);
903
5.98M
  } else {
904
5.98M
    size = dns_rdataslab_size(header);
905
5.98M
  }
906
907
5.98M
  isc_mem_put(mctx, header, size);
908
5.98M
}
909
910
void
911
0
dns_slabheader_freeproof(isc_mem_t *mctx, dns_slabheader_proof_t **proofp) {
912
0
  unsigned int buflen;
913
0
  uint8_t *rawbuf;
914
0
  dns_slabheader_proof_t *proof = *proofp;
915
0
  *proofp = NULL;
916
917
0
  if (dns_name_dynamic(&proof->name)) {
918
0
    dns_name_free(&proof->name, mctx);
919
0
  }
920
0
  if (proof->neg != NULL) {
921
0
    rawbuf = proof->neg;
922
0
    rawbuf -= sizeof(dns_slabheader_t);
923
0
    buflen = dns_rdataslab_size((dns_slabheader_t *)rawbuf);
924
925
0
    isc_mem_put(mctx, rawbuf, buflen);
926
0
  }
927
0
  if (proof->negsig != NULL) {
928
0
    rawbuf = proof->negsig;
929
0
    rawbuf -= sizeof(dns_slabheader_t);
930
0
    buflen = dns_rdataslab_size((dns_slabheader_t *)rawbuf);
931
932
0
    isc_mem_put(mctx, rawbuf, buflen);
933
0
  }
934
0
  isc_mem_put(mctx, proof, sizeof(*proof));
935
0
}
936
937
dns_slabheader_t *
938
0
dns_slabheader_top(dns_slabheader_t *header) {
939
0
  dns_typepair_t type, negtype;
940
0
  dns_rdatatype_t rdtype, covers;
941
942
0
  type = header->type;
943
0
  rdtype = DNS_TYPEPAIR_TYPE(header->type);
944
0
  if (NEGATIVE(header)) {
945
0
    covers = DNS_TYPEPAIR_COVERS(header->type);
946
0
    negtype = DNS_TYPEPAIR_VALUE(covers, 0);
947
0
  } else {
948
0
    negtype = DNS_TYPEPAIR_VALUE(0, rdtype);
949
0
  }
950
951
  /*
952
   * Find the start of the header chain for the next type
953
   * by walking back up the list.
954
   */
955
0
  while (header->up != NULL &&
956
0
         (header->up->type == type || header->up->type == negtype))
957
0
  {
958
0
    header = header->up;
959
0
  }
960
961
0
  return header;
962
0
}
963
964
/* Fixed RRSet helper macros */
965
966
446
#define DNS_RDATASET_LENGTH 2;
967
968
static void
969
167
rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
970
167
  dns_db_t *db = rdataset->slab.db;
971
167
  dns_dbnode_t *node = rdataset->slab.node;
972
973
167
  dns__db_detachnode(db, &node DNS__DB_FLARG_PASS);
974
167
}
975
976
static isc_result_t
977
166
rdataset_first(dns_rdataset_t *rdataset) {
978
166
  unsigned char *raw = rdataset->slab.raw;
979
166
  uint16_t count = peek_uint16(raw);
980
166
  if (count == 0) {
981
0
    rdataset->slab.iter_pos = NULL;
982
0
    rdataset->slab.iter_count = 0;
983
0
    return ISC_R_NOMORE;
984
0
  }
985
986
  /*
987
   * iter_count is the number of rdata beyond the cursor
988
   * position, so we decrement the total count by one before
989
   * storing it.
990
   *
991
   * 'raw' points to the first record.
992
   */
993
166
  rdataset->slab.iter_pos = raw + DNS_RDATASET_LENGTH;
994
166
  rdataset->slab.iter_count = count - 1;
995
996
166
  return ISC_R_SUCCESS;
997
166
}
998
999
static isc_result_t
1000
207
rdataset_next(dns_rdataset_t *rdataset) {
1001
207
  uint16_t count = rdataset->slab.iter_count;
1002
207
  if (count == 0) {
1003
150
    rdataset->slab.iter_pos = NULL;
1004
150
    return ISC_R_NOMORE;
1005
150
  }
1006
57
  rdataset->slab.iter_count = count - 1;
1007
1008
  /*
1009
   * Skip forward one record (length + 4) or one offset (4).
1010
   */
1011
57
  unsigned char *raw = rdataset->slab.iter_pos;
1012
57
  uint16_t length = peek_uint16(raw);
1013
57
  raw += length;
1014
57
  rdataset->slab.iter_pos = raw + DNS_RDATASET_LENGTH;
1015
1016
57
  return ISC_R_SUCCESS;
1017
207
}
1018
1019
static void
1020
223
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
1021
223
  unsigned char *raw = NULL;
1022
223
  unsigned int length;
1023
223
  isc_region_t r;
1024
223
  unsigned int flags = 0;
1025
1026
223
  raw = rdataset->slab.iter_pos;
1027
223
  REQUIRE(raw != NULL);
1028
1029
  /*
1030
   * Find the start of the record if not already in iter_pos
1031
   * then skip the length and order fields.
1032
   */
1033
223
  length = peek_uint16(raw);
1034
1035
223
  raw += DNS_RDATASET_LENGTH;
1036
1037
223
  if (rdataset->type == dns_rdatatype_rrsig) {
1038
0
    if (*raw & DNS_RDATASLAB_OFFLINE) {
1039
0
      flags |= DNS_RDATA_OFFLINE;
1040
0
    }
1041
0
    length--;
1042
0
    raw++;
1043
0
  }
1044
223
  r.length = length;
1045
223
  r.base = raw;
1046
223
  dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
1047
223
  rdata->flags |= flags;
1048
223
}
1049
1050
static void
1051
0
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) {
1052
0
  dns_db_t *db = source->slab.db;
1053
0
  dns_dbnode_t *node = source->slab.node;
1054
0
  dns_dbnode_t *cloned_node = NULL;
1055
1056
0
  dns__db_attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS);
1057
0
  INSIST(!ISC_LINK_LINKED(target, link));
1058
0
  *target = *source;
1059
0
  ISC_LINK_INIT(target, link);
1060
1061
0
  target->slab.iter_pos = NULL;
1062
0
  target->slab.iter_count = 0;
1063
0
}
1064
1065
static unsigned int
1066
0
rdataset_count(dns_rdataset_t *rdataset) {
1067
0
  unsigned char *raw = NULL;
1068
0
  unsigned int count;
1069
1070
0
  raw = rdataset->slab.raw;
1071
0
  count = get_uint16(raw);
1072
1073
0
  return count;
1074
0
}
1075
1076
static isc_result_t
1077
rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
1078
        dns_rdataset_t *nsec,
1079
0
        dns_rdataset_t *nsecsig DNS__DB_FLARG) {
1080
0
  dns_db_t *db = rdataset->slab.db;
1081
0
  dns_dbnode_t *node = rdataset->slab.node;
1082
0
  const dns_slabheader_proof_t *noqname = rdataset->slab.noqname;
1083
1084
  /*
1085
   * The _KEEPCASE attribute is set to prevent setownercase and
1086
   * getownercase methods from affecting the case of NSEC/NSEC3
1087
   * owner names.
1088
   */
1089
0
  dns__db_attachnode(db, node,
1090
0
         &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
1091
0
  *nsec = (dns_rdataset_t){
1092
0
    .methods = &dns_rdataslab_rdatasetmethods,
1093
0
    .rdclass = db->rdclass,
1094
0
    .type = noqname->type,
1095
0
    .ttl = rdataset->ttl,
1096
0
    .trust = rdataset->trust,
1097
0
    .slab.db = db,
1098
0
    .slab.node = node,
1099
0
    .slab.raw = noqname->neg,
1100
0
    .link = nsec->link,
1101
0
    .count = nsec->count,
1102
0
    .attributes = nsec->attributes,
1103
0
    .magic = nsec->magic,
1104
0
  };
1105
0
  nsec->attributes.keepcase = true;
1106
1107
0
  dns__db_attachnode(db, node,
1108
0
         &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
1109
0
  *nsecsig = (dns_rdataset_t){
1110
0
    .methods = &dns_rdataslab_rdatasetmethods,
1111
0
    .rdclass = db->rdclass,
1112
0
    .type = dns_rdatatype_rrsig,
1113
0
    .covers = noqname->type,
1114
0
    .ttl = rdataset->ttl,
1115
0
    .trust = rdataset->trust,
1116
0
    .slab.db = db,
1117
0
    .slab.node = node,
1118
0
    .slab.raw = noqname->negsig,
1119
0
    .link = nsecsig->link,
1120
0
    .count = nsecsig->count,
1121
0
    .attributes = nsecsig->attributes,
1122
0
    .magic = nsecsig->magic,
1123
0
  };
1124
0
  nsecsig->attributes.keepcase = true;
1125
1126
0
  dns_name_clone(&noqname->name, name);
1127
1128
0
  return ISC_R_SUCCESS;
1129
0
}
1130
1131
static isc_result_t
1132
rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
1133
        dns_rdataset_t *nsec,
1134
0
        dns_rdataset_t *nsecsig DNS__DB_FLARG) {
1135
0
  dns_db_t *db = rdataset->slab.db;
1136
0
  dns_dbnode_t *node = rdataset->slab.node;
1137
0
  const dns_slabheader_proof_t *closest = rdataset->slab.closest;
1138
1139
  /*
1140
   * As mentioned above, rdataset->slab.raw usually refers the data
1141
   * following an dns_slabheader, but in this case it points to a bare
1142
   * rdataslab belonging to the dns_slabheader's `closest` field.
1143
   */
1144
0
  dns__db_attachnode(db, node,
1145
0
         &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
1146
0
  *nsec = (dns_rdataset_t){
1147
0
    .methods = &dns_rdataslab_rdatasetmethods,
1148
0
    .rdclass = db->rdclass,
1149
0
    .type = closest->type,
1150
0
    .ttl = rdataset->ttl,
1151
0
    .trust = rdataset->trust,
1152
0
    .slab.db = db,
1153
0
    .slab.node = node,
1154
0
    .slab.raw = closest->neg,
1155
0
    .link = nsec->link,
1156
0
    .count = nsec->count,
1157
0
    .attributes = nsec->attributes,
1158
0
    .magic = nsec->magic,
1159
0
  };
1160
0
  nsec->attributes.keepcase = true;
1161
1162
0
  dns__db_attachnode(db, node,
1163
0
         &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
1164
0
  *nsecsig = (dns_rdataset_t){
1165
0
    .methods = &dns_rdataslab_rdatasetmethods,
1166
0
    .rdclass = db->rdclass,
1167
0
    .type = dns_rdatatype_rrsig,
1168
0
    .covers = closest->type,
1169
0
    .ttl = rdataset->ttl,
1170
0
    .trust = rdataset->trust,
1171
0
    .slab.db = db,
1172
0
    .slab.node = node,
1173
0
    .slab.raw = closest->negsig,
1174
0
    .link = nsecsig->link,
1175
0
    .count = nsecsig->count,
1176
0
    .attributes = nsecsig->attributes,
1177
0
    .magic = nsecsig->magic,
1178
0
  };
1179
0
  nsecsig->attributes.keepcase = true;
1180
1181
0
  dns_name_clone(&closest->name, name);
1182
1183
0
  return ISC_R_SUCCESS;
1184
0
}
1185
1186
static void
1187
0
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
1188
0
  dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
1189
1190
0
  dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
1191
0
  header->trust = rdataset->trust = trust;
1192
0
  dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
1193
0
}
1194
1195
static void
1196
0
rdataset_expire(dns_rdataset_t *rdataset DNS__DB_FLARG) {
1197
0
  dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
1198
1199
0
  dns_db_expiredata(header->db, header->node, header);
1200
0
}
1201
1202
static void
1203
0
rdataset_clearprefetch(dns_rdataset_t *rdataset) {
1204
0
  dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
1205
1206
0
  dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
1207
0
  DNS_SLABHEADER_CLRATTR(header, DNS_SLABHEADERATTR_PREFETCH);
1208
0
  dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
1209
0
}
1210
1211
static void
1212
0
rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
1213
0
  dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
1214
1215
0
  DNS_SLABHEADER_CLRATTR(header, DNS_SLABHEADERATTR_CASEFULLYLOWER);
1216
1217
0
  dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
1218
0
  dns_slabheader_setownercase(header, name);
1219
0
  dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
1220
0
}
1221
1222
static void
1223
0
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
1224
0
  dns_slabheader_t *header = dns_rdataset_getheader(rdataset);
1225
0
  uint8_t mask = (1 << 7);
1226
0
  uint8_t bits = 0;
1227
1228
0
  if (CASEFULLYLOWER(header)) {
1229
0
    isc_ascii_lowercopy(name->ndata, name->ndata, name->length);
1230
0
    return;
1231
0
  }
1232
1233
0
  dns_db_locknode(header->db, header->node, isc_rwlocktype_read);
1234
0
  if (CASESET(header)) {
1235
0
    uint8_t *nd = name->ndata;
1236
0
    for (size_t i = 0; i < name->length; i++) {
1237
0
      if (mask == (1 << 7)) {
1238
0
        bits = header->upper[i / 8];
1239
0
        mask = 1;
1240
0
      } else {
1241
0
        mask <<= 1;
1242
0
      }
1243
0
      nd[i] = (bits & mask) ? isc_ascii_toupper(nd[i])
1244
0
                : isc_ascii_tolower(nd[i]);
1245
0
    }
1246
0
  }
1247
0
  dns_db_unlocknode(header->db, header->node, isc_rwlocktype_read);
1248
0
}
1249
1250
static dns_slabheader_t *
1251
0
rdataset_getheader(const dns_rdataset_t *rdataset) {
1252
0
  dns_slabheader_t *header = (dns_slabheader_t *)rdataset->slab.raw;
1253
0
  return header - 1;
1254
0
}
1255
1256
static bool
1257
rdataset_equals(const dns_rdataset_t *rdataset1,
1258
0
    const dns_rdataset_t *rdataset2) {
1259
0
  if (rdataset1->rdclass != rdataset2->rdclass ||
1260
0
      rdataset1->type != rdataset2->type)
1261
0
  {
1262
0
    return false;
1263
0
  }
1264
1265
0
  dns_slabheader_t *header1 = (dns_slabheader_t *)rdataset1->slab.raw - 1;
1266
0
  dns_slabheader_t *header2 = (dns_slabheader_t *)rdataset2->slab.raw - 1;
1267
1268
0
  return dns_rdataslab_equalx(header1, header2, rdataset1->rdclass,
1269
0
            rdataset2->type);
1270
0
}