]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/rdataset.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / rdataset.c
1 /*
2  * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <stdlib.h>
25
26 #include <isc/buffer.h>
27 #include <isc/mem.h>
28 #include <isc/random.h>
29 #include <isc/serial.h>
30 #include <isc/util.h>
31
32 #include <dns/name.h>
33 #include <dns/ncache.h>
34 #include <dns/rdata.h>
35 #include <dns/rdataset.h>
36 #include <dns/compress.h>
37
38 static const char *trustnames[] = {
39         "none",
40         "pending-additional",
41         "pending-answer",
42         "additional",
43         "glue",
44         "answer",
45         "authauthority",
46         "authanswer",
47         "secure",
48         "local" /* aka ultimate */
49 };
50
51 const char *
52 dns_trust_totext(dns_trust_t trust) {
53         if (trust >= sizeof(trustnames)/sizeof(*trustnames))
54                 return ("bad");
55         return (trustnames[trust]);
56 }
57
58 void
59 dns_rdataset_init(dns_rdataset_t *rdataset) {
60
61         /*
62          * Make 'rdataset' a valid, disassociated rdataset.
63          */
64
65         REQUIRE(rdataset != NULL);
66
67         rdataset->magic = DNS_RDATASET_MAGIC;
68         rdataset->methods = NULL;
69         ISC_LINK_INIT(rdataset, link);
70         rdataset->rdclass = 0;
71         rdataset->type = 0;
72         rdataset->ttl = 0;
73         rdataset->trust = 0;
74         rdataset->covers = 0;
75         rdataset->attributes = 0;
76         rdataset->count = ISC_UINT32_MAX;
77         rdataset->private1 = NULL;
78         rdataset->private2 = NULL;
79         rdataset->private3 = NULL;
80         rdataset->privateuint4 = 0;
81         rdataset->private5 = NULL;
82         rdataset->private6 = NULL;
83         rdataset->resign = 0;
84 }
85
86 void
87 dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
88
89         /*
90          * Invalidate 'rdataset'.
91          */
92
93         REQUIRE(DNS_RDATASET_VALID(rdataset));
94         REQUIRE(rdataset->methods == NULL);
95
96         rdataset->magic = 0;
97         ISC_LINK_INIT(rdataset, link);
98         rdataset->rdclass = 0;
99         rdataset->type = 0;
100         rdataset->ttl = 0;
101         rdataset->trust = 0;
102         rdataset->covers = 0;
103         rdataset->attributes = 0;
104         rdataset->count = ISC_UINT32_MAX;
105         rdataset->private1 = NULL;
106         rdataset->private2 = NULL;
107         rdataset->private3 = NULL;
108         rdataset->privateuint4 = 0;
109         rdataset->private5 = NULL;
110 }
111
112 void
113 dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
114
115         /*
116          * Disassociate 'rdataset' from its rdata, allowing it to be reused.
117          */
118
119         REQUIRE(DNS_RDATASET_VALID(rdataset));
120         REQUIRE(rdataset->methods != NULL);
121
122         (rdataset->methods->disassociate)(rdataset);
123         rdataset->methods = NULL;
124         ISC_LINK_INIT(rdataset, link);
125         rdataset->rdclass = 0;
126         rdataset->type = 0;
127         rdataset->ttl = 0;
128         rdataset->trust = 0;
129         rdataset->covers = 0;
130         rdataset->attributes = 0;
131         rdataset->count = ISC_UINT32_MAX;
132         rdataset->private1 = NULL;
133         rdataset->private2 = NULL;
134         rdataset->private3 = NULL;
135         rdataset->privateuint4 = 0;
136         rdataset->private5 = NULL;
137         rdataset->private6 = NULL;
138 }
139
140 isc_boolean_t
141 dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
142         /*
143          * Is 'rdataset' associated?
144          */
145
146         REQUIRE(DNS_RDATASET_VALID(rdataset));
147
148         if (rdataset->methods != NULL)
149                 return (ISC_TRUE);
150
151         return (ISC_FALSE);
152 }
153
154 static void
155 question_disassociate(dns_rdataset_t *rdataset) {
156         UNUSED(rdataset);
157 }
158
159 static isc_result_t
160 question_cursor(dns_rdataset_t *rdataset) {
161         UNUSED(rdataset);
162
163         return (ISC_R_NOMORE);
164 }
165
166 static void
167 question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
168         /*
169          * This routine should never be called.
170          */
171         UNUSED(rdataset);
172         UNUSED(rdata);
173
174         REQUIRE(0);
175 }
176
177 static void
178 question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
179         *target = *source;
180 }
181
182 static unsigned int
183 question_count(dns_rdataset_t *rdataset) {
184         /*
185          * This routine should never be called.
186          */
187         UNUSED(rdataset);
188         REQUIRE(0);
189
190         return (0);
191 }
192
193 static dns_rdatasetmethods_t question_methods = {
194         question_disassociate,
195         question_cursor,
196         question_cursor,
197         question_current,
198         question_clone,
199         question_count,
200         NULL,
201         NULL,
202         NULL,
203         NULL,
204         NULL,
205         NULL,
206         NULL,
207         NULL,
208         NULL
209 };
210
211 void
212 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
213                           dns_rdatatype_t type)
214 {
215
216         /*
217          * Make 'rdataset' a valid, associated, question rdataset, with a
218          * question class of 'rdclass' and type 'type'.
219          */
220
221         REQUIRE(DNS_RDATASET_VALID(rdataset));
222         REQUIRE(rdataset->methods == NULL);
223
224         rdataset->methods = &question_methods;
225         rdataset->rdclass = rdclass;
226         rdataset->type = type;
227         rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
228 }
229
230 unsigned int
231 dns_rdataset_count(dns_rdataset_t *rdataset) {
232
233         /*
234          * Return the number of records in 'rdataset'.
235          */
236
237         REQUIRE(DNS_RDATASET_VALID(rdataset));
238         REQUIRE(rdataset->methods != NULL);
239
240         return ((rdataset->methods->count)(rdataset));
241 }
242
243 void
244 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
245
246         /*
247          * Make 'target' refer to the same rdataset as 'source'.
248          */
249
250         REQUIRE(DNS_RDATASET_VALID(source));
251         REQUIRE(source->methods != NULL);
252         REQUIRE(DNS_RDATASET_VALID(target));
253         REQUIRE(target->methods == NULL);
254
255         (source->methods->clone)(source, target);
256 }
257
258 isc_result_t
259 dns_rdataset_first(dns_rdataset_t *rdataset) {
260
261         /*
262          * Move the rdata cursor to the first rdata in the rdataset (if any).
263          */
264
265         REQUIRE(DNS_RDATASET_VALID(rdataset));
266         REQUIRE(rdataset->methods != NULL);
267
268         return ((rdataset->methods->first)(rdataset));
269 }
270
271 isc_result_t
272 dns_rdataset_next(dns_rdataset_t *rdataset) {
273
274         /*
275          * Move the rdata cursor to the next rdata in the rdataset (if any).
276          */
277
278         REQUIRE(DNS_RDATASET_VALID(rdataset));
279         REQUIRE(rdataset->methods != NULL);
280
281         return ((rdataset->methods->next)(rdataset));
282 }
283
284 void
285 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
286
287         /*
288          * Make 'rdata' refer to the current rdata.
289          */
290
291         REQUIRE(DNS_RDATASET_VALID(rdataset));
292         REQUIRE(rdataset->methods != NULL);
293
294         (rdataset->methods->current)(rdataset, rdata);
295 }
296
297 #define MAX_SHUFFLE     32
298 #define WANT_FIXED(r)   (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
299 #define WANT_RANDOM(r)  (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
300
301 struct towire_sort {
302         int key;
303         dns_rdata_t *rdata;
304 };
305
306 static int
307 towire_compare(const void *av, const void *bv) {
308         const struct towire_sort *a = (const struct towire_sort *) av;
309         const struct towire_sort *b = (const struct towire_sort *) bv;
310         return (a->key - b->key);
311 }
312
313 static isc_result_t
314 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
315              dns_compress_t *cctx, isc_buffer_t *target,
316              dns_rdatasetorderfunc_t order, const void *order_arg,
317              isc_boolean_t partial, unsigned int options,
318              unsigned int *countp, void **state)
319 {
320         dns_rdata_t rdata = DNS_RDATA_INIT;
321         isc_region_t r;
322         isc_result_t result;
323         unsigned int i, count = 0, added, choice;
324         isc_buffer_t savedbuffer, rdlen, rrbuffer;
325         unsigned int headlen;
326         isc_boolean_t question = ISC_FALSE;
327         isc_boolean_t shuffle = ISC_FALSE;
328         dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
329         struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
330
331         UNUSED(state);
332
333         /*
334          * Convert 'rdataset' to wire format, compressing names as specified
335          * in cctx, and storing the result in 'target'.
336          */
337
338         REQUIRE(DNS_RDATASET_VALID(rdataset));
339         REQUIRE(countp != NULL);
340         REQUIRE((order == NULL) == (order_arg == NULL));
341         REQUIRE(cctx != NULL && cctx->mctx != NULL);
342
343         if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
344                 question = ISC_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                 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
356                                           countp));
357         } else {
358                 count = (rdataset->methods->count)(rdataset);
359                 result = dns_rdataset_first(rdataset);
360                 if (result == ISC_R_NOMORE)
361                         return (ISC_R_SUCCESS);
362                 if (result != ISC_R_SUCCESS)
363                         return (result);
364         }
365
366         /*
367          * Do we want to shuffle this answer?
368          */
369         if (!question && count > 1 &&
370             (!WANT_FIXED(rdataset) || order != NULL) &&
371             rdataset->type != dns_rdatatype_rrsig)
372                 shuffle = ISC_TRUE;
373
374         if (shuffle && count > MAX_SHUFFLE) {
375                 shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
376                 sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
377                 if (shuffled == NULL || sorted == NULL)
378                         shuffle = ISC_FALSE;
379         } else {
380                 shuffled = shuffled_fixed;
381                 sorted = sorted_fixed;
382         }
383
384         if (shuffle) {
385                 /*
386                  * First we get handles to all of the rdata.
387                  */
388                 i = 0;
389                 do {
390                         INSIST(i < count);
391                         dns_rdata_init(&shuffled[i]);
392                         dns_rdataset_current(rdataset, &shuffled[i]);
393                         i++;
394                         result = dns_rdataset_next(rdataset);
395                 } while (result == ISC_R_SUCCESS);
396                 if (result != ISC_R_NOMORE)
397                         goto cleanup;
398                 INSIST(i == count);
399
400                 /*
401                  * Now we shuffle.
402                  */
403                 if (WANT_FIXED(rdataset)) {
404                         /*
405                          * 'Fixed' order.
406                          */
407                         INSIST(order != NULL);
408                         for (i = 0; i < count; i++) {
409                                 sorted[i].key = (*order)(&shuffled[i],
410                                                          order_arg);
411                                 sorted[i].rdata = &shuffled[i];
412                         }
413                 } else if (WANT_RANDOM(rdataset)) {
414                         /*
415                          * 'Random' order.
416                          */
417                         for (i = 0; i < count; i++) {
418                                 dns_rdata_t rdata;
419                                 isc_uint32_t val;
420
421                                 isc_random_get(&val);
422                                 choice = i + (val % (count - i));
423                                 rdata = shuffled[i];
424                                 shuffled[i] = shuffled[choice];
425                                 shuffled[choice] = rdata;
426                                 if (order != NULL)
427                                         sorted[i].key = (*order)(&shuffled[i],
428                                                                  order_arg);
429                                 else
430                                         sorted[i].key = 0; /* Unused */
431                                 sorted[i].rdata = &shuffled[i];
432                         }
433                 } else {
434                         /*
435                          * "Cyclic" order.
436                          */
437                         isc_uint32_t val;
438                         unsigned int j;
439
440                         val = rdataset->count;
441                         if (val == ISC_UINT32_MAX)
442                                 isc_random_get(&val);
443                         j = val % count;
444                         for (i = 0; i < count; i++) {
445                                 if (order != NULL)
446                                         sorted[i].key = (*order)(&shuffled[j],
447                                                                  order_arg);
448                                 else
449                                         sorted[i].key = 0; /* Unused */
450                                 sorted[i].rdata = &shuffled[j];
451                                 j++;
452                                 if (j == count)
453                                         j = 0; /* Wrap around. */
454                         }
455                 }
456
457                 /*
458                  * Sorted order.
459                  */
460                 if (order != NULL)
461                         qsort(sorted, count, sizeof(sorted[0]),
462                               towire_compare);
463         }
464
465         savedbuffer = *target;
466         i = 0;
467         added = 0;
468
469         do {
470                 /*
471                  * Copy out the name, type, class, ttl.
472                  */
473
474                 rrbuffer = *target;
475                 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
476                 result = dns_name_towire(owner_name, cctx, target);
477                 if (result != ISC_R_SUCCESS)
478                         goto rollback;
479                 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
480                 if (!question)
481                         headlen += sizeof(dns_ttl_t)
482                                 + 2;  /* XXX 2 for rdata len */
483                 isc_buffer_availableregion(target, &r);
484                 if (r.length < headlen) {
485                         result = ISC_R_NOSPACE;
486                         goto rollback;
487                 }
488                 isc_buffer_putuint16(target, rdataset->type);
489                 isc_buffer_putuint16(target, rdataset->rdclass);
490                 if (!question) {
491                         isc_buffer_putuint32(target, rdataset->ttl);
492
493                         /*
494                          * Save space for rdlen.
495                          */
496                         rdlen = *target;
497                         isc_buffer_add(target, 2);
498
499                         /*
500                          * Copy out the rdata
501                          */
502                         if (shuffle)
503                                 rdata = *(sorted[i].rdata);
504                         else {
505                                 dns_rdata_reset(&rdata);
506                                 dns_rdataset_current(rdataset, &rdata);
507                         }
508                         result = dns_rdata_towire(&rdata, cctx, target);
509                         if (result != ISC_R_SUCCESS)
510                                 goto rollback;
511                         INSIST((target->used >= rdlen.used + 2) &&
512                                (target->used - rdlen.used - 2 < 65536));
513                         isc_buffer_putuint16(&rdlen,
514                                              (isc_uint16_t)(target->used -
515                                                             rdlen.used - 2));
516                         added++;
517                 }
518
519                 if (shuffle) {
520                         i++;
521                         if (i == count)
522                                 result = ISC_R_NOMORE;
523                         else
524                                 result = ISC_R_SUCCESS;
525                 } else {
526                         result = dns_rdataset_next(rdataset);
527                 }
528         } while (result == ISC_R_SUCCESS);
529
530         if (result != ISC_R_NOMORE)
531                 goto rollback;
532
533         *countp += count;
534
535         result = ISC_R_SUCCESS;
536         goto cleanup;
537
538  rollback:
539         if (partial && result == ISC_R_NOSPACE) {
540                 INSIST(rrbuffer.used < 65536);
541                 dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
542                 *countp += added;
543                 *target = rrbuffer;
544                 goto cleanup;
545         }
546         INSIST(savedbuffer.used < 65536);
547         dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
548         *countp = 0;
549         *target = savedbuffer;
550
551  cleanup:
552         if (sorted != NULL && sorted != sorted_fixed)
553                 isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
554         if (shuffled != NULL && shuffled != shuffled_fixed)
555                 isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
556         return (result);
557 }
558
559 isc_result_t
560 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
561                           const dns_name_t *owner_name,
562                           dns_compress_t *cctx,
563                           isc_buffer_t *target,
564                           dns_rdatasetorderfunc_t order,
565                           const void *order_arg,
566                           unsigned int options,
567                           unsigned int *countp)
568 {
569         return (towiresorted(rdataset, owner_name, cctx, target,
570                              order, order_arg, ISC_FALSE, options,
571                              countp, NULL));
572 }
573
574 isc_result_t
575 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
576                            const dns_name_t *owner_name,
577                            dns_compress_t *cctx,
578                            isc_buffer_t *target,
579                            dns_rdatasetorderfunc_t order,
580                            const void *order_arg,
581                            unsigned int options,
582                            unsigned int *countp,
583                            void **state)
584 {
585         REQUIRE(state == NULL); /* XXX remove when implemented */
586         return (towiresorted(rdataset, owner_name, cctx, target,
587                              order, order_arg, ISC_TRUE, options,
588                              countp, state));
589 }
590
591 isc_result_t
592 dns_rdataset_towire(dns_rdataset_t *rdataset,
593                     dns_name_t *owner_name,
594                     dns_compress_t *cctx,
595                     isc_buffer_t *target,
596                     unsigned int options,
597                     unsigned int *countp)
598 {
599         return (towiresorted(rdataset, owner_name, cctx, target,
600                              NULL, NULL, ISC_FALSE, options, countp, NULL));
601 }
602
603 isc_result_t
604 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
605                             dns_additionaldatafunc_t add, void *arg)
606 {
607         dns_rdata_t rdata = DNS_RDATA_INIT;
608         isc_result_t result;
609
610         /*
611          * For each rdata in rdataset, call 'add' for each name and type in the
612          * rdata which is subject to additional section processing.
613          */
614
615         REQUIRE(DNS_RDATASET_VALID(rdataset));
616         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
617
618         result = dns_rdataset_first(rdataset);
619         if (result != ISC_R_SUCCESS)
620                 return (result);
621
622         do {
623                 dns_rdataset_current(rdataset, &rdata);
624                 result = dns_rdata_additionaldata(&rdata, add, arg);
625                 if (result == ISC_R_SUCCESS)
626                         result = dns_rdataset_next(rdataset);
627                 dns_rdata_reset(&rdata);
628         } while (result == ISC_R_SUCCESS);
629
630         if (result != ISC_R_NOMORE)
631                 return (result);
632
633         return (ISC_R_SUCCESS);
634 }
635
636 isc_result_t
637 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
638
639         REQUIRE(DNS_RDATASET_VALID(rdataset));
640         REQUIRE(rdataset->methods != NULL);
641         if (rdataset->methods->addnoqname == NULL)
642                 return (ISC_R_NOTIMPLEMENTED);
643         return((rdataset->methods->addnoqname)(rdataset, name));
644 }
645
646 isc_result_t
647 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
648                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
649 {
650         REQUIRE(DNS_RDATASET_VALID(rdataset));
651         REQUIRE(rdataset->methods != NULL);
652
653         if (rdataset->methods->getnoqname == NULL)
654                 return (ISC_R_NOTIMPLEMENTED);
655         return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
656 }
657
658 isc_result_t
659 dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
660
661         REQUIRE(DNS_RDATASET_VALID(rdataset));
662         REQUIRE(rdataset->methods != NULL);
663         if (rdataset->methods->addclosest == NULL)
664                 return (ISC_R_NOTIMPLEMENTED);
665         return((rdataset->methods->addclosest)(rdataset, name));
666 }
667
668 isc_result_t
669 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
670                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
671 {
672         REQUIRE(DNS_RDATASET_VALID(rdataset));
673         REQUIRE(rdataset->methods != NULL);
674
675         if (rdataset->methods->getclosest == NULL)
676                 return (ISC_R_NOTIMPLEMENTED);
677         return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
678 }
679
680 /*
681  * Additional cache stuff
682  */
683 isc_result_t
684 dns_rdataset_getadditional(dns_rdataset_t *rdataset,
685                            dns_rdatasetadditional_t type,
686                            dns_rdatatype_t qtype,
687                            dns_acache_t *acache,
688                            dns_zone_t **zonep,
689                            dns_db_t **dbp,
690                            dns_dbversion_t **versionp,
691                            dns_dbnode_t **nodep,
692                            dns_name_t *fname,
693                            dns_message_t *msg,
694                            isc_stdtime_t now)
695 {
696         REQUIRE(DNS_RDATASET_VALID(rdataset));
697         REQUIRE(rdataset->methods != NULL);
698         REQUIRE(zonep == NULL || *zonep == NULL);
699         REQUIRE(dbp != NULL && *dbp == NULL);
700         REQUIRE(versionp != NULL && *versionp == NULL);
701         REQUIRE(nodep != NULL && *nodep == NULL);
702         REQUIRE(fname != NULL);
703         REQUIRE(msg != NULL);
704
705         if (acache != NULL && rdataset->methods->getadditional != NULL) {
706                 return ((rdataset->methods->getadditional)(rdataset, type,
707                                                            qtype, acache,
708                                                            zonep, dbp,
709                                                            versionp, nodep,
710                                                            fname, msg, now));
711         }
712
713         return (ISC_R_FAILURE);
714 }
715
716 isc_result_t
717 dns_rdataset_setadditional(dns_rdataset_t *rdataset,
718                            dns_rdatasetadditional_t type,
719                            dns_rdatatype_t qtype,
720                            dns_acache_t *acache,
721                            dns_zone_t *zone,
722                            dns_db_t *db,
723                            dns_dbversion_t *version,
724                            dns_dbnode_t *node,
725                            dns_name_t *fname)
726 {
727         REQUIRE(DNS_RDATASET_VALID(rdataset));
728         REQUIRE(rdataset->methods != NULL);
729
730         if (acache != NULL && rdataset->methods->setadditional != NULL) {
731                 return ((rdataset->methods->setadditional)(rdataset, type,
732                                                            qtype, acache, zone,
733                                                            db, version,
734                                                            node, fname));
735         }
736
737         return (ISC_R_FAILURE);
738 }
739
740 isc_result_t
741 dns_rdataset_putadditional(dns_acache_t *acache,
742                            dns_rdataset_t *rdataset,
743                            dns_rdatasetadditional_t type,
744                            dns_rdatatype_t qtype)
745 {
746         REQUIRE(DNS_RDATASET_VALID(rdataset));
747         REQUIRE(rdataset->methods != NULL);
748
749         if (acache != NULL && rdataset->methods->putadditional != NULL) {
750                 return ((rdataset->methods->putadditional)(acache, rdataset,
751                                                            type, qtype));
752         }
753
754         return (ISC_R_FAILURE);
755 }
756
757 void
758 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
759         REQUIRE(DNS_RDATASET_VALID(rdataset));
760         REQUIRE(rdataset->methods != NULL);
761
762         if (rdataset->methods->settrust != NULL)
763                 (rdataset->methods->settrust)(rdataset, trust);
764         else
765                 rdataset->trust = trust;
766 }
767
768 void
769 dns_rdataset_expire(dns_rdataset_t *rdataset) {
770         REQUIRE(DNS_RDATASET_VALID(rdataset));
771         REQUIRE(rdataset->methods != NULL);
772
773         if (rdataset->methods->expire != NULL)
774                 (rdataset->methods->expire)(rdataset);
775 }
776
777 void
778 dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
779                      dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
780                      isc_boolean_t acceptexpired)
781 {
782         isc_uint32_t ttl = 0;
783
784         REQUIRE(DNS_RDATASET_VALID(rdataset));
785         REQUIRE(DNS_RDATASET_VALID(sigrdataset));
786         REQUIRE(rrsig != NULL);
787
788         /*
789          * If we accept expired RRsets keep them for no more than 120 seconds.
790          */
791         if (acceptexpired &&
792             (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) ||
793              isc_serial_le(rrsig->timeexpire, now)))
794                 ttl = 120;
795         else if (isc_serial_ge(rrsig->timeexpire, now))
796                 ttl = rrsig->timeexpire - now;
797
798         ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl),
799                       ISC_MIN(rrsig->originalttl, ttl));
800         rdataset->ttl = ttl;
801         sigrdataset->ttl = ttl;
802 }