"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/dns/ncache.c" (4 Sep 2020, 19886 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ncache.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <inttypes.h>
   15 #include <stdbool.h>
   16 
   17 #include <isc/buffer.h>
   18 #include <isc/util.h>
   19 
   20 #include <dns/db.h>
   21 #include <dns/message.h>
   22 #include <dns/ncache.h>
   23 #include <dns/rdata.h>
   24 #include <dns/rdatalist.h>
   25 #include <dns/rdataset.h>
   26 #include <dns/rdatastruct.h>
   27 
   28 #define DNS_NCACHE_RDATA 100U
   29 
   30 /*
   31  * The format of an ncache rdata is a sequence of zero or more records of
   32  * the following format:
   33  *
   34  *  owner name
   35  *  type
   36  *  trust
   37  *  rdata count
   38  *      rdata length            These two occur 'rdata count'
   39  *      rdata               times.
   40  *
   41  */
   42 
   43 static isc_result_t
   44 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
   45       dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
   46       dns_ttl_t maxttl, bool optout, bool secure,
   47       dns_rdataset_t *addedrdataset);
   48 
   49 static inline isc_result_t
   50 copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
   51     isc_result_t result;
   52     unsigned int count;
   53     isc_region_t ar, r;
   54     dns_rdata_t rdata = DNS_RDATA_INIT;
   55 
   56     /*
   57      * Copy the rdataset count to the buffer.
   58      */
   59     isc_buffer_availableregion(buffer, &ar);
   60     if (ar.length < 2) {
   61         return (ISC_R_NOSPACE);
   62     }
   63     count = dns_rdataset_count(rdataset);
   64     INSIST(count <= 65535);
   65     isc_buffer_putuint16(buffer, (uint16_t)count);
   66 
   67     result = dns_rdataset_first(rdataset);
   68     while (result == ISC_R_SUCCESS) {
   69         dns_rdataset_current(rdataset, &rdata);
   70         dns_rdata_toregion(&rdata, &r);
   71         INSIST(r.length <= 65535);
   72         isc_buffer_availableregion(buffer, &ar);
   73         if (ar.length < 2) {
   74             return (ISC_R_NOSPACE);
   75         }
   76         /*
   77          * Copy the rdata length to the buffer.
   78          */
   79         isc_buffer_putuint16(buffer, (uint16_t)r.length);
   80         /*
   81          * Copy the rdata to the buffer.
   82          */
   83         result = isc_buffer_copyregion(buffer, &r);
   84         if (result != ISC_R_SUCCESS) {
   85             return (result);
   86         }
   87         dns_rdata_reset(&rdata);
   88         result = dns_rdataset_next(rdataset);
   89     }
   90     if (result != ISC_R_NOMORE) {
   91         return (result);
   92     }
   93 
   94     return (ISC_R_SUCCESS);
   95 }
   96 
   97 isc_result_t
   98 dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
   99            dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
  100            dns_ttl_t maxttl, dns_rdataset_t *addedrdataset) {
  101     return (addoptout(message, cache, node, covers, now, minttl, maxttl,
  102               false, false, addedrdataset));
  103 }
  104 
  105 isc_result_t
  106 dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
  107              dns_dbnode_t *node, dns_rdatatype_t covers,
  108              isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
  109              bool optout, dns_rdataset_t *addedrdataset) {
  110     return (addoptout(message, cache, node, covers, now, minttl, maxttl,
  111               optout, true, addedrdataset));
  112 }
  113 
  114 static isc_result_t
  115 addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
  116       dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
  117       dns_ttl_t maxttl, bool optout, bool secure,
  118       dns_rdataset_t *addedrdataset) {
  119     isc_result_t result;
  120     isc_buffer_t buffer;
  121     isc_region_t r;
  122     dns_rdataset_t *rdataset;
  123     dns_rdatatype_t type;
  124     dns_name_t *name;
  125     dns_ttl_t ttl;
  126     dns_trust_t trust;
  127     dns_rdata_t rdata[DNS_NCACHE_RDATA];
  128     dns_rdataset_t ncrdataset;
  129     dns_rdatalist_t ncrdatalist;
  130     unsigned char data[65536];
  131     unsigned int next = 0;
  132 
  133     /*
  134      * Convert the authority data from 'message' into a negative cache
  135      * rdataset, and store it in 'cache' at 'node'.
  136      */
  137 
  138     REQUIRE(message != NULL);
  139 
  140     /*
  141      * We assume that all data in the authority section has been
  142      * validated by the caller.
  143      */
  144 
  145     /*
  146      * Initialize the list.
  147      */
  148     dns_rdatalist_init(&ncrdatalist);
  149     ncrdatalist.rdclass = dns_db_class(cache);
  150     ncrdatalist.covers = covers;
  151     ncrdatalist.ttl = maxttl;
  152 
  153     /*
  154      * Build an ncache rdatas into buffer.
  155      */
  156     ttl = maxttl;
  157     trust = 0xffff;
  158     isc_buffer_init(&buffer, data, sizeof(data));
  159     if (message->counts[DNS_SECTION_AUTHORITY]) {
  160         result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
  161     } else {
  162         result = ISC_R_NOMORE;
  163     }
  164     while (result == ISC_R_SUCCESS) {
  165         name = NULL;
  166         dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
  167         if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
  168             for (rdataset = ISC_LIST_HEAD(name->list);
  169                  rdataset != NULL;
  170                  rdataset = ISC_LIST_NEXT(rdataset, link))
  171             {
  172                 if ((rdataset->attributes &
  173                      DNS_RDATASETATTR_NCACHE) == 0) {
  174                     continue;
  175                 }
  176                 type = rdataset->type;
  177                 if (type == dns_rdatatype_rrsig) {
  178                     type = rdataset->covers;
  179                 }
  180                 if (type == dns_rdatatype_soa ||
  181                     type == dns_rdatatype_nsec ||
  182                     type == dns_rdatatype_nsec3)
  183                 {
  184                     if (ttl > rdataset->ttl) {
  185                         ttl = rdataset->ttl;
  186                     }
  187                     if (ttl < minttl) {
  188                         ttl = minttl;
  189                     }
  190                     if (trust > rdataset->trust) {
  191                         trust = rdataset->trust;
  192                     }
  193                     /*
  194                      * Copy the owner name to the buffer.
  195                      */
  196                     dns_name_toregion(name, &r);
  197                     result = isc_buffer_copyregion(&buffer,
  198                                        &r);
  199                     if (result != ISC_R_SUCCESS) {
  200                         return (result);
  201                     }
  202                     /*
  203                      * Copy the type to the buffer.
  204                      */
  205                     isc_buffer_availableregion(&buffer, &r);
  206                     if (r.length < 3) {
  207                         return (ISC_R_NOSPACE);
  208                     }
  209                     isc_buffer_putuint16(&buffer,
  210                                  rdataset->type);
  211                     isc_buffer_putuint8(
  212                         &buffer,
  213                         (unsigned char)rdataset->trust);
  214                     /*
  215                      * Copy the rdataset into the buffer.
  216                      */
  217                     result = copy_rdataset(rdataset,
  218                                    &buffer);
  219                     if (result != ISC_R_SUCCESS) {
  220                         return (result);
  221                     }
  222 
  223                     if (next >= DNS_NCACHE_RDATA) {
  224                         return (ISC_R_NOSPACE);
  225                     }
  226                     dns_rdata_init(&rdata[next]);
  227                     isc_buffer_remainingregion(&buffer, &r);
  228                     rdata[next].data = r.base;
  229                     rdata[next].length = r.length;
  230                     rdata[next].rdclass =
  231                         ncrdatalist.rdclass;
  232                     rdata[next].type = 0;
  233                     rdata[next].flags = 0;
  234                     ISC_LIST_APPEND(ncrdatalist.rdata,
  235                             &rdata[next], link);
  236                     isc_buffer_forward(&buffer, r.length);
  237                     next++;
  238                 }
  239             }
  240         }
  241         result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
  242     }
  243     if (result != ISC_R_NOMORE) {
  244         return (result);
  245     }
  246 
  247     if (trust == 0xffff) {
  248         if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
  249             message->counts[DNS_SECTION_ANSWER] == 0)
  250         {
  251             /*
  252              * The response has aa set and we haven't followed
  253              * any CNAME or DNAME chains.
  254              */
  255             trust = dns_trust_authauthority;
  256         } else {
  257             trust = dns_trust_additional;
  258         }
  259         ttl = 0;
  260     }
  261 
  262     INSIST(trust != 0xffff);
  263 
  264     ncrdatalist.ttl = ttl;
  265 
  266     dns_rdataset_init(&ncrdataset);
  267     RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset) ==
  268               ISC_R_SUCCESS);
  269     if (!secure && trust > dns_trust_answer) {
  270         trust = dns_trust_answer;
  271     }
  272     ncrdataset.trust = trust;
  273     ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
  274     if (message->rcode == dns_rcode_nxdomain) {
  275         ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
  276     }
  277     if (optout) {
  278         ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;
  279     }
  280 
  281     return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset, 0,
  282                    addedrdataset));
  283 }
  284 
  285 isc_result_t
  286 dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
  287           isc_buffer_t *target, unsigned int options,
  288           unsigned int *countp) {
  289     dns_rdata_t rdata = DNS_RDATA_INIT;
  290     isc_result_t result;
  291     isc_region_t remaining, tavailable;
  292     isc_buffer_t source, savedbuffer, rdlen;
  293     dns_name_t name;
  294     dns_rdatatype_t type;
  295     unsigned int i, rcount, count;
  296 
  297     /*
  298      * Convert the negative caching rdataset 'rdataset' to wire format,
  299      * compressing names as specified in 'cctx', and storing the result in
  300      * 'target'.
  301      */
  302 
  303     REQUIRE(rdataset != NULL);
  304     REQUIRE(rdataset->type == 0);
  305     REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  306 
  307     savedbuffer = *target;
  308     count = 0;
  309 
  310     result = dns_rdataset_first(rdataset);
  311     while (result == ISC_R_SUCCESS) {
  312         dns_rdataset_current(rdataset, &rdata);
  313         isc_buffer_init(&source, rdata.data, rdata.length);
  314         isc_buffer_add(&source, rdata.length);
  315         dns_name_init(&name, NULL);
  316         isc_buffer_remainingregion(&source, &remaining);
  317         dns_name_fromregion(&name, &remaining);
  318         INSIST(remaining.length >= name.length);
  319         isc_buffer_forward(&source, name.length);
  320         remaining.length -= name.length;
  321 
  322         INSIST(remaining.length >= 5);
  323         type = isc_buffer_getuint16(&source);
  324         isc_buffer_forward(&source, 1);
  325         rcount = isc_buffer_getuint16(&source);
  326 
  327         for (i = 0; i < rcount; i++) {
  328             /*
  329              * Get the length of this rdata and set up an
  330              * rdata structure for it.
  331              */
  332             isc_buffer_remainingregion(&source, &remaining);
  333             INSIST(remaining.length >= 2);
  334             dns_rdata_reset(&rdata);
  335             rdata.length = isc_buffer_getuint16(&source);
  336             isc_buffer_remainingregion(&source, &remaining);
  337             rdata.data = remaining.base;
  338             rdata.type = type;
  339             rdata.rdclass = rdataset->rdclass;
  340             INSIST(remaining.length >= rdata.length);
  341             isc_buffer_forward(&source, rdata.length);
  342 
  343             if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
  344                 dns_rdatatype_isdnssec(type))
  345             {
  346                 continue;
  347             }
  348 
  349             /*
  350              * Write the name.
  351              */
  352             dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
  353             result = dns_name_towire(&name, cctx, target);
  354             if (result != ISC_R_SUCCESS) {
  355                 goto rollback;
  356             }
  357 
  358             /*
  359              * See if we have space for type, class, ttl, and
  360              * rdata length.  Write the type, class, and ttl.
  361              */
  362             isc_buffer_availableregion(target, &tavailable);
  363             if (tavailable.length < 10) {
  364                 result = ISC_R_NOSPACE;
  365                 goto rollback;
  366             }
  367             isc_buffer_putuint16(target, type);
  368             isc_buffer_putuint16(target, rdataset->rdclass);
  369             isc_buffer_putuint32(target, rdataset->ttl);
  370 
  371             /*
  372              * Save space for rdata length.
  373              */
  374             rdlen = *target;
  375             isc_buffer_add(target, 2);
  376 
  377             /*
  378              * Write the rdata.
  379              */
  380             result = dns_rdata_towire(&rdata, cctx, target);
  381             if (result != ISC_R_SUCCESS) {
  382                 goto rollback;
  383             }
  384 
  385             /*
  386              * Set the rdata length field to the compressed
  387              * length.
  388              */
  389             INSIST((target->used >= rdlen.used + 2) &&
  390                    (target->used - rdlen.used - 2 < 65536));
  391             isc_buffer_putuint16(
  392                 &rdlen,
  393                 (uint16_t)(target->used - rdlen.used - 2));
  394 
  395             count++;
  396         }
  397         INSIST(isc_buffer_remaininglength(&source) == 0);
  398         result = dns_rdataset_next(rdataset);
  399         dns_rdata_reset(&rdata);
  400     }
  401     if (result != ISC_R_NOMORE) {
  402         goto rollback;
  403     }
  404 
  405     *countp = count;
  406 
  407     return (ISC_R_SUCCESS);
  408 
  409 rollback:
  410     INSIST(savedbuffer.used < 65536);
  411     dns_compress_rollback(cctx, (uint16_t)savedbuffer.used);
  412     *countp = 0;
  413     *target = savedbuffer;
  414 
  415     return (result);
  416 }
  417 
  418 static void
  419 rdataset_disassociate(dns_rdataset_t *rdataset) {
  420     UNUSED(rdataset);
  421 }
  422 
  423 static isc_result_t
  424 rdataset_first(dns_rdataset_t *rdataset) {
  425     unsigned char *raw = rdataset->private3;
  426     unsigned int count;
  427 
  428     count = raw[0] * 256 + raw[1];
  429     if (count == 0) {
  430         rdataset->private5 = NULL;
  431         return (ISC_R_NOMORE);
  432     }
  433     raw += 2;
  434     /*
  435      * The privateuint4 field is the number of rdata beyond the cursor
  436      * position, so we decrement the total count by one before storing
  437      * it.
  438      */
  439     count--;
  440     rdataset->privateuint4 = count;
  441     rdataset->private5 = raw;
  442 
  443     return (ISC_R_SUCCESS);
  444 }
  445 
  446 static isc_result_t
  447 rdataset_next(dns_rdataset_t *rdataset) {
  448     unsigned int count;
  449     unsigned int length;
  450     unsigned char *raw;
  451 
  452     count = rdataset->privateuint4;
  453     if (count == 0) {
  454         return (ISC_R_NOMORE);
  455     }
  456     count--;
  457     rdataset->privateuint4 = count;
  458     raw = rdataset->private5;
  459     length = raw[0] * 256 + raw[1];
  460     raw += length + 2;
  461     rdataset->private5 = raw;
  462 
  463     return (ISC_R_SUCCESS);
  464 }
  465 
  466 static void
  467 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
  468     unsigned char *raw = rdataset->private5;
  469     isc_region_t r;
  470 
  471     REQUIRE(raw != NULL);
  472 
  473     r.length = raw[0] * 256 + raw[1];
  474     raw += 2;
  475     r.base = raw;
  476     dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
  477 }
  478 
  479 static void
  480 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  481     *target = *source;
  482 
  483     /*
  484      * Reset iterator state.
  485      */
  486     target->privateuint4 = 0;
  487     target->private5 = NULL;
  488 }
  489 
  490 static unsigned int
  491 rdataset_count(dns_rdataset_t *rdataset) {
  492     unsigned char *raw = rdataset->private3;
  493     unsigned int count;
  494 
  495     count = raw[0] * 256 + raw[1];
  496 
  497     return (count);
  498 }
  499 
  500 static void
  501 rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
  502     unsigned char *raw = rdataset->private3;
  503 
  504     raw[-1] = (unsigned char)trust;
  505 }
  506 
  507 static dns_rdatasetmethods_t rdataset_methods = {
  508     rdataset_disassociate,
  509     rdataset_first,
  510     rdataset_next,
  511     rdataset_current,
  512     rdataset_clone,
  513     rdataset_count,
  514     NULL,          /* addnoqname */
  515     NULL,          /* getnoqname */
  516     NULL,          /* addclosest */
  517     NULL,          /* getclosest */
  518     rdataset_settrust, /* settrust */
  519     NULL,          /* expire */
  520     NULL,          /* clearprefetch */
  521     NULL,          /* setownercase */
  522     NULL,          /* getownercase */
  523     NULL           /* addglue */
  524 };
  525 
  526 isc_result_t
  527 dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
  528                dns_rdatatype_t type, dns_rdataset_t *rdataset) {
  529     isc_result_t result;
  530     dns_rdata_t rdata = DNS_RDATA_INIT;
  531     isc_region_t remaining;
  532     isc_buffer_t source;
  533     dns_name_t tname;
  534     dns_rdatatype_t ttype;
  535     dns_trust_t trust = dns_trust_none;
  536     dns_rdataset_t rclone;
  537 
  538     REQUIRE(ncacherdataset != NULL);
  539     REQUIRE(ncacherdataset->type == 0);
  540     REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  541     REQUIRE(name != NULL);
  542     REQUIRE(!dns_rdataset_isassociated(rdataset));
  543     REQUIRE(type != dns_rdatatype_rrsig);
  544 
  545     dns_rdataset_init(&rclone);
  546     dns_rdataset_clone(ncacherdataset, &rclone);
  547     result = dns_rdataset_first(&rclone);
  548     while (result == ISC_R_SUCCESS) {
  549         dns_rdataset_current(&rclone, &rdata);
  550         isc_buffer_init(&source, rdata.data, rdata.length);
  551         isc_buffer_add(&source, rdata.length);
  552         dns_name_init(&tname, NULL);
  553         isc_buffer_remainingregion(&source, &remaining);
  554         dns_name_fromregion(&tname, &remaining);
  555         INSIST(remaining.length >= tname.length);
  556         isc_buffer_forward(&source, tname.length);
  557         remaining.length -= tname.length;
  558 
  559         INSIST(remaining.length >= 3);
  560         ttype = isc_buffer_getuint16(&source);
  561 
  562         if (ttype == type && dns_name_equal(&tname, name)) {
  563             trust = isc_buffer_getuint8(&source);
  564             INSIST(trust <= dns_trust_ultimate);
  565             isc_buffer_remainingregion(&source, &remaining);
  566             break;
  567         }
  568         result = dns_rdataset_next(&rclone);
  569         dns_rdata_reset(&rdata);
  570     }
  571     dns_rdataset_disassociate(&rclone);
  572     if (result == ISC_R_NOMORE) {
  573         return (ISC_R_NOTFOUND);
  574     }
  575     if (result != ISC_R_SUCCESS) {
  576         return (result);
  577     }
  578 
  579     INSIST(remaining.length != 0);
  580 
  581     rdataset->methods = &rdataset_methods;
  582     rdataset->rdclass = ncacherdataset->rdclass;
  583     rdataset->type = type;
  584     rdataset->covers = 0;
  585     rdataset->ttl = ncacherdataset->ttl;
  586     rdataset->trust = trust;
  587     rdataset->private1 = NULL;
  588     rdataset->private2 = NULL;
  589 
  590     rdataset->private3 = remaining.base;
  591 
  592     /*
  593      * Reset iterator state.
  594      */
  595     rdataset->privateuint4 = 0;
  596     rdataset->private5 = NULL;
  597     rdataset->private6 = NULL;
  598     return (ISC_R_SUCCESS);
  599 }
  600 
  601 isc_result_t
  602 dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
  603               dns_rdatatype_t covers, dns_rdataset_t *rdataset) {
  604     dns_name_t tname;
  605     dns_rdata_rrsig_t rrsig;
  606     dns_rdata_t rdata = DNS_RDATA_INIT;
  607     dns_rdataset_t rclone;
  608     dns_rdatatype_t type;
  609     dns_trust_t trust = dns_trust_none;
  610     isc_buffer_t source;
  611     isc_region_t remaining, sigregion;
  612     isc_result_t result;
  613     unsigned char *raw;
  614     unsigned int count;
  615 
  616     REQUIRE(ncacherdataset != NULL);
  617     REQUIRE(ncacherdataset->type == 0);
  618     REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  619     REQUIRE(name != NULL);
  620     REQUIRE(!dns_rdataset_isassociated(rdataset));
  621 
  622     dns_rdataset_init(&rclone);
  623     dns_rdataset_clone(ncacherdataset, &rclone);
  624     result = dns_rdataset_first(&rclone);
  625     while (result == ISC_R_SUCCESS) {
  626         dns_rdataset_current(&rclone, &rdata);
  627         isc_buffer_init(&source, rdata.data, rdata.length);
  628         isc_buffer_add(&source, rdata.length);
  629         dns_name_init(&tname, NULL);
  630         isc_buffer_remainingregion(&source, &remaining);
  631         dns_name_fromregion(&tname, &remaining);
  632         INSIST(remaining.length >= tname.length);
  633         isc_buffer_forward(&source, tname.length);
  634         isc_region_consume(&remaining, tname.length);
  635 
  636         INSIST(remaining.length >= 2);
  637         type = isc_buffer_getuint16(&source);
  638         isc_region_consume(&remaining, 2);
  639 
  640         if (type != dns_rdatatype_rrsig ||
  641             !dns_name_equal(&tname, name)) {
  642             result = dns_rdataset_next(&rclone);
  643             dns_rdata_reset(&rdata);
  644             continue;
  645         }
  646 
  647         INSIST(remaining.length >= 1);
  648         trust = isc_buffer_getuint8(&source);
  649         INSIST(trust <= dns_trust_ultimate);
  650         isc_region_consume(&remaining, 1);
  651 
  652         raw = remaining.base;
  653         count = raw[0] * 256 + raw[1];
  654         INSIST(count > 0);
  655         raw += 2;
  656         sigregion.length = raw[0] * 256 + raw[1];
  657         raw += 2;
  658         sigregion.base = raw;
  659         dns_rdata_reset(&rdata);
  660         dns_rdata_fromregion(&rdata, rdataset->rdclass,
  661                      dns_rdatatype_rrsig, &sigregion);
  662         (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
  663         if (rrsig.covered == covers) {
  664             isc_buffer_remainingregion(&source, &remaining);
  665             break;
  666         }
  667 
  668         result = dns_rdataset_next(&rclone);
  669         dns_rdata_reset(&rdata);
  670     }
  671     dns_rdataset_disassociate(&rclone);
  672     if (result == ISC_R_NOMORE) {
  673         return (ISC_R_NOTFOUND);
  674     }
  675     if (result != ISC_R_SUCCESS) {
  676         return (result);
  677     }
  678 
  679     INSIST(remaining.length != 0);
  680 
  681     rdataset->methods = &rdataset_methods;
  682     rdataset->rdclass = ncacherdataset->rdclass;
  683     rdataset->type = dns_rdatatype_rrsig;
  684     rdataset->covers = covers;
  685     rdataset->ttl = ncacherdataset->ttl;
  686     rdataset->trust = trust;
  687     rdataset->private1 = NULL;
  688     rdataset->private2 = NULL;
  689 
  690     rdataset->private3 = remaining.base;
  691 
  692     /*
  693      * Reset iterator state.
  694      */
  695     rdataset->privateuint4 = 0;
  696     rdataset->private5 = NULL;
  697     rdataset->private6 = NULL;
  698     return (ISC_R_SUCCESS);
  699 }
  700 
  701 void
  702 dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
  703            dns_rdataset_t *rdataset) {
  704     dns_rdata_t rdata = DNS_RDATA_INIT;
  705     dns_trust_t trust;
  706     isc_region_t remaining, sigregion;
  707     isc_buffer_t source;
  708     dns_name_t tname;
  709     dns_rdatatype_t type;
  710     unsigned int count;
  711     dns_rdata_rrsig_t rrsig;
  712     unsigned char *raw;
  713 
  714     REQUIRE(ncacherdataset != NULL);
  715     REQUIRE(ncacherdataset->type == 0);
  716     REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  717     REQUIRE(found != NULL);
  718     REQUIRE(!dns_rdataset_isassociated(rdataset));
  719 
  720     dns_rdataset_current(ncacherdataset, &rdata);
  721     isc_buffer_init(&source, rdata.data, rdata.length);
  722     isc_buffer_add(&source, rdata.length);
  723 
  724     dns_name_init(&tname, NULL);
  725     isc_buffer_remainingregion(&source, &remaining);
  726     dns_name_fromregion(found, &remaining);
  727     INSIST(remaining.length >= found->length);
  728     isc_buffer_forward(&source, found->length);
  729     remaining.length -= found->length;
  730 
  731     INSIST(remaining.length >= 5);
  732     type = isc_buffer_getuint16(&source);
  733     trust = isc_buffer_getuint8(&source);
  734     INSIST(trust <= dns_trust_ultimate);
  735     isc_buffer_remainingregion(&source, &remaining);
  736 
  737     rdataset->methods = &rdataset_methods;
  738     rdataset->rdclass = ncacherdataset->rdclass;
  739     rdataset->type = type;
  740     if (type == dns_rdatatype_rrsig) {
  741         /*
  742          * Extract covers from RRSIG.
  743          */
  744         raw = remaining.base;
  745         count = raw[0] * 256 + raw[1];
  746         INSIST(count > 0);
  747         raw += 2;
  748         sigregion.length = raw[0] * 256 + raw[1];
  749         raw += 2;
  750         sigregion.base = raw;
  751         dns_rdata_reset(&rdata);
  752         dns_rdata_fromregion(&rdata, rdataset->rdclass, rdataset->type,
  753                      &sigregion);
  754         (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
  755         rdataset->covers = rrsig.covered;
  756     } else {
  757         rdataset->covers = 0;
  758     }
  759     rdataset->ttl = ncacherdataset->ttl;
  760     rdataset->trust = trust;
  761     rdataset->private1 = NULL;
  762     rdataset->private2 = NULL;
  763 
  764     rdataset->private3 = remaining.base;
  765 
  766     /*
  767      * Reset iterator state.
  768      */
  769     rdataset->privateuint4 = 0;
  770     rdataset->private5 = NULL;
  771     rdataset->private6 = NULL;
  772 }