"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/ns/client.c" (4 Sep 2020, 80911 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 "client.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 #include <inttypes.h>
   13 #include <stdbool.h>
   14 
   15 #include <isc/aes.h>
   16 #include <isc/atomic.h>
   17 #include <isc/formatcheck.h>
   18 #include <isc/fuzz.h>
   19 #include <isc/hmac.h>
   20 #include <isc/mutex.h>
   21 #include <isc/nonce.h>
   22 #include <isc/once.h>
   23 #include <isc/platform.h>
   24 #include <isc/print.h>
   25 #include <isc/random.h>
   26 #include <isc/safe.h>
   27 #include <isc/serial.h>
   28 #include <isc/siphash.h>
   29 #include <isc/stats.h>
   30 #include <isc/stdio.h>
   31 #include <isc/string.h>
   32 #include <isc/task.h>
   33 #include <isc/timer.h>
   34 #include <isc/util.h>
   35 
   36 #include <dns/adb.h>
   37 #include <dns/badcache.h>
   38 #include <dns/cache.h>
   39 #include <dns/db.h>
   40 #include <dns/dispatch.h>
   41 #include <dns/dnstap.h>
   42 #include <dns/edns.h>
   43 #include <dns/events.h>
   44 #include <dns/message.h>
   45 #include <dns/peer.h>
   46 #include <dns/rcode.h>
   47 #include <dns/rdata.h>
   48 #include <dns/rdataclass.h>
   49 #include <dns/rdatalist.h>
   50 #include <dns/rdataset.h>
   51 #include <dns/resolver.h>
   52 #include <dns/stats.h>
   53 #include <dns/tsig.h>
   54 #include <dns/view.h>
   55 #include <dns/zone.h>
   56 
   57 #include <ns/client.h>
   58 #include <ns/interfacemgr.h>
   59 #include <ns/log.h>
   60 #include <ns/notify.h>
   61 #include <ns/server.h>
   62 #include <ns/stats.h>
   63 #include <ns/update.h>
   64 
   65 /***
   66  *** Client
   67  ***/
   68 
   69 /*! \file
   70  * Client Routines
   71  *
   72  * Important note!
   73  *
   74  * All client state changes, other than that from idle to listening, occur
   75  * as a result of events.  This guarantees serialization and avoids the
   76  * need for locking.
   77  *
   78  * If a routine is ever created that allows someone other than the client's
   79  * task to change the client, then the client will have to be locked.
   80  */
   81 
   82 #ifdef NS_CLIENT_TRACE
   83 #define CTRACE(m)                                                         \
   84     ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
   85               ISC_LOG_DEBUG(3), "%s", (m))
   86 #define MTRACE(m)                                                          \
   87     isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
   88               ISC_LOG_DEBUG(3), "clientmgr @%p: %s", manager, (m))
   89 #else /* ifdef NS_CLIENT_TRACE */
   90 #define CTRACE(m) ((void)(m))
   91 #define MTRACE(m) ((void)(m))
   92 #endif /* ifdef NS_CLIENT_TRACE */
   93 
   94 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
   95 
   96 #define COOKIE_SIZE 24U /* 8 + 4 + 4 + 8 */
   97 #define ECS_SIZE    20U /* 2 + 1 + 1 + [0..16] */
   98 
   99 #define WANTNSID(x) (((x)->attributes & NS_CLIENTATTR_WANTNSID) != 0)
  100 #define WANTEXPIRE(x)   (((x)->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0)
  101 #define WANTPAD(x)  (((x)->attributes & NS_CLIENTATTR_WANTPAD) != 0)
  102 #define USEKEEPALIVE(x) (((x)->attributes & NS_CLIENTATTR_USEKEEPALIVE) != 0)
  103 
  104 #define MANAGER_MAGIC    ISC_MAGIC('N', 'S', 'C', 'm')
  105 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
  106 
  107 /*
  108  * Enable ns_client_dropport() by default.
  109  */
  110 #ifndef NS_CLIENT_DROPPORT
  111 #define NS_CLIENT_DROPPORT 1
  112 #endif /* ifndef NS_CLIENT_DROPPORT */
  113 
  114 #define CLIENT_NMCTXS_PERCPU 8
  115 /*%<
  116  * Number of 'mctx pools' for clients. (Should this be configurable?)
  117  * When enabling threads, we use a pool of memory contexts shared by
  118  * client objects, since concurrent access to a shared context would cause
  119  * heavy contentions.  The above constant is expected to be enough for
  120  * completely avoiding contentions among threads for an authoritative-only
  121  * server.
  122  */
  123 
  124 #define CLIENT_NTASKS_PERCPU 32
  125 /*%<
  126  * Number of tasks to be used by clients - those are used only when recursing
  127  */
  128 
  129 #if defined(_WIN32) && !defined(_WIN64)
  130 LIBNS_EXTERNAL_DATA atomic_uint_fast32_t ns_client_requests;
  131 #else  /* if defined(_WIN32) && !defined(_WIN64) */
  132 LIBNS_EXTERNAL_DATA atomic_uint_fast64_t ns_client_requests;
  133 #endif /* if defined(_WIN32) && !defined(_WIN64) */
  134 
  135 static void
  136 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp);
  137 static void
  138 clientmgr_detach(ns_clientmgr_t **mp);
  139 static void
  140 clientmgr_destroy(ns_clientmgr_t *manager);
  141 static void
  142 ns_client_endrequest(ns_client_t *client);
  143 static void
  144 ns_client_dumpmessage(ns_client_t *client, const char *reason);
  145 static void
  146 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
  147            const unsigned char *secret, isc_buffer_t *buf);
  148 static void
  149 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp);
  150 static void
  151 get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp);
  152 
  153 void
  154 ns_client_recursing(ns_client_t *client) {
  155     REQUIRE(NS_CLIENT_VALID(client));
  156     REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
  157 
  158     LOCK(&client->manager->reclock);
  159     client->state = NS_CLIENTSTATE_RECURSING;
  160     ISC_LIST_APPEND(client->manager->recursing, client, rlink);
  161     UNLOCK(&client->manager->reclock);
  162 }
  163 
  164 void
  165 ns_client_killoldestquery(ns_client_t *client) {
  166     ns_client_t *oldest;
  167     REQUIRE(NS_CLIENT_VALID(client));
  168 
  169     LOCK(&client->manager->reclock);
  170     oldest = ISC_LIST_HEAD(client->manager->recursing);
  171     if (oldest != NULL) {
  172         ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
  173         ns_query_cancel(oldest);
  174         ns_stats_increment(client->sctx->nsstats,
  175                    ns_statscounter_reclimitdropped);
  176     }
  177     UNLOCK(&client->manager->reclock);
  178 }
  179 
  180 void
  181 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
  182     UNUSED(client);
  183     UNUSED(seconds);
  184     /* XXXWPK TODO use netmgr to set timeout */
  185 }
  186 
  187 static void
  188 ns_client_endrequest(ns_client_t *client) {
  189     INSIST(client->nupdates == 0);
  190     INSIST(client->state == NS_CLIENTSTATE_WORKING ||
  191            client->state == NS_CLIENTSTATE_RECURSING);
  192 
  193     CTRACE("endrequest");
  194 
  195     if (client->state == NS_CLIENTSTATE_RECURSING) {
  196         LOCK(&client->manager->reclock);
  197         if (ISC_LINK_LINKED(client, rlink)) {
  198             ISC_LIST_UNLINK(client->manager->recursing, client,
  199                     rlink);
  200         }
  201         UNLOCK(&client->manager->reclock);
  202     }
  203 
  204     if (client->cleanup != NULL) {
  205         (client->cleanup)(client);
  206         client->cleanup = NULL;
  207     }
  208 
  209     if (client->view != NULL) {
  210 #ifdef ENABLE_AFL
  211         if (client->sctx->fuzztype == isc_fuzz_resolver) {
  212             dns_cache_clean(client->view->cache, INT_MAX);
  213             dns_adb_flush(client->view->adb);
  214         }
  215 #endif /* ifdef ENABLE_AFL */
  216         dns_view_detach(&client->view);
  217     }
  218     if (client->opt != NULL) {
  219         INSIST(dns_rdataset_isassociated(client->opt));
  220         dns_rdataset_disassociate(client->opt);
  221         dns_message_puttemprdataset(client->message, &client->opt);
  222     }
  223 
  224     client->signer = NULL;
  225     client->udpsize = 512;
  226     client->extflags = 0;
  227     client->ednsversion = -1;
  228     dns_ecs_init(&client->ecs);
  229     dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
  230 
  231     /*
  232      * Clean up from recursion - normally this would be done in
  233      * fetch_callback(), but if we're shutting down and canceling then
  234      * it might not have happened.
  235      */
  236     if (client->recursionquota != NULL) {
  237         isc_quota_detach(&client->recursionquota);
  238         if (client->query.prefetch == NULL) {
  239             ns_stats_decrement(client->sctx->nsstats,
  240                        ns_statscounter_recursclients);
  241         }
  242     }
  243 
  244     /*
  245      * Clear all client attributes that are specific to the request
  246      */
  247     client->attributes = 0;
  248 #ifdef ENABLE_AFL
  249     if (client->sctx->fuzznotify != NULL &&
  250         (client->sctx->fuzztype == isc_fuzz_client ||
  251          client->sctx->fuzztype == isc_fuzz_tcpclient ||
  252          client->sctx->fuzztype == isc_fuzz_resolver))
  253     {
  254         client->sctx->fuzznotify();
  255     }
  256 #endif /* ENABLE_AFL */
  257 }
  258 
  259 void
  260 ns_client_drop(ns_client_t *client, isc_result_t result) {
  261     REQUIRE(NS_CLIENT_VALID(client));
  262     REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
  263         client->state == NS_CLIENTSTATE_RECURSING);
  264 
  265     CTRACE("drop");
  266     if (result != ISC_R_SUCCESS) {
  267         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  268                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
  269                   "request failed: %s", isc_result_totext(result));
  270     }
  271 }
  272 
  273 static void
  274 client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
  275     ns_client_t *client = cbarg;
  276 
  277     REQUIRE(client->handle == handle);
  278 
  279     CTRACE("senddone");
  280     if (result != ISC_R_SUCCESS) {
  281         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  282                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
  283                   "send failed: %s", isc_result_totext(result));
  284     }
  285 
  286     isc_nmhandle_unref(handle);
  287 }
  288 
  289 static void
  290 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
  291             unsigned char **datap) {
  292     unsigned char *data;
  293     uint32_t bufsize;
  294 
  295     REQUIRE(datap != NULL);
  296 
  297     if (TCP_CLIENT(client)) {
  298         INSIST(client->tcpbuf == NULL);
  299         client->tcpbuf = isc_mem_get(client->mctx,
  300                          NS_CLIENT_TCP_BUFFER_SIZE);
  301         data = client->tcpbuf;
  302         isc_buffer_init(buffer, data, NS_CLIENT_TCP_BUFFER_SIZE);
  303     } else {
  304         data = client->sendbuf;
  305         if ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) == 0) {
  306             if (client->view != NULL) {
  307                 bufsize = client->view->nocookieudp;
  308             } else {
  309                 bufsize = 512;
  310             }
  311         } else {
  312             bufsize = client->udpsize;
  313         }
  314         if (bufsize > client->udpsize) {
  315             bufsize = client->udpsize;
  316         }
  317         if (bufsize > NS_CLIENT_SEND_BUFFER_SIZE) {
  318             bufsize = NS_CLIENT_SEND_BUFFER_SIZE;
  319         }
  320         isc_buffer_init(buffer, data, bufsize);
  321     }
  322     *datap = data;
  323 }
  324 
  325 static isc_result_t
  326 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
  327     isc_region_t r;
  328 
  329     isc_buffer_usedregion(buffer, &r);
  330 
  331     INSIST(client->handle != NULL);
  332 
  333     return (isc_nm_send(client->handle, &r, client_senddone, client));
  334 }
  335 
  336 void
  337 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
  338     isc_result_t result;
  339     unsigned char *data;
  340     isc_buffer_t buffer;
  341     isc_region_t r;
  342     isc_region_t *mr;
  343 
  344     REQUIRE(NS_CLIENT_VALID(client));
  345 
  346     CTRACE("sendraw");
  347 
  348     mr = dns_message_getrawmessage(message);
  349     if (mr == NULL) {
  350         result = ISC_R_UNEXPECTEDEND;
  351         goto done;
  352     }
  353 
  354     client_allocsendbuf(client, &buffer, &data);
  355 
  356     if (mr->length > isc_buffer_length(&buffer)) {
  357         result = ISC_R_NOSPACE;
  358         goto done;
  359     }
  360 
  361     /*
  362      * Copy message to buffer and fixup id.
  363      */
  364     isc_buffer_availableregion(&buffer, &r);
  365     result = isc_buffer_copyregion(&buffer, mr);
  366     if (result != ISC_R_SUCCESS) {
  367         goto done;
  368     }
  369     r.base[0] = (client->message->id >> 8) & 0xff;
  370     r.base[1] = client->message->id & 0xff;
  371 
  372     result = client_sendpkg(client, &buffer);
  373     if (result == ISC_R_SUCCESS) {
  374         return;
  375     }
  376 
  377 done:
  378     if (client->tcpbuf != NULL) {
  379         isc_mem_put(client->mctx, client->tcpbuf,
  380                 NS_CLIENT_TCP_BUFFER_SIZE);
  381         client->tcpbuf = NULL;
  382     }
  383 
  384     ns_client_drop(client, result);
  385     isc_nmhandle_unref(client->handle);
  386 }
  387 
  388 void
  389 ns_client_send(ns_client_t *client) {
  390     isc_result_t result;
  391     unsigned char *data;
  392     isc_buffer_t buffer = { .magic = 0 };
  393     isc_region_t r;
  394     dns_compress_t cctx;
  395     bool cleanup_cctx = false;
  396     unsigned int render_opts;
  397     unsigned int preferred_glue;
  398     bool opt_included = false;
  399     size_t respsize;
  400     dns_aclenv_t *env;
  401 #ifdef HAVE_DNSTAP
  402     unsigned char zone[DNS_NAME_MAXWIRE];
  403     dns_dtmsgtype_t dtmsgtype;
  404     isc_region_t zr;
  405 #endif /* HAVE_DNSTAP */
  406 
  407     /*
  408      * XXXWPK TODO
  409      * Delay the response according to the -T delay option
  410      */
  411 
  412     REQUIRE(NS_CLIENT_VALID(client));
  413     /*
  414      * We need to do it to make sure the client and handle
  415      * won't disappear from under us with client_senddone.
  416      */
  417 
  418     env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
  419 
  420     CTRACE("send");
  421 
  422     if (client->message->opcode == dns_opcode_query &&
  423         (client->attributes & NS_CLIENTATTR_RA) != 0)
  424     {
  425         client->message->flags |= DNS_MESSAGEFLAG_RA;
  426     }
  427 
  428     if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) {
  429         render_opts = 0;
  430     } else {
  431         render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
  432     }
  433 
  434     preferred_glue = 0;
  435     if (client->view != NULL) {
  436         if (client->view->preferred_glue == dns_rdatatype_a) {
  437             preferred_glue = DNS_MESSAGERENDER_PREFER_A;
  438         } else if (client->view->preferred_glue == dns_rdatatype_aaaa) {
  439             preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
  440         }
  441     }
  442     if (preferred_glue == 0) {
  443         if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
  444             preferred_glue = DNS_MESSAGERENDER_PREFER_A;
  445         } else {
  446             preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
  447         }
  448     }
  449 
  450     /*
  451      * Create an OPT for our reply.
  452      */
  453     if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
  454         result = ns_client_addopt(client, client->message,
  455                       &client->opt);
  456         if (result != ISC_R_SUCCESS) {
  457             goto done;
  458         }
  459     }
  460 
  461     client_allocsendbuf(client, &buffer, &data);
  462 
  463     result = dns_compress_init(&cctx, -1, client->mctx);
  464     if (result != ISC_R_SUCCESS) {
  465         goto done;
  466     }
  467     if (client->peeraddr_valid && client->view != NULL) {
  468         isc_netaddr_t netaddr;
  469         dns_name_t *name = NULL;
  470 
  471         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
  472         if (client->message->tsigkey != NULL) {
  473             name = &client->message->tsigkey->name;
  474         }
  475 
  476         if (client->view->nocasecompress == NULL ||
  477             !dns_acl_allowed(&netaddr, name,
  478                      client->view->nocasecompress, env))
  479         {
  480             dns_compress_setsensitive(&cctx, true);
  481         }
  482 
  483         if (!client->view->msgcompression) {
  484             dns_compress_disable(&cctx);
  485         }
  486     }
  487     cleanup_cctx = true;
  488 
  489     result = dns_message_renderbegin(client->message, &cctx, &buffer);
  490     if (result != ISC_R_SUCCESS) {
  491         goto done;
  492     }
  493 
  494     if (client->opt != NULL) {
  495         result = dns_message_setopt(client->message, client->opt);
  496         opt_included = true;
  497         client->opt = NULL;
  498         if (result != ISC_R_SUCCESS) {
  499             goto done;
  500         }
  501     }
  502     result = dns_message_rendersection(client->message,
  503                        DNS_SECTION_QUESTION, 0);
  504     if (result == ISC_R_NOSPACE) {
  505         client->message->flags |= DNS_MESSAGEFLAG_TC;
  506         goto renderend;
  507     }
  508     if (result != ISC_R_SUCCESS) {
  509         goto done;
  510     }
  511     /*
  512      * Stop after the question if TC was set for rate limiting.
  513      */
  514     if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
  515         goto renderend;
  516     }
  517     result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER,
  518                        DNS_MESSAGERENDER_PARTIAL |
  519                            render_opts);
  520     if (result == ISC_R_NOSPACE) {
  521         client->message->flags |= DNS_MESSAGEFLAG_TC;
  522         goto renderend;
  523     }
  524     if (result != ISC_R_SUCCESS) {
  525         goto done;
  526     }
  527     result = dns_message_rendersection(
  528         client->message, DNS_SECTION_AUTHORITY,
  529         DNS_MESSAGERENDER_PARTIAL | render_opts);
  530     if (result == ISC_R_NOSPACE) {
  531         client->message->flags |= DNS_MESSAGEFLAG_TC;
  532         goto renderend;
  533     }
  534     if (result != ISC_R_SUCCESS) {
  535         goto done;
  536     }
  537     result = dns_message_rendersection(client->message,
  538                        DNS_SECTION_ADDITIONAL,
  539                        preferred_glue | render_opts);
  540     if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) {
  541         goto done;
  542     }
  543 renderend:
  544     result = dns_message_renderend(client->message);
  545     if (result != ISC_R_SUCCESS) {
  546         goto done;
  547     }
  548 
  549 #ifdef HAVE_DNSTAP
  550     memset(&zr, 0, sizeof(zr));
  551     if (((client->message->flags & DNS_MESSAGEFLAG_AA) != 0) &&
  552         (client->query.authzone != NULL))
  553     {
  554         isc_buffer_t b;
  555         dns_name_t *zo = dns_zone_getorigin(client->query.authzone);
  556 
  557         isc_buffer_init(&b, zone, sizeof(zone));
  558         dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
  559         result = dns_name_towire(zo, &cctx, &b);
  560         if (result == ISC_R_SUCCESS) {
  561             isc_buffer_usedregion(&b, &zr);
  562         }
  563     }
  564 
  565     if (client->message->opcode == dns_opcode_update) {
  566         dtmsgtype = DNS_DTTYPE_UR;
  567     } else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
  568         dtmsgtype = DNS_DTTYPE_CR;
  569     } else {
  570         dtmsgtype = DNS_DTTYPE_AR;
  571     }
  572 #endif /* HAVE_DNSTAP */
  573 
  574     if (cleanup_cctx) {
  575         dns_compress_invalidate(&cctx);
  576         cleanup_cctx = false;
  577     }
  578 
  579     if (client->sendcb != NULL) {
  580         client->sendcb(&buffer);
  581     } else if (TCP_CLIENT(client)) {
  582         isc_buffer_usedregion(&buffer, &r);
  583 #ifdef HAVE_DNSTAP
  584         if (client->view != NULL) {
  585             dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
  586                     &client->destsockaddr, true, &zr,
  587                     &client->requesttime, NULL, &buffer);
  588         }
  589 #endif /* HAVE_DNSTAP */
  590 
  591         respsize = isc_buffer_usedlength(&buffer);
  592 
  593         isc_nmhandle_ref(client->handle);
  594         result = client_sendpkg(client, &buffer);
  595         if (result != ISC_R_SUCCESS) {
  596             /* We won't get a callback to clean it up */
  597             isc_nmhandle_unref(client->handle);
  598         }
  599 
  600         switch (isc_sockaddr_pf(&client->peeraddr)) {
  601         case AF_INET:
  602             isc_stats_increment(client->sctx->tcpoutstats4,
  603                         ISC_MIN((int)respsize / 16, 256));
  604             break;
  605         case AF_INET6:
  606             isc_stats_increment(client->sctx->tcpoutstats6,
  607                         ISC_MIN((int)respsize / 16, 256));
  608             break;
  609         default:
  610             INSIST(0);
  611             ISC_UNREACHABLE();
  612         }
  613     } else {
  614 #ifdef HAVE_DNSTAP
  615         /*
  616          * Log dnstap data first, because client_sendpkg() may
  617          * leave client->view set to NULL.
  618          */
  619         if (client->view != NULL) {
  620             dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
  621                     &client->destsockaddr, false, &zr,
  622                     &client->requesttime, NULL, &buffer);
  623         }
  624 #endif /* HAVE_DNSTAP */
  625 
  626         respsize = isc_buffer_usedlength(&buffer);
  627 
  628         isc_nmhandle_ref(client->handle);
  629         result = client_sendpkg(client, &buffer);
  630         if (result != ISC_R_SUCCESS) {
  631             /* We won't get a callback to clean it up */
  632             isc_nmhandle_unref(client->handle);
  633         }
  634 
  635         switch (isc_sockaddr_pf(&client->peeraddr)) {
  636         case AF_INET:
  637             isc_stats_increment(client->sctx->udpoutstats4,
  638                         ISC_MIN((int)respsize / 16, 256));
  639             break;
  640         case AF_INET6:
  641             isc_stats_increment(client->sctx->udpoutstats6,
  642                         ISC_MIN((int)respsize / 16, 256));
  643             break;
  644         default:
  645             INSIST(0);
  646             ISC_UNREACHABLE();
  647         }
  648     }
  649 
  650     /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
  651     ns_stats_increment(client->sctx->nsstats, ns_statscounter_response);
  652 
  653     dns_rcodestats_increment(client->sctx->rcodestats,
  654                  client->message->rcode);
  655     if (opt_included) {
  656         ns_stats_increment(client->sctx->nsstats,
  657                    ns_statscounter_edns0out);
  658     }
  659     if (client->message->tsigkey != NULL) {
  660         ns_stats_increment(client->sctx->nsstats,
  661                    ns_statscounter_tsigout);
  662     }
  663     if (client->message->sig0key != NULL) {
  664         ns_stats_increment(client->sctx->nsstats,
  665                    ns_statscounter_sig0out);
  666     }
  667     if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
  668         ns_stats_increment(client->sctx->nsstats,
  669                    ns_statscounter_truncatedresp);
  670     }
  671 
  672     if (result == ISC_R_SUCCESS) {
  673         return;
  674     }
  675 
  676 done:
  677     if (client->tcpbuf != NULL) {
  678         isc_mem_put(client->mctx, client->tcpbuf,
  679                 NS_CLIENT_TCP_BUFFER_SIZE);
  680         client->tcpbuf = NULL;
  681     }
  682 
  683     if (cleanup_cctx) {
  684         dns_compress_invalidate(&cctx);
  685     }
  686 }
  687 
  688 #if NS_CLIENT_DROPPORT
  689 #define DROPPORT_NO   0
  690 #define DROPPORT_REQUEST  1
  691 #define DROPPORT_RESPONSE 2
  692 /*%
  693  * ns_client_dropport determines if certain requests / responses
  694  * should be dropped based on the port number.
  695  *
  696  * Returns:
  697  * \li  0:  Don't drop.
  698  * \li  1:  Drop request.
  699  * \li  2:  Drop (error) response.
  700  */
  701 static int
  702 ns_client_dropport(in_port_t port) {
  703     switch (port) {
  704     case 7:  /* echo */
  705     case 13: /* daytime */
  706     case 19: /* chargen */
  707     case 37: /* time */
  708         return (DROPPORT_REQUEST);
  709     case 464: /* kpasswd */
  710         return (DROPPORT_RESPONSE);
  711     }
  712     return (DROPPORT_NO);
  713 }
  714 #endif /* if NS_CLIENT_DROPPORT */
  715 
  716 void
  717 ns_client_error(ns_client_t *client, isc_result_t result) {
  718     dns_rcode_t rcode;
  719     dns_message_t *message;
  720 
  721     REQUIRE(NS_CLIENT_VALID(client));
  722 
  723     CTRACE("error");
  724 
  725     message = client->message;
  726 
  727     if (client->rcode_override == -1) {
  728         rcode = dns_result_torcode(result);
  729     } else {
  730         rcode = (dns_rcode_t)(client->rcode_override & 0xfff);
  731     }
  732 
  733 #if NS_CLIENT_DROPPORT
  734     /*
  735      * Don't send FORMERR to ports on the drop port list.
  736      */
  737     if (rcode == dns_rcode_formerr &&
  738         ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
  739             DROPPORT_NO)
  740     {
  741         char buf[64];
  742         isc_buffer_t b;
  743 
  744         isc_buffer_init(&b, buf, sizeof(buf) - 1);
  745         if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS) {
  746             isc_buffer_putstr(&b, "UNKNOWN RCODE");
  747         }
  748         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  749                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
  750                   "dropped error (%.*s) response: suspicious port",
  751                   (int)isc_buffer_usedlength(&b), buf);
  752         ns_client_drop(client, ISC_R_SUCCESS);
  753         return;
  754     }
  755 #endif /* if NS_CLIENT_DROPPORT */
  756 
  757     /*
  758      * Try to rate limit error responses.
  759      */
  760     if (client->view != NULL && client->view->rrl != NULL) {
  761         bool wouldlog;
  762         char log_buf[DNS_RRL_LOG_BUF_LEN];
  763         dns_rrl_result_t rrl_result;
  764         int loglevel;
  765 
  766         INSIST(rcode != dns_rcode_noerror &&
  767                rcode != dns_rcode_nxdomain);
  768         if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
  769             loglevel = DNS_RRL_LOG_DROP;
  770         } else {
  771             loglevel = ISC_LOG_DEBUG(1);
  772         }
  773         wouldlog = isc_log_wouldlog(ns_lctx, loglevel);
  774         rrl_result = dns_rrl(
  775             client->view, &client->peeraddr, TCP_CLIENT(client),
  776             dns_rdataclass_in, dns_rdatatype_none, NULL, result,
  777             client->now, wouldlog, log_buf, sizeof(log_buf));
  778         if (rrl_result != DNS_RRL_RESULT_OK) {
  779             /*
  780              * Log dropped errors in the query category
  781              * so that they are not lost in silence.
  782              * Starts of rate-limited bursts are logged in
  783              * NS_LOGCATEGORY_RRL.
  784              */
  785             if (wouldlog) {
  786                 ns_client_log(client,
  787                           NS_LOGCATEGORY_QUERY_ERRORS,
  788                           NS_LOGMODULE_CLIENT, loglevel,
  789                           "%s", log_buf);
  790             }
  791             /*
  792              * Some error responses cannot be 'slipped',
  793              * so don't try to slip any error responses.
  794              */
  795             if (!client->view->rrl->log_only) {
  796                 ns_stats_increment(client->sctx->nsstats,
  797                            ns_statscounter_ratedropped);
  798                 ns_stats_increment(client->sctx->nsstats,
  799                            ns_statscounter_dropped);
  800                 ns_client_drop(client, DNS_R_DROP);
  801                 return;
  802             }
  803         }
  804     }
  805 
  806     /*
  807      * Message may be an in-progress reply that we had trouble
  808      * with, in which case QR will be set.  We need to clear QR before
  809      * calling dns_message_reply() to avoid triggering an assertion.
  810      */
  811     message->flags &= ~DNS_MESSAGEFLAG_QR;
  812     /*
  813      * AA and AD shouldn't be set.
  814      */
  815     message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
  816     result = dns_message_reply(message, true);
  817     if (result != ISC_R_SUCCESS) {
  818         /*
  819          * It could be that we've got a query with a good header,
  820          * but a bad question section, so we try again with
  821          * want_question_section set to false.
  822          */
  823         result = dns_message_reply(message, false);
  824         if (result != ISC_R_SUCCESS) {
  825             ns_client_drop(client, result);
  826             return;
  827         }
  828     }
  829     message->rcode = rcode;
  830 
  831     if (rcode == dns_rcode_formerr) {
  832         /*
  833          * FORMERR loop avoidance:  If we sent a FORMERR message
  834          * with the same ID to the same client less than two
  835          * seconds ago, assume that we are in an infinite error
  836          * packet dialog with a server for some protocol whose
  837          * error responses look enough like DNS queries to
  838          * elicit a FORMERR response.  Drop a packet to break
  839          * the loop.
  840          */
  841         if (isc_sockaddr_equal(&client->peeraddr,
  842                        &client->formerrcache.addr) &&
  843             message->id == client->formerrcache.id &&
  844             (isc_time_seconds(&client->requesttime) -
  845              client->formerrcache.time) < 2)
  846         {
  847             /* Drop packet. */
  848             ns_client_log(client, NS_LOGCATEGORY_CLIENT,
  849                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
  850                       "possible error packet loop, "
  851                       "FORMERR dropped");
  852             ns_client_drop(client, result);
  853             return;
  854         }
  855         client->formerrcache.addr = client->peeraddr;
  856         client->formerrcache.time =
  857             isc_time_seconds(&client->requesttime);
  858         client->formerrcache.id = message->id;
  859     } else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
  860            client->view != NULL && client->view->fail_ttl != 0 &&
  861            ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
  862     {
  863         /*
  864          * SERVFAIL caching: store qname/qtype of failed queries
  865          */
  866         isc_time_t expire;
  867         isc_interval_t i;
  868         uint32_t flags = 0;
  869 
  870         if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
  871             flags = NS_FAILCACHE_CD;
  872         }
  873 
  874         isc_interval_set(&i, client->view->fail_ttl, 0);
  875         result = isc_time_nowplusinterval(&expire, &i);
  876         if (result == ISC_R_SUCCESS) {
  877             dns_badcache_add(
  878                 client->view->failcache, client->query.qname,
  879                 client->query.qtype, true, flags, &expire);
  880         }
  881     }
  882 
  883     ns_client_send(client);
  884 }
  885 
  886 isc_result_t
  887 ns_client_addopt(ns_client_t *client, dns_message_t *message,
  888          dns_rdataset_t **opt) {
  889     unsigned char ecs[ECS_SIZE];
  890     char nsid[BUFSIZ], *nsidp;
  891     unsigned char cookie[COOKIE_SIZE];
  892     isc_result_t result;
  893     dns_view_t *view;
  894     dns_resolver_t *resolver;
  895     uint16_t udpsize;
  896     dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
  897     int count = 0;
  898     unsigned int flags;
  899     unsigned char expire[4];
  900     unsigned char advtimo[2];
  901     dns_aclenv_t *env;
  902 
  903     REQUIRE(NS_CLIENT_VALID(client));
  904     REQUIRE(opt != NULL && *opt == NULL);
  905     REQUIRE(message != NULL);
  906 
  907     env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
  908     view = client->view;
  909     resolver = (view != NULL) ? view->resolver : NULL;
  910     if (resolver != NULL) {
  911         udpsize = dns_resolver_getudpsize(resolver);
  912     } else {
  913         udpsize = client->sctx->udpsize;
  914     }
  915 
  916     flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
  917 
  918     /* Set EDNS options if applicable */
  919     if (WANTNSID(client)) {
  920         if (client->sctx->server_id != NULL) {
  921             nsidp = client->sctx->server_id;
  922         } else if (client->sctx->gethostname != NULL) {
  923             result = client->sctx->gethostname(nsid, sizeof(nsid));
  924             if (result != ISC_R_SUCCESS) {
  925                 goto no_nsid;
  926             }
  927             nsidp = nsid;
  928         } else {
  929             goto no_nsid;
  930         }
  931 
  932         INSIST(count < DNS_EDNSOPTIONS);
  933         ednsopts[count].code = DNS_OPT_NSID;
  934         ednsopts[count].length = (uint16_t)strlen(nsidp);
  935         ednsopts[count].value = (unsigned char *)nsidp;
  936         count++;
  937     }
  938 no_nsid:
  939     if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) {
  940         isc_buffer_t buf;
  941         isc_stdtime_t now;
  942         uint32_t nonce;
  943 
  944         isc_buffer_init(&buf, cookie, sizeof(cookie));
  945         isc_stdtime_get(&now);
  946 
  947         isc_random_buf(&nonce, sizeof(nonce));
  948 
  949         compute_cookie(client, now, nonce, client->sctx->secret, &buf);
  950 
  951         INSIST(count < DNS_EDNSOPTIONS);
  952         ednsopts[count].code = DNS_OPT_COOKIE;
  953         ednsopts[count].length = COOKIE_SIZE;
  954         ednsopts[count].value = cookie;
  955         count++;
  956     }
  957     if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
  958         isc_buffer_t buf;
  959 
  960         INSIST(count < DNS_EDNSOPTIONS);
  961 
  962         isc_buffer_init(&buf, expire, sizeof(expire));
  963         isc_buffer_putuint32(&buf, client->expire);
  964         ednsopts[count].code = DNS_OPT_EXPIRE;
  965         ednsopts[count].length = 4;
  966         ednsopts[count].value = expire;
  967         count++;
  968     }
  969     if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
  970         (client->ecs.addr.family == AF_INET ||
  971          client->ecs.addr.family == AF_INET6 ||
  972          client->ecs.addr.family == AF_UNSPEC))
  973     {
  974         isc_buffer_t buf;
  975         uint8_t addr[16];
  976         uint32_t plen, addrl;
  977         uint16_t family = 0;
  978 
  979         /* Add CLIENT-SUBNET option. */
  980 
  981         plen = client->ecs.source;
  982 
  983         /* Round up prefix len to a multiple of 8 */
  984         addrl = (plen + 7) / 8;
  985 
  986         switch (client->ecs.addr.family) {
  987         case AF_UNSPEC:
  988             INSIST(plen == 0);
  989             family = 0;
  990             break;
  991         case AF_INET:
  992             INSIST(plen <= 32);
  993             family = 1;
  994             memmove(addr, &client->ecs.addr.type, addrl);
  995             break;
  996         case AF_INET6:
  997             INSIST(plen <= 128);
  998             family = 2;
  999             memmove(addr, &client->ecs.addr.type, addrl);
 1000             break;
 1001         default:
 1002             INSIST(0);
 1003             ISC_UNREACHABLE();
 1004         }
 1005 
 1006         isc_buffer_init(&buf, ecs, sizeof(ecs));
 1007         /* family */
 1008         isc_buffer_putuint16(&buf, family);
 1009         /* source prefix-length */
 1010         isc_buffer_putuint8(&buf, client->ecs.source);
 1011         /* scope prefix-length */
 1012         isc_buffer_putuint8(&buf, client->ecs.scope);
 1013 
 1014         /* address */
 1015         if (addrl > 0) {
 1016             /* Mask off last address byte */
 1017             if ((plen % 8) != 0) {
 1018                 addr[addrl - 1] &= ~0U << (8 - (plen % 8));
 1019             }
 1020             isc_buffer_putmem(&buf, addr, (unsigned)addrl);
 1021         }
 1022 
 1023         ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
 1024         ednsopts[count].length = addrl + 4;
 1025         ednsopts[count].value = ecs;
 1026         count++;
 1027     }
 1028     if (TCP_CLIENT(client) && USEKEEPALIVE(client)) {
 1029         isc_buffer_t buf;
 1030         uint32_t adv;
 1031 
 1032         INSIST(count < DNS_EDNSOPTIONS);
 1033 
 1034         isc_nm_tcp_gettimeouts(isc_nmhandle_netmgr(client->handle),
 1035                        NULL, NULL, NULL, &adv);
 1036         isc_buffer_init(&buf, advtimo, sizeof(advtimo));
 1037         isc_buffer_putuint16(&buf, (uint16_t)adv);
 1038         ednsopts[count].code = DNS_OPT_TCP_KEEPALIVE;
 1039         ednsopts[count].length = 2;
 1040         ednsopts[count].value = advtimo;
 1041         count++;
 1042     }
 1043 
 1044     /* Padding must be added last */
 1045     if ((view != NULL) && (view->padding > 0) && WANTPAD(client) &&
 1046         (TCP_CLIENT(client) ||
 1047          ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)))
 1048     {
 1049         isc_netaddr_t netaddr;
 1050         int match;
 1051 
 1052         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 1053         result = dns_acl_match(&netaddr, NULL, view->pad_acl, env,
 1054                        &match, NULL);
 1055         if (result == ISC_R_SUCCESS && match > 0) {
 1056             INSIST(count < DNS_EDNSOPTIONS);
 1057 
 1058             ednsopts[count].code = DNS_OPT_PAD;
 1059             ednsopts[count].length = 0;
 1060             ednsopts[count].value = NULL;
 1061             count++;
 1062 
 1063             dns_message_setpadding(message, view->padding);
 1064         }
 1065     }
 1066 
 1067     result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts,
 1068                       count);
 1069     return (result);
 1070 }
 1071 
 1072 static void
 1073 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
 1074            const unsigned char *secret, isc_buffer_t *buf) {
 1075     unsigned char digest[ISC_MAX_MD_SIZE] ISC_NONSTRING = { 0 };
 1076     STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_SIPHASH24_TAG_LENGTH, "You need "
 1077                                    "to "
 1078                                    "increase "
 1079                                    "the digest "
 1080                                    "buffer.");
 1081     STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_AES_BLOCK_LENGTH, "You need to "
 1082                                    "increase the "
 1083                                    "digest "
 1084                                    "buffer.");
 1085 
 1086     switch (client->sctx->cookiealg) {
 1087     case ns_cookiealg_siphash24: {
 1088         unsigned char input[16 + 16] ISC_NONSTRING = { 0 };
 1089         size_t inputlen = 0;
 1090         isc_netaddr_t netaddr;
 1091         unsigned char *cp;
 1092 
 1093         cp = isc_buffer_used(buf);
 1094         isc_buffer_putmem(buf, client->cookie, 8);
 1095         isc_buffer_putuint8(buf, NS_COOKIE_VERSION_1);
 1096         isc_buffer_putuint24(buf, 0); /* Reserved */
 1097         isc_buffer_putuint32(buf, when);
 1098 
 1099         memmove(input, cp, 16);
 1100 
 1101         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 1102         switch (netaddr.family) {
 1103         case AF_INET:
 1104             cp = (unsigned char *)&netaddr.type.in;
 1105             memmove(input + 16, cp, 4);
 1106             inputlen = 20;
 1107             break;
 1108         case AF_INET6:
 1109             cp = (unsigned char *)&netaddr.type.in6;
 1110             memmove(input + 16, cp, 16);
 1111             inputlen = 32;
 1112             break;
 1113         default:
 1114             INSIST(0);
 1115             ISC_UNREACHABLE();
 1116         }
 1117 
 1118         isc_siphash24(secret, input, inputlen, digest);
 1119         isc_buffer_putmem(buf, digest, 8);
 1120         break;
 1121     }
 1122     case ns_cookiealg_aes: {
 1123         unsigned char input[4 + 4 + 16] ISC_NONSTRING = { 0 };
 1124         isc_netaddr_t netaddr;
 1125         unsigned char *cp;
 1126         unsigned int i;
 1127 
 1128         cp = isc_buffer_used(buf);
 1129         isc_buffer_putmem(buf, client->cookie, 8);
 1130         isc_buffer_putuint32(buf, nonce);
 1131         isc_buffer_putuint32(buf, when);
 1132         memmove(input, cp, 16);
 1133         isc_aes128_crypt(secret, input, digest);
 1134         for (i = 0; i < 8; i++) {
 1135             input[i] = digest[i] ^ digest[i + 8];
 1136         }
 1137         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 1138         switch (netaddr.family) {
 1139         case AF_INET:
 1140             cp = (unsigned char *)&netaddr.type.in;
 1141             memmove(input + 8, cp, 4);
 1142             memset(input + 12, 0, 4);
 1143             isc_aes128_crypt(secret, input, digest);
 1144             break;
 1145         case AF_INET6:
 1146             cp = (unsigned char *)&netaddr.type.in6;
 1147             memmove(input + 8, cp, 16);
 1148             isc_aes128_crypt(secret, input, digest);
 1149             for (i = 0; i < 8; i++) {
 1150                 input[i + 8] = digest[i] ^ digest[i + 8];
 1151             }
 1152             isc_aes128_crypt(client->sctx->secret, input + 8,
 1153                      digest);
 1154             break;
 1155         default:
 1156             INSIST(0);
 1157             ISC_UNREACHABLE();
 1158         }
 1159         for (i = 0; i < 8; i++) {
 1160             digest[i] ^= digest[i + 8];
 1161         }
 1162         isc_buffer_putmem(buf, digest, 8);
 1163         break;
 1164     }
 1165 
 1166     default:
 1167         INSIST(0);
 1168         ISC_UNREACHABLE();
 1169     }
 1170 }
 1171 
 1172 static void
 1173 process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
 1174     ns_altsecret_t *altsecret;
 1175     unsigned char dbuf[COOKIE_SIZE];
 1176     unsigned char *old;
 1177     isc_stdtime_t now;
 1178     uint32_t when;
 1179     uint32_t nonce;
 1180     isc_buffer_t db;
 1181 
 1182     /*
 1183      * If we have already seen a cookie option skip this cookie option.
 1184      */
 1185     if ((!client->sctx->answercookie) ||
 1186         (client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
 1187     {
 1188         isc_buffer_forward(buf, (unsigned int)optlen);
 1189         return;
 1190     }
 1191 
 1192     client->attributes |= NS_CLIENTATTR_WANTCOOKIE;
 1193 
 1194     ns_stats_increment(client->sctx->nsstats, ns_statscounter_cookiein);
 1195 
 1196     if (optlen != COOKIE_SIZE) {
 1197         /*
 1198          * Not our token.
 1199          */
 1200         INSIST(optlen >= 8U);
 1201         memmove(client->cookie, isc_buffer_current(buf), 8);
 1202         isc_buffer_forward(buf, (unsigned int)optlen);
 1203 
 1204         if (optlen == 8U) {
 1205             ns_stats_increment(client->sctx->nsstats,
 1206                        ns_statscounter_cookienew);
 1207         } else {
 1208             ns_stats_increment(client->sctx->nsstats,
 1209                        ns_statscounter_cookiebadsize);
 1210         }
 1211         return;
 1212     }
 1213 
 1214     /*
 1215      * Process all of the incoming buffer.
 1216      */
 1217     old = isc_buffer_current(buf);
 1218     memmove(client->cookie, old, 8);
 1219     isc_buffer_forward(buf, 8);
 1220     nonce = isc_buffer_getuint32(buf);
 1221     when = isc_buffer_getuint32(buf);
 1222     isc_buffer_forward(buf, 8);
 1223 
 1224     /*
 1225      * Allow for a 5 minute clock skew between servers sharing a secret.
 1226      * Only accept COOKIE if we have talked to the client in the last hour.
 1227      */
 1228     isc_stdtime_get(&now);
 1229     if (isc_serial_gt(when, (now + 300)) || /* In the future. */
 1230         isc_serial_lt(when, (now - 3600)))
 1231     { /* In the past. */
 1232         ns_stats_increment(client->sctx->nsstats,
 1233                    ns_statscounter_cookiebadtime);
 1234         return;
 1235     }
 1236 
 1237     isc_buffer_init(&db, dbuf, sizeof(dbuf));
 1238     compute_cookie(client, when, nonce, client->sctx->secret, &db);
 1239 
 1240     if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
 1241         ns_stats_increment(client->sctx->nsstats,
 1242                    ns_statscounter_cookiematch);
 1243         client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
 1244         return;
 1245     }
 1246 
 1247     for (altsecret = ISC_LIST_HEAD(client->sctx->altsecrets);
 1248          altsecret != NULL; altsecret = ISC_LIST_NEXT(altsecret, link))
 1249     {
 1250         isc_buffer_init(&db, dbuf, sizeof(dbuf));
 1251         compute_cookie(client, when, nonce, altsecret->secret, &db);
 1252         if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
 1253             ns_stats_increment(client->sctx->nsstats,
 1254                        ns_statscounter_cookiematch);
 1255             client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
 1256             return;
 1257         }
 1258     }
 1259 
 1260     ns_stats_increment(client->sctx->nsstats,
 1261                ns_statscounter_cookienomatch);
 1262 }
 1263 
 1264 static isc_result_t
 1265 process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
 1266     uint16_t family;
 1267     uint8_t addrlen, addrbytes, scope, *paddr;
 1268     isc_netaddr_t caddr;
 1269 
 1270     /*
 1271      * If we have already seen a ECS option skip this ECS option.
 1272      */
 1273     if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
 1274         isc_buffer_forward(buf, (unsigned int)optlen);
 1275         return (ISC_R_SUCCESS);
 1276     }
 1277 
 1278     /*
 1279      * XXXMUKS: Is there any need to repeat these checks here
 1280      * (except query's scope length) when they are done in the OPT
 1281      * RDATA fromwire code?
 1282      */
 1283 
 1284     if (optlen < 4U) {
 1285         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1286                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1287                   "EDNS client-subnet option too short");
 1288         return (DNS_R_FORMERR);
 1289     }
 1290 
 1291     family = isc_buffer_getuint16(buf);
 1292     addrlen = isc_buffer_getuint8(buf);
 1293     scope = isc_buffer_getuint8(buf);
 1294     optlen -= 4;
 1295 
 1296     if (scope != 0U) {
 1297         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1298                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1299                   "EDNS client-subnet option: invalid scope");
 1300         return (DNS_R_OPTERR);
 1301     }
 1302 
 1303     memset(&caddr, 0, sizeof(caddr));
 1304     switch (family) {
 1305     case 0:
 1306         /*
 1307          * XXXMUKS: In queries, if FAMILY is set to 0, SOURCE
 1308          * PREFIX-LENGTH must be 0 and ADDRESS should not be
 1309          * present as the address and prefix lengths don't make
 1310          * sense because the family is unknown.
 1311          */
 1312         if (addrlen != 0U) {
 1313             ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1314                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1315                       "EDNS client-subnet option: invalid "
 1316                       "address length (%u) for FAMILY=0",
 1317                       addrlen);
 1318             return (DNS_R_OPTERR);
 1319         }
 1320         caddr.family = AF_UNSPEC;
 1321         break;
 1322     case 1:
 1323         if (addrlen > 32U) {
 1324             ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1325                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1326                       "EDNS client-subnet option: invalid "
 1327                       "address length (%u) for IPv4",
 1328                       addrlen);
 1329             return (DNS_R_OPTERR);
 1330         }
 1331         caddr.family = AF_INET;
 1332         break;
 1333     case 2:
 1334         if (addrlen > 128U) {
 1335             ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1336                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1337                       "EDNS client-subnet option: invalid "
 1338                       "address length (%u) for IPv6",
 1339                       addrlen);
 1340             return (DNS_R_OPTERR);
 1341         }
 1342         caddr.family = AF_INET6;
 1343         break;
 1344     default:
 1345         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1346                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1347                   "EDNS client-subnet option: invalid family");
 1348         return (DNS_R_OPTERR);
 1349     }
 1350 
 1351     addrbytes = (addrlen + 7) / 8;
 1352     if (isc_buffer_remaininglength(buf) < addrbytes) {
 1353         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1354                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
 1355                   "EDNS client-subnet option: address too short");
 1356         return (DNS_R_OPTERR);
 1357     }
 1358 
 1359     paddr = (uint8_t *)&caddr.type;
 1360     if (addrbytes != 0U) {
 1361         memmove(paddr, isc_buffer_current(buf), addrbytes);
 1362         isc_buffer_forward(buf, addrbytes);
 1363         optlen -= addrbytes;
 1364 
 1365         if ((addrlen % 8) != 0) {
 1366             uint8_t bits = ~0U << (8 - (addrlen % 8));
 1367             bits &= paddr[addrbytes - 1];
 1368             if (bits != paddr[addrbytes - 1]) {
 1369                 return (DNS_R_OPTERR);
 1370             }
 1371         }
 1372     }
 1373 
 1374     memmove(&client->ecs.addr, &caddr, sizeof(caddr));
 1375     client->ecs.source = addrlen;
 1376     client->ecs.scope = 0;
 1377     client->attributes |= NS_CLIENTATTR_HAVEECS;
 1378 
 1379     isc_buffer_forward(buf, (unsigned int)optlen);
 1380     return (ISC_R_SUCCESS);
 1381 }
 1382 
 1383 static isc_result_t
 1384 process_keytag(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
 1385     if (optlen == 0 || (optlen % 2) != 0) {
 1386         isc_buffer_forward(buf, (unsigned int)optlen);
 1387         return (DNS_R_OPTERR);
 1388     }
 1389 
 1390     /* Silently drop additional keytag options. */
 1391     if (client->keytag != NULL) {
 1392         isc_buffer_forward(buf, (unsigned int)optlen);
 1393         return (ISC_R_SUCCESS);
 1394     }
 1395 
 1396     client->keytag = isc_mem_get(client->mctx, optlen);
 1397     {
 1398         client->keytag_len = (uint16_t)optlen;
 1399         memmove(client->keytag, isc_buffer_current(buf), optlen);
 1400     }
 1401     isc_buffer_forward(buf, (unsigned int)optlen);
 1402     return (ISC_R_SUCCESS);
 1403 }
 1404 
 1405 static isc_result_t
 1406 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
 1407     dns_rdata_t rdata;
 1408     isc_buffer_t optbuf;
 1409     isc_result_t result;
 1410     uint16_t optcode;
 1411     uint16_t optlen;
 1412 
 1413     /*
 1414      * Set the client's UDP buffer size.
 1415      */
 1416     client->udpsize = opt->rdclass;
 1417 
 1418     /*
 1419      * If the requested UDP buffer size is less than 512,
 1420      * ignore it and use 512.
 1421      */
 1422     if (client->udpsize < 512) {
 1423         client->udpsize = 512;
 1424     }
 1425 
 1426     /*
 1427      * Get the flags out of the OPT record.
 1428      */
 1429     client->extflags = (uint16_t)(opt->ttl & 0xFFFF);
 1430 
 1431     /*
 1432      * Do we understand this version of EDNS?
 1433      *
 1434      * XXXRTH need library support for this!
 1435      */
 1436     client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
 1437     if (client->ednsversion > DNS_EDNS_VERSION) {
 1438         ns_stats_increment(client->sctx->nsstats,
 1439                    ns_statscounter_badednsver);
 1440         result = ns_client_addopt(client, client->message,
 1441                       &client->opt);
 1442         if (result == ISC_R_SUCCESS) {
 1443             result = DNS_R_BADVERS;
 1444         }
 1445         ns_client_error(client, result);
 1446         return (result);
 1447     }
 1448 
 1449     /* Check for NSID request */
 1450     result = dns_rdataset_first(opt);
 1451     if (result == ISC_R_SUCCESS) {
 1452         dns_rdata_init(&rdata);
 1453         dns_rdataset_current(opt, &rdata);
 1454         isc_buffer_init(&optbuf, rdata.data, rdata.length);
 1455         isc_buffer_add(&optbuf, rdata.length);
 1456         while (isc_buffer_remaininglength(&optbuf) >= 4) {
 1457             optcode = isc_buffer_getuint16(&optbuf);
 1458             optlen = isc_buffer_getuint16(&optbuf);
 1459             switch (optcode) {
 1460             case DNS_OPT_NSID:
 1461                 if (!WANTNSID(client)) {
 1462                     ns_stats_increment(
 1463                         client->sctx->nsstats,
 1464                         ns_statscounter_nsidopt);
 1465                 }
 1466                 client->attributes |= NS_CLIENTATTR_WANTNSID;
 1467                 isc_buffer_forward(&optbuf, optlen);
 1468                 break;
 1469             case DNS_OPT_COOKIE:
 1470                 process_cookie(client, &optbuf, optlen);
 1471                 break;
 1472             case DNS_OPT_EXPIRE:
 1473                 if (!WANTEXPIRE(client)) {
 1474                     ns_stats_increment(
 1475                         client->sctx->nsstats,
 1476                         ns_statscounter_expireopt);
 1477                 }
 1478                 client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
 1479                 isc_buffer_forward(&optbuf, optlen);
 1480                 break;
 1481             case DNS_OPT_CLIENT_SUBNET:
 1482                 result = process_ecs(client, &optbuf, optlen);
 1483                 if (result != ISC_R_SUCCESS) {
 1484                     ns_client_error(client, result);
 1485                     return (result);
 1486                 }
 1487                 ns_stats_increment(client->sctx->nsstats,
 1488                            ns_statscounter_ecsopt);
 1489                 break;
 1490             case DNS_OPT_TCP_KEEPALIVE:
 1491                 if (!USEKEEPALIVE(client)) {
 1492                     ns_stats_increment(
 1493                         client->sctx->nsstats,
 1494                         ns_statscounter_keepaliveopt);
 1495                 }
 1496                 client->attributes |=
 1497                     NS_CLIENTATTR_USEKEEPALIVE;
 1498                 isc_buffer_forward(&optbuf, optlen);
 1499                 break;
 1500             case DNS_OPT_PAD:
 1501                 client->attributes |= NS_CLIENTATTR_WANTPAD;
 1502                 ns_stats_increment(client->sctx->nsstats,
 1503                            ns_statscounter_padopt);
 1504                 isc_buffer_forward(&optbuf, optlen);
 1505                 break;
 1506             case DNS_OPT_KEY_TAG:
 1507                 result = process_keytag(client, &optbuf,
 1508                             optlen);
 1509                 if (result != ISC_R_SUCCESS) {
 1510                     ns_client_error(client, result);
 1511                     return (result);
 1512                 }
 1513                 ns_stats_increment(client->sctx->nsstats,
 1514                            ns_statscounter_keytagopt);
 1515                 break;
 1516             default:
 1517                 ns_stats_increment(client->sctx->nsstats,
 1518                            ns_statscounter_otheropt);
 1519                 isc_buffer_forward(&optbuf, optlen);
 1520                 break;
 1521             }
 1522         }
 1523     }
 1524 
 1525     ns_stats_increment(client->sctx->nsstats, ns_statscounter_edns0in);
 1526     client->attributes |= NS_CLIENTATTR_WANTOPT;
 1527 
 1528     return (result);
 1529 }
 1530 
 1531 void
 1532 ns__client_reset_cb(void *client0) {
 1533     ns_client_t *client = client0;
 1534 
 1535     ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
 1536               ISC_LOG_DEBUG(3), "reset client");
 1537 
 1538     /*
 1539      * We never started processing this client, possible if we're
 1540      * shutting down, just exit.
 1541      */
 1542     if (client->state == NS_CLIENTSTATE_READY) {
 1543         return;
 1544     }
 1545 
 1546     ns_client_endrequest(client);
 1547     if (client->tcpbuf != NULL) {
 1548         isc_mem_put(client->mctx, client->tcpbuf,
 1549                 NS_CLIENT_TCP_BUFFER_SIZE);
 1550     }
 1551 
 1552     if (client->keytag != NULL) {
 1553         isc_mem_put(client->mctx, client->keytag, client->keytag_len);
 1554         client->keytag_len = 0;
 1555     }
 1556 
 1557     client->state = NS_CLIENTSTATE_READY;
 1558     INSIST(client->recursionquota == NULL);
 1559 }
 1560 
 1561 void
 1562 ns__client_put_cb(void *client0) {
 1563     ns_client_t *client = client0;
 1564 
 1565     ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
 1566               ISC_LOG_DEBUG(3), "freeing client");
 1567 
 1568     /*
 1569      * Call this first because it requires a valid client.
 1570      */
 1571     ns_query_free(client);
 1572 
 1573     client->magic = 0;
 1574     client->shuttingdown = true;
 1575 
 1576     if (client->manager != NULL) {
 1577         clientmgr_detach(&client->manager);
 1578     }
 1579 
 1580     isc_mem_put(client->mctx, client->sendbuf, NS_CLIENT_SEND_BUFFER_SIZE);
 1581     if (client->opt != NULL) {
 1582         INSIST(dns_rdataset_isassociated(client->opt));
 1583         dns_rdataset_disassociate(client->opt);
 1584         dns_message_puttemprdataset(client->message, &client->opt);
 1585     }
 1586 
 1587     dns_message_destroy(&client->message);
 1588 
 1589     /*
 1590      * Detaching the task must be done after unlinking from
 1591      * the manager's lists because the manager accesses
 1592      * client->task.
 1593      */
 1594     if (client->task != NULL) {
 1595         isc_task_detach(&client->task);
 1596     }
 1597 
 1598     /*
 1599      * Destroy the fetchlock mutex that was created in
 1600      * ns_query_init().
 1601      */
 1602     isc_mutex_destroy(&client->query.fetchlock);
 1603 
 1604     if (client->sctx != NULL) {
 1605         ns_server_detach(&client->sctx);
 1606     }
 1607 
 1608     if (client->mctx != NULL) {
 1609         isc_mem_detach(&client->mctx);
 1610     }
 1611 }
 1612 
 1613 /*
 1614  * Handle an incoming request event from the socket (UDP case)
 1615  * or tcpmsg (TCP case).
 1616  */
 1617 void
 1618 ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
 1619     ns_client_t *client;
 1620     ns_clientmgr_t *mgr;
 1621     ns_interface_t *ifp;
 1622     isc_result_t result;
 1623     isc_result_t sigresult = ISC_R_SUCCESS;
 1624     isc_buffer_t *buffer;
 1625     isc_buffer_t tbuffer;
 1626     dns_rdataset_t *opt;
 1627     const dns_name_t *signame;
 1628     bool ra; /* Recursion available. */
 1629     isc_netaddr_t netaddr;
 1630     int match;
 1631     dns_messageid_t id;
 1632     unsigned int flags;
 1633     bool notimp;
 1634     size_t reqsize;
 1635     dns_aclenv_t *env;
 1636 #ifdef HAVE_DNSTAP
 1637     dns_dtmsgtype_t dtmsgtype;
 1638 #endif /* ifdef HAVE_DNSTAP */
 1639     ifp = (ns_interface_t *)arg;
 1640 
 1641     mgr = ifp->clientmgr;
 1642     if (mgr == NULL) {
 1643         /* The interface was shut down in the meantime, just bail */
 1644         return;
 1645     }
 1646 
 1647     REQUIRE(VALID_MANAGER(mgr));
 1648 
 1649     client = isc_nmhandle_getdata(handle);
 1650     if (client == NULL) {
 1651         client = isc_nmhandle_getextra(handle);
 1652 
 1653         result = ns__client_setup(client, mgr, true);
 1654         if (result != ISC_R_SUCCESS) {
 1655             return;
 1656         }
 1657 
 1658         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 1659                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 1660                   "allocate new client");
 1661     } else {
 1662         result = ns__client_setup(client, NULL, false);
 1663         if (result != ISC_R_SUCCESS) {
 1664             return;
 1665         }
 1666     }
 1667 
 1668     client->state = NS_CLIENTSTATE_READY;
 1669 
 1670     isc_task_pause(client->task);
 1671     if (client->handle == NULL) {
 1672         isc_nmhandle_setdata(handle, client, ns__client_reset_cb,
 1673                      ns__client_put_cb);
 1674         client->handle = handle;
 1675     }
 1676     if (isc_nmhandle_is_stream(handle)) {
 1677         client->attributes |= NS_CLIENTATTR_TCP;
 1678     }
 1679 
 1680     INSIST(client->recursionquota == NULL);
 1681 
 1682     INSIST(client->state == NS_CLIENTSTATE_READY);
 1683 
 1684     (void)atomic_fetch_add_relaxed(&ns_client_requests, 1);
 1685 
 1686     isc_buffer_init(&tbuffer, region->base, region->length);
 1687     isc_buffer_add(&tbuffer, region->length);
 1688     buffer = &tbuffer;
 1689 
 1690     client->peeraddr = isc_nmhandle_peeraddr(client->handle);
 1691 
 1692     client->peeraddr_valid = true;
 1693 
 1694     reqsize = isc_buffer_usedlength(buffer);
 1695 
 1696     client->state = NS_CLIENTSTATE_WORKING;
 1697 
 1698     TIME_NOW(&client->requesttime);
 1699     client->tnow = client->requesttime;
 1700     client->now = isc_time_seconds(&client->tnow);
 1701 
 1702     isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 1703 
 1704 #if NS_CLIENT_DROPPORT
 1705     if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
 1706         DROPPORT_REQUEST)
 1707     {
 1708         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 1709                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
 1710                   "dropped request: suspicious port");
 1711         isc_task_unpause(client->task);
 1712         return;
 1713     }
 1714 #endif /* if NS_CLIENT_DROPPORT */
 1715 
 1716     env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
 1717     if (client->sctx->blackholeacl != NULL &&
 1718         (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
 1719                &match, NULL) == ISC_R_SUCCESS) &&
 1720         match > 0)
 1721     {
 1722         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 1723                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
 1724                   "dropped request: blackholed peer");
 1725         isc_task_unpause(client->task);
 1726         return;
 1727     }
 1728 
 1729     ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
 1730               ISC_LOG_DEBUG(3), "%s request",
 1731               TCP_CLIENT(client) ? "TCP" : "UDP");
 1732 
 1733     result = dns_message_peekheader(buffer, &id, &flags);
 1734     if (result != ISC_R_SUCCESS) {
 1735         /*
 1736          * There isn't enough header to determine whether
 1737          * this was a request or a response.  Drop it.
 1738          */
 1739         isc_task_unpause(client->task);
 1740         return;
 1741     }
 1742 
 1743     /*
 1744      * The client object handles requests, not responses.
 1745      * If this is a UDP response, forward it to the dispatcher.
 1746      * If it's a TCP response, discard it here.
 1747      */
 1748     if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
 1749         CTRACE("unexpected response");
 1750         isc_task_unpause(client->task);
 1751         return;
 1752     }
 1753 
 1754     /*
 1755      * Update some statistics counters.  Don't count responses.
 1756      */
 1757     if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
 1758         ns_stats_increment(client->sctx->nsstats,
 1759                    ns_statscounter_requestv4);
 1760     } else {
 1761         ns_stats_increment(client->sctx->nsstats,
 1762                    ns_statscounter_requestv6);
 1763     }
 1764     if (TCP_CLIENT(client)) {
 1765         ns_stats_increment(client->sctx->nsstats,
 1766                    ns_statscounter_requesttcp);
 1767         switch (isc_sockaddr_pf(&client->peeraddr)) {
 1768         case AF_INET:
 1769             isc_stats_increment(client->sctx->tcpinstats4,
 1770                         ISC_MIN((int)reqsize / 16, 18));
 1771             break;
 1772         case AF_INET6:
 1773             isc_stats_increment(client->sctx->tcpinstats6,
 1774                         ISC_MIN((int)reqsize / 16, 18));
 1775             break;
 1776         default:
 1777             INSIST(0);
 1778             ISC_UNREACHABLE();
 1779         }
 1780     } else {
 1781         switch (isc_sockaddr_pf(&client->peeraddr)) {
 1782         case AF_INET:
 1783             isc_stats_increment(client->sctx->udpinstats4,
 1784                         ISC_MIN((int)reqsize / 16, 18));
 1785             break;
 1786         case AF_INET6:
 1787             isc_stats_increment(client->sctx->udpinstats6,
 1788                         ISC_MIN((int)reqsize / 16, 18));
 1789             break;
 1790         default:
 1791             INSIST(0);
 1792             ISC_UNREACHABLE();
 1793         }
 1794     }
 1795 
 1796     /*
 1797      * It's a request.  Parse it.
 1798      */
 1799     result = dns_message_parse(client->message, buffer, 0);
 1800     if (result != ISC_R_SUCCESS) {
 1801         /*
 1802          * Parsing the request failed.  Send a response
 1803          * (typically FORMERR or SERVFAIL).
 1804          */
 1805         if (result == DNS_R_OPTERR) {
 1806             (void)ns_client_addopt(client, client->message,
 1807                            &client->opt);
 1808         }
 1809 
 1810         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1811                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
 1812                   "message parsing failed: %s",
 1813                   isc_result_totext(result));
 1814         if (result == ISC_R_NOSPACE || result == DNS_R_BADTSIG) {
 1815             result = DNS_R_FORMERR;
 1816         }
 1817         ns_client_error(client, result);
 1818         isc_task_unpause(client->task);
 1819         return;
 1820     }
 1821 
 1822     /*
 1823      * Disable pipelined TCP query processing if necessary.
 1824      */
 1825     if (TCP_CLIENT(client) &&
 1826         (client->message->opcode != dns_opcode_query ||
 1827          (client->sctx->keepresporder != NULL &&
 1828           dns_acl_allowed(&netaddr, NULL, client->sctx->keepresporder,
 1829                   env))))
 1830     {
 1831         isc_nm_tcpdns_sequential(handle);
 1832     }
 1833 
 1834     dns_opcodestats_increment(client->sctx->opcodestats,
 1835                   client->message->opcode);
 1836     switch (client->message->opcode) {
 1837     case dns_opcode_query:
 1838     case dns_opcode_update:
 1839     case dns_opcode_notify:
 1840         notimp = false;
 1841         break;
 1842     case dns_opcode_iquery:
 1843     default:
 1844         notimp = true;
 1845         break;
 1846     }
 1847 
 1848     client->message->rcode = dns_rcode_noerror;
 1849 
 1850     /*
 1851      * Deal with EDNS.
 1852      */
 1853     if ((client->sctx->options & NS_SERVER_NOEDNS) != 0) {
 1854         opt = NULL;
 1855     } else {
 1856         opt = dns_message_getopt(client->message);
 1857     }
 1858 
 1859     client->ecs.source = 0;
 1860     client->ecs.scope = 0;
 1861 
 1862     if (opt != NULL) {
 1863         /*
 1864          * Are returning FORMERR to all EDNS queries?
 1865          * Simulate a STD13 compliant server.
 1866          */
 1867         if ((client->sctx->options & NS_SERVER_EDNSFORMERR) != 0) {
 1868             ns_client_error(client, DNS_R_FORMERR);
 1869             isc_task_unpause(client->task);
 1870             return;
 1871         }
 1872 
 1873         /*
 1874          * Are returning NOTIMP to all EDNS queries?
 1875          */
 1876         if ((client->sctx->options & NS_SERVER_EDNSNOTIMP) != 0) {
 1877             ns_client_error(client, DNS_R_NOTIMP);
 1878             isc_task_unpause(client->task);
 1879             return;
 1880         }
 1881 
 1882         /*
 1883          * Are returning REFUSED to all EDNS queries?
 1884          */
 1885         if ((client->sctx->options & NS_SERVER_EDNSREFUSED) != 0) {
 1886             ns_client_error(client, DNS_R_REFUSED);
 1887             isc_task_unpause(client->task);
 1888             return;
 1889         }
 1890 
 1891         /*
 1892          * Are we dropping all EDNS queries?
 1893          */
 1894         if ((client->sctx->options & NS_SERVER_DROPEDNS) != 0) {
 1895             ns_client_drop(client, ISC_R_SUCCESS);
 1896             isc_task_unpause(client->task);
 1897             return;
 1898         }
 1899 
 1900         result = process_opt(client, opt);
 1901         if (result != ISC_R_SUCCESS) {
 1902             isc_task_unpause(client->task);
 1903             return;
 1904         }
 1905     }
 1906 
 1907     if (client->message->rdclass == 0) {
 1908         if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
 1909             client->message->opcode == dns_opcode_query &&
 1910             client->message->counts[DNS_SECTION_QUESTION] == 0U)
 1911         {
 1912             result = dns_message_reply(client->message, true);
 1913             if (result != ISC_R_SUCCESS) {
 1914                 ns_client_error(client, result);
 1915                 isc_task_unpause(client->task);
 1916                 return;
 1917             }
 1918 
 1919             if (notimp) {
 1920                 client->message->rcode = dns_rcode_notimp;
 1921             }
 1922 
 1923             ns_client_send(client);
 1924             isc_task_unpause(client->task);
 1925             return;
 1926         }
 1927 
 1928         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1929                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
 1930                   "message class could not be determined");
 1931         ns_client_dumpmessage(client, "message class could not be "
 1932                           "determined");
 1933         ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
 1934         isc_task_unpause(client->task);
 1935         return;
 1936     }
 1937 
 1938     /*
 1939      * Determine the destination address.  If the receiving interface is
 1940      * bound to a specific address, we simply use it regardless of the
 1941      * address family.  All IPv4 queries should fall into this case.
 1942      * Otherwise, if this is a TCP query, get the address from the
 1943      * receiving socket (this needs a system call and can be heavy).
 1944      * For IPv6 UDP queries, we get this from the pktinfo structure (if
 1945      * supported).
 1946      *
 1947      * If all the attempts fail (this can happen due to memory shortage,
 1948      * etc), we regard this as an error for safety.
 1949      */
 1950     if ((client->manager->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
 1951     {
 1952         isc_netaddr_fromsockaddr(&client->destaddr,
 1953                      &client->manager->interface->addr);
 1954     } else {
 1955         isc_sockaddr_t sockaddr =
 1956             isc_nmhandle_localaddr(client->handle);
 1957         isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
 1958     }
 1959 
 1960     isc_sockaddr_fromnetaddr(&client->destsockaddr, &client->destaddr, 0);
 1961 
 1962     result = client->sctx->matchingview(&netaddr, &client->destaddr,
 1963                         client->message, env, &sigresult,
 1964                         &client->view);
 1965     if (result != ISC_R_SUCCESS) {
 1966         char classname[DNS_RDATACLASS_FORMATSIZE];
 1967 
 1968         /*
 1969          * Do a dummy TSIG verification attempt so that the
 1970          * response will have a TSIG if the query did, as
 1971          * required by RFC2845.
 1972          */
 1973         isc_buffer_t b;
 1974         isc_region_t *r;
 1975 
 1976         dns_message_resetsig(client->message);
 1977 
 1978         r = dns_message_getrawmessage(client->message);
 1979         isc_buffer_init(&b, r->base, r->length);
 1980         isc_buffer_add(&b, r->length);
 1981         (void)dns_tsig_verify(&b, client->message, NULL, NULL);
 1982 
 1983         dns_rdataclass_format(client->message->rdclass, classname,
 1984                       sizeof(classname));
 1985         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 1986                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
 1987                   "no matching view in class '%s'", classname);
 1988         ns_client_dumpmessage(client, "no matching view in class");
 1989         ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
 1990         isc_task_unpause(client->task);
 1991         return;
 1992     }
 1993 
 1994     ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
 1995               ISC_LOG_DEBUG(5), "using view '%s'", client->view->name);
 1996 
 1997     /*
 1998      * Check for a signature.  We log bad signatures regardless of
 1999      * whether they ultimately cause the request to be rejected or
 2000      * not.  We do not log the lack of a signature unless we are
 2001      * debugging.
 2002      */
 2003     client->signer = NULL;
 2004     dns_name_init(&client->signername, NULL);
 2005     result = dns_message_signer(client->message, &client->signername);
 2006     if (result != ISC_R_NOTFOUND) {
 2007         signame = NULL;
 2008         if (dns_message_gettsig(client->message, &signame) != NULL) {
 2009             ns_stats_increment(client->sctx->nsstats,
 2010                        ns_statscounter_tsigin);
 2011         } else {
 2012             ns_stats_increment(client->sctx->nsstats,
 2013                        ns_statscounter_sig0in);
 2014         }
 2015     }
 2016     if (result == ISC_R_SUCCESS) {
 2017         char namebuf[DNS_NAME_FORMATSIZE];
 2018         dns_name_format(&client->signername, namebuf, sizeof(namebuf));
 2019         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2020                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 2021                   "request has valid signature: %s", namebuf);
 2022         client->signer = &client->signername;
 2023     } else if (result == ISC_R_NOTFOUND) {
 2024         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2025                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 2026                   "request is not signed");
 2027     } else if (result == DNS_R_NOIDENTITY) {
 2028         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2029                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 2030                   "request is signed by a nonauthoritative key");
 2031     } else {
 2032         char tsigrcode[64];
 2033         isc_buffer_t b;
 2034         dns_rcode_t status;
 2035         isc_result_t tresult;
 2036 
 2037         /* There is a signature, but it is bad. */
 2038         ns_stats_increment(client->sctx->nsstats,
 2039                    ns_statscounter_invalidsig);
 2040         signame = NULL;
 2041         if (dns_message_gettsig(client->message, &signame) != NULL) {
 2042             char namebuf[DNS_NAME_FORMATSIZE];
 2043             char cnamebuf[DNS_NAME_FORMATSIZE];
 2044             dns_name_format(signame, namebuf, sizeof(namebuf));
 2045             status = client->message->tsigstatus;
 2046             isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
 2047             tresult = dns_tsigrcode_totext(status, &b);
 2048             INSIST(tresult == ISC_R_SUCCESS);
 2049             tsigrcode[isc_buffer_usedlength(&b)] = '\0';
 2050             if (client->message->tsigkey->generated) {
 2051                 dns_name_format(
 2052                     client->message->tsigkey->creator,
 2053                     cnamebuf, sizeof(cnamebuf));
 2054                 ns_client_log(
 2055                     client, DNS_LOGCATEGORY_SECURITY,
 2056                     NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
 2057                     "request has invalid signature: "
 2058                     "TSIG %s (%s): %s (%s)",
 2059                     namebuf, cnamebuf,
 2060                     isc_result_totext(result), tsigrcode);
 2061             } else {
 2062                 ns_client_log(
 2063                     client, DNS_LOGCATEGORY_SECURITY,
 2064                     NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
 2065                     "request has invalid signature: "
 2066                     "TSIG %s: %s (%s)",
 2067                     namebuf, isc_result_totext(result),
 2068                     tsigrcode);
 2069             }
 2070         } else {
 2071             status = client->message->sig0status;
 2072             isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
 2073             tresult = dns_tsigrcode_totext(status, &b);
 2074             INSIST(tresult == ISC_R_SUCCESS);
 2075             tsigrcode[isc_buffer_usedlength(&b)] = '\0';
 2076             ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2077                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
 2078                       "request has invalid signature: %s (%s)",
 2079                       isc_result_totext(result), tsigrcode);
 2080         }
 2081 
 2082         /*
 2083          * Accept update messages signed by unknown keys so that
 2084          * update forwarding works transparently through slaves
 2085          * that don't have all the same keys as the master.
 2086          */
 2087         if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
 2088               client->message->opcode == dns_opcode_update))
 2089         {
 2090             ns_client_error(client, sigresult);
 2091             isc_task_unpause(client->task);
 2092             return;
 2093         }
 2094     }
 2095 
 2096     /*
 2097      * Decide whether recursive service is available to this client.
 2098      * We do this here rather than in the query code so that we can
 2099      * set the RA bit correctly on all kinds of responses, not just
 2100      * responses to ordinary queries.  Note if you can't query the
 2101      * cache there is no point in setting RA.
 2102      */
 2103     ra = false;
 2104     if (client->view->resolver != NULL && client->view->recursion &&
 2105         ns_client_checkaclsilent(client, NULL, client->view->recursionacl,
 2106                      true) == ISC_R_SUCCESS &&
 2107         ns_client_checkaclsilent(client, NULL, client->view->cacheacl,
 2108                      true) == ISC_R_SUCCESS &&
 2109         ns_client_checkaclsilent(client, &client->destaddr,
 2110                      client->view->recursiononacl,
 2111                      true) == ISC_R_SUCCESS &&
 2112         ns_client_checkaclsilent(client, &client->destaddr,
 2113                      client->view->cacheonacl,
 2114                      true) == ISC_R_SUCCESS)
 2115     {
 2116         ra = true;
 2117     }
 2118 
 2119     if (ra) {
 2120         client->attributes |= NS_CLIENTATTR_RA;
 2121     }
 2122 
 2123     ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
 2124               ISC_LOG_DEBUG(3),
 2125               ra ? "recursion available" : "recursion not available");
 2126 
 2127     /*
 2128      * Adjust maximum UDP response size for this client.
 2129      */
 2130     if (client->udpsize > 512) {
 2131         dns_peer_t *peer = NULL;
 2132         uint16_t udpsize = client->view->maxudp;
 2133         (void)dns_peerlist_peerbyaddr(client->view->peers, &netaddr,
 2134                           &peer);
 2135         if (peer != NULL) {
 2136             dns_peer_getmaxudp(peer, &udpsize);
 2137         }
 2138         if (client->udpsize > udpsize) {
 2139             client->udpsize = udpsize;
 2140         }
 2141     }
 2142 
 2143     /*
 2144      * Dispatch the request.
 2145      */
 2146     switch (client->message->opcode) {
 2147     case dns_opcode_query:
 2148         CTRACE("query");
 2149 #ifdef HAVE_DNSTAP
 2150         if (ra && (client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
 2151             dtmsgtype = DNS_DTTYPE_CQ;
 2152         } else {
 2153             dtmsgtype = DNS_DTTYPE_AQ;
 2154         }
 2155 
 2156         dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
 2157                 &client->destsockaddr, TCP_CLIENT(client), NULL,
 2158                 &client->requesttime, NULL, buffer);
 2159 #endif /* HAVE_DNSTAP */
 2160 
 2161         isc_nmhandle_ref(client->handle);
 2162         ns_query_start(client);
 2163         break;
 2164     case dns_opcode_update:
 2165         CTRACE("update");
 2166 #ifdef HAVE_DNSTAP
 2167         dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
 2168                 &client->destsockaddr, TCP_CLIENT(client), NULL,
 2169                 &client->requesttime, NULL, buffer);
 2170 #endif /* HAVE_DNSTAP */
 2171         ns_client_settimeout(client, 60);
 2172         isc_nmhandle_ref(client->handle);
 2173         ns_update_start(client, sigresult);
 2174         break;
 2175     case dns_opcode_notify:
 2176         CTRACE("notify");
 2177         ns_client_settimeout(client, 60);
 2178         isc_nmhandle_ref(client->handle);
 2179         ns_notify_start(client);
 2180         break;
 2181     case dns_opcode_iquery:
 2182         CTRACE("iquery");
 2183         ns_client_error(client, DNS_R_NOTIMP);
 2184         break;
 2185     default:
 2186         CTRACE("unknown opcode");
 2187         ns_client_error(client, DNS_R_NOTIMP);
 2188     }
 2189 
 2190     isc_task_unpause(client->task);
 2191 }
 2192 
 2193 isc_result_t
 2194 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
 2195     ns_interface_t *ifp = (ns_interface_t *)arg;
 2196     dns_aclenv_t *env = ns_interfacemgr_getaclenv(ifp->mgr);
 2197     ns_server_t *sctx = ns_interfacemgr_getserver(ifp->mgr);
 2198     unsigned int tcpquota;
 2199     isc_sockaddr_t peeraddr;
 2200     isc_netaddr_t netaddr;
 2201     int match;
 2202 
 2203     UNUSED(result);
 2204 
 2205     if (handle != NULL) {
 2206         peeraddr = isc_nmhandle_peeraddr(handle);
 2207         isc_netaddr_fromsockaddr(&netaddr, &peeraddr);
 2208 
 2209         if (sctx->blackholeacl != NULL &&
 2210             (dns_acl_match(&netaddr, NULL, sctx->blackholeacl, env,
 2211                    &match, NULL) == ISC_R_SUCCESS) &&
 2212             match > 0)
 2213         {
 2214             return (ISC_R_CONNREFUSED);
 2215         }
 2216     }
 2217 
 2218     tcpquota = isc_quota_getused(&sctx->tcpquota);
 2219     ns_stats_update_if_greater(sctx->nsstats, ns_statscounter_tcphighwater,
 2220                    tcpquota);
 2221 
 2222     return (ISC_R_SUCCESS);
 2223 }
 2224 
 2225 static void
 2226 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
 2227     isc_mem_t *clientmctx;
 2228     MTRACE("clientmctx");
 2229 
 2230     int tid = isc_nm_tid();
 2231     if (tid < 0) {
 2232         tid = isc_random_uniform(manager->ncpus);
 2233     }
 2234     int rand = isc_random_uniform(CLIENT_NMCTXS_PERCPU);
 2235     int nextmctx = (rand * manager->ncpus) + tid;
 2236     clientmctx = manager->mctxpool[nextmctx];
 2237 
 2238     isc_mem_attach(clientmctx, mctxp);
 2239 }
 2240 
 2241 static void
 2242 get_clienttask(ns_clientmgr_t *manager, isc_task_t **taskp) {
 2243     MTRACE("clienttask");
 2244 
 2245     int tid = isc_nm_tid();
 2246     if (tid < 0) {
 2247         tid = isc_random_uniform(manager->ncpus);
 2248     }
 2249 
 2250     int rand = isc_random_uniform(CLIENT_NTASKS_PERCPU);
 2251     int nexttask = (rand * manager->ncpus) + tid;
 2252     isc_task_attach(manager->taskpool[nexttask], taskp);
 2253 }
 2254 
 2255 isc_result_t
 2256 ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
 2257     isc_result_t result;
 2258 
 2259     /*
 2260      * Caller must be holding the manager lock.
 2261      *
 2262      * Note: creating a client does not add the client to the
 2263      * manager's client list or set the client's manager pointer.
 2264      * The caller is responsible for that.
 2265      */
 2266 
 2267     REQUIRE(NS_CLIENT_VALID(client) || (new &&client != NULL));
 2268     REQUIRE(VALID_MANAGER(mgr) || !new);
 2269 
 2270     if (new) {
 2271         *client = (ns_client_t){ .magic = 0 };
 2272 
 2273         get_clientmctx(mgr, &client->mctx);
 2274         clientmgr_attach(mgr, &client->manager);
 2275         ns_server_attach(mgr->sctx, &client->sctx);
 2276         get_clienttask(mgr, &client->task);
 2277 
 2278         result = dns_message_create(client->mctx,
 2279                         DNS_MESSAGE_INTENTPARSE,
 2280                         &client->message);
 2281         if (result != ISC_R_SUCCESS) {
 2282             goto cleanup;
 2283         }
 2284 
 2285         client->sendbuf = isc_mem_get(client->mctx,
 2286                           NS_CLIENT_SEND_BUFFER_SIZE);
 2287         /*
 2288          * Set magic earlier than usual because ns_query_init()
 2289          * and the functions it calls will require it.
 2290          */
 2291         client->magic = NS_CLIENT_MAGIC;
 2292         result = ns_query_init(client);
 2293         if (result != ISC_R_SUCCESS) {
 2294             goto cleanup;
 2295         }
 2296     } else {
 2297         ns_clientmgr_t *oldmgr = client->manager;
 2298         ns_server_t *sctx = client->sctx;
 2299         isc_task_t *task = client->task;
 2300         unsigned char *sendbuf = client->sendbuf;
 2301         dns_message_t *message = client->message;
 2302         isc_mem_t *oldmctx = client->mctx;
 2303         ns_query_t query = client->query;
 2304 
 2305         /*
 2306          * Retain these values from the existing client, but
 2307          * zero every thing else.
 2308          */
 2309         *client = (ns_client_t){ .magic = 0,
 2310                      .mctx = oldmctx,
 2311                      .manager = oldmgr,
 2312                      .sctx = sctx,
 2313                      .task = task,
 2314                      .sendbuf = sendbuf,
 2315                      .message = message,
 2316                      .query = query };
 2317     }
 2318 
 2319     client->state = NS_CLIENTSTATE_INACTIVE;
 2320     client->udpsize = 512;
 2321     client->ednsversion = -1;
 2322     dns_name_init(&client->signername, NULL);
 2323     dns_ecs_init(&client->ecs);
 2324     isc_sockaddr_any(&client->formerrcache.addr);
 2325     client->formerrcache.time = 0;
 2326     client->formerrcache.id = 0;
 2327     ISC_LINK_INIT(client, rlink);
 2328     client->rcode_override = -1; /* not set */
 2329 
 2330     client->magic = NS_CLIENT_MAGIC;
 2331 
 2332     CTRACE("client_setup");
 2333 
 2334     return (ISC_R_SUCCESS);
 2335 
 2336 cleanup:
 2337     if (client->sendbuf != NULL) {
 2338         isc_mem_put(client->mctx, client->sendbuf,
 2339                 NS_CLIENT_SEND_BUFFER_SIZE);
 2340     }
 2341 
 2342     if (client->message != NULL) {
 2343         dns_message_destroy(&client->message);
 2344     }
 2345 
 2346     if (client->task != NULL) {
 2347         isc_task_detach(&client->task);
 2348     }
 2349 
 2350     if (client->manager != NULL) {
 2351         clientmgr_detach(&client->manager);
 2352     }
 2353     if (client->mctx != NULL) {
 2354         isc_mem_detach(&client->mctx);
 2355     }
 2356     if (client->sctx != NULL) {
 2357         ns_server_detach(&client->sctx);
 2358     }
 2359 
 2360     return (result);
 2361 }
 2362 
 2363 bool
 2364 ns_client_shuttingdown(ns_client_t *client) {
 2365     return (client->shuttingdown);
 2366 }
 2367 
 2368 /***
 2369  *** Client Manager
 2370  ***/
 2371 
 2372 static void
 2373 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp) {
 2374     int32_t oldrefs;
 2375 
 2376     REQUIRE(VALID_MANAGER(source));
 2377     REQUIRE(targetp != NULL && *targetp == NULL);
 2378 
 2379     oldrefs = isc_refcount_increment0(&source->references);
 2380     isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
 2381               ISC_LOG_DEBUG(3), "clientmgr @%p attach: %d", source,
 2382               oldrefs + 1);
 2383 
 2384     *targetp = source;
 2385 }
 2386 
 2387 static void
 2388 clientmgr_detach(ns_clientmgr_t **mp) {
 2389     int32_t oldrefs;
 2390     ns_clientmgr_t *mgr = *mp;
 2391     *mp = NULL;
 2392 
 2393     oldrefs = isc_refcount_decrement(&mgr->references);
 2394     isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
 2395               ISC_LOG_DEBUG(3), "clientmgr @%p detach: %d", mgr,
 2396               oldrefs - 1);
 2397     if (oldrefs == 1) {
 2398         clientmgr_destroy(mgr);
 2399     }
 2400 }
 2401 
 2402 static void
 2403 clientmgr_destroy(ns_clientmgr_t *manager) {
 2404     int i;
 2405 
 2406     MTRACE("clientmgr_destroy");
 2407 
 2408     isc_refcount_destroy(&manager->references);
 2409     manager->magic = 0;
 2410 
 2411     for (i = 0; i < manager->ncpus * CLIENT_NMCTXS_PERCPU; i++) {
 2412         isc_mem_detach(&manager->mctxpool[i]);
 2413     }
 2414     isc_mem_put(manager->mctx, manager->mctxpool,
 2415             manager->ncpus * CLIENT_NMCTXS_PERCPU *
 2416                 sizeof(isc_mem_t *));
 2417 
 2418     if (manager->interface != NULL) {
 2419         ns_interface_detach(&manager->interface);
 2420     }
 2421 
 2422     isc_mutex_destroy(&manager->lock);
 2423     isc_mutex_destroy(&manager->reclock);
 2424 
 2425     if (manager->excl != NULL) {
 2426         isc_task_detach(&manager->excl);
 2427     }
 2428 
 2429     for (i = 0; i < manager->ncpus * CLIENT_NTASKS_PERCPU; i++) {
 2430         if (manager->taskpool[i] != NULL) {
 2431             isc_task_detach(&manager->taskpool[i]);
 2432         }
 2433     }
 2434     isc_mem_put(manager->mctx, manager->taskpool,
 2435             manager->ncpus * CLIENT_NTASKS_PERCPU *
 2436                 sizeof(isc_task_t *));
 2437     ns_server_detach(&manager->sctx);
 2438 
 2439     isc_mem_put(manager->mctx, manager, sizeof(*manager));
 2440 }
 2441 
 2442 isc_result_t
 2443 ns_clientmgr_create(isc_mem_t *mctx, ns_server_t *sctx, isc_taskmgr_t *taskmgr,
 2444             isc_timermgr_t *timermgr, ns_interface_t *interface,
 2445             int ncpus, ns_clientmgr_t **managerp) {
 2446     ns_clientmgr_t *manager;
 2447     isc_result_t result;
 2448     int i;
 2449     int npools;
 2450 
 2451     manager = isc_mem_get(mctx, sizeof(*manager));
 2452     *manager = (ns_clientmgr_t){ .magic = 0 };
 2453 
 2454     isc_mutex_init(&manager->lock);
 2455     isc_mutex_init(&manager->reclock);
 2456 
 2457     manager->excl = NULL;
 2458     result = isc_taskmgr_excltask(taskmgr, &manager->excl);
 2459     if (result != ISC_R_SUCCESS) {
 2460         goto cleanup_reclock;
 2461     }
 2462 
 2463     manager->mctx = mctx;
 2464     manager->taskmgr = taskmgr;
 2465     manager->timermgr = timermgr;
 2466     manager->ncpus = ncpus;
 2467 
 2468     ns_interface_attach(interface, &manager->interface);
 2469 
 2470     manager->exiting = false;
 2471     int ntasks = CLIENT_NTASKS_PERCPU * manager->ncpus;
 2472     manager->taskpool = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
 2473     for (i = 0; i < ntasks; i++) {
 2474         manager->taskpool[i] = NULL;
 2475         result = isc_task_create_bound(manager->taskmgr, 20,
 2476                            &manager->taskpool[i],
 2477                            i % CLIENT_NTASKS_PERCPU);
 2478         RUNTIME_CHECK(result == ISC_R_SUCCESS);
 2479     }
 2480     isc_refcount_init(&manager->references, 1);
 2481     manager->sctx = NULL;
 2482     ns_server_attach(sctx, &manager->sctx);
 2483 
 2484     ISC_LIST_INIT(manager->recursing);
 2485 
 2486     npools = CLIENT_NMCTXS_PERCPU * manager->ncpus;
 2487     manager->mctxpool = isc_mem_get(manager->mctx,
 2488                     npools * sizeof(isc_mem_t *));
 2489     for (i = 0; i < npools; i++) {
 2490         manager->mctxpool[i] = NULL;
 2491         isc_mem_create(&manager->mctxpool[i]);
 2492         isc_mem_setname(manager->mctxpool[i], "client", NULL);
 2493     }
 2494 
 2495     manager->magic = MANAGER_MAGIC;
 2496 
 2497     MTRACE("create");
 2498 
 2499     *managerp = manager;
 2500 
 2501     return (ISC_R_SUCCESS);
 2502 
 2503 cleanup_reclock:
 2504     isc_mutex_destroy(&manager->reclock);
 2505     isc_mutex_destroy(&manager->lock);
 2506 
 2507     isc_mem_put(manager->mctx, manager, sizeof(*manager));
 2508 
 2509     return (result);
 2510 }
 2511 
 2512 void
 2513 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
 2514     isc_result_t result;
 2515     ns_clientmgr_t *manager;
 2516     bool unlock = false;
 2517 
 2518     REQUIRE(managerp != NULL);
 2519     manager = *managerp;
 2520     *managerp = NULL;
 2521     REQUIRE(VALID_MANAGER(manager));
 2522 
 2523     MTRACE("destroy");
 2524 
 2525     /*
 2526      * Check for success because we may already be task-exclusive
 2527      * at this point.  Only if we succeed at obtaining an exclusive
 2528      * lock now will we need to relinquish it later.
 2529      */
 2530     result = isc_task_beginexclusive(manager->excl);
 2531     if (result == ISC_R_SUCCESS) {
 2532         unlock = true;
 2533     }
 2534 
 2535     manager->exiting = true;
 2536 
 2537     if (unlock) {
 2538         isc_task_endexclusive(manager->excl);
 2539     }
 2540 
 2541     if (isc_refcount_decrement(&manager->references) == 1) {
 2542         clientmgr_destroy(manager);
 2543     }
 2544 }
 2545 
 2546 isc_sockaddr_t *
 2547 ns_client_getsockaddr(ns_client_t *client) {
 2548     return (&client->peeraddr);
 2549 }
 2550 
 2551 isc_sockaddr_t *
 2552 ns_client_getdestaddr(ns_client_t *client) {
 2553     return (&client->destsockaddr);
 2554 }
 2555 
 2556 isc_result_t
 2557 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
 2558              dns_acl_t *acl, bool default_allow) {
 2559     isc_result_t result;
 2560     dns_aclenv_t *env =
 2561         ns_interfacemgr_getaclenv(client->manager->interface->mgr);
 2562     isc_netaddr_t tmpnetaddr;
 2563     int match;
 2564 
 2565     if (acl == NULL) {
 2566         if (default_allow) {
 2567             goto allow;
 2568         } else {
 2569             goto deny;
 2570         }
 2571     }
 2572 
 2573     if (netaddr == NULL) {
 2574         isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
 2575         netaddr = &tmpnetaddr;
 2576     }
 2577 
 2578     result = dns_acl_match(netaddr, client->signer, acl, env, &match, NULL);
 2579     if (result != ISC_R_SUCCESS) {
 2580         goto deny; /* Internal error, already logged. */
 2581     }
 2582 
 2583     if (match > 0) {
 2584         goto allow;
 2585     }
 2586     goto deny; /* Negative match or no match. */
 2587 
 2588 allow:
 2589     return (ISC_R_SUCCESS);
 2590 
 2591 deny:
 2592     return (DNS_R_REFUSED);
 2593 }
 2594 
 2595 isc_result_t
 2596 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
 2597            const char *opname, dns_acl_t *acl, bool default_allow,
 2598            int log_level) {
 2599     isc_result_t result;
 2600     isc_netaddr_t netaddr;
 2601 
 2602     if (sockaddr != NULL) {
 2603         isc_netaddr_fromsockaddr(&netaddr, sockaddr);
 2604     }
 2605 
 2606     result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
 2607                       acl, default_allow);
 2608 
 2609     if (result == ISC_R_SUCCESS) {
 2610         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2611                   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 2612                   "%s approved", opname);
 2613     } else {
 2614         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 2615                   NS_LOGMODULE_CLIENT, log_level, "%s denied",
 2616                   opname);
 2617     }
 2618     return (result);
 2619 }
 2620 
 2621 static void
 2622 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
 2623     if (client->peeraddr_valid) {
 2624         isc_sockaddr_format(&client->peeraddr, peerbuf,
 2625                     (unsigned int)len);
 2626     } else {
 2627         snprintf(peerbuf, len, "@%p", client);
 2628     }
 2629 }
 2630 
 2631 void
 2632 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
 2633            isc_logmodule_t *module, int level, const char *fmt,
 2634            va_list ap) {
 2635     char msgbuf[4096];
 2636     char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
 2637     char peerbuf[ISC_SOCKADDR_FORMATSIZE];
 2638     const char *viewname = "";
 2639     const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
 2640     const char *signer = "", *qname = "";
 2641     dns_name_t *q = NULL;
 2642 
 2643     REQUIRE(client != NULL);
 2644 
 2645     vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
 2646 
 2647     if (client->signer != NULL) {
 2648         dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
 2649         sep1 = "/key ";
 2650         signer = signerbuf;
 2651     }
 2652 
 2653     q = client->query.origqname != NULL ? client->query.origqname
 2654                         : client->query.qname;
 2655     if (q != NULL) {
 2656         dns_name_format(q, qnamebuf, sizeof(qnamebuf));
 2657         sep2 = " (";
 2658         sep3 = ")";
 2659         qname = qnamebuf;
 2660     }
 2661 
 2662     if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
 2663         strcmp(client->view->name, "_default") != 0)
 2664     {
 2665         sep4 = ": view ";
 2666         viewname = client->view->name;
 2667     }
 2668 
 2669     if (client->peeraddr_valid) {
 2670         isc_sockaddr_format(&client->peeraddr, peerbuf,
 2671                     sizeof(peerbuf));
 2672     } else {
 2673         snprintf(peerbuf, sizeof(peerbuf), "(no-peer)");
 2674     }
 2675 
 2676     isc_log_write(ns_lctx, category, module, level,
 2677               "client @%p %s%s%s%s%s%s%s%s: %s", client, peerbuf, sep1,
 2678               signer, sep2, qname, sep3, sep4, viewname, msgbuf);
 2679 }
 2680 
 2681 void
 2682 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
 2683           isc_logmodule_t *module, int level, const char *fmt, ...) {
 2684     va_list ap;
 2685 
 2686     if (!isc_log_wouldlog(ns_lctx, level)) {
 2687         return;
 2688     }
 2689 
 2690     va_start(ap, fmt);
 2691     ns_client_logv(client, category, module, level, fmt, ap);
 2692     va_end(ap);
 2693 }
 2694 
 2695 void
 2696 ns_client_aclmsg(const char *msg, const dns_name_t *name, dns_rdatatype_t type,
 2697          dns_rdataclass_t rdclass, char *buf, size_t len) {
 2698     char namebuf[DNS_NAME_FORMATSIZE];
 2699     char typebuf[DNS_RDATATYPE_FORMATSIZE];
 2700     char classbuf[DNS_RDATACLASS_FORMATSIZE];
 2701 
 2702     dns_name_format(name, namebuf, sizeof(namebuf));
 2703     dns_rdatatype_format(type, typebuf, sizeof(typebuf));
 2704     dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
 2705     (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
 2706                classbuf);
 2707 }
 2708 
 2709 static void
 2710 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
 2711     isc_buffer_t buffer;
 2712     char *buf = NULL;
 2713     int len = 1024;
 2714     isc_result_t result;
 2715 
 2716     if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
 2717         return;
 2718     }
 2719 
 2720     /*
 2721      * Note that these are multiline debug messages.  We want a newline
 2722      * to appear in the log after each message.
 2723      */
 2724 
 2725     do {
 2726         buf = isc_mem_get(client->mctx, len);
 2727         isc_buffer_init(&buffer, buf, len);
 2728         result = dns_message_totext(
 2729             client->message, &dns_master_style_debug, 0, &buffer);
 2730         if (result == ISC_R_NOSPACE) {
 2731             isc_mem_put(client->mctx, buf, len);
 2732             len += 1024;
 2733         } else if (result == ISC_R_SUCCESS) {
 2734             ns_client_log(client, NS_LOGCATEGORY_CLIENT,
 2735                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
 2736                       "%s\n%.*s", reason,
 2737                       (int)isc_buffer_usedlength(&buffer), buf);
 2738         }
 2739     } while (result == ISC_R_NOSPACE);
 2740 
 2741     if (buf != NULL) {
 2742         isc_mem_put(client->mctx, buf, len);
 2743     }
 2744 }
 2745 
 2746 void
 2747 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
 2748     ns_client_t *client;
 2749     char namebuf[DNS_NAME_FORMATSIZE];
 2750     char original[DNS_NAME_FORMATSIZE];
 2751     char peerbuf[ISC_SOCKADDR_FORMATSIZE];
 2752     char typebuf[DNS_RDATATYPE_FORMATSIZE];
 2753     char classbuf[DNS_RDATACLASS_FORMATSIZE];
 2754     const char *name;
 2755     const char *sep;
 2756     const char *origfor;
 2757     dns_rdataset_t *rdataset;
 2758 
 2759     REQUIRE(VALID_MANAGER(manager));
 2760 
 2761     LOCK(&manager->reclock);
 2762     client = ISC_LIST_HEAD(manager->recursing);
 2763     while (client != NULL) {
 2764         INSIST(client->state == NS_CLIENTSTATE_RECURSING);
 2765 
 2766         ns_client_name(client, peerbuf, sizeof(peerbuf));
 2767         if (client->view != NULL &&
 2768             strcmp(client->view->name, "_bind") != 0 &&
 2769             strcmp(client->view->name, "_default") != 0)
 2770         {
 2771             name = client->view->name;
 2772             sep = ": view ";
 2773         } else {
 2774             name = "";
 2775             sep = "";
 2776         }
 2777 
 2778         LOCK(&client->query.fetchlock);
 2779         INSIST(client->query.qname != NULL);
 2780         dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
 2781         if (client->query.qname != client->query.origqname &&
 2782             client->query.origqname != NULL)
 2783         {
 2784             origfor = " for ";
 2785             dns_name_format(client->query.origqname, original,
 2786                     sizeof(original));
 2787         } else {
 2788             origfor = "";
 2789             original[0] = '\0';
 2790         }
 2791         rdataset = ISC_LIST_HEAD(client->query.qname->list);
 2792         if (rdataset == NULL && client->query.origqname != NULL) {
 2793             rdataset = ISC_LIST_HEAD(client->query.origqname->list);
 2794         }
 2795         if (rdataset != NULL) {
 2796             dns_rdatatype_format(rdataset->type, typebuf,
 2797                          sizeof(typebuf));
 2798             dns_rdataclass_format(rdataset->rdclass, classbuf,
 2799                           sizeof(classbuf));
 2800         } else {
 2801             strlcpy(typebuf, "-", sizeof(typebuf));
 2802             strlcpy(classbuf, "-", sizeof(classbuf));
 2803         }
 2804         UNLOCK(&client->query.fetchlock);
 2805         fprintf(f,
 2806             "; client %s%s%s: id %u '%s/%s/%s'%s%s "
 2807             "requesttime %u\n",
 2808             peerbuf, sep, name, client->message->id, namebuf,
 2809             typebuf, classbuf, origfor, original,
 2810             isc_time_seconds(&client->requesttime));
 2811         client = ISC_LIST_NEXT(client, rlink);
 2812     }
 2813     UNLOCK(&manager->reclock);
 2814 }
 2815 
 2816 void
 2817 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
 2818     LOCK(&client->query.fetchlock);
 2819     if (client->query.restarts > 0) {
 2820         /*
 2821          * client->query.qname was dynamically allocated.
 2822          */
 2823         dns_message_puttempname(client->message, &client->query.qname);
 2824     }
 2825     client->query.qname = name;
 2826     client->query.attributes &= ~NS_QUERYATTR_REDIRECT;
 2827     UNLOCK(&client->query.fetchlock);
 2828 }
 2829 
 2830 isc_result_t
 2831 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
 2832     ns_client_t *client = (ns_client_t *)ci->data;
 2833 
 2834     REQUIRE(NS_CLIENT_VALID(client));
 2835     REQUIRE(addrp != NULL);
 2836 
 2837     *addrp = &client->peeraddr;
 2838     return (ISC_R_SUCCESS);
 2839 }
 2840 
 2841 dns_rdataset_t *
 2842 ns_client_newrdataset(ns_client_t *client) {
 2843     dns_rdataset_t *rdataset;
 2844     isc_result_t result;
 2845 
 2846     REQUIRE(NS_CLIENT_VALID(client));
 2847 
 2848     rdataset = NULL;
 2849     result = dns_message_gettemprdataset(client->message, &rdataset);
 2850     if (result != ISC_R_SUCCESS) {
 2851         return (NULL);
 2852     }
 2853 
 2854     return (rdataset);
 2855 }
 2856 
 2857 void
 2858 ns_client_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
 2859     dns_rdataset_t *rdataset;
 2860 
 2861     REQUIRE(NS_CLIENT_VALID(client));
 2862     REQUIRE(rdatasetp != NULL);
 2863 
 2864     rdataset = *rdatasetp;
 2865 
 2866     if (rdataset != NULL) {
 2867         if (dns_rdataset_isassociated(rdataset)) {
 2868             dns_rdataset_disassociate(rdataset);
 2869         }
 2870         dns_message_puttemprdataset(client->message, rdatasetp);
 2871     }
 2872 }
 2873 
 2874 isc_result_t
 2875 ns_client_newnamebuf(ns_client_t *client) {
 2876     isc_buffer_t *dbuf;
 2877 
 2878     CTRACE("ns_client_newnamebuf");
 2879 
 2880     dbuf = NULL;
 2881     isc_buffer_allocate(client->mctx, &dbuf, 1024);
 2882     ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
 2883 
 2884     CTRACE("ns_client_newnamebuf: done");
 2885     return (ISC_R_SUCCESS);
 2886 }
 2887 
 2888 dns_name_t *
 2889 ns_client_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf) {
 2890     dns_name_t *name;
 2891     isc_region_t r;
 2892     isc_result_t result;
 2893 
 2894     REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
 2895 
 2896     CTRACE("ns_client_newname");
 2897 
 2898     name = NULL;
 2899     result = dns_message_gettempname(client->message, &name);
 2900     if (result != ISC_R_SUCCESS) {
 2901         CTRACE("ns_client_newname: "
 2902                "dns_message_gettempname failed: done");
 2903         return (NULL);
 2904     }
 2905     isc_buffer_availableregion(dbuf, &r);
 2906     isc_buffer_init(nbuf, r.base, r.length);
 2907     dns_name_init(name, NULL);
 2908     dns_name_setbuffer(name, nbuf);
 2909     client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
 2910 
 2911     CTRACE("ns_client_newname: done");
 2912     return (name);
 2913 }
 2914 
 2915 isc_buffer_t *
 2916 ns_client_getnamebuf(ns_client_t *client) {
 2917     isc_buffer_t *dbuf;
 2918     isc_result_t result;
 2919     isc_region_t r;
 2920 
 2921     CTRACE("ns_client_getnamebuf");
 2922 
 2923     /*%
 2924      * Return a name buffer with space for a maximal name, allocating
 2925      * a new one if necessary.
 2926      */
 2927     if (ISC_LIST_EMPTY(client->query.namebufs)) {
 2928         result = ns_client_newnamebuf(client);
 2929         if (result != ISC_R_SUCCESS) {
 2930             CTRACE("ns_client_getnamebuf: "
 2931                    "ns_client_newnamebuf failed: done");
 2932             return (NULL);
 2933         }
 2934     }
 2935 
 2936     dbuf = ISC_LIST_TAIL(client->query.namebufs);
 2937     INSIST(dbuf != NULL);
 2938     isc_buffer_availableregion(dbuf, &r);
 2939     if (r.length < DNS_NAME_MAXWIRE) {
 2940         result = ns_client_newnamebuf(client);
 2941         if (result != ISC_R_SUCCESS) {
 2942             CTRACE("ns_client_getnamebuf: "
 2943                    "ns_client_newnamebuf failed: done");
 2944             return (NULL);
 2945         }
 2946         dbuf = ISC_LIST_TAIL(client->query.namebufs);
 2947         isc_buffer_availableregion(dbuf, &r);
 2948         INSIST(r.length >= 255);
 2949     }
 2950     CTRACE("ns_client_getnamebuf: done");
 2951     return (dbuf);
 2952 }
 2953 
 2954 void
 2955 ns_client_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
 2956     isc_region_t r;
 2957 
 2958     CTRACE("ns_client_keepname");
 2959 
 2960     /*%
 2961      * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
 2962      * adjusted to take account of that.  We do the adjustment.
 2963      */
 2964     REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
 2965 
 2966     dns_name_toregion(name, &r);
 2967     isc_buffer_add(dbuf, r.length);
 2968     dns_name_setbuffer(name, NULL);
 2969     client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
 2970 }
 2971 
 2972 void
 2973 ns_client_releasename(ns_client_t *client, dns_name_t **namep) {
 2974     dns_name_t *name = *namep;
 2975 
 2976     /*%
 2977      * 'name' is no longer needed.  Return it to our pool of temporary
 2978      * names.  If it is using a name buffer, relinquish its exclusive
 2979      * rights on the buffer.
 2980      */
 2981 
 2982     CTRACE("ns_client_releasename");
 2983     if (dns_name_hasbuffer(name)) {
 2984         INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) !=
 2985                0);
 2986         client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
 2987     }
 2988     dns_message_puttempname(client->message, namep);
 2989     CTRACE("ns_client_releasename: done");
 2990 }
 2991 
 2992 isc_result_t
 2993 ns_client_newdbversion(ns_client_t *client, unsigned int n) {
 2994     unsigned int i;
 2995     ns_dbversion_t *dbversion;
 2996 
 2997     for (i = 0; i < n; i++) {
 2998         dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
 2999         {
 3000             dbversion->db = NULL;
 3001             dbversion->version = NULL;
 3002             ISC_LIST_INITANDAPPEND(client->query.freeversions,
 3003                            dbversion, link);
 3004         }
 3005     }
 3006 
 3007     return (ISC_R_SUCCESS);
 3008 }
 3009 
 3010 static inline ns_dbversion_t *
 3011 client_getdbversion(ns_client_t *client) {
 3012     isc_result_t result;
 3013     ns_dbversion_t *dbversion;
 3014 
 3015     if (ISC_LIST_EMPTY(client->query.freeversions)) {
 3016         result = ns_client_newdbversion(client, 1);
 3017         if (result != ISC_R_SUCCESS) {
 3018             return (NULL);
 3019         }
 3020     }
 3021     dbversion = ISC_LIST_HEAD(client->query.freeversions);
 3022     INSIST(dbversion != NULL);
 3023     ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
 3024 
 3025     return (dbversion);
 3026 }
 3027 
 3028 ns_dbversion_t *
 3029 ns_client_findversion(ns_client_t *client, dns_db_t *db) {
 3030     ns_dbversion_t *dbversion;
 3031 
 3032     for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
 3033          dbversion != NULL; dbversion = ISC_LIST_NEXT(dbversion, link))
 3034     {
 3035         if (dbversion->db == db) {
 3036             break;
 3037         }
 3038     }
 3039 
 3040     if (dbversion == NULL) {
 3041         /*
 3042          * This is a new zone for this query.  Add it to
 3043          * the active list.
 3044          */
 3045         dbversion = client_getdbversion(client);
 3046         if (dbversion == NULL) {
 3047             return (NULL);
 3048         }
 3049         dns_db_attach(db, &dbversion->db);
 3050         dns_db_currentversion(db, &dbversion->version);
 3051         dbversion->acl_checked = false;
 3052         dbversion->queryok = false;
 3053         ISC_LIST_APPEND(client->query.activeversions, dbversion, link);
 3054     }
 3055 
 3056     return (dbversion);
 3057 }