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