Coverage Report

Created: 2025-08-03 06:32

/src/bind9/lib/dns/ncache.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 <inttypes.h>
17
#include <stdbool.h>
18
19
#include <isc/buffer.h>
20
#include <isc/util.h>
21
22
#include <dns/db.h>
23
#include <dns/message.h>
24
#include <dns/ncache.h>
25
#include <dns/rdata.h>
26
#include <dns/rdatalist.h>
27
#include <dns/rdataset.h>
28
#include <dns/rdatastruct.h>
29
30
0
#define DNS_NCACHE_RDATA 100U
31
32
/*
33
 * The format of an ncache rdata is a sequence of zero or more records
34
 * of the following format:
35
 *
36
 *  owner name
37
 *  type
38
 *  trust
39
 *  rdata count
40
 *  rdata length      These two occur 'rdata
41
 *  rdata       count' times.
42
 *
43
 */
44
45
static uint8_t
46
0
atomic_getuint8(isc_buffer_t *b) {
47
0
  atomic_uchar *cp = isc_buffer_current(b);
48
0
  uint8_t ret = atomic_load_relaxed(cp);
49
0
  isc_buffer_forward(b, 1);
50
0
  return ret;
51
0
}
52
53
static isc_result_t
54
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
55
    dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
56
    dns_ttl_t maxttl, bool optout, bool secure,
57
    dns_rdataset_t *addedrdataset);
58
59
static isc_result_t
60
0
copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
61
0
  unsigned int count;
62
0
  isc_region_t ar, r;
63
64
  /*
65
   * Copy the rdataset count to the buffer.
66
   */
67
0
  isc_buffer_availableregion(buffer, &ar);
68
0
  if (ar.length < 2) {
69
0
    return ISC_R_NOSPACE;
70
0
  }
71
0
  count = dns_rdataset_count(rdataset);
72
0
  INSIST(count <= 65535);
73
0
  isc_buffer_putuint16(buffer, (uint16_t)count);
74
75
0
  DNS_RDATASET_FOREACH (rdataset) {
76
0
    isc_result_t result;
77
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
78
0
    dns_rdataset_current(rdataset, &rdata);
79
80
0
    dns_rdata_toregion(&rdata, &r);
81
0
    INSIST(r.length <= 65535);
82
0
    isc_buffer_availableregion(buffer, &ar);
83
0
    if (ar.length < 2) {
84
0
      return ISC_R_NOSPACE;
85
0
    }
86
    /*
87
     * Copy the rdata length to the buffer.
88
     */
89
0
    isc_buffer_putuint16(buffer, (uint16_t)r.length);
90
    /*
91
     * Copy the rdata to the buffer.
92
     */
93
0
    result = isc_buffer_copyregion(buffer, &r);
94
0
    if (result != ISC_R_SUCCESS) {
95
0
      return result;
96
0
    }
97
0
  }
98
99
0
  return ISC_R_SUCCESS;
100
0
}
101
102
isc_result_t
103
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
104
         dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
105
0
         dns_ttl_t maxttl, dns_rdataset_t *addedrdataset) {
106
0
  return addoptout(message, cache, node, covers, now, minttl, maxttl,
107
0
       false, false, addedrdataset);
108
0
}
109
110
isc_result_t
111
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
112
         dns_dbnode_t *node, dns_rdatatype_t covers,
113
         isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
114
0
         bool optout, dns_rdataset_t *addedrdataset) {
115
0
  return addoptout(message, cache, node, covers, now, minttl, maxttl,
116
0
       optout, true, addedrdataset);
117
0
}
118
119
static isc_result_t
120
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
121
    dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
122
    dns_ttl_t maxttl, bool optout, bool secure,
123
0
    dns_rdataset_t *addedrdataset) {
124
0
  isc_buffer_t buffer;
125
0
  isc_region_t r;
126
0
  dns_rdatatype_t type;
127
0
  dns_ttl_t ttl;
128
0
  dns_trust_t trust;
129
0
  dns_rdata_t rdata[DNS_NCACHE_RDATA];
130
0
  dns_rdataset_t ncrdataset;
131
0
  dns_rdatalist_t ncrdatalist;
132
0
  unsigned char data[65536];
133
0
  unsigned int next = 0;
134
135
  /*
136
   * Convert the authority data from 'message' into a negative cache
137
   * rdataset, and store it in 'cache' at 'node'.
138
   */
139
140
0
  REQUIRE(message != NULL);
141
142
  /*
143
   * We assume that all data in the authority section has been
144
   * validated by the caller.
145
   */
146
147
  /*
148
   * Initialize the list.
149
   */
150
0
  dns_rdatalist_init(&ncrdatalist);
151
0
  ncrdatalist.rdclass = dns_db_class(cache);
152
0
  ncrdatalist.covers = covers;
153
0
  ncrdatalist.ttl = maxttl;
154
155
  /*
156
   * Build an ncache rdatas into buffer.
157
   */
158
0
  ttl = maxttl;
159
0
  trust = 0xffff;
160
0
  isc_buffer_init(&buffer, data, sizeof(data));
161
162
0
  MSG_SECTION_FOREACH (message, DNS_SECTION_AUTHORITY, name) {
163
0
    isc_result_t result = ISC_R_SUCCESS;
164
165
0
    if (name->attributes.ncache) {
166
0
      ISC_LIST_FOREACH (name->list, rdataset, link) {
167
0
        if (!rdataset->attributes.ncache) {
168
0
          continue;
169
0
        }
170
0
        type = rdataset->type;
171
0
        if (type == dns_rdatatype_rrsig) {
172
0
          type = rdataset->covers;
173
0
        }
174
0
        if (type == dns_rdatatype_soa ||
175
0
            type == dns_rdatatype_nsec ||
176
0
            type == dns_rdatatype_nsec3)
177
0
        {
178
0
          if (ttl > rdataset->ttl) {
179
0
            ttl = rdataset->ttl;
180
0
          }
181
0
          if (ttl < minttl) {
182
0
            ttl = minttl;
183
0
          }
184
0
          if (trust > rdataset->trust) {
185
0
            trust = rdataset->trust;
186
0
          }
187
          /*
188
           * Copy the owner name to the buffer.
189
           */
190
0
          dns_name_toregion(name, &r);
191
0
          result = isc_buffer_copyregion(&buffer,
192
0
                       &r);
193
0
          if (result != ISC_R_SUCCESS) {
194
0
            return result;
195
0
          }
196
          /*
197
           * Copy the type to the buffer.
198
           */
199
0
          isc_buffer_availableregion(&buffer, &r);
200
0
          if (r.length < 3) {
201
0
            return ISC_R_NOSPACE;
202
0
          }
203
0
          isc_buffer_putuint16(&buffer,
204
0
                   rdataset->type);
205
0
          isc_buffer_putuint8(
206
0
            &buffer,
207
0
            (unsigned char)rdataset->trust);
208
          /*
209
           * Copy the rdataset into the buffer.
210
           */
211
0
          result = copy_rdataset(rdataset,
212
0
                     &buffer);
213
0
          if (result != ISC_R_SUCCESS) {
214
0
            return result;
215
0
          }
216
217
0
          if (next >= DNS_NCACHE_RDATA) {
218
0
            return ISC_R_NOSPACE;
219
0
          }
220
0
          dns_rdata_init(&rdata[next]);
221
0
          isc_buffer_remainingregion(&buffer, &r);
222
0
          rdata[next].data = r.base;
223
0
          rdata[next].length = r.length;
224
0
          rdata[next].rdclass =
225
0
            ncrdatalist.rdclass;
226
0
          rdata[next].type = 0;
227
0
          rdata[next].flags = 0;
228
0
          ISC_LIST_APPEND(ncrdatalist.rdata,
229
0
              &rdata[next], link);
230
0
          isc_buffer_forward(&buffer, r.length);
231
0
          next++;
232
0
        }
233
0
      }
234
0
    }
235
0
  }
236
237
0
  if (trust == 0xffff) {
238
0
    if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
239
0
        message->counts[DNS_SECTION_ANSWER] == 0)
240
0
    {
241
      /*
242
       * The response has aa set and we haven't followed
243
       * any CNAME or DNAME chains.
244
       */
245
0
      trust = dns_trust_authauthority;
246
0
    } else {
247
0
      trust = dns_trust_additional;
248
0
    }
249
0
    ttl = 0;
250
0
  }
251
252
0
  INSIST(trust != 0xffff);
253
254
0
  ncrdatalist.ttl = ttl;
255
256
0
  dns_rdataset_init(&ncrdataset);
257
0
  dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset);
258
0
  if (!secure && trust > dns_trust_answer) {
259
0
    trust = dns_trust_answer;
260
0
  }
261
0
  ncrdataset.trust = trust;
262
0
  ncrdataset.attributes.negative = true;
263
0
  if (message->rcode == dns_rcode_nxdomain) {
264
0
    ncrdataset.attributes.nxdomain = true;
265
0
  }
266
0
  if (optout) {
267
0
    ncrdataset.attributes.optout = true;
268
0
  }
269
270
0
  return dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0,
271
0
          addedrdataset);
272
0
}
273
274
isc_result_t
275
dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
276
      isc_buffer_t *target, unsigned int options,
277
0
      unsigned int *countp) {
278
0
  isc_result_t result;
279
0
  isc_region_t remaining, tavailable;
280
0
  isc_buffer_t source, savedbuffer, rdlen;
281
0
  dns_name_t name;
282
0
  dns_rdatatype_t type;
283
0
  unsigned int i, rcount, count;
284
285
  /*
286
   * Convert the negative caching rdataset 'rdataset' to wire format,
287
   * compressing names as specified in 'cctx', and storing the result in
288
   * 'target'.
289
   */
290
291
0
  REQUIRE(rdataset != NULL);
292
0
  REQUIRE(rdataset->type == 0);
293
0
  REQUIRE(rdataset->attributes.negative);
294
295
0
  savedbuffer = *target;
296
0
  count = 0;
297
298
0
  DNS_RDATASET_FOREACH (rdataset) {
299
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
300
0
    dns_rdataset_current(rdataset, &rdata);
301
302
0
    isc_buffer_init(&source, rdata.data, rdata.length);
303
0
    isc_buffer_add(&source, rdata.length);
304
0
    dns_name_init(&name);
305
0
    isc_buffer_remainingregion(&source, &remaining);
306
0
    dns_name_fromregion(&name, &remaining);
307
0
    INSIST(remaining.length >= name.length);
308
0
    isc_buffer_forward(&source, name.length);
309
0
    remaining.length -= name.length;
310
311
0
    INSIST(remaining.length >= 5);
312
0
    type = isc_buffer_getuint16(&source);
313
0
    isc_buffer_forward(&source, 1);
314
0
    rcount = isc_buffer_getuint16(&source);
315
316
0
    for (i = 0; i < rcount; i++) {
317
      /*
318
       * Get the length of this rdata and set up an
319
       * rdata structure for it.
320
       */
321
0
      isc_buffer_remainingregion(&source, &remaining);
322
0
      INSIST(remaining.length >= 2);
323
0
      dns_rdata_reset(&rdata);
324
0
      rdata.length = isc_buffer_getuint16(&source);
325
0
      isc_buffer_remainingregion(&source, &remaining);
326
0
      rdata.data = remaining.base;
327
0
      rdata.type = type;
328
0
      rdata.rdclass = rdataset->rdclass;
329
0
      INSIST(remaining.length >= rdata.length);
330
0
      isc_buffer_forward(&source, rdata.length);
331
332
0
      if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
333
0
          dns_rdatatype_isdnssec(type))
334
0
      {
335
0
        continue;
336
0
      }
337
338
      /*
339
       * Write the name.
340
       */
341
0
      dns_compress_setpermitted(cctx, true);
342
0
      result = dns_name_towire(&name, cctx, target);
343
0
      if (result != ISC_R_SUCCESS) {
344
0
        goto rollback;
345
0
      }
346
347
      /*
348
       * See if we have space for type, class, ttl, and
349
       * rdata length.  Write the type, class, and ttl.
350
       */
351
0
      isc_buffer_availableregion(target, &tavailable);
352
0
      if (tavailable.length < 10) {
353
0
        result = ISC_R_NOSPACE;
354
0
        goto rollback;
355
0
      }
356
0
      isc_buffer_putuint16(target, type);
357
0
      isc_buffer_putuint16(target, rdataset->rdclass);
358
0
      isc_buffer_putuint32(target, rdataset->ttl);
359
360
      /*
361
       * Save space for rdata length.
362
       */
363
0
      rdlen = *target;
364
0
      isc_buffer_add(target, 2);
365
366
      /*
367
       * Write the rdata.
368
       */
369
0
      result = dns_rdata_towire(&rdata, cctx, target);
370
0
      if (result != ISC_R_SUCCESS) {
371
0
        goto rollback;
372
0
      }
373
374
      /*
375
       * Set the rdata length field to the compressed
376
       * length.
377
       */
378
0
      INSIST((target->used >= rdlen.used + 2) &&
379
0
             (target->used - rdlen.used - 2 < 65536));
380
0
      isc_buffer_putuint16(
381
0
        &rdlen,
382
0
        (uint16_t)(target->used - rdlen.used - 2));
383
384
0
      count++;
385
0
    }
386
0
    INSIST(isc_buffer_remaininglength(&source) == 0);
387
0
  }
388
389
0
  *countp = count;
390
391
0
  return ISC_R_SUCCESS;
392
393
0
rollback:
394
0
  dns_compress_rollback(cctx, savedbuffer.used);
395
0
  *countp = 0;
396
0
  *target = savedbuffer;
397
398
0
  return result;
399
0
}
400
401
static void
402
0
rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
403
0
  UNUSED(rdataset);
404
0
}
405
406
static isc_result_t
407
0
rdataset_first(dns_rdataset_t *rdataset) {
408
0
  unsigned char *raw;
409
0
  unsigned int count;
410
411
0
  raw = rdataset->ncache.raw;
412
0
  count = raw[0] * 256 + raw[1];
413
0
  if (count == 0) {
414
0
    rdataset->ncache.iter_pos = NULL;
415
0
    return ISC_R_NOMORE;
416
0
  }
417
  /*
418
   * iter_count is the number of rdata beyond the cursor position,
419
   * so we decrement the total count by one before storing it.
420
   */
421
0
  rdataset->ncache.iter_pos = raw + 2;
422
0
  rdataset->ncache.iter_count = count - 1;
423
0
  return ISC_R_SUCCESS;
424
0
}
425
426
static isc_result_t
427
0
rdataset_next(dns_rdataset_t *rdataset) {
428
0
  unsigned int count;
429
0
  unsigned int length;
430
0
  unsigned char *raw;
431
432
0
  raw = rdataset->ncache.iter_pos;
433
0
  count = rdataset->ncache.iter_count;
434
0
  if (count == 0) {
435
0
    rdataset->ncache.iter_pos = NULL;
436
0
    return ISC_R_NOMORE;
437
0
  }
438
439
0
  length = raw[0] * 256 + raw[1];
440
0
  rdataset->ncache.iter_pos = raw + 2 + length;
441
0
  rdataset->ncache.iter_count = count - 1;
442
0
  return ISC_R_SUCCESS;
443
0
}
444
445
static void
446
0
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
447
0
  unsigned char *raw;
448
0
  isc_region_t r;
449
450
0
  raw = rdataset->ncache.iter_pos;
451
0
  REQUIRE(raw != NULL);
452
453
0
  r.length = raw[0] * 256 + raw[1];
454
0
  r.base = raw + 2;
455
0
  dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
456
0
}
457
458
static void
459
0
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) {
460
0
  *target = *source;
461
0
  target->ncache.iter_pos = NULL;
462
0
  target->ncache.iter_count = 0;
463
0
}
464
465
static unsigned int
466
0
rdataset_count(dns_rdataset_t *rdataset) {
467
0
  unsigned char *raw;
468
0
  unsigned int count;
469
470
0
  raw = rdataset->ncache.raw;
471
0
  count = raw[0] * 256 + raw[1];
472
473
0
  return count;
474
0
}
475
476
static void
477
0
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
478
0
  atomic_uchar *raw;
479
480
0
  raw = (atomic_uchar *)rdataset->ncache.raw;
481
0
  atomic_store_relaxed(&raw[-1], (unsigned char)trust);
482
0
  rdataset->trust = trust;
483
0
}
484
485
static dns_rdatasetmethods_t rdataset_methods = {
486
  .disassociate = rdataset_disassociate,
487
  .first = rdataset_first,
488
  .next = rdataset_next,
489
  .current = rdataset_current,
490
  .clone = rdataset_clone,
491
  .count = rdataset_count,
492
  .settrust = rdataset_settrust,
493
};
494
495
isc_result_t
496
dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
497
0
           dns_rdatatype_t type, dns_rdataset_t *rdataset) {
498
0
  isc_result_t result = ISC_R_NOTFOUND;
499
0
  isc_region_t remaining;
500
0
  isc_buffer_t source;
501
0
  dns_name_t tname;
502
0
  dns_rdatatype_t ttype;
503
0
  dns_trust_t trust = dns_trust_none;
504
0
  dns_rdataset_t rclone;
505
506
0
  REQUIRE(ncacherdataset != NULL);
507
0
  REQUIRE(DNS_RDATASET_VALID(ncacherdataset));
508
0
  REQUIRE(ncacherdataset->type == 0);
509
0
  REQUIRE(ncacherdataset->attributes.negative);
510
0
  REQUIRE(name != NULL);
511
0
  REQUIRE(!dns_rdataset_isassociated(rdataset));
512
0
  REQUIRE(type != dns_rdatatype_rrsig);
513
514
0
  dns_rdataset_init(&rclone);
515
0
  dns_rdataset_clone(ncacherdataset, &rclone);
516
0
  DNS_RDATASET_FOREACH (&rclone) {
517
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
518
0
    dns_rdataset_current(&rclone, &rdata);
519
520
0
    isc_buffer_init(&source, rdata.data, rdata.length);
521
0
    isc_buffer_add(&source, rdata.length);
522
0
    dns_name_init(&tname);
523
0
    isc_buffer_remainingregion(&source, &remaining);
524
0
    dns_name_fromregion(&tname, &remaining);
525
0
    INSIST(remaining.length >= tname.length);
526
0
    isc_buffer_forward(&source, tname.length);
527
0
    remaining.length -= tname.length;
528
529
0
    INSIST(remaining.length >= 3);
530
0
    ttype = isc_buffer_getuint16(&source);
531
532
0
    if (ttype == type && dns_name_equal(&tname, name)) {
533
0
      trust = atomic_getuint8(&source);
534
0
      INSIST(trust <= dns_trust_ultimate);
535
0
      isc_buffer_remainingregion(&source, &remaining);
536
0
      result = ISC_R_SUCCESS;
537
0
      break;
538
0
    }
539
0
  }
540
0
  dns_rdataset_disassociate(&rclone);
541
542
0
  if (result == ISC_R_SUCCESS) {
543
0
    INSIST(remaining.length != 0);
544
545
0
    rdataset->methods = &rdataset_methods;
546
0
    rdataset->rdclass = ncacherdataset->rdclass;
547
0
    rdataset->type = type;
548
0
    rdataset->covers = 0;
549
0
    rdataset->ttl = ncacherdataset->ttl;
550
0
    rdataset->trust = trust;
551
0
    rdataset->ncache.raw = remaining.base;
552
0
    rdataset->ncache.iter_pos = NULL;
553
0
    rdataset->ncache.iter_count = 0;
554
0
  }
555
556
0
  return result;
557
0
}
558
559
isc_result_t
560
dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
561
0
        dns_rdatatype_t covers, dns_rdataset_t *rdataset) {
562
0
  isc_result_t result = ISC_R_NOTFOUND;
563
0
  dns_name_t tname;
564
0
  dns_rdata_rrsig_t rrsig;
565
0
  dns_rdataset_t rclone;
566
0
  dns_rdatatype_t type;
567
0
  dns_trust_t trust = dns_trust_none;
568
0
  isc_buffer_t source;
569
0
  isc_region_t remaining, sigregion;
570
0
  unsigned char *raw = NULL;
571
0
  unsigned int count;
572
573
0
  REQUIRE(ncacherdataset != NULL);
574
0
  REQUIRE(ncacherdataset->type == 0);
575
0
  REQUIRE(ncacherdataset->attributes.negative);
576
0
  REQUIRE(name != NULL);
577
0
  REQUIRE(!dns_rdataset_isassociated(rdataset));
578
579
0
  dns_rdataset_init(&rclone);
580
0
  dns_rdataset_clone(ncacherdataset, &rclone);
581
0
  DNS_RDATASET_FOREACH (&rclone) {
582
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
583
0
    dns_rdataset_current(&rclone, &rdata);
584
585
0
    isc_buffer_init(&source, rdata.data, rdata.length);
586
0
    isc_buffer_add(&source, rdata.length);
587
0
    dns_name_init(&tname);
588
0
    isc_buffer_remainingregion(&source, &remaining);
589
0
    dns_name_fromregion(&tname, &remaining);
590
0
    INSIST(remaining.length >= tname.length);
591
0
    isc_buffer_forward(&source, tname.length);
592
0
    isc_region_consume(&remaining, tname.length);
593
594
0
    INSIST(remaining.length >= 2);
595
0
    type = isc_buffer_getuint16(&source);
596
0
    isc_region_consume(&remaining, 2);
597
598
0
    if (type != dns_rdatatype_rrsig ||
599
0
        !dns_name_equal(&tname, name))
600
0
    {
601
0
      continue;
602
0
    }
603
604
0
    INSIST(remaining.length >= 1);
605
0
    trust = atomic_getuint8(&source);
606
0
    INSIST(trust <= dns_trust_ultimate);
607
0
    isc_region_consume(&remaining, 1);
608
609
0
    raw = remaining.base;
610
0
    count = raw[0] * 256 + raw[1];
611
0
    INSIST(count > 0);
612
0
    raw += 2;
613
0
    sigregion.length = raw[0] * 256 + raw[1];
614
0
    raw += 2;
615
0
    sigregion.base = raw;
616
0
    dns_rdata_reset(&rdata);
617
0
    dns_rdata_fromregion(&rdata, rdataset->rdclass,
618
0
             dns_rdatatype_rrsig, &sigregion);
619
0
    (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
620
0
    if (rrsig.covered == covers) {
621
0
      isc_buffer_remainingregion(&source, &remaining);
622
0
      result = ISC_R_SUCCESS;
623
0
      break;
624
0
    }
625
0
  }
626
0
  dns_rdataset_disassociate(&rclone);
627
628
0
  if (result == ISC_R_SUCCESS) {
629
0
    INSIST(remaining.length != 0);
630
631
0
    rdataset->methods = &rdataset_methods;
632
0
    rdataset->rdclass = ncacherdataset->rdclass;
633
0
    rdataset->type = dns_rdatatype_rrsig;
634
0
    rdataset->covers = covers;
635
0
    rdataset->ttl = ncacherdataset->ttl;
636
0
    rdataset->trust = trust;
637
0
    rdataset->ncache.raw = remaining.base;
638
0
    rdataset->ncache.iter_pos = NULL;
639
0
    rdataset->ncache.iter_count = 0;
640
0
  }
641
642
0
  return result;
643
0
}
644
645
void
646
dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
647
0
       dns_rdataset_t *rdataset) {
648
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
649
0
  dns_trust_t trust;
650
0
  isc_region_t remaining, sigregion;
651
0
  isc_buffer_t source;
652
0
  dns_name_t tname;
653
0
  dns_rdatatype_t type, covers;
654
0
  unsigned int count;
655
0
  dns_rdata_rrsig_t rrsig;
656
0
  unsigned char *raw;
657
658
0
  REQUIRE(ncacherdataset != NULL);
659
0
  REQUIRE(ncacherdataset->type == 0);
660
0
  REQUIRE(ncacherdataset->attributes.negative);
661
0
  REQUIRE(found != NULL);
662
0
  REQUIRE(!dns_rdataset_isassociated(rdataset));
663
664
0
  dns_rdataset_current(ncacherdataset, &rdata);
665
0
  isc_buffer_init(&source, rdata.data, rdata.length);
666
0
  isc_buffer_add(&source, rdata.length);
667
668
0
  dns_name_init(&tname);
669
0
  isc_buffer_remainingregion(&source, &remaining);
670
0
  dns_name_fromregion(found, &remaining);
671
0
  INSIST(remaining.length >= found->length);
672
0
  isc_buffer_forward(&source, found->length);
673
0
  remaining.length -= found->length;
674
675
0
  INSIST(remaining.length >= 5);
676
0
  type = isc_buffer_getuint16(&source);
677
0
  trust = atomic_getuint8(&source);
678
0
  INSIST(trust <= dns_trust_ultimate);
679
0
  isc_buffer_remainingregion(&source, &remaining);
680
681
0
  covers = 0;
682
0
  if (type == dns_rdatatype_rrsig) {
683
    /*
684
     * Extract covers from RRSIG.
685
     */
686
0
    raw = remaining.base;
687
0
    count = raw[0] * 256 + raw[1];
688
0
    INSIST(count > 0);
689
0
    raw += 2;
690
0
    sigregion.length = raw[0] * 256 + raw[1];
691
0
    raw += 2;
692
0
    sigregion.base = raw;
693
0
    dns_rdata_reset(&rdata);
694
0
    dns_rdata_fromregion(&rdata, ncacherdataset->rdclass, type,
695
0
             &sigregion);
696
0
    (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
697
0
    covers = rrsig.covered;
698
0
  }
699
700
0
  rdataset->methods = &rdataset_methods;
701
0
  rdataset->rdclass = ncacherdataset->rdclass;
702
0
  rdataset->type = type;
703
0
  rdataset->covers = covers;
704
0
  rdataset->ttl = ncacherdataset->ttl;
705
0
  rdataset->trust = trust;
706
0
  rdataset->ncache.raw = remaining.base;
707
0
  rdataset->ncache.iter_pos = NULL;
708
0
  rdataset->ncache.iter_count = 0;
709
0
}