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