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