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