Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / rdataset.c
1 /*
2  * Copyright (C) 2004-2007, 2009  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 2009/01/19 23:47:02 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 };
184
185 void
186 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
187                           dns_rdatatype_t type)
188 {
189
190         /*
191          * Make 'rdataset' a valid, associated, question rdataset, with a
192          * question class of 'rdclass' and type 'type'.
193          */
194
195         REQUIRE(DNS_RDATASET_VALID(rdataset));
196         REQUIRE(rdataset->methods == NULL);
197
198         rdataset->methods = &question_methods;
199         rdataset->rdclass = rdclass;
200         rdataset->type = type;
201         rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
202 }
203
204 unsigned int
205 dns_rdataset_count(dns_rdataset_t *rdataset) {
206
207         /*
208          * Return the number of records in 'rdataset'.
209          */
210
211         REQUIRE(DNS_RDATASET_VALID(rdataset));
212         REQUIRE(rdataset->methods != NULL);
213
214         return ((rdataset->methods->count)(rdataset));
215 }
216
217 void
218 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
219
220         /*
221          * Make 'target' refer to the same rdataset as 'source'.
222          */
223
224         REQUIRE(DNS_RDATASET_VALID(source));
225         REQUIRE(source->methods != NULL);
226         REQUIRE(DNS_RDATASET_VALID(target));
227         REQUIRE(target->methods == NULL);
228
229         (source->methods->clone)(source, target);
230 }
231
232 isc_result_t
233 dns_rdataset_first(dns_rdataset_t *rdataset) {
234
235         /*
236          * Move the rdata cursor to the first rdata in the rdataset (if any).
237          */
238
239         REQUIRE(DNS_RDATASET_VALID(rdataset));
240         REQUIRE(rdataset->methods != NULL);
241
242         return ((rdataset->methods->first)(rdataset));
243 }
244
245 isc_result_t
246 dns_rdataset_next(dns_rdataset_t *rdataset) {
247
248         /*
249          * Move the rdata cursor to the next rdata in the rdataset (if any).
250          */
251
252         REQUIRE(DNS_RDATASET_VALID(rdataset));
253         REQUIRE(rdataset->methods != NULL);
254
255         return ((rdataset->methods->next)(rdataset));
256 }
257
258 void
259 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
260
261         /*
262          * Make 'rdata' refer to the current rdata.
263          */
264
265         REQUIRE(DNS_RDATASET_VALID(rdataset));
266         REQUIRE(rdataset->methods != NULL);
267
268         (rdataset->methods->current)(rdataset, rdata);
269 }
270
271 #define MAX_SHUFFLE     32
272 #define WANT_FIXED(r)   (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
273 #define WANT_RANDOM(r)  (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
274
275 struct towire_sort {
276         int key;
277         dns_rdata_t *rdata;
278 };
279
280 static int
281 towire_compare(const void *av, const void *bv) {
282         const struct towire_sort *a = (const struct towire_sort *) av;
283         const struct towire_sort *b = (const struct towire_sort *) bv;
284         return (a->key - b->key);
285 }
286
287 static isc_result_t
288 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
289              dns_compress_t *cctx, isc_buffer_t *target,
290              dns_rdatasetorderfunc_t order, const void *order_arg,
291              isc_boolean_t partial, unsigned int options,
292              unsigned int *countp, void **state)
293 {
294         dns_rdata_t rdata = DNS_RDATA_INIT;
295         isc_region_t r;
296         isc_result_t result;
297         unsigned int i, count, added, choice;
298         isc_buffer_t savedbuffer, rdlen, rrbuffer;
299         unsigned int headlen;
300         isc_boolean_t question = ISC_FALSE;
301         isc_boolean_t shuffle = ISC_FALSE;
302         dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
303         struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
304
305         UNUSED(state);
306
307         /*
308          * Convert 'rdataset' to wire format, compressing names as specified
309          * in cctx, and storing the result in 'target'.
310          */
311
312         REQUIRE(DNS_RDATASET_VALID(rdataset));
313         REQUIRE(countp != NULL);
314         REQUIRE((order == NULL) == (order_arg == NULL));
315         REQUIRE(cctx != NULL && cctx->mctx != NULL);
316
317         count = 0;
318         if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
319                 question = ISC_TRUE;
320                 count = 1;
321                 result = dns_rdataset_first(rdataset);
322                 INSIST(result == ISC_R_NOMORE);
323         } else if (rdataset->type == 0) {
324                 /*
325                  * This is a negative caching rdataset.
326                  */
327                 unsigned int ncache_opts = 0;
328                 if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
329                         ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
330                 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
331                                           countp));
332         } else {
333                 count = (rdataset->methods->count)(rdataset);
334                 result = dns_rdataset_first(rdataset);
335                 if (result == ISC_R_NOMORE)
336                         return (ISC_R_SUCCESS);
337                 if (result != ISC_R_SUCCESS)
338                         return (result);
339         }
340
341         /*
342          * Do we want to shuffle this answer?
343          */
344         if (!question && count > 1 &&
345             (!WANT_FIXED(rdataset) || order != NULL) &&
346             rdataset->type != dns_rdatatype_rrsig)
347                 shuffle = ISC_TRUE;
348
349         if (shuffle && count > MAX_SHUFFLE) {
350                 shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
351                 sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
352                 if (shuffled == NULL || sorted == NULL)
353                         shuffle = ISC_FALSE;
354         } else {
355                 shuffled = shuffled_fixed;
356                 sorted = sorted_fixed;
357         }
358
359         if (shuffle) {
360                 /*
361                  * First we get handles to all of the rdata.
362                  */
363                 i = 0;
364                 do {
365                         INSIST(i < count);
366                         dns_rdata_init(&shuffled[i]);
367                         dns_rdataset_current(rdataset, &shuffled[i]);
368                         i++;
369                         result = dns_rdataset_next(rdataset);
370                 } while (result == ISC_R_SUCCESS);
371                 if (result != ISC_R_NOMORE)
372                         goto cleanup;
373                 INSIST(i == count);
374
375                 /*
376                  * Now we shuffle.
377                  */
378                 if (WANT_FIXED(rdataset)) {
379                         /*
380                          * 'Fixed' order.
381                          */
382                         INSIST(order != NULL);
383                         for (i = 0; i < count; i++) {
384                                 sorted[i].key = (*order)(&shuffled[i],
385                                                          order_arg);
386                                 sorted[i].rdata = &shuffled[i];
387                         }
388                 } else if (WANT_RANDOM(rdataset)) {
389                         /*
390                          * 'Random' order.
391                          */
392                         for (i = 0; i < count; i++) {
393                                 dns_rdata_t rdata;
394                                 isc_uint32_t val;
395
396                                 isc_random_get(&val);
397                                 choice = i + (val % (count - i));
398                                 rdata = shuffled[i];
399                                 shuffled[i] = shuffled[choice];
400                                 shuffled[choice] = rdata;
401                                 if (order != NULL)
402                                         sorted[i].key = (*order)(&shuffled[i],
403                                                                  order_arg);
404                                 else
405                                         sorted[i].key = 0; /* Unused */
406                                 sorted[i].rdata = &shuffled[i];
407                         }
408                 } else {
409                         /*
410                          * "Cyclic" order.
411                          */
412                         isc_uint32_t val;
413                         unsigned int j;
414
415                         val = rdataset->count;
416                         if (val == ISC_UINT32_MAX)
417                                 isc_random_get(&val);
418                         j = val % count;
419                         for (i = 0; i < count; i++) {
420                                 if (order != NULL)
421                                         sorted[j].key = (*order)(&shuffled[i],
422                                                                  order_arg);
423                                 else
424                                         sorted[j].key = 0; /* Unused */
425                                 sorted[j].rdata = &shuffled[i];
426                                 j++;
427                                 if (j == count)
428                                         j = 0; /* Wrap around. */
429                         }
430                 }
431
432                 /*
433                  * Sorted order.
434                  */
435                 if (order != NULL)
436                         qsort(sorted, count, sizeof(sorted[0]),
437                               towire_compare);
438         }
439
440         savedbuffer = *target;
441         i = 0;
442         added = 0;
443
444         do {
445                 /*
446                  * Copy out the name, type, class, ttl.
447                  */
448
449                 rrbuffer = *target;
450                 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
451                 result = dns_name_towire(owner_name, cctx, target);
452                 if (result != ISC_R_SUCCESS)
453                         goto rollback;
454                 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
455                 if (!question)
456                         headlen += sizeof(dns_ttl_t)
457                                 + 2;  /* XXX 2 for rdata len */
458                 isc_buffer_availableregion(target, &r);
459                 if (r.length < headlen) {
460                         result = ISC_R_NOSPACE;
461                         goto rollback;
462                 }
463                 isc_buffer_putuint16(target, rdataset->type);
464                 isc_buffer_putuint16(target, rdataset->rdclass);
465                 if (!question) {
466                         isc_buffer_putuint32(target, rdataset->ttl);
467
468                         /*
469                          * Save space for rdlen.
470                          */
471                         rdlen = *target;
472                         isc_buffer_add(target, 2);
473
474                         /*
475                          * Copy out the rdata
476                          */
477                         if (shuffle)
478                                 rdata = *(sorted[i].rdata);
479                         else {
480                                 dns_rdata_reset(&rdata);
481                                 dns_rdataset_current(rdataset, &rdata);
482                         }
483                         result = dns_rdata_towire(&rdata, cctx, target);
484                         if (result != ISC_R_SUCCESS)
485                                 goto rollback;
486                         INSIST((target->used >= rdlen.used + 2) &&
487                                (target->used - rdlen.used - 2 < 65536));
488                         isc_buffer_putuint16(&rdlen,
489                                              (isc_uint16_t)(target->used -
490                                                             rdlen.used - 2));
491                         added++;
492                 }
493
494                 if (shuffle) {
495                         i++;
496                         if (i == count)
497                                 result = ISC_R_NOMORE;
498                         else
499                                 result = ISC_R_SUCCESS;
500                 } else {
501                         result = dns_rdataset_next(rdataset);
502                 }
503         } while (result == ISC_R_SUCCESS);
504
505         if (result != ISC_R_NOMORE)
506                 goto rollback;
507
508         *countp += count;
509
510         result = ISC_R_SUCCESS;
511         goto cleanup;
512
513  rollback:
514         if (partial && result == ISC_R_NOSPACE) {
515                 INSIST(rrbuffer.used < 65536);
516                 dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
517                 *countp += added;
518                 *target = rrbuffer;
519                 goto cleanup;
520         }
521         INSIST(savedbuffer.used < 65536);
522         dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
523         *countp = 0;
524         *target = savedbuffer;
525
526  cleanup:
527         if (sorted != NULL && sorted != sorted_fixed)
528                 isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
529         if (shuffled != NULL && shuffled != shuffled_fixed)
530                 isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
531         return (result);
532 }
533
534 isc_result_t
535 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
536                           const dns_name_t *owner_name,
537                           dns_compress_t *cctx,
538                           isc_buffer_t *target,
539                           dns_rdatasetorderfunc_t order,
540                           const void *order_arg,
541                           unsigned int options,
542                           unsigned int *countp)
543 {
544         return (towiresorted(rdataset, owner_name, cctx, target,
545                              order, order_arg, ISC_FALSE, options,
546                              countp, NULL));
547 }
548
549 isc_result_t
550 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
551                            const dns_name_t *owner_name,
552                            dns_compress_t *cctx,
553                            isc_buffer_t *target,
554                            dns_rdatasetorderfunc_t order,
555                            const void *order_arg,
556                            unsigned int options,
557                            unsigned int *countp,
558                            void **state)
559 {
560         REQUIRE(state == NULL); /* XXX remove when implemented */
561         return (towiresorted(rdataset, owner_name, cctx, target,
562                              order, order_arg, ISC_TRUE, options,
563                              countp, state));
564 }
565
566 isc_result_t
567 dns_rdataset_towire(dns_rdataset_t *rdataset,
568                     dns_name_t *owner_name,
569                     dns_compress_t *cctx,
570                     isc_buffer_t *target,
571                     unsigned int options,
572                     unsigned int *countp)
573 {
574         return (towiresorted(rdataset, owner_name, cctx, target,
575                              NULL, NULL, ISC_FALSE, options, countp, NULL));
576 }
577
578 isc_result_t
579 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
580                             dns_additionaldatafunc_t add, void *arg)
581 {
582         dns_rdata_t rdata = DNS_RDATA_INIT;
583         isc_result_t result;
584
585         /*
586          * For each rdata in rdataset, call 'add' for each name and type in the
587          * rdata which is subject to additional section processing.
588          */
589
590         REQUIRE(DNS_RDATASET_VALID(rdataset));
591         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
592
593         result = dns_rdataset_first(rdataset);
594         if (result != ISC_R_SUCCESS)
595                 return (result);
596
597         do {
598                 dns_rdataset_current(rdataset, &rdata);
599                 result = dns_rdata_additionaldata(&rdata, add, arg);
600                 if (result == ISC_R_SUCCESS)
601                         result = dns_rdataset_next(rdataset);
602                 dns_rdata_reset(&rdata);
603         } while (result == ISC_R_SUCCESS);
604
605         if (result != ISC_R_NOMORE)
606                 return (result);
607
608         return (ISC_R_SUCCESS);
609 }
610
611 isc_result_t
612 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
613
614         REQUIRE(DNS_RDATASET_VALID(rdataset));
615         REQUIRE(rdataset->methods != NULL);
616         if (rdataset->methods->addnoqname == NULL)
617                 return (ISC_R_NOTIMPLEMENTED);
618         return((rdataset->methods->addnoqname)(rdataset, name));
619 }
620
621 isc_result_t
622 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
623                         dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
624 {
625         REQUIRE(DNS_RDATASET_VALID(rdataset));
626         REQUIRE(rdataset->methods != NULL);
627
628         if (rdataset->methods->getnoqname == NULL)
629                 return (ISC_R_NOTIMPLEMENTED);
630         return((rdataset->methods->getnoqname)(rdataset, name, nsec, nsecsig));
631 }
632
633 /*
634  * Additional cache stuff
635  */
636 isc_result_t
637 dns_rdataset_getadditional(dns_rdataset_t *rdataset,
638                            dns_rdatasetadditional_t type,
639                            dns_rdatatype_t qtype,
640                            dns_acache_t *acache,
641                            dns_zone_t **zonep,
642                            dns_db_t **dbp,
643                            dns_dbversion_t **versionp,
644                            dns_dbnode_t **nodep,
645                            dns_name_t *fname,
646                            dns_message_t *msg,
647                            isc_stdtime_t now)
648 {
649         REQUIRE(DNS_RDATASET_VALID(rdataset));
650         REQUIRE(rdataset->methods != NULL);
651         REQUIRE(zonep == NULL || *zonep == NULL);
652         REQUIRE(dbp != NULL && *dbp == NULL);
653         REQUIRE(versionp != NULL && *versionp == NULL);
654         REQUIRE(nodep != NULL && *nodep == NULL);
655         REQUIRE(fname != NULL);
656         REQUIRE(msg != NULL);
657
658         if (acache != NULL && rdataset->methods->getadditional != NULL) {
659                 return ((rdataset->methods->getadditional)(rdataset, type,
660                                                            qtype, acache,
661                                                            zonep, dbp,
662                                                            versionp, nodep,
663                                                            fname, msg, now));
664         }
665
666         return (ISC_R_FAILURE);
667 }
668
669 isc_result_t
670 dns_rdataset_setadditional(dns_rdataset_t *rdataset,
671                            dns_rdatasetadditional_t type,
672                            dns_rdatatype_t qtype,
673                            dns_acache_t *acache,
674                            dns_zone_t *zone,
675                            dns_db_t *db,
676                            dns_dbversion_t *version,
677                            dns_dbnode_t *node,
678                            dns_name_t *fname)
679 {
680         REQUIRE(DNS_RDATASET_VALID(rdataset));
681         REQUIRE(rdataset->methods != NULL);
682
683         if (acache != NULL && rdataset->methods->setadditional != NULL) {
684                 return ((rdataset->methods->setadditional)(rdataset, type,
685                                                            qtype, acache, zone,
686                                                            db, version,
687                                                            node, fname));
688         }
689
690         return (ISC_R_FAILURE);
691 }
692
693 isc_result_t
694 dns_rdataset_putadditional(dns_acache_t *acache,
695                            dns_rdataset_t *rdataset,
696                            dns_rdatasetadditional_t type,
697                            dns_rdatatype_t qtype)
698 {
699         REQUIRE(DNS_RDATASET_VALID(rdataset));
700         REQUIRE(rdataset->methods != NULL);
701
702         if (acache != NULL && rdataset->methods->putadditional != NULL) {
703                 return ((rdataset->methods->putadditional)(acache, rdataset,
704                                                            type, qtype));
705         }
706
707         return (ISC_R_FAILURE);
708 }
709