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