"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/dns/dnsrps.c" (4 Sep 2020, 24117 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 "dnsrps.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.3_vs_9.17.4.

    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 #ifdef USE_DNSRPS
   18 
   19 #include <stdlib.h>
   20 
   21 #include <isc/mem.h>
   22 #include <isc/string.h>
   23 #include <isc/util.h>
   24 
   25 #include <dns/db.h>
   26 #define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
   27 #include <dns/dnsrps.h>
   28 #include <dns/rdataset.h>
   29 #include <dns/rdatasetiter.h>
   30 #include <dns/result.h>
   31 #include <dns/rpz.h>
   32 
   33 librpz_t *librpz;
   34 librpz_emsg_t librpz_lib_open_emsg;
   35 static void *librpz_handle;
   36 
   37 #define RPSDB_MAGIC    ISC_MAGIC('R', 'P', 'Z', 'F')
   38 #define VALID_RPSDB(rpsdb) ((rpsdb)->common.impmagic == RPSDB_MAGIC)
   39 
   40 #define RD_DB(r)      ((r)->private1)
   41 #define RD_CUR_RR(r)  ((r)->private2)
   42 #define RD_NEXT_RR(r) ((r)->resign)
   43 #define RD_COUNT(r)   ((r)->privateuint4)
   44 
   45 typedef struct {
   46     dns_rdatasetiter_t common;
   47     dns_rdatatype_t type;
   48     dns_rdataclass_t class;
   49     uint32_t ttl;
   50     uint count;
   51     librpz_idx_t next_rr;
   52 } rpsdb_rdatasetiter_t;
   53 
   54 static dns_dbmethods_t rpsdb_db_methods;
   55 static dns_rdatasetmethods_t rpsdb_rdataset_methods;
   56 static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods;
   57 
   58 static librpz_clist_t *clist;
   59 
   60 static isc_mutex_t dnsrps_mutex;
   61 
   62 static void
   63 dnsrps_lock(void *mutex0) {
   64     isc_mutex_t *mutex = mutex0;
   65 
   66     LOCK(mutex);
   67 }
   68 
   69 static void
   70 dnsrps_unlock(void *mutex0) {
   71     isc_mutex_t *mutex = mutex0;
   72 
   73     UNLOCK(mutex);
   74 }
   75 
   76 static void
   77 dnsrps_mutex_destroy(void *mutex0) {
   78     isc_mutex_t *mutex = mutex0;
   79 
   80     isc_mutex_destroy(mutex);
   81 }
   82 
   83 static void
   84 dnsrps_log_fnc(librpz_log_level_t level, void *ctxt, const char *buf) {
   85     int isc_level;
   86 
   87     UNUSED(ctxt);
   88 
   89     /* Setting librpz_log_level in the configuration overrides the
   90      * BIND9 logging levels. */
   91     if (level > LIBRPZ_LOG_TRACE1 &&
   92         level <= librpz->log_level_val(LIBRPZ_LOG_INVALID))
   93     {
   94         level = LIBRPZ_LOG_TRACE1;
   95     }
   96 
   97     switch (level) {
   98     case LIBRPZ_LOG_FATAL:
   99     case LIBRPZ_LOG_ERROR: /* errors */
  100     default:
  101         isc_level = DNS_RPZ_ERROR_LEVEL;
  102         break;
  103 
  104     case LIBRPZ_LOG_TRACE1: /* big events such as dnsrpzd starts */
  105         isc_level = DNS_RPZ_INFO_LEVEL;
  106         break;
  107 
  108     case LIBRPZ_LOG_TRACE2: /* smaller dnsrpzd zone transfers */
  109         isc_level = DNS_RPZ_DEBUG_LEVEL1;
  110         break;
  111 
  112     case LIBRPZ_LOG_TRACE3: /* librpz hits */
  113         isc_level = DNS_RPZ_DEBUG_LEVEL2;
  114         break;
  115 
  116     case LIBRPZ_LOG_TRACE4: /* librpz lookups */
  117         isc_level = DNS_RPZ_DEBUG_LEVEL3;
  118         break;
  119     }
  120     isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
  121               isc_level, "dnsrps: %s", buf);
  122 }
  123 
  124 /*
  125  * Start dnsrps for the entire server.
  126  *  This is not thread safe, but it is called by a single thread.
  127  */
  128 isc_result_t
  129 dns_dnsrps_server_create(void) {
  130     librpz_emsg_t emsg;
  131 
  132     INSIST(clist == NULL);
  133     INSIST(librpz == NULL);
  134     INSIST(librpz_handle == NULL);
  135 
  136     /*
  137      * Notice if librpz is available.
  138      */
  139     librpz = librpz_lib_open(&librpz_lib_open_emsg, &librpz_handle,
  140                  DNSRPS_LIBRPZ_PATH);
  141     /*
  142      * Stop now without complaining if librpz is not available.
  143      * Complain later if and when librpz is needed for a view with
  144      * "dnsrps-enable yes" (including the default view).
  145      */
  146     if (librpz == NULL) {
  147         return (ISC_R_SUCCESS);
  148     }
  149 
  150     isc_mutex_init(&dnsrps_mutex);
  151 
  152     librpz->set_log(dnsrps_log_fnc, NULL);
  153 
  154     clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock,
  155                      dnsrps_mutex_destroy, &dnsrps_mutex,
  156                      dns_lctx);
  157     if (clist == NULL) {
  158         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
  159                   DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
  160                   "dnsrps: %s", emsg.c);
  161         return (ISC_R_NOMEMORY);
  162     }
  163     return (ISC_R_SUCCESS);
  164 }
  165 
  166 /*
  167  * Stop dnsrps for the entire server.
  168  *  This is not thread safe.
  169  */
  170 void
  171 dns_dnsrps_server_destroy(void) {
  172     if (clist != NULL) {
  173         librpz->clist_detach(&clist);
  174     }
  175 
  176 #ifdef LIBRPZ_USE_DLOPEN
  177     if (librpz != NULL) {
  178         INSIST(librpz_handle != NULL);
  179         if (dlclose(librpz_handle) != 0) {
  180             isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
  181                       DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
  182                       "dnsrps: dlclose(): %s", dlerror());
  183         }
  184         librpz_handle = NULL;
  185     }
  186 #endif /* ifdef LIBRPZ_USE_DLOPEN */
  187 }
  188 
  189 /*
  190  * Ready dnsrps for a view.
  191  */
  192 isc_result_t
  193 dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr) {
  194     librpz_emsg_t emsg;
  195 
  196     isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
  197               DNS_RPZ_DEBUG_LEVEL3, "dnsrps configuration \"%s\"",
  198               rps_cstr);
  199 
  200     new->rps_client = librpz->client_create(&emsg, clist, rps_cstr, false);
  201     if (new->rps_client == NULL) {
  202         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
  203                   DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
  204                   "librpz->client_create(): %s", emsg.c);
  205         new->p.dnsrps_enabled = false;
  206         return (ISC_R_FAILURE);
  207     }
  208 
  209     new->p.dnsrps_enabled = true;
  210     return (ISC_R_SUCCESS);
  211 }
  212 
  213 /*
  214  * Connect to and start the dnsrps daemon, dnsrpzd.
  215  */
  216 isc_result_t
  217 dns_dnsrps_connect(dns_rpz_zones_t *rpzs) {
  218     librpz_emsg_t emsg;
  219 
  220     if (rpzs == NULL || !rpzs->p.dnsrps_enabled) {
  221         return (ISC_R_SUCCESS);
  222     }
  223 
  224     /*
  225      * Fail only if we failed to link to librpz.
  226      */
  227     if (librpz == NULL) {
  228         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
  229                   DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
  230                   "librpz->connect(): %s", librpz_lib_open_emsg.c);
  231         return (ISC_R_FAILURE);
  232     }
  233 
  234     if (!librpz->connect(&emsg, rpzs->rps_client, true)) {
  235         isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
  236                   DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
  237                   "librpz->connect(): %s", emsg.c);
  238         return (ISC_R_SUCCESS);
  239     }
  240 
  241     isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
  242               DNS_RPZ_INFO_LEVEL, "dnsrps: librpz version %s",
  243               librpz->version);
  244 
  245     return (ISC_R_SUCCESS);
  246 }
  247 
  248 /*
  249  * Get ready to try RPZ rewriting.
  250  */
  251 isc_result_t
  252 dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st,
  253             dns_rpz_zones_t *rpzs, const dns_name_t *qname,
  254             isc_mem_t *mctx, bool have_rd) {
  255     rpsdb_t *rpsdb;
  256 
  257     rpsdb = isc_mem_get(mctx, sizeof(*rpsdb));
  258     memset(rpsdb, 0, sizeof(*rpsdb));
  259 
  260     if (!librpz->rsp_create(emsg, &rpsdb->rsp, NULL, rpzs->rps_client,
  261                 have_rd, false))
  262     {
  263         isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
  264         return (DNS_R_SERVFAIL);
  265     }
  266     if (rpsdb->rsp == NULL) {
  267         isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
  268         return (DNS_R_DISALLOWED);
  269     }
  270 
  271     rpsdb->common.magic = DNS_DB_MAGIC;
  272     rpsdb->common.impmagic = RPSDB_MAGIC;
  273     rpsdb->common.methods = &rpsdb_db_methods;
  274     rpsdb->common.rdclass = dns_rdataclass_in;
  275     dns_name_init(&rpsdb->common.origin, NULL);
  276     isc_mem_attach(mctx, &rpsdb->common.mctx);
  277 
  278     rpsdb->ref_cnt = 1;
  279     rpsdb->qname = qname;
  280 
  281     st->rpsdb = &rpsdb->common;
  282     return (ISC_R_SUCCESS);
  283 }
  284 
  285 /*
  286  * Convert a dnsrps policy to a classic BIND9 RPZ policy.
  287  */
  288 dns_rpz_policy_t
  289 dns_dnsrps_2policy(librpz_policy_t rps_policy) {
  290     switch (rps_policy) {
  291     case LIBRPZ_POLICY_UNDEFINED:
  292         return (DNS_RPZ_POLICY_MISS);
  293     case LIBRPZ_POLICY_PASSTHRU:
  294         return (DNS_RPZ_POLICY_PASSTHRU);
  295     case LIBRPZ_POLICY_DROP:
  296         return (DNS_RPZ_POLICY_DROP);
  297     case LIBRPZ_POLICY_TCP_ONLY:
  298         return (DNS_RPZ_POLICY_TCP_ONLY);
  299     case LIBRPZ_POLICY_NXDOMAIN:
  300         return (DNS_RPZ_POLICY_NXDOMAIN);
  301     case LIBRPZ_POLICY_NODATA:
  302         return (DNS_RPZ_POLICY_NODATA);
  303     case LIBRPZ_POLICY_RECORD:
  304     case LIBRPZ_POLICY_CNAME:
  305         return (DNS_RPZ_POLICY_RECORD);
  306 
  307     case LIBRPZ_POLICY_DELETED:
  308     case LIBRPZ_POLICY_GIVEN:
  309     case LIBRPZ_POLICY_DISABLED:
  310     default:
  311         INSIST(0);
  312         ISC_UNREACHABLE();
  313     }
  314 }
  315 
  316 /*
  317  * Convert a dnsrps trigger to a classic BIND9 RPZ rewrite or trigger type.
  318  */
  319 dns_rpz_type_t
  320 dns_dnsrps_trig2type(librpz_trig_t trig) {
  321     switch (trig) {
  322     case LIBRPZ_TRIG_BAD:
  323     default:
  324         return (DNS_RPZ_TYPE_BAD);
  325     case LIBRPZ_TRIG_CLIENT_IP:
  326         return (DNS_RPZ_TYPE_CLIENT_IP);
  327     case LIBRPZ_TRIG_QNAME:
  328         return (DNS_RPZ_TYPE_QNAME);
  329     case LIBRPZ_TRIG_IP:
  330         return (DNS_RPZ_TYPE_IP);
  331     case LIBRPZ_TRIG_NSDNAME:
  332         return (DNS_RPZ_TYPE_NSDNAME);
  333     case LIBRPZ_TRIG_NSIP:
  334         return (DNS_RPZ_TYPE_NSIP);
  335     }
  336 }
  337 
  338 /*
  339  * Convert a classic BIND9 RPZ rewrite or trigger type to a librpz trigger type.
  340  */
  341 librpz_trig_t
  342 dns_dnsrps_type2trig(dns_rpz_type_t type) {
  343     switch (type) {
  344     case DNS_RPZ_TYPE_BAD:
  345     default:
  346         return (LIBRPZ_TRIG_BAD);
  347     case DNS_RPZ_TYPE_CLIENT_IP:
  348         return (LIBRPZ_TRIG_CLIENT_IP);
  349     case DNS_RPZ_TYPE_QNAME:
  350         return (LIBRPZ_TRIG_QNAME);
  351     case DNS_RPZ_TYPE_IP:
  352         return (LIBRPZ_TRIG_IP);
  353     case DNS_RPZ_TYPE_NSDNAME:
  354         return (LIBRPZ_TRIG_NSDNAME);
  355     case DNS_RPZ_TYPE_NSIP:
  356         return (LIBRPZ_TRIG_NSIP);
  357     }
  358 }
  359 
  360 static void
  361 rpsdb_attach(dns_db_t *source, dns_db_t **targetp) {
  362     rpsdb_t *rpsdb = (rpsdb_t *)source;
  363 
  364     REQUIRE(VALID_RPSDB(rpsdb));
  365 
  366     /*
  367      * Use a simple count because only one thread uses any single rpsdb_t
  368      */
  369     ++rpsdb->ref_cnt;
  370     *targetp = source;
  371 }
  372 
  373 static void
  374 rpsdb_detach(dns_db_t **dbp) {
  375     rpsdb_t *rpsdb = (rpsdb_t *)*dbp;
  376 
  377     REQUIRE(VALID_RPSDB(rpsdb));
  378     REQUIRE(rpsdb->ref_cnt > 0);
  379 
  380     *dbp = NULL;
  381 
  382     /*
  383      * Simple count because only one thread uses a rpsdb_t.
  384      */
  385     if (--rpsdb->ref_cnt != 0) {
  386         return;
  387     }
  388 
  389     librpz->rsp_detach(&rpsdb->rsp);
  390     rpsdb->common.impmagic = 0;
  391     isc_mem_putanddetach(&rpsdb->common.mctx, rpsdb, sizeof(*rpsdb));
  392 }
  393 
  394 static void
  395 rpsdb_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
  396     rpsdb_t *rpsdb = (rpsdb_t *)db;
  397 
  398     REQUIRE(VALID_RPSDB(rpsdb));
  399     REQUIRE(targetp != NULL && *targetp == NULL);
  400     REQUIRE(source == &rpsdb->origin_node || source == &rpsdb->data_node);
  401 
  402     /*
  403      * Simple count because only one thread uses a rpsdb_t.
  404      */
  405     ++rpsdb->ref_cnt;
  406     *targetp = source;
  407 }
  408 
  409 static void
  410 rpsdb_detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
  411     rpsdb_t *rpsdb = (rpsdb_t *)db;
  412 
  413     REQUIRE(VALID_RPSDB(rpsdb));
  414     REQUIRE(*targetp == &rpsdb->origin_node ||
  415         *targetp == &rpsdb->data_node);
  416 
  417     *targetp = NULL;
  418     rpsdb_detach(&db);
  419 }
  420 
  421 static isc_result_t
  422 rpsdb_findnode(dns_db_t *db, const dns_name_t *name, bool create,
  423            dns_dbnode_t **nodep) {
  424     rpsdb_t *rpsdb = (rpsdb_t *)db;
  425     dns_db_t *dbp;
  426 
  427     REQUIRE(VALID_RPSDB(rpsdb));
  428     REQUIRE(nodep != NULL && *nodep == NULL);
  429     REQUIRE(!create);
  430 
  431     /*
  432      * A fake/shim rpsdb has two nodes.
  433      * One is the origin to support query_addsoa() in bin/named/query.c.
  434      * The other contains rewritten RRs.
  435      */
  436     if (dns_name_equal(name, &db->origin)) {
  437         *nodep = &rpsdb->origin_node;
  438     } else {
  439         *nodep = &rpsdb->data_node;
  440     }
  441     dbp = NULL;
  442     rpsdb_attach(db, &dbp);
  443 
  444     return (ISC_R_SUCCESS);
  445 }
  446 
  447 static void
  448 rpsdb_bind_rdataset(dns_rdataset_t *rdataset, uint count, librpz_idx_t next_rr,
  449             dns_rdatatype_t type, uint16_t class, uint32_t ttl,
  450             rpsdb_t *rpsdb) {
  451     dns_db_t *dbp;
  452 
  453     INSIST(rdataset->methods == NULL); /* We must be disassociated. */
  454     REQUIRE(type != dns_rdatatype_none);
  455 
  456     rdataset->methods = &rpsdb_rdataset_methods;
  457     rdataset->rdclass = class;
  458     rdataset->type = type;
  459     rdataset->ttl = ttl;
  460     dbp = NULL;
  461     dns_db_attach(&rpsdb->common, &dbp);
  462     RD_DB(rdataset) = dbp;
  463     RD_COUNT(rdataset) = count;
  464     RD_NEXT_RR(rdataset) = next_rr;
  465     RD_CUR_RR(rdataset) = NULL;
  466 }
  467 
  468 static isc_result_t
  469 rpsdb_bind_soa(dns_rdataset_t *rdataset, rpsdb_t *rpsdb) {
  470     uint32_t ttl;
  471     librpz_emsg_t emsg;
  472 
  473     if (!librpz->rsp_soa(&emsg, &ttl, NULL, NULL, &rpsdb->result,
  474                  rpsdb->rsp)) {
  475         librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  476         return (DNS_R_SERVFAIL);
  477     }
  478     rpsdb_bind_rdataset(rdataset, 1, LIBRPZ_IDX_BAD, dns_rdatatype_soa,
  479                 dns_rdataclass_in, ttl, rpsdb);
  480     return (ISC_R_SUCCESS);
  481 }
  482 
  483 /*
  484  * Forge an rdataset of the desired type from a librpz result.
  485  * This is written for simplicity instead of speed, because RPZ rewriting
  486  * should be rare compared to normal BIND operations.
  487  */
  488 static isc_result_t
  489 rpsdb_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  490            dns_rdatatype_t type, dns_rdatatype_t covers,
  491            isc_stdtime_t now, dns_rdataset_t *rdataset,
  492            dns_rdataset_t *sigrdataset) {
  493     rpsdb_t *rpsdb = (rpsdb_t *)db;
  494     dns_rdatatype_t foundtype;
  495     dns_rdataclass_t class;
  496     uint32_t ttl;
  497     uint count;
  498     librpz_emsg_t emsg;
  499 
  500     UNUSED(version);
  501     UNUSED(covers);
  502     UNUSED(now);
  503     UNUSED(sigrdataset);
  504 
  505     REQUIRE(VALID_RPSDB(rpsdb));
  506 
  507     if (node == &rpsdb->origin_node) {
  508         if (type == dns_rdatatype_any) {
  509             return (ISC_R_SUCCESS);
  510         }
  511         if (type == dns_rdatatype_soa) {
  512             return (rpsdb_bind_soa(rdataset, rpsdb));
  513         }
  514         return (DNS_R_NXRRSET);
  515     }
  516 
  517     REQUIRE(node == &rpsdb->data_node);
  518 
  519     switch (rpsdb->result.policy) {
  520     case LIBRPZ_POLICY_UNDEFINED:
  521     case LIBRPZ_POLICY_DELETED:
  522     case LIBRPZ_POLICY_PASSTHRU:
  523     case LIBRPZ_POLICY_DROP:
  524     case LIBRPZ_POLICY_TCP_ONLY:
  525     case LIBRPZ_POLICY_GIVEN:
  526     case LIBRPZ_POLICY_DISABLED:
  527     default:
  528         librpz->log(LIBRPZ_LOG_ERROR, NULL,
  529                 "impossible dnsrps policy %d at %s:%d",
  530                 rpsdb->result.policy, __FILE__, __LINE__);
  531         return (DNS_R_SERVFAIL);
  532 
  533     case LIBRPZ_POLICY_NXDOMAIN:
  534         return (DNS_R_NXDOMAIN);
  535 
  536     case LIBRPZ_POLICY_NODATA:
  537         return (DNS_R_NXRRSET);
  538 
  539     case LIBRPZ_POLICY_RECORD:
  540     case LIBRPZ_POLICY_CNAME:
  541         break;
  542     }
  543 
  544     if (type == dns_rdatatype_soa) {
  545         return (rpsdb_bind_soa(rdataset, rpsdb));
  546     }
  547 
  548     /*
  549      * There is little to do for an ANY query.
  550      */
  551     if (type == dns_rdatatype_any) {
  552         return (ISC_R_SUCCESS);
  553     }
  554 
  555     /*
  556      * Reset to the start of the RRs.
  557      * This function is only used after a policy has been chosen,
  558      * and so without caring whether it is after recursion.
  559      */
  560     if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
  561         librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  562         return (DNS_R_SERVFAIL);
  563     }
  564     if (!librpz->rsp_rr(&emsg, &foundtype, &class, &ttl, NULL,
  565                 &rpsdb->result, rpsdb->qname->ndata,
  566                 rpsdb->qname->length, rpsdb->rsp))
  567     {
  568         librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  569         return (DNS_R_SERVFAIL);
  570     }
  571     REQUIRE(foundtype != dns_rdatatype_none);
  572 
  573     /*
  574      * Ho many of the target RR type are available?
  575      */
  576     count = 0;
  577     do {
  578         if (type == foundtype || type == dns_rdatatype_any) {
  579             ++count;
  580         }
  581 
  582         if (!librpz->rsp_rr(&emsg, &foundtype, NULL, NULL, NULL,
  583                     &rpsdb->result, rpsdb->qname->ndata,
  584                     rpsdb->qname->length, rpsdb->rsp))
  585         {
  586             librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  587             return (DNS_R_SERVFAIL);
  588         }
  589     } while (foundtype != dns_rdatatype_none);
  590     if (count == 0) {
  591         return (DNS_R_NXRRSET);
  592     }
  593     rpsdb_bind_rdataset(rdataset, count, rpsdb->result.next_rr, type, class,
  594                 ttl, rpsdb);
  595     return (ISC_R_SUCCESS);
  596 }
  597 
  598 static isc_result_t
  599 rpsdb_finddb(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
  600          dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
  601          dns_dbnode_t **nodep, dns_name_t *foundname,
  602          dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
  603     dns_dbnode_t *node;
  604 
  605     UNUSED(version);
  606     UNUSED(options);
  607     UNUSED(now);
  608     UNUSED(sigrdataset);
  609 
  610     if (nodep == NULL) {
  611         node = NULL;
  612         nodep = &node;
  613     }
  614     rpsdb_findnode(db, name, false, nodep);
  615     dns_name_copynf(name, foundname);
  616     return (rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0, rdataset,
  617                    sigrdataset));
  618 }
  619 
  620 static isc_result_t
  621 rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  622            isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
  623     rpsdb_t *rpsdb = (rpsdb_t *)db;
  624     rpsdb_rdatasetiter_t *rpsdb_iter;
  625 
  626     UNUSED(version);
  627     UNUSED(now);
  628 
  629     REQUIRE(VALID_RPSDB(rpsdb));
  630     REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node);
  631 
  632     rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter));
  633 
  634     memset(rpsdb_iter, 0, sizeof(*rpsdb_iter));
  635     rpsdb_iter->common.magic = DNS_RDATASETITER_MAGIC;
  636     rpsdb_iter->common.methods = &rpsdb_rdatasetiter_methods;
  637     rpsdb_iter->common.db = db;
  638     rpsdb_attachnode(db, node, &rpsdb_iter->common.node);
  639 
  640     *iteratorp = &rpsdb_iter->common;
  641 
  642     return (ISC_R_SUCCESS);
  643 }
  644 
  645 static bool
  646 rpsdb_issecure(dns_db_t *db) {
  647     UNUSED(db);
  648 
  649     return (false);
  650 }
  651 
  652 static isc_result_t
  653 rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
  654     rpsdb_t *rpsdb = (rpsdb_t *)db;
  655 
  656     REQUIRE(VALID_RPSDB(rpsdb));
  657     REQUIRE(nodep != NULL && *nodep == NULL);
  658 
  659     rpsdb_attachnode(db, &rpsdb->origin_node, nodep);
  660     return (ISC_R_SUCCESS);
  661 }
  662 
  663 static void
  664 rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset) {
  665     dns_db_t *db;
  666 
  667     /*
  668      * Detach the last RR delivered.
  669      */
  670     if (RD_CUR_RR(rdataset) != NULL) {
  671         free(RD_CUR_RR(rdataset));
  672         RD_CUR_RR(rdataset) = NULL;
  673     }
  674 
  675     db = RD_DB(rdataset);
  676     RD_DB(rdataset) = NULL;
  677     dns_db_detach(&db);
  678 }
  679 
  680 static isc_result_t
  681 rpsdb_rdataset_next(dns_rdataset_t *rdataset) {
  682     rpsdb_t *rpsdb;
  683     uint16_t type;
  684     dns_rdataclass_t class;
  685     librpz_rr_t *rr;
  686     librpz_emsg_t emsg;
  687 
  688     rpsdb = RD_DB(rdataset);
  689 
  690     /*
  691      * Detach the previous RR.
  692      */
  693     if (RD_CUR_RR(rdataset) != NULL) {
  694         free(RD_CUR_RR(rdataset));
  695         RD_CUR_RR(rdataset) = NULL;
  696     }
  697 
  698     /*
  699      * Get the next RR of the specified type.
  700      * SOAs differ.
  701      */
  702     if (rdataset->type == dns_rdatatype_soa) {
  703         if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL) {
  704             return (ISC_R_NOMORE);
  705         }
  706         RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL;
  707         if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL, &rpsdb->result,
  708                      rpsdb->rsp)) {
  709             librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  710             return (DNS_R_SERVFAIL);
  711         }
  712         RD_CUR_RR(rdataset) = rr;
  713         return (ISC_R_SUCCESS);
  714     }
  715 
  716     rpsdb->result.next_rr = RD_NEXT_RR(rdataset);
  717     for (;;) {
  718         if (!librpz->rsp_rr(&emsg, &type, &class, NULL, &rr,
  719                     &rpsdb->result, rpsdb->qname->ndata,
  720                     rpsdb->qname->length, rpsdb->rsp))
  721         {
  722             librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  723             return (DNS_R_SERVFAIL);
  724         }
  725         if (rdataset->type == type && rdataset->rdclass == class) {
  726             RD_CUR_RR(rdataset) = rr;
  727             RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
  728             return (ISC_R_SUCCESS);
  729         }
  730         if (type == dns_rdatatype_none) {
  731             return (ISC_R_NOMORE);
  732         }
  733         free(rr);
  734     }
  735 }
  736 
  737 static isc_result_t
  738 rpsdb_rdataset_first(dns_rdataset_t *rdataset) {
  739     rpsdb_t *rpsdb;
  740     librpz_emsg_t emsg;
  741 
  742     rpsdb = RD_DB(rdataset);
  743     REQUIRE(VALID_RPSDB(rpsdb));
  744 
  745     if (RD_CUR_RR(rdataset) != NULL) {
  746         free(RD_CUR_RR(rdataset));
  747         RD_CUR_RR(rdataset) = NULL;
  748     }
  749 
  750     if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
  751         librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  752         return (DNS_R_SERVFAIL);
  753     }
  754     if (rdataset->type == dns_rdatatype_soa) {
  755         RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD;
  756     } else {
  757         RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
  758     }
  759 
  760     return (rpsdb_rdataset_next(rdataset));
  761 }
  762 
  763 static void
  764 rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
  765     rpsdb_t *rpsdb;
  766     librpz_rr_t *rr;
  767     isc_region_t r;
  768 
  769     rpsdb = RD_DB(rdataset);
  770     REQUIRE(VALID_RPSDB(rpsdb));
  771     rr = RD_CUR_RR(rdataset);
  772     REQUIRE(rr != NULL);
  773 
  774     r.length = ntohs(rr->rdlength);
  775     r.base = rr->rdata;
  776     dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r);
  777 }
  778 
  779 static void
  780 rpsdb_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  781     rpsdb_t *rpsdb;
  782     dns_db_t *dbp;
  783 
  784     INSIST(!ISC_LINK_LINKED(target, link));
  785     *target = *source;
  786     ISC_LINK_INIT(target, link);
  787     rpsdb = RD_DB(source);
  788     REQUIRE(VALID_RPSDB(rpsdb));
  789     dbp = NULL;
  790     dns_db_attach(&rpsdb->common, &dbp);
  791     RD_DB(target) = dbp;
  792     RD_CUR_RR(target) = NULL;
  793     RD_NEXT_RR(target) = LIBRPZ_IDX_NULL;
  794 }
  795 
  796 static unsigned int
  797 rpsdb_rdataset_count(dns_rdataset_t *rdataset) {
  798     rpsdb_t *rpsdb;
  799 
  800     rpsdb = RD_DB(rdataset);
  801     REQUIRE(VALID_RPSDB(rpsdb));
  802 
  803     return (RD_COUNT(rdataset));
  804 }
  805 
  806 static void
  807 rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
  808     rpsdb_t *rpsdb;
  809     dns_rdatasetiter_t *iterator;
  810     isc_mem_t *mctx;
  811 
  812     iterator = *iteratorp;
  813     *iteratorp = NULL;
  814     rpsdb = (rpsdb_t *)iterator->db;
  815     REQUIRE(VALID_RPSDB(rpsdb));
  816 
  817     mctx = iterator->db->mctx;
  818     dns_db_detachnode(iterator->db, &iterator->node);
  819     isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t));
  820 }
  821 
  822 static isc_result_t
  823 rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter) {
  824     rpsdb_t *rpsdb;
  825     rpsdb_rdatasetiter_t *rpsdb_iter;
  826     dns_rdatatype_t next_type, type;
  827     dns_rdataclass_t next_class, class;
  828     uint32_t ttl;
  829     librpz_emsg_t emsg;
  830 
  831     rpsdb = (rpsdb_t *)iter->db;
  832     REQUIRE(VALID_RPSDB(rpsdb));
  833     rpsdb_iter = (rpsdb_rdatasetiter_t *)iter;
  834 
  835     /*
  836      * This function is only used after a policy has been chosen,
  837      * and so without caring whether it is after recursion.
  838      */
  839     if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
  840         librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  841         return (DNS_R_SERVFAIL);
  842     }
  843     /*
  844      * Find the next class and type after the current class and type
  845      * among the RRs in current result.
  846      * As a side effect, count the number of those RRs.
  847      */
  848     rpsdb_iter->count = 0;
  849     next_class = dns_rdataclass_reserved0;
  850     next_type = dns_rdatatype_none;
  851     for (;;) {
  852         if (!librpz->rsp_rr(&emsg, &type, &class, &ttl, NULL,
  853                     &rpsdb->result, rpsdb->qname->ndata,
  854                     rpsdb->qname->length, rpsdb->rsp))
  855         {
  856             librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
  857             return (DNS_R_SERVFAIL);
  858         }
  859         if (type == dns_rdatatype_none) {
  860             if (next_type == dns_rdatatype_none) {
  861                 return (ISC_R_NOMORE);
  862             }
  863             rpsdb_iter->type = next_type;
  864             rpsdb_iter->class = next_class;
  865             return (ISC_R_SUCCESS);
  866         }
  867         /*
  868          * Skip RRs with the current class and type or before.
  869          */
  870         if (rpsdb_iter->class > class ||
  871             (rpsdb_iter->class = class && rpsdb_iter->type >= type))
  872         {
  873             continue;
  874         }
  875         if (next_type == dns_rdatatype_none || next_class > class ||
  876             (next_class == class && next_type > type))
  877         {
  878             /*
  879              * This is the first of a subsequent class and type.
  880              */
  881             next_type = type;
  882             next_class = class;
  883             rpsdb_iter->ttl = ttl;
  884             rpsdb_iter->count = 1;
  885             rpsdb_iter->next_rr = rpsdb->result.next_rr;
  886         } else if (next_type == type && next_class == class) {
  887             ++rpsdb_iter->count;
  888         }
  889     }
  890 }
  891 
  892 static isc_result_t
  893 rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator) {
  894     rpsdb_t *rpsdb;
  895     rpsdb_rdatasetiter_t *rpsdb_iter;
  896 
  897     rpsdb = (rpsdb_t *)iterator->db;
  898     REQUIRE(VALID_RPSDB(rpsdb));
  899     rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
  900 
  901     rpsdb_iter->type = dns_rdatatype_none;
  902     rpsdb_iter->class = dns_rdataclass_reserved0;
  903     return (rpsdb_rdatasetiter_next(iterator));
  904 }
  905 
  906 static void
  907 rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator,
  908                dns_rdataset_t *rdataset) {
  909     rpsdb_t *rpsdb;
  910     rpsdb_rdatasetiter_t *rpsdb_iter;
  911 
  912     rpsdb = (rpsdb_t *)iterator->db;
  913     REQUIRE(VALID_RPSDB(rpsdb));
  914     rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
  915     REQUIRE(rpsdb_iter->type != dns_rdatatype_none);
  916 
  917     rpsdb_bind_rdataset(rdataset, rpsdb_iter->count, rpsdb_iter->next_rr,
  918                 rpsdb_iter->type, rpsdb_iter->class,
  919                 rpsdb_iter->ttl, rpsdb);
  920 }
  921 
  922 static dns_dbmethods_t rpsdb_db_methods = {
  923     rpsdb_attach,
  924     rpsdb_detach,
  925     NULL, /* beginload */
  926     NULL, /* endload */
  927     NULL, /* serialize */
  928     NULL, /* dump */
  929     NULL, /* currentversion */
  930     NULL, /* newversion */
  931     NULL, /* attachversion */
  932     NULL, /* closeversion */
  933     rpsdb_findnode,
  934     rpsdb_finddb,
  935     NULL, /* findzonecut*/
  936     rpsdb_attachnode,
  937     rpsdb_detachnode,
  938     NULL, /* expirenode */
  939     NULL, /* printnode */
  940     NULL, /* createiterator */
  941     rpsdb_findrdataset,
  942     rpsdb_allrdatasets,
  943     NULL, /* addrdataset */
  944     NULL, /* subtractrdataset */
  945     NULL, /* deleterdataset */
  946     rpsdb_issecure,
  947     NULL, /* nodecount */
  948     NULL, /* ispersistent */
  949     NULL, /* overmem */
  950     NULL, /* settask */
  951     rpsdb_getoriginnode,
  952     NULL, /* transfernode */
  953     NULL, /* getnsec3parameters */
  954     NULL, /* findnsec3node */
  955     NULL, /* setsigningtime */
  956     NULL, /* getsigningtime */
  957     NULL, /* resigned */
  958     NULL, /* isdnssec */
  959     NULL, /* getrrsetstats */
  960     NULL, /* rpz_attach */
  961     NULL, /* rpz_ready */
  962     NULL, /* findnodeext */
  963     NULL, /* findext */
  964     NULL, /* setcachestats */
  965     NULL, /* hashsize */
  966     NULL, /* nodefullname */
  967     NULL, /* getsize */
  968     NULL, /* setservestalettl */
  969     NULL, /* getservestalettl */
  970     NULL, /* setgluecachestats */
  971     NULL  /* adjusthashsize */
  972 };
  973 
  974 static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
  975     rpsdb_rdataset_disassociate,
  976     rpsdb_rdataset_first,
  977     rpsdb_rdataset_next,
  978     rpsdb_rdataset_current,
  979     rpsdb_rdataset_clone,
  980     rpsdb_rdataset_count,
  981     NULL,
  982     NULL,
  983     NULL,
  984     NULL,
  985     NULL,
  986     NULL,
  987     NULL,
  988     NULL,
  989     NULL,
  990     NULL
  991 };
  992 
  993 static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = {
  994     rpsdb_rdatasetiter_destroy, rpsdb_rdatasetiter_first,
  995     rpsdb_rdatasetiter_next, rpsdb_rdatasetiter_current
  996 };
  997 
  998 #endif /* USE_DNSRPS */