"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/ns/query.c" (4 Sep 2020, 312021 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.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 "query.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 #include <string.h>
   17 
   18 #include <isc/hex.h>
   19 #include <isc/mem.h>
   20 #include <isc/once.h>
   21 #include <isc/print.h>
   22 #include <isc/random.h>
   23 #include <isc/rwlock.h>
   24 #include <isc/serial.h>
   25 #include <isc/stats.h>
   26 #include <isc/string.h>
   27 #include <isc/thread.h>
   28 #include <isc/util.h>
   29 
   30 #include <dns/adb.h>
   31 #include <dns/badcache.h>
   32 #include <dns/byaddr.h>
   33 #include <dns/cache.h>
   34 #include <dns/db.h>
   35 #include <dns/dlz.h>
   36 #include <dns/dns64.h>
   37 #include <dns/dnsrps.h>
   38 #include <dns/dnssec.h>
   39 #include <dns/events.h>
   40 #include <dns/keytable.h>
   41 #include <dns/message.h>
   42 #include <dns/ncache.h>
   43 #include <dns/nsec.h>
   44 #include <dns/nsec3.h>
   45 #include <dns/order.h>
   46 #include <dns/rdata.h>
   47 #include <dns/rdataclass.h>
   48 #include <dns/rdatalist.h>
   49 #include <dns/rdataset.h>
   50 #include <dns/rdatasetiter.h>
   51 #include <dns/rdatastruct.h>
   52 #include <dns/rdatatype.h>
   53 #include <dns/resolver.h>
   54 #include <dns/result.h>
   55 #include <dns/stats.h>
   56 #include <dns/tkey.h>
   57 #include <dns/types.h>
   58 #include <dns/view.h>
   59 #include <dns/zone.h>
   60 #include <dns/zt.h>
   61 
   62 #include <ns/client.h>
   63 #include <ns/hooks.h>
   64 #include <ns/interfacemgr.h>
   65 #include <ns/log.h>
   66 #include <ns/server.h>
   67 #include <ns/sortlist.h>
   68 #include <ns/stats.h>
   69 #include <ns/xfrout.h>
   70 
   71 #if 0
   72 /*
   73  * It has been recommended that DNS64 be changed to return excluded
   74  * AAAA addresses if DNS64 synthesis does not occur.  This minimises
   75  * the impact on the lookup results.  While most DNS AAAA lookups are
   76  * done to send IP packets to a host, not all of them are and filtering
   77  * excluded addresses has a negative impact on those uses.
   78  */
   79 #define dns64_bis_return_excluded_addresses 1
   80 #endif /* if 0 */
   81 
   82 /*%
   83  * Maximum number of chained queries before we give up
   84  * to prevent CNAME loops.
   85  */
   86 #define MAX_RESTARTS 16
   87 
   88 #define QUERY_ERROR(qctx, r)                \
   89     do {                                \
   90         qctx->result = r;           \
   91         qctx->want_restart = false; \
   92         qctx->line = __LINE__;      \
   93     } while (0)
   94 
   95 /*% Partial answer? */
   96 #define PARTIALANSWER(c) \
   97     (((c)->query.attributes & NS_QUERYATTR_PARTIALANSWER) != 0)
   98 /*% Use Cache? */
   99 #define USECACHE(c) (((c)->query.attributes & NS_QUERYATTR_CACHEOK) != 0)
  100 /*% Recursion OK? */
  101 #define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
  102 /*% Recursing? */
  103 #define RECURSING(c) (((c)->query.attributes & NS_QUERYATTR_RECURSING) != 0)
  104 /*% Want Recursion? */
  105 #define WANTRECURSION(c) \
  106     (((c)->query.attributes & NS_QUERYATTR_WANTRECURSION) != 0)
  107 /*% Is TCP? */
  108 #define TCP(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
  109 
  110 /*% Want DNSSEC? */
  111 #define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
  112 /*% Want WANTAD? */
  113 #define WANTAD(c) (((c)->attributes & NS_CLIENTATTR_WANTAD) != 0)
  114 /*% Client presented a valid COOKIE. */
  115 #define HAVECOOKIE(c) (((c)->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)
  116 /*% Client presented a COOKIE. */
  117 #define WANTCOOKIE(c) (((c)->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
  118 /*% Client presented a CLIENT-SUBNET option. */
  119 #define HAVEECS(c) (((c)->attributes & NS_CLIENTATTR_HAVEECS) != 0)
  120 /*% No authority? */
  121 #define NOAUTHORITY(c) (((c)->query.attributes & NS_QUERYATTR_NOAUTHORITY) != 0)
  122 /*% No additional? */
  123 #define NOADDITIONAL(c) \
  124     (((c)->query.attributes & NS_QUERYATTR_NOADDITIONAL) != 0)
  125 /*% Secure? */
  126 #define SECURE(c) (((c)->query.attributes & NS_QUERYATTR_SECURE) != 0)
  127 /*% DNS64 A lookup? */
  128 #define DNS64(c) (((c)->query.attributes & NS_QUERYATTR_DNS64) != 0)
  129 
  130 #define DNS64EXCLUDE(c) \
  131     (((c)->query.attributes & NS_QUERYATTR_DNS64EXCLUDE) != 0)
  132 
  133 #define REDIRECT(c) (((c)->query.attributes & NS_QUERYATTR_REDIRECT) != 0)
  134 
  135 /*% Does the rdataset 'r' have an attached 'No QNAME Proof'? */
  136 #define NOQNAME(r) (((r)->attributes & DNS_RDATASETATTR_NOQNAME) != 0)
  137 
  138 /*% Does the rdataset 'r' contain a stale answer? */
  139 #define STALE(r) (((r)->attributes & DNS_RDATASETATTR_STALE) != 0)
  140 
  141 #ifdef WANT_QUERYTRACE
  142 static inline void
  143 client_trace(ns_client_t *client, int level, const char *message) {
  144     if (client != NULL && client->query.qname != NULL) {
  145         if (isc_log_wouldlog(ns_lctx, level)) {
  146             char qbuf[DNS_NAME_FORMATSIZE];
  147             char tbuf[DNS_RDATATYPE_FORMATSIZE];
  148             dns_name_format(client->query.qname, qbuf,
  149                     sizeof(qbuf));
  150             dns_rdatatype_format(client->query.qtype, tbuf,
  151                          sizeof(tbuf));
  152             isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
  153                       NS_LOGMODULE_QUERY, level,
  154                       "query client=%p thread=0x%lx "
  155                       "(%s/%s): %s",
  156                       client, (unsigned long)isc_thread_self(),
  157                       qbuf, tbuf, message);
  158         }
  159     } else {
  160         isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT,
  161                   NS_LOGMODULE_QUERY, level,
  162                   "query client=%p thread=0x%lx "
  163                   "(<unknown-query>): %s",
  164                   client, (unsigned long)isc_thread_self(),
  165                   message);
  166     }
  167 }
  168 #define CTRACE(l, m)  client_trace(client, l, m)
  169 #define CCTRACE(l, m) client_trace(qctx->client, l, m)
  170 #else /* ifdef WANT_QUERYTRACE */
  171 #define CTRACE(l, m)  ((void)m)
  172 #define CCTRACE(l, m) ((void)m)
  173 #endif /* WANT_QUERYTRACE */
  174 
  175 #define DNS_GETDB_NOEXACT   0x01U
  176 #define DNS_GETDB_NOLOG     0x02U
  177 #define DNS_GETDB_PARTIAL   0x04U
  178 #define DNS_GETDB_IGNOREACL 0x08U
  179 
  180 #define PENDINGOK(x) (((x)&DNS_DBFIND_PENDINGOK) != 0)
  181 
  182 #define SFCACHE_CDFLAG 0x1
  183 
  184 /*
  185  * These have the same semantics as:
  186  *
  187  *  foo_attach(b, a);
  188  *  foo_detach(&a);
  189  *
  190  * without the locking and magic testing.
  191  *
  192  * We use SAVE and RESTORE as that shows the operation being performed.
  193  */
  194 #define SAVE(a, b)                 \
  195     do {                       \
  196         INSIST(a == NULL); \
  197         a = b;             \
  198         b = NULL;          \
  199     } while (0)
  200 #define RESTORE(a, b) SAVE(a, b)
  201 
  202 static bool
  203 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
  204      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
  205 
  206 static void
  207 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
  208                dns_dbversion_t *version, ns_client_t *client,
  209                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
  210                dns_name_t *fname, bool exact, dns_name_t *found);
  211 
  212 static inline void
  213 log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
  214 
  215 static void
  216 rpz_st_clear(ns_client_t *client);
  217 
  218 static bool
  219 rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
  220           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
  221 
  222 static void
  223 log_noexistnodata(void *val, int level, const char *fmt, ...)
  224     ISC_FORMAT_PRINTF(3, 4);
  225 
  226 /*
  227  * Return the hooktable in use with 'qctx', or if there isn't one
  228  * set, return the default hooktable.
  229  */
  230 static inline ns_hooktable_t *
  231 get_hooktab(query_ctx_t *qctx) {
  232     if (qctx == NULL || qctx->view == NULL || qctx->view->hooktable == NULL)
  233     {
  234         return (ns__hook_table);
  235     }
  236 
  237     return (qctx->view->hooktable);
  238 }
  239 
  240 /*
  241  * Call the specified hook function in every configured module that implements
  242  * that function. If any hook function returns NS_HOOK_RETURN, we
  243  * set 'result' and terminate processing by jumping to the 'cleanup' tag.
  244  *
  245  * (Note that a hook function may set the 'result' to ISC_R_SUCCESS but
  246  * still terminate processing within the calling function. That's why this
  247  * is a macro instead of an inline function; it needs to be able to use
  248  * 'goto cleanup' regardless of the return value.)
  249  */
  250 #define CALL_HOOK(_id, _qctx)                                       \
  251     do {                                                        \
  252         isc_result_t _res;                                  \
  253         ns_hooktable_t *_tab = get_hooktab(_qctx);          \
  254         ns_hook_t *_hook;                                   \
  255         _hook = ISC_LIST_HEAD((*_tab)[_id]);                \
  256         while (_hook != NULL) {                             \
  257             ns_hook_action_t _func = _hook->action;     \
  258             void *_data = _hook->action_data;           \
  259             INSIST(_func != NULL);                      \
  260             switch (_func(_qctx, _data, &_res)) {       \
  261             case NS_HOOK_CONTINUE:                      \
  262                 _hook = ISC_LIST_NEXT(_hook, link); \
  263                 break;                              \
  264             case NS_HOOK_RETURN:                        \
  265                 result = _res;                      \
  266                 goto cleanup;                       \
  267             default:                                    \
  268                 INSIST(0);                          \
  269             }                                           \
  270         }                                                   \
  271     } while (false)
  272 
  273 /*
  274  * Call the specified hook function in every configured module that
  275  * implements that function. All modules are called; hook function return
  276  * codes are ignored. This is intended for use with initialization and
  277  * destruction calls which *must* run in every configured module.
  278  *
  279  * (This could be implemented as an inline void function, but is left as a
  280  * macro for symmetry with CALL_HOOK above.)
  281  */
  282 #define CALL_HOOK_NORETURN(_id, _qctx)                          \
  283     do {                                                    \
  284         isc_result_t _res;                              \
  285         ns_hooktable_t *_tab = get_hooktab(_qctx);      \
  286         ns_hook_t *_hook;                               \
  287         _hook = ISC_LIST_HEAD((*_tab)[_id]);            \
  288         while (_hook != NULL) {                         \
  289             ns_hook_action_t _func = _hook->action; \
  290             void *_data = _hook->action_data;       \
  291             INSIST(_func != NULL);                  \
  292             _func(_qctx, _data, &_res);             \
  293             _hook = ISC_LIST_NEXT(_hook, link);     \
  294         }                                               \
  295     } while (false)
  296 
  297 /*
  298  * The functions defined below implement the query logic that previously lived
  299  * in the single very complex function query_find().  The query_ctx_t structure
  300  * defined in <ns/query.h> maintains state from function to function.  The call
  301  * flow for the general query processing algorithm is described below:
  302  *
  303  * 1. Set up query context and other resources for a client
  304  *    query (query_setup())
  305  *
  306  * 2. Start the search (ns__query_start())
  307  *
  308  * 3. Identify authoritative data sources which may have an answer;
  309  *    search them (query_lookup()). If an answer is found, go to 7.
  310  *
  311  * 4. If recursion or cache access are allowed, search the cache
  312  *    (query_lookup() again, using the cache database) to find a better
  313  *    answer. If an answer is found, go to 7.
  314  *
  315  * 5. If recursion is allowed, begin recursion (ns_query_recurse()).
  316  *    Go to 15 to clean up this phase of the query. When recursion
  317  *    is complete, processing will resume at 6.
  318  *
  319  * 6. Resume from recursion; set up query context for resumed processing.
  320  *
  321  * 7. Determine what sort of answer we've found (query_gotanswer())
  322  *    and call other functions accordingly:
  323  *      - not found (auth or cache), go to 8
  324  *      - delegation, go to 9
  325  *      - no such domain (auth), go to 10
  326  *      - empty answer (auth), go to 11
  327  *      - negative response (cache), go to 12
  328  *      - answer found, go to 13
  329  *
  330  * 8. The answer was not found in the database (query_notfound().
  331  *    Set up a referral and go to 9.
  332  *
  333  * 9. Handle a delegation response (query_delegation()). If we need
  334  *    to and are allowed to recurse (query_delegation_recurse()), go to 5,
  335  *    otherwise go to 15 to clean up and return the delegation to the client.
  336  *
  337  * 10. No such domain (query_nxdomain()). Attempt redirection; if
  338  *     unsuccessful, add authority section records (query_addsoa(),
  339  *     query_addauth()), then go to 15 to return NXDOMAIN to client.
  340  *
  341  * 11. Empty answer (query_nodata()). Add authority section records
  342  *     (query_addsoa(), query_addauth()) and signatures if authoritative
  343  *     (query_sign_nodata()) then go to 15 and return
  344  *     NOERROR/ANCOUNT=0 to client.
  345  *
  346  * 12. No such domain or empty answer returned from cache (query_ncache()).
  347  *     Set response code appropriately, go to 11.
  348  *
  349  * 13. Prepare a response (query_prepresponse()) and then fill it
  350  *     appropriately (query_respond(), or for type ANY,
  351  *     query_respond_any()).
  352  *
  353  * 14. If a restart is needed due to CNAME/DNAME chaining, go to 2.
  354  *
  355  * 15. Clean up resources. If recursing, stop and wait for the event
  356  *     handler to be called back (step 6).  If an answer is ready,
  357  *     return it to the client.
  358  *
  359  * (XXX: This description omits several special cases including
  360  * DNS64, RPZ, RRL, and the SERVFAIL cache. It also doesn't discuss
  361  * plugins.)
  362  */
  363 
  364 static void
  365 query_trace(query_ctx_t *qctx);
  366 
  367 static void
  368 qctx_init(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype,
  369       query_ctx_t *qctx);
  370 
  371 static isc_result_t
  372 query_setup(ns_client_t *client, dns_rdatatype_t qtype);
  373 
  374 static isc_result_t
  375 query_lookup(query_ctx_t *qctx);
  376 
  377 static void
  378 fetch_callback(isc_task_t *task, isc_event_t *event);
  379 
  380 static void
  381 recparam_update(ns_query_recparam_t *param, dns_rdatatype_t qtype,
  382         const dns_name_t *qname, const dns_name_t *qdomain);
  383 
  384 static isc_result_t
  385 query_resume(query_ctx_t *qctx);
  386 
  387 static isc_result_t
  388 query_checkrrl(query_ctx_t *qctx, isc_result_t result);
  389 
  390 static isc_result_t
  391 query_checkrpz(query_ctx_t *qctx, isc_result_t result);
  392 
  393 static isc_result_t
  394 query_rpzcname(query_ctx_t *qctx, dns_name_t *cname);
  395 
  396 static isc_result_t
  397 query_gotanswer(query_ctx_t *qctx, isc_result_t result);
  398 
  399 static void
  400 query_addnoqnameproof(query_ctx_t *qctx);
  401 
  402 static isc_result_t
  403 query_respond_any(query_ctx_t *qctx);
  404 
  405 static isc_result_t
  406 query_respond(query_ctx_t *qctx);
  407 
  408 static isc_result_t
  409 query_dns64(query_ctx_t *qctx);
  410 
  411 static void
  412 query_filter64(query_ctx_t *qctx);
  413 
  414 static isc_result_t
  415 query_notfound(query_ctx_t *qctx);
  416 
  417 static isc_result_t
  418 query_zone_delegation(query_ctx_t *qctx);
  419 
  420 static isc_result_t
  421 query_delegation(query_ctx_t *qctx);
  422 
  423 static isc_result_t
  424 query_delegation_recurse(query_ctx_t *qctx);
  425 
  426 static void
  427 query_addds(query_ctx_t *qctx);
  428 
  429 static isc_result_t
  430 query_nodata(query_ctx_t *qctx, isc_result_t result);
  431 
  432 static isc_result_t
  433 query_sign_nodata(query_ctx_t *qctx);
  434 
  435 static void
  436 query_addnxrrsetnsec(query_ctx_t *qctx);
  437 
  438 static isc_result_t
  439 query_nxdomain(query_ctx_t *qctx, bool empty_wild);
  440 
  441 static isc_result_t
  442 query_redirect(query_ctx_t *qctx);
  443 
  444 static isc_result_t
  445 query_ncache(query_ctx_t *qctx, isc_result_t result);
  446 
  447 static isc_result_t
  448 query_coveringnsec(query_ctx_t *qctx);
  449 
  450 static isc_result_t
  451 query_zerottl_refetch(query_ctx_t *qctx);
  452 
  453 static isc_result_t
  454 query_cname(query_ctx_t *qctx);
  455 
  456 static isc_result_t
  457 query_dname(query_ctx_t *qctx);
  458 
  459 static isc_result_t
  460 query_addcname(query_ctx_t *qctx, dns_trust_t trust, dns_ttl_t ttl);
  461 
  462 static isc_result_t
  463 query_prepresponse(query_ctx_t *qctx);
  464 
  465 static isc_result_t
  466 query_addsoa(query_ctx_t *qctx, unsigned int override_ttl,
  467          dns_section_t section);
  468 
  469 static isc_result_t
  470 query_addns(query_ctx_t *qctx);
  471 
  472 static void
  473 query_addbestns(query_ctx_t *qctx);
  474 
  475 static void
  476 query_addwildcardproof(query_ctx_t *qctx, bool ispositive, bool nodata);
  477 
  478 static void
  479 query_addauth(query_ctx_t *qctx);
  480 
  481 /*
  482  * Increment query statistics counters.
  483  */
  484 static inline void
  485 inc_stats(ns_client_t *client, isc_statscounter_t counter) {
  486     dns_zone_t *zone = client->query.authzone;
  487     dns_rdatatype_t qtype;
  488     dns_rdataset_t *rdataset;
  489     isc_stats_t *zonestats;
  490     dns_stats_t *querystats = NULL;
  491 
  492     ns_stats_increment(client->sctx->nsstats, counter);
  493 
  494     if (zone == NULL) {
  495         return;
  496     }
  497 
  498     /* Do regular response type stats */
  499     zonestats = dns_zone_getrequeststats(zone);
  500 
  501     if (zonestats != NULL) {
  502         isc_stats_increment(zonestats, counter);
  503     }
  504 
  505     /* Do query type statistics
  506      *
  507      * We only increment per-type if we're using the authoritative
  508      * answer counter, preventing double-counting.
  509      */
  510     if (counter == ns_statscounter_authans) {
  511         querystats = dns_zone_getrcvquerystats(zone);
  512         if (querystats != NULL) {
  513             rdataset = ISC_LIST_HEAD(client->query.qname->list);
  514             if (rdataset != NULL) {
  515                 qtype = rdataset->type;
  516                 dns_rdatatypestats_increment(querystats, qtype);
  517             }
  518         }
  519     }
  520 }
  521 
  522 static void
  523 query_send(ns_client_t *client) {
  524     isc_statscounter_t counter;
  525 
  526     if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) {
  527         inc_stats(client, ns_statscounter_nonauthans);
  528     } else {
  529         inc_stats(client, ns_statscounter_authans);
  530     }
  531 
  532     if (client->message->rcode == dns_rcode_noerror) {
  533         dns_section_t answer = DNS_SECTION_ANSWER;
  534         if (ISC_LIST_EMPTY(client->message->sections[answer])) {
  535             if (client->query.isreferral) {
  536                 counter = ns_statscounter_referral;
  537             } else {
  538                 counter = ns_statscounter_nxrrset;
  539             }
  540         } else {
  541             counter = ns_statscounter_success;
  542         }
  543     } else if (client->message->rcode == dns_rcode_nxdomain) {
  544         counter = ns_statscounter_nxdomain;
  545     } else if (client->message->rcode == dns_rcode_badcookie) {
  546         counter = ns_statscounter_badcookie;
  547     } else { /* We end up here in case of YXDOMAIN, and maybe others */
  548         counter = ns_statscounter_failure;
  549     }
  550 
  551     inc_stats(client, counter);
  552     ns_client_send(client);
  553     isc_nmhandle_unref(client->handle);
  554 }
  555 
  556 static void
  557 query_error(ns_client_t *client, isc_result_t result, int line) {
  558     int loglevel = ISC_LOG_DEBUG(3);
  559 
  560     switch (dns_result_torcode(result)) {
  561     case dns_rcode_servfail:
  562         loglevel = ISC_LOG_DEBUG(1);
  563         inc_stats(client, ns_statscounter_servfail);
  564         break;
  565     case dns_rcode_formerr:
  566         inc_stats(client, ns_statscounter_formerr);
  567         break;
  568     default:
  569         inc_stats(client, ns_statscounter_failure);
  570         break;
  571     }
  572 
  573     if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
  574         loglevel = ISC_LOG_INFO;
  575     }
  576 
  577     log_queryerror(client, result, line, loglevel);
  578 
  579     ns_client_error(client, result);
  580     isc_nmhandle_unref(client->handle);
  581 }
  582 
  583 static void
  584 query_next(ns_client_t *client, isc_result_t result) {
  585     if (result == DNS_R_DUPLICATE) {
  586         inc_stats(client, ns_statscounter_duplicate);
  587     } else if (result == DNS_R_DROP) {
  588         inc_stats(client, ns_statscounter_dropped);
  589     } else {
  590         inc_stats(client, ns_statscounter_failure);
  591     }
  592     ns_client_drop(client, result);
  593     isc_nmhandle_unref(client->handle);
  594 }
  595 
  596 static inline void
  597 query_freefreeversions(ns_client_t *client, bool everything) {
  598     ns_dbversion_t *dbversion, *dbversion_next;
  599     unsigned int i;
  600 
  601     for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
  602          dbversion != NULL; dbversion = dbversion_next, i++)
  603     {
  604         dbversion_next = ISC_LIST_NEXT(dbversion, link);
  605         /*
  606          * If we're not freeing everything, we keep the first three
  607          * dbversions structures around.
  608          */
  609         if (i > 3 || everything) {
  610             ISC_LIST_UNLINK(client->query.freeversions, dbversion,
  611                     link);
  612             isc_mem_put(client->mctx, dbversion,
  613                     sizeof(*dbversion));
  614         }
  615     }
  616 }
  617 
  618 void
  619 ns_query_cancel(ns_client_t *client) {
  620     REQUIRE(NS_CLIENT_VALID(client));
  621 
  622     LOCK(&client->query.fetchlock);
  623     if (client->query.fetch != NULL) {
  624         dns_resolver_cancelfetch(client->query.fetch);
  625 
  626         client->query.fetch = NULL;
  627     }
  628     UNLOCK(&client->query.fetchlock);
  629 }
  630 
  631 static inline void
  632 query_reset(ns_client_t *client, bool everything) {
  633     isc_buffer_t *dbuf, *dbuf_next;
  634     ns_dbversion_t *dbversion, *dbversion_next;
  635 
  636     CTRACE(ISC_LOG_DEBUG(3), "query_reset");
  637 
  638     /*%
  639      * Reset the query state of a client to its default state.
  640      */
  641 
  642     /*
  643      * Cancel the fetch if it's running.
  644      */
  645     ns_query_cancel(client);
  646 
  647     /*
  648      * Cleanup any active versions.
  649      */
  650     for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
  651          dbversion != NULL; dbversion = dbversion_next)
  652     {
  653         dbversion_next = ISC_LIST_NEXT(dbversion, link);
  654         dns_db_closeversion(dbversion->db, &dbversion->version, false);
  655         dns_db_detach(&dbversion->db);
  656         ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion,
  657                        link);
  658     }
  659     ISC_LIST_INIT(client->query.activeversions);
  660 
  661     if (client->query.authdb != NULL) {
  662         dns_db_detach(&client->query.authdb);
  663     }
  664     if (client->query.authzone != NULL) {
  665         dns_zone_detach(&client->query.authzone);
  666     }
  667 
  668     if (client->query.dns64_aaaa != NULL) {
  669         ns_client_putrdataset(client, &client->query.dns64_aaaa);
  670     }
  671     if (client->query.dns64_sigaaaa != NULL) {
  672         ns_client_putrdataset(client, &client->query.dns64_sigaaaa);
  673     }
  674     if (client->query.dns64_aaaaok != NULL) {
  675         isc_mem_put(client->mctx, client->query.dns64_aaaaok,
  676                 client->query.dns64_aaaaoklen * sizeof(bool));
  677         client->query.dns64_aaaaok = NULL;
  678         client->query.dns64_aaaaoklen = 0;
  679     }
  680 
  681     ns_client_putrdataset(client, &client->query.redirect.rdataset);
  682     ns_client_putrdataset(client, &client->query.redirect.sigrdataset);
  683     if (client->query.redirect.db != NULL) {
  684         if (client->query.redirect.node != NULL) {
  685             dns_db_detachnode(client->query.redirect.db,
  686                       &client->query.redirect.node);
  687         }
  688         dns_db_detach(&client->query.redirect.db);
  689     }
  690     if (client->query.redirect.zone != NULL) {
  691         dns_zone_detach(&client->query.redirect.zone);
  692     }
  693 
  694     query_freefreeversions(client, everything);
  695 
  696     for (dbuf = ISC_LIST_HEAD(client->query.namebufs); dbuf != NULL;
  697          dbuf = dbuf_next)
  698     {
  699         dbuf_next = ISC_LIST_NEXT(dbuf, link);
  700         if (dbuf_next != NULL || everything) {
  701             ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
  702             isc_buffer_free(&dbuf);
  703         }
  704     }
  705 
  706     if (client->query.restarts > 0) {
  707         /*
  708          * client->query.qname was dynamically allocated.
  709          */
  710         dns_message_puttempname(client->message, &client->query.qname);
  711     }
  712     client->query.qname = NULL;
  713     client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
  714                     NS_QUERYATTR_CACHEOK | NS_QUERYATTR_SECURE);
  715     client->query.restarts = 0;
  716     client->query.timerset = false;
  717     if (client->query.rpz_st != NULL) {
  718         rpz_st_clear(client);
  719         if (everything) {
  720             INSIST(client->query.rpz_st->rpsdb == NULL);
  721             isc_mem_put(client->mctx, client->query.rpz_st,
  722                     sizeof(*client->query.rpz_st));
  723             client->query.rpz_st = NULL;
  724         }
  725     }
  726     client->query.origqname = NULL;
  727     client->query.dboptions = 0;
  728     client->query.fetchoptions = 0;
  729     client->query.gluedb = NULL;
  730     client->query.authdbset = false;
  731     client->query.isreferral = false;
  732     client->query.dns64_options = 0;
  733     client->query.dns64_ttl = UINT32_MAX;
  734     recparam_update(&client->query.recparam, 0, NULL, NULL);
  735     client->query.root_key_sentinel_keyid = 0;
  736     client->query.root_key_sentinel_is_ta = false;
  737     client->query.root_key_sentinel_not_ta = false;
  738 }
  739 
  740 static void
  741 query_cleanup(ns_client_t *client) {
  742     query_reset(client, false);
  743 }
  744 
  745 void
  746 ns_query_free(ns_client_t *client) {
  747     REQUIRE(NS_CLIENT_VALID(client));
  748 
  749     query_reset(client, true);
  750 }
  751 
  752 isc_result_t
  753 ns_query_init(ns_client_t *client) {
  754     isc_result_t result;
  755 
  756     REQUIRE(NS_CLIENT_VALID(client));
  757 
  758     ISC_LIST_INIT(client->query.namebufs);
  759     ISC_LIST_INIT(client->query.activeversions);
  760     ISC_LIST_INIT(client->query.freeversions);
  761     client->query.restarts = 0;
  762     client->query.timerset = false;
  763     client->query.rpz_st = NULL;
  764     client->query.qname = NULL;
  765     /*
  766      * This mutex is destroyed when the client is destroyed in
  767      * exit_check().
  768      */
  769     isc_mutex_init(&client->query.fetchlock);
  770 
  771     client->query.fetch = NULL;
  772     client->query.prefetch = NULL;
  773     client->query.authdb = NULL;
  774     client->query.authzone = NULL;
  775     client->query.authdbset = false;
  776     client->query.isreferral = false;
  777     client->query.dns64_aaaa = NULL;
  778     client->query.dns64_sigaaaa = NULL;
  779     client->query.dns64_aaaaok = NULL;
  780     client->query.dns64_aaaaoklen = 0;
  781     client->query.redirect.db = NULL;
  782     client->query.redirect.node = NULL;
  783     client->query.redirect.zone = NULL;
  784     client->query.redirect.qtype = dns_rdatatype_none;
  785     client->query.redirect.result = ISC_R_SUCCESS;
  786     client->query.redirect.rdataset = NULL;
  787     client->query.redirect.sigrdataset = NULL;
  788     client->query.redirect.authoritative = false;
  789     client->query.redirect.is_zone = false;
  790     client->query.redirect.fname =
  791         dns_fixedname_initname(&client->query.redirect.fixed);
  792     query_reset(client, false);
  793     result = ns_client_newdbversion(client, 3);
  794     if (result != ISC_R_SUCCESS) {
  795         isc_mutex_destroy(&client->query.fetchlock);
  796         return (result);
  797     }
  798     result = ns_client_newnamebuf(client);
  799     if (result != ISC_R_SUCCESS) {
  800         query_freefreeversions(client, true);
  801         isc_mutex_destroy(&client->query.fetchlock);
  802     }
  803 
  804     return (result);
  805 }
  806 
  807 /*%
  808  * Check if 'client' is allowed to query the cache of its associated view.
  809  * Unless 'options' has DNS_GETDB_NOLOG set, log the result of cache ACL
  810  * evaluation using the appropriate level, along with 'name' and 'qtype'.
  811  *
  812  * The cache ACL is only evaluated once for each client and then the result is
  813  * cached: if NS_QUERYATTR_CACHEACLOKVALID is set in client->query.attributes,
  814  * cache ACL evaluation has already been performed.  The evaluation result is
  815  * also stored in client->query.attributes: if NS_QUERYATTR_CACHEACLOK is set,
  816  * the client is allowed cache access.
  817  *
  818  * Returns:
  819  *
  820  *\li   #ISC_R_SUCCESS  'client' is allowed to access cache
  821  *\li   #DNS_R_REFUSED  'client' is not allowed to access cache
  822  */
  823 static isc_result_t
  824 query_checkcacheaccess(ns_client_t *client, const dns_name_t *name,
  825                dns_rdatatype_t qtype, unsigned int options) {
  826     isc_result_t result;
  827 
  828     if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) == 0) {
  829         /*
  830          * The view's cache ACLs have not yet been evaluated.
  831          * Do it now. Both allow-query-cache and
  832          * allow-query-cache-on must be satsified.
  833          */
  834         bool log = ((options & DNS_GETDB_NOLOG) == 0);
  835         char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
  836 
  837         result = ns_client_checkaclsilent(client, NULL,
  838                           client->view->cacheacl, true);
  839         if (result == ISC_R_SUCCESS) {
  840             result = ns_client_checkaclsilent(
  841                 client, &client->destaddr,
  842                 client->view->cacheonacl, true);
  843         }
  844         if (result == ISC_R_SUCCESS) {
  845             /*
  846              * We were allowed by the "allow-query-cache" ACL.
  847              */
  848             client->query.attributes |= NS_QUERYATTR_CACHEACLOK;
  849             if (log && isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3)))
  850             {
  851                 ns_client_aclmsg("query (cache)", name, qtype,
  852                          client->view->rdclass, msg,
  853                          sizeof(msg));
  854                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  855                           NS_LOGMODULE_QUERY,
  856                           ISC_LOG_DEBUG(3), "%s approved",
  857                           msg);
  858             }
  859         } else if (log) {
  860             /*
  861              * We were denied by the "allow-query-cache" ACL.
  862              * There is no need to clear NS_QUERYATTR_CACHEACLOK
  863              * since it is cleared by query_reset(), before query
  864              * processing starts.
  865              */
  866             ns_client_aclmsg("query (cache)", name, qtype,
  867                      client->view->rdclass, msg,
  868                      sizeof(msg));
  869             ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  870                       NS_LOGMODULE_QUERY, ISC_LOG_INFO,
  871                       "%s denied", msg);
  872         }
  873 
  874         /*
  875          * Evaluation has been finished; make sure we will just consult
  876          * NS_QUERYATTR_CACHEACLOK for this client from now on.
  877          */
  878         client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
  879     }
  880 
  881     return ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) != 0
  882             ? ISC_R_SUCCESS
  883             : DNS_R_REFUSED);
  884 }
  885 
  886 static inline isc_result_t
  887 query_validatezonedb(ns_client_t *client, const dns_name_t *name,
  888              dns_rdatatype_t qtype, unsigned int options,
  889              dns_zone_t *zone, dns_db_t *db,
  890              dns_dbversion_t **versionp) {
  891     isc_result_t result;
  892     dns_acl_t *queryacl, *queryonacl;
  893     ns_dbversion_t *dbversion;
  894 
  895     REQUIRE(zone != NULL);
  896     REQUIRE(db != NULL);
  897 
  898     /*
  899      * Mirror zone data is treated as cache data.
  900      */
  901     if (dns_zone_gettype(zone) == dns_zone_mirror) {
  902         return (query_checkcacheaccess(client, name, qtype, options));
  903     }
  904 
  905     /*
  906      * This limits our searching to the zone where the first name
  907      * (the query target) was looked for.  This prevents following
  908      * CNAMES or DNAMES into other zones and prevents returning
  909      * additional data from other zones. This does not apply if we're
  910      * answering a query where recursion is requested and allowed.
  911      */
  912     if (client->query.rpz_st == NULL &&
  913         !(WANTRECURSION(client) && RECURSIONOK(client)) &&
  914         client->query.authdbset && db != client->query.authdb)
  915     {
  916         return (DNS_R_REFUSED);
  917     }
  918 
  919     /*
  920      * Non recursive query to a static-stub zone is prohibited; its
  921      * zone content is not public data, but a part of local configuration
  922      * and should not be disclosed.
  923      */
  924     if (dns_zone_gettype(zone) == dns_zone_staticstub &&
  925         !RECURSIONOK(client)) {
  926         return (DNS_R_REFUSED);
  927     }
  928 
  929     /*
  930      * If the zone has an ACL, we'll check it, otherwise
  931      * we use the view's "allow-query" ACL.  Each ACL is only checked
  932      * once per query.
  933      *
  934      * Also, get the database version to use.
  935      */
  936 
  937     /*
  938      * Get the current version of this database.
  939      */
  940     dbversion = ns_client_findversion(client, db);
  941     if (dbversion == NULL) {
  942         CTRACE(ISC_LOG_ERROR, "unable to get db version");
  943         return (DNS_R_SERVFAIL);
  944     }
  945 
  946     if ((options & DNS_GETDB_IGNOREACL) != 0) {
  947         goto approved;
  948     }
  949     if (dbversion->acl_checked) {
  950         if (!dbversion->queryok) {
  951             return (DNS_R_REFUSED);
  952         }
  953         goto approved;
  954     }
  955 
  956     queryacl = dns_zone_getqueryacl(zone);
  957     if (queryacl == NULL) {
  958         queryacl = client->view->queryacl;
  959         if ((client->query.attributes & NS_QUERYATTR_QUERYOKVALID) != 0)
  960         {
  961             /*
  962              * We've evaluated the view's queryacl already.  If
  963              * NS_QUERYATTR_QUERYOK is set, then the client is
  964              * allowed to make queries, otherwise the query should
  965              * be refused.
  966              */
  967             dbversion->acl_checked = true;
  968             if ((client->query.attributes & NS_QUERYATTR_QUERYOK) ==
  969                 0) {
  970                 dbversion->queryok = false;
  971                 return (DNS_R_REFUSED);
  972             }
  973             dbversion->queryok = true;
  974             goto approved;
  975         }
  976     }
  977 
  978     result = ns_client_checkaclsilent(client, NULL, queryacl, true);
  979     if ((options & DNS_GETDB_NOLOG) == 0) {
  980         char msg[NS_CLIENT_ACLMSGSIZE("query")];
  981         if (result == ISC_R_SUCCESS) {
  982             if (isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(3))) {
  983                 ns_client_aclmsg("query", name, qtype,
  984                          client->view->rdclass, msg,
  985                          sizeof(msg));
  986                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  987                           NS_LOGMODULE_QUERY,
  988                           ISC_LOG_DEBUG(3), "%s approved",
  989                           msg);
  990             }
  991         } else {
  992             ns_client_aclmsg("query", name, qtype,
  993                      client->view->rdclass, msg,
  994                      sizeof(msg));
  995             ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  996                       NS_LOGMODULE_QUERY, ISC_LOG_INFO,
  997                       "%s denied", msg);
  998         }
  999     }
 1000 
 1001     if (queryacl == client->view->queryacl) {
 1002         if (result == ISC_R_SUCCESS) {
 1003             /*
 1004              * We were allowed by the default
 1005              * "allow-query" ACL.  Remember this so we
 1006              * don't have to check again.
 1007              */
 1008             client->query.attributes |= NS_QUERYATTR_QUERYOK;
 1009         }
 1010         /*
 1011          * We've now evaluated the view's query ACL, and
 1012          * the NS_QUERYATTR_QUERYOK attribute is now valid.
 1013          */
 1014         client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
 1015     }
 1016 
 1017     /* If and only if we've gotten this far, check allow-query-on too */
 1018     if (result == ISC_R_SUCCESS) {
 1019         queryonacl = dns_zone_getqueryonacl(zone);
 1020         if (queryonacl == NULL) {
 1021             queryonacl = client->view->queryonacl;
 1022         }
 1023 
 1024         result = ns_client_checkaclsilent(client, &client->destaddr,
 1025                           queryonacl, true);
 1026         if ((options & DNS_GETDB_NOLOG) == 0 && result != ISC_R_SUCCESS)
 1027         {
 1028             ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 1029                       NS_LOGMODULE_QUERY, ISC_LOG_INFO,
 1030                       "query-on denied");
 1031         }
 1032     }
 1033 
 1034     dbversion->acl_checked = true;
 1035     if (result != ISC_R_SUCCESS) {
 1036         dbversion->queryok = false;
 1037         return (DNS_R_REFUSED);
 1038     }
 1039     dbversion->queryok = true;
 1040 
 1041 approved:
 1042     /* Transfer ownership, if necessary. */
 1043     if (versionp != NULL) {
 1044         *versionp = dbversion->version;
 1045     }
 1046     return (ISC_R_SUCCESS);
 1047 }
 1048 
 1049 static inline isc_result_t
 1050 query_getzonedb(ns_client_t *client, const dns_name_t *name,
 1051         dns_rdatatype_t qtype, unsigned int options, dns_zone_t **zonep,
 1052         dns_db_t **dbp, dns_dbversion_t **versionp) {
 1053     isc_result_t result;
 1054     unsigned int ztoptions;
 1055     dns_zone_t *zone = NULL;
 1056     dns_db_t *db = NULL;
 1057     bool partial = false;
 1058 
 1059     REQUIRE(zonep != NULL && *zonep == NULL);
 1060     REQUIRE(dbp != NULL && *dbp == NULL);
 1061 
 1062     /*%
 1063      * Find a zone database to answer the query.
 1064      */
 1065     ztoptions = DNS_ZTFIND_MIRROR;
 1066     if ((options & DNS_GETDB_NOEXACT) != 0) {
 1067         ztoptions |= DNS_ZTFIND_NOEXACT;
 1068     }
 1069 
 1070     result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
 1071                  &zone);
 1072 
 1073     if (result == DNS_R_PARTIALMATCH) {
 1074         partial = true;
 1075     }
 1076     if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
 1077         result = dns_zone_getdb(zone, &db);
 1078     }
 1079 
 1080     if (result != ISC_R_SUCCESS) {
 1081         goto fail;
 1082     }
 1083 
 1084     result = query_validatezonedb(client, name, qtype, options, zone, db,
 1085                       versionp);
 1086 
 1087     if (result != ISC_R_SUCCESS) {
 1088         goto fail;
 1089     }
 1090 
 1091     /* Transfer ownership. */
 1092     *zonep = zone;
 1093     *dbp = db;
 1094 
 1095     if (partial && (options & DNS_GETDB_PARTIAL) != 0) {
 1096         return (DNS_R_PARTIALMATCH);
 1097     }
 1098     return (ISC_R_SUCCESS);
 1099 
 1100 fail:
 1101     if (zone != NULL) {
 1102         dns_zone_detach(&zone);
 1103     }
 1104     if (db != NULL) {
 1105         dns_db_detach(&db);
 1106     }
 1107 
 1108     return (result);
 1109 }
 1110 
 1111 static void
 1112 rpz_log_rewrite(ns_client_t *client, bool disabled, dns_rpz_policy_t policy,
 1113         dns_rpz_type_t type, dns_zone_t *p_zone, dns_name_t *p_name,
 1114         dns_name_t *cname, dns_rpz_num_t rpz_num) {
 1115     char cname_buf[DNS_NAME_FORMATSIZE] = { 0 };
 1116     char p_name_buf[DNS_NAME_FORMATSIZE];
 1117     char qname_buf[DNS_NAME_FORMATSIZE];
 1118     char classbuf[DNS_RDATACLASS_FORMATSIZE];
 1119     char typebuf[DNS_RDATATYPE_FORMATSIZE];
 1120     const char *s1 = cname_buf, *s2 = cname_buf;
 1121     dns_rdataset_t *rdataset;
 1122     dns_rpz_st_t *st;
 1123     isc_stats_t *zonestats;
 1124 
 1125     /*
 1126      * Count enabled rewrites in the global counter.
 1127      * Count both enabled and disabled rewrites for each zone.
 1128      */
 1129     if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) {
 1130         ns_stats_increment(client->sctx->nsstats,
 1131                    ns_statscounter_rpz_rewrites);
 1132     }
 1133     if (p_zone != NULL) {
 1134         zonestats = dns_zone_getrequeststats(p_zone);
 1135         if (zonestats != NULL) {
 1136             isc_stats_increment(zonestats,
 1137                         ns_statscounter_rpz_rewrites);
 1138         }
 1139     }
 1140 
 1141     if (!isc_log_wouldlog(ns_lctx, DNS_RPZ_INFO_LEVEL)) {
 1142         return;
 1143     }
 1144 
 1145     st = client->query.rpz_st;
 1146     if ((st->popt.no_log & DNS_RPZ_ZBIT(rpz_num)) != 0) {
 1147         return;
 1148     }
 1149 
 1150     dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
 1151     dns_name_format(p_name, p_name_buf, sizeof(p_name_buf));
 1152     if (cname != NULL) {
 1153         s1 = " (CNAME to: ";
 1154         dns_name_format(cname, cname_buf, sizeof(cname_buf));
 1155         s2 = ")";
 1156     }
 1157 
 1158     /*
 1159      *  Log Qclass and Qtype in addition to existing
 1160      *  fields.
 1161      */
 1162     rdataset = ISC_LIST_HEAD(client->query.origqname->list);
 1163     INSIST(rdataset != NULL);
 1164     dns_rdataclass_format(rdataset->rdclass, classbuf, sizeof(classbuf));
 1165     dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
 1166 
 1167     ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
 1168               DNS_RPZ_INFO_LEVEL,
 1169               "%srpz %s %s rewrite %s/%s/%s via %s%s%s%s",
 1170               disabled ? "disabled " : "", dns_rpz_type2str(type),
 1171               dns_rpz_policy2str(policy), qname_buf, typebuf, classbuf,
 1172               p_name_buf, s1, cname_buf, s2);
 1173 }
 1174 
 1175 static void
 1176 rpz_log_fail_helper(ns_client_t *client, int level, dns_name_t *p_name,
 1177             dns_rpz_type_t rpz_type1, dns_rpz_type_t rpz_type2,
 1178             const char *str, isc_result_t result) {
 1179     char qnamebuf[DNS_NAME_FORMATSIZE];
 1180     char p_namebuf[DNS_NAME_FORMATSIZE];
 1181     const char *failed, *via, *slash, *str_blank;
 1182     const char *rpztypestr1;
 1183     const char *rpztypestr2;
 1184 
 1185     if (!isc_log_wouldlog(ns_lctx, level)) {
 1186         return;
 1187     }
 1188 
 1189     /*
 1190      * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems.
 1191      */
 1192     if (level <= DNS_RPZ_DEBUG_LEVEL1) {
 1193         failed = " failed: ";
 1194     } else {
 1195         failed = ": ";
 1196     }
 1197 
 1198     rpztypestr1 = dns_rpz_type2str(rpz_type1);
 1199     if (rpz_type2 != DNS_RPZ_TYPE_BAD) {
 1200         slash = "/";
 1201         rpztypestr2 = dns_rpz_type2str(rpz_type2);
 1202     } else {
 1203         slash = "";
 1204         rpztypestr2 = "";
 1205     }
 1206 
 1207     str_blank = (*str != ' ' && *str != '\0') ? " " : "";
 1208 
 1209     dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf));
 1210 
 1211     if (p_name != NULL) {
 1212         via = " via ";
 1213         dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
 1214     } else {
 1215         via = "";
 1216         p_namebuf[0] = '\0';
 1217     }
 1218 
 1219     ns_client_log(client, NS_LOGCATEGORY_QUERY_ERRORS, NS_LOGMODULE_QUERY,
 1220               level, "rpz %s%s%s rewrite %s%s%s%s%s%s%s", rpztypestr1,
 1221               slash, rpztypestr2, qnamebuf, via, p_namebuf, str_blank,
 1222               str, failed, isc_result_totext(result));
 1223 }
 1224 
 1225 static void
 1226 rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name,
 1227          dns_rpz_type_t rpz_type, const char *str, isc_result_t result) {
 1228     rpz_log_fail_helper(client, level, p_name, rpz_type, DNS_RPZ_TYPE_BAD,
 1229                 str, result);
 1230 }
 1231 
 1232 /*
 1233  * Get a policy rewrite zone database.
 1234  */
 1235 static isc_result_t
 1236 rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type,
 1237       dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) {
 1238     char qnamebuf[DNS_NAME_FORMATSIZE];
 1239     char p_namebuf[DNS_NAME_FORMATSIZE];
 1240     dns_dbversion_t *rpz_version = NULL;
 1241     isc_result_t result;
 1242 
 1243     CTRACE(ISC_LOG_DEBUG(3), "rpz_getdb");
 1244 
 1245     result = query_getzonedb(client, p_name, dns_rdatatype_any,
 1246                  DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
 1247     if (result == ISC_R_SUCCESS) {
 1248         dns_rpz_st_t *st = client->query.rpz_st;
 1249 
 1250         /*
 1251          * It isn't meaningful to log this message when
 1252          * logging is disabled for some policy zones.
 1253          */
 1254         if (st->popt.no_log == 0 &&
 1255             isc_log_wouldlog(ns_lctx, DNS_RPZ_DEBUG_LEVEL2)) {
 1256             dns_name_format(client->query.qname, qnamebuf,
 1257                     sizeof(qnamebuf));
 1258             dns_name_format(p_name, p_namebuf, sizeof(p_namebuf));
 1259             ns_client_log(client, DNS_LOGCATEGORY_RPZ,
 1260                       NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
 1261                       "try rpz %s rewrite %s via %s",
 1262                       dns_rpz_type2str(rpz_type), qnamebuf,
 1263                       p_namebuf);
 1264         }
 1265         *versionp = rpz_version;
 1266         return (ISC_R_SUCCESS);
 1267     }
 1268     rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
 1269              "query_getzonedb()", result);
 1270     return (result);
 1271 }
 1272 
 1273 /*%
 1274  * Find a cache database to answer the query.  This may fail with DNS_R_REFUSED
 1275  * if the client is not allowed to use the cache.
 1276  */
 1277 static inline isc_result_t
 1278 query_getcachedb(ns_client_t *client, const dns_name_t *name,
 1279          dns_rdatatype_t qtype, dns_db_t **dbp, unsigned int options) {
 1280     isc_result_t result;
 1281     dns_db_t *db = NULL;
 1282 
 1283     REQUIRE(dbp != NULL && *dbp == NULL);
 1284 
 1285     if (!USECACHE(client)) {
 1286         return (DNS_R_REFUSED);
 1287     }
 1288 
 1289     dns_db_attach(client->view->cachedb, &db);
 1290 
 1291     result = query_checkcacheaccess(client, name, qtype, options);
 1292     if (result != ISC_R_SUCCESS) {
 1293         dns_db_detach(&db);
 1294     }
 1295 
 1296     /*
 1297      * If query_checkcacheaccess() succeeded, transfer ownership of 'db'.
 1298      * Otherwise, 'db' will be NULL due to the dns_db_detach() call above.
 1299      */
 1300     *dbp = db;
 1301 
 1302     return (result);
 1303 }
 1304 
 1305 static inline isc_result_t
 1306 query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
 1307         unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
 1308         dns_dbversion_t **versionp, bool *is_zonep) {
 1309     isc_result_t result;
 1310     isc_result_t tresult;
 1311     unsigned int namelabels;
 1312     unsigned int zonelabels;
 1313     dns_zone_t *zone = NULL;
 1314 
 1315     REQUIRE(zonep != NULL && *zonep == NULL);
 1316 
 1317     /* Calculate how many labels are in name. */
 1318     namelabels = dns_name_countlabels(name);
 1319     zonelabels = 0;
 1320 
 1321     /* Try to find name in bind's standard database. */
 1322     result = query_getzonedb(client, name, qtype, options, &zone, dbp,
 1323                  versionp);
 1324 
 1325     /* See how many labels are in the zone's name.    */
 1326     if (result == ISC_R_SUCCESS && zone != NULL) {
 1327         zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
 1328     }
 1329 
 1330     /*
 1331      * If # zone labels < # name labels, try to find an even better match
 1332      * Only try if DLZ drivers are loaded for this view
 1333      */
 1334     if (ISC_UNLIKELY(zonelabels < namelabels &&
 1335              !ISC_LIST_EMPTY(client->view->dlz_searched)))
 1336     {
 1337         dns_clientinfomethods_t cm;
 1338         dns_clientinfo_t ci;
 1339         dns_db_t *tdbp;
 1340 
 1341         dns_clientinfomethods_init(&cm, ns_client_sourceip);
 1342         dns_clientinfo_init(&ci, client, NULL);
 1343 
 1344         tdbp = NULL;
 1345         tresult = dns_view_searchdlz(client->view, name, zonelabels,
 1346                          &cm, &ci, &tdbp);
 1347         /* If we successful, we found a better match. */
 1348         if (tresult == ISC_R_SUCCESS) {
 1349             ns_dbversion_t *dbversion;
 1350 
 1351             /*
 1352              * If the previous search returned a zone, detach it.
 1353              */
 1354             if (zone != NULL) {
 1355                 dns_zone_detach(&zone);
 1356             }
 1357 
 1358             /*
 1359              * If the previous search returned a database,
 1360              * detach it.
 1361              */
 1362             if (*dbp != NULL) {
 1363                 dns_db_detach(dbp);
 1364             }
 1365 
 1366             /*
 1367              * If the previous search returned a version, clear it.
 1368              */
 1369             *versionp = NULL;
 1370 
 1371             dbversion = ns_client_findversion(client, tdbp);
 1372             if (dbversion == NULL) {
 1373                 tresult = ISC_R_NOMEMORY;
 1374             } else {
 1375                 /*
 1376                  * Be sure to return our database.
 1377                  */
 1378                 *dbp = tdbp;
 1379                 *versionp = dbversion->version;
 1380             }
 1381 
 1382             /*
 1383              * We return a null zone, No stats for DLZ zones.
 1384              */
 1385             zone = NULL;
 1386             result = tresult;
 1387         }
 1388     }
 1389 
 1390     /* If successful, Transfer ownership of zone. */
 1391     if (result == ISC_R_SUCCESS) {
 1392         *zonep = zone;
 1393         /*
 1394          * If neither attempt above succeeded, return the cache instead
 1395          */
 1396         *is_zonep = true;
 1397     } else {
 1398         if (result == ISC_R_NOTFOUND) {
 1399             result = query_getcachedb(client, name, qtype, dbp,
 1400                           options);
 1401         }
 1402         *is_zonep = false;
 1403     }
 1404     return (result);
 1405 }
 1406 
 1407 static inline bool
 1408 query_isduplicate(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
 1409           dns_name_t **mnamep) {
 1410     dns_section_t section;
 1411     dns_name_t *mname = NULL;
 1412     isc_result_t result;
 1413 
 1414     CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
 1415 
 1416     for (section = DNS_SECTION_ANSWER; section <= DNS_SECTION_ADDITIONAL;
 1417          section++) {
 1418         result = dns_message_findname(client->message, section, name,
 1419                           type, 0, &mname, NULL);
 1420         if (result == ISC_R_SUCCESS) {
 1421             /*
 1422              * We've already got this RRset in the response.
 1423              */
 1424             CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: true: "
 1425                          "done");
 1426             return (true);
 1427         } else if (result == DNS_R_NXRRSET) {
 1428             /*
 1429              * The name exists, but the rdataset does not.
 1430              */
 1431             if (section == DNS_SECTION_ADDITIONAL) {
 1432                 break;
 1433             }
 1434         } else {
 1435             RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
 1436         }
 1437         mname = NULL;
 1438     }
 1439 
 1440     if (mnamep != NULL) {
 1441         *mnamep = mname;
 1442     }
 1443 
 1444     CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
 1445     return (false);
 1446 }
 1447 
 1448 /*
 1449  * Look up data for given 'name' and 'type' in given 'version' of 'db' for
 1450  * 'client'. Called from query_additionalauth().
 1451  *
 1452  * If the lookup is successful:
 1453  *
 1454  *   - store the node containing the result at 'nodep',
 1455  *
 1456  *   - store the owner name of the returned node in 'fname',
 1457  *
 1458  *   - if 'type' is not ANY, dns_db_findext() will put the exact rdataset being
 1459  *     looked for in 'rdataset' and its signatures (if any) in 'sigrdataset',
 1460  *
 1461  *   - if 'type' is ANY, dns_db_findext() will leave 'rdataset' and
 1462  *     'sigrdataset' disassociated and the returned node will be iterated in
 1463  *     query_additional_cb().
 1464  *
 1465  * If the lookup is not successful:
 1466  *
 1467  *   - 'nodep' will not be written to,
 1468  *   - 'fname' may still be modified as it is passed to dns_db_findext(),
 1469  *   - 'rdataset' and 'sigrdataset' will remain disassociated.
 1470  */
 1471 static isc_result_t
 1472 query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version,
 1473              const dns_name_t *name, dns_rdatatype_t type,
 1474              ns_client_t *client, dns_dbnode_t **nodep,
 1475              dns_name_t *fname, dns_rdataset_t *rdataset,
 1476              dns_rdataset_t *sigrdataset) {
 1477     dns_clientinfomethods_t cm;
 1478     dns_dbnode_t *node = NULL;
 1479     dns_clientinfo_t ci;
 1480     isc_result_t result;
 1481 
 1482     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 1483     dns_clientinfo_init(&ci, client, NULL);
 1484 
 1485     /*
 1486      * Since we are looking for authoritative data, we do not set
 1487      * the GLUEOK flag.  Glue will be looked for later, but not
 1488      * necessarily in the same database.
 1489      */
 1490     result = dns_db_findext(db, name, version, type,
 1491                 client->query.dboptions, client->now, &node,
 1492                 fname, &cm, &ci, rdataset, sigrdataset);
 1493     if (result != ISC_R_SUCCESS) {
 1494         if (dns_rdataset_isassociated(rdataset)) {
 1495             dns_rdataset_disassociate(rdataset);
 1496         }
 1497 
 1498         if (sigrdataset != NULL &&
 1499             dns_rdataset_isassociated(sigrdataset)) {
 1500             dns_rdataset_disassociate(sigrdataset);
 1501         }
 1502 
 1503         if (node != NULL) {
 1504             dns_db_detachnode(db, &node);
 1505         }
 1506 
 1507         return (result);
 1508     }
 1509 
 1510     /*
 1511      * Do not return signatures if the zone is not fully signed.
 1512      */
 1513     if (sigrdataset != NULL && !dns_db_issecure(db) &&
 1514         dns_rdataset_isassociated(sigrdataset))
 1515     {
 1516         dns_rdataset_disassociate(sigrdataset);
 1517     }
 1518 
 1519     *nodep = node;
 1520 
 1521     return (ISC_R_SUCCESS);
 1522 }
 1523 
 1524 /*
 1525  * For query context 'qctx', try finding authoritative additional data for
 1526  * given 'name' and 'type'. Called from query_additional_cb().
 1527  *
 1528  * If successful:
 1529  *
 1530  *   - store pointers to the database and node which contain the result in
 1531  *     'dbp' and 'nodep', respectively,
 1532  *
 1533  *   - store the owner name of the returned node in 'fname',
 1534  *
 1535  *   - potentially bind 'rdataset' and 'sigrdataset', as explained in the
 1536  *     comment for query_additionalauthfind().
 1537  *
 1538  * If unsuccessful:
 1539  *
 1540  *   - 'dbp' and 'nodep' will not be written to,
 1541  *   - 'fname' may still be modified as it is passed to dns_db_findext(),
 1542  *   - 'rdataset' and 'sigrdataset' will remain disassociated.
 1543  */
 1544 static isc_result_t
 1545 query_additionalauth(query_ctx_t *qctx, const dns_name_t *name,
 1546              dns_rdatatype_t type, dns_db_t **dbp, dns_dbnode_t **nodep,
 1547              dns_name_t *fname, dns_rdataset_t *rdataset,
 1548              dns_rdataset_t *sigrdataset) {
 1549     ns_client_t *client = qctx->client;
 1550     ns_dbversion_t *dbversion = NULL;
 1551     dns_dbversion_t *version = NULL;
 1552     dns_dbnode_t *node = NULL;
 1553     dns_zone_t *zone = NULL;
 1554     dns_db_t *db = NULL;
 1555     isc_result_t result;
 1556 
 1557     /*
 1558      * First, look within the same zone database for authoritative
 1559      * additional data.
 1560      */
 1561     if (!client->query.authdbset || client->query.authdb == NULL) {
 1562         return (ISC_R_NOTFOUND);
 1563     }
 1564 
 1565     dbversion = ns_client_findversion(client, client->query.authdb);
 1566     if (dbversion == NULL) {
 1567         return (ISC_R_NOTFOUND);
 1568     }
 1569 
 1570     dns_db_attach(client->query.authdb, &db);
 1571     version = dbversion->version;
 1572 
 1573     CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: same zone");
 1574 
 1575     result = query_additionalauthfind(db, version, name, type, client,
 1576                       &node, fname, rdataset, sigrdataset);
 1577     if (result != ISC_R_SUCCESS &&
 1578         qctx->view->minimalresponses == dns_minimal_no &&
 1579         RECURSIONOK(client))
 1580     {
 1581         /*
 1582          * If we aren't doing response minimization and recursion is
 1583          * allowed, we can try and see if any other zone matches.
 1584          */
 1585         version = NULL;
 1586         dns_db_detach(&db);
 1587         result = query_getzonedb(client, name, type, DNS_GETDB_NOLOG,
 1588                      &zone, &db, &version);
 1589         if (result != ISC_R_SUCCESS) {
 1590             return (result);
 1591         }
 1592         dns_zone_detach(&zone);
 1593 
 1594         CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: other zone");
 1595 
 1596         result = query_additionalauthfind(db, version, name, type,
 1597                           client, &node, fname,
 1598                           rdataset, sigrdataset);
 1599     }
 1600 
 1601     if (result != ISC_R_SUCCESS) {
 1602         dns_db_detach(&db);
 1603     } else {
 1604         *nodep = node;
 1605         node = NULL;
 1606 
 1607         *dbp = db;
 1608         db = NULL;
 1609     }
 1610 
 1611     return (result);
 1612 }
 1613 
 1614 static isc_result_t
 1615 query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) {
 1616     query_ctx_t *qctx = arg;
 1617     ns_client_t *client = qctx->client;
 1618     isc_result_t result, eresult = ISC_R_SUCCESS;
 1619     dns_dbnode_t *node = NULL;
 1620     dns_db_t *db = NULL;
 1621     dns_name_t *fname = NULL, *mname = NULL;
 1622     dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
 1623     dns_rdataset_t *trdataset = NULL;
 1624     isc_buffer_t *dbuf = NULL;
 1625     isc_buffer_t b;
 1626     ns_dbversion_t *dbversion = NULL;
 1627     dns_dbversion_t *version = NULL;
 1628     bool added_something = false, need_addname = false;
 1629     dns_rdatatype_t type;
 1630     dns_clientinfomethods_t cm;
 1631     dns_clientinfo_t ci;
 1632     dns_rdatasetadditional_t additionaltype =
 1633         dns_rdatasetadditional_fromauth;
 1634 
 1635     REQUIRE(NS_CLIENT_VALID(client));
 1636     REQUIRE(qtype != dns_rdatatype_any);
 1637 
 1638     if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype)) {
 1639         return (ISC_R_SUCCESS);
 1640     }
 1641 
 1642     CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb");
 1643 
 1644     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 1645     dns_clientinfo_init(&ci, client, NULL);
 1646 
 1647     /*
 1648      * We treat type A additional section processing as if it
 1649      * were "any address type" additional section processing.
 1650      * To avoid multiple lookups, we do an 'any' database
 1651      * lookup and iterate over the node.
 1652      */
 1653     if (qtype == dns_rdatatype_a) {
 1654         type = dns_rdatatype_any;
 1655     } else {
 1656         type = qtype;
 1657     }
 1658 
 1659     /*
 1660      * Get some resources.
 1661      */
 1662     dbuf = ns_client_getnamebuf(client);
 1663     if (dbuf == NULL) {
 1664         goto cleanup;
 1665     }
 1666     fname = ns_client_newname(client, dbuf, &b);
 1667     rdataset = ns_client_newrdataset(client);
 1668     if (fname == NULL || rdataset == NULL) {
 1669         goto cleanup;
 1670     }
 1671     if (WANTDNSSEC(client)) {
 1672         sigrdataset = ns_client_newrdataset(client);
 1673         if (sigrdataset == NULL) {
 1674             goto cleanup;
 1675         }
 1676     }
 1677 
 1678     /*
 1679      * If we want only minimal responses and are here, then it must
 1680      * be for glue.
 1681      */
 1682     if (qctx->view->minimalresponses == dns_minimal_yes) {
 1683         goto try_glue;
 1684     }
 1685 
 1686     /*
 1687      * First, look for authoritative additional data.
 1688      */
 1689     result = query_additionalauth(qctx, name, type, &db, &node, fname,
 1690                       rdataset, sigrdataset);
 1691     if (result == ISC_R_SUCCESS) {
 1692         goto found;
 1693     }
 1694 
 1695     /*
 1696      * No authoritative data was found.  The cache is our next best bet.
 1697      */
 1698     if (!qctx->view->recursion) {
 1699         goto try_glue;
 1700     }
 1701 
 1702     additionaltype = dns_rdatasetadditional_fromcache;
 1703     result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
 1704     if (result != ISC_R_SUCCESS) {
 1705         /*
 1706          * Most likely the client isn't allowed to query the cache.
 1707          */
 1708         goto try_glue;
 1709     }
 1710     /*
 1711      * Attempt to validate glue.
 1712      */
 1713     if (sigrdataset == NULL) {
 1714         sigrdataset = ns_client_newrdataset(client);
 1715         if (sigrdataset == NULL) {
 1716             goto cleanup;
 1717         }
 1718     }
 1719 
 1720     version = NULL;
 1721     result = dns_db_findext(db, name, version, type,
 1722                 client->query.dboptions | DNS_DBFIND_GLUEOK |
 1723                     DNS_DBFIND_ADDITIONALOK,
 1724                 client->now, &node, fname, &cm, &ci, rdataset,
 1725                 sigrdataset);
 1726 
 1727     dns_cache_updatestats(qctx->view->cache, result);
 1728     if (!WANTDNSSEC(client)) {
 1729         ns_client_putrdataset(client, &sigrdataset);
 1730     }
 1731     if (result == ISC_R_SUCCESS) {
 1732         goto found;
 1733     }
 1734 
 1735     if (dns_rdataset_isassociated(rdataset)) {
 1736         dns_rdataset_disassociate(rdataset);
 1737     }
 1738     if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
 1739         dns_rdataset_disassociate(sigrdataset);
 1740     }
 1741     if (node != NULL) {
 1742         dns_db_detachnode(db, &node);
 1743     }
 1744     dns_db_detach(&db);
 1745 
 1746 try_glue:
 1747     /*
 1748      * No cached data was found.  Glue is our last chance.
 1749      * RFC1035 sayeth:
 1750      *
 1751      *  NS records cause both the usual additional section
 1752      *  processing to locate a type A record, and, when used
 1753      *  in a referral, a special search of the zone in which
 1754      *  they reside for glue information.
 1755      *
 1756      * This is the "special search".  Note that we must search
 1757      * the zone where the NS record resides, not the zone it
 1758      * points to, and that we only do the search in the delegation
 1759      * case (identified by client->query.gluedb being set).
 1760      */
 1761 
 1762     if (client->query.gluedb == NULL) {
 1763         goto cleanup;
 1764     }
 1765 
 1766     /*
 1767      * Don't poison caches using the bailiwick protection model.
 1768      */
 1769     if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb))) {
 1770         goto cleanup;
 1771     }
 1772 
 1773     dbversion = ns_client_findversion(client, client->query.gluedb);
 1774     if (dbversion == NULL) {
 1775         goto cleanup;
 1776     }
 1777 
 1778     dns_db_attach(client->query.gluedb, &db);
 1779     version = dbversion->version;
 1780     additionaltype = dns_rdatasetadditional_fromglue;
 1781     result = dns_db_findext(db, name, version, type,
 1782                 client->query.dboptions | DNS_DBFIND_GLUEOK,
 1783                 client->now, &node, fname, &cm, &ci, rdataset,
 1784                 sigrdataset);
 1785     if (result != ISC_R_SUCCESS && result != DNS_R_ZONECUT &&
 1786         result != DNS_R_GLUE) {
 1787         goto cleanup;
 1788     }
 1789 
 1790 found:
 1791     /*
 1792      * We have found a potential additional data rdataset, or
 1793      * at least a node to iterate over.
 1794      */
 1795     ns_client_keepname(client, fname, dbuf);
 1796 
 1797     /*
 1798      * If we have an rdataset, add it to the additional data
 1799      * section.
 1800      */
 1801     mname = NULL;
 1802     if (dns_rdataset_isassociated(rdataset) &&
 1803         !query_isduplicate(client, fname, type, &mname))
 1804     {
 1805         if (mname != NULL) {
 1806             INSIST(mname != fname);
 1807             ns_client_releasename(client, &fname);
 1808             fname = mname;
 1809         } else {
 1810             need_addname = true;
 1811         }
 1812         ISC_LIST_APPEND(fname->list, rdataset, link);
 1813         trdataset = rdataset;
 1814         rdataset = NULL;
 1815         added_something = true;
 1816         /*
 1817          * Note: we only add SIGs if we've added the type they cover,
 1818          * so we do not need to check if the SIG rdataset is already
 1819          * in the response.
 1820          */
 1821         if (sigrdataset != NULL &&
 1822             dns_rdataset_isassociated(sigrdataset)) {
 1823             ISC_LIST_APPEND(fname->list, sigrdataset, link);
 1824             sigrdataset = NULL;
 1825         }
 1826     }
 1827 
 1828     if (qtype == dns_rdatatype_a) {
 1829         /*
 1830          * We now go looking for A and AAAA records, along with
 1831          * their signatures.
 1832          *
 1833          * XXXRTH  This code could be more efficient.
 1834          */
 1835         if (rdataset != NULL) {
 1836             if (dns_rdataset_isassociated(rdataset)) {
 1837                 dns_rdataset_disassociate(rdataset);
 1838             }
 1839         } else {
 1840             rdataset = ns_client_newrdataset(client);
 1841             if (rdataset == NULL) {
 1842                 goto addname;
 1843             }
 1844         }
 1845         if (sigrdataset != NULL) {
 1846             if (dns_rdataset_isassociated(sigrdataset)) {
 1847                 dns_rdataset_disassociate(sigrdataset);
 1848             }
 1849         } else if (WANTDNSSEC(client)) {
 1850             sigrdataset = ns_client_newrdataset(client);
 1851             if (sigrdataset == NULL) {
 1852                 goto addname;
 1853             }
 1854         }
 1855         if (query_isduplicate(client, fname, dns_rdatatype_a, NULL)) {
 1856             goto aaaa_lookup;
 1857         }
 1858         result = dns_db_findrdataset(db, node, version, dns_rdatatype_a,
 1859                          0, client->now, rdataset,
 1860                          sigrdataset);
 1861         if (result == DNS_R_NCACHENXDOMAIN) {
 1862             goto addname;
 1863         } else if (result == DNS_R_NCACHENXRRSET) {
 1864             dns_rdataset_disassociate(rdataset);
 1865             if (sigrdataset != NULL &&
 1866                 dns_rdataset_isassociated(sigrdataset)) {
 1867                 dns_rdataset_disassociate(sigrdataset);
 1868             }
 1869         } else if (result == ISC_R_SUCCESS) {
 1870             bool invalid = false;
 1871             mname = NULL;
 1872             if (additionaltype ==
 1873                     dns_rdatasetadditional_fromcache &&
 1874                 (DNS_TRUST_PENDING(rdataset->trust) ||
 1875                  DNS_TRUST_GLUE(rdataset->trust)))
 1876             {
 1877                 /* validate() may change rdataset->trust */
 1878                 invalid = !validate(client, db, fname, rdataset,
 1879                             sigrdataset);
 1880             }
 1881             if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
 1882                 dns_rdataset_disassociate(rdataset);
 1883                 if (sigrdataset != NULL &&
 1884                     dns_rdataset_isassociated(sigrdataset)) {
 1885                     dns_rdataset_disassociate(sigrdataset);
 1886                 }
 1887             } else if (!query_isduplicate(client, fname,
 1888                               dns_rdatatype_a, &mname))
 1889             {
 1890                 if (mname != fname) {
 1891                     if (mname != NULL) {
 1892                         ns_client_releasename(client,
 1893                                       &fname);
 1894                         fname = mname;
 1895                     } else {
 1896                         need_addname = true;
 1897                     }
 1898                 }
 1899                 ISC_LIST_APPEND(fname->list, rdataset, link);
 1900                 added_something = true;
 1901                 if (sigrdataset != NULL &&
 1902                     dns_rdataset_isassociated(sigrdataset)) {
 1903                     ISC_LIST_APPEND(fname->list,
 1904                             sigrdataset, link);
 1905                     sigrdataset =
 1906                         ns_client_newrdataset(client);
 1907                 }
 1908                 rdataset = ns_client_newrdataset(client);
 1909                 if (rdataset == NULL) {
 1910                     goto addname;
 1911                 }
 1912                 if (WANTDNSSEC(client) && sigrdataset == NULL) {
 1913                     goto addname;
 1914                 }
 1915             } else {
 1916                 dns_rdataset_disassociate(rdataset);
 1917                 if (sigrdataset != NULL &&
 1918                     dns_rdataset_isassociated(sigrdataset)) {
 1919                     dns_rdataset_disassociate(sigrdataset);
 1920                 }
 1921             }
 1922         }
 1923     aaaa_lookup:
 1924         if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
 1925         {
 1926             goto addname;
 1927         }
 1928         result = dns_db_findrdataset(db, node, version,
 1929                          dns_rdatatype_aaaa, 0, client->now,
 1930                          rdataset, sigrdataset);
 1931         if (result == DNS_R_NCACHENXDOMAIN) {
 1932             goto addname;
 1933         } else if (result == DNS_R_NCACHENXRRSET) {
 1934             dns_rdataset_disassociate(rdataset);
 1935             if (sigrdataset != NULL &&
 1936                 dns_rdataset_isassociated(sigrdataset)) {
 1937                 dns_rdataset_disassociate(sigrdataset);
 1938             }
 1939         } else if (result == ISC_R_SUCCESS) {
 1940             bool invalid = false;
 1941             mname = NULL;
 1942 
 1943             if (additionaltype ==
 1944                     dns_rdatasetadditional_fromcache &&
 1945                 (DNS_TRUST_PENDING(rdataset->trust) ||
 1946                  DNS_TRUST_GLUE(rdataset->trust)))
 1947             {
 1948                 /* validate() may change rdataset->trust */
 1949                 invalid = !validate(client, db, fname, rdataset,
 1950                             sigrdataset);
 1951             }
 1952 
 1953             if (invalid && DNS_TRUST_PENDING(rdataset->trust)) {
 1954                 dns_rdataset_disassociate(rdataset);
 1955                 if (sigrdataset != NULL &&
 1956                     dns_rdataset_isassociated(sigrdataset)) {
 1957                     dns_rdataset_disassociate(sigrdataset);
 1958                 }
 1959             } else if (!query_isduplicate(client, fname,
 1960                               dns_rdatatype_aaaa,
 1961                               &mname)) {
 1962                 if (mname != fname) {
 1963                     if (mname != NULL) {
 1964                         ns_client_releasename(client,
 1965                                       &fname);
 1966                         fname = mname;
 1967                     } else {
 1968                         need_addname = true;
 1969                     }
 1970                 }
 1971                 ISC_LIST_APPEND(fname->list, rdataset, link);
 1972                 added_something = true;
 1973                 if (sigrdataset != NULL &&
 1974                     dns_rdataset_isassociated(sigrdataset)) {
 1975                     ISC_LIST_APPEND(fname->list,
 1976                             sigrdataset, link);
 1977                     sigrdataset = NULL;
 1978                 }
 1979                 rdataset = NULL;
 1980             }
 1981         }
 1982     }
 1983 
 1984 addname:
 1985     CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: addname");
 1986     /*
 1987      * If we haven't added anything, then we're done.
 1988      */
 1989     if (!added_something) {
 1990         goto cleanup;
 1991     }
 1992 
 1993     /*
 1994      * We may have added our rdatasets to an existing name, if so, then
 1995      * need_addname will be false.  Whether we used an existing name
 1996      * or a new one, we must set fname to NULL to prevent cleanup.
 1997      */
 1998     if (need_addname) {
 1999         dns_message_addname(client->message, fname,
 2000                     DNS_SECTION_ADDITIONAL);
 2001     }
 2002     fname = NULL;
 2003 
 2004     /*
 2005      * In a few cases, we want to add additional data for additional
 2006      * data.  It's simpler to just deal with special cases here than
 2007      * to try to create a general purpose mechanism and allow the
 2008      * rdata implementations to do it themselves.
 2009      *
 2010      * This involves recursion, but the depth is limited.  The
 2011      * most complex case is adding a SRV rdataset, which involves
 2012      * recursing to add address records, which in turn can cause
 2013      * recursion to add KEYs.
 2014      */
 2015     if (type == dns_rdatatype_srv && trdataset != NULL) {
 2016         /*
 2017          * If we're adding SRV records to the additional data
 2018          * section, it's helpful if we add the SRV additional data
 2019          * as well.
 2020          */
 2021         eresult = dns_rdataset_additionaldata(
 2022             trdataset, query_additional_cb, qctx);
 2023     }
 2024 
 2025 cleanup:
 2026     CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: cleanup");
 2027     ns_client_putrdataset(client, &rdataset);
 2028     if (sigrdataset != NULL) {
 2029         ns_client_putrdataset(client, &sigrdataset);
 2030     }
 2031     if (fname != NULL) {
 2032         ns_client_releasename(client, &fname);
 2033     }
 2034     if (node != NULL) {
 2035         dns_db_detachnode(db, &node);
 2036     }
 2037     if (db != NULL) {
 2038         dns_db_detach(&db);
 2039     }
 2040 
 2041     CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: done");
 2042     return (eresult);
 2043 }
 2044 
 2045 /*
 2046  * Add 'rdataset' to 'name'.
 2047  */
 2048 static inline void
 2049 query_addtoname(dns_name_t *name, dns_rdataset_t *rdataset) {
 2050     ISC_LIST_APPEND(name->list, rdataset, link);
 2051 }
 2052 
 2053 /*
 2054  * Set the ordering for 'rdataset'.
 2055  */
 2056 static void
 2057 query_setorder(query_ctx_t *qctx, dns_name_t *name, dns_rdataset_t *rdataset) {
 2058     ns_client_t *client = qctx->client;
 2059     dns_order_t *order = client->view->order;
 2060 
 2061     CTRACE(ISC_LOG_DEBUG(3), "query_setorder");
 2062 
 2063     UNUSED(client);
 2064 
 2065     if (order != NULL) {
 2066         rdataset->attributes |= dns_order_find(
 2067             order, name, rdataset->type, rdataset->rdclass);
 2068     }
 2069     rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
 2070 }
 2071 
 2072 /*
 2073  * Handle glue and fetch any other needed additional data for 'rdataset'.
 2074  */
 2075 static void
 2076 query_additional(query_ctx_t *qctx, dns_rdataset_t *rdataset) {
 2077     ns_client_t *client = qctx->client;
 2078     isc_result_t result;
 2079 
 2080     CTRACE(ISC_LOG_DEBUG(3), "query_additional");
 2081 
 2082     if (NOADDITIONAL(client)) {
 2083         return;
 2084     }
 2085 
 2086     /*
 2087      * Try to process glue directly.
 2088      */
 2089     if (qctx->view->use_glue_cache &&
 2090         (rdataset->type == dns_rdatatype_ns) &&
 2091         (client->query.gluedb != NULL) &&
 2092         dns_db_iszone(client->query.gluedb))
 2093     {
 2094         ns_dbversion_t *dbversion;
 2095 
 2096         dbversion = ns_client_findversion(client, client->query.gluedb);
 2097         if (dbversion == NULL) {
 2098             goto regular;
 2099         }
 2100 
 2101         result = dns_rdataset_addglue(rdataset, dbversion->version,
 2102                           client->message);
 2103         if (result == ISC_R_SUCCESS) {
 2104             return;
 2105         }
 2106     }
 2107 
 2108 regular:
 2109     /*
 2110      * Add other additional data if needed.
 2111      * We don't care if dns_rdataset_additionaldata() fails.
 2112      */
 2113     (void)dns_rdataset_additionaldata(rdataset, query_additional_cb, qctx);
 2114     CTRACE(ISC_LOG_DEBUG(3), "query_additional: done");
 2115 }
 2116 
 2117 static void
 2118 query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
 2119            dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
 2120            isc_buffer_t *dbuf, dns_section_t section) {
 2121     isc_result_t result;
 2122     ns_client_t *client = qctx->client;
 2123     dns_name_t *name = *namep, *mname = NULL;
 2124     dns_rdataset_t *rdataset = *rdatasetp, *mrdataset = NULL;
 2125     dns_rdataset_t *sigrdataset = NULL;
 2126 
 2127     CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
 2128 
 2129     REQUIRE(name != NULL);
 2130 
 2131     if (sigrdatasetp != NULL) {
 2132         sigrdataset = *sigrdatasetp;
 2133     }
 2134 
 2135     /*%
 2136      * To the current response for 'client', add the answer RRset
 2137      * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
 2138      * owner name '*namep', to section 'section', unless they are
 2139      * already there.  Also add any pertinent additional data.
 2140      *
 2141      * If 'dbuf' is not NULL, then '*namep' is the name whose data is
 2142      * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
 2143      * when it returns the name will either have been kept or released.
 2144      */
 2145     result = dns_message_findname(client->message, section, name,
 2146                       rdataset->type, rdataset->covers, &mname,
 2147                       &mrdataset);
 2148     if (result == ISC_R_SUCCESS) {
 2149         /*
 2150          * We've already got an RRset of the given name and type.
 2151          */
 2152         CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: dns_message_findname "
 2153                      "succeeded: done");
 2154         if (dbuf != NULL) {
 2155             ns_client_releasename(client, namep);
 2156         }
 2157         if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0) {
 2158             mrdataset->attributes |= DNS_RDATASETATTR_REQUIRED;
 2159         }
 2160         return;
 2161     } else if (result == DNS_R_NXDOMAIN) {
 2162         /*
 2163          * The name doesn't exist.
 2164          */
 2165         if (dbuf != NULL) {
 2166             ns_client_keepname(client, name, dbuf);
 2167         }
 2168         dns_message_addname(client->message, name, section);
 2169         *namep = NULL;
 2170         mname = name;
 2171     } else {
 2172         RUNTIME_CHECK(result == DNS_R_NXRRSET);
 2173         if (dbuf != NULL) {
 2174             ns_client_releasename(client, namep);
 2175         }
 2176     }
 2177 
 2178     if (rdataset->trust != dns_trust_secure &&
 2179         (section == DNS_SECTION_ANSWER || section == DNS_SECTION_AUTHORITY))
 2180     {
 2181         client->query.attributes &= ~NS_QUERYATTR_SECURE;
 2182     }
 2183 
 2184     /*
 2185      * Update message name, set rdataset order, and do additional
 2186      * section processing if needed.
 2187      */
 2188     query_addtoname(mname, rdataset);
 2189     query_setorder(qctx, mname, rdataset);
 2190     query_additional(qctx, rdataset);
 2191 
 2192     /*
 2193      * Note: we only add SIGs if we've added the type they cover, so
 2194      * we do not need to check if the SIG rdataset is already in the
 2195      * response.
 2196      */
 2197     *rdatasetp = NULL;
 2198     if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
 2199         /*
 2200          * We have a signature.  Add it to the response.
 2201          */
 2202         ISC_LIST_APPEND(mname->list, sigrdataset, link);
 2203         *sigrdatasetp = NULL;
 2204     }
 2205 
 2206     CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
 2207 }
 2208 
 2209 /*
 2210  * Mark the RRsets as secure.  Update the cache (db) to reflect the
 2211  * change in trust level.
 2212  */
 2213 static void
 2214 mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
 2215         dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
 2216         dns_rdataset_t *sigrdataset) {
 2217     isc_result_t result;
 2218     dns_dbnode_t *node = NULL;
 2219     dns_clientinfomethods_t cm;
 2220     dns_clientinfo_t ci;
 2221     isc_stdtime_t now;
 2222 
 2223     rdataset->trust = dns_trust_secure;
 2224     sigrdataset->trust = dns_trust_secure;
 2225     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 2226     dns_clientinfo_init(&ci, client, NULL);
 2227 
 2228     /*
 2229      * Save the updated secure state.  Ignore failures.
 2230      */
 2231     result = dns_db_findnodeext(db, name, true, &cm, &ci, &node);
 2232     if (result != ISC_R_SUCCESS) {
 2233         return;
 2234     }
 2235 
 2236     isc_stdtime_get(&now);
 2237     dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
 2238                  client->view->acceptexpired);
 2239 
 2240     (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset, 0,
 2241                  NULL);
 2242     (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset, 0,
 2243                  NULL);
 2244     dns_db_detachnode(db, &node);
 2245 }
 2246 
 2247 /*
 2248  * Find the secure key that corresponds to rrsig.
 2249  * Note: 'keyrdataset' maintains state between successive calls,
 2250  * there may be multiple keys with the same keyid.
 2251  * Return false if we have exhausted all the possible keys.
 2252  */
 2253 static bool
 2254 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
 2255     dns_rdataset_t *keyrdataset, dst_key_t **keyp) {
 2256     isc_result_t result;
 2257     dns_dbnode_t *node = NULL;
 2258     bool secure = false;
 2259     dns_clientinfomethods_t cm;
 2260     dns_clientinfo_t ci;
 2261 
 2262     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 2263     dns_clientinfo_init(&ci, client, NULL);
 2264 
 2265     if (!dns_rdataset_isassociated(keyrdataset)) {
 2266         result = dns_db_findnodeext(db, &rrsig->signer, false, &cm, &ci,
 2267                         &node);
 2268         if (result != ISC_R_SUCCESS) {
 2269             return (false);
 2270         }
 2271 
 2272         result = dns_db_findrdataset(db, node, NULL,
 2273                          dns_rdatatype_dnskey, 0,
 2274                          client->now, keyrdataset, NULL);
 2275         dns_db_detachnode(db, &node);
 2276         if (result != ISC_R_SUCCESS) {
 2277             return (false);
 2278         }
 2279 
 2280         if (keyrdataset->trust != dns_trust_secure) {
 2281             return (false);
 2282         }
 2283 
 2284         result = dns_rdataset_first(keyrdataset);
 2285     } else {
 2286         result = dns_rdataset_next(keyrdataset);
 2287     }
 2288 
 2289     for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset))
 2290     {
 2291         dns_rdata_t rdata = DNS_RDATA_INIT;
 2292         isc_buffer_t b;
 2293 
 2294         dns_rdataset_current(keyrdataset, &rdata);
 2295         isc_buffer_init(&b, rdata.data, rdata.length);
 2296         isc_buffer_add(&b, rdata.length);
 2297         result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
 2298                      client->mctx, keyp);
 2299         if (result != ISC_R_SUCCESS) {
 2300             continue;
 2301         }
 2302         if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
 2303             rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
 2304             dst_key_iszonekey(*keyp))
 2305         {
 2306             secure = true;
 2307             break;
 2308         }
 2309         dst_key_free(keyp);
 2310     }
 2311     return (secure);
 2312 }
 2313 
 2314 static bool
 2315 verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
 2316        dns_rdata_t *rdata, ns_client_t *client) {
 2317     isc_result_t result;
 2318     dns_fixedname_t fixed;
 2319     bool ignore = false;
 2320 
 2321     dns_fixedname_init(&fixed);
 2322 
 2323 again:
 2324     result = dns_dnssec_verify(name, rdataset, key, ignore,
 2325                    client->view->maxbits, client->mctx, rdata,
 2326                    NULL);
 2327     if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) {
 2328         ignore = true;
 2329         goto again;
 2330     }
 2331     if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
 2332         return (true);
 2333     }
 2334     return (false);
 2335 }
 2336 
 2337 /*
 2338  * Validate the rdataset if possible with available records.
 2339  */
 2340 static bool
 2341 validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
 2342      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
 2343     isc_result_t result;
 2344     dns_rdata_t rdata = DNS_RDATA_INIT;
 2345     dns_rdata_rrsig_t rrsig;
 2346     dst_key_t *key = NULL;
 2347     dns_rdataset_t keyrdataset;
 2348 
 2349     if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset)) {
 2350         return (false);
 2351     }
 2352 
 2353     for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
 2354          result = dns_rdataset_next(sigrdataset))
 2355     {
 2356         dns_rdata_reset(&rdata);
 2357         dns_rdataset_current(sigrdataset, &rdata);
 2358         result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
 2359         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 2360         if (!dns_resolver_algorithm_supported(client->view->resolver,
 2361                               name, rrsig.algorithm))
 2362         {
 2363             continue;
 2364         }
 2365         if (!dns_name_issubdomain(name, &rrsig.signer)) {
 2366             continue;
 2367         }
 2368         dns_rdataset_init(&keyrdataset);
 2369         do {
 2370             if (!get_key(client, db, &rrsig, &keyrdataset, &key)) {
 2371                 break;
 2372             }
 2373             if (verify(key, name, rdataset, &rdata, client)) {
 2374                 dst_key_free(&key);
 2375                 dns_rdataset_disassociate(&keyrdataset);
 2376                 mark_secure(client, db, name, &rrsig, rdataset,
 2377                         sigrdataset);
 2378                 return (true);
 2379             }
 2380             dst_key_free(&key);
 2381         } while (1);
 2382         if (dns_rdataset_isassociated(&keyrdataset)) {
 2383             dns_rdataset_disassociate(&keyrdataset);
 2384         }
 2385     }
 2386     return (false);
 2387 }
 2388 
 2389 static void
 2390 fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
 2391     if (*rdataset == NULL) {
 2392         *rdataset = ns_client_newrdataset(client);
 2393     } else if (dns_rdataset_isassociated(*rdataset)) {
 2394         dns_rdataset_disassociate(*rdataset);
 2395     }
 2396 }
 2397 
 2398 static void
 2399 fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
 2400      isc_buffer_t *nbuf) {
 2401     if (*fname == NULL) {
 2402         *dbuf = ns_client_getnamebuf(client);
 2403         if (*dbuf == NULL) {
 2404             return;
 2405         }
 2406         *fname = ns_client_newname(client, *dbuf, nbuf);
 2407     }
 2408 }
 2409 
 2410 static void
 2411 free_devent(ns_client_t *client, isc_event_t **eventp,
 2412         dns_fetchevent_t **deventp) {
 2413     dns_fetchevent_t *devent = *deventp;
 2414 
 2415     REQUIRE((void *)(*eventp) == (void *)(*deventp));
 2416 
 2417     CTRACE(ISC_LOG_DEBUG(3), "free_devent");
 2418 
 2419     if (devent->fetch != NULL) {
 2420         dns_resolver_destroyfetch(&devent->fetch);
 2421     }
 2422     if (devent->node != NULL) {
 2423         dns_db_detachnode(devent->db, &devent->node);
 2424     }
 2425     if (devent->db != NULL) {
 2426         dns_db_detach(&devent->db);
 2427     }
 2428     if (devent->rdataset != NULL) {
 2429         ns_client_putrdataset(client, &devent->rdataset);
 2430     }
 2431     if (devent->sigrdataset != NULL) {
 2432         ns_client_putrdataset(client, &devent->sigrdataset);
 2433     }
 2434 
 2435     /*
 2436      * If the two pointers are the same then leave the setting of
 2437      * (*deventp) to NULL to isc_event_free.
 2438      */
 2439     if ((void *)eventp != (void *)deventp) {
 2440         (*deventp) = NULL;
 2441     }
 2442     isc_event_free(eventp);
 2443 }
 2444 
 2445 static void
 2446 prefetch_done(isc_task_t *task, isc_event_t *event) {
 2447     dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
 2448     ns_client_t *client;
 2449 
 2450     UNUSED(task);
 2451 
 2452     REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
 2453     client = devent->ev_arg;
 2454     REQUIRE(NS_CLIENT_VALID(client));
 2455     REQUIRE(task == client->task);
 2456 
 2457     CTRACE(ISC_LOG_DEBUG(3), "prefetch_done");
 2458 
 2459     LOCK(&client->query.fetchlock);
 2460     if (client->query.prefetch != NULL) {
 2461         INSIST(devent->fetch == client->query.prefetch);
 2462         client->query.prefetch = NULL;
 2463     }
 2464     UNLOCK(&client->query.fetchlock);
 2465 
 2466     /*
 2467      * We're done prefetching, detach from quota.
 2468      */
 2469     if (client->recursionquota != NULL) {
 2470         isc_quota_detach(&client->recursionquota);
 2471     }
 2472 
 2473     free_devent(client, &event, &devent);
 2474     isc_nmhandle_unref(client->handle);
 2475 }
 2476 
 2477 static void
 2478 query_prefetch(ns_client_t *client, dns_name_t *qname,
 2479            dns_rdataset_t *rdataset) {
 2480     isc_result_t result;
 2481     isc_sockaddr_t *peeraddr;
 2482     dns_rdataset_t *tmprdataset;
 2483     unsigned int options;
 2484 
 2485     CTRACE(ISC_LOG_DEBUG(3), "query_prefetch");
 2486 
 2487     if (client->query.prefetch != NULL ||
 2488         client->view->prefetch_trigger == 0U ||
 2489         rdataset->ttl > client->view->prefetch_trigger ||
 2490         (rdataset->attributes & DNS_RDATASETATTR_PREFETCH) == 0)
 2491     {
 2492         return;
 2493     }
 2494 
 2495     if (client->recursionquota == NULL) {
 2496         result = isc_quota_attach(&client->sctx->recursionquota,
 2497                       &client->recursionquota);
 2498         if (result == ISC_R_SOFTQUOTA) {
 2499             isc_quota_detach(&client->recursionquota);
 2500         }
 2501         if (result != ISC_R_SUCCESS) {
 2502             return;
 2503         }
 2504     }
 2505 
 2506     tmprdataset = ns_client_newrdataset(client);
 2507     if (tmprdataset == NULL) {
 2508         return;
 2509     }
 2510 
 2511     if (!TCP(client)) {
 2512         peeraddr = &client->peeraddr;
 2513     } else {
 2514         peeraddr = NULL;
 2515     }
 2516 
 2517     isc_nmhandle_ref(client->handle);
 2518     options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
 2519     result = dns_resolver_createfetch(
 2520         client->view->resolver, qname, rdataset->type, NULL, NULL, NULL,
 2521         peeraddr, client->message->id, options, 0, NULL, client->task,
 2522         prefetch_done, client, tmprdataset, NULL,
 2523         &client->query.prefetch);
 2524     if (result != ISC_R_SUCCESS) {
 2525         ns_client_putrdataset(client, &tmprdataset);
 2526         isc_nmhandle_unref(client->handle);
 2527     }
 2528 
 2529     dns_rdataset_clearprefetch(rdataset);
 2530     ns_stats_increment(client->sctx->nsstats, ns_statscounter_prefetch);
 2531 }
 2532 
 2533 static inline void
 2534 rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
 2535       dns_rdataset_t **rdatasetp) {
 2536     if (nodep != NULL && *nodep != NULL) {
 2537         REQUIRE(dbp != NULL && *dbp != NULL);
 2538         dns_db_detachnode(*dbp, nodep);
 2539     }
 2540     if (dbp != NULL && *dbp != NULL) {
 2541         dns_db_detach(dbp);
 2542     }
 2543     if (zonep != NULL && *zonep != NULL) {
 2544         dns_zone_detach(zonep);
 2545     }
 2546     if (rdatasetp != NULL && *rdatasetp != NULL &&
 2547         dns_rdataset_isassociated(*rdatasetp))
 2548     {
 2549         dns_rdataset_disassociate(*rdatasetp);
 2550     }
 2551 }
 2552 
 2553 static inline void
 2554 rpz_match_clear(dns_rpz_st_t *st) {
 2555     rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
 2556     st->m.version = NULL;
 2557 }
 2558 
 2559 static inline isc_result_t
 2560 rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) {
 2561     REQUIRE(rdatasetp != NULL);
 2562 
 2563     CTRACE(ISC_LOG_DEBUG(3), "rpz_ready");
 2564 
 2565     if (*rdatasetp == NULL) {
 2566         *rdatasetp = ns_client_newrdataset(client);
 2567         if (*rdatasetp == NULL) {
 2568             CTRACE(ISC_LOG_ERROR, "rpz_ready: "
 2569                           "ns_client_newrdataset failed");
 2570             return (DNS_R_SERVFAIL);
 2571         }
 2572     } else if (dns_rdataset_isassociated(*rdatasetp)) {
 2573         dns_rdataset_disassociate(*rdatasetp);
 2574     }
 2575     return (ISC_R_SUCCESS);
 2576 }
 2577 
 2578 static void
 2579 rpz_st_clear(ns_client_t *client) {
 2580     dns_rpz_st_t *st = client->query.rpz_st;
 2581 
 2582     CTRACE(ISC_LOG_DEBUG(3), "rpz_st_clear");
 2583 
 2584     if (st->m.rdataset != NULL) {
 2585         ns_client_putrdataset(client, &st->m.rdataset);
 2586     }
 2587     rpz_match_clear(st);
 2588 
 2589     rpz_clean(NULL, &st->r.db, NULL, NULL);
 2590     if (st->r.ns_rdataset != NULL) {
 2591         ns_client_putrdataset(client, &st->r.ns_rdataset);
 2592     }
 2593     if (st->r.r_rdataset != NULL) {
 2594         ns_client_putrdataset(client, &st->r.r_rdataset);
 2595     }
 2596 
 2597     rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
 2598     if (st->q.rdataset != NULL) {
 2599         ns_client_putrdataset(client, &st->q.rdataset);
 2600     }
 2601     if (st->q.sigrdataset != NULL) {
 2602         ns_client_putrdataset(client, &st->q.sigrdataset);
 2603     }
 2604     st->state = 0;
 2605     st->m.type = DNS_RPZ_TYPE_BAD;
 2606     st->m.policy = DNS_RPZ_POLICY_MISS;
 2607     if (st->rpsdb != NULL) {
 2608         dns_db_detach(&st->rpsdb);
 2609     }
 2610 }
 2611 
 2612 static dns_rpz_zbits_t
 2613 rpz_get_zbits(ns_client_t *client, dns_rdatatype_t ip_type,
 2614           dns_rpz_type_t rpz_type) {
 2615     dns_rpz_st_t *st;
 2616     dns_rpz_zbits_t zbits = 0;
 2617 
 2618     REQUIRE(client != NULL);
 2619     REQUIRE(client->query.rpz_st != NULL);
 2620 
 2621     st = client->query.rpz_st;
 2622 
 2623 #ifdef USE_DNSRPS
 2624     if (st->popt.dnsrps_enabled) {
 2625         if (st->rpsdb == NULL ||
 2626             librpz->have_trig(dns_dnsrps_type2trig(rpz_type),
 2627                       ip_type == dns_rdatatype_aaaa,
 2628                       ((rpsdb_t *)st->rpsdb)->rsp))
 2629         {
 2630             return (DNS_RPZ_ALL_ZBITS);
 2631         }
 2632         return (0);
 2633     }
 2634 #endif /* ifdef USE_DNSRPS */
 2635 
 2636     switch (rpz_type) {
 2637     case DNS_RPZ_TYPE_CLIENT_IP:
 2638         zbits = st->have.client_ip;
 2639         break;
 2640     case DNS_RPZ_TYPE_QNAME:
 2641         zbits = st->have.qname;
 2642         break;
 2643     case DNS_RPZ_TYPE_IP:
 2644         if (ip_type == dns_rdatatype_a) {
 2645             zbits = st->have.ipv4;
 2646         } else if (ip_type == dns_rdatatype_aaaa) {
 2647             zbits = st->have.ipv6;
 2648         } else {
 2649             zbits = st->have.ip;
 2650         }
 2651         break;
 2652     case DNS_RPZ_TYPE_NSDNAME:
 2653         zbits = st->have.nsdname;
 2654         break;
 2655     case DNS_RPZ_TYPE_NSIP:
 2656         if (ip_type == dns_rdatatype_a) {
 2657             zbits = st->have.nsipv4;
 2658         } else if (ip_type == dns_rdatatype_aaaa) {
 2659             zbits = st->have.nsipv6;
 2660         } else {
 2661             zbits = st->have.nsip;
 2662         }
 2663         break;
 2664     default:
 2665         INSIST(0);
 2666         ISC_UNREACHABLE();
 2667     }
 2668 
 2669     /*
 2670      * Choose
 2671      *  the earliest configured policy zone (rpz->num)
 2672      *  QNAME over IP over NSDNAME over NSIP (rpz_type)
 2673      *  the smallest name,
 2674      *  the longest IP address prefix,
 2675      *  the lexically smallest address.
 2676      */
 2677     if (st->m.policy != DNS_RPZ_POLICY_MISS) {
 2678         if (st->m.type >= rpz_type) {
 2679             zbits &= DNS_RPZ_ZMASK(st->m.rpz->num);
 2680         } else {
 2681             zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1;
 2682         }
 2683     }
 2684 
 2685     /*
 2686      * If the client wants recursion, allow only compatible policies.
 2687      */
 2688     if (!RECURSIONOK(client)) {
 2689         zbits &= st->popt.no_rd_ok;
 2690     }
 2691 
 2692     return (zbits);
 2693 }
 2694 
 2695 static void
 2696 query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
 2697     isc_result_t result;
 2698     isc_sockaddr_t *peeraddr;
 2699     dns_rdataset_t *tmprdataset;
 2700     unsigned int options;
 2701 
 2702     CTRACE(ISC_LOG_DEBUG(3), "query_rpzfetch");
 2703 
 2704     if (client->query.prefetch != NULL) {
 2705         return;
 2706     }
 2707 
 2708     if (client->recursionquota == NULL) {
 2709         result = isc_quota_attach(&client->sctx->recursionquota,
 2710                       &client->recursionquota);
 2711         if (result == ISC_R_SOFTQUOTA) {
 2712             isc_quota_detach(&client->recursionquota);
 2713         }
 2714         if (result != ISC_R_SUCCESS) {
 2715             return;
 2716         }
 2717     }
 2718 
 2719     tmprdataset = ns_client_newrdataset(client);
 2720     if (tmprdataset == NULL) {
 2721         return;
 2722     }
 2723 
 2724     if (!TCP(client)) {
 2725         peeraddr = &client->peeraddr;
 2726     } else {
 2727         peeraddr = NULL;
 2728     }
 2729 
 2730     options = client->query.fetchoptions;
 2731     isc_nmhandle_ref(client->handle);
 2732     result = dns_resolver_createfetch(
 2733         client->view->resolver, qname, type, NULL, NULL, NULL, peeraddr,
 2734         client->message->id, options, 0, NULL, client->task,
 2735         prefetch_done, client, tmprdataset, NULL,
 2736         &client->query.prefetch);
 2737     if (result != ISC_R_SUCCESS) {
 2738         ns_client_putrdataset(client, &tmprdataset);
 2739         isc_nmhandle_unref(client->handle);
 2740     }
 2741 }
 2742 
 2743 /*
 2744  * Get an NS, A, or AAAA rrset related to the response for the client
 2745  * to check the contents of that rrset for hits by eligible policy zones.
 2746  */
 2747 static isc_result_t
 2748 rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
 2749            dns_rpz_type_t rpz_type, dns_db_t **dbp,
 2750            dns_dbversion_t *version, dns_rdataset_t **rdatasetp,
 2751            bool resuming) {
 2752     dns_rpz_st_t *st;
 2753     bool is_zone;
 2754     dns_dbnode_t *node;
 2755     dns_fixedname_t fixed;
 2756     dns_name_t *found;
 2757     isc_result_t result;
 2758     dns_clientinfomethods_t cm;
 2759     dns_clientinfo_t ci;
 2760 
 2761     CTRACE(ISC_LOG_DEBUG(3), "rpz_rrset_find");
 2762 
 2763     st = client->query.rpz_st;
 2764     if ((st->state & DNS_RPZ_RECURSING) != 0) {
 2765         INSIST(st->r.r_type == type);
 2766         INSIST(dns_name_equal(name, st->r_name));
 2767         INSIST(*rdatasetp == NULL ||
 2768                !dns_rdataset_isassociated(*rdatasetp));
 2769         st->state &= ~DNS_RPZ_RECURSING;
 2770         RESTORE(*dbp, st->r.db);
 2771         if (*rdatasetp != NULL) {
 2772             ns_client_putrdataset(client, rdatasetp);
 2773         }
 2774         RESTORE(*rdatasetp, st->r.r_rdataset);
 2775         result = st->r.r_result;
 2776         if (result == DNS_R_DELEGATION) {
 2777             CTRACE(ISC_LOG_ERROR, "RPZ recursing");
 2778             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
 2779                      rpz_type, "rpz_rrset_find(1)", result);
 2780             st->m.policy = DNS_RPZ_POLICY_ERROR;
 2781             result = DNS_R_SERVFAIL;
 2782         }
 2783         return (result);
 2784     }
 2785 
 2786     result = rpz_ready(client, rdatasetp);
 2787     if (result != ISC_R_SUCCESS) {
 2788         st->m.policy = DNS_RPZ_POLICY_ERROR;
 2789         return (result);
 2790     }
 2791     if (*dbp != NULL) {
 2792         is_zone = false;
 2793     } else {
 2794         dns_zone_t *zone;
 2795 
 2796         version = NULL;
 2797         zone = NULL;
 2798         result = query_getdb(client, name, type, 0, &zone, dbp,
 2799                      &version, &is_zone);
 2800         if (result != ISC_R_SUCCESS) {
 2801             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
 2802                      rpz_type, "rpz_rrset_find(2)", result);
 2803             st->m.policy = DNS_RPZ_POLICY_ERROR;
 2804             if (zone != NULL) {
 2805                 dns_zone_detach(&zone);
 2806             }
 2807             return (result);
 2808         }
 2809         if (zone != NULL) {
 2810             dns_zone_detach(&zone);
 2811         }
 2812     }
 2813 
 2814     node = NULL;
 2815     found = dns_fixedname_initname(&fixed);
 2816     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 2817     dns_clientinfo_init(&ci, client, NULL);
 2818     result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK,
 2819                 client->now, &node, found, &cm, &ci, *rdatasetp,
 2820                 NULL);
 2821     if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
 2822         /*
 2823          * Try the cache if we're authoritative for an
 2824          * ancestor but not the domain itself.
 2825          */
 2826         rpz_clean(NULL, dbp, &node, rdatasetp);
 2827         version = NULL;
 2828         dns_db_attach(client->view->cachedb, dbp);
 2829         result = dns_db_findext(*dbp, name, version, type, 0,
 2830                     client->now, &node, found, &cm, &ci,
 2831                     *rdatasetp, NULL);
 2832     }
 2833     rpz_clean(NULL, dbp, &node, NULL);
 2834     if (result == DNS_R_DELEGATION) {
 2835         rpz_clean(NULL, NULL, NULL, rdatasetp);
 2836         /*
 2837          * Recurse for NS rrset or A or AAAA rrset for an NS.
 2838          * Do not recurse for addresses for the query name.
 2839          */
 2840         if (rpz_type == DNS_RPZ_TYPE_IP) {
 2841             result = DNS_R_NXRRSET;
 2842         } else if (!client->view->rpzs->p.nsip_wait_recurse) {
 2843             query_rpzfetch(client, name, type);
 2844             result = DNS_R_NXRRSET;
 2845         } else {
 2846             dns_name_copynf(name, st->r_name);
 2847             result = ns_query_recurse(client, type, st->r_name,
 2848                           NULL, NULL, resuming);
 2849             if (result == ISC_R_SUCCESS) {
 2850                 st->state |= DNS_RPZ_RECURSING;
 2851                 result = DNS_R_DELEGATION;
 2852             }
 2853         }
 2854     }
 2855     return (result);
 2856 }
 2857 
 2858 /*
 2859  * Compute a policy owner name, p_name, in a policy zone given the needed
 2860  * policy type and the trigger name.
 2861  */
 2862 static isc_result_t
 2863 rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, dns_rpz_zone_t *rpz,
 2864            dns_rpz_type_t rpz_type, dns_name_t *trig_name) {
 2865     dns_offsets_t prefix_offsets;
 2866     dns_name_t prefix, *suffix;
 2867     unsigned int first, labels;
 2868     isc_result_t result;
 2869 
 2870     CTRACE(ISC_LOG_DEBUG(3), "rpz_get_p_name");
 2871 
 2872     /*
 2873      * The policy owner name consists of a suffix depending on the type
 2874      * and policy zone and a prefix that is the longest possible string
 2875      * from the trigger name that keesp the resulting policy owner name
 2876      * from being too long.
 2877      */
 2878     switch (rpz_type) {
 2879     case DNS_RPZ_TYPE_CLIENT_IP:
 2880         suffix = &rpz->client_ip;
 2881         break;
 2882     case DNS_RPZ_TYPE_QNAME:
 2883         suffix = &rpz->origin;
 2884         break;
 2885     case DNS_RPZ_TYPE_IP:
 2886         suffix = &rpz->ip;
 2887         break;
 2888     case DNS_RPZ_TYPE_NSDNAME:
 2889         suffix = &rpz->nsdname;
 2890         break;
 2891     case DNS_RPZ_TYPE_NSIP:
 2892         suffix = &rpz->nsip;
 2893         break;
 2894     default:
 2895         INSIST(0);
 2896         ISC_UNREACHABLE();
 2897     }
 2898 
 2899     /*
 2900      * Start with relative version of the full trigger name,
 2901      * and trim enough allow the addition of the suffix.
 2902      */
 2903     dns_name_init(&prefix, prefix_offsets);
 2904     labels = dns_name_countlabels(trig_name);
 2905     first = 0;
 2906     for (;;) {
 2907         dns_name_getlabelsequence(trig_name, first, labels - first - 1,
 2908                       &prefix);
 2909         result = dns_name_concatenate(&prefix, suffix, p_name, NULL);
 2910         if (result == ISC_R_SUCCESS) {
 2911             break;
 2912         }
 2913         INSIST(result == DNS_R_NAMETOOLONG);
 2914         /*
 2915          * Trim the trigger name until the combination is not too long.
 2916          */
 2917         if (labels - first < 2) {
 2918             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix,
 2919                      rpz_type, "concatenate()", result);
 2920             return (ISC_R_FAILURE);
 2921         }
 2922         /*
 2923          * Complain once about trimming the trigger name.
 2924          */
 2925         if (first == 0) {
 2926             rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix,
 2927                      rpz_type, "concatenate()", result);
 2928         }
 2929         ++first;
 2930     }
 2931     return (ISC_R_SUCCESS);
 2932 }
 2933 
 2934 /*
 2935  * Look in policy zone rpz for a policy of rpz_type by p_name.
 2936  * The self-name (usually the client qname or an NS name) is compared with
 2937  * the target of a CNAME policy for the old style passthru encoding.
 2938  * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep,
 2939  * *rdatasetp, and *policyp.
 2940  * The target DNS type, qtype, chooses the best rdataset for *rdatasetp.
 2941  * The caller must decide if the found policy is most suitable, including
 2942  * better than a previously found policy.
 2943  * If it is best, the caller records it in client->query.rpz_st->m.
 2944  */
 2945 static isc_result_t
 2946 rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
 2947        dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
 2948        dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
 2949        dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
 2950        dns_rpz_policy_t *policyp) {
 2951     dns_fixedname_t foundf;
 2952     dns_name_t *found;
 2953     isc_result_t result;
 2954     dns_clientinfomethods_t cm;
 2955     dns_clientinfo_t ci;
 2956     bool found_a = false;
 2957 
 2958     REQUIRE(nodep != NULL);
 2959 
 2960     CTRACE(ISC_LOG_DEBUG(3), "rpz_find_p");
 2961 
 2962     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 2963     dns_clientinfo_init(&ci, client, NULL);
 2964 
 2965     /*
 2966      * Try to find either a CNAME or the type of record demanded by the
 2967      * request from the policy zone.
 2968      */
 2969     rpz_clean(zonep, dbp, nodep, rdatasetp);
 2970     result = rpz_ready(client, rdatasetp);
 2971     if (result != ISC_R_SUCCESS) {
 2972         CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
 2973         return (DNS_R_SERVFAIL);
 2974     }
 2975     *versionp = NULL;
 2976     result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
 2977     if (result != ISC_R_SUCCESS) {
 2978         return (DNS_R_NXDOMAIN);
 2979     }
 2980     found = dns_fixedname_initname(&foundf);
 2981 
 2982     result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0,
 2983                 client->now, nodep, found, &cm, &ci, *rdatasetp,
 2984                 NULL);
 2985     /*
 2986      * Choose the best rdataset if we found something.
 2987      */
 2988     if (result == ISC_R_SUCCESS) {
 2989         dns_rdatasetiter_t *rdsiter;
 2990 
 2991         rdsiter = NULL;
 2992         result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0,
 2993                          &rdsiter);
 2994         if (result != ISC_R_SUCCESS) {
 2995             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
 2996                      rpz_type, "allrdatasets()", result);
 2997             CTRACE(ISC_LOG_ERROR,
 2998                    "rpz_find_p: allrdatasets failed");
 2999             return (DNS_R_SERVFAIL);
 3000         }
 3001         if (qtype == dns_rdatatype_aaaa &&
 3002             !ISC_LIST_EMPTY(client->view->dns64)) {
 3003             for (result = dns_rdatasetiter_first(rdsiter);
 3004                  result == ISC_R_SUCCESS;
 3005                  result = dns_rdatasetiter_next(rdsiter))
 3006             {
 3007                 dns_rdatasetiter_current(rdsiter, *rdatasetp);
 3008                 if ((*rdatasetp)->type == dns_rdatatype_a) {
 3009                     found_a = true;
 3010                 }
 3011                 dns_rdataset_disassociate(*rdatasetp);
 3012             }
 3013         }
 3014         for (result = dns_rdatasetiter_first(rdsiter);
 3015              result == ISC_R_SUCCESS;
 3016              result = dns_rdatasetiter_next(rdsiter))
 3017         {
 3018             dns_rdatasetiter_current(rdsiter, *rdatasetp);
 3019             if ((*rdatasetp)->type == dns_rdatatype_cname ||
 3020                 (*rdatasetp)->type == qtype) {
 3021                 break;
 3022             }
 3023             dns_rdataset_disassociate(*rdatasetp);
 3024         }
 3025         dns_rdatasetiter_destroy(&rdsiter);
 3026         if (result != ISC_R_SUCCESS) {
 3027             if (result != ISC_R_NOMORE) {
 3028                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
 3029                          p_name, rpz_type, "rdatasetiter",
 3030                          result);
 3031                 CTRACE(ISC_LOG_ERROR, "rpz_find_p: "
 3032                               "rdatasetiter failed");
 3033                 return (DNS_R_SERVFAIL);
 3034             }
 3035             /*
 3036              * Ask again to get the right DNS_R_DNAME/NXRRSET/...
 3037              * result if there is neither a CNAME nor target type.
 3038              */
 3039             if (dns_rdataset_isassociated(*rdatasetp)) {
 3040                 dns_rdataset_disassociate(*rdatasetp);
 3041             }
 3042             dns_db_detachnode(*dbp, nodep);
 3043 
 3044             if (qtype == dns_rdatatype_rrsig ||
 3045                 qtype == dns_rdatatype_sig) {
 3046                 result = DNS_R_NXRRSET;
 3047             } else {
 3048                 result = dns_db_findext(*dbp, p_name, *versionp,
 3049                             qtype, 0, client->now,
 3050                             nodep, found, &cm, &ci,
 3051                             *rdatasetp, NULL);
 3052             }
 3053         }
 3054     }
 3055     switch (result) {
 3056     case ISC_R_SUCCESS:
 3057         if ((*rdatasetp)->type != dns_rdatatype_cname) {
 3058             *policyp = DNS_RPZ_POLICY_RECORD;
 3059         } else {
 3060             *policyp = dns_rpz_decode_cname(rpz, *rdatasetp,
 3061                             self_name);
 3062             if ((*policyp == DNS_RPZ_POLICY_RECORD ||
 3063                  *policyp == DNS_RPZ_POLICY_WILDCNAME) &&
 3064                 qtype != dns_rdatatype_cname &&
 3065                 qtype != dns_rdatatype_any)
 3066             {
 3067                 return (DNS_R_CNAME);
 3068             }
 3069         }
 3070         return (ISC_R_SUCCESS);
 3071     case DNS_R_NXRRSET:
 3072         if (found_a) {
 3073             *policyp = DNS_RPZ_POLICY_DNS64;
 3074         } else {
 3075             *policyp = DNS_RPZ_POLICY_NODATA;
 3076         }
 3077         return (result);
 3078     case DNS_R_DNAME:
 3079     /*
 3080      * DNAME policy RRs have very few if any uses that are not
 3081      * better served with simple wildcards.  Making them work would
 3082      * require complications to get the number of labels matched
 3083      * in the name or the found name to the main DNS_R_DNAME case
 3084      * in query_dname().  The domain also does not appear in the
 3085      * summary database at the right level, so this happens only
 3086      * with a single policy zone when we have no summary database.
 3087      * Treat it as a miss.
 3088      */
 3089     case DNS_R_NXDOMAIN:
 3090     case DNS_R_EMPTYNAME:
 3091         return (DNS_R_NXDOMAIN);
 3092     default:
 3093         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, "",
 3094                  result);
 3095         CTRACE(ISC_LOG_ERROR, "rpz_find_p: unexpected result");
 3096         return (DNS_R_SERVFAIL);
 3097     }
 3098 }
 3099 
 3100 static void
 3101 rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
 3102        dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix,
 3103        isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp,
 3104        dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
 3105        dns_dbversion_t *version) {
 3106     dns_rdataset_t *trdataset = NULL;
 3107 
 3108     rpz_match_clear(st);
 3109     st->m.rpz = rpz;
 3110     st->m.type = rpz_type;
 3111     st->m.policy = policy;
 3112     dns_name_copynf(p_name, st->p_name);
 3113     st->m.prefix = prefix;
 3114     st->m.result = result;
 3115     SAVE(st->m.zone, *zonep);
 3116     SAVE(st->m.db, *dbp);
 3117     SAVE(st->m.node, *nodep);
 3118     if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) {
 3119         /*
 3120          * Save the replacement rdataset from the policy
 3121          * and make the previous replacement rdataset scratch.
 3122          */
 3123         SAVE(trdataset, st->m.rdataset);
 3124         SAVE(st->m.rdataset, *rdatasetp);
 3125         SAVE(*rdatasetp, trdataset);
 3126         st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl);
 3127     } else {
 3128         st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl);
 3129     }
 3130     SAVE(st->m.version, version);
 3131 }
 3132 
 3133 #ifdef USE_DNSRPS
 3134 /*
 3135  * Check the results of a RPZ service interface lookup.
 3136  * Stop after an error (<0) or not a hit on a disabled zone (0).
 3137  * Continue after a hit on a disabled zone (>0).
 3138  */
 3139 static int
 3140 dnsrps_ck(librpz_emsg_t *emsg, ns_client_t *client, rpsdb_t *rpsdb,
 3141       bool recursed) {
 3142     isc_region_t region;
 3143     librpz_domain_buf_t pname_buf;
 3144 
 3145     if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
 3146         return (-1);
 3147     }
 3148 
 3149     /*
 3150      * Forget the state from before the IP address or domain check
 3151      * if the lookup hit nothing.
 3152      */
 3153     if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED ||
 3154         rpsdb->result.hit_id != rpsdb->hit_id ||
 3155         rpsdb->result.policy != LIBRPZ_POLICY_DISABLED)
 3156     {
 3157         if (!librpz->rsp_pop_discard(emsg, rpsdb->rsp)) {
 3158             return (-1);
 3159         }
 3160         return (0);
 3161     }
 3162 
 3163     /*
 3164      * Log a hit on a disabled zone.
 3165      * Forget the zone to not try it again, and restore the pre-hit state.
 3166      */
 3167     if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
 3168         return (-1);
 3169     }
 3170     region.base = pname_buf.d;
 3171     region.length = pname_buf.size;
 3172     dns_name_fromregion(client->query.rpz_st->p_name, &region);
 3173     rpz_log_rewrite(client, true, dns_dnsrps_2policy(rpsdb->result.zpolicy),
 3174             dns_dnsrps_trig2type(rpsdb->result.trig), NULL,
 3175             client->query.rpz_st->p_name, NULL,
 3176             rpsdb->result.cznum);
 3177 
 3178     if (!librpz->rsp_forget_zone(emsg, rpsdb->result.cznum, rpsdb->rsp) ||
 3179         !librpz->rsp_pop(emsg, &rpsdb->result, rpsdb->rsp))
 3180     {
 3181         return (-1);
 3182     }
 3183     return (1);
 3184 }
 3185 
 3186 /*
 3187  * Ready the shim database and rdataset for a DNSRPS hit.
 3188  */
 3189 static bool
 3190 dnsrps_set_p(librpz_emsg_t *emsg, ns_client_t *client, dns_rpz_st_t *st,
 3191          dns_rdatatype_t qtype, dns_rdataset_t **p_rdatasetp,
 3192          bool recursed) {
 3193     rpsdb_t *rpsdb;
 3194     librpz_domain_buf_t pname_buf;
 3195     isc_region_t region;
 3196     dns_zone_t *p_zone;
 3197     dns_db_t *p_db;
 3198     dns_dbnode_t *p_node;
 3199     dns_rpz_policy_t policy;
 3200     dns_fixedname_t foundf;
 3201     dns_name_t *found;
 3202     dns_rdatatype_t foundtype, searchtype;
 3203     isc_result_t result;
 3204 
 3205     rpsdb = (rpsdb_t *)st->rpsdb;
 3206 
 3207     if (!librpz->rsp_result(emsg, &rpsdb->result, recursed, rpsdb->rsp)) {
 3208         return (false);
 3209     }
 3210 
 3211     if (rpsdb->result.policy == LIBRPZ_POLICY_UNDEFINED) {
 3212         return (true);
 3213     }
 3214 
 3215     /*
 3216      * Give the fake or shim DNSRPS database its new origin.
 3217      */
 3218     if (!librpz->rsp_soa(emsg, NULL, NULL, &rpsdb->origin_buf,
 3219                  &rpsdb->result, rpsdb->rsp))
 3220     {
 3221         return (false);
 3222     }
 3223     region.base = rpsdb->origin_buf.d;
 3224     region.length = rpsdb->origin_buf.size;
 3225     dns_name_fromregion(&rpsdb->common.origin, &region);
 3226 
 3227     if (!librpz->rsp_domain(emsg, &pname_buf, rpsdb->rsp)) {
 3228         return (false);
 3229     }
 3230     region.base = pname_buf.d;
 3231     region.length = pname_buf.size;
 3232     dns_name_fromregion(st->p_name, &region);
 3233 
 3234     p_zone = NULL;
 3235     p_db = NULL;
 3236     p_node = NULL;
 3237     rpz_ready(client, p_rdatasetp);
 3238     dns_db_attach(st->rpsdb, &p_db);
 3239     policy = dns_dnsrps_2policy(rpsdb->result.policy);
 3240     if (policy != DNS_RPZ_POLICY_RECORD) {
 3241         result = ISC_R_SUCCESS;
 3242     } else if (qtype == dns_rdatatype_rrsig) {
 3243         /*
 3244          * dns_find_db() refuses to look for and fail to
 3245          * find dns_rdatatype_rrsig.
 3246          */
 3247         result = DNS_R_NXRRSET;
 3248         policy = DNS_RPZ_POLICY_NODATA;
 3249     } else {
 3250         /*
 3251          * Get the next (and so first) RR from the policy node.
 3252          * If it is a CNAME, then look for it regardless of the
 3253          * query type.
 3254          */
 3255         if (!librpz->rsp_rr(emsg, &foundtype, NULL, NULL, NULL,
 3256                     &rpsdb->result, rpsdb->qname->ndata,
 3257                     rpsdb->qname->length, rpsdb->rsp))
 3258         {
 3259             return (false);
 3260         }
 3261         if (foundtype == dns_rdatatype_cname) {
 3262             searchtype = dns_rdatatype_cname;
 3263         } else {
 3264             searchtype = qtype;
 3265         }
 3266         /*
 3267          * Get the DNSPRS imitation rdataset.
 3268          */
 3269         found = dns_fixedname_initname(&foundf);
 3270         result = dns_db_find(p_db, st->p_name, NULL, searchtype, 0, 0,
 3271                      &p_node, found, *p_rdatasetp, NULL);
 3272 
 3273         if (result == ISC_R_SUCCESS) {
 3274             if (searchtype == dns_rdatatype_cname &&
 3275                 qtype != dns_rdatatype_cname) {
 3276                 result = DNS_R_CNAME;
 3277             }
 3278         } else if (result == DNS_R_NXRRSET) {
 3279             policy = DNS_RPZ_POLICY_NODATA;
 3280         } else {
 3281             snprintf(emsg->c, sizeof(emsg->c), "dns_db_find(): %s",
 3282                  isc_result_totext(result));
 3283             return (false);
 3284         }
 3285     }
 3286 
 3287     rpz_save_p(st, client->view->rpzs->zones[rpsdb->result.cznum],
 3288            dns_dnsrps_trig2type(rpsdb->result.trig), policy, st->p_name,
 3289            0, result, &p_zone, &p_db, &p_node, p_rdatasetp, NULL);
 3290 
 3291     rpz_clean(NULL, NULL, NULL, p_rdatasetp);
 3292 
 3293     return (true);
 3294 }
 3295 
 3296 static isc_result_t
 3297 dnsrps_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
 3298           dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
 3299     dns_rpz_st_t *st;
 3300     rpsdb_t *rpsdb;
 3301     librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
 3302     bool recursed = false;
 3303     int res;
 3304     librpz_emsg_t emsg;
 3305     isc_result_t result;
 3306 
 3307     st = client->query.rpz_st;
 3308     rpsdb = (rpsdb_t *)st->rpsdb;
 3309 
 3310     result = rpz_ready(client, p_rdatasetp);
 3311     if (result != ISC_R_SUCCESS) {
 3312         st->m.policy = DNS_RPZ_POLICY_ERROR;
 3313         return (result);
 3314     }
 3315 
 3316     switch (rpz_type) {
 3317     case DNS_RPZ_TYPE_CLIENT_IP:
 3318         trig = LIBRPZ_TRIG_CLIENT_IP;
 3319         recursed = false;
 3320         break;
 3321     case DNS_RPZ_TYPE_IP:
 3322         trig = LIBRPZ_TRIG_IP;
 3323         recursed = true;
 3324         break;
 3325     case DNS_RPZ_TYPE_NSIP:
 3326         trig = LIBRPZ_TRIG_NSIP;
 3327         recursed = true;
 3328         break;
 3329     default:
 3330         INSIST(0);
 3331         ISC_UNREACHABLE();
 3332     }
 3333 
 3334     do {
 3335         if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
 3336             !librpz->ck_ip(&emsg,
 3337                    netaddr->family == AF_INET
 3338                        ? (const void *)&netaddr->type.in
 3339                        : (const void *)&netaddr->type.in6,
 3340                    netaddr->family, trig, ++rpsdb->hit_id,
 3341                    recursed, rpsdb->rsp) ||
 3342             (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
 3343         {
 3344             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
 3345                      rpz_type, emsg.c, DNS_R_SERVFAIL);
 3346             st->m.policy = DNS_RPZ_POLICY_ERROR;
 3347             return (DNS_R_SERVFAIL);
 3348         }
 3349     } while (res != 0);
 3350     return (ISC_R_SUCCESS);
 3351 }
 3352 
 3353 static isc_result_t
 3354 dnsrps_rewrite_name(ns_client_t *client, dns_name_t *trig_name, bool recursed,
 3355             dns_rpz_type_t rpz_type, dns_rdataset_t **p_rdatasetp) {
 3356     dns_rpz_st_t *st;
 3357     rpsdb_t *rpsdb;
 3358     librpz_trig_t trig = LIBRPZ_TRIG_CLIENT_IP;
 3359     isc_region_t r;
 3360     int res;
 3361     librpz_emsg_t emsg;
 3362     isc_result_t result;
 3363 
 3364     st = client->query.rpz_st;
 3365     rpsdb = (rpsdb_t *)st->rpsdb;
 3366 
 3367     result = rpz_ready(client, p_rdatasetp);
 3368     if (result != ISC_R_SUCCESS) {
 3369         st->m.policy = DNS_RPZ_POLICY_ERROR;
 3370         return (result);
 3371     }
 3372 
 3373     switch (rpz_type) {
 3374     case DNS_RPZ_TYPE_QNAME:
 3375         trig = LIBRPZ_TRIG_QNAME;
 3376         break;
 3377     case DNS_RPZ_TYPE_NSDNAME:
 3378         trig = LIBRPZ_TRIG_NSDNAME;
 3379         break;
 3380     default:
 3381         INSIST(0);
 3382         ISC_UNREACHABLE();
 3383     }
 3384 
 3385     dns_name_toregion(trig_name, &r);
 3386     do {
 3387         if (!librpz->rsp_push(&emsg, rpsdb->rsp) ||
 3388             !librpz->ck_domain(&emsg, r.base, r.length, trig,
 3389                        ++rpsdb->hit_id, recursed, rpsdb->rsp) ||
 3390             (res = dnsrps_ck(&emsg, client, rpsdb, recursed)) < 0)
 3391         {
 3392             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
 3393                      rpz_type, emsg.c, DNS_R_SERVFAIL);
 3394             st->m.policy = DNS_RPZ_POLICY_ERROR;
 3395             return (DNS_R_SERVFAIL);
 3396         }
 3397     } while (res != 0);
 3398     return (ISC_R_SUCCESS);
 3399 }
 3400 #endif /* USE_DNSRPS */
 3401 
 3402 /*
 3403  * Check this address in every eligible policy zone.
 3404  */
 3405 static isc_result_t
 3406 rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr,
 3407            dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
 3408            dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) {
 3409     dns_rpz_zones_t *rpzs;
 3410     dns_rpz_st_t *st;
 3411     dns_rpz_zone_t *rpz;
 3412     dns_rpz_prefix_t prefix;
 3413     dns_rpz_num_t rpz_num;
 3414     dns_fixedname_t ip_namef, p_namef;
 3415     dns_name_t *ip_name, *p_name;
 3416     dns_zone_t *p_zone;
 3417     dns_db_t *p_db;
 3418     dns_dbversion_t *p_version;
 3419     dns_dbnode_t *p_node;
 3420     dns_rpz_policy_t policy;
 3421     isc_result_t result;
 3422 
 3423     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip");
 3424 
 3425     rpzs = client->view->rpzs;
 3426     st = client->query.rpz_st;
 3427 #ifdef USE_DNSRPS
 3428     if (st->popt.dnsrps_enabled) {
 3429         return (dnsrps_rewrite_ip(client, netaddr, rpz_type,
 3430                       p_rdatasetp));
 3431     }
 3432 #endif /* ifdef USE_DNSRPS */
 3433 
 3434     ip_name = dns_fixedname_initname(&ip_namef);
 3435 
 3436     p_zone = NULL;
 3437     p_db = NULL;
 3438     p_node = NULL;
 3439 
 3440     while (zbits != 0) {
 3441         rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr,
 3442                       ip_name, &prefix);
 3443         if (rpz_num == DNS_RPZ_INVALID_NUM) {
 3444             break;
 3445         }
 3446         zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1);
 3447 
 3448         /*
 3449          * Do not try applying policy zones that cannot replace a
 3450          * previously found policy zone.
 3451          * Stop looking if the next best choice cannot
 3452          * replace what we already have.
 3453          */
 3454         rpz = rpzs->zones[rpz_num];
 3455         if (st->m.policy != DNS_RPZ_POLICY_MISS) {
 3456             if (st->m.rpz->num < rpz->num) {
 3457                 break;
 3458             }
 3459             if (st->m.rpz->num == rpz->num &&
 3460                 (st->m.type < rpz_type || st->m.prefix > prefix))
 3461             {
 3462                 break;
 3463             }
 3464         }
 3465 
 3466         /*
 3467          * Get the policy for a prefix at least as long
 3468          * as the prefix of the entry we had before.
 3469          */
 3470         p_name = dns_fixedname_initname(&p_namef);
 3471         result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name);
 3472         if (result != ISC_R_SUCCESS) {
 3473             continue;
 3474         }
 3475         result = rpz_find_p(client, ip_name, qtype, p_name, rpz,
 3476                     rpz_type, &p_zone, &p_db, &p_version,
 3477                     &p_node, p_rdatasetp, &policy);
 3478         switch (result) {
 3479         case DNS_R_NXDOMAIN:
 3480             /*
 3481              * Continue after a policy record that is missing
 3482              * contrary to the summary data.  The summary
 3483              * data can out of date during races with and among
 3484              * policy zone updates.
 3485              */
 3486             CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip: mismatched "
 3487                           "summary data; "
 3488                           "continuing");
 3489             continue;
 3490         case DNS_R_SERVFAIL:
 3491             rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
 3492             st->m.policy = DNS_RPZ_POLICY_ERROR;
 3493             return (DNS_R_SERVFAIL);
 3494         default:
 3495             /*
 3496              * Forget this policy if it is not preferable
 3497              * to the previously found policy.
 3498              * If this policy is not good, then stop looking
 3499              * because none of the later policy zones would work.
 3500              *
 3501              * With more than one applicable policy, prefer
 3502              * the earliest configured policy,
 3503              * client-IP over QNAME over IP over NSDNAME over NSIP,
 3504              * the longest prefix
 3505              * the lexically smallest address.
 3506              * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num.
 3507              * We can compare new and current p_name because
 3508              * both are of the same type and in the same zone.
 3509              * The tests above eliminate other reasons to
 3510              * reject this policy.  If this policy can't work,
 3511              * then neither can later zones.
 3512              */
 3513             if (st->m.policy != DNS_RPZ_POLICY_MISS &&
 3514                 rpz->num == st->m.rpz->num &&
 3515                 (st->m.type == rpz_type && st->m.prefix == prefix &&
 3516                  0 > dns_name_rdatacompare(st->p_name, p_name)))
 3517             {
 3518                 break;
 3519             }
 3520 
 3521             /*
 3522              * Stop checking after saving an enabled hit in this
 3523              * policy zone.  The radix tree in the policy zone
 3524              * ensures that we found the longest match.
 3525              */
 3526             if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
 3527                 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip: "
 3528                              "rpz_save_p");
 3529                 rpz_save_p(st, rpz, rpz_type, policy, p_name,
 3530                        prefix, result, &p_zone, &p_db,
 3531                        &p_node, p_rdatasetp, p_version);
 3532                 break;
 3533             }
 3534 
 3535             /*
 3536              * Log DNS_RPZ_POLICY_DISABLED zones
 3537              * and try the next eligible policy zone.
 3538              */
 3539             rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
 3540                     p_name, NULL, rpz_num);
 3541         }
 3542     }
 3543 
 3544     rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp);
 3545     return (ISC_R_SUCCESS);
 3546 }
 3547 
 3548 /*
 3549  * Check the IP addresses in the A or AAAA rrsets for name against
 3550  * all eligible rpz_type (IP or NSIP) response policy rewrite rules.
 3551  */
 3552 static isc_result_t
 3553 rpz_rewrite_ip_rrset(ns_client_t *client, dns_name_t *name,
 3554              dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
 3555              dns_rdatatype_t ip_type, dns_db_t **ip_dbp,
 3556              dns_dbversion_t *ip_version, dns_rdataset_t **ip_rdatasetp,
 3557              dns_rdataset_t **p_rdatasetp, bool resuming) {
 3558     dns_rpz_zbits_t zbits;
 3559     isc_netaddr_t netaddr;
 3560     struct in_addr ina;
 3561     struct in6_addr in6a;
 3562     isc_result_t result;
 3563 
 3564     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrset");
 3565 
 3566     zbits = rpz_get_zbits(client, ip_type, rpz_type);
 3567     if (zbits == 0) {
 3568         return (ISC_R_SUCCESS);
 3569     }
 3570 
 3571     /*
 3572      * Get the A or AAAA rdataset.
 3573      */
 3574     result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp,
 3575                 ip_version, ip_rdatasetp, resuming);
 3576     switch (result) {
 3577     case ISC_R_SUCCESS:
 3578     case DNS_R_GLUE:
 3579     case DNS_R_ZONECUT:
 3580         break;
 3581     case DNS_R_EMPTYNAME:
 3582     case DNS_R_EMPTYWILD:
 3583     case DNS_R_NXDOMAIN:
 3584     case DNS_R_NCACHENXDOMAIN:
 3585     case DNS_R_NXRRSET:
 3586     case DNS_R_NCACHENXRRSET:
 3587     case ISC_R_NOTFOUND:
 3588         return (ISC_R_SUCCESS);
 3589     case DNS_R_DELEGATION:
 3590     case DNS_R_DUPLICATE:
 3591     case DNS_R_DROP:
 3592         return (result);
 3593     case DNS_R_CNAME:
 3594     case DNS_R_DNAME:
 3595         rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type,
 3596                  "NS address rewrite rrset", result);
 3597         return (ISC_R_SUCCESS);
 3598     default:
 3599         if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
 3600             client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
 3601             rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
 3602                      rpz_type, "NS address rewrite rrset",
 3603                      result);
 3604         }
 3605         CTRACE(ISC_LOG_ERROR, "rpz_rewrite_ip_rrset: unexpected "
 3606                       "result");
 3607         return (DNS_R_SERVFAIL);
 3608     }
 3609 
 3610     /*
 3611      * Check all of the IP addresses in the rdataset.
 3612      */
 3613     for (result = dns_rdataset_first(*ip_rdatasetp);
 3614          result == ISC_R_SUCCESS; result = dns_rdataset_next(*ip_rdatasetp))
 3615     {
 3616         dns_rdata_t rdata = DNS_RDATA_INIT;
 3617         dns_rdataset_current(*ip_rdatasetp, &rdata);
 3618         switch (rdata.type) {
 3619         case dns_rdatatype_a:
 3620             INSIST(rdata.length == 4);
 3621             memmove(&ina.s_addr, rdata.data, 4);
 3622             isc_netaddr_fromin(&netaddr, &ina);
 3623             break;
 3624         case dns_rdatatype_aaaa:
 3625             INSIST(rdata.length == 16);
 3626             memmove(in6a.s6_addr, rdata.data, 16);
 3627             isc_netaddr_fromin6(&netaddr, &in6a);
 3628             break;
 3629         default:
 3630             continue;
 3631         }
 3632 
 3633         result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type,
 3634                     zbits, p_rdatasetp);
 3635         if (result != ISC_R_SUCCESS) {
 3636             return (result);
 3637         }
 3638     }
 3639 
 3640     return (ISC_R_SUCCESS);
 3641 }
 3642 
 3643 /*
 3644  * Look for IP addresses in A and AAAA rdatasets
 3645  * that trigger all eligible IP or NSIP policy rules.
 3646  */
 3647 static isc_result_t
 3648 rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name,
 3649               dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
 3650               dns_rdataset_t **ip_rdatasetp, bool resuming) {
 3651     dns_rpz_st_t *st;
 3652     dns_dbversion_t *ip_version;
 3653     dns_db_t *ip_db;
 3654     dns_rdataset_t *p_rdataset;
 3655     isc_result_t result;
 3656 
 3657     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ip_rrsets");
 3658 
 3659     st = client->query.rpz_st;
 3660     ip_version = NULL;
 3661     ip_db = NULL;
 3662     p_rdataset = NULL;
 3663     if ((st->state & DNS_RPZ_DONE_IPv4) == 0 &&
 3664         (qtype == dns_rdatatype_a || qtype == dns_rdatatype_any ||
 3665          rpz_type == DNS_RPZ_TYPE_NSIP))
 3666     {
 3667         /*
 3668          * Rewrite based on an IPv4 address that will appear
 3669          * in the ANSWER section or if we are checking IP addresses.
 3670          */
 3671         result = rpz_rewrite_ip_rrset(
 3672             client, name, qtype, rpz_type, dns_rdatatype_a, &ip_db,
 3673             ip_version, ip_rdatasetp, &p_rdataset, resuming);
 3674         if (result == ISC_R_SUCCESS) {
 3675             st->state |= DNS_RPZ_DONE_IPv4;
 3676         }
 3677     } else {
 3678         result = ISC_R_SUCCESS;
 3679     }
 3680     if (result == ISC_R_SUCCESS &&
 3681         (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_any ||
 3682          rpz_type == DNS_RPZ_TYPE_NSIP))
 3683     {
 3684         /*
 3685          * Rewrite based on IPv6 addresses that will appear
 3686          * in the ANSWER section or if we are checking IP addresses.
 3687          */
 3688         result = rpz_rewrite_ip_rrset(client, name, qtype, rpz_type,
 3689                           dns_rdatatype_aaaa, &ip_db,
 3690                           ip_version, ip_rdatasetp,
 3691                           &p_rdataset, resuming);
 3692     }
 3693     if (ip_db != NULL) {
 3694         dns_db_detach(&ip_db);
 3695     }
 3696     ns_client_putrdataset(client, &p_rdataset);
 3697     return (result);
 3698 }
 3699 
 3700 /*
 3701  * Try to rewrite a request for a qtype rdataset based on the trigger name
 3702  * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME).
 3703  * Record the results including the replacement rdataset if any
 3704  * in client->query.rpz_st.
 3705  * *rdatasetp is a scratch rdataset.
 3706  */
 3707 static isc_result_t
 3708 rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name,
 3709          dns_rdatatype_t qtype, dns_rpz_type_t rpz_type,
 3710          dns_rpz_zbits_t allowed_zbits, bool recursed,
 3711          dns_rdataset_t **rdatasetp) {
 3712     dns_rpz_zones_t *rpzs;
 3713     dns_rpz_zone_t *rpz;
 3714     dns_rpz_st_t *st;
 3715     dns_fixedname_t p_namef;
 3716     dns_name_t *p_name;
 3717     dns_rpz_zbits_t zbits;
 3718     dns_rpz_num_t rpz_num;
 3719     dns_zone_t *p_zone;
 3720     dns_db_t *p_db;
 3721     dns_dbversion_t *p_version;
 3722     dns_dbnode_t *p_node;
 3723     dns_rpz_policy_t policy;
 3724     isc_result_t result;
 3725 
 3726 #ifndef USE_DNSRPS
 3727     UNUSED(recursed);
 3728 #endif /* ifndef USE_DNSRPS */
 3729 
 3730     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name");
 3731 
 3732     rpzs = client->view->rpzs;
 3733     st = client->query.rpz_st;
 3734 
 3735 #ifdef USE_DNSRPS
 3736     if (st->popt.dnsrps_enabled) {
 3737         return (dnsrps_rewrite_name(client, trig_name, recursed,
 3738                         rpz_type, rdatasetp));
 3739     }
 3740 #endif /* ifdef USE_DNSRPS */
 3741 
 3742     zbits = rpz_get_zbits(client, qtype, rpz_type);
 3743     zbits &= allowed_zbits;
 3744     if (zbits == 0) {
 3745         return (ISC_R_SUCCESS);
 3746     }
 3747 
 3748     /*
 3749      * Use the summary database to find the bit mask of policy zones
 3750      * with policies for this trigger name. We do this even if there
 3751      * is only one eligible policy zone so that wildcard triggers
 3752      * are matched correctly, and not into their parent.
 3753      */
 3754     zbits = dns_rpz_find_name(rpzs, rpz_type, zbits, trig_name);
 3755     if (zbits == 0) {
 3756         return (ISC_R_SUCCESS);
 3757     }
 3758 
 3759     p_name = dns_fixedname_initname(&p_namef);
 3760 
 3761     p_zone = NULL;
 3762     p_db = NULL;
 3763     p_node = NULL;
 3764 
 3765     /*
 3766      * Check the trigger name in every policy zone that the summary data
 3767      * says has a hit for the trigger name.
 3768      * Most of the time there are no eligible zones and the summary data
 3769      * keeps us from getting this far.
 3770      * We check the most eligible zone first and so usually check only
 3771      * one policy zone.
 3772      */
 3773     for (rpz_num = 0; zbits != 0; ++rpz_num, zbits >>= 1) {
 3774         if ((zbits & 1) == 0) {
 3775             continue;
 3776         }
 3777 
 3778         /*
 3779          * Do not check policy zones that cannot replace a previously
 3780          * found policy.
 3781          */
 3782         rpz = rpzs->zones[rpz_num];
 3783         if (st->m.policy != DNS_RPZ_POLICY_MISS) {
 3784             if (st->m.rpz->num < rpz->num) {
 3785                 break;
 3786             }
 3787             if (st->m.rpz->num == rpz->num && st->m.type < rpz_type)
 3788             {
 3789                 break;
 3790             }
 3791         }
 3792 
 3793         /*
 3794          * Get the next policy zone's record for this trigger name.
 3795          */
 3796         result = rpz_get_p_name(client, p_name, rpz, rpz_type,
 3797                     trig_name);
 3798         if (result != ISC_R_SUCCESS) {
 3799             continue;
 3800         }
 3801         result = rpz_find_p(client, trig_name, qtype, p_name, rpz,
 3802                     rpz_type, &p_zone, &p_db, &p_version,
 3803                     &p_node, rdatasetp, &policy);
 3804         switch (result) {
 3805         case DNS_R_NXDOMAIN:
 3806             /*
 3807              * Continue after a missing policy record
 3808              * contrary to the summary data.  The summary
 3809              * data can out of date during races with and among
 3810              * policy zone updates.
 3811              */
 3812             CTRACE(ISC_LOG_ERROR, "rpz_rewrite_name: mismatched "
 3813                           "summary data; "
 3814                           "continuing");
 3815             continue;
 3816         case DNS_R_SERVFAIL:
 3817             rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
 3818             st->m.policy = DNS_RPZ_POLICY_ERROR;
 3819             return (DNS_R_SERVFAIL);
 3820         default:
 3821             /*
 3822              * With more than one applicable policy, prefer
 3823              * the earliest configured policy,
 3824              * client-IP over QNAME over IP over NSDNAME over NSIP,
 3825              * and the smallest name.
 3826              * We known st->m.rpz->num >= rpz->num  and either
 3827              * st->m.rpz->num > rpz->num or st->m.type >= rpz_type
 3828              */
 3829             if (st->m.policy != DNS_RPZ_POLICY_MISS &&
 3830                 rpz->num == st->m.rpz->num &&
 3831                 (st->m.type < rpz_type ||
 3832                  (st->m.type == rpz_type &&
 3833                   0 >= dns_name_compare(p_name, st->p_name))))
 3834             {
 3835                 continue;
 3836             }
 3837 
 3838             if (rpz->policy != DNS_RPZ_POLICY_DISABLED) {
 3839                 CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_name: "
 3840                              "rpz_save_p");
 3841                 rpz_save_p(st, rpz, rpz_type, policy, p_name, 0,
 3842                        result, &p_zone, &p_db, &p_node,
 3843                        rdatasetp, p_version);
 3844                 /*
 3845                  * After a hit, higher numbered policy zones
 3846                  * are irrelevant
 3847                  */
 3848                 rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
 3849                 return (ISC_R_SUCCESS);
 3850             }
 3851             /*
 3852              * Log DNS_RPZ_POLICY_DISABLED zones
 3853              * and try the next eligible policy zone.
 3854              */
 3855             rpz_log_rewrite(client, true, policy, rpz_type, p_zone,
 3856                     p_name, NULL, rpz_num);
 3857             break;
 3858         }
 3859     }
 3860 
 3861     rpz_clean(&p_zone, &p_db, &p_node, rdatasetp);
 3862     return (ISC_R_SUCCESS);
 3863 }
 3864 
 3865 static void
 3866 rpz_rewrite_ns_skip(ns_client_t *client, dns_name_t *nsname,
 3867             isc_result_t result, int level, const char *str) {
 3868     dns_rpz_st_t *st;
 3869 
 3870     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite_ns_skip");
 3871 
 3872     st = client->query.rpz_st;
 3873 
 3874     if (str != NULL) {
 3875         rpz_log_fail_helper(client, level, nsname, DNS_RPZ_TYPE_NSIP,
 3876                     DNS_RPZ_TYPE_NSDNAME, str, result);
 3877     }
 3878     if (st->r.ns_rdataset != NULL &&
 3879         dns_rdataset_isassociated(st->r.ns_rdataset)) {
 3880         dns_rdataset_disassociate(st->r.ns_rdataset);
 3881     }
 3882 
 3883     st->r.label--;
 3884 }
 3885 
 3886 /*
 3887  * RPZ query result types
 3888  */
 3889 typedef enum {
 3890     qresult_type_done = 0,
 3891     qresult_type_restart = 1,
 3892     qresult_type_recurse = 2
 3893 } qresult_type_t;
 3894 
 3895 /*
 3896  * Look for response policy zone QNAME, NSIP, and NSDNAME rewriting.
 3897  */
 3898 static isc_result_t
 3899 rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
 3900         bool resuming, dns_rdataset_t *ordataset, dns_rdataset_t *osigset) {
 3901     dns_rpz_zones_t *rpzs;
 3902     dns_rpz_st_t *st;
 3903     dns_rdataset_t *rdataset;
 3904     dns_fixedname_t nsnamef;
 3905     dns_name_t *nsname;
 3906     qresult_type_t qresult_type;
 3907     dns_rpz_zbits_t zbits;
 3908     isc_result_t result = ISC_R_SUCCESS;
 3909     dns_rpz_have_t have;
 3910     dns_rpz_popt_t popt;
 3911     int rpz_ver;
 3912 #ifdef USE_DNSRPS
 3913     librpz_emsg_t emsg;
 3914 #endif /* ifdef USE_DNSRPS */
 3915 
 3916     CTRACE(ISC_LOG_DEBUG(3), "rpz_rewrite");
 3917 
 3918     rpzs = client->view->rpzs;
 3919     st = client->query.rpz_st;
 3920 
 3921     if (rpzs == NULL ||
 3922         (st != NULL && (st->state & DNS_RPZ_REWRITTEN) != 0)) {
 3923         return (DNS_R_DISALLOWED);
 3924     }
 3925 
 3926     RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
 3927     if ((rpzs->p.num_zones == 0 && !rpzs->p.dnsrps_enabled) ||
 3928         (!RECURSIONOK(client) && rpzs->p.no_rd_ok == 0) ||
 3929         !rpz_ck_dnssec(client, qresult, ordataset, osigset))
 3930     {
 3931         RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
 3932         return (DNS_R_DISALLOWED);
 3933     }
 3934     have = rpzs->have;
 3935     popt = rpzs->p;
 3936     rpz_ver = rpzs->rpz_ver;
 3937     RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
 3938 
 3939 #ifndef USE_DNSRPS
 3940     INSIST(!popt.dnsrps_enabled);
 3941 #endif /* ifndef USE_DNSRPS */
 3942 
 3943     if (st == NULL) {
 3944         st = isc_mem_get(client->mctx, sizeof(*st));
 3945         st->state = 0;
 3946         st->rpsdb = NULL;
 3947     }
 3948     if (st->state == 0) {
 3949         st->state |= DNS_RPZ_ACTIVE;
 3950         memset(&st->m, 0, sizeof(st->m));
 3951         st->m.type = DNS_RPZ_TYPE_BAD;
 3952         st->m.policy = DNS_RPZ_POLICY_MISS;
 3953         st->m.ttl = ~0;
 3954         memset(&st->r, 0, sizeof(st->r));
 3955         memset(&st->q, 0, sizeof(st->q));
 3956         st->p_name = dns_fixedname_initname(&st->_p_namef);
 3957         st->r_name = dns_fixedname_initname(&st->_r_namef);
 3958         st->fname = dns_fixedname_initname(&st->_fnamef);
 3959         st->have = have;
 3960         st->popt = popt;
 3961         st->rpz_ver = rpz_ver;
 3962         client->query.rpz_st = st;
 3963 #ifdef USE_DNSRPS
 3964         if (popt.dnsrps_enabled) {
 3965             if (st->rpsdb != NULL) {
 3966                 dns_db_detach(&st->rpsdb);
 3967             }
 3968             result = dns_dnsrps_rewrite_init(
 3969                 &emsg, st, rpzs, client->query.qname,
 3970                 client->mctx, RECURSIONOK(client));
 3971             if (result != ISC_R_SUCCESS) {
 3972                 rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
 3973                          DNS_RPZ_TYPE_QNAME, emsg.c,
 3974                          result);
 3975                 st->m.policy = DNS_RPZ_POLICY_ERROR;
 3976                 return (ISC_R_SUCCESS);
 3977             }
 3978         }
 3979 #endif /* ifdef USE_DNSRPS */
 3980     }
 3981 
 3982     /*
 3983      * There is nothing to rewrite if the main query failed.
 3984      */
 3985     switch (qresult) {
 3986     case ISC_R_SUCCESS:
 3987     case DNS_R_GLUE:
 3988     case DNS_R_ZONECUT:
 3989         qresult_type = qresult_type_done;
 3990         break;
 3991     case DNS_R_EMPTYNAME:
 3992     case DNS_R_NXRRSET:
 3993     case DNS_R_NXDOMAIN:
 3994     case DNS_R_EMPTYWILD:
 3995     case DNS_R_NCACHENXDOMAIN:
 3996     case DNS_R_NCACHENXRRSET:
 3997     case DNS_R_COVERINGNSEC:
 3998     case DNS_R_CNAME:
 3999     case DNS_R_DNAME:
 4000         qresult_type = qresult_type_restart;
 4001         break;
 4002     case DNS_R_DELEGATION:
 4003     case ISC_R_NOTFOUND:
 4004         /*
 4005          * If recursion is on, do only tentative rewriting.
 4006          * If recursion is off, this the normal and only time we
 4007          * can rewrite.
 4008          */
 4009         if (RECURSIONOK(client)) {
 4010             qresult_type = qresult_type_recurse;
 4011         } else {
 4012             qresult_type = qresult_type_restart;
 4013         }
 4014         break;
 4015     case ISC_R_FAILURE:
 4016     case ISC_R_TIMEDOUT:
 4017     case DNS_R_BROKENCHAIN:
 4018         rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, NULL,
 4019                  DNS_RPZ_TYPE_QNAME,
 4020                  "stop on qresult in rpz_rewrite()", qresult);
 4021         return (ISC_R_SUCCESS);
 4022     default:
 4023         rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, NULL,
 4024                  DNS_RPZ_TYPE_QNAME,
 4025                  "stop on unrecognized qresult in rpz_rewrite()",
 4026                  qresult);
 4027         return (ISC_R_SUCCESS);
 4028     }
 4029 
 4030     rdataset = NULL;
 4031 
 4032     if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) !=
 4033         (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME))
 4034     {
 4035         isc_netaddr_t netaddr;
 4036         dns_rpz_zbits_t allowed;
 4037 
 4038         if (!st->popt.dnsrps_enabled &&
 4039             qresult_type == qresult_type_recurse) {
 4040             /*
 4041              * This request needs recursion that has not been done.
 4042              * Get bits for the policy zones that do not need
 4043              * to wait for the results of recursion.
 4044              */
 4045             allowed = st->have.qname_skip_recurse;
 4046             if (allowed == 0) {
 4047                 return (ISC_R_SUCCESS);
 4048             }
 4049         } else {
 4050             allowed = DNS_RPZ_ALL_ZBITS;
 4051         }
 4052 
 4053         /*
 4054          * Check once for triggers for the client IP address.
 4055          */
 4056         if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) {
 4057             zbits = rpz_get_zbits(client, dns_rdatatype_none,
 4058                           DNS_RPZ_TYPE_CLIENT_IP);
 4059             zbits &= allowed;
 4060             if (zbits != 0) {
 4061                 isc_netaddr_fromsockaddr(&netaddr,
 4062                              &client->peeraddr);
 4063                 result = rpz_rewrite_ip(client, &netaddr, qtype,
 4064                             DNS_RPZ_TYPE_CLIENT_IP,
 4065                             zbits, &rdataset);
 4066                 if (result != ISC_R_SUCCESS) {
 4067                     goto cleanup;
 4068                 }
 4069             }
 4070         }
 4071 
 4072         /*
 4073          * Check triggers for the query name if this is the first time
 4074          * for the current qname.
 4075          * There is a first time for each name in a CNAME chain
 4076          */
 4077         if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
 4078             bool norec = (qresult_type != qresult_type_recurse);
 4079             result = rpz_rewrite_name(client, client->query.qname,
 4080                           qtype, DNS_RPZ_TYPE_QNAME,
 4081                           allowed, norec, &rdataset);
 4082             if (result != ISC_R_SUCCESS) {
 4083                 goto cleanup;
 4084             }
 4085 
 4086             /*
 4087              * Check IPv4 addresses in A RRs next.
 4088              * Reset to the start of the NS names.
 4089              */
 4090             st->r.label = dns_name_countlabels(client->query.qname);
 4091             st->state &= ~(DNS_RPZ_DONE_QNAME_IP |
 4092                        DNS_RPZ_DONE_IPv4);
 4093         }
 4094 
 4095         /*
 4096          * Quit if this was an attempt to find a qname or
 4097          * client-IP trigger before recursion.
 4098          * We will be back if no pre-recursion triggers hit.
 4099          * For example, consider 2 policy zones, both with qname and
 4100          * IP address triggers.  If the qname misses the 1st zone,
 4101          * then we cannot know whether a hit for the qname in the
 4102          * 2nd zone matters until after recursing to get the A RRs and
 4103          * testing them in the first zone.
 4104          * Do not bother saving the work from this attempt,
 4105          * because recursion is so slow.
 4106          */
 4107         if (qresult_type == qresult_type_recurse) {
 4108             goto cleanup;
 4109         }
 4110 
 4111         /*
 4112          * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP
 4113          * is reset at the end of dealing with each CNAME.
 4114          */
 4115         st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME);
 4116     }
 4117 
 4118     /*
 4119      * Check known IP addresses for the query name if the database lookup
 4120      * resulted in some addresses (qresult_type == qresult_type_done)
 4121      * and if we have not already checked them.
 4122      * Any recursion required for the query has already happened.
 4123      * Do not check addresses that will not be in the ANSWER section.
 4124      */
 4125     if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 &&
 4126         qresult_type == qresult_type_done &&
 4127         rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0)
 4128     {
 4129         result = rpz_rewrite_ip_rrsets(client, client->query.qname,
 4130                            qtype, DNS_RPZ_TYPE_IP,
 4131                            &rdataset, resuming);
 4132         if (result != ISC_R_SUCCESS) {
 4133             goto cleanup;
 4134         }
 4135         /*
 4136          * We are finished checking the IP addresses for the qname.
 4137          * Start with IPv4 if we will check NS IP addresses.
 4138          */
 4139         st->state |= DNS_RPZ_DONE_QNAME_IP;
 4140         st->state &= ~DNS_RPZ_DONE_IPv4;
 4141     }
 4142 
 4143     /*
 4144      * Stop looking for rules if there are none of the other kinds
 4145      * that could override what we already have.
 4146      */
 4147     if (rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSDNAME) ==
 4148             0 &&
 4149         rpz_get_zbits(client, dns_rdatatype_any, DNS_RPZ_TYPE_NSIP) == 0)
 4150     {
 4151         result = ISC_R_SUCCESS;
 4152         goto cleanup;
 4153     }
 4154 
 4155     dns_fixedname_init(&nsnamef);
 4156     dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
 4157     while (st->r.label > st->popt.min_ns_labels) {
 4158         /*
 4159          * Get NS rrset for each domain in the current qname.
 4160          */
 4161         if (st->r.label == dns_name_countlabels(client->query.qname)) {
 4162             nsname = client->query.qname;
 4163         } else {
 4164             nsname = dns_fixedname_name(&nsnamef);
 4165             dns_name_split(client->query.qname, st->r.label, NULL,
 4166                        nsname);
 4167         }
 4168         if (st->r.ns_rdataset == NULL ||
 4169             !dns_rdataset_isassociated(st->r.ns_rdataset)) {
 4170             dns_db_t *db = NULL;
 4171             result = rpz_rrset_find(client, nsname,
 4172                         dns_rdatatype_ns,
 4173                         DNS_RPZ_TYPE_NSDNAME, &db, NULL,
 4174                         &st->r.ns_rdataset, resuming);
 4175             if (db != NULL) {
 4176                 dns_db_detach(&db);
 4177             }
 4178             if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
 4179                 goto cleanup;
 4180             }
 4181             switch (result) {
 4182             case ISC_R_SUCCESS:
 4183                 result = dns_rdataset_first(st->r.ns_rdataset);
 4184                 if (result != ISC_R_SUCCESS) {
 4185                     goto cleanup;
 4186                 }
 4187                 st->state &= ~(DNS_RPZ_DONE_NSDNAME |
 4188                            DNS_RPZ_DONE_IPv4);
 4189                 break;
 4190             case DNS_R_DELEGATION:
 4191             case DNS_R_DUPLICATE:
 4192             case DNS_R_DROP:
 4193                 goto cleanup;
 4194             case DNS_R_EMPTYNAME:
 4195             case DNS_R_NXRRSET:
 4196             case DNS_R_EMPTYWILD:
 4197             case DNS_R_NXDOMAIN:
 4198             case DNS_R_NCACHENXDOMAIN:
 4199             case DNS_R_NCACHENXRRSET:
 4200             case ISC_R_NOTFOUND:
 4201             case DNS_R_CNAME:
 4202             case DNS_R_DNAME:
 4203                 rpz_rewrite_ns_skip(client, nsname, result, 0,
 4204                             NULL);
 4205                 continue;
 4206             case ISC_R_TIMEDOUT:
 4207             case DNS_R_BROKENCHAIN:
 4208             case ISC_R_FAILURE:
 4209                 rpz_rewrite_ns_skip(client, nsname, result,
 4210                             DNS_RPZ_DEBUG_LEVEL3,
 4211                             " NS rpz_rrset_find()");
 4212                 continue;
 4213             default:
 4214                 rpz_rewrite_ns_skip(client, nsname, result,
 4215                             DNS_RPZ_INFO_LEVEL,
 4216                             " unrecognized NS"
 4217                             " rpz_rrset_find()");
 4218                 continue;
 4219             }
 4220         }
 4221         /*
 4222          * Check all NS names.
 4223          */
 4224         do {
 4225             dns_rdata_ns_t ns;
 4226             dns_rdata_t nsrdata = DNS_RDATA_INIT;
 4227 
 4228             dns_rdataset_current(st->r.ns_rdataset, &nsrdata);
 4229             result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
 4230             RUNTIME_CHECK(result == ISC_R_SUCCESS);
 4231             dns_rdata_reset(&nsrdata);
 4232 
 4233             /*
 4234              * Do nothing about "NS ."
 4235              */
 4236             if (dns_name_equal(&ns.name, dns_rootname)) {
 4237                 dns_rdata_freestruct(&ns);
 4238                 result = dns_rdataset_next(st->r.ns_rdataset);
 4239                 continue;
 4240             }
 4241             /*
 4242              * Check this NS name if we did not handle it
 4243              * during a previous recursion.
 4244              */
 4245             if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) {
 4246                 result = rpz_rewrite_name(
 4247                     client, &ns.name, qtype,
 4248                     DNS_RPZ_TYPE_NSDNAME, DNS_RPZ_ALL_ZBITS,
 4249                     true, &rdataset);
 4250                 if (result != ISC_R_SUCCESS) {
 4251                     dns_rdata_freestruct(&ns);
 4252                     goto cleanup;
 4253                 }
 4254                 st->state |= DNS_RPZ_DONE_NSDNAME;
 4255             }
 4256             /*
 4257              * Check all IP addresses for this NS name.
 4258              */
 4259             result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype,
 4260                                DNS_RPZ_TYPE_NSIP,
 4261                                &rdataset, resuming);
 4262             dns_rdata_freestruct(&ns);
 4263             if (result != ISC_R_SUCCESS) {
 4264                 goto cleanup;
 4265             }
 4266             st->state &= ~(DNS_RPZ_DONE_NSDNAME |
 4267                        DNS_RPZ_DONE_IPv4);
 4268             result = dns_rdataset_next(st->r.ns_rdataset);
 4269         } while (result == ISC_R_SUCCESS);
 4270         dns_rdataset_disassociate(st->r.ns_rdataset);
 4271         st->r.label--;
 4272 
 4273         if (rpz_get_zbits(client, dns_rdatatype_any,
 4274                   DNS_RPZ_TYPE_NSDNAME) == 0 &&
 4275             rpz_get_zbits(client, dns_rdatatype_any,
 4276                   DNS_RPZ_TYPE_NSIP) == 0)
 4277         {
 4278             break;
 4279         }
 4280     }
 4281 
 4282     /*
 4283      * Use the best hit, if any.
 4284      */
 4285     result = ISC_R_SUCCESS;
 4286 
 4287 cleanup:
 4288 #ifdef USE_DNSRPS
 4289     if (st->popt.dnsrps_enabled && st->m.policy != DNS_RPZ_POLICY_ERROR &&
 4290         !dnsrps_set_p(&emsg, client, st, qtype, &rdataset,
 4291               (qresult_type != qresult_type_recurse)))
 4292     {
 4293         rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, NULL,
 4294                  DNS_RPZ_TYPE_BAD, emsg.c, DNS_R_SERVFAIL);
 4295         st->m.policy = DNS_RPZ_POLICY_ERROR;
 4296     }
 4297 #endif /* ifdef USE_DNSRPS */
 4298     if (st->m.policy != DNS_RPZ_POLICY_MISS &&
 4299         st->m.policy != DNS_RPZ_POLICY_ERROR &&
 4300         st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
 4301     {
 4302         st->m.policy = st->m.rpz->policy;
 4303     }
 4304     if (st->m.policy == DNS_RPZ_POLICY_MISS ||
 4305         st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
 4306         st->m.policy == DNS_RPZ_POLICY_ERROR)
 4307     {
 4308         if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
 4309             result != DNS_R_DELEGATION) {
 4310             rpz_log_rewrite(client, false, st->m.policy, st->m.type,
 4311                     st->m.zone, st->p_name, NULL,
 4312                     st->m.rpz->num);
 4313         }
 4314         rpz_match_clear(st);
 4315     }
 4316     if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
 4317         CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
 4318         st->m.type = DNS_RPZ_TYPE_BAD;
 4319         result = DNS_R_SERVFAIL;
 4320     }
 4321     ns_client_putrdataset(client, &rdataset);
 4322     if ((st->state & DNS_RPZ_RECURSING) == 0) {
 4323         rpz_clean(NULL, &st->r.db, NULL, &st->r.ns_rdataset);
 4324     }
 4325 
 4326     return (result);
 4327 }
 4328 
 4329 /*
 4330  * See if response policy zone rewriting is allowed by a lack of interest
 4331  * by the client in DNSSEC or a lack of signatures.
 4332  */
 4333 static bool
 4334 rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult,
 4335           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
 4336     dns_fixedname_t fixed;
 4337     dns_name_t *found;
 4338     dns_rdataset_t trdataset;
 4339     dns_rdatatype_t type;
 4340     isc_result_t result;
 4341 
 4342     CTRACE(ISC_LOG_DEBUG(3), "rpz_ck_dnssec");
 4343 
 4344     if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) {
 4345         return (true);
 4346     }
 4347 
 4348     /*
 4349      * We do not know if there are signatures if we have not recursed
 4350      * for them.
 4351      */
 4352     if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) {
 4353         return (false);
 4354     }
 4355 
 4356     if (sigrdataset == NULL) {
 4357         return (true);
 4358     }
 4359     if (dns_rdataset_isassociated(sigrdataset)) {
 4360         return (false);
 4361     }
 4362 
 4363     /*
 4364      * We are happy to rewrite nothing.
 4365      */
 4366     if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
 4367         return (true);
 4368     }
 4369     /*
 4370      * Do not rewrite if there is any sign of signatures.
 4371      */
 4372     if (rdataset->type == dns_rdatatype_nsec ||
 4373         rdataset->type == dns_rdatatype_nsec3 ||
 4374         rdataset->type == dns_rdatatype_rrsig)
 4375     {
 4376         return (false);
 4377     }
 4378 
 4379     /*
 4380      * Look for a signature in a negative cache rdataset.
 4381      */
 4382     if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0) {
 4383         return (true);
 4384     }
 4385     found = dns_fixedname_initname(&fixed);
 4386     dns_rdataset_init(&trdataset);
 4387     for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
 4388          result = dns_rdataset_next(rdataset))
 4389     {
 4390         dns_ncache_current(rdataset, found, &trdataset);
 4391         type = trdataset.type;
 4392         dns_rdataset_disassociate(&trdataset);
 4393         if (type == dns_rdatatype_nsec || type == dns_rdatatype_nsec3 ||
 4394             type == dns_rdatatype_rrsig)
 4395         {
 4396             return (false);
 4397         }
 4398     }
 4399     return (true);
 4400 }
 4401 
 4402 /*
 4403  * Extract a network address from the RDATA of an A or AAAA
 4404  * record.
 4405  *
 4406  * Returns:
 4407  *  ISC_R_SUCCESS
 4408  *  ISC_R_NOTIMPLEMENTED    The rdata is not a known address type.
 4409  */
 4410 static isc_result_t
 4411 rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
 4412     struct in_addr ina;
 4413     struct in6_addr in6a;
 4414 
 4415     switch (rdata->type) {
 4416     case dns_rdatatype_a:
 4417         INSIST(rdata->length == 4);
 4418         memmove(&ina.s_addr, rdata->data, 4);
 4419         isc_netaddr_fromin(netaddr, &ina);
 4420         return (ISC_R_SUCCESS);
 4421     case dns_rdatatype_aaaa:
 4422         INSIST(rdata->length == 16);
 4423         memmove(in6a.s6_addr, rdata->data, 16);
 4424         isc_netaddr_fromin6(netaddr, &in6a);
 4425         return (ISC_R_SUCCESS);
 4426     default:
 4427         return (ISC_R_NOTIMPLEMENTED);
 4428     }
 4429 }
 4430 
 4431 static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
 4432 static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
 4433 static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
 4434 
 4435 static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
 4436 
 4437 static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
 4438 static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
 4439 static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
 4440 static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
 4441 static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
 4442 static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
 4443 static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
 4444 static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
 4445 static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
 4446 static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
 4447 static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
 4448 static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
 4449 static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
 4450 static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
 4451 static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
 4452 static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
 4453 
 4454 static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
 4455 
 4456 static dns_name_t rfc1918names[] = {
 4457     DNS_NAME_INITABSOLUTE(inaddr10, inaddr10_offsets),
 4458     DNS_NAME_INITABSOLUTE(inaddr16172, inaddr172_offsets),
 4459     DNS_NAME_INITABSOLUTE(inaddr17172, inaddr172_offsets),
 4460     DNS_NAME_INITABSOLUTE(inaddr18172, inaddr172_offsets),
 4461     DNS_NAME_INITABSOLUTE(inaddr19172, inaddr172_offsets),
 4462     DNS_NAME_INITABSOLUTE(inaddr20172, inaddr172_offsets),
 4463     DNS_NAME_INITABSOLUTE(inaddr21172, inaddr172_offsets),
 4464     DNS_NAME_INITABSOLUTE(inaddr22172, inaddr172_offsets),
 4465     DNS_NAME_INITABSOLUTE(inaddr23172, inaddr172_offsets),
 4466     DNS_NAME_INITABSOLUTE(inaddr24172, inaddr172_offsets),
 4467     DNS_NAME_INITABSOLUTE(inaddr25172, inaddr172_offsets),
 4468     DNS_NAME_INITABSOLUTE(inaddr26172, inaddr172_offsets),
 4469     DNS_NAME_INITABSOLUTE(inaddr27172, inaddr172_offsets),
 4470     DNS_NAME_INITABSOLUTE(inaddr28172, inaddr172_offsets),
 4471     DNS_NAME_INITABSOLUTE(inaddr29172, inaddr172_offsets),
 4472     DNS_NAME_INITABSOLUTE(inaddr30172, inaddr172_offsets),
 4473     DNS_NAME_INITABSOLUTE(inaddr31172, inaddr172_offsets),
 4474     DNS_NAME_INITABSOLUTE(inaddr168192, inaddr192_offsets)
 4475 };
 4476 
 4477 static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
 4478 static unsigned char hostmaster_data[] = "\012hostmaster\014root-"
 4479                      "servers\003org";
 4480 
 4481 static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
 4482 static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
 4483 
 4484 static dns_name_t const prisoner = DNS_NAME_INITABSOLUTE(prisoner_data,
 4485                              prisoner_offsets);
 4486 static dns_name_t const hostmaster = DNS_NAME_INITABSOLUTE(hostmaster_data,
 4487                                hostmaster_offsets);
 4488 
 4489 static void
 4490 warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
 4491     unsigned int i;
 4492     dns_rdata_t rdata = DNS_RDATA_INIT;
 4493     dns_rdata_soa_t soa;
 4494     dns_rdataset_t found;
 4495     isc_result_t result;
 4496 
 4497     for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
 4498         if (dns_name_issubdomain(fname, &rfc1918names[i])) {
 4499             dns_rdataset_init(&found);
 4500             result = dns_ncache_getrdataset(
 4501                 rdataset, &rfc1918names[i], dns_rdatatype_soa,
 4502                 &found);
 4503             if (result != ISC_R_SUCCESS) {
 4504                 return;
 4505             }
 4506 
 4507             result = dns_rdataset_first(&found);
 4508             RUNTIME_CHECK(result == ISC_R_SUCCESS);
 4509             dns_rdataset_current(&found, &rdata);
 4510             result = dns_rdata_tostruct(&rdata, &soa, NULL);
 4511             RUNTIME_CHECK(result == ISC_R_SUCCESS);
 4512             if (dns_name_equal(&soa.origin, &prisoner) &&
 4513                 dns_name_equal(&soa.contact, &hostmaster))
 4514             {
 4515                 char buf[DNS_NAME_FORMATSIZE];
 4516                 dns_name_format(fname, buf, sizeof(buf));
 4517                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 4518                           NS_LOGMODULE_QUERY,
 4519                           ISC_LOG_WARNING,
 4520                           "RFC 1918 response from "
 4521                           "Internet for %s",
 4522                           buf);
 4523             }
 4524             dns_rdataset_disassociate(&found);
 4525             return;
 4526         }
 4527     }
 4528 }
 4529 
 4530 static void
 4531 query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
 4532                dns_dbversion_t *version, ns_client_t *client,
 4533                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
 4534                dns_name_t *fname, bool exact, dns_name_t *found) {
 4535     unsigned char salt[256];
 4536     size_t salt_length;
 4537     uint16_t iterations;
 4538     isc_result_t result;
 4539     unsigned int dboptions;
 4540     dns_fixedname_t fixed;
 4541     dns_hash_t hash;
 4542     dns_name_t name;
 4543     unsigned int skip = 0, labels;
 4544     dns_rdata_nsec3_t nsec3;
 4545     dns_rdata_t rdata = DNS_RDATA_INIT;
 4546     bool optout;
 4547     dns_clientinfomethods_t cm;
 4548     dns_clientinfo_t ci;
 4549 
 4550     salt_length = sizeof(salt);
 4551     result = dns_db_getnsec3parameters(db, version, &hash, NULL,
 4552                        &iterations, salt, &salt_length);
 4553     if (result != ISC_R_SUCCESS) {
 4554         return;
 4555     }
 4556 
 4557     dns_name_init(&name, NULL);
 4558     dns_name_clone(qname, &name);
 4559     labels = dns_name_countlabels(&name);
 4560     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 4561     dns_clientinfo_init(&ci, client, NULL);
 4562 
 4563     /*
 4564      * Map unknown algorithm to known value.
 4565      */
 4566     if (hash == DNS_NSEC3_UNKNOWNALG) {
 4567         hash = 1;
 4568     }
 4569 
 4570 again:
 4571     dns_fixedname_init(&fixed);
 4572     result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
 4573                     dns_db_origin(db), hash, iterations, salt,
 4574                     salt_length);
 4575     if (result != ISC_R_SUCCESS) {
 4576         return;
 4577     }
 4578 
 4579     dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
 4580     result = dns_db_findext(db, dns_fixedname_name(&fixed), version,
 4581                 dns_rdatatype_nsec3, dboptions, client->now,
 4582                 NULL, fname, &cm, &ci, rdataset, sigrdataset);
 4583 
 4584     if (result == DNS_R_NXDOMAIN) {
 4585         if (!dns_rdataset_isassociated(rdataset)) {
 4586             return;
 4587         }
 4588         result = dns_rdataset_first(rdataset);
 4589         INSIST(result == ISC_R_SUCCESS);
 4590         dns_rdataset_current(rdataset, &rdata);
 4591         result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
 4592         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 4593         dns_rdata_reset(&rdata);
 4594         optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
 4595         if (found != NULL && optout &&
 4596             dns_name_issubdomain(&name, dns_db_origin(db))) {
 4597             dns_rdataset_disassociate(rdataset);
 4598             if (dns_rdataset_isassociated(sigrdataset)) {
 4599                 dns_rdataset_disassociate(sigrdataset);
 4600             }
 4601             skip++;
 4602             dns_name_getlabelsequence(qname, skip, labels - skip,
 4603                           &name);
 4604             ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
 4605                       NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3),
 4606                       "looking for closest provable encloser");
 4607             goto again;
 4608         }
 4609         if (exact) {
 4610             ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
 4611                       NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
 4612                       "expected a exact match NSEC3, got "
 4613                       "a covering record");
 4614         }
 4615     } else if (result != ISC_R_SUCCESS) {
 4616         return;
 4617     } else if (!exact) {
 4618         ns_client_log(client, DNS_LOGCATEGORY_DNSSEC,
 4619                   NS_LOGMODULE_QUERY, ISC_LOG_WARNING,
 4620                   "expected covering NSEC3, got an exact match");
 4621     }
 4622     if (found == qname) {
 4623         if (skip != 0U) {
 4624             dns_name_getlabelsequence(qname, skip, labels - skip,
 4625                           found);
 4626         }
 4627     } else if (found != NULL) {
 4628         dns_name_copynf(&name, found);
 4629     }
 4630     return;
 4631 }
 4632 
 4633 static uint32_t
 4634 dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
 4635     dns_dbnode_t *node = NULL;
 4636     dns_rdata_soa_t soa;
 4637     dns_rdata_t rdata = DNS_RDATA_INIT;
 4638     dns_rdataset_t rdataset;
 4639     isc_result_t result;
 4640     uint32_t ttl = UINT32_MAX;
 4641 
 4642     dns_rdataset_init(&rdataset);
 4643 
 4644     result = dns_db_getoriginnode(db, &node);
 4645     if (result != ISC_R_SUCCESS) {
 4646         goto cleanup;
 4647     }
 4648 
 4649     result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, 0, 0,
 4650                      &rdataset, NULL);
 4651     if (result != ISC_R_SUCCESS) {
 4652         goto cleanup;
 4653     }
 4654     result = dns_rdataset_first(&rdataset);
 4655     if (result != ISC_R_SUCCESS) {
 4656         goto cleanup;
 4657     }
 4658 
 4659     dns_rdataset_current(&rdataset, &rdata);
 4660     result = dns_rdata_tostruct(&rdata, &soa, NULL);
 4661     RUNTIME_CHECK(result == ISC_R_SUCCESS);
 4662     ttl = ISC_MIN(rdataset.ttl, soa.minimum);
 4663 
 4664 cleanup:
 4665     if (dns_rdataset_isassociated(&rdataset)) {
 4666         dns_rdataset_disassociate(&rdataset);
 4667     }
 4668     if (node != NULL) {
 4669         dns_db_detachnode(db, &node);
 4670     }
 4671     return (ttl);
 4672 }
 4673 
 4674 static bool
 4675 dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
 4676          dns_rdataset_t *sigrdataset) {
 4677     isc_netaddr_t netaddr;
 4678     dns_aclenv_t *env =
 4679         ns_interfacemgr_getaclenv(client->manager->interface->mgr);
 4680     dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
 4681     unsigned int flags = 0;
 4682     unsigned int i, count;
 4683     bool *aaaaok;
 4684 
 4685     INSIST(client->query.dns64_aaaaok == NULL);
 4686     INSIST(client->query.dns64_aaaaoklen == 0);
 4687     INSIST(client->query.dns64_aaaa == NULL);
 4688     INSIST(client->query.dns64_sigaaaa == NULL);
 4689 
 4690     if (dns64 == NULL) {
 4691         return (true);
 4692     }
 4693 
 4694     if (RECURSIONOK(client)) {
 4695         flags |= DNS_DNS64_RECURSIVE;
 4696     }
 4697 
 4698     if (WANTDNSSEC(client) && sigrdataset != NULL &&
 4699         dns_rdataset_isassociated(sigrdataset))
 4700     {
 4701         flags |= DNS_DNS64_DNSSEC;
 4702     }
 4703 
 4704     count = dns_rdataset_count(rdataset);
 4705     aaaaok = isc_mem_get(client->mctx, sizeof(bool) * count);
 4706 
 4707     isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 4708     if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, env, flags,
 4709                  rdataset, aaaaok, count))
 4710     {
 4711         for (i = 0; i < count; i++) {
 4712             if (aaaaok != NULL && !aaaaok[i]) {
 4713                 SAVE(client->query.dns64_aaaaok, aaaaok);
 4714                 client->query.dns64_aaaaoklen = count;
 4715                 break;
 4716             }
 4717         }
 4718         if (aaaaok != NULL) {
 4719             isc_mem_put(client->mctx, aaaaok, sizeof(bool) * count);
 4720         }
 4721         return (true);
 4722     }
 4723     if (aaaaok != NULL) {
 4724         isc_mem_put(client->mctx, aaaaok, sizeof(bool) * count);
 4725     }
 4726     return (false);
 4727 }
 4728 
 4729 /*
 4730  * Look for the name and type in the redirection zone.  If found update
 4731  * the arguments as appropriate.  Return true if a update was
 4732  * performed.
 4733  *
 4734  * Only perform the update if the client is in the allow query acl and
 4735  * returning the update would not cause a DNSSEC validation failure.
 4736  */
 4737 static isc_result_t
 4738 redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
 4739      dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
 4740      dns_rdatatype_t qtype) {
 4741     dns_db_t *db = NULL;
 4742     dns_dbnode_t *node = NULL;
 4743     dns_fixedname_t fixed;
 4744     dns_name_t *found;
 4745     dns_rdataset_t trdataset;
 4746     isc_result_t result;
 4747     dns_rdatatype_t type;
 4748     dns_clientinfomethods_t cm;
 4749     dns_clientinfo_t ci;
 4750     ns_dbversion_t *dbversion;
 4751 
 4752     CTRACE(ISC_LOG_DEBUG(3), "redirect");
 4753 
 4754     if (client->view->redirect == NULL) {
 4755         return (ISC_R_NOTFOUND);
 4756     }
 4757 
 4758     found = dns_fixedname_initname(&fixed);
 4759     dns_rdataset_init(&trdataset);
 4760 
 4761     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 4762     dns_clientinfo_init(&ci, client, NULL);
 4763 
 4764     if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
 4765     {
 4766         return (ISC_R_NOTFOUND);
 4767     }
 4768 
 4769     if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
 4770         if (rdataset->trust == dns_trust_secure) {
 4771             return (ISC_R_NOTFOUND);
 4772         }
 4773         if (rdataset->trust == dns_trust_ultimate &&
 4774             (rdataset->type == dns_rdatatype_nsec ||
 4775              rdataset->type == dns_rdatatype_nsec3))
 4776         {
 4777             return (ISC_R_NOTFOUND);
 4778         }
 4779         if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
 4780             for (result = dns_rdataset_first(rdataset);
 4781                  result == ISC_R_SUCCESS;
 4782                  result = dns_rdataset_next(rdataset))
 4783             {
 4784                 dns_ncache_current(rdataset, found, &trdataset);
 4785                 type = trdataset.type;
 4786                 dns_rdataset_disassociate(&trdataset);
 4787                 if (type == dns_rdatatype_nsec ||
 4788                     type == dns_rdatatype_nsec3 ||
 4789                     type == dns_rdatatype_rrsig)
 4790                 {
 4791                     return (ISC_R_NOTFOUND);
 4792                 }
 4793             }
 4794         }
 4795     }
 4796 
 4797     result = ns_client_checkaclsilent(
 4798         client, NULL, dns_zone_getqueryacl(client->view->redirect),
 4799         true);
 4800     if (result != ISC_R_SUCCESS) {
 4801         return (ISC_R_NOTFOUND);
 4802     }
 4803 
 4804     result = dns_zone_getdb(client->view->redirect, &db);
 4805     if (result != ISC_R_SUCCESS) {
 4806         return (ISC_R_NOTFOUND);
 4807     }
 4808 
 4809     dbversion = ns_client_findversion(client, db);
 4810     if (dbversion == NULL) {
 4811         dns_db_detach(&db);
 4812         return (ISC_R_NOTFOUND);
 4813     }
 4814 
 4815     /*
 4816      * Lookup the requested data in the redirect zone.
 4817      */
 4818     result = dns_db_findext(db, client->query.qname, dbversion->version,
 4819                 qtype, DNS_DBFIND_NOZONECUT, client->now, &node,
 4820                 found, &cm, &ci, &trdataset, NULL);
 4821     if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
 4822         if (dns_rdataset_isassociated(rdataset)) {
 4823             dns_rdataset_disassociate(rdataset);
 4824         }
 4825         if (dns_rdataset_isassociated(&trdataset)) {
 4826             dns_rdataset_disassociate(&trdataset);
 4827         }
 4828         goto nxrrset;
 4829     } else if (result != ISC_R_SUCCESS) {
 4830         if (dns_rdataset_isassociated(&trdataset)) {
 4831             dns_rdataset_disassociate(&trdataset);
 4832         }
 4833         if (node != NULL) {
 4834             dns_db_detachnode(db, &node);
 4835         }
 4836         dns_db_detach(&db);
 4837         return (ISC_R_NOTFOUND);
 4838     }
 4839 
 4840     CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
 4841     dns_name_copynf(found, name);
 4842     if (dns_rdataset_isassociated(rdataset)) {
 4843         dns_rdataset_disassociate(rdataset);
 4844     }
 4845     if (dns_rdataset_isassociated(&trdataset)) {
 4846         dns_rdataset_clone(&trdataset, rdataset);
 4847         dns_rdataset_disassociate(&trdataset);
 4848     }
 4849 nxrrset:
 4850     if (*nodep != NULL) {
 4851         dns_db_detachnode(*dbp, nodep);
 4852     }
 4853     dns_db_detach(dbp);
 4854     dns_db_attachnode(db, node, nodep);
 4855     dns_db_attach(db, dbp);
 4856     dns_db_detachnode(db, &node);
 4857     dns_db_detach(&db);
 4858     *versionp = dbversion->version;
 4859 
 4860     client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
 4861                      NS_QUERYATTR_NOADDITIONAL);
 4862 
 4863     return (result);
 4864 }
 4865 
 4866 static isc_result_t
 4867 redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
 4868       dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
 4869       dns_rdatatype_t qtype, bool *is_zonep) {
 4870     dns_db_t *db = NULL;
 4871     dns_dbnode_t *node = NULL;
 4872     dns_fixedname_t fixed;
 4873     dns_fixedname_t fixedredirect;
 4874     dns_name_t *found, *redirectname;
 4875     dns_rdataset_t trdataset;
 4876     isc_result_t result;
 4877     dns_rdatatype_t type;
 4878     dns_clientinfomethods_t cm;
 4879     dns_clientinfo_t ci;
 4880     dns_dbversion_t *version = NULL;
 4881     dns_zone_t *zone = NULL;
 4882     bool is_zone;
 4883     unsigned int labels;
 4884     unsigned int options;
 4885 
 4886     CTRACE(ISC_LOG_DEBUG(3), "redirect2");
 4887 
 4888     if (client->view->redirectzone == NULL) {
 4889         return (ISC_R_NOTFOUND);
 4890     }
 4891 
 4892     if (dns_name_issubdomain(name, client->view->redirectzone)) {
 4893         return (ISC_R_NOTFOUND);
 4894     }
 4895 
 4896     found = dns_fixedname_initname(&fixed);
 4897     dns_rdataset_init(&trdataset);
 4898 
 4899     dns_clientinfomethods_init(&cm, ns_client_sourceip);
 4900     dns_clientinfo_init(&ci, client, NULL);
 4901 
 4902     if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
 4903     {
 4904         return (ISC_R_NOTFOUND);
 4905     }
 4906 
 4907     if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
 4908         if (rdataset->trust == dns_trust_secure) {
 4909             return (ISC_R_NOTFOUND);
 4910         }
 4911         if (rdataset->trust == dns_trust_ultimate &&
 4912             (rdataset->type == dns_rdatatype_nsec ||
 4913              rdataset->type == dns_rdatatype_nsec3))
 4914         {
 4915             return (ISC_R_NOTFOUND);
 4916         }
 4917         if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
 4918             for (result = dns_rdataset_first(rdataset);
 4919                  result == ISC_R_SUCCESS;
 4920                  result = dns_rdataset_next(rdataset))
 4921             {
 4922                 dns_ncache_current(rdataset, found, &trdataset);
 4923                 type = trdataset.type;
 4924                 dns_rdataset_disassociate(&trdataset);
 4925                 if (type == dns_rdatatype_nsec ||
 4926                     type == dns_rdatatype_nsec3 ||
 4927                     type == dns_rdatatype_rrsig)
 4928                 {
 4929                     return (ISC_R_NOTFOUND);
 4930                 }
 4931             }
 4932         }
 4933     }
 4934 
 4935     redirectname = dns_fixedname_initname(&fixedredirect);
 4936     labels = dns_name_countlabels(client->query.qname);
 4937     if (labels > 1U) {
 4938         dns_name_t prefix;
 4939 
 4940         dns_name_init(&prefix, NULL);
 4941         dns_name_getlabelsequence(client->query.qname, 0, labels - 1,
 4942                       &prefix);
 4943         result = dns_name_concatenate(&prefix,
 4944                           client->view->redirectzone,
 4945                           redirectname, NULL);
 4946         if (result != ISC_R_SUCCESS) {
 4947             return (ISC_R_NOTFOUND);
 4948         }
 4949     } else {
 4950         dns_name_copynf(redirectname, client->view->redirectzone);
 4951     }
 4952 
 4953     options = 0;
 4954     result = query_getdb(client, redirectname, qtype, options, &zone, &db,
 4955                  &version, &is_zone);
 4956     if (result != ISC_R_SUCCESS) {
 4957         return (ISC_R_NOTFOUND);
 4958     }
 4959     if (zone != NULL) {
 4960         dns_zone_detach(&zone);
 4961     }
 4962 
 4963     /*
 4964      * Lookup the requested data in the redirect zone.
 4965      */
 4966     result = dns_db_findext(db, redirectname, version, qtype, 0,
 4967                 client->now, &node, found, &cm, &ci, &trdataset,
 4968                 NULL);
 4969     if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
 4970         if (dns_rdataset_isassociated(rdataset)) {
 4971             dns_rdataset_disassociate(rdataset);
 4972         }
 4973         if (dns_rdataset_isassociated(&trdataset)) {
 4974             dns_rdataset_disassociate(&trdataset);
 4975         }
 4976         goto nxrrset;
 4977     } else if (result == ISC_R_NOTFOUND || result == DNS_R_DELEGATION) {
 4978         /*
 4979          * Cleanup.
 4980          */
 4981         if (dns_rdataset_isassociated(&trdataset)) {
 4982             dns_rdataset_disassociate(&trdataset);
 4983         }
 4984         if (node != NULL) {
 4985             dns_db_detachnode(db, &node);
 4986         }
 4987         dns_db_detach(&db);
 4988         /*
 4989          * Don't loop forever if the lookup failed last time.
 4990          */
 4991         if (!REDIRECT(client)) {
 4992             result = ns_query_recurse(client, qtype, redirectname,
 4993                           NULL, NULL, true);
 4994             if (result == ISC_R_SUCCESS) {
 4995                 client->query.attributes |=
 4996                     NS_QUERYATTR_RECURSING;
 4997                 client->query.attributes |=
 4998                     NS_QUERYATTR_REDIRECT;
 4999                 return (DNS_R_CONTINUE);
 5000             }
 5001         }
 5002         return (ISC_R_NOTFOUND);
 5003     } else if (result != ISC_R_SUCCESS) {
 5004         if (dns_rdataset_isassociated(&trdataset)) {
 5005             dns_rdataset_disassociate(&trdataset);
 5006         }
 5007         if (node != NULL) {
 5008             dns_db_detachnode(db, &node);
 5009         }
 5010         dns_db_detach(&db);
 5011         return (ISC_R_NOTFOUND);
 5012     }
 5013 
 5014     CTRACE(ISC_LOG_DEBUG(3), "redirect2: found data: done");
 5015     /*
 5016      * Adjust the found name to not include the redirectzone suffix.
 5017      */
 5018     dns_name_split(found, dns_name_countlabels(client->view->redirectzone),
 5019                found, NULL);
 5020     /*
 5021      * Make the name absolute.
 5022      */
 5023     result = dns_name_concatenate(found, dns_rootname, found, NULL);
 5024     RUNTIME_CHECK(result == ISC_R_SUCCESS);
 5025 
 5026     dns_name_copynf(found, name);
 5027     if (dns_rdataset_isassociated(rdataset)) {
 5028         dns_rdataset_disassociate(rdataset);
 5029     }
 5030     if (dns_rdataset_isassociated(&trdataset)) {
 5031         dns_rdataset_clone(&trdataset, rdataset);
 5032         dns_rdataset_disassociate(&trdataset);
 5033     }
 5034 nxrrset:
 5035     if (*nodep != NULL) {
 5036         dns_db_detachnode(*dbp, nodep);
 5037     }
 5038     dns_db_detach(dbp);
 5039     dns_db_attachnode(db, node, nodep);
 5040     dns_db_attach(db, dbp);
 5041     dns_db_detachnode(db, &node);
 5042     dns_db_detach(&db);
 5043     *is_zonep = is_zone;
 5044     *versionp = version;
 5045 
 5046     client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
 5047                      NS_QUERYATTR_NOADDITIONAL);
 5048 
 5049     return (result);
 5050 }
 5051 
 5052 /*%
 5053  * Initialize query context 'qctx'. Run by query_setup() when
 5054  * first handling a client query, and by query_resume() when
 5055  * returning from recursion.
 5056  *
 5057  * Whenever this function is called, qctx_destroy() must be called
 5058  * when leaving the scope or freeing the qctx.
 5059  */
 5060 static void
 5061 qctx_init(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype,
 5062       query_ctx_t *qctx) {
 5063     REQUIRE(qctx != NULL);
 5064     REQUIRE(client != NULL);
 5065 
 5066     memset(qctx, 0, sizeof(*qctx));
 5067 
 5068     /* Set this first so CCTRACE will work */
 5069     qctx->client = client;
 5070 
 5071     dns_view_attach(client->view, &qctx->view);
 5072 
 5073     CCTRACE(ISC_LOG_DEBUG(3), "qctx_init");
 5074 
 5075     qctx->event = event;
 5076     qctx->qtype = qctx->type = qtype;
 5077     qctx->result = ISC_R_SUCCESS;
 5078     qctx->findcoveringnsec = qctx->view->synthfromdnssec;
 5079 
 5080     CALL_HOOK_NORETURN(NS_QUERY_QCTX_INITIALIZED, qctx);
 5081 }
 5082 
 5083 /*%
 5084  * Clean up and disassociate the rdataset and node pointers in qctx.
 5085  */
 5086 static void
 5087 qctx_clean(query_ctx_t *qctx) {
 5088     if (qctx->rdataset != NULL && dns_rdataset_isassociated(qctx->rdataset))
 5089     {
 5090         dns_rdataset_disassociate(qctx->rdataset);
 5091     }
 5092     if (qctx->sigrdataset != NULL &&
 5093         dns_rdataset_isassociated(qctx->sigrdataset)) {
 5094         dns_rdataset_disassociate(qctx->sigrdataset);
 5095     }
 5096     if (qctx->db != NULL && qctx->node != NULL) {
 5097         dns_db_detachnode(qctx->db, &qctx->node);
 5098     }
 5099 }
 5100 
 5101 /*%
 5102  * Free any allocated memory associated with qctx.
 5103  */
 5104 static void
 5105 qctx_freedata(query_ctx_t *qctx) {
 5106     if (qctx->rdataset != NULL) {
 5107         ns_client_putrdataset(qctx->client, &qctx->rdataset);
 5108     }
 5109 
 5110     if (qctx->sigrdataset != NULL) {
 5111         ns_client_putrdataset(qctx->client, &qctx->sigrdataset);
 5112     }
 5113 
 5114     if (qctx->fname != NULL) {
 5115         ns_client_releasename(qctx->client, &qctx->fname);
 5116     }
 5117 
 5118     if (qctx->db != NULL) {
 5119         INSIST(qctx->node == NULL);
 5120         dns_db_detach(&qctx->db);
 5121     }
 5122 
 5123     if (qctx->zone != NULL) {
 5124         dns_zone_detach(&qctx->zone);
 5125     }
 5126 
 5127     if (qctx->zdb != NULL) {
 5128         ns_client_putrdataset(qctx->client, &qctx->zsigrdataset);
 5129         ns_client_putrdataset(qctx->client, &qctx->zrdataset);
 5130         ns_client_releasename(qctx->client, &qctx->zfname);
 5131         dns_db_detachnode(qctx->zdb, &qctx->znode);
 5132         dns_db_detach(&qctx->zdb);
 5133     }
 5134 
 5135     if (qctx->event != NULL) {
 5136         free_devent(qctx->client, ISC_EVENT_PTR(&qctx->event),
 5137                 &qctx->event);
 5138     }
 5139 }
 5140 
 5141 static void
 5142 qctx_destroy(query_ctx_t *qctx) {
 5143     CALL_HOOK_NORETURN(NS_QUERY_QCTX_DESTROYED, qctx);
 5144 
 5145     dns_view_detach(&qctx->view);
 5146 }
 5147 
 5148 /*%
 5149  * Log detailed information about the query immediately after
 5150  * the client request or a return from recursion.
 5151  */
 5152 static void
 5153 query_trace(query_ctx_t *qctx) {
 5154 #ifdef WANT_QUERYTRACE
 5155     char mbuf[2 * DNS_NAME_FORMATSIZE];
 5156     char qbuf[DNS_NAME_FORMATSIZE];
 5157 
 5158     if (qctx->client->query.origqname != NULL) {
 5159         dns_name_format(qctx->client->query.origqname, qbuf,
 5160                 sizeof(qbuf));
 5161     } else {
 5162         snprintf(qbuf, sizeof(qbuf), "<unset>");
 5163     }
 5164 
 5165     snprintf(mbuf, sizeof(mbuf) - 1,
 5166          "client attr:0x%x, query attr:0x%X, restarts:%u, "
 5167          "origqname:%s, timer:%d, authdb:%d, referral:%d",
 5168          qctx->client->attributes, qctx->client->query.attributes,
 5169          qctx->client->query.restarts, qbuf,
 5170          (int)qctx->client->query.timerset,
 5171          (int)qctx->client->query.authdbset,
 5172          (int)qctx->client->query.isreferral);
 5173     CCTRACE(ISC_LOG_DEBUG(3), mbuf);
 5174 #else  /* ifdef WANT_QUERYTRACE */
 5175     UNUSED(qctx);
 5176 #endif /* ifdef WANT_QUERYTRACE */
 5177 }
 5178 
 5179 /*
 5180  * Set up query processing for the current query of 'client'.
 5181  * Calls qctx_init() to initialize a query context, checks
 5182  * the SERVFAIL cache, then hands off processing to ns__query_start().
 5183  *
 5184  * This is called only from ns_query_start(), to begin a query
 5185  * for the first time.  Restarting an existing query (for
 5186  * instance, to handle CNAME lookups), is done by calling
 5187  * ns__query_start() again with the same query context. Resuming from
 5188  * recursion is handled by query_resume().
 5189  */
 5190 static isc_result_t
 5191 query_setup(ns_client_t *client, dns_rdatatype_t qtype) {
 5192     isc_result_t result;
 5193     query_ctx_t qctx;
 5194 
 5195     qctx_init(client, NULL, qtype, &qctx);
 5196     query_trace(&qctx);
 5197 
 5198     CALL_HOOK(NS_QUERY_SETUP, &qctx);
 5199 
 5200     /*
 5201      * If it's a SIG query, we'll iterate the node.
 5202      */
 5203     if (qctx.qtype == dns_rdatatype_rrsig ||
 5204         qctx.qtype == dns_rdatatype_sig) {
 5205         qctx.type = dns_rdatatype_any;
 5206     }
 5207 
 5208     /*
 5209      * Check SERVFAIL cache
 5210      */
 5211     result = ns__query_sfcache(&qctx);
 5212     if (result != ISC_R_COMPLETE) {
 5213         qctx_destroy(&qctx);
 5214         return (result);
 5215     }
 5216 
 5217     result = ns__query_start(&qctx);
 5218 
 5219 cleanup:
 5220     qctx_destroy(&qctx);
 5221     return (result);
 5222 }
 5223 
 5224 static bool
 5225 get_root_key_sentinel_id(query_ctx_t *qctx, const char *ndata) {
 5226     unsigned int v = 0;
 5227     int i;
 5228 
 5229     for (i = 0; i < 5; i++) {
 5230         if (ndata[i] < '0' || ndata[i] > '9') {
 5231             return (false);
 5232         }
 5233         v *= 10;
 5234         v += ndata[i] - '0';
 5235     }
 5236     if (v > 65535U) {
 5237         return (false);
 5238     }
 5239     qctx->client->query.root_key_sentinel_keyid = v;
 5240     return (true);
 5241 }
 5242 
 5243 /*%
 5244  * Find out if the query is for a root key sentinel and if so, record the type
 5245  * of root key sentinel query and the key id that is being checked for.
 5246  *
 5247  * The code is assuming a zero padded decimal field of width 5.
 5248  */
 5249 static void
 5250 root_key_sentinel_detect(query_ctx_t *qctx) {
 5251     const char *ndata = (const char *)qctx->client->query.qname->ndata;
 5252 
 5253     if (qctx->client->query.qname->length > 30 && ndata[0] == 29 &&
 5254         strncasecmp(ndata + 1, "root-key-sentinel-is-ta-", 24) == 0)
 5255     {
 5256         if (!get_root_key_sentinel_id(qctx, ndata + 25)) {
 5257             return;
 5258         }
 5259         qctx->client->query.root_key_sentinel_is_ta = true;
 5260         /*
 5261          * Simplify processing by disabling aggressive
 5262          * negative caching.
 5263          */
 5264         qctx->findcoveringnsec = false;
 5265         ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
 5266                   NS_LOGMODULE_QUERY, ISC_LOG_INFO,
 5267                   "root-key-sentinel-is-ta query label found");
 5268     } else if (qctx->client->query.qname->length > 31 && ndata[0] == 30 &&
 5269            strncasecmp(ndata + 1, "root-key-sentinel-not-ta-", 25) == 0)
 5270     {
 5271         if (!get_root_key_sentinel_id(qctx, ndata + 26)) {
 5272             return;
 5273         }
 5274         qctx->client->query.root_key_sentinel_not_ta = true;
 5275         /*
 5276          * Simplify processing by disabling aggressive
 5277          * negative caching.
 5278          */
 5279         qctx->findcoveringnsec = false;
 5280         ns_client_log(qctx->client, NS_LOGCATEGORY_TAT,
 5281                   NS_LOGMODULE_QUERY, ISC_LOG_INFO,
 5282                   "root-key-sentinel-not-ta query label found");
 5283     }
 5284 }
 5285 
 5286 /*%
 5287  * Starting point for a client query or a chaining query.
 5288  *
 5289  * Called first by query_setup(), and then again as often as needed to
 5290  * follow a CNAME chain.  Determines which authoritative database to
 5291  * search, then hands off processing to query_lookup().
 5292  */
 5293 isc_result_t
 5294 ns__query_start(query_ctx_t *qctx) {
 5295     isc_result_t result;
 5296     CCTRACE(ISC_LOG_DEBUG(3), "ns__query_start");
 5297     qctx->want_restart = false;
 5298     qctx->authoritative = false;
 5299     qctx->version = NULL;
 5300     qctx->zversion = NULL;
 5301     qctx->need_wildcardproof = false;
 5302     qctx->rpz = false;
 5303 
 5304     CALL_HOOK(NS_QUERY_START_BEGIN, qctx);
 5305 
 5306     /*
 5307      * If we require a server cookie then send back BADCOOKIE
 5308      * before we have done too much work.
 5309      */
 5310     if (!TCP(qctx->client) && qctx->view->requireservercookie &&
 5311         WANTCOOKIE(qctx->client) && !HAVECOOKIE(qctx->client))
 5312     {
 5313         qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AA;
 5314         qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD;
 5315         qctx->client->message->rcode = dns_rcode_badcookie;
 5316         return (ns_query_done(qctx));
 5317     }
 5318 
 5319     if (qctx->view->checknames &&
 5320         !dns_rdata_checkowner(qctx->client->query.qname,
 5321                   qctx->client->message->rdclass, qctx->qtype,
 5322                   false))
 5323     {
 5324         char namebuf[DNS_NAME_FORMATSIZE];
 5325         char typebuf[DNS_RDATATYPE_FORMATSIZE];
 5326         char classbuf[DNS_RDATACLASS_FORMATSIZE];
 5327 
 5328         dns_name_format(qctx->client->query.qname, namebuf,
 5329                 sizeof(namebuf));
 5330         dns_rdatatype_format(qctx->qtype, typebuf, sizeof(typebuf));
 5331         dns_rdataclass_format(qctx->client->message->rdclass, classbuf,
 5332                       sizeof(classbuf));
 5333         ns_client_log(qctx->client, DNS_LOGCATEGORY_SECURITY,
 5334                   NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
 5335                   "check-names failure %s/%s/%s", namebuf, typebuf,
 5336                   classbuf);
 5337         QUERY_ERROR(qctx, DNS_R_REFUSED);
 5338         return (ns_query_done(qctx));
 5339     }
 5340 
 5341     /*
 5342      * Setup for root key sentinel processing.
 5343      */
 5344     if (qctx->view->root_key_sentinel &&
 5345         qctx->client->query.restarts == 0 &&
 5346         (qctx->qtype == dns_rdatatype_a ||
 5347          qctx->qtype == dns_rdatatype_aaaa) &&
 5348         (qctx->client->message->flags & DNS_MESSAGEFLAG_CD) == 0)
 5349     {
 5350         root_key_sentinel_detect(qctx);
 5351     }
 5352 
 5353     /*
 5354      * First we must find the right database.
 5355      */
 5356     qctx->options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
 5357     if (dns_rdatatype_atparent(qctx->qtype) &&
 5358         !dns_name_equal(qctx->client->query.qname, dns_rootname))
 5359     {
 5360         /*
 5361          * If authoritative data for this QTYPE is supposed to live in
 5362          * the parent zone, do not look for an exact match for QNAME,
 5363          * but rather for its containing zone (unless the QNAME is
 5364          * root).
 5365          */
 5366         qctx->options |= DNS_GETDB_NOEXACT;
 5367     }
 5368 
 5369     result = query_getdb(qctx->client, qctx->client->query.qname,
 5370                  qctx->qtype, qctx->options, &qctx->zone, &qctx->db,
 5371                  &qctx->version, &qctx->is_zone);
 5372     if (ISC_UNLIKELY((result != ISC_R_SUCCESS || !qctx->is_zone) &&
 5373              qctx->qtype == dns_rdatatype_ds &&
 5374              !RECURSIONOK(qctx->client) &&
 5375              (qctx->options & DNS_GETDB_NOEXACT) != 0))
 5376     {
 5377         /*
 5378          * This is a non-recursive QTYPE=DS query with QNAME whose
 5379          * parent we are not authoritative for.  Check whether we are
 5380          * authoritative for QNAME, because if so, we need to send a
 5381          * "no data" response as required by RFC 4035, section 3.1.4.1.
 5382          */
 5383         dns_db_t *tdb = NULL;
 5384         dns_zone_t *tzone = NULL;
 5385         dns_dbversion_t *tversion = NULL;
 5386         isc_result_t tresult;
 5387 
 5388         tresult = query_getzonedb(
 5389             qctx->client, qctx->client->query.qname, qctx->qtype,
 5390             DNS_GETDB_PARTIAL, &tzone, &tdb, &tversion);
 5391         if (tresult == ISC_R_SUCCESS) {
 5392             /*
 5393              * We are authoritative for QNAME.  Attach the relevant
 5394              * zone to query context, set result to ISC_R_SUCCESS.
 5395              */
 5396             qctx->options &= ~DNS_GETDB_NOEXACT;
 5397             ns_client_putrdataset(qctx->client, &qctx->rdataset);
 5398             if (qctx->db != NULL) {
 5399                 dns_db_detach(&qctx->db);
 5400             }
 5401             if (qctx->zone != NULL) {
 5402                 dns_zone_detach(&qctx->zone);
 5403             }
 5404             qctx->version = NULL;
 5405             RESTORE(qctx->version, tversion);
 5406             RESTORE(qctx->db, tdb);
 5407             RESTORE(qctx->zone, tzone);
 5408             qctx->is_zone = true;
 5409             result = ISC_R_SUCCESS;
 5410         } else {
 5411             /*
 5412              * We are not authoritative for QNAME.  Clean up and
 5413              * leave result as it was.
 5414              */
 5415             if (tdb != NULL) {
 5416                 dns_db_detach(&tdb);
 5417             }
 5418             if (tzone != NULL) {
 5419                 dns_zone_detach(&tzone);
 5420             }
 5421         }
 5422     }
 5423     /*
 5424      * If we did not find a database from which we can answer the query,
 5425      * respond with either REFUSED or SERVFAIL, depending on what the
 5426      * result of query_getdb() was.
 5427      */
 5428     if (result != ISC_R_SUCCESS) {
 5429         if (result == DNS_R_REFUSED) {
 5430             if (WANTRECURSION(qctx->client)) {
 5431                 inc_stats(qctx->client,
 5432                       ns_statscounter_recurserej);
 5433             } else {
 5434                 inc_stats(qctx->client,
 5435                       ns_statscounter_authrej);
 5436             }
 5437             if (!PARTIALANSWER(qctx->client)) {
 5438                 QUERY_ERROR(qctx, DNS_R_REFUSED);
 5439             }
 5440         } else {
 5441             CCTRACE(ISC_LOG_ERROR, "ns__query_start: query_getdb "
 5442                            "failed");
 5443             QUERY_ERROR(qctx, result);
 5444         }
 5445         return (ns_query_done(qctx));
 5446     }
 5447 
 5448     /*
 5449      * We found a database from which we can answer the query.  Update
 5450      * relevant query context flags if the answer is to be prepared using
 5451      * authoritative data.
 5452      */
 5453     qctx->is_staticstub_zone = false;
 5454     if (qctx->is_zone) {
 5455         qctx->authoritative = true;
 5456         if (qctx->zone != NULL) {
 5457             if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) {
 5458                 qctx->authoritative = false;
 5459             }
 5460             if (dns_zone_gettype(qctx->zone) == dns_zone_staticstub)
 5461             {
 5462                 qctx->is_staticstub_zone = true;
 5463             }
 5464         }
 5465     }
 5466 
 5467     /*
 5468      * Attach to the database which will be used to prepare the answer.
 5469      * Update query statistics.
 5470      */
 5471     if (qctx->event == NULL && qctx->client->query.restarts == 0) {
 5472         if (qctx->is_zone) {
 5473             if (qctx->zone != NULL) {
 5474                 /*
 5475                  * if is_zone = true, zone = NULL then this is
 5476                  * a DLZ zone.  Don't attempt to attach zone.
 5477                  */
 5478                 dns_zone_attach(qctx->zone,
 5479                         &qctx->client->query.authzone);
 5480             }
 5481             dns_db_attach(qctx->db, &qctx->client->query.authdb);
 5482         }
 5483         qctx->client->query.authdbset = true;
 5484 
 5485         /* Track TCP vs UDP stats per zone */
 5486         if (TCP(qctx->client)) {
 5487             inc_stats(qctx->client, ns_statscounter_tcp);
 5488         } else {
 5489             inc_stats(qctx->client, ns_statscounter_udp);
 5490         }
 5491     }
 5492 
 5493     return (query_lookup(qctx));
 5494 
 5495 cleanup:
 5496     return (result);
 5497 }