]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/bind9/lib/dns/rdataset.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / bind9 / lib / dns / rdataset.c
1 /*
2  * Copyright (C) 2004-2011  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.86.148.4 2011-06-08 23:02:42 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 = 0, 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         if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
343                 question = ISC_TRUE;
344                 count = 1;
345                 result = dns_rdataset_first(rdataset);
346                 INSIST(result == ISC_R_NOMORE);
347         } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
348                 /*
349                  * This is a negative caching rdataset.
350                  */
351                 unsigned int ncache_opts = 0;
352                 if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
353                         ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
354                 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
355                                           countp));
356         } else {
357                 count = (rdataset->methods->count)(rdataset);
358                 result = dns_rdataset_first(rdataset);
359                 if (result == ISC_R_NOMORE)
360                         return (ISC_R_SUCCESS);
361                 if (result != ISC_R_SUCCESS)
362                         return (result);
363         }
364
365         /*
366          * Do we want to shuffle this answer?
367          */
368         if (!question && count > 1 &&
369             (!WANT_FIXED(rdataset) || order != NULL) &&
370             rdataset->type != dns_rdatatype_rrsig)
371                 shuffle = ISC_TRUE;
372
373         if (shuffle && count > MAX_SHUFFLE) {
374                 shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
375                 sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
376                 if (shuffled == NULL || sorted == NULL)
377                         shuffle = ISC_FALSE;
378         } else {
379                 shuffled = shuffled_fixed;
380                 sorted = sorted_fixed;
381         }
382
383         if (shuffle) {
384                 /*
385                  * First we get handles to all of the rdata.
386                  */
387                 i = 0;
388                 do {
389                         INSIST(i < count);
390                         dns_rdata_init(&shuffled[i]);
391                         dns_rdataset_current(rdataset, &shuffled[i]);
392                         i++;
393                         result = dns_rdataset_next(rdataset);
394                 } while (result == ISC_R_SUCCESS);
395                 if (result != ISC_R_NOMORE)
396                         goto cleanup;
397                 INSIST(i == count);
398
399                 /*
400                  * Now we shuffle.
401                  */
402                 if (WANT_FIXED(rdataset)) {
403                         /*
404                          * 'Fixed' order.
405                          */
406                         INSIST(order != NULL);
407                         for (i = 0; i < count; i++) {
408                                 sorted[i].key = (*order)(&shuffled[i],
409                                                          order_arg);
410                                 sorted[i].rdata = &shuffled[i];
411                         }
412                 } else if (WANT_RANDOM(rdataset)) {
413                         /*
414                          * 'Random' order.
415                          */
416                         for (i = 0; i < count; i++) {
417                                 dns_rdata_t rdata;
418                                 isc_uint32_t val;
419
420                                 isc_random_get(&val);
421                                 choice = i + (val % (count - i));
422                                 rdata = shuffled[i];
423                                 shuffled[i] = shuffled[choice];
424                                 shuffled[choice] = rdata;
425                                 if (order != NULL)
426                                         sorted[i].key = (*order)(&shuffled[i],
427                                                                  order_arg);
428                                 else
429                                         sorted[i].key = 0; /* Unused */
430                                 sorted[i].rdata = &shuffled[i];
431                         }
432                 } else {
433                         /*
434                          * "Cyclic" order.
435                          */
436                         isc_uint32_t val;
437                         unsigned int j;
438
439                         val = rdataset->count;
440                         if (val == ISC_UINT32_MAX)
441                                 isc_random_get(&val);
442                         j = val % count;
443                         for (i = 0; i < count; i++) {
444                                 if (order != NULL)
445                                         sorted[j].key = (*order)(&shuffled[i],
446                                                                  order_arg);
447                                 else
448                                         sorted[j].key = 0; /* Unused */
449                                 sorted[j].rdata = &shuffled[i];
450                                 j++;
451                                 if (j == count)
452                                         j = 0; /* Wrap around. */
453                         }
454                 }
455
456                 /*
457                  * Sorted order.
458                  */
459                 if (order != NULL)
460                         qsort(sorted, count, sizeof(sorted[0]),
461                               towire_compare);
462         }
463
464         savedbuffer = *target;
465         i = 0;
466         added = 0;
467
468         do {
469                 /*
470                  * Copy out the name, type, class, ttl.
471                  */
472
473                 rrbuffer = *target;
474                 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
475                 result = dns_name_towire(owner_name, cctx, target);
476                 if (result != ISC_R_SUCCESS)
477                         goto rollback;
478                 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
479                 if (!question)
480                         headlen += sizeof(dns_ttl_t)
481                                 + 2;  /* XXX 2 for rdata len */
482                 isc_buffer_availableregion(target, &r);
483                 if (r.length < headlen) {
484                         result = ISC_R_NOSPACE;
485                         goto rollback;
486                 }
487                 isc_buffer_putuint16(target, rdataset->type);
488                 isc_buffer_putuint16(target, rdataset->rdclass);
489                 if (!question) {
490                         isc_buffer_putuint32(target, rdataset->ttl);
491
492                         /*
493                          * Save space for rdlen.
494                          */
495                         rdlen = *target;
496                         isc_buffer_add(target, 2);
497
498                         /*
499                          * Copy out the rdata
500                          */
501                         if (shuffle)
502                                 rdata = *(sorted[i].rdata);
503                         else {
504                                 dns_rdata_reset(&rdata);
505                                 dns_rdataset_current(rdataset, &rdata);
506                         }
507                         result = dns_rdata_towire(&rdata, cctx, target);
508                         if (result != ISC_R_SUCCESS)
509                                 goto rollback;
510                         INSIST((target->used >= rdlen.used + 2) &&
511                                (target->used - rdlen.used - 2 < 65536));
512                         isc_buffer_putuint16(&rdlen,
513                                              (isc_uint16_t)(target->used -
514                                                             rdlen.used - 2));
515                         added++;
516                 }
517
518                 if (shuffle) {
519                         i++;
520                         if (i == count)
521                                 result = ISC_R_NOMORE;
522                         else
523                                 result = ISC_R_SUCCESS;
524                 } else {
525                         result = dns_rdataset_next(rdataset);
526                 }
527         } while (result == ISC_R_SUCCESS);
528
529         if (result != ISC_R_NOMORE)
530                 goto rollback;
531
532         *countp += count;
533
534         result = ISC_R_SUCCESS;
535         goto cleanup;
536
537  rollback:
538         if (partial && result == ISC_R_NOSPACE) {
539                 INSIST(rrbuffer.used < 65536);
540                 dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
541                 *countp += added;
542                 *target = rrbuffer;
543                 goto cleanup;
544         }
545         INSIST(savedbuffer.used < 65536);
546         dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
547         *countp = 0;
548         *target = savedbuffer;
549
550  cleanup:
551         if (sorted != NULL && sorted != sorted_fixed)
552                 isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
553         if (shuffled != NULL && shuffled != shuffled_fixed)
554                 isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
555         return (result);
556 }
557
558 isc_result_t
559 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
560                           const dns_name_t *owner_name,
561                           dns_compress_t *cctx,
562                           isc_buffer_t *target,
563                           dns_rdatasetorderfunc_t order,
564                           const void *order_arg,
565                           unsigned int options,
566                           unsigned int *countp)
567 {
568         return (towiresorted(rdataset, owner_name, cctx, target,
569                              order, order_arg, ISC_FALSE, options,
570                              countp, NULL));
571 }
572
573 isc_result_t
574 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
575                            const dns_name_t *owner_name,
576                            dns_compress_t *cctx,
577                            isc_buffer_t *target,
578                            dns_rdatasetorderfunc_t order,
579                            const void *order_arg,
580                            unsigned int options,
581                            unsigned int *countp,
582                            void **state)
583 {
584         REQUIRE(state == NULL); /* XXX remove when implemented */
585         return (towiresorted(rdataset, owner_name, cctx, target,
586                              order, order_arg, ISC_TRUE, options,
587                              countp, state));
588 }
589
590 isc_result_t
591 dns_rdataset_towire(dns_rdataset_t *rdataset,
592                     dns_name_t *owner_name,
593                     dns_compress_t *cctx,
594                     isc_buffer_t *target,
595                     unsigned int options,
596                     unsigned int *countp)
597 {
598         return (towiresorted(rdataset, owner_name, cctx, target,
599                              NULL, NULL, ISC_FALSE, options, countp, NULL));
600 }
601
602 isc_result_t
603 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
604                             dns_additionaldatafunc_t add, void *arg)
605 {
606         dns_rdata_t rdata = DNS_RDATA_INIT;
607         isc_result_t result;
608
609         /*
610          * For each rdata in rdataset, call 'add' for each name and type in the
611          * rdata which is subject to additional section processing.
612          */
613
614         REQUIRE(DNS_RDATASET_VALID(rdataset));
615         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
616
617         result = dns_rdataset_first(rdataset);
618         if (result != ISC_R_SUCCESS)
619                 return (result);
620
621         do {
622                 dns_rdataset_current(rdataset, &rdata);
623                 result = dns_rdata_additionaldata(&rdata, add, arg);
624                 if (result == ISC_R_SUCCESS)
625                         result = dns_rdataset_next(rdataset);
626                 dns_rdata_reset(&rdata);
627         } while (result == ISC_R_SUCCESS);
628
629         if (result != ISC_R_NOMORE)
630                 return (result);
631
632         return (ISC_R_SUCCESS);
633 }
634
635 isc_result_t
636 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
637
638         REQUIRE(DNS_RDATASET_VALID(rdataset));
639         REQUIRE(rdataset->methods != NULL);
640         if (rdataset->methods->addnoqname == NULL)
641                 return (ISC_R_NOTIMPLEMENTED);
642         return((rdataset->methods->addnoqname)(rdataset, name));
643 }
644
645 isc_result_t
646 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
647                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
648 {
649         REQUIRE(DNS_RDATASET_VALID(rdataset));
650         REQUIRE(rdataset->methods != NULL);
651
652         if (rdataset->methods->getnoqname == NULL)
653                 return (ISC_R_NOTIMPLEMENTED);
654         return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
655 }
656
657 isc_result_t
658 dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
659
660         REQUIRE(DNS_RDATASET_VALID(rdataset));
661         REQUIRE(rdataset->methods != NULL);
662         if (rdataset->methods->addclosest == NULL)
663                 return (ISC_R_NOTIMPLEMENTED);
664         return((rdataset->methods->addclosest)(rdataset, name));
665 }
666
667 isc_result_t
668 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
669                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
670 {
671         REQUIRE(DNS_RDATASET_VALID(rdataset));
672         REQUIRE(rdataset->methods != NULL);
673
674         if (rdataset->methods->getclosest == NULL)
675                 return (ISC_R_NOTIMPLEMENTED);
676         return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
677 }
678
679 /*
680  * Additional cache stuff
681  */
682 isc_result_t
683 dns_rdataset_getadditional(dns_rdataset_t *rdataset,
684                            dns_rdatasetadditional_t type,
685                            dns_rdatatype_t qtype,
686                            dns_acache_t *acache,
687                            dns_zone_t **zonep,
688                            dns_db_t **dbp,
689                            dns_dbversion_t **versionp,
690                            dns_dbnode_t **nodep,
691                            dns_name_t *fname,
692                            dns_message_t *msg,
693                            isc_stdtime_t now)
694 {
695         REQUIRE(DNS_RDATASET_VALID(rdataset));
696         REQUIRE(rdataset->methods != NULL);
697         REQUIRE(zonep == NULL || *zonep == NULL);
698         REQUIRE(dbp != NULL && *dbp == NULL);
699         REQUIRE(versionp != NULL && *versionp == NULL);
700         REQUIRE(nodep != NULL && *nodep == NULL);
701         REQUIRE(fname != NULL);
702         REQUIRE(msg != NULL);
703
704         if (acache != NULL && rdataset->methods->getadditional != NULL) {
705                 return ((rdataset->methods->getadditional)(rdataset, type,
706                                                            qtype, acache,
707                                                            zonep, dbp,
708                                                            versionp, nodep,
709                                                            fname, msg, now));
710         }
711
712         return (ISC_R_FAILURE);
713 }
714
715 isc_result_t
716 dns_rdataset_setadditional(dns_rdataset_t *rdataset,
717                            dns_rdatasetadditional_t type,
718                            dns_rdatatype_t qtype,
719                            dns_acache_t *acache,
720                            dns_zone_t *zone,
721                            dns_db_t *db,
722                            dns_dbversion_t *version,
723                            dns_dbnode_t *node,
724                            dns_name_t *fname)
725 {
726         REQUIRE(DNS_RDATASET_VALID(rdataset));
727         REQUIRE(rdataset->methods != NULL);
728
729         if (acache != NULL && rdataset->methods->setadditional != NULL) {
730                 return ((rdataset->methods->setadditional)(rdataset, type,
731                                                            qtype, acache, zone,
732                                                            db, version,
733                                                            node, fname));
734         }
735
736         return (ISC_R_FAILURE);
737 }
738
739 isc_result_t
740 dns_rdataset_putadditional(dns_acache_t *acache,
741                            dns_rdataset_t *rdataset,
742                            dns_rdatasetadditional_t type,
743                            dns_rdatatype_t qtype)
744 {
745         REQUIRE(DNS_RDATASET_VALID(rdataset));
746         REQUIRE(rdataset->methods != NULL);
747
748         if (acache != NULL && rdataset->methods->putadditional != NULL) {
749                 return ((rdataset->methods->putadditional)(acache, rdataset,
750                                                            type, qtype));
751         }
752
753         return (ISC_R_FAILURE);
754 }
755
756 void
757 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
758         REQUIRE(DNS_RDATASET_VALID(rdataset));
759         REQUIRE(rdataset->methods != NULL);
760
761         if (rdataset->methods->settrust != NULL)
762                 (rdataset->methods->settrust)(rdataset, trust);
763         else
764                 rdataset->trust = trust;
765 }
766
767 void
768 dns_rdataset_expire(dns_rdataset_t *rdataset) {
769         REQUIRE(DNS_RDATASET_VALID(rdataset));
770         REQUIRE(rdataset->methods != NULL);
771
772         if (rdataset->methods->expire != NULL)
773                 (rdataset->methods->expire)(rdataset);
774 }