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