1 /* $NetBSD: rdataset.c,v 1.7 2022/09/23 12:15: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 #include <stdlib.h>
21
22 #include <isc/buffer.h>
23 #include <isc/mem.h>
24 #include <isc/random.h>
25 #include <isc/serial.h>
26 #include <isc/util.h>
27
28 #include <dns/compress.h>
29 #include <dns/fixedname.h>
30 #include <dns/name.h>
31 #include <dns/ncache.h>
32 #include <dns/rdata.h>
33 #include <dns/rdataset.h>
34
35 static const char *trustnames[] = {
36 "none", "pending-additional",
37 "pending-answer", "additional",
38 "glue", "answer",
39 "authauthority", "authanswer",
40 "secure", "local" /* aka ultimate */
41 };
42
43 const char *
dns_trust_totext(dns_trust_t trust)44 dns_trust_totext(dns_trust_t trust) {
45 if (trust >= sizeof(trustnames) / sizeof(*trustnames)) {
46 return ("bad");
47 }
48 return (trustnames[trust]);
49 }
50
51 #define DNS_RDATASET_COUNT_UNDEFINED UINT32_MAX
52
53 void
dns_rdataset_init(dns_rdataset_t * rdataset)54 dns_rdataset_init(dns_rdataset_t *rdataset) {
55 /*
56 * Make 'rdataset' a valid, disassociated rdataset.
57 */
58
59 REQUIRE(rdataset != NULL);
60
61 rdataset->magic = DNS_RDATASET_MAGIC;
62 rdataset->methods = NULL;
63 ISC_LINK_INIT(rdataset, link);
64 rdataset->rdclass = 0;
65 rdataset->type = 0;
66 rdataset->ttl = 0;
67 rdataset->trust = 0;
68 rdataset->covers = 0;
69 rdataset->attributes = 0;
70 rdataset->count = DNS_RDATASET_COUNT_UNDEFINED;
71 rdataset->private1 = NULL;
72 rdataset->private2 = NULL;
73 rdataset->private3 = NULL;
74 rdataset->privateuint4 = 0;
75 rdataset->private5 = NULL;
76 rdataset->private6 = NULL;
77 rdataset->private7 = NULL;
78 rdataset->resign = 0;
79 }
80
81 void
dns_rdataset_invalidate(dns_rdataset_t * rdataset)82 dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
83 /*
84 * Invalidate 'rdataset'.
85 */
86
87 REQUIRE(DNS_RDATASET_VALID(rdataset));
88 REQUIRE(rdataset->methods == NULL);
89
90 rdataset->magic = 0;
91 ISC_LINK_INIT(rdataset, link);
92 rdataset->rdclass = 0;
93 rdataset->type = 0;
94 rdataset->ttl = 0;
95 rdataset->trust = 0;
96 rdataset->covers = 0;
97 rdataset->attributes = 0;
98 rdataset->count = DNS_RDATASET_COUNT_UNDEFINED;
99 rdataset->private1 = NULL;
100 rdataset->private2 = NULL;
101 rdataset->private3 = NULL;
102 rdataset->privateuint4 = 0;
103 rdataset->private5 = NULL;
104 }
105
106 void
dns_rdataset_disassociate(dns_rdataset_t * rdataset)107 dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
108 /*
109 * Disassociate 'rdataset' from its rdata, allowing it to be reused.
110 */
111
112 REQUIRE(DNS_RDATASET_VALID(rdataset));
113 REQUIRE(rdataset->methods != NULL);
114
115 (rdataset->methods->disassociate)(rdataset);
116 rdataset->methods = NULL;
117 ISC_LINK_INIT(rdataset, link);
118 rdataset->rdclass = 0;
119 rdataset->type = 0;
120 rdataset->ttl = 0;
121 rdataset->trust = 0;
122 rdataset->covers = 0;
123 rdataset->attributes = 0;
124 rdataset->count = DNS_RDATASET_COUNT_UNDEFINED;
125 rdataset->private1 = NULL;
126 rdataset->private2 = NULL;
127 rdataset->private3 = NULL;
128 rdataset->privateuint4 = 0;
129 rdataset->private5 = NULL;
130 rdataset->private6 = NULL;
131 }
132
133 bool
dns_rdataset_isassociated(dns_rdataset_t * rdataset)134 dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
135 /*
136 * Is 'rdataset' associated?
137 */
138
139 REQUIRE(DNS_RDATASET_VALID(rdataset));
140
141 if (rdataset->methods != NULL) {
142 return (true);
143 }
144
145 return (false);
146 }
147
148 static void
question_disassociate(dns_rdataset_t * rdataset)149 question_disassociate(dns_rdataset_t *rdataset) {
150 UNUSED(rdataset);
151 }
152
153 static isc_result_t
question_cursor(dns_rdataset_t * rdataset)154 question_cursor(dns_rdataset_t *rdataset) {
155 UNUSED(rdataset);
156
157 return (ISC_R_NOMORE);
158 }
159
160 static void
question_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)161 question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
162 /*
163 * This routine should never be called.
164 */
165 UNUSED(rdataset);
166 UNUSED(rdata);
167
168 REQUIRE(0);
169 }
170
171 static void
question_clone(dns_rdataset_t * source,dns_rdataset_t * target)172 question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
173 *target = *source;
174 }
175
176 static unsigned int
question_count(dns_rdataset_t * rdataset)177 question_count(dns_rdataset_t *rdataset) {
178 /*
179 * This routine should never be called.
180 */
181 UNUSED(rdataset);
182 REQUIRE(0);
183
184 return (0);
185 }
186
187 static dns_rdatasetmethods_t question_methods = {
188 question_disassociate,
189 question_cursor,
190 question_cursor,
191 question_current,
192 question_clone,
193 question_count,
194 NULL, /* addnoqname */
195 NULL, /* getnoqname */
196 NULL, /* addclosest */
197 NULL, /* getclosest */
198 NULL, /* settrust */
199 NULL, /* expire */
200 NULL, /* clearprefetch */
201 NULL, /* setownercase */
202 NULL, /* getownercase */
203 NULL /* addglue */
204 };
205
206 void
dns_rdataset_makequestion(dns_rdataset_t * rdataset,dns_rdataclass_t rdclass,dns_rdatatype_t type)207 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
208 dns_rdatatype_t type) {
209 /*
210 * Make 'rdataset' a valid, associated, question rdataset, with a
211 * question class of 'rdclass' and type 'type'.
212 */
213
214 REQUIRE(DNS_RDATASET_VALID(rdataset));
215 REQUIRE(rdataset->methods == NULL);
216
217 rdataset->methods = &question_methods;
218 rdataset->rdclass = rdclass;
219 rdataset->type = type;
220 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
221 }
222
223 unsigned int
dns_rdataset_count(dns_rdataset_t * rdataset)224 dns_rdataset_count(dns_rdataset_t *rdataset) {
225 /*
226 * Return the number of records in 'rdataset'.
227 */
228
229 REQUIRE(DNS_RDATASET_VALID(rdataset));
230 REQUIRE(rdataset->methods != NULL);
231
232 return ((rdataset->methods->count)(rdataset));
233 }
234
235 void
dns_rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)236 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
237 /*
238 * Make 'target' refer to the same rdataset as 'source'.
239 */
240
241 REQUIRE(DNS_RDATASET_VALID(source));
242 REQUIRE(source->methods != NULL);
243 REQUIRE(DNS_RDATASET_VALID(target));
244 REQUIRE(target->methods == NULL);
245
246 (source->methods->clone)(source, target);
247 }
248
249 isc_result_t
dns_rdataset_first(dns_rdataset_t * rdataset)250 dns_rdataset_first(dns_rdataset_t *rdataset) {
251 /*
252 * Move the rdata cursor to the first rdata in the rdataset (if any).
253 */
254
255 REQUIRE(DNS_RDATASET_VALID(rdataset));
256 REQUIRE(rdataset->methods != NULL);
257
258 return ((rdataset->methods->first)(rdataset));
259 }
260
261 isc_result_t
dns_rdataset_next(dns_rdataset_t * rdataset)262 dns_rdataset_next(dns_rdataset_t *rdataset) {
263 /*
264 * Move the rdata cursor to the next rdata in the rdataset (if any).
265 */
266
267 REQUIRE(DNS_RDATASET_VALID(rdataset));
268 REQUIRE(rdataset->methods != NULL);
269
270 return ((rdataset->methods->next)(rdataset));
271 }
272
273 void
dns_rdataset_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)274 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
275 /*
276 * Make 'rdata' refer to the current rdata.
277 */
278
279 REQUIRE(DNS_RDATASET_VALID(rdataset));
280 REQUIRE(rdataset->methods != NULL);
281
282 (rdataset->methods->current)(rdataset, rdata);
283 }
284
285 #define MAX_SHUFFLE 32
286 #define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
287 #define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
288 #define WANT_CYCLIC(r) (((r)->attributes & DNS_RDATASETATTR_CYCLIC) != 0)
289
290 struct towire_sort {
291 int key;
292 dns_rdata_t *rdata;
293 };
294
295 static int
towire_compare(const void * av,const void * bv)296 towire_compare(const void *av, const void *bv) {
297 const struct towire_sort *a = (const struct towire_sort *)av;
298 const struct towire_sort *b = (const struct towire_sort *)bv;
299 return (a->key - b->key);
300 }
301
302 static void
swap_rdata(dns_rdata_t * in,unsigned int a,unsigned int b)303 swap_rdata(dns_rdata_t *in, unsigned int a, unsigned int b) {
304 dns_rdata_t rdata = in[a];
305 in[a] = in[b];
306 in[b] = rdata;
307 }
308
309 static isc_result_t
towiresorted(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,bool partial,unsigned int options,unsigned int * countp,void ** state)310 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
311 dns_compress_t *cctx, isc_buffer_t *target,
312 dns_rdatasetorderfunc_t order, const void *order_arg, bool partial,
313 unsigned int options, unsigned int *countp, void **state) {
314 isc_region_t r;
315 isc_result_t result;
316 unsigned int i, count = 0, added;
317 isc_buffer_t savedbuffer, rdlen, rrbuffer;
318 unsigned int headlen;
319 bool question = false;
320 bool shuffle = false, sort = false;
321 bool want_random, want_cyclic;
322 dns_rdata_t in_fixed[MAX_SHUFFLE];
323 dns_rdata_t *in = in_fixed;
324 struct towire_sort out_fixed[MAX_SHUFFLE];
325 struct towire_sort *out = out_fixed;
326 dns_fixedname_t fixed;
327 dns_name_t *name;
328 uint16_t offset;
329
330 UNUSED(state);
331
332 /*
333 * Convert 'rdataset' to wire format, compressing names as specified
334 * in cctx, and storing the result in 'target'.
335 */
336
337 REQUIRE(DNS_RDATASET_VALID(rdataset));
338 REQUIRE(rdataset->methods != NULL);
339 REQUIRE(countp != NULL);
340 REQUIRE(cctx != NULL && cctx->mctx != NULL);
341
342 want_random = WANT_RANDOM(rdataset);
343 want_cyclic = WANT_CYCLIC(rdataset);
344
345 if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
346 question = true;
347 count = 1;
348 result = dns_rdataset_first(rdataset);
349 INSIST(result == ISC_R_NOMORE);
350 } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
351 /*
352 * This is a negative caching rdataset.
353 */
354 unsigned int ncache_opts = 0;
355 if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0) {
356 ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
357 }
358 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
359 countp));
360 } else {
361 count = (rdataset->methods->count)(rdataset);
362 result = dns_rdataset_first(rdataset);
363 if (result == ISC_R_NOMORE) {
364 return (ISC_R_SUCCESS);
365 }
366 if (result != ISC_R_SUCCESS) {
367 return (result);
368 }
369 }
370
371 /*
372 * Do we want to sort and/or shuffle this answer?
373 */
374 if (!question && count > 1 && rdataset->type != dns_rdatatype_rrsig) {
375 if (order != NULL) {
376 sort = true;
377 }
378 if (want_random || want_cyclic) {
379 shuffle = true;
380 }
381 }
382
383 if ((shuffle || sort)) {
384 if (count > MAX_SHUFFLE) {
385 in = isc_mem_get(cctx->mctx, count * sizeof(*in));
386 out = isc_mem_get(cctx->mctx, count * sizeof(*out));
387 if (in == NULL || out == NULL) {
388 shuffle = sort = false;
389 }
390 }
391 }
392
393 if ((shuffle || sort)) {
394 uint32_t seed = 0;
395 unsigned int j = 0;
396
397 /*
398 * First we get handles to all of the rdata.
399 */
400 i = 0;
401 do {
402 INSIST(i < count);
403 dns_rdata_init(&in[i]);
404 dns_rdataset_current(rdataset, &in[i]);
405 i++;
406 result = dns_rdataset_next(rdataset);
407 } while (result == ISC_R_SUCCESS);
408 if (result != ISC_R_NOMORE) {
409 goto cleanup;
410 }
411 INSIST(i == count);
412
413 if (ISC_LIKELY(want_random)) {
414 seed = isc_random32();
415 }
416
417 if (ISC_UNLIKELY(want_cyclic) &&
418 (rdataset->count != DNS_RDATASET_COUNT_UNDEFINED))
419 {
420 j = rdataset->count % count;
421 }
422
423 for (i = 0; i < count; i++) {
424 if (ISC_LIKELY(want_random)) {
425 swap_rdata(in, j, j + seed % (count - j));
426 }
427
428 out[i].key = (sort) ? (*order)(&in[j], order_arg) : 0;
429 out[i].rdata = &in[j];
430 if (++j == count) {
431 j = 0;
432 }
433 }
434 /*
435 * Sortlist order.
436 */
437 if (sort) {
438 qsort(out, count, sizeof(out[0]), towire_compare);
439 }
440 }
441
442 savedbuffer = *target;
443 i = 0;
444 added = 0;
445
446 name = dns_fixedname_initname(&fixed);
447 dns_name_copynf(owner_name, name);
448 dns_rdataset_getownercase(rdataset, name);
449 offset = 0xffff;
450
451 name->attributes |= owner_name->attributes & DNS_NAMEATTR_NOCOMPRESS;
452
453 do {
454 /*
455 * Copy out the name, type, class, ttl.
456 */
457
458 rrbuffer = *target;
459 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
460 result = dns_name_towire2(name, cctx, target, &offset);
461 if (result != ISC_R_SUCCESS) {
462 goto rollback;
463 }
464 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
465 if (!question) {
466 headlen += sizeof(dns_ttl_t) + 2;
467 } /* XXX 2 for rdata len
468 */
469 isc_buffer_availableregion(target, &r);
470 if (r.length < headlen) {
471 result = ISC_R_NOSPACE;
472 goto rollback;
473 }
474 isc_buffer_putuint16(target, rdataset->type);
475 isc_buffer_putuint16(target, rdataset->rdclass);
476 if (!question) {
477 dns_rdata_t rdata = DNS_RDATA_INIT;
478
479 isc_buffer_putuint32(target, rdataset->ttl);
480
481 /*
482 * Save space for rdlen.
483 */
484 rdlen = *target;
485 isc_buffer_add(target, 2);
486
487 /*
488 * Copy out the rdata
489 */
490 if (shuffle || sort) {
491 rdata = *(out[i].rdata);
492 } else {
493 dns_rdata_reset(&rdata);
494 dns_rdataset_current(rdataset, &rdata);
495 }
496 result = dns_rdata_towire(&rdata, cctx, target);
497 if (result != ISC_R_SUCCESS) {
498 goto rollback;
499 }
500 INSIST((target->used >= rdlen.used + 2) &&
501 (target->used - rdlen.used - 2 < 65536));
502 isc_buffer_putuint16(
503 &rdlen,
504 (uint16_t)(target->used - rdlen.used - 2));
505 added++;
506 }
507
508 if (shuffle || sort) {
509 i++;
510 if (i == count) {
511 result = ISC_R_NOMORE;
512 } else {
513 result = ISC_R_SUCCESS;
514 }
515 } else {
516 result = dns_rdataset_next(rdataset);
517 }
518 } while (result == ISC_R_SUCCESS);
519
520 if (result != ISC_R_NOMORE) {
521 goto rollback;
522 }
523
524 *countp += count;
525
526 result = ISC_R_SUCCESS;
527 goto cleanup;
528
529 rollback:
530 if (partial && result == ISC_R_NOSPACE) {
531 INSIST(rrbuffer.used < 65536);
532 dns_compress_rollback(cctx, (uint16_t)rrbuffer.used);
533 *countp += added;
534 *target = rrbuffer;
535 goto cleanup;
536 }
537 INSIST(savedbuffer.used < 65536);
538 dns_compress_rollback(cctx, (uint16_t)savedbuffer.used);
539 *countp = 0;
540 *target = savedbuffer;
541
542 cleanup:
543 if (out != NULL && out != out_fixed) {
544 isc_mem_put(cctx->mctx, out, count * sizeof(*out));
545 }
546 if (in != NULL && in != in_fixed) {
547 isc_mem_put(cctx->mctx, in, count * sizeof(*in));
548 }
549 return (result);
550 }
551
552 isc_result_t
dns_rdataset_towiresorted(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,unsigned int options,unsigned int * countp)553 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
554 const dns_name_t *owner_name, dns_compress_t *cctx,
555 isc_buffer_t *target, dns_rdatasetorderfunc_t order,
556 const void *order_arg, unsigned int options,
557 unsigned int *countp) {
558 return (towiresorted(rdataset, owner_name, cctx, target, order,
559 order_arg, false, options, countp, NULL));
560 }
561
562 isc_result_t
dns_rdataset_towirepartial(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,dns_rdatasetorderfunc_t order,const void * order_arg,unsigned int options,unsigned int * countp,void ** state)563 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
564 const dns_name_t *owner_name, dns_compress_t *cctx,
565 isc_buffer_t *target, dns_rdatasetorderfunc_t order,
566 const void *order_arg, unsigned int options,
567 unsigned int *countp, void **state) {
568 REQUIRE(state == NULL); /* XXX remove when implemented */
569 return (towiresorted(rdataset, owner_name, cctx, target, order,
570 order_arg, true, options, countp, state));
571 }
572
573 isc_result_t
dns_rdataset_towire(dns_rdataset_t * rdataset,const dns_name_t * owner_name,dns_compress_t * cctx,isc_buffer_t * target,unsigned int options,unsigned int * countp)574 dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
575 dns_compress_t *cctx, isc_buffer_t *target,
576 unsigned int options, unsigned int *countp) {
577 return (towiresorted(rdataset, owner_name, cctx, target, NULL, NULL,
578 false, options, countp, NULL));
579 }
580
581 isc_result_t
dns_rdataset_additionaldata(dns_rdataset_t * rdataset,dns_additionaldatafunc_t add,void * arg)582 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
583 dns_additionaldatafunc_t add, void *arg) {
584 dns_rdata_t rdata = DNS_RDATA_INIT;
585 isc_result_t result;
586
587 /*
588 * For each rdata in rdataset, call 'add' for each name and type in the
589 * rdata which is subject to additional section processing.
590 */
591
592 REQUIRE(DNS_RDATASET_VALID(rdataset));
593 REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
594
595 result = dns_rdataset_first(rdataset);
596 if (result != ISC_R_SUCCESS) {
597 return (result);
598 }
599
600 do {
601 dns_rdataset_current(rdataset, &rdata);
602 result = dns_rdata_additionaldata(&rdata, add, arg);
603 if (result == ISC_R_SUCCESS) {
604 result = dns_rdataset_next(rdataset);
605 }
606 dns_rdata_reset(&rdata);
607 } while (result == ISC_R_SUCCESS);
608
609 if (result != ISC_R_NOMORE) {
610 return (result);
611 }
612
613 return (ISC_R_SUCCESS);
614 }
615
616 isc_result_t
dns_rdataset_addnoqname(dns_rdataset_t * rdataset,dns_name_t * name)617 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
618 REQUIRE(DNS_RDATASET_VALID(rdataset));
619 REQUIRE(rdataset->methods != NULL);
620 if (rdataset->methods->addnoqname == NULL) {
621 return (ISC_R_NOTIMPLEMENTED);
622 }
623 return ((rdataset->methods->addnoqname)(rdataset, name));
624 }
625
626 isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)627 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
628 dns_rdataset_t *neg, dns_rdataset_t *negsig) {
629 REQUIRE(DNS_RDATASET_VALID(rdataset));
630 REQUIRE(rdataset->methods != NULL);
631
632 if (rdataset->methods->getnoqname == NULL) {
633 return (ISC_R_NOTIMPLEMENTED);
634 }
635 return ((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
636 }
637
638 isc_result_t
dns_rdataset_addclosest(dns_rdataset_t * rdataset,const dns_name_t * name)639 dns_rdataset_addclosest(dns_rdataset_t *rdataset, const dns_name_t *name) {
640 REQUIRE(DNS_RDATASET_VALID(rdataset));
641 REQUIRE(rdataset->methods != NULL);
642 if (rdataset->methods->addclosest == NULL) {
643 return (ISC_R_NOTIMPLEMENTED);
644 }
645 return ((rdataset->methods->addclosest)(rdataset, name));
646 }
647
648 isc_result_t
dns_rdataset_getclosest(dns_rdataset_t * rdataset,dns_name_t * name,dns_rdataset_t * neg,dns_rdataset_t * negsig)649 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
650 dns_rdataset_t *neg, dns_rdataset_t *negsig) {
651 REQUIRE(DNS_RDATASET_VALID(rdataset));
652 REQUIRE(rdataset->methods != NULL);
653
654 if (rdataset->methods->getclosest == NULL) {
655 return (ISC_R_NOTIMPLEMENTED);
656 }
657 return ((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
658 }
659
660 void
dns_rdataset_settrust(dns_rdataset_t * rdataset,dns_trust_t trust)661 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
662 REQUIRE(DNS_RDATASET_VALID(rdataset));
663 REQUIRE(rdataset->methods != NULL);
664
665 if (rdataset->methods->settrust != NULL) {
666 (rdataset->methods->settrust)(rdataset, trust);
667 } else {
668 rdataset->trust = trust;
669 }
670 }
671
672 void
dns_rdataset_expire(dns_rdataset_t * rdataset)673 dns_rdataset_expire(dns_rdataset_t *rdataset) {
674 REQUIRE(DNS_RDATASET_VALID(rdataset));
675 REQUIRE(rdataset->methods != NULL);
676
677 if (rdataset->methods->expire != NULL) {
678 (rdataset->methods->expire)(rdataset);
679 }
680 }
681
682 void
dns_rdataset_clearprefetch(dns_rdataset_t * rdataset)683 dns_rdataset_clearprefetch(dns_rdataset_t *rdataset) {
684 REQUIRE(DNS_RDATASET_VALID(rdataset));
685 REQUIRE(rdataset->methods != NULL);
686
687 if (rdataset->methods->clearprefetch != NULL) {
688 (rdataset->methods->clearprefetch)(rdataset);
689 }
690 }
691
692 void
dns_rdataset_setownercase(dns_rdataset_t * rdataset,const dns_name_t * name)693 dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
694 REQUIRE(DNS_RDATASET_VALID(rdataset));
695 REQUIRE(rdataset->methods != NULL);
696
697 if (rdataset->methods->setownercase != NULL) {
698 (rdataset->methods->setownercase)(rdataset, name);
699 }
700 }
701
702 void
dns_rdataset_getownercase(const dns_rdataset_t * rdataset,dns_name_t * name)703 dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
704 REQUIRE(DNS_RDATASET_VALID(rdataset));
705 REQUIRE(rdataset->methods != NULL);
706
707 if (rdataset->methods->getownercase != NULL) {
708 (rdataset->methods->getownercase)(rdataset, name);
709 }
710 }
711
712 void
dns_rdataset_trimttl(dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,dns_rdata_rrsig_t * rrsig,isc_stdtime_t now,bool acceptexpired)713 dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
714 dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
715 bool acceptexpired) {
716 uint32_t ttl = 0;
717
718 REQUIRE(DNS_RDATASET_VALID(rdataset));
719 REQUIRE(DNS_RDATASET_VALID(sigrdataset));
720 REQUIRE(rrsig != NULL);
721
722 /*
723 * If we accept expired RRsets keep them for no more than 120 seconds.
724 */
725 if (acceptexpired &&
726 (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) ||
727 isc_serial_le(rrsig->timeexpire, now)))
728 {
729 ttl = 120;
730 } else if (isc_serial_ge(rrsig->timeexpire, now)) {
731 ttl = rrsig->timeexpire - now;
732 }
733
734 ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl),
735 ISC_MIN(rrsig->originalttl, ttl));
736 rdataset->ttl = ttl;
737 sigrdataset->ttl = ttl;
738 }
739
740 isc_result_t
dns_rdataset_addglue(dns_rdataset_t * rdataset,dns_dbversion_t * version,dns_message_t * msg)741 dns_rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
742 dns_message_t *msg) {
743 REQUIRE(DNS_RDATASET_VALID(rdataset));
744 REQUIRE(rdataset->methods != NULL);
745 REQUIRE(rdataset->type == dns_rdatatype_ns);
746
747 if (rdataset->methods->addglue == NULL) {
748 return (ISC_R_NOTIMPLEMENTED);
749 }
750
751 return ((rdataset->methods->addglue)(rdataset, version, msg));
752 }
753