ncache.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2008, 2010-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 <isc/buffer.h>
00025 #include <isc/util.h>
00026 
00027 #include <dns/db.h>
00028 #include <dns/message.h>
00029 #include <dns/ncache.h>
00030 #include <dns/rdata.h>
00031 #include <dns/rdatalist.h>
00032 #include <dns/rdataset.h>
00033 #include <dns/rdatastruct.h>
00034 
00035 #define DNS_NCACHE_RDATA 20U
00036 
00037 /*
00038  * The format of an ncache rdata is a sequence of zero or more records of
00039  * the following format:
00040  *
00041  *      owner name
00042  *      type
00043  *      trust
00044  *      rdata count
00045  *              rdata length                    These two occur 'rdata count'
00046  *              rdata                           times.
00047  *
00048  */
00049 
00050 static isc_result_t
00051 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
00052           dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
00053           isc_boolean_t optout, isc_boolean_t secure,
00054           dns_rdataset_t *addedrdataset);
00055 
00056 static inline isc_result_t
00057 copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
00058         isc_result_t result;
00059         unsigned int count;
00060         isc_region_t ar, r;
00061         dns_rdata_t rdata = DNS_RDATA_INIT;
00062 
00063         /*
00064          * Copy the rdataset count to the buffer.
00065          */
00066         isc_buffer_availableregion(buffer, &ar);
00067         if (ar.length < 2)
00068                 return (ISC_R_NOSPACE);
00069         count = dns_rdataset_count(rdataset);
00070         INSIST(count <= 65535);
00071         isc_buffer_putuint16(buffer, (isc_uint16_t)count);
00072 
00073         result = dns_rdataset_first(rdataset);
00074         while (result == ISC_R_SUCCESS) {
00075                 dns_rdataset_current(rdataset, &rdata);
00076                 dns_rdata_toregion(&rdata, &r);
00077                 INSIST(r.length <= 65535);
00078                 isc_buffer_availableregion(buffer, &ar);
00079                 if (ar.length < 2)
00080                         return (ISC_R_NOSPACE);
00081                 /*
00082                  * Copy the rdata length to the buffer.
00083                  */
00084                 isc_buffer_putuint16(buffer, (isc_uint16_t)r.length);
00085                 /*
00086                  * Copy the rdata to the buffer.
00087                  */
00088                 result = isc_buffer_copyregion(buffer, &r);
00089                 if (result != ISC_R_SUCCESS)
00090                         return (result);
00091                 dns_rdata_reset(&rdata);
00092                 result = dns_rdataset_next(rdataset);
00093         }
00094         if (result != ISC_R_NOMORE)
00095                 return (result);
00096 
00097         return (ISC_R_SUCCESS);
00098 }
00099 
00100 isc_result_t
00101 dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
00102                dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
00103                dns_rdataset_t *addedrdataset)
00104 {
00105         return (addoptout(message, cache, node, covers, now, maxttl,
00106                           ISC_FALSE, ISC_FALSE, addedrdataset));
00107 }
00108 
00109 isc_result_t
00110 dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
00111                      dns_dbnode_t *node, dns_rdatatype_t covers,
00112                      isc_stdtime_t now, dns_ttl_t maxttl,
00113                      isc_boolean_t optout, dns_rdataset_t *addedrdataset)
00114 {
00115         return (addoptout(message, cache, node, covers, now, maxttl,
00116                           optout, ISC_TRUE, addedrdataset));
00117 }
00118 
00119 static isc_result_t
00120 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
00121           dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
00122           isc_boolean_t optout, isc_boolean_t secure,
00123           dns_rdataset_t *addedrdataset)
00124 {
00125         isc_result_t result;
00126         isc_buffer_t buffer;
00127         isc_region_t r;
00128         dns_rdataset_t *rdataset;
00129         dns_rdatatype_t type;
00130         dns_name_t *name;
00131         dns_ttl_t ttl;
00132         dns_trust_t trust;
00133         dns_rdata_t rdata[DNS_NCACHE_RDATA];
00134         dns_rdataset_t ncrdataset;
00135         dns_rdatalist_t ncrdatalist;
00136         unsigned char data[4096];
00137         unsigned int next = 0;
00138 
00139         /*
00140          * Convert the authority data from 'message' into a negative cache
00141          * rdataset, and store it in 'cache' at 'node'.
00142          */
00143 
00144         REQUIRE(message != NULL);
00145 
00146         /*
00147          * We assume that all data in the authority section has been
00148          * validated by the caller.
00149          */
00150 
00151         /*
00152          * Initialize the list.
00153          */
00154         dns_rdatalist_init(&ncrdatalist);
00155         ncrdatalist.rdclass = dns_db_class(cache);
00156         ncrdatalist.covers = covers;
00157         ncrdatalist.ttl = maxttl;
00158 
00159         /*
00160          * Build an ncache rdatas into buffer.
00161          */
00162         ttl = maxttl;
00163         trust = 0xffff;
00164         isc_buffer_init(&buffer, data, sizeof(data));
00165         if (message->counts[DNS_SECTION_AUTHORITY])
00166                 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
00167         else
00168                 result = ISC_R_NOMORE;
00169         while (result == ISC_R_SUCCESS) {
00170                 name = NULL;
00171                 dns_message_currentname(message, DNS_SECTION_AUTHORITY,
00172                                         &name);
00173                 if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
00174                         for (rdataset = ISC_LIST_HEAD(name->list);
00175                              rdataset != NULL;
00176                              rdataset = ISC_LIST_NEXT(rdataset, link)) {
00177                                 if ((rdataset->attributes &
00178                                      DNS_RDATASETATTR_NCACHE) == 0)
00179                                         continue;
00180                                 type = rdataset->type;
00181                                 if (type == dns_rdatatype_rrsig)
00182                                         type = rdataset->covers;
00183                                 if (type == dns_rdatatype_soa ||
00184                                     type == dns_rdatatype_nsec ||
00185                                     type == dns_rdatatype_nsec3) {
00186                                         if (ttl > rdataset->ttl)
00187                                                 ttl = rdataset->ttl;
00188                                         if (trust > rdataset->trust)
00189                                                 trust = rdataset->trust;
00190                                         /*
00191                                          * Copy the owner name to the buffer.
00192                                          */
00193                                         dns_name_toregion(name, &r);
00194                                         result = isc_buffer_copyregion(&buffer,
00195                                                                        &r);
00196                                         if (result != ISC_R_SUCCESS)
00197                                                 return (result);
00198                                         /*
00199                                          * Copy the type to the buffer.
00200                                          */
00201                                         isc_buffer_availableregion(&buffer,
00202                                                                    &r);
00203                                         if (r.length < 3)
00204                                                 return (ISC_R_NOSPACE);
00205                                         isc_buffer_putuint16(&buffer,
00206                                                              rdataset->type);
00207                                         isc_buffer_putuint8(&buffer,
00208                                                (unsigned char)rdataset->trust);
00209                                         /*
00210                                          * Copy the rdataset into the buffer.
00211                                          */
00212                                         result = copy_rdataset(rdataset,
00213                                                                &buffer);
00214                                         if (result != ISC_R_SUCCESS)
00215                                                 return (result);
00216 
00217                                         if (next >= DNS_NCACHE_RDATA)
00218                                                 return (ISC_R_NOSPACE);
00219                                         dns_rdata_init(&rdata[next]);
00220                                         isc_buffer_remainingregion(&buffer, &r);
00221                                         rdata[next].data = r.base;
00222                                         rdata[next].length = r.length;
00223                                         rdata[next].rdclass =
00224                                                 ncrdatalist.rdclass;
00225                                         rdata[next].type = 0;
00226                                         rdata[next].flags = 0;
00227                                         ISC_LIST_APPEND(ncrdatalist.rdata,
00228                                                         &rdata[next], link);
00229                                         isc_buffer_forward(&buffer, r.length);
00230                                         next++;
00231                                 }
00232                         }
00233                 }
00234                 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
00235         }
00236         if (result != ISC_R_NOMORE)
00237                 return (result);
00238 
00239         if (trust == 0xffff) {
00240                 if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
00241                     message->counts[DNS_SECTION_ANSWER] == 0) {
00242                         /*
00243                          * The response has aa set and we haven't followed
00244                          * any CNAME or DNAME chains.
00245                          */
00246                         trust = dns_trust_authauthority;
00247                 } else
00248                         trust = dns_trust_additional;
00249                 ttl = 0;
00250         }
00251 
00252         INSIST(trust != 0xffff);
00253 
00254         ncrdatalist.ttl = ttl;
00255 
00256         dns_rdataset_init(&ncrdataset);
00257         RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
00258                       == ISC_R_SUCCESS);
00259         if (!secure && trust > dns_trust_answer)
00260                 trust = dns_trust_answer;
00261         ncrdataset.trust = trust;
00262         ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
00263         if (message->rcode == dns_rcode_nxdomain)
00264                 ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
00265         if (optout)
00266                 ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;
00267 
00268         return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
00269                                    0, addedrdataset));
00270 }
00271 
00272 isc_result_t
00273 dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
00274                   isc_buffer_t *target, unsigned int options,
00275                   unsigned int *countp)
00276 {
00277         dns_rdata_t rdata = DNS_RDATA_INIT;
00278         isc_result_t result;
00279         isc_region_t remaining, tavailable;
00280         isc_buffer_t source, savedbuffer, rdlen;
00281         dns_name_t name;
00282         dns_rdatatype_t type;
00283         unsigned int i, rcount, count;
00284 
00285         /*
00286          * Convert the negative caching rdataset 'rdataset' to wire format,
00287          * compressing names as specified in 'cctx', and storing the result in
00288          * 'target'.
00289          */
00290 
00291         REQUIRE(rdataset != NULL);
00292         REQUIRE(rdataset->type == 0);
00293         REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
00294 
00295         savedbuffer = *target;
00296         count = 0;
00297 
00298         result = dns_rdataset_first(rdataset);
00299         while (result == ISC_R_SUCCESS) {
00300                 dns_rdataset_current(rdataset, &rdata);
00301                 isc_buffer_init(&source, rdata.data, rdata.length);
00302                 isc_buffer_add(&source, rdata.length);
00303                 dns_name_init(&name, NULL);
00304                 isc_buffer_remainingregion(&source, &remaining);
00305                 dns_name_fromregion(&name, &remaining);
00306                 INSIST(remaining.length >= name.length);
00307                 isc_buffer_forward(&source, name.length);
00308                 remaining.length -= name.length;
00309 
00310                 INSIST(remaining.length >= 5);
00311                 type = isc_buffer_getuint16(&source);
00312                 isc_buffer_forward(&source, 1);
00313                 rcount = isc_buffer_getuint16(&source);
00314 
00315                 for (i = 0; i < rcount; i++) {
00316                         /*
00317                          * Get the length of this rdata and set up an
00318                          * rdata structure for it.
00319                          */
00320                         isc_buffer_remainingregion(&source, &remaining);
00321                         INSIST(remaining.length >= 2);
00322                         dns_rdata_reset(&rdata);
00323                         rdata.length = isc_buffer_getuint16(&source);
00324                         isc_buffer_remainingregion(&source, &remaining);
00325                         rdata.data = remaining.base;
00326                         rdata.type = type;
00327                         rdata.rdclass = rdataset->rdclass;
00328                         INSIST(remaining.length >= rdata.length);
00329                         isc_buffer_forward(&source, rdata.length);
00330 
00331                         if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
00332                             dns_rdatatype_isdnssec(type))
00333                                 continue;
00334 
00335                         /*
00336                          * Write the name.
00337                          */
00338                         dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
00339                         result = dns_name_towire(&name, cctx, target);
00340                         if (result != ISC_R_SUCCESS)
00341                                 goto rollback;
00342 
00343                         /*
00344                          * See if we have space for type, class, ttl, and
00345                          * rdata length.  Write the type, class, and ttl.
00346                          */
00347                         isc_buffer_availableregion(target, &tavailable);
00348                         if (tavailable.length < 10) {
00349                                 result = ISC_R_NOSPACE;
00350                                 goto rollback;
00351                         }
00352                         isc_buffer_putuint16(target, type);
00353                         isc_buffer_putuint16(target, rdataset->rdclass);
00354                         isc_buffer_putuint32(target, rdataset->ttl);
00355 
00356                         /*
00357                          * Save space for rdata length.
00358                          */
00359                         rdlen = *target;
00360                         isc_buffer_add(target, 2);
00361 
00362                         /*
00363                          * Write the rdata.
00364                          */
00365                         result = dns_rdata_towire(&rdata, cctx, target);
00366                         if (result != ISC_R_SUCCESS)
00367                                 goto rollback;
00368 
00369                         /*
00370                          * Set the rdata length field to the compressed
00371                          * length.
00372                          */
00373                         INSIST((target->used >= rdlen.used + 2) &&
00374                                (target->used - rdlen.used - 2 < 65536));
00375                         isc_buffer_putuint16(&rdlen,
00376                                              (isc_uint16_t)(target->used -
00377                                                             rdlen.used - 2));
00378 
00379                         count++;
00380                 }
00381                 INSIST(isc_buffer_remaininglength(&source) == 0);
00382                 result = dns_rdataset_next(rdataset);
00383                 dns_rdata_reset(&rdata);
00384         }
00385         if (result != ISC_R_NOMORE)
00386                 goto rollback;
00387 
00388         *countp = count;
00389 
00390         return (ISC_R_SUCCESS);
00391 
00392  rollback:
00393         INSIST(savedbuffer.used < 65536);
00394         dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
00395         *countp = 0;
00396         *target = savedbuffer;
00397 
00398         return (result);
00399 }
00400 
00401 static void
00402 rdataset_disassociate(dns_rdataset_t *rdataset) {
00403         UNUSED(rdataset);
00404 }
00405 
00406 static isc_result_t
00407 rdataset_first(dns_rdataset_t *rdataset) {
00408         unsigned char *raw = rdataset->private3;
00409         unsigned int count;
00410 
00411         count = raw[0] * 256 + raw[1];
00412         if (count == 0) {
00413                 rdataset->private5 = NULL;
00414                 return (ISC_R_NOMORE);
00415         }
00416         raw += 2;
00417         /*
00418          * The privateuint4 field is the number of rdata beyond the cursor
00419          * position, so we decrement the total count by one before storing
00420          * it.
00421          */
00422         count--;
00423         rdataset->privateuint4 = count;
00424         rdataset->private5 = raw;
00425 
00426         return (ISC_R_SUCCESS);
00427 }
00428 
00429 static isc_result_t
00430 rdataset_next(dns_rdataset_t *rdataset) {
00431         unsigned int count;
00432         unsigned int length;
00433         unsigned char *raw;
00434 
00435         count = rdataset->privateuint4;
00436         if (count == 0)
00437                 return (ISC_R_NOMORE);
00438         count--;
00439         rdataset->privateuint4 = count;
00440         raw = rdataset->private5;
00441         length = raw[0] * 256 + raw[1];
00442         raw += length + 2;
00443         rdataset->private5 = raw;
00444 
00445         return (ISC_R_SUCCESS);
00446 }
00447 
00448 static void
00449 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00450         unsigned char *raw = rdataset->private5;
00451         isc_region_t r;
00452 
00453         REQUIRE(raw != NULL);
00454 
00455         r.length = raw[0] * 256 + raw[1];
00456         raw += 2;
00457         r.base = raw;
00458         dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
00459 }
00460 
00461 static void
00462 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00463         *target = *source;
00464 
00465         /*
00466          * Reset iterator state.
00467          */
00468         target->privateuint4 = 0;
00469         target->private5 = NULL;
00470 }
00471 
00472 static unsigned int
00473 rdataset_count(dns_rdataset_t *rdataset) {
00474         unsigned char *raw = rdataset->private3;
00475         unsigned int count;
00476 
00477         count = raw[0] * 256 + raw[1];
00478 
00479         return (count);
00480 }
00481 
00482 static void
00483 rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
00484         unsigned char *raw = rdataset->private3;
00485 
00486         raw[-1] = (unsigned char)trust;
00487 }
00488 
00489 static dns_rdatasetmethods_t rdataset_methods = {
00490         rdataset_disassociate,
00491         rdataset_first,
00492         rdataset_next,
00493         rdataset_current,
00494         rdataset_clone,
00495         rdataset_count,
00496         NULL,
00497         NULL,
00498         NULL,
00499         NULL,
00500         NULL,
00501         NULL,
00502         NULL,
00503         rdataset_settrust,
00504         NULL,
00505         NULL,
00506         NULL,
00507         NULL
00508 };
00509 
00510 isc_result_t
00511 dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
00512                        dns_rdatatype_t type, dns_rdataset_t *rdataset)
00513 {
00514         isc_result_t result;
00515         dns_rdata_t rdata = DNS_RDATA_INIT;
00516         isc_region_t remaining;
00517         isc_buffer_t source;
00518         dns_name_t tname;
00519         dns_rdatatype_t ttype;
00520         dns_trust_t trust = dns_trust_none;
00521         dns_rdataset_t clone;
00522 
00523         REQUIRE(ncacherdataset != NULL);
00524         REQUIRE(ncacherdataset->type == 0);
00525         REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
00526         REQUIRE(name != NULL);
00527         REQUIRE(!dns_rdataset_isassociated(rdataset));
00528         REQUIRE(type != dns_rdatatype_rrsig);
00529 
00530         dns_rdataset_init(&clone);
00531         dns_rdataset_clone(ncacherdataset, &clone);
00532         result = dns_rdataset_first(&clone);
00533         while (result == ISC_R_SUCCESS) {
00534                 dns_rdataset_current(&clone, &rdata);
00535                 isc_buffer_init(&source, rdata.data, rdata.length);
00536                 isc_buffer_add(&source, rdata.length);
00537                 dns_name_init(&tname, NULL);
00538                 isc_buffer_remainingregion(&source, &remaining);
00539                 dns_name_fromregion(&tname, &remaining);
00540                 INSIST(remaining.length >= tname.length);
00541                 isc_buffer_forward(&source, tname.length);
00542                 remaining.length -= tname.length;
00543 
00544                 INSIST(remaining.length >= 3);
00545                 ttype = isc_buffer_getuint16(&source);
00546 
00547                 if (ttype == type && dns_name_equal(&tname, name)) {
00548                         trust = isc_buffer_getuint8(&source);
00549                         INSIST(trust <= dns_trust_ultimate);
00550                         isc_buffer_remainingregion(&source, &remaining);
00551                         break;
00552                 }
00553                 result = dns_rdataset_next(&clone);
00554                 dns_rdata_reset(&rdata);
00555         }
00556         dns_rdataset_disassociate(&clone);
00557         if (result == ISC_R_NOMORE)
00558                 return (ISC_R_NOTFOUND);
00559         if (result != ISC_R_SUCCESS)
00560                 return (result);
00561 
00562         INSIST(remaining.length != 0);
00563 
00564         rdataset->methods = &rdataset_methods;
00565         rdataset->rdclass = ncacherdataset->rdclass;
00566         rdataset->type = type;
00567         rdataset->covers = 0;
00568         rdataset->ttl = ncacherdataset->ttl;
00569         rdataset->trust = trust;
00570         rdataset->private1 = NULL;
00571         rdataset->private2 = NULL;
00572 
00573         rdataset->private3 = remaining.base;
00574 
00575         /*
00576          * Reset iterator state.
00577          */
00578         rdataset->privateuint4 = 0;
00579         rdataset->private5 = NULL;
00580         rdataset->private6 = NULL;
00581         return (ISC_R_SUCCESS);
00582 }
00583 
00584 isc_result_t
00585 dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
00586                           dns_rdatatype_t covers, dns_rdataset_t *rdataset)
00587 {
00588         dns_name_t tname;
00589         dns_rdata_rrsig_t rrsig;
00590         dns_rdata_t rdata = DNS_RDATA_INIT;
00591         dns_rdataset_t clone;
00592         dns_rdatatype_t type;
00593         dns_trust_t trust = dns_trust_none;
00594         isc_buffer_t source;
00595         isc_region_t remaining, sigregion;
00596         isc_result_t result;
00597         unsigned char *raw;
00598         unsigned int count;
00599 
00600         REQUIRE(ncacherdataset != NULL);
00601         REQUIRE(ncacherdataset->type == 0);
00602         REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
00603         REQUIRE(name != NULL);
00604         REQUIRE(!dns_rdataset_isassociated(rdataset));
00605 
00606         dns_rdataset_init(&clone);
00607         dns_rdataset_clone(ncacherdataset, &clone);
00608         result = dns_rdataset_first(&clone);
00609         while (result == ISC_R_SUCCESS) {
00610                 dns_rdataset_current(&clone, &rdata);
00611                 isc_buffer_init(&source, rdata.data, rdata.length);
00612                 isc_buffer_add(&source, rdata.length);
00613                 dns_name_init(&tname, NULL);
00614                 isc_buffer_remainingregion(&source, &remaining);
00615                 dns_name_fromregion(&tname, &remaining);
00616                 INSIST(remaining.length >= tname.length);
00617                 isc_buffer_forward(&source, tname.length);
00618                 remaining.length -= tname.length;
00619                 remaining.base += tname.length;
00620 
00621                 INSIST(remaining.length >= 2);
00622                 type = isc_buffer_getuint16(&source);
00623                 remaining.length -= 2;
00624                 remaining.base += 2;
00625 
00626                 if (type != dns_rdatatype_rrsig ||
00627                     !dns_name_equal(&tname, name)) {
00628                         result = dns_rdataset_next(&clone);
00629                         dns_rdata_reset(&rdata);
00630                         continue;
00631                 }
00632 
00633                 INSIST(remaining.length >= 1);
00634                 trust = isc_buffer_getuint8(&source);
00635                 INSIST(trust <= dns_trust_ultimate);
00636                 remaining.length -= 1;
00637                 remaining.base += 1;
00638 
00639                 raw = remaining.base;
00640                 count = raw[0] * 256 + raw[1];
00641                 INSIST(count > 0);
00642                 raw += 2;
00643                 sigregion.length = raw[0] * 256 + raw[1];
00644                 raw += 2;
00645                 sigregion.base = raw;
00646                 dns_rdata_reset(&rdata);
00647                 dns_rdata_fromregion(&rdata, rdataset->rdclass,
00648                                      dns_rdatatype_rrsig, &sigregion);
00649                 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
00650                 if (rrsig.covered == covers) {
00651                         isc_buffer_remainingregion(&source, &remaining);
00652                         break;
00653                 }
00654 
00655                 result = dns_rdataset_next(&clone);
00656                 dns_rdata_reset(&rdata);
00657         }
00658         dns_rdataset_disassociate(&clone);
00659         if (result == ISC_R_NOMORE)
00660                 return (ISC_R_NOTFOUND);
00661         if (result != ISC_R_SUCCESS)
00662                 return (result);
00663 
00664         INSIST(remaining.length != 0);
00665 
00666         rdataset->methods = &rdataset_methods;
00667         rdataset->rdclass = ncacherdataset->rdclass;
00668         rdataset->type = dns_rdatatype_rrsig;
00669         rdataset->covers = covers;
00670         rdataset->ttl = ncacherdataset->ttl;
00671         rdataset->trust = trust;
00672         rdataset->private1 = NULL;
00673         rdataset->private2 = NULL;
00674 
00675         rdataset->private3 = remaining.base;
00676 
00677         /*
00678          * Reset iterator state.
00679          */
00680         rdataset->privateuint4 = 0;
00681         rdataset->private5 = NULL;
00682         rdataset->private6 = NULL;
00683         return (ISC_R_SUCCESS);
00684 }
00685 
00686 void
00687 dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
00688                    dns_rdataset_t *rdataset)
00689 {
00690         dns_rdata_t rdata = DNS_RDATA_INIT;
00691         dns_trust_t trust;
00692         isc_region_t remaining, sigregion;
00693         isc_buffer_t source;
00694         dns_name_t tname;
00695         dns_rdatatype_t type;
00696         unsigned int count;
00697         dns_rdata_rrsig_t rrsig;
00698         unsigned char *raw;
00699 
00700         REQUIRE(ncacherdataset != NULL);
00701         REQUIRE(ncacherdataset->type == 0);
00702         REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
00703         REQUIRE(found != NULL);
00704         REQUIRE(!dns_rdataset_isassociated(rdataset));
00705 
00706         dns_rdataset_current(ncacherdataset, &rdata);
00707         isc_buffer_init(&source, rdata.data, rdata.length);
00708         isc_buffer_add(&source, rdata.length);
00709 
00710         dns_name_init(&tname, NULL);
00711         isc_buffer_remainingregion(&source, &remaining);
00712         dns_name_fromregion(found, &remaining);
00713         INSIST(remaining.length >= found->length);
00714         isc_buffer_forward(&source, found->length);
00715         remaining.length -= found->length;
00716 
00717         INSIST(remaining.length >= 5);
00718         type = isc_buffer_getuint16(&source);
00719         trust = isc_buffer_getuint8(&source);
00720         INSIST(trust <= dns_trust_ultimate);
00721         isc_buffer_remainingregion(&source, &remaining);
00722 
00723         rdataset->methods = &rdataset_methods;
00724         rdataset->rdclass = ncacherdataset->rdclass;
00725         rdataset->type = type;
00726         if (type == dns_rdatatype_rrsig) {
00727                 /*
00728                  * Extract covers from RRSIG.
00729                  */
00730                 raw = remaining.base;
00731                 count = raw[0] * 256 + raw[1];
00732                 INSIST(count > 0);
00733                 raw += 2;
00734                 sigregion.length = raw[0] * 256 + raw[1];
00735                 raw += 2;
00736                 sigregion.base = raw;
00737                 dns_rdata_reset(&rdata);
00738                 dns_rdata_fromregion(&rdata, rdataset->rdclass,
00739                                      rdataset->type, &sigregion);
00740                 (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
00741                 rdataset->covers = rrsig.covered;
00742         } else
00743                 rdataset->covers = 0;
00744         rdataset->ttl = ncacherdataset->ttl;
00745         rdataset->trust = trust;
00746         rdataset->private1 = NULL;
00747         rdataset->private2 = NULL;
00748 
00749         rdataset->private3 = remaining.base;
00750 
00751         /*
00752          * Reset iterator state.
00753          */
00754         rdataset->privateuint4 = 0;
00755         rdataset->private5 = NULL;
00756         rdataset->private6 = NULL;
00757 }

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