]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/rdataset.c
Upgrade to 9.6-ESV-R4-P1, which address the following issues:
[FreeBSD/stable/8.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.4.6.1 2011-05-27 00:19:19 each 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 static const char *trustnames[] = {
38         "none",
39         "pending-additional",
40         "pending-answer",
41         "additional",
42         "glue",
43         "answer",
44         "authauthority",
45         "authanswer",
46         "secure",
47         "local" /* aka ultimate */
48 };
49
50 const char *
51 dns_trust_totext(dns_trust_t trust) {
52         if (trust >= sizeof(trustnames)/sizeof(*trustnames))
53                 return ("bad");
54         return (trustnames[trust]);
55 }
56
57 void
58 dns_rdataset_init(dns_rdataset_t *rdataset) {
59
60         /*
61          * Make 'rdataset' a valid, disassociated rdataset.
62          */
63
64         REQUIRE(rdataset != NULL);
65
66         rdataset->magic = DNS_RDATASET_MAGIC;
67         rdataset->methods = NULL;
68         ISC_LINK_INIT(rdataset, link);
69         rdataset->rdclass = 0;
70         rdataset->type = 0;
71         rdataset->ttl = 0;
72         rdataset->trust = 0;
73         rdataset->covers = 0;
74         rdataset->attributes = 0;
75         rdataset->count = ISC_UINT32_MAX;
76         rdataset->private1 = NULL;
77         rdataset->private2 = NULL;
78         rdataset->private3 = NULL;
79         rdataset->privateuint4 = 0;
80         rdataset->private5 = NULL;
81         rdataset->private6 = NULL;
82         rdataset->resign = 0;
83 }
84
85 void
86 dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
87
88         /*
89          * Invalidate 'rdataset'.
90          */
91
92         REQUIRE(DNS_RDATASET_VALID(rdataset));
93         REQUIRE(rdataset->methods == NULL);
94
95         rdataset->magic = 0;
96         ISC_LINK_INIT(rdataset, link);
97         rdataset->rdclass = 0;
98         rdataset->type = 0;
99         rdataset->ttl = 0;
100         rdataset->trust = 0;
101         rdataset->covers = 0;
102         rdataset->attributes = 0;
103         rdataset->count = ISC_UINT32_MAX;
104         rdataset->private1 = NULL;
105         rdataset->private2 = NULL;
106         rdataset->private3 = NULL;
107         rdataset->privateuint4 = 0;
108         rdataset->private5 = NULL;
109 }
110
111 void
112 dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
113
114         /*
115          * Disassociate 'rdataset' from its rdata, allowing it to be reused.
116          */
117
118         REQUIRE(DNS_RDATASET_VALID(rdataset));
119         REQUIRE(rdataset->methods != NULL);
120
121         (rdataset->methods->disassociate)(rdataset);
122         rdataset->methods = NULL;
123         ISC_LINK_INIT(rdataset, link);
124         rdataset->rdclass = 0;
125         rdataset->type = 0;
126         rdataset->ttl = 0;
127         rdataset->trust = 0;
128         rdataset->covers = 0;
129         rdataset->attributes = 0;
130         rdataset->count = ISC_UINT32_MAX;
131         rdataset->private1 = NULL;
132         rdataset->private2 = NULL;
133         rdataset->private3 = NULL;
134         rdataset->privateuint4 = 0;
135         rdataset->private5 = NULL;
136         rdataset->private6 = NULL;
137 }
138
139 isc_boolean_t
140 dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
141         /*
142          * Is 'rdataset' associated?
143          */
144
145         REQUIRE(DNS_RDATASET_VALID(rdataset));
146
147         if (rdataset->methods != NULL)
148                 return (ISC_TRUE);
149
150         return (ISC_FALSE);
151 }
152
153 static void
154 question_disassociate(dns_rdataset_t *rdataset) {
155         UNUSED(rdataset);
156 }
157
158 static isc_result_t
159 question_cursor(dns_rdataset_t *rdataset) {
160         UNUSED(rdataset);
161
162         return (ISC_R_NOMORE);
163 }
164
165 static void
166 question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
167         /*
168          * This routine should never be called.
169          */
170         UNUSED(rdataset);
171         UNUSED(rdata);
172
173         REQUIRE(0);
174 }
175
176 static void
177 question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
178         *target = *source;
179 }
180
181 static unsigned int
182 question_count(dns_rdataset_t *rdataset) {
183         /*
184          * This routine should never be called.
185          */
186         UNUSED(rdataset);
187         REQUIRE(0);
188
189         return (0);
190 }
191
192 static dns_rdatasetmethods_t question_methods = {
193         question_disassociate,
194         question_cursor,
195         question_cursor,
196         question_current,
197         question_clone,
198         question_count,
199         NULL,
200         NULL,
201         NULL,
202         NULL,
203         NULL,
204         NULL,
205         NULL,
206         NULL,
207         NULL
208 };
209
210 void
211 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
212                           dns_rdatatype_t type)
213 {
214
215         /*
216          * Make 'rdataset' a valid, associated, question rdataset, with a
217          * question class of 'rdclass' and type 'type'.
218          */
219
220         REQUIRE(DNS_RDATASET_VALID(rdataset));
221         REQUIRE(rdataset->methods == NULL);
222
223         rdataset->methods = &question_methods;
224         rdataset->rdclass = rdclass;
225         rdataset->type = type;
226         rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
227 }
228
229 unsigned int
230 dns_rdataset_count(dns_rdataset_t *rdataset) {
231
232         /*
233          * Return the number of records in 'rdataset'.
234          */
235
236         REQUIRE(DNS_RDATASET_VALID(rdataset));
237         REQUIRE(rdataset->methods != NULL);
238
239         return ((rdataset->methods->count)(rdataset));
240 }
241
242 void
243 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
244
245         /*
246          * Make 'target' refer to the same rdataset as 'source'.
247          */
248
249         REQUIRE(DNS_RDATASET_VALID(source));
250         REQUIRE(source->methods != NULL);
251         REQUIRE(DNS_RDATASET_VALID(target));
252         REQUIRE(target->methods == NULL);
253
254         (source->methods->clone)(source, target);
255 }
256
257 isc_result_t
258 dns_rdataset_first(dns_rdataset_t *rdataset) {
259
260         /*
261          * Move the rdata cursor to the first rdata in the rdataset (if any).
262          */
263
264         REQUIRE(DNS_RDATASET_VALID(rdataset));
265         REQUIRE(rdataset->methods != NULL);
266
267         return ((rdataset->methods->first)(rdataset));
268 }
269
270 isc_result_t
271 dns_rdataset_next(dns_rdataset_t *rdataset) {
272
273         /*
274          * Move the rdata cursor to the next rdata in the rdataset (if any).
275          */
276
277         REQUIRE(DNS_RDATASET_VALID(rdataset));
278         REQUIRE(rdataset->methods != NULL);
279
280         return ((rdataset->methods->next)(rdataset));
281 }
282
283 void
284 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
285
286         /*
287          * Make 'rdata' refer to the current rdata.
288          */
289
290         REQUIRE(DNS_RDATASET_VALID(rdataset));
291         REQUIRE(rdataset->methods != NULL);
292
293         (rdataset->methods->current)(rdataset, rdata);
294 }
295
296 #define MAX_SHUFFLE     32
297 #define WANT_FIXED(r)   (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
298 #define WANT_RANDOM(r)  (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
299
300 struct towire_sort {
301         int key;
302         dns_rdata_t *rdata;
303 };
304
305 static int
306 towire_compare(const void *av, const void *bv) {
307         const struct towire_sort *a = (const struct towire_sort *) av;
308         const struct towire_sort *b = (const struct towire_sort *) bv;
309         return (a->key - b->key);
310 }
311
312 static isc_result_t
313 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
314              dns_compress_t *cctx, isc_buffer_t *target,
315              dns_rdatasetorderfunc_t order, const void *order_arg,
316              isc_boolean_t partial, unsigned int options,
317              unsigned int *countp, void **state)
318 {
319         dns_rdata_t rdata = DNS_RDATA_INIT;
320         isc_region_t r;
321         isc_result_t result;
322         unsigned int i, count, added, choice;
323         isc_buffer_t savedbuffer, rdlen, rrbuffer;
324         unsigned int headlen;
325         isc_boolean_t question = ISC_FALSE;
326         isc_boolean_t shuffle = ISC_FALSE;
327         dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
328         struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
329
330         UNUSED(state);
331
332         /*
333          * Convert 'rdataset' to wire format, compressing names as specified
334          * in cctx, and storing the result in 'target'.
335          */
336
337         REQUIRE(DNS_RDATASET_VALID(rdataset));
338         REQUIRE(countp != NULL);
339         REQUIRE((order == NULL) == (order_arg == NULL));
340         REQUIRE(cctx != NULL && cctx->mctx != NULL);
341
342         count = 0;
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->type == 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[j].key = (*order)(&shuffled[i],
447                                                                  order_arg);
448                                 else
449                                         sorted[j].key = 0; /* Unused */
450                                 sorted[j].rdata = &shuffled[i];
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 }