rdataset.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id$ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <stdlib.h>
00025 
00026 #include <isc/buffer.h>
00027 #include <isc/mem.h>
00028 #include <isc/random.h>
00029 #include <isc/serial.h>
00030 #include <isc/util.h>
00031 
00032 #include <dns/compress.h>
00033 #include <dns/fixedname.h>
00034 #include <dns/name.h>
00035 #include <dns/ncache.h>
00036 #include <dns/rdata.h>
00037 #include <dns/rdataset.h>
00038 
00039 static const char *trustnames[] = {
00040         "none",
00041         "pending-additional",
00042         "pending-answer",
00043         "additional",
00044         "glue",
00045         "answer",
00046         "authauthority",
00047         "authanswer",
00048         "secure",
00049         "local" /* aka ultimate */
00050 };
00051 
00052 const char *
00053 dns_trust_totext(dns_trust_t trust) {
00054         if (trust >= sizeof(trustnames)/sizeof(*trustnames))
00055                 return ("bad");
00056         return (trustnames[trust]);
00057 }
00058 
00059 void
00060 dns_rdataset_init(dns_rdataset_t *rdataset) {
00061 
00062         /*
00063          * Make 'rdataset' a valid, disassociated rdataset.
00064          */
00065 
00066         REQUIRE(rdataset != NULL);
00067 
00068         rdataset->magic = DNS_RDATASET_MAGIC;
00069         rdataset->methods = NULL;
00070         ISC_LINK_INIT(rdataset, link);
00071         rdataset->rdclass = 0;
00072         rdataset->type = 0;
00073         rdataset->ttl = 0;
00074         rdataset->trust = 0;
00075         rdataset->covers = 0;
00076         rdataset->attributes = 0;
00077         rdataset->count = ISC_UINT32_MAX;
00078         rdataset->private1 = NULL;
00079         rdataset->private2 = NULL;
00080         rdataset->private3 = NULL;
00081         rdataset->privateuint4 = 0;
00082         rdataset->private5 = NULL;
00083         rdataset->private6 = NULL;
00084         rdataset->private7 = NULL;
00085         rdataset->resign = 0;
00086 }
00087 
00088 void
00089 dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
00090 
00091         /*
00092          * Invalidate 'rdataset'.
00093          */
00094 
00095         REQUIRE(DNS_RDATASET_VALID(rdataset));
00096         REQUIRE(rdataset->methods == NULL);
00097 
00098         rdataset->magic = 0;
00099         ISC_LINK_INIT(rdataset, link);
00100         rdataset->rdclass = 0;
00101         rdataset->type = 0;
00102         rdataset->ttl = 0;
00103         rdataset->trust = 0;
00104         rdataset->covers = 0;
00105         rdataset->attributes = 0;
00106         rdataset->count = ISC_UINT32_MAX;
00107         rdataset->private1 = NULL;
00108         rdataset->private2 = NULL;
00109         rdataset->private3 = NULL;
00110         rdataset->privateuint4 = 0;
00111         rdataset->private5 = NULL;
00112 }
00113 
00114 void
00115 dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
00116 
00117         /*
00118          * Disassociate 'rdataset' from its rdata, allowing it to be reused.
00119          */
00120 
00121         REQUIRE(DNS_RDATASET_VALID(rdataset));
00122         REQUIRE(rdataset->methods != NULL);
00123 
00124         (rdataset->methods->disassociate)(rdataset);
00125         rdataset->methods = NULL;
00126         ISC_LINK_INIT(rdataset, link);
00127         rdataset->rdclass = 0;
00128         rdataset->type = 0;
00129         rdataset->ttl = 0;
00130         rdataset->trust = 0;
00131         rdataset->covers = 0;
00132         rdataset->attributes = 0;
00133         rdataset->count = ISC_UINT32_MAX;
00134         rdataset->private1 = NULL;
00135         rdataset->private2 = NULL;
00136         rdataset->private3 = NULL;
00137         rdataset->privateuint4 = 0;
00138         rdataset->private5 = NULL;
00139         rdataset->private6 = NULL;
00140 }
00141 
00142 isc_boolean_t
00143 dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
00144         /*
00145          * Is 'rdataset' associated?
00146          */
00147 
00148         REQUIRE(DNS_RDATASET_VALID(rdataset));
00149 
00150         if (rdataset->methods != NULL)
00151                 return (ISC_TRUE);
00152 
00153         return (ISC_FALSE);
00154 }
00155 
00156 static void
00157 question_disassociate(dns_rdataset_t *rdataset) {
00158         UNUSED(rdataset);
00159 }
00160 
00161 static isc_result_t
00162 question_cursor(dns_rdataset_t *rdataset) {
00163         UNUSED(rdataset);
00164 
00165         return (ISC_R_NOMORE);
00166 }
00167 
00168 static void
00169 question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00170         /*
00171          * This routine should never be called.
00172          */
00173         UNUSED(rdataset);
00174         UNUSED(rdata);
00175 
00176         REQUIRE(0);
00177 }
00178 
00179 static void
00180 question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00181         *target = *source;
00182 }
00183 
00184 static unsigned int
00185 question_count(dns_rdataset_t *rdataset) {
00186         /*
00187          * This routine should never be called.
00188          */
00189         UNUSED(rdataset);
00190         REQUIRE(0);
00191 
00192         return (0);
00193 }
00194 
00195 static dns_rdatasetmethods_t question_methods = {
00196         question_disassociate,
00197         question_cursor,
00198         question_cursor,
00199         question_current,
00200         question_clone,
00201         question_count,
00202         NULL,
00203         NULL,
00204         NULL,
00205         NULL,
00206         NULL,
00207         NULL,
00208         NULL,
00209         NULL,
00210         NULL,
00211         NULL,
00212         NULL,
00213         NULL
00214 };
00215 
00216 void
00217 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
00218                           dns_rdatatype_t type)
00219 {
00220 
00221         /*
00222          * Make 'rdataset' a valid, associated, question rdataset, with a
00223          * question class of 'rdclass' and type 'type'.
00224          */
00225 
00226         REQUIRE(DNS_RDATASET_VALID(rdataset));
00227         REQUIRE(rdataset->methods == NULL);
00228 
00229         rdataset->methods = &question_methods;
00230         rdataset->rdclass = rdclass;
00231         rdataset->type = type;
00232         rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
00233 }
00234 
00235 unsigned int
00236 dns_rdataset_count(dns_rdataset_t *rdataset) {
00237 
00238         /*
00239          * Return the number of records in 'rdataset'.
00240          */
00241 
00242         REQUIRE(DNS_RDATASET_VALID(rdataset));
00243         REQUIRE(rdataset->methods != NULL);
00244 
00245         return ((rdataset->methods->count)(rdataset));
00246 }
00247 
00248 void
00249 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00250 
00251         /*
00252          * Make 'target' refer to the same rdataset as 'source'.
00253          */
00254 
00255         REQUIRE(DNS_RDATASET_VALID(source));
00256         REQUIRE(source->methods != NULL);
00257         REQUIRE(DNS_RDATASET_VALID(target));
00258         REQUIRE(target->methods == NULL);
00259 
00260         (source->methods->clone)(source, target);
00261 }
00262 
00263 isc_result_t
00264 dns_rdataset_first(dns_rdataset_t *rdataset) {
00265 
00266         /*
00267          * Move the rdata cursor to the first rdata in the rdataset (if any).
00268          */
00269 
00270         REQUIRE(DNS_RDATASET_VALID(rdataset));
00271         REQUIRE(rdataset->methods != NULL);
00272 
00273         return ((rdataset->methods->first)(rdataset));
00274 }
00275 
00276 isc_result_t
00277 dns_rdataset_next(dns_rdataset_t *rdataset) {
00278 
00279         /*
00280          * Move the rdata cursor to the next rdata in the rdataset (if any).
00281          */
00282 
00283         REQUIRE(DNS_RDATASET_VALID(rdataset));
00284         REQUIRE(rdataset->methods != NULL);
00285 
00286         return ((rdataset->methods->next)(rdataset));
00287 }
00288 
00289 void
00290 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00291 
00292         /*
00293          * Make 'rdata' refer to the current rdata.
00294          */
00295 
00296         REQUIRE(DNS_RDATASET_VALID(rdataset));
00297         REQUIRE(rdataset->methods != NULL);
00298 
00299         (rdataset->methods->current)(rdataset, rdata);
00300 }
00301 
00302 #define MAX_SHUFFLE     32
00303 #define WANT_FIXED(r)   (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
00304 #define WANT_RANDOM(r)  (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
00305 
00306 struct towire_sort {
00307         int key;
00308         dns_rdata_t *rdata;
00309 };
00310 
00311 static int
00312 towire_compare(const void *av, const void *bv) {
00313         const struct towire_sort *a = (const struct towire_sort *) av;
00314         const struct towire_sort *b = (const struct towire_sort *) bv;
00315         return (a->key - b->key);
00316 }
00317 
00318 static isc_result_t
00319 towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
00320              dns_compress_t *cctx, isc_buffer_t *target,
00321              dns_rdatasetorderfunc_t order, const void *order_arg,
00322              isc_boolean_t partial, unsigned int options,
00323              unsigned int *countp, void **state)
00324 {
00325         dns_rdata_t rdata = DNS_RDATA_INIT;
00326         isc_region_t r;
00327         isc_result_t result;
00328         unsigned int i, count = 0, added, choice;
00329         isc_buffer_t savedbuffer, rdlen, rrbuffer;
00330         unsigned int headlen;
00331         isc_boolean_t question = ISC_FALSE;
00332         isc_boolean_t shuffle = ISC_FALSE;
00333         dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
00334         struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
00335         dns_fixedname_t fixed;
00336         dns_name_t *name;
00337 
00338         UNUSED(state);
00339 
00340         /*
00341          * Convert 'rdataset' to wire format, compressing names as specified
00342          * in cctx, and storing the result in 'target'.
00343          */
00344 
00345         REQUIRE(DNS_RDATASET_VALID(rdataset));
00346         REQUIRE(countp != NULL);
00347         REQUIRE((order == NULL) == (order_arg == NULL));
00348         REQUIRE(cctx != NULL && cctx->mctx != NULL);
00349 
00350         if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
00351                 question = ISC_TRUE;
00352                 count = 1;
00353                 result = dns_rdataset_first(rdataset);
00354                 INSIST(result == ISC_R_NOMORE);
00355         } else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
00356                 /*
00357                  * This is a negative caching rdataset.
00358                  */
00359                 unsigned int ncache_opts = 0;
00360                 if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
00361                         ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
00362                 return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
00363                                           countp));
00364         } else {
00365                 count = (rdataset->methods->count)(rdataset);
00366                 result = dns_rdataset_first(rdataset);
00367                 if (result == ISC_R_NOMORE)
00368                         return (ISC_R_SUCCESS);
00369                 if (result != ISC_R_SUCCESS)
00370                         return (result);
00371         }
00372 
00373         /*
00374          * Do we want to shuffle this answer?
00375          */
00376         if (!question && count > 1 &&
00377             (!WANT_FIXED(rdataset) || order != NULL) &&
00378             rdataset->type != dns_rdatatype_rrsig)
00379                 shuffle = ISC_TRUE;
00380 
00381         if (shuffle && count > MAX_SHUFFLE) {
00382                 shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
00383                 sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
00384                 if (shuffled == NULL || sorted == NULL)
00385                         shuffle = ISC_FALSE;
00386         } else {
00387                 shuffled = shuffled_fixed;
00388                 sorted = sorted_fixed;
00389         }
00390 
00391         if (shuffle) {
00392                 /*
00393                  * First we get handles to all of the rdata.
00394                  */
00395                 i = 0;
00396                 do {
00397                         INSIST(i < count);
00398                         dns_rdata_init(&shuffled[i]);
00399                         dns_rdataset_current(rdataset, &shuffled[i]);
00400                         i++;
00401                         result = dns_rdataset_next(rdataset);
00402                 } while (result == ISC_R_SUCCESS);
00403                 if (result != ISC_R_NOMORE)
00404                         goto cleanup;
00405                 INSIST(i == count);
00406 
00407                 /*
00408                  * Now we shuffle.
00409                  */
00410                 if (WANT_FIXED(rdataset)) {
00411                         /*
00412                          * 'Fixed' order.
00413                          */
00414                         INSIST(order != NULL);
00415                         for (i = 0; i < count; i++) {
00416                                 sorted[i].key = (*order)(&shuffled[i],
00417                                                          order_arg);
00418                                 sorted[i].rdata = &shuffled[i];
00419                         }
00420                 } else if (WANT_RANDOM(rdataset)) {
00421                         /*
00422                          * 'Random' order.
00423                          */
00424                         for (i = 0; i < count; i++) {
00425                                 isc_uint32_t val;
00426 
00427                                 isc_random_get(&val);
00428                                 choice = i + (val % (count - i));
00429                                 rdata = shuffled[i];
00430                                 shuffled[i] = shuffled[choice];
00431                                 shuffled[choice] = rdata;
00432                                 if (order != NULL)
00433                                         sorted[i].key = (*order)(&shuffled[i],
00434                                                                  order_arg);
00435                                 else
00436                                         sorted[i].key = 0; /* Unused */
00437                                 sorted[i].rdata = &shuffled[i];
00438                         }
00439                 } else {
00440                         /*
00441                          * "Cyclic" order.
00442                          */
00443                         isc_uint32_t val;
00444                         unsigned int j;
00445 
00446                         val = rdataset->count;
00447                         if (val == ISC_UINT32_MAX)
00448                                 isc_random_get(&val);
00449                         j = val % count;
00450                         for (i = 0; i < count; i++) {
00451                                 if (order != NULL)
00452                                         sorted[i].key = (*order)(&shuffled[j],
00453                                                                  order_arg);
00454                                 else
00455                                         sorted[i].key = 0; /* Unused */
00456                                 sorted[i].rdata = &shuffled[j];
00457                                 j++;
00458                                 if (j == count)
00459                                         j = 0; /* Wrap around. */
00460                         }
00461                 }
00462 
00463                 /*
00464                  * Sorted order.
00465                  */
00466                 if (order != NULL)
00467                         qsort(sorted, count, sizeof(sorted[0]),
00468                               towire_compare);
00469         }
00470 
00471         savedbuffer = *target;
00472         i = 0;
00473         added = 0;
00474 
00475         dns_fixedname_init(&fixed);
00476         name = dns_fixedname_name(&fixed);
00477         dns_name_copy(owner_name, name, NULL);
00478         dns_rdataset_getownercase(rdataset, name);
00479 
00480         do {
00481                 /*
00482                  * Copy out the name, type, class, ttl.
00483                  */
00484 
00485                 rrbuffer = *target;
00486                 dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
00487                 result = dns_name_towire(name, cctx, target);
00488                 if (result != ISC_R_SUCCESS)
00489                         goto rollback;
00490                 headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
00491                 if (!question)
00492                         headlen += sizeof(dns_ttl_t)
00493                                 + 2;  /* XXX 2 for rdata len */
00494                 isc_buffer_availableregion(target, &r);
00495                 if (r.length < headlen) {
00496                         result = ISC_R_NOSPACE;
00497                         goto rollback;
00498                 }
00499                 isc_buffer_putuint16(target, rdataset->type);
00500                 isc_buffer_putuint16(target, rdataset->rdclass);
00501                 if (!question) {
00502                         isc_buffer_putuint32(target, rdataset->ttl);
00503 
00504                         /*
00505                          * Save space for rdlen.
00506                          */
00507                         rdlen = *target;
00508                         isc_buffer_add(target, 2);
00509 
00510                         /*
00511                          * Copy out the rdata
00512                          */
00513                         if (shuffle)
00514                                 rdata = *(sorted[i].rdata);
00515                         else {
00516                                 dns_rdata_reset(&rdata);
00517                                 dns_rdataset_current(rdataset, &rdata);
00518                         }
00519                         result = dns_rdata_towire(&rdata, cctx, target);
00520                         if (result != ISC_R_SUCCESS)
00521                                 goto rollback;
00522                         INSIST((target->used >= rdlen.used + 2) &&
00523                                (target->used - rdlen.used - 2 < 65536));
00524                         isc_buffer_putuint16(&rdlen,
00525                                              (isc_uint16_t)(target->used -
00526                                                             rdlen.used - 2));
00527                         added++;
00528                 }
00529 
00530                 if (shuffle) {
00531                         i++;
00532                         if (i == count)
00533                                 result = ISC_R_NOMORE;
00534                         else
00535                                 result = ISC_R_SUCCESS;
00536                 } else {
00537                         result = dns_rdataset_next(rdataset);
00538                 }
00539         } while (result == ISC_R_SUCCESS);
00540 
00541         if (result != ISC_R_NOMORE)
00542                 goto rollback;
00543 
00544         *countp += count;
00545 
00546         result = ISC_R_SUCCESS;
00547         goto cleanup;
00548 
00549  rollback:
00550         if (partial && result == ISC_R_NOSPACE) {
00551                 INSIST(rrbuffer.used < 65536);
00552                 dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
00553                 *countp += added;
00554                 *target = rrbuffer;
00555                 goto cleanup;
00556         }
00557         INSIST(savedbuffer.used < 65536);
00558         dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
00559         *countp = 0;
00560         *target = savedbuffer;
00561 
00562  cleanup:
00563         if (sorted != NULL && sorted != sorted_fixed)
00564                 isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
00565         if (shuffled != NULL && shuffled != shuffled_fixed)
00566                 isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
00567         return (result);
00568 }
00569 
00570 isc_result_t
00571 dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
00572                           const dns_name_t *owner_name,
00573                           dns_compress_t *cctx,
00574                           isc_buffer_t *target,
00575                           dns_rdatasetorderfunc_t order,
00576                           const void *order_arg,
00577                           unsigned int options,
00578                           unsigned int *countp)
00579 {
00580         return (towiresorted(rdataset, owner_name, cctx, target,
00581                              order, order_arg, ISC_FALSE, options,
00582                              countp, NULL));
00583 }
00584 
00585 isc_result_t
00586 dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
00587                            const dns_name_t *owner_name,
00588                            dns_compress_t *cctx,
00589                            isc_buffer_t *target,
00590                            dns_rdatasetorderfunc_t order,
00591                            const void *order_arg,
00592                            unsigned int options,
00593                            unsigned int *countp,
00594                            void **state)
00595 {
00596         REQUIRE(state == NULL); /* XXX remove when implemented */
00597         return (towiresorted(rdataset, owner_name, cctx, target,
00598                              order, order_arg, ISC_TRUE, options,
00599                              countp, state));
00600 }
00601 
00602 isc_result_t
00603 dns_rdataset_towire(dns_rdataset_t *rdataset,
00604                     dns_name_t *owner_name,
00605                     dns_compress_t *cctx,
00606                     isc_buffer_t *target,
00607                     unsigned int options,
00608                     unsigned int *countp)
00609 {
00610         return (towiresorted(rdataset, owner_name, cctx, target,
00611                              NULL, NULL, ISC_FALSE, options, countp, NULL));
00612 }
00613 
00614 isc_result_t
00615 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
00616                             dns_additionaldatafunc_t add, void *arg)
00617 {
00618         dns_rdata_t rdata = DNS_RDATA_INIT;
00619         isc_result_t result;
00620 
00621         /*
00622          * For each rdata in rdataset, call 'add' for each name and type in the
00623          * rdata which is subject to additional section processing.
00624          */
00625 
00626         REQUIRE(DNS_RDATASET_VALID(rdataset));
00627         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
00628 
00629         result = dns_rdataset_first(rdataset);
00630         if (result != ISC_R_SUCCESS)
00631                 return (result);
00632 
00633         do {
00634                 dns_rdataset_current(rdataset, &rdata);
00635                 result = dns_rdata_additionaldata(&rdata, add, arg);
00636                 if (result == ISC_R_SUCCESS)
00637                         result = dns_rdataset_next(rdataset);
00638                 dns_rdata_reset(&rdata);
00639         } while (result == ISC_R_SUCCESS);
00640 
00641         if (result != ISC_R_NOMORE)
00642                 return (result);
00643 
00644         return (ISC_R_SUCCESS);
00645 }
00646 
00647 isc_result_t
00648 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
00649 
00650         REQUIRE(DNS_RDATASET_VALID(rdataset));
00651         REQUIRE(rdataset->methods != NULL);
00652         if (rdataset->methods->addnoqname == NULL)
00653                 return (ISC_R_NOTIMPLEMENTED);
00654         return((rdataset->methods->addnoqname)(rdataset, name));
00655 }
00656 
00657 isc_result_t
00658 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
00659                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
00660 {
00661         REQUIRE(DNS_RDATASET_VALID(rdataset));
00662         REQUIRE(rdataset->methods != NULL);
00663 
00664         if (rdataset->methods->getnoqname == NULL)
00665                 return (ISC_R_NOTIMPLEMENTED);
00666         return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
00667 }
00668 
00669 isc_result_t
00670 dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
00671 
00672         REQUIRE(DNS_RDATASET_VALID(rdataset));
00673         REQUIRE(rdataset->methods != NULL);
00674         if (rdataset->methods->addclosest == NULL)
00675                 return (ISC_R_NOTIMPLEMENTED);
00676         return((rdataset->methods->addclosest)(rdataset, name));
00677 }
00678 
00679 isc_result_t
00680 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
00681                         dns_rdataset_t *neg, dns_rdataset_t *negsig)
00682 {
00683         REQUIRE(DNS_RDATASET_VALID(rdataset));
00684         REQUIRE(rdataset->methods != NULL);
00685 
00686         if (rdataset->methods->getclosest == NULL)
00687                 return (ISC_R_NOTIMPLEMENTED);
00688         return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
00689 }
00690 
00691 /*
00692  * Additional cache stuff
00693  */
00694 isc_result_t
00695 dns_rdataset_getadditional(dns_rdataset_t *rdataset,
00696                            dns_rdatasetadditional_t type,
00697                            dns_rdatatype_t qtype,
00698                            dns_acache_t *acache,
00699                            dns_zone_t **zonep,
00700                            dns_db_t **dbp,
00701                            dns_dbversion_t **versionp,
00702                            dns_dbnode_t **nodep,
00703                            dns_name_t *fname,
00704                            dns_message_t *msg,
00705                            isc_stdtime_t now)
00706 {
00707         REQUIRE(DNS_RDATASET_VALID(rdataset));
00708         REQUIRE(rdataset->methods != NULL);
00709         REQUIRE(zonep == NULL || *zonep == NULL);
00710         REQUIRE(dbp != NULL && *dbp == NULL);
00711         REQUIRE(versionp != NULL && *versionp == NULL);
00712         REQUIRE(nodep != NULL && *nodep == NULL);
00713         REQUIRE(fname != NULL);
00714         REQUIRE(msg != NULL);
00715 
00716         if (acache != NULL && rdataset->methods->getadditional != NULL) {
00717                 return ((rdataset->methods->getadditional)(rdataset, type,
00718                                                            qtype, acache,
00719                                                            zonep, dbp,
00720                                                            versionp, nodep,
00721                                                            fname, msg, now));
00722         }
00723 
00724         return (ISC_R_FAILURE);
00725 }
00726 
00727 isc_result_t
00728 dns_rdataset_setadditional(dns_rdataset_t *rdataset,
00729                            dns_rdatasetadditional_t type,
00730                            dns_rdatatype_t qtype,
00731                            dns_acache_t *acache,
00732                            dns_zone_t *zone,
00733                            dns_db_t *db,
00734                            dns_dbversion_t *version,
00735                            dns_dbnode_t *node,
00736                            dns_name_t *fname)
00737 {
00738         REQUIRE(DNS_RDATASET_VALID(rdataset));
00739         REQUIRE(rdataset->methods != NULL);
00740 
00741         if (acache != NULL && rdataset->methods->setadditional != NULL) {
00742                 return ((rdataset->methods->setadditional)(rdataset, type,
00743                                                            qtype, acache, zone,
00744                                                            db, version,
00745                                                            node, fname));
00746         }
00747 
00748         return (ISC_R_FAILURE);
00749 }
00750 
00751 isc_result_t
00752 dns_rdataset_putadditional(dns_acache_t *acache,
00753                            dns_rdataset_t *rdataset,
00754                            dns_rdatasetadditional_t type,
00755                            dns_rdatatype_t qtype)
00756 {
00757         REQUIRE(DNS_RDATASET_VALID(rdataset));
00758         REQUIRE(rdataset->methods != NULL);
00759 
00760         if (acache != NULL && rdataset->methods->putadditional != NULL) {
00761                 return ((rdataset->methods->putadditional)(acache, rdataset,
00762                                                            type, qtype));
00763         }
00764 
00765         return (ISC_R_FAILURE);
00766 }
00767 
00768 void
00769 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
00770         REQUIRE(DNS_RDATASET_VALID(rdataset));
00771         REQUIRE(rdataset->methods != NULL);
00772 
00773         if (rdataset->methods->settrust != NULL)
00774                 (rdataset->methods->settrust)(rdataset, trust);
00775         else
00776                 rdataset->trust = trust;
00777 }
00778 
00779 void
00780 dns_rdataset_expire(dns_rdataset_t *rdataset) {
00781         REQUIRE(DNS_RDATASET_VALID(rdataset));
00782         REQUIRE(rdataset->methods != NULL);
00783 
00784         if (rdataset->methods->expire != NULL)
00785                 (rdataset->methods->expire)(rdataset);
00786 }
00787 
00788 void
00789 dns_rdataset_clearprefetch(dns_rdataset_t *rdataset) {
00790         REQUIRE(DNS_RDATASET_VALID(rdataset));
00791         REQUIRE(rdataset->methods != NULL);
00792 
00793         if (rdataset->methods->clearprefetch != NULL)
00794                 (rdataset->methods->clearprefetch)(rdataset);
00795 }
00796 
00797 void
00798 dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
00799         REQUIRE(DNS_RDATASET_VALID(rdataset));
00800         REQUIRE(rdataset->methods != NULL);
00801 
00802         if (rdataset->methods->setownercase != NULL)
00803                 (rdataset->methods->setownercase)(rdataset, name);
00804 }
00805 
00806 void
00807 dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
00808         REQUIRE(DNS_RDATASET_VALID(rdataset));
00809         REQUIRE(rdataset->methods != NULL);
00810 
00811         if (rdataset->methods->getownercase != NULL)
00812                 (rdataset->methods->getownercase)(rdataset, name);
00813 }
00814 
00815 void
00816 dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
00817                      dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
00818                      isc_boolean_t acceptexpired)
00819 {
00820         isc_uint32_t ttl = 0;
00821 
00822         REQUIRE(DNS_RDATASET_VALID(rdataset));
00823         REQUIRE(DNS_RDATASET_VALID(sigrdataset));
00824         REQUIRE(rrsig != NULL);
00825 
00826         /*
00827          * If we accept expired RRsets keep them for no more than 120 seconds.
00828          */
00829         if (acceptexpired &&
00830             (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) ||
00831              isc_serial_le(rrsig->timeexpire, now)))
00832                 ttl = 120;
00833         else if (isc_serial_ge(rrsig->timeexpire, now))
00834                 ttl = rrsig->timeexpire - now;
00835 
00836         ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl),
00837                       ISC_MIN(rrsig->originalttl, ttl));
00838         rdataset->ttl = ttl;
00839         sigrdataset->ttl = ttl;
00840 }

Generated on Tue Apr 28 17:41:00 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha