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