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