client.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 #include <config.h>
00019 
00020 #include <isc/formatcheck.h>
00021 #include <isc/mutex.h>
00022 #include <isc/once.h>
00023 #include <isc/platform.h>
00024 #include <isc/print.h>
00025 #include <isc/queue.h>
00026 #include <isc/random.h>
00027 #include <isc/serial.h>
00028 #include <isc/stats.h>
00029 #include <isc/stdio.h>
00030 #include <isc/string.h>
00031 #include <isc/task.h>
00032 #include <isc/timer.h>
00033 #include <isc/util.h>
00034 
00035 #ifdef AES_SIT
00036 #include <isc/aes.h>
00037 #else
00038 #include <isc/hmacsha.h>
00039 #endif
00040 
00041 #include <dns/badcache.h>
00042 #include <dns/db.h>
00043 #include <dns/dispatch.h>
00044 #include <dns/edns.h>
00045 #include <dns/events.h>
00046 #include <dns/message.h>
00047 #include <dns/peer.h>
00048 #include <dns/rcode.h>
00049 #include <dns/rdata.h>
00050 #include <dns/rdataclass.h>
00051 #include <dns/rdatalist.h>
00052 #include <dns/rdataset.h>
00053 #include <dns/resolver.h>
00054 #include <dns/stats.h>
00055 #include <dns/tsig.h>
00056 #include <dns/view.h>
00057 #include <dns/zone.h>
00058 
00059 #include <named/interfacemgr.h>
00060 #include <named/log.h>
00061 #include <named/notify.h>
00062 #include <named/os.h>
00063 #include <named/server.h>
00064 #include <named/update.h>
00065 
00066 /***
00067  *** Client
00068  ***/
00069 
00070 /*! \file
00071  * Client Routines
00072  *
00073  * Important note!
00074  *
00075  * All client state changes, other than that from idle to listening, occur
00076  * as a result of events.  This guarantees serialization and avoids the
00077  * need for locking.
00078  *
00079  * If a routine is ever created that allows someone other than the client's
00080  * task to change the client, then the client will have to be locked.
00081  */
00082 
00083 #define NS_CLIENT_TRACE
00084 #ifdef NS_CLIENT_TRACE
00085 #define CTRACE(m)       ns_client_log(client, \
00086                                       NS_LOGCATEGORY_CLIENT, \
00087                                       NS_LOGMODULE_CLIENT, \
00088                                       ISC_LOG_DEBUG(3), \
00089                                       "%s", (m))
00090 #define MTRACE(m)       isc_log_write(ns_g_lctx, \
00091                                       NS_LOGCATEGORY_GENERAL, \
00092                                       NS_LOGMODULE_CLIENT, \
00093                                       ISC_LOG_DEBUG(3), \
00094                                       "clientmgr @%p: %s", manager, (m))
00095 #else
00096 #define CTRACE(m)       ((void)(m))
00097 #define MTRACE(m)       ((void)(m))
00098 #endif
00099 
00100 #define TCP_CLIENT(c)   (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
00101 
00102 #define TCP_BUFFER_SIZE                 (65535 + 2)
00103 #define SEND_BUFFER_SIZE                4096
00104 #define RECV_BUFFER_SIZE                4096
00105 
00106 #ifdef ISC_PLATFORM_USETHREADS
00107 #define NMCTXS                          100
00108 /*%<
00109  * Number of 'mctx pools' for clients. (Should this be configurable?)
00110  * When enabling threads, we use a pool of memory contexts shared by
00111  * client objects, since concurrent access to a shared context would cause
00112  * heavy contentions.  The above constant is expected to be enough for
00113  * completely avoiding contentions among threads for an authoritative-only
00114  * server.
00115  */
00116 #else
00117 #define NMCTXS                          0
00118 /*%<
00119  * If named with built without thread, simply share manager's context.  Using
00120  * a separate context in this case would simply waste memory.
00121  */
00122 #endif
00123 
00124 #define SIT_SIZE 24U /* 8 + 4 + 4 + 8 */
00125 #define ECS_SIZE 20U /* 2 + 1 + 1 + [0..16] */
00126 
00127 /*% nameserver client manager structure */
00128 struct ns_clientmgr {
00129         /* Unlocked. */
00130         unsigned int                    magic;
00131 
00132         /* The queue object has its own locks */
00133         client_queue_t                  inactive;     /*%< To be recycled */
00134 
00135         isc_mem_t *                     mctx;
00136         isc_taskmgr_t *                 taskmgr;
00137         isc_timermgr_t *                timermgr;
00138 
00139         /* Lock covers manager state. */
00140         isc_mutex_t                     lock;
00141         isc_boolean_t                   exiting;
00142 
00143         /* Lock covers the clients list */
00144         isc_mutex_t                     listlock;
00145         client_list_t                   clients;      /*%< All active clients */
00146 
00147         /* Lock covers the recursing list */
00148         isc_mutex_t                     reclock;
00149         client_list_t                   recursing;    /*%< Recursing clients */
00150 
00151 #if NMCTXS > 0
00152         /*%< mctx pool for clients. */
00153         unsigned int                    nextmctx;
00154         isc_mem_t *                     mctxpool[NMCTXS];
00155 #endif
00156 };
00157 
00158 #define MANAGER_MAGIC                   ISC_MAGIC('N', 'S', 'C', 'm')
00159 #define VALID_MANAGER(m)                ISC_MAGIC_VALID(m, MANAGER_MAGIC)
00160 
00161 /*!
00162  * Client object states.  Ordering is significant: higher-numbered
00163  * states are generally "more active", meaning that the client can
00164  * have more dynamically allocated data, outstanding events, etc.
00165  * In the list below, any such properties listed for state N
00166  * also apply to any state > N.
00167  *
00168  * To force the client into a less active state, set client->newstate
00169  * to that state and call exit_check().  This will cause any
00170  * activities defined for higher-numbered states to be aborted.
00171  */
00172 
00173 #define NS_CLIENTSTATE_FREED    0
00174 /*%<
00175  * The client object no longer exists.
00176  */
00177 
00178 #define NS_CLIENTSTATE_INACTIVE 1
00179 /*%<
00180  * The client object exists and has a task and timer.
00181  * Its "query" struct and sendbuf are initialized.
00182  * It is on the client manager's list of inactive clients.
00183  * It has a message and OPT, both in the reset state.
00184  */
00185 
00186 #define NS_CLIENTSTATE_READY    2
00187 /*%<
00188  * The client object is either a TCP or a UDP one, and
00189  * it is associated with a network interface.  It is on the
00190  * client manager's list of active clients.
00191  *
00192  * If it is a TCP client object, it has a TCP listener socket
00193  * and an outstanding TCP listen request.
00194  *
00195  * If it is a UDP client object, it has a UDP listener socket
00196  * and an outstanding UDP receive request.
00197  */
00198 
00199 #define NS_CLIENTSTATE_READING  3
00200 /*%<
00201  * The client object is a TCP client object that has received
00202  * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
00203  * outstanding TCP read request.  This state is not used for
00204  * UDP client objects.
00205  */
00206 
00207 #define NS_CLIENTSTATE_WORKING  4
00208 /*%<
00209  * The client object has received a request and is working
00210  * on it.  It has a view, and it may have any of a non-reset OPT,
00211  * recursion quota, and an outstanding write request.
00212  */
00213 
00214 #define NS_CLIENTSTATE_RECURSING  5
00215 /*%<
00216  * The client object is recursing.  It will be on the 'recursing'
00217  * list.
00218  */
00219 
00220 #define NS_CLIENTSTATE_MAX      9
00221 /*%<
00222  * Sentinel value used to indicate "no state".  When client->newstate
00223  * has this value, we are not attempting to exit the current state.
00224  * Must be greater than any valid state.
00225  */
00226 
00227 /*
00228  * Enable ns_client_dropport() by default.
00229  */
00230 #ifndef NS_CLIENT_DROPPORT
00231 #define NS_CLIENT_DROPPORT 1
00232 #endif
00233 
00234 unsigned int ns_client_requests;
00235 
00236 static void client_read(ns_client_t *client);
00237 static void client_accept(ns_client_t *client);
00238 static void client_udprecv(ns_client_t *client);
00239 static void clientmgr_destroy(ns_clientmgr_t *manager);
00240 static isc_boolean_t exit_check(ns_client_t *client);
00241 static void ns_client_endrequest(ns_client_t *client);
00242 static void client_start(isc_task_t *task, isc_event_t *event);
00243 static void client_request(isc_task_t *task, isc_event_t *event);
00244 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
00245 static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
00246                                dns_dispatch_t *disp, isc_boolean_t tcp);
00247 static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp,
00248                                isc_socket_t *sock);
00249 static inline isc_boolean_t
00250 allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr,
00251         isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl);
00252 #ifdef ISC_PLATFORM_USESIT
00253 static void compute_sit(ns_client_t *client, isc_uint32_t when,
00254                         isc_uint32_t nonce, isc_buffer_t *buf);
00255 #endif
00256 
00257 void
00258 ns_client_recursing(ns_client_t *client) {
00259         REQUIRE(NS_CLIENT_VALID(client));
00260         REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
00261 
00262         LOCK(&client->manager->reclock);
00263         client->newstate = client->state = NS_CLIENTSTATE_RECURSING;
00264         ISC_LIST_APPEND(client->manager->recursing, client, rlink);
00265         UNLOCK(&client->manager->reclock);
00266 }
00267 
00268 void
00269 ns_client_killoldestquery(ns_client_t *client) {
00270         ns_client_t *oldest;
00271         REQUIRE(NS_CLIENT_VALID(client));
00272 
00273         LOCK(&client->manager->reclock);
00274         oldest = ISC_LIST_HEAD(client->manager->recursing);
00275         if (oldest != NULL) {
00276                 ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
00277                 UNLOCK(&client->manager->reclock);
00278                 ns_query_cancel(oldest);
00279         } else
00280                 UNLOCK(&client->manager->reclock);
00281 }
00282 
00283 void
00284 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
00285         isc_result_t result;
00286         isc_interval_t interval;
00287 
00288         isc_interval_set(&interval, seconds, 0);
00289         result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
00290                                  &interval, ISC_FALSE);
00291         client->timerset = ISC_TRUE;
00292         if (result != ISC_R_SUCCESS) {
00293                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
00294                               NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
00295                               "setting timeout: %s",
00296                               isc_result_totext(result));
00297                 /* Continue anyway. */
00298         }
00299 }
00300 
00301 /*%
00302  * Check for a deactivation or shutdown request and take appropriate
00303  * action.  Returns ISC_TRUE if either is in progress; in this case
00304  * the caller must no longer use the client object as it may have been
00305  * freed.
00306  */
00307 static isc_boolean_t
00308 exit_check(ns_client_t *client) {
00309         isc_boolean_t destroy_manager = ISC_FALSE;
00310         ns_clientmgr_t *manager = NULL;
00311 
00312         REQUIRE(NS_CLIENT_VALID(client));
00313         manager = client->manager;
00314 
00315         if (client->state <= client->newstate)
00316                 return (ISC_FALSE); /* Business as usual. */
00317 
00318         INSIST(client->newstate < NS_CLIENTSTATE_RECURSING);
00319 
00320         /*
00321          * We need to detach from the view early when shutting down
00322          * the server to break the following vicious circle:
00323          *
00324          *  - The resolver will not shut down until the view refcount is zero
00325          *  - The view refcount does not go to zero until all clients detach
00326          *  - The client does not detach from the view until references is zero
00327          *  - references does not go to zero until the resolver has shut down
00328          *
00329          * Keep the view attached until any outstanding updates complete.
00330          */
00331         if (client->nupdates == 0 &&
00332             client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
00333                 dns_view_detach(&client->view);
00334 
00335         if (client->state == NS_CLIENTSTATE_WORKING ||
00336             client->state == NS_CLIENTSTATE_RECURSING)
00337         {
00338                 INSIST(client->newstate <= NS_CLIENTSTATE_READING);
00339                 /*
00340                  * Let the update processing complete.
00341                  */
00342                 if (client->nupdates > 0)
00343                         return (ISC_TRUE);
00344 
00345                 /*
00346                  * We are trying to abort request processing.
00347                  */
00348                 if (client->nsends > 0) {
00349                         isc_socket_t *sock;
00350                         if (TCP_CLIENT(client))
00351                                 sock = client->tcpsocket;
00352                         else
00353                                 sock = client->udpsocket;
00354                         isc_socket_cancel(sock, client->task,
00355                                           ISC_SOCKCANCEL_SEND);
00356                 }
00357 
00358                 if (! (client->nsends == 0 && client->nrecvs == 0 &&
00359                        client->references == 0))
00360                 {
00361                         /*
00362                          * Still waiting for I/O cancel completion.
00363                          * or lingering references.
00364                          */
00365                         return (ISC_TRUE);
00366                 }
00367 
00368                 /*
00369                  * I/O cancel is complete.  Burn down all state
00370                  * related to the current request.  Ensure that
00371                  * the client is no longer on the recursing list.
00372                  *
00373                  * We need to check whether the client is still linked,
00374                  * because it may already have been removed from the
00375                  * recursing list by ns_client_killoldestquery()
00376                  */
00377                 if (client->state == NS_CLIENTSTATE_RECURSING) {
00378                         LOCK(&manager->reclock);
00379                         if (ISC_LINK_LINKED(client, rlink))
00380                                 ISC_LIST_UNLINK(manager->recursing,
00381                                                 client, rlink);
00382                         UNLOCK(&manager->reclock);
00383                 }
00384                 ns_client_endrequest(client);
00385 
00386                 client->state = NS_CLIENTSTATE_READING;
00387                 INSIST(client->recursionquota == NULL);
00388 
00389                 if (NS_CLIENTSTATE_READING == client->newstate) {
00390                         if (!client->pipelined) {
00391                                 client_read(client);
00392                                 client->newstate = NS_CLIENTSTATE_MAX;
00393                                 return (ISC_TRUE); /* We're done. */
00394                         } else if (client->mortal) {
00395                                 client->newstate = NS_CLIENTSTATE_INACTIVE;
00396                         }
00397                 }
00398         }
00399 
00400         if (client->state == NS_CLIENTSTATE_READING) {
00401                 /*
00402                  * We are trying to abort the current TCP connection,
00403                  * if any.
00404                  */
00405                 INSIST(client->recursionquota == NULL);
00406                 INSIST(client->newstate <= NS_CLIENTSTATE_READY);
00407                 if (client->nreads > 0)
00408                         dns_tcpmsg_cancelread(&client->tcpmsg);
00409                 if (! client->nreads == 0) {
00410                         /* Still waiting for read cancel completion. */
00411                         return (ISC_TRUE);
00412                 }
00413 
00414                 if (client->tcpmsg_valid) {
00415                         dns_tcpmsg_invalidate(&client->tcpmsg);
00416                         client->tcpmsg_valid = ISC_FALSE;
00417                 }
00418                 if (client->tcpsocket != NULL) {
00419                         CTRACE("closetcp");
00420                         isc_socket_detach(&client->tcpsocket);
00421                 }
00422 
00423                 if (client->tcpquota != NULL)
00424                         isc_quota_detach(&client->tcpquota);
00425 
00426                 if (client->timerset) {
00427                         (void)isc_timer_reset(client->timer,
00428                                               isc_timertype_inactive,
00429                                               NULL, NULL, ISC_TRUE);
00430                         client->timerset = ISC_FALSE;
00431                 }
00432 
00433                 client->pipelined = ISC_FALSE;
00434 
00435                 client->peeraddr_valid = ISC_FALSE;
00436 
00437                 client->state = NS_CLIENTSTATE_READY;
00438                 INSIST(client->recursionquota == NULL);
00439 
00440                 /*
00441                  * Now the client is ready to accept a new TCP connection
00442                  * or UDP request, but we may have enough clients doing
00443                  * that already.  Check whether this client needs to remain
00444                  * active and force it to go inactive if not.
00445                  *
00446                  * UDP clients go inactive at this point, but TCP clients
00447                  * may remain active if we have fewer active TCP client
00448                  * objects than desired due to an earlier quota exhaustion.
00449                  */
00450                 if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {
00451                         LOCK(&client->interface->lock);
00452                         if (client->interface->ntcpcurrent <
00453                                     client->interface->ntcptarget)
00454                                 client->mortal = ISC_FALSE;
00455                         UNLOCK(&client->interface->lock);
00456                 }
00457 
00458                 /*
00459                  * We don't need the client; send it to the inactive
00460                  * queue for recycling.
00461                  */
00462                 if (client->mortal) {
00463                         if (client->newstate > NS_CLIENTSTATE_INACTIVE)
00464                                 client->newstate = NS_CLIENTSTATE_INACTIVE;
00465                 }
00466 
00467                 if (NS_CLIENTSTATE_READY == client->newstate) {
00468                         if (TCP_CLIENT(client)) {
00469                                 client_accept(client);
00470                         } else
00471                                 client_udprecv(client);
00472                         client->newstate = NS_CLIENTSTATE_MAX;
00473                         return (ISC_TRUE);
00474                 }
00475         }
00476 
00477         if (client->state == NS_CLIENTSTATE_READY) {
00478                 INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
00479 
00480                 /*
00481                  * We are trying to enter the inactive state.
00482                  */
00483                 if (client->naccepts > 0)
00484                         isc_socket_cancel(client->tcplistener, client->task,
00485                                           ISC_SOCKCANCEL_ACCEPT);
00486 
00487                 /* Still waiting for accept cancel completion. */
00488                 if (! (client->naccepts == 0))
00489                         return (ISC_TRUE);
00490 
00491                 /* Accept cancel is complete. */
00492                 if (client->nrecvs > 0)
00493                         isc_socket_cancel(client->udpsocket, client->task,
00494                                           ISC_SOCKCANCEL_RECV);
00495 
00496                 /* Still waiting for recv cancel completion. */
00497                 if (! (client->nrecvs == 0))
00498                         return (ISC_TRUE);
00499 
00500                 /* Still waiting for control event to be delivered */
00501                 if (client->nctls > 0)
00502                         return (ISC_TRUE);
00503 
00504                 /* Deactivate the client. */
00505                 if (client->interface)
00506                         ns_interface_detach(&client->interface);
00507 
00508                 INSIST(client->naccepts == 0);
00509                 INSIST(client->recursionquota == NULL);
00510                 if (client->tcplistener != NULL)
00511                         isc_socket_detach(&client->tcplistener);
00512 
00513                 if (client->udpsocket != NULL)
00514                         isc_socket_detach(&client->udpsocket);
00515 
00516                 if (client->dispatch != NULL)
00517                         dns_dispatch_detach(&client->dispatch);
00518 
00519                 client->attributes = 0;
00520                 client->mortal = ISC_FALSE;
00521 
00522                 /*
00523                  * Put the client on the inactive list.  If we are aiming for
00524                  * the "freed" state, it will be removed from the inactive
00525                  * list shortly, and we need to keep the manager locked until
00526                  * that has been done, lest the manager decide to reactivate
00527                  * the dying client inbetween.
00528                  */
00529                 client->state = NS_CLIENTSTATE_INACTIVE;
00530                 INSIST(client->recursionquota == NULL);
00531 
00532                 if (client->state == client->newstate) {
00533                         client->newstate = NS_CLIENTSTATE_MAX;
00534                         if (!ns_g_clienttest && manager != NULL &&
00535                             !manager->exiting)
00536                                 ISC_QUEUE_PUSH(manager->inactive, client,
00537                                                ilink);
00538                         if (client->needshutdown)
00539                                 isc_task_shutdown(client->task);
00540                         return (ISC_TRUE);
00541                 }
00542         }
00543 
00544         if (client->state == NS_CLIENTSTATE_INACTIVE) {
00545                 INSIST(client->newstate == NS_CLIENTSTATE_FREED);
00546                 /*
00547                  * We are trying to free the client.
00548                  *
00549                  * When "shuttingdown" is true, either the task has received
00550                  * its shutdown event or no shutdown event has ever been
00551                  * set up.  Thus, we have no outstanding shutdown
00552                  * event at this point.
00553                  */
00554                 REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
00555 
00556                 INSIST(client->recursionquota == NULL);
00557                 INSIST(!ISC_QLINK_LINKED(client, ilink));
00558 
00559                 if (manager != NULL) {
00560                         LOCK(&manager->listlock);
00561                         ISC_LIST_UNLINK(manager->clients, client, link);
00562                         LOCK(&manager->lock);
00563                         if (manager->exiting &&
00564                             ISC_LIST_EMPTY(manager->clients))
00565                                 destroy_manager = ISC_TRUE;
00566                         UNLOCK(&manager->lock);
00567                         UNLOCK(&manager->listlock);
00568                 }
00569 
00570                 ns_query_free(client);
00571                 isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
00572                 isc_event_free((isc_event_t **)&client->sendevent);
00573                 isc_event_free((isc_event_t **)&client->recvevent);
00574                 isc_timer_detach(&client->timer);
00575                 if (client->delaytimer != NULL)
00576                         isc_timer_detach(&client->delaytimer);
00577 
00578                 if (client->tcpbuf != NULL)
00579                         isc_mem_put(client->mctx, client->tcpbuf,
00580                                     TCP_BUFFER_SIZE);
00581                 if (client->opt != NULL) {
00582                         INSIST(dns_rdataset_isassociated(client->opt));
00583                         dns_rdataset_disassociate(client->opt);
00584                         dns_message_puttemprdataset(client->message,
00585                                                     &client->opt);
00586                 }
00587 
00588                 dns_message_destroy(&client->message);
00589 
00590                 /*
00591                  * Detaching the task must be done after unlinking from
00592                  * the manager's lists because the manager accesses
00593                  * client->task.
00594                  */
00595                 if (client->task != NULL)
00596                         isc_task_detach(&client->task);
00597 
00598                 CTRACE("free");
00599                 client->magic = 0;
00600 
00601                 /*
00602                  * Check that there are no other external references to
00603                  * the memory context.
00604                  */
00605                 if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
00606                         isc_mem_stats(client->mctx, stderr);
00607                         INSIST(0);
00608                 }
00609 
00610                 /*
00611                  * Destroy the fetchlock mutex that was created in
00612                  * ns_query_init().
00613                  */
00614                 DESTROYLOCK(&client->query.fetchlock);
00615 
00616                 isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
00617         }
00618 
00619         if (destroy_manager && manager != NULL)
00620                 clientmgr_destroy(manager);
00621 
00622         return (ISC_TRUE);
00623 }
00624 
00625 /*%
00626  * The client's task has received the client's control event
00627  * as part of the startup process.
00628  */
00629 static void
00630 client_start(isc_task_t *task, isc_event_t *event) {
00631         ns_client_t *client = (ns_client_t *) event->ev_arg;
00632 
00633         INSIST(task == client->task);
00634 
00635         UNUSED(task);
00636 
00637         INSIST(client->nctls == 1);
00638         client->nctls--;
00639 
00640         if (exit_check(client))
00641                 return;
00642 
00643         if (TCP_CLIENT(client)) {
00644                 if (client->pipelined) {
00645                         client_read(client);
00646                 } else {
00647                         client_accept(client);
00648                 }
00649         } else {
00650                 client_udprecv(client);
00651         }
00652 }
00653 
00654 
00655 /*%
00656  * The client's task has received a shutdown event.
00657  */
00658 static void
00659 client_shutdown(isc_task_t *task, isc_event_t *event) {
00660         ns_client_t *client;
00661 
00662         REQUIRE(event != NULL);
00663         REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
00664         client = event->ev_arg;
00665         REQUIRE(NS_CLIENT_VALID(client));
00666         REQUIRE(task == client->task);
00667 
00668         UNUSED(task);
00669 
00670         CTRACE("shutdown");
00671 
00672         isc_event_free(&event);
00673 
00674         if (client->shutdown != NULL) {
00675                 (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
00676                 client->shutdown = NULL;
00677                 client->shutdown_arg = NULL;
00678         }
00679 
00680         if (ISC_QLINK_LINKED(client, ilink))
00681                 ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink);
00682 
00683         client->newstate = NS_CLIENTSTATE_FREED;
00684         client->needshutdown = ISC_FALSE;
00685         (void)exit_check(client);
00686 }
00687 
00688 static void
00689 ns_client_endrequest(ns_client_t *client) {
00690         INSIST(client->naccepts == 0);
00691         INSIST(client->nreads == 0);
00692         INSIST(client->nsends == 0);
00693         INSIST(client->nrecvs == 0);
00694         INSIST(client->nupdates == 0);
00695         INSIST(client->state == NS_CLIENTSTATE_WORKING ||
00696                client->state == NS_CLIENTSTATE_RECURSING);
00697 
00698         CTRACE("endrequest");
00699 
00700         if (client->next != NULL) {
00701                 (client->next)(client);
00702                 client->next = NULL;
00703         }
00704 
00705         if (client->view != NULL)
00706                 dns_view_detach(&client->view);
00707         if (client->opt != NULL) {
00708                 INSIST(dns_rdataset_isassociated(client->opt));
00709                 dns_rdataset_disassociate(client->opt);
00710                 dns_message_puttemprdataset(client->message, &client->opt);
00711         }
00712 
00713         client->signer = NULL;
00714         client->udpsize = 512;
00715         client->extflags = 0;
00716         client->ednsversion = -1;
00717         dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
00718 
00719         if (client->recursionquota != NULL) {
00720                 isc_quota_detach(&client->recursionquota);
00721                 isc_stats_decrement(ns_g_server->nsstats,
00722                                     dns_nsstatscounter_recursclients);
00723         }
00724 
00725         /*
00726          * Clear all client attributes that are specific to
00727          * the request; that's all except the TCP flag.
00728          */
00729         client->attributes &= NS_CLIENTATTR_TCP;
00730 }
00731 
00732 void
00733 ns_client_next(ns_client_t *client, isc_result_t result) {
00734         int newstate;
00735 
00736         REQUIRE(NS_CLIENT_VALID(client));
00737         REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
00738                 client->state == NS_CLIENTSTATE_RECURSING ||
00739                 client->state == NS_CLIENTSTATE_READING);
00740 
00741         CTRACE("next");
00742 
00743         if (result != ISC_R_SUCCESS)
00744                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
00745                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
00746                               "request failed: %s", isc_result_totext(result));
00747 
00748         /*
00749          * An error processing a TCP request may have left
00750          * the connection out of sync.  To be safe, we always
00751          * sever the connection when result != ISC_R_SUCCESS.
00752          */
00753         if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
00754                 newstate = NS_CLIENTSTATE_READING;
00755         else
00756                 newstate = NS_CLIENTSTATE_READY;
00757 
00758         if (client->newstate > newstate)
00759                 client->newstate = newstate;
00760         (void)exit_check(client);
00761 }
00762 
00763 
00764 static void
00765 client_senddone(isc_task_t *task, isc_event_t *event) {
00766         ns_client_t *client;
00767         isc_socketevent_t *sevent = (isc_socketevent_t *) event;
00768 
00769         REQUIRE(sevent != NULL);
00770         REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
00771         client = sevent->ev_arg;
00772         REQUIRE(NS_CLIENT_VALID(client));
00773         REQUIRE(task == client->task);
00774         REQUIRE(sevent == client->sendevent);
00775 
00776         UNUSED(task);
00777 
00778         CTRACE("senddone");
00779 
00780         if (sevent->result != ISC_R_SUCCESS)
00781                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
00782                               NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
00783                               "error sending response: %s",
00784                               isc_result_totext(sevent->result));
00785 
00786         INSIST(client->nsends > 0);
00787         client->nsends--;
00788 
00789         if (client->tcpbuf != NULL) {
00790                 INSIST(TCP_CLIENT(client));
00791                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
00792                 client->tcpbuf = NULL;
00793         }
00794 
00795         ns_client_next(client, ISC_R_SUCCESS);
00796 }
00797 
00798 /*%
00799  * We only want to fail with ISC_R_NOSPACE when called from
00800  * ns_client_sendraw() and not when called from ns_client_send(),
00801  * tcpbuffer is NULL when called from ns_client_sendraw() and
00802  * length != 0.  tcpbuffer != NULL when called from ns_client_send()
00803  * and length == 0.
00804  */
00805 
00806 static isc_result_t
00807 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
00808                     isc_buffer_t *tcpbuffer, isc_uint32_t length,
00809                     unsigned char *sendbuf, unsigned char **datap)
00810 {
00811         unsigned char *data;
00812         isc_uint32_t bufsize;
00813         isc_result_t result;
00814 
00815         INSIST(datap != NULL);
00816         INSIST((tcpbuffer == NULL && length != 0) ||
00817                (tcpbuffer != NULL && length == 0));
00818 
00819         if (TCP_CLIENT(client)) {
00820                 INSIST(client->tcpbuf == NULL);
00821                 if (length + 2 > TCP_BUFFER_SIZE) {
00822                         result = ISC_R_NOSPACE;
00823                         goto done;
00824                 }
00825                 client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
00826                 if (client->tcpbuf == NULL) {
00827                         result = ISC_R_NOMEMORY;
00828                         goto done;
00829                 }
00830                 data = client->tcpbuf;
00831                 if (tcpbuffer != NULL) {
00832                         isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
00833                         isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
00834                 } else {
00835                         isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
00836                         INSIST(length <= 0xffff);
00837                         isc_buffer_putuint16(buffer, (isc_uint16_t)length);
00838                 }
00839         } else {
00840                 data = sendbuf;
00841 #ifdef ISC_PLATFORM_USESIT
00842                 if ((client->attributes & NS_CLIENTATTR_HAVESIT) == 0) {
00843                         if (client->view != NULL)
00844                                 bufsize = client->view->situdp;
00845                         else
00846                                 bufsize = 512;
00847                 } else
00848                         bufsize = client->udpsize;
00849                 if (bufsize > client->udpsize)
00850                         bufsize = client->udpsize;
00851                 if (bufsize > SEND_BUFFER_SIZE)
00852                         bufsize = SEND_BUFFER_SIZE;
00853 #else
00854                 if (client->udpsize < SEND_BUFFER_SIZE)
00855                         bufsize = client->udpsize;
00856                 else
00857                         bufsize = SEND_BUFFER_SIZE;
00858 #endif
00859                 if (length > bufsize) {
00860                         result = ISC_R_NOSPACE;
00861                         goto done;
00862                 }
00863                 isc_buffer_init(buffer, data, bufsize);
00864         }
00865         *datap = data;
00866         result = ISC_R_SUCCESS;
00867 
00868  done:
00869         return (result);
00870 }
00871 
00872 static isc_result_t
00873 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
00874         struct in6_pktinfo *pktinfo;
00875         isc_result_t result;
00876         isc_region_t r;
00877         isc_sockaddr_t *address;
00878         isc_socket_t *sock;
00879         isc_netaddr_t netaddr;
00880         int match;
00881         unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
00882         isc_dscp_t dispdscp = -1;
00883 
00884         if (TCP_CLIENT(client)) {
00885                 sock = client->tcpsocket;
00886                 address = NULL;
00887         } else {
00888                 sock = client->udpsocket;
00889                 address = &client->peeraddr;
00890 
00891                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
00892                 if (ns_g_server->blackholeacl != NULL &&
00893                     dns_acl_match(&netaddr, NULL,
00894                                   ns_g_server->blackholeacl,
00895                                   &ns_g_server->aclenv,
00896                                   &match, NULL) == ISC_R_SUCCESS &&
00897                     match > 0)
00898                         return (DNS_R_BLACKHOLED);
00899                 sockflags |= ISC_SOCKFLAG_NORETRY;
00900         }
00901 
00902         if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
00903             (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
00904                 pktinfo = &client->pktinfo;
00905         else
00906                 pktinfo = NULL;
00907 
00908         if (client->dispatch != NULL) {
00909                 dispdscp = dns_dispatch_getdscp(client->dispatch);
00910                 if (dispdscp != -1)
00911                         client->dscp = dispdscp;
00912         }
00913 
00914         if (client->dscp == -1) {
00915                 client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
00916                 client->sendevent->dscp = 0;
00917         } else {
00918                 client->sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
00919                 client->sendevent->dscp = client->dscp;
00920         }
00921 
00922         isc_buffer_usedregion(buffer, &r);
00923 
00924         CTRACE("sendto");
00925 
00926         result = isc_socket_sendto2(sock, &r, client->task,
00927                                     address, pktinfo,
00928                                     client->sendevent, sockflags);
00929         if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
00930                 client->nsends++;
00931                 if (result == ISC_R_SUCCESS)
00932                         client_senddone(client->task,
00933                                         (isc_event_t *)client->sendevent);
00934                 result = ISC_R_SUCCESS;
00935         }
00936         return (result);
00937 }
00938 
00939 void
00940 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
00941         isc_result_t result;
00942         unsigned char *data;
00943         isc_buffer_t buffer;
00944         isc_region_t r;
00945         isc_region_t *mr;
00946         unsigned char sendbuf[SEND_BUFFER_SIZE];
00947 
00948         REQUIRE(NS_CLIENT_VALID(client));
00949 
00950         CTRACE("sendraw");
00951 
00952         mr = dns_message_getrawmessage(message);
00953         if (mr == NULL) {
00954                 result = ISC_R_UNEXPECTEDEND;
00955                 goto done;
00956         }
00957 
00958         result = client_allocsendbuf(client, &buffer, NULL, mr->length,
00959                                      sendbuf, &data);
00960         if (result != ISC_R_SUCCESS)
00961                 goto done;
00962 
00963         /*
00964          * Copy message to buffer and fixup id.
00965          */
00966         isc_buffer_availableregion(&buffer, &r);
00967         result = isc_buffer_copyregion(&buffer, mr);
00968         if (result != ISC_R_SUCCESS)
00969                 goto done;
00970         r.base[0] = (client->message->id >> 8) & 0xff;
00971         r.base[1] = client->message->id & 0xff;
00972 
00973         result = client_sendpkg(client, &buffer);
00974         if (result == ISC_R_SUCCESS)
00975                 return;
00976 
00977  done:
00978         if (client->tcpbuf != NULL) {
00979                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
00980                 client->tcpbuf = NULL;
00981         }
00982         ns_client_next(client, result);
00983 }
00984 
00985 static void
00986 client_send(ns_client_t *client) {
00987         isc_result_t result;
00988         unsigned char *data;
00989         isc_buffer_t buffer;
00990         isc_buffer_t tcpbuffer;
00991         isc_region_t r;
00992         dns_compress_t cctx;
00993         isc_boolean_t cleanup_cctx = ISC_FALSE;
00994         unsigned char sendbuf[SEND_BUFFER_SIZE];
00995         unsigned int render_opts;
00996         unsigned int preferred_glue;
00997         isc_boolean_t opt_included = ISC_FALSE;
00998 
00999         REQUIRE(NS_CLIENT_VALID(client));
01000 
01001         CTRACE("send");
01002 
01003         if ((client->attributes & NS_CLIENTATTR_RA) != 0)
01004                 client->message->flags |= DNS_MESSAGEFLAG_RA;
01005 
01006         if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
01007                 render_opts = 0;
01008         else
01009                 render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
01010 
01011         preferred_glue = 0;
01012         if (client->view != NULL) {
01013                 if (client->view->preferred_glue == dns_rdatatype_a)
01014                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
01015                 else if (client->view->preferred_glue == dns_rdatatype_aaaa)
01016                         preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
01017         }
01018 
01019 #ifdef ALLOW_FILTER_AAAA
01020         /*
01021          * filter-aaaa-on-v4 yes or break-dnssec option to suppress
01022          * AAAA records.
01023          *
01024          * We already know that request came via IPv4,
01025          * that we have both AAAA and A records,
01026          * and that we either have no signatures that the client wants
01027          * or we are supposed to break DNSSEC.
01028          *
01029          * Override preferred glue if necessary.
01030          */
01031         if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
01032                 render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
01033                 if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
01034                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
01035         }
01036 #endif
01037 
01038         /*
01039          * Create an OPT for our reply.
01040          */
01041         if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
01042                 result = ns_client_addopt(client, client->message,
01043                                           &client->opt);
01044                 if (result != ISC_R_SUCCESS)
01045                         goto done;
01046         }
01047 
01048         /*
01049          * XXXRTH  The following doesn't deal with TCP buffer resizing.
01050          */
01051         result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
01052                                      sendbuf, &data);
01053         if (result != ISC_R_SUCCESS)
01054                 goto done;
01055 
01056         result = dns_compress_init(&cctx, -1, client->mctx);
01057         if (result != ISC_R_SUCCESS)
01058                 goto done;
01059         if (client->peeraddr_valid && client->view != NULL) {
01060                 isc_netaddr_t netaddr;
01061                 dns_name_t *name = NULL;
01062 
01063                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
01064                 if (client->message->tsigkey != NULL)
01065                         name = &client->message->tsigkey->name;
01066                 if (client->view->nocasecompress == NULL ||
01067                     !allowed(&netaddr, name, NULL, 0, NULL,
01068                              client->view->nocasecompress))
01069                 {
01070                         dns_compress_setsensitive(&cctx, ISC_TRUE);
01071                 }
01072         }
01073         cleanup_cctx = ISC_TRUE;
01074 
01075         result = dns_message_renderbegin(client->message, &cctx, &buffer);
01076         if (result != ISC_R_SUCCESS)
01077                 goto done;
01078 
01079         if (client->opt != NULL) {
01080                 result = dns_message_setopt(client->message, client->opt);
01081                 opt_included = ISC_TRUE;
01082                 client->opt = NULL;
01083                 if (result != ISC_R_SUCCESS)
01084                         goto done;
01085         }
01086         result = dns_message_rendersection(client->message,
01087                                            DNS_SECTION_QUESTION, 0);
01088         if (result == ISC_R_NOSPACE) {
01089                 client->message->flags |= DNS_MESSAGEFLAG_TC;
01090                 goto renderend;
01091         }
01092         if (result != ISC_R_SUCCESS)
01093                 goto done;
01094         /*
01095          * Stop after the question if TC was set for rate limiting.
01096          */
01097         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
01098                 goto renderend;
01099         result = dns_message_rendersection(client->message,
01100                                            DNS_SECTION_ANSWER,
01101                                            DNS_MESSAGERENDER_PARTIAL |
01102                                            render_opts);
01103         if (result == ISC_R_NOSPACE) {
01104                 client->message->flags |= DNS_MESSAGEFLAG_TC;
01105                 goto renderend;
01106         }
01107         if (result != ISC_R_SUCCESS)
01108                 goto done;
01109         result = dns_message_rendersection(client->message,
01110                                            DNS_SECTION_AUTHORITY,
01111                                            DNS_MESSAGERENDER_PARTIAL |
01112                                            render_opts);
01113         if (result == ISC_R_NOSPACE) {
01114                 client->message->flags |= DNS_MESSAGEFLAG_TC;
01115                 goto renderend;
01116         }
01117         if (result != ISC_R_SUCCESS)
01118                 goto done;
01119         result = dns_message_rendersection(client->message,
01120                                            DNS_SECTION_ADDITIONAL,
01121                                            preferred_glue | render_opts);
01122         if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
01123                 goto done;
01124  renderend:
01125         result = dns_message_renderend(client->message);
01126 
01127         if (result != ISC_R_SUCCESS)
01128                 goto done;
01129 
01130         if (cleanup_cctx) {
01131                 dns_compress_invalidate(&cctx);
01132                 cleanup_cctx = ISC_FALSE;
01133         }
01134 
01135         if (TCP_CLIENT(client)) {
01136                 isc_buffer_usedregion(&buffer, &r);
01137                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
01138                 isc_buffer_add(&tcpbuffer, r.length);
01139                 result = client_sendpkg(client, &tcpbuffer);
01140         } else
01141                 result = client_sendpkg(client, &buffer);
01142 
01143         /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
01144         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
01145         if (opt_included) {
01146                 isc_stats_increment(ns_g_server->nsstats,
01147                                     dns_nsstatscounter_edns0out);
01148         }
01149         if (client->message->tsigkey != NULL) {
01150                 isc_stats_increment(ns_g_server->nsstats,
01151                                     dns_nsstatscounter_tsigout);
01152         }
01153         if (client->message->sig0key != NULL) {
01154                 isc_stats_increment(ns_g_server->nsstats,
01155                                     dns_nsstatscounter_sig0out);
01156         }
01157         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
01158                 isc_stats_increment(ns_g_server->nsstats,
01159                                     dns_nsstatscounter_truncatedresp);
01160 
01161         if (result == ISC_R_SUCCESS)
01162                 return;
01163 
01164  done:
01165         if (client->tcpbuf != NULL) {
01166                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
01167                 client->tcpbuf = NULL;
01168         }
01169 
01170         if (cleanup_cctx)
01171                 dns_compress_invalidate(&cctx);
01172 
01173         ns_client_next(client, result);
01174 }
01175 
01176 /*
01177  * Completes the sending of a delayed client response.
01178  */
01179 static void
01180 client_delay(isc_task_t *task, isc_event_t *event) {
01181         ns_client_t *client;
01182 
01183         REQUIRE(event != NULL);
01184         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
01185                 event->ev_type == ISC_TIMEREVENT_IDLE);
01186         client = event->ev_arg;
01187         REQUIRE(NS_CLIENT_VALID(client));
01188         REQUIRE(task == client->task);
01189         REQUIRE(client->delaytimer != NULL);
01190 
01191         UNUSED(task);
01192 
01193         CTRACE("client_delay");
01194 
01195         isc_event_free(&event);
01196         isc_timer_detach(&client->delaytimer);
01197 
01198         client_send(client);
01199         ns_client_detach(&client);
01200 }
01201 
01202 void
01203 ns_client_send(ns_client_t *client) {
01204 
01205         /*
01206          * Delay the response by ns_g_delay ms.
01207          */
01208         if (ns_g_delay != 0) {
01209                 ns_client_t *dummy = NULL;
01210                 isc_result_t result;
01211                 isc_interval_t interval;
01212 
01213                 /*
01214                  * Replace ourselves if we have not already been replaced.
01215                  */
01216                 if (!client->mortal) {
01217                         result = ns_client_replace(client);
01218                         if (result != ISC_R_SUCCESS)
01219                                 goto nodelay;
01220                 }
01221 
01222                 ns_client_attach(client, &dummy);
01223                 if (ns_g_delay >= 1000)
01224                         isc_interval_set(&interval, ns_g_delay / 1000,
01225                                          (ns_g_delay % 1000) * 1000000);
01226                 else
01227                         isc_interval_set(&interval, 0, ns_g_delay * 1000000);
01228                 result = isc_timer_create(client->manager->timermgr,
01229                                           isc_timertype_once, NULL, &interval,
01230                                           client->task, client_delay,
01231                                           client, &client->delaytimer);
01232                 if (result == ISC_R_SUCCESS)
01233                         return;
01234 
01235                 ns_client_detach(&dummy);
01236         }
01237 
01238  nodelay:
01239         client_send(client);
01240 }
01241 
01242 #if NS_CLIENT_DROPPORT
01243 #define DROPPORT_NO             0
01244 #define DROPPORT_REQUEST        1
01245 #define DROPPORT_RESPONSE       2
01246 /*%
01247  * ns_client_dropport determines if certain requests / responses
01248  * should be dropped based on the port number.
01249  *
01250  * Returns:
01251  * \li  0:      Don't drop.
01252  * \li  1:      Drop request.
01253  * \li  2:      Drop (error) response.
01254  */
01255 static int
01256 ns_client_dropport(in_port_t port) {
01257         switch (port) {
01258         case 7: /* echo */
01259         case 13: /* daytime */
01260         case 19: /* chargen */
01261         case 37: /* time */
01262                 return (DROPPORT_REQUEST);
01263         case 464: /* kpasswd */
01264                 return (DROPPORT_RESPONSE);
01265         }
01266         return (DROPPORT_NO);
01267 }
01268 #endif
01269 
01270 void
01271 ns_client_error(ns_client_t *client, isc_result_t result) {
01272         dns_rcode_t rcode;
01273         dns_message_t *message;
01274 
01275         REQUIRE(NS_CLIENT_VALID(client));
01276 
01277         CTRACE("error");
01278 
01279         message = client->message;
01280         rcode = dns_result_torcode(result);
01281 
01282 #if NS_CLIENT_DROPPORT
01283         /*
01284          * Don't send FORMERR to ports on the drop port list.
01285          */
01286         if (rcode == dns_rcode_formerr &&
01287             ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
01288             DROPPORT_NO) {
01289                 char buf[64];
01290                 isc_buffer_t b;
01291 
01292                 isc_buffer_init(&b, buf, sizeof(buf) - 1);
01293                 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
01294                         isc_buffer_putstr(&b, "UNKNOWN RCODE");
01295                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
01296                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
01297                               "dropped error (%.*s) response: suspicious port",
01298                               (int)isc_buffer_usedlength(&b), buf);
01299                 ns_client_next(client, ISC_R_SUCCESS);
01300                 return;
01301         }
01302 #endif
01303 
01304         /*
01305          * Try to rate limit error responses.
01306          */
01307         if (client->view != NULL && client->view->rrl != NULL) {
01308                 isc_boolean_t wouldlog;
01309                 char log_buf[DNS_RRL_LOG_BUF_LEN];
01310                 dns_rrl_result_t rrl_result;
01311                 int loglevel;
01312 
01313                 INSIST(rcode != dns_rcode_noerror &&
01314                        rcode != dns_rcode_nxdomain);
01315                 if (ns_g_server->log_queries)
01316                         loglevel = DNS_RRL_LOG_DROP;
01317                 else
01318                         loglevel = ISC_LOG_DEBUG(1);
01319                 wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel);
01320                 rrl_result = dns_rrl(client->view, &client->peeraddr,
01321                                      TCP_CLIENT(client),
01322                                      dns_rdataclass_in, dns_rdatatype_none,
01323                                      NULL, result, client->now,
01324                                      wouldlog, log_buf, sizeof(log_buf));
01325                 if (rrl_result != DNS_RRL_RESULT_OK) {
01326                         /*
01327                          * Log dropped errors in the query category
01328                          * so that they are not lost in silence.
01329                          * Starts of rate-limited bursts are logged in
01330                          * NS_LOGCATEGORY_RRL.
01331                          */
01332                         if (wouldlog) {
01333                                 ns_client_log(client,
01334                                               NS_LOGCATEGORY_QUERY_EERRORS,
01335                                               NS_LOGMODULE_CLIENT,
01336                                               loglevel,
01337                                               "%s", log_buf);
01338                         }
01339                         /*
01340                          * Some error responses cannot be 'slipped',
01341                          * so don't try to slip any error responses.
01342                          */
01343                         if (!client->view->rrl->log_only) {
01344                                 isc_stats_increment(ns_g_server->nsstats,
01345                                                 dns_nsstatscounter_ratedropped);
01346                                 isc_stats_increment(ns_g_server->nsstats,
01347                                                 dns_nsstatscounter_dropped);
01348                                 ns_client_next(client, DNS_R_DROP);
01349                                 return;
01350                         }
01351                 }
01352         }
01353 
01354         /*
01355          * Message may be an in-progress reply that we had trouble
01356          * with, in which case QR will be set.  We need to clear QR before
01357          * calling dns_message_reply() to avoid triggering an assertion.
01358          */
01359         message->flags &= ~DNS_MESSAGEFLAG_QR;
01360         /*
01361          * AA and AD shouldn't be set.
01362          */
01363         message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
01364         result = dns_message_reply(message, ISC_TRUE);
01365         if (result != ISC_R_SUCCESS) {
01366                 /*
01367                  * It could be that we've got a query with a good header,
01368                  * but a bad question section, so we try again with
01369                  * want_question_section set to ISC_FALSE.
01370                  */
01371                 result = dns_message_reply(message, ISC_FALSE);
01372                 if (result != ISC_R_SUCCESS) {
01373                         ns_client_next(client, result);
01374                         return;
01375                 }
01376         }
01377         message->rcode = rcode;
01378 
01379         if (rcode == dns_rcode_formerr) {
01380                 /*
01381                  * FORMERR loop avoidance:  If we sent a FORMERR message
01382                  * with the same ID to the same client less than two
01383                  * seconds ago, assume that we are in an infinite error
01384                  * packet dialog with a server for some protocol whose
01385                  * error responses look enough like DNS queries to
01386                  * elicit a FORMERR response.  Drop a packet to break
01387                  * the loop.
01388                  */
01389                 if (isc_sockaddr_equal(&client->peeraddr,
01390                                        &client->formerrcache.addr) &&
01391                     message->id == client->formerrcache.id &&
01392                     client->requesttime - client->formerrcache.time < 2) {
01393                         /* Drop packet. */
01394                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01395                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
01396                                       "possible error packet loop, "
01397                                       "FORMERR dropped");
01398                         ns_client_next(client, result);
01399                         return;
01400                 }
01401                 client->formerrcache.addr = client->peeraddr;
01402                 client->formerrcache.time = client->requesttime;
01403                 client->formerrcache.id = message->id;
01404         } else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
01405                    client->view != NULL && client->view->fail_ttl != 0 &&
01406                    ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
01407         {
01408                 /*
01409                  * SERVFAIL caching: store qname/qtype of failed queries
01410                  */
01411                 isc_time_t expire;
01412                 isc_interval_t i;
01413                 isc_uint32_t flags = 0;
01414 
01415                 if ((message->flags & DNS_MESSAGEFLAG_CD) != 0)
01416                         flags = NS_FAILCACHE_CD;
01417 
01418                 isc_interval_set(&i, client->view->fail_ttl, 0);
01419                 result = isc_time_nowplusinterval(&expire, &i);
01420                 if (result == ISC_R_SUCCESS)
01421                         dns_badcache_add(client->view->failcache,
01422                                          client->query.qname,
01423                                          client->query.qtype,
01424                                          ISC_TRUE, flags, &expire);
01425         }
01426         ns_client_send(client);
01427 }
01428 
01429 isc_result_t
01430 ns_client_addopt(ns_client_t *client, dns_message_t *message,
01431                  dns_rdataset_t **opt)
01432 {
01433         unsigned char ecs[ECS_SIZE];
01434         char nsid[BUFSIZ], *nsidp;
01435 #ifdef ISC_PLATFORM_USESIT
01436         unsigned char sit[SIT_SIZE];
01437 #endif
01438         isc_result_t result;
01439         dns_view_t *view;
01440         dns_resolver_t *resolver;
01441         isc_uint16_t udpsize;
01442         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
01443         int count = 0;
01444         unsigned int flags;
01445         unsigned char expire[4];
01446 
01447         REQUIRE(NS_CLIENT_VALID(client));
01448         REQUIRE(opt != NULL && *opt == NULL);
01449         REQUIRE(message != NULL);
01450 
01451         view = client->view;
01452         resolver = (view != NULL) ? view->resolver : NULL;
01453         if (resolver != NULL)
01454                 udpsize = dns_resolver_getudpsize(resolver);
01455         else
01456                 udpsize = ns_g_udpsize;
01457 
01458         flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
01459 
01460         /* Set EDNS options if applicable */
01461         if ((client->attributes & NS_CLIENTATTR_WANTNSID) != 0 &&
01462             (ns_g_server->server_id != NULL ||
01463              ns_g_server->server_usehostname)) {
01464                 if (ns_g_server->server_usehostname) {
01465                         result = ns_os_gethostname(nsid, sizeof(nsid));
01466                         if (result != ISC_R_SUCCESS) {
01467                                 goto no_nsid;
01468                         }
01469                         nsidp = nsid;
01470                 } else
01471                         nsidp = ns_g_server->server_id;
01472 
01473                 INSIST(count < DNS_EDNSOPTIONS);
01474                 ednsopts[count].code = DNS_OPT_NSID;
01475                 ednsopts[count].length = (isc_uint16_t)strlen(nsidp);
01476                 ednsopts[count].value = (unsigned char *)nsidp;
01477                 count++;
01478         }
01479  no_nsid:
01480 #ifdef ISC_PLATFORM_USESIT
01481         if ((client->attributes & NS_CLIENTATTR_WANTSIT) != 0) {
01482                 isc_buffer_t buf;
01483                 isc_stdtime_t now;
01484                 isc_uint32_t nonce;
01485 
01486                 isc_buffer_init(&buf, sit, sizeof(sit));
01487                 isc_stdtime_get(&now);
01488                 isc_random_get(&nonce);
01489 
01490                 compute_sit(client, now, nonce, &buf);
01491 
01492                 INSIST(count < DNS_EDNSOPTIONS);
01493                 ednsopts[count].code = DNS_OPT_SIT;
01494                 ednsopts[count].length = SIT_SIZE;
01495                 ednsopts[count].value = sit;
01496                 count++;
01497         }
01498 #endif
01499         if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
01500                 isc_buffer_t buf;
01501 
01502                 INSIST(count < DNS_EDNSOPTIONS);
01503 
01504                 isc_buffer_init(&buf, expire, sizeof(expire));
01505                 isc_buffer_putuint32(&buf, client->expire);
01506                 ednsopts[count].code = DNS_OPT_EXPIRE;
01507                 ednsopts[count].length = 4;
01508                 ednsopts[count].value = expire;
01509                 count++;
01510         }
01511         if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
01512             (client->ecs_addr.family == AF_INET ||
01513              client->ecs_addr.family == AF_INET6))
01514         {
01515                 int i, addrbytes = (client->ecs_addrlen + 7) / 8;
01516                 isc_uint8_t *paddr;
01517                 isc_buffer_t buf;
01518 
01519                 /* Add client subnet option. */
01520                 isc_buffer_init(&buf, ecs, sizeof(ecs));
01521                 if (client->ecs_addr.family == AF_INET)
01522                         isc_buffer_putuint16(&buf, 1);
01523                 else
01524                         isc_buffer_putuint16(&buf, 2);
01525                 isc_buffer_putuint8(&buf, client->ecs_addrlen);
01526                 isc_buffer_putuint8(&buf, client->ecs_scope);
01527 
01528                 paddr = (isc_uint8_t *) &client->ecs_addr.type;
01529                 for (i = 0; i < addrbytes; i++) {
01530                         unsigned char uc;
01531                         uc = paddr[i];
01532                         if (i == addrbytes - 1 &&
01533                             ((client->ecs_addrlen % 8) != 0))
01534                                 uc &= (1U << (8 - (client->ecs_addrlen % 8)));
01535                         isc_buffer_putuint8(&buf, uc);
01536                 }
01537 
01538                 ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
01539                 ednsopts[count].length = addrbytes + 4;
01540                 ednsopts[count].value = ecs;
01541                 count++;
01542         }
01543 
01544         result = dns_message_buildopt(message, opt, 0, udpsize, flags,
01545                                       ednsopts, count);
01546         return (result);
01547 }
01548 
01549 static inline isc_boolean_t
01550 allowed(isc_netaddr_t *addr, dns_name_t *signer,
01551         isc_netaddr_t *ecs_addr, isc_uint8_t ecs_addrlen,
01552         isc_uint8_t *ecs_scope, dns_acl_t *acl)
01553 {
01554         int match;
01555         isc_result_t result;
01556 
01557         if (acl == NULL)
01558                 return (ISC_TRUE);
01559         result = dns_acl_match2(addr, signer, ecs_addr, ecs_addrlen, ecs_scope,
01560                                 acl, &ns_g_server->aclenv, &match, NULL);
01561         if (result == ISC_R_SUCCESS && match > 0)
01562                 return (ISC_TRUE);
01563         return (ISC_FALSE);
01564 }
01565 
01566 /*
01567  * Callback to see if a non-recursive query coming from 'srcaddr' to
01568  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
01569  * delivered to 'myview'.
01570  *
01571  * We run this unlocked as both the view list and the interface list
01572  * are updated when the appropriate task has exclusivity.
01573  */
01574 isc_boolean_t
01575 ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
01576                  isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
01577                  dns_rdataclass_t rdclass, void *arg)
01578 {
01579         dns_view_t *view;
01580         dns_tsigkey_t *key = NULL;
01581         dns_name_t *tsig = NULL;
01582         isc_netaddr_t netsrc;
01583         isc_netaddr_t netdst;
01584 
01585         UNUSED(arg);
01586 
01587         /*
01588          * ns_g_server->interfacemgr is task exclusive locked.
01589          */
01590         if (ns_g_server->interfacemgr == NULL)
01591                 return (ISC_TRUE);
01592 
01593         if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
01594                 return (ISC_FALSE);
01595 
01596         isc_netaddr_fromsockaddr(&netsrc, srcaddr);
01597         isc_netaddr_fromsockaddr(&netdst, dstaddr);
01598 
01599         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
01600              view != NULL;
01601              view = ISC_LIST_NEXT(view, link)) {
01602 
01603                 if (view->matchrecursiveonly)
01604                         continue;
01605 
01606                 if (rdclass != view->rdclass)
01607                         continue;
01608 
01609                 if (mykey != NULL) {
01610                         isc_boolean_t match;
01611                         isc_result_t result;
01612 
01613                         result = dns_view_gettsig(view, &mykey->name, &key);
01614                         if (result != ISC_R_SUCCESS)
01615                                 continue;
01616                         match = dst_key_compare(mykey->key, key->key);
01617                         dns_tsigkey_detach(&key);
01618                         if (!match)
01619                                 continue;
01620                         tsig = dns_tsigkey_identity(mykey);
01621                 }
01622 
01623                 if (allowed(&netsrc, tsig, NULL, 0, NULL,
01624                             view->matchclients) &&
01625                     allowed(&netdst, tsig, NULL, 0, NULL,
01626                             view->matchdestinations))
01627                         break;
01628         }
01629         return (ISC_TF(view == myview));
01630 }
01631 
01632 #ifdef ISC_PLATFORM_USESIT
01633 static void
01634 compute_sit(ns_client_t *client, isc_uint32_t when, isc_uint32_t nonce,
01635             isc_buffer_t *buf)
01636 {
01637 #ifdef AES_SIT
01638         unsigned char digest[ISC_AES_BLOCK_LENGTH];
01639         unsigned char input[4 + 4 + 16];
01640         isc_netaddr_t netaddr;
01641         unsigned char *cp;
01642         unsigned int i;
01643 
01644         memset(input, 0, sizeof(input));
01645         cp = isc_buffer_used(buf);
01646         isc_buffer_putmem(buf, client->cookie, 8);
01647         isc_buffer_putuint32(buf, nonce);
01648         isc_buffer_putuint32(buf, when);
01649         memmove(input, cp, 16);
01650         isc_aes128_crypt(ns_g_server->secret, input, digest);
01651         for (i = 0; i < 8; i++)
01652                 input[i] = digest[i] ^ digest[i + 8];
01653         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
01654         switch (netaddr.family) {
01655         case AF_INET:
01656                 memmove(input + 8, (unsigned char *)&netaddr.type.in, 4);
01657                 memset(input + 12, 0, 4);
01658                 isc_aes128_crypt(ns_g_server->secret, input, digest);
01659                 break;
01660         case AF_INET6:
01661                 memmove(input + 8, (unsigned char *)&netaddr.type.in6, 16);
01662                 isc_aes128_crypt(ns_g_server->secret, input, digest);
01663                 for (i = 0; i < 8; i++)
01664                         input[i + 8] = digest[i] ^ digest[i + 8];
01665                 isc_aes128_crypt(ns_g_server->secret, input + 8, digest);
01666                 break;
01667         }
01668         for (i = 0; i < 8; i++)
01669                 digest[i] ^= digest[i + 8];
01670         isc_buffer_putmem(buf, digest, 8);
01671 #endif
01672 #ifdef HMAC_SHA1_SIT
01673         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
01674         isc_netaddr_t netaddr;
01675         unsigned char *cp;
01676         isc_hmacsha1_t hmacsha1;
01677 
01678         cp = isc_buffer_used(buf);
01679         isc_buffer_putmem(buf, client->cookie, 8);
01680         isc_buffer_putuint32(buf, nonce);
01681         isc_buffer_putuint32(buf, when);
01682 
01683         isc_hmacsha1_init(&hmacsha1,
01684                           ns_g_server->secret,
01685                           ISC_SHA1_DIGESTLENGTH);
01686         isc_hmacsha1_update(&hmacsha1, cp, 16);
01687         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
01688         switch (netaddr.family) {
01689         case AF_INET:
01690                 isc_hmacsha1_update(&hmacsha1,
01691                                     (unsigned char *)&netaddr.type.in, 4);
01692                 break;
01693         case AF_INET6:
01694                 isc_hmacsha1_update(&hmacsha1,
01695                                     (unsigned char *)&netaddr.type.in6, 16);
01696                 break;
01697         }
01698         isc_hmacsha1_update(&hmacsha1, client->cookie, sizeof(client->cookie));
01699         isc_hmacsha1_sign(&hmacsha1, digest, sizeof(digest));
01700         isc_buffer_putmem(buf, digest, 8);
01701         isc_hmacsha1_invalidate(&hmacsha1);
01702 #endif
01703 #ifdef HMAC_SHA256_SIT
01704         unsigned char digest[ISC_SHA256_DIGESTLENGTH];
01705         isc_netaddr_t netaddr;
01706         unsigned char *cp;
01707         isc_hmacsha256_t hmacsha256;
01708 
01709         cp = isc_buffer_used(buf);
01710         isc_buffer_putmem(buf, client->cookie, 8);
01711         isc_buffer_putuint32(buf, nonce);
01712         isc_buffer_putuint32(buf, when);
01713 
01714         isc_hmacsha256_init(&hmacsha256,
01715                             ns_g_server->secret,
01716                             ISC_SHA256_DIGESTLENGTH);
01717         isc_hmacsha256_update(&hmacsha256, cp, 16);
01718         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
01719         switch (netaddr.family) {
01720         case AF_INET:
01721                 isc_hmacsha256_update(&hmacsha256,
01722                                       (unsigned char *)&netaddr.type.in, 4);
01723                 break;
01724         case AF_INET6:
01725                 isc_hmacsha256_update(&hmacsha256,
01726                                       (unsigned char *)&netaddr.type.in6, 16);
01727                 break;
01728         }
01729         isc_hmacsha256_update(&hmacsha256, client->cookie,
01730                               sizeof(client->cookie));
01731         isc_hmacsha256_sign(&hmacsha256, digest, sizeof(digest));
01732         isc_buffer_putmem(buf, digest, 8);
01733         isc_hmacsha256_invalidate(&hmacsha256);
01734 #endif
01735 }
01736 
01737 static void
01738 process_sit(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
01739         unsigned char dbuf[SIT_SIZE];
01740         unsigned char *old;
01741         isc_stdtime_t now;
01742         isc_uint32_t when;
01743         isc_uint32_t nonce;
01744         isc_buffer_t db;
01745 
01746         client->attributes |= NS_CLIENTATTR_WANTSIT;
01747 
01748         isc_stats_increment(ns_g_server->nsstats,
01749                             dns_nsstatscounter_sitopt);
01750 
01751         if (optlen != SIT_SIZE) {
01752                 /*
01753                  * Not our token.
01754                  */
01755                 if (optlen >= 8U)
01756                         memmove(client->cookie, isc_buffer_current(buf), 8);
01757                 else
01758                         memset(client->cookie, 0, 8);
01759                 isc_buffer_forward(buf, (unsigned int)optlen);
01760 
01761                 if (optlen == 8U)
01762                         isc_stats_increment(ns_g_server->nsstats,
01763                                             dns_nsstatscounter_sitnew);
01764                 else
01765                         isc_stats_increment(ns_g_server->nsstats,
01766                                             dns_nsstatscounter_sitbadsize);
01767                 return;
01768         }
01769 
01770         /*
01771          * Process all of the incoming buffer.
01772          */
01773         old = isc_buffer_current(buf);
01774         memmove(client->cookie, old, 8);
01775         isc_buffer_forward(buf, 8);
01776         nonce = isc_buffer_getuint32(buf);
01777         when = isc_buffer_getuint32(buf);
01778         isc_buffer_forward(buf, 8);
01779 
01780         /*
01781          * Allow for a 5 minute clock skew between servers sharing a secret.
01782          * Only accept SIT if we have talked to the client in the last hour.
01783          */
01784         isc_stdtime_get(&now);
01785         if (isc_serial_gt(when, (now + 300)) ||         /* In the future. */
01786             isc_serial_lt(when, (now - 3600))) {        /* In the past. */
01787                 isc_stats_increment(ns_g_server->nsstats,
01788                                     dns_nsstatscounter_sitbadtime);
01789                 return;
01790         }
01791 
01792         isc_buffer_init(&db, dbuf, sizeof(dbuf));
01793         compute_sit(client, when, nonce, &db);
01794 
01795         if (memcmp(old, dbuf, SIT_SIZE) != 0) {
01796                 isc_stats_increment(ns_g_server->nsstats,
01797                                     dns_nsstatscounter_sitnomatch);
01798                 return;
01799         }
01800         isc_stats_increment(ns_g_server->nsstats,
01801                             dns_nsstatscounter_sitmatch);
01802 
01803         client->attributes |= NS_CLIENTATTR_HAVESIT;
01804 }
01805 #endif
01806 
01807 static isc_result_t
01808 process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
01809         isc_uint16_t family;
01810         isc_uint8_t addrlen, addrbytes, scope, *paddr;
01811         isc_netaddr_t caddr;
01812         int i;
01813 
01814         if (optlen < 4U) {
01815                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01816                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
01817                               "EDNS client subnet option too short");
01818                 return (DNS_R_FORMERR);
01819         }
01820 
01821         family = isc_buffer_getuint16(buf);
01822         addrlen = isc_buffer_getuint8(buf);
01823         scope = isc_buffer_getuint8(buf);
01824         optlen -= 4;
01825 
01826         if (scope != 0U) {
01827                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01828                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
01829                               "EDNS client subnet option: invalid scope");
01830                 return (DNS_R_FORMERR);
01831         }
01832 
01833         memset(&caddr, 0, sizeof(caddr));
01834         switch (family) {
01835         case 1:
01836                 if (addrlen > 32U)
01837                         goto invalid_length;
01838                 caddr.family = AF_INET;
01839                 break;
01840         case 2:
01841                 if (addrlen > 128U) {
01842         invalid_length:
01843                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01844                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
01845                                       "EDNS client subnet option: invalid "
01846                                       "address length (%u) for %s",
01847                                       addrlen, family == 1 ? "IPv4" : "IPv6");
01848                         return (DNS_R_FORMERR);
01849                 }
01850                 caddr.family = AF_INET6;
01851                 break;
01852         default:
01853                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01854                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
01855                               "EDNS client subnet option: invalid family");
01856                 return (DNS_R_FORMERR);
01857         }
01858 
01859         addrbytes = (addrlen + 7) / 8;
01860         if (isc_buffer_remaininglength(buf) < addrbytes) {
01861                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
01862                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
01863                               "EDNS client subnet option: address too short");
01864                 return (DNS_R_FORMERR);
01865         }
01866 
01867         paddr = (isc_uint8_t *) &caddr.type;
01868         for (i = 0; i < addrbytes; i++) {
01869                 paddr[i] = isc_buffer_getuint8(buf);
01870                 optlen--;
01871         }
01872 
01873         memmove(&client->ecs_addr, &caddr, sizeof(caddr));
01874         client->ecs_addrlen = addrlen;
01875         client->ecs_scope = 0;
01876         client->attributes |= NS_CLIENTATTR_HAVEECS;
01877 
01878         isc_buffer_forward(buf, (unsigned int)optlen);
01879         return (ISC_R_SUCCESS);
01880 }
01881 
01882 static isc_result_t
01883 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
01884         dns_rdata_t rdata;
01885         isc_buffer_t optbuf;
01886         isc_result_t result;
01887         isc_uint16_t optcode;
01888         isc_uint16_t optlen;
01889 
01890         /*
01891          * Set the client's UDP buffer size.
01892          */
01893         client->udpsize = opt->rdclass;
01894 
01895         /*
01896          * If the requested UDP buffer size is less than 512,
01897          * ignore it and use 512.
01898          */
01899         if (client->udpsize < 512)
01900                 client->udpsize = 512;
01901 
01902         /*
01903          * Get the flags out of the OPT record.
01904          */
01905         client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
01906 
01907         /*
01908          * Do we understand this version of EDNS?
01909          *
01910          * XXXRTH need library support for this!
01911          */
01912         client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
01913         if (client->ednsversion > DNS_EDNS_VERSION) {
01914                 isc_stats_increment(ns_g_server->nsstats,
01915                                     dns_nsstatscounter_badednsver);
01916                 result = ns_client_addopt(client, client->message,
01917                                           &client->opt);
01918                 if (result == ISC_R_SUCCESS)
01919                         result = DNS_R_BADVERS;
01920                 ns_client_error(client, result);
01921                 goto cleanup;
01922         }
01923 
01924         /* Check for NSID request */
01925         result = dns_rdataset_first(opt);
01926         if (result == ISC_R_SUCCESS) {
01927                 dns_rdata_init(&rdata);
01928                 dns_rdataset_current(opt, &rdata);
01929                 isc_buffer_init(&optbuf, rdata.data, rdata.length);
01930                 isc_buffer_add(&optbuf, rdata.length);
01931                 while (isc_buffer_remaininglength(&optbuf) >= 4) {
01932                         optcode = isc_buffer_getuint16(&optbuf);
01933                         optlen = isc_buffer_getuint16(&optbuf);
01934                         switch (optcode) {
01935                         case DNS_OPT_NSID:
01936                                 isc_stats_increment(ns_g_server->nsstats,
01937                                                     dns_nsstatscounter_nsidopt);
01938                                 client->attributes |= NS_CLIENTATTR_WANTNSID;
01939                                 isc_buffer_forward(&optbuf, optlen);
01940                                 break;
01941 #ifdef ISC_PLATFORM_USESIT
01942                         case DNS_OPT_SIT:
01943                                 process_sit(client, &optbuf, optlen);
01944                                 break;
01945 #endif
01946                         case DNS_OPT_EXPIRE:
01947                                 isc_stats_increment(ns_g_server->nsstats,
01948                                                   dns_nsstatscounter_expireopt);
01949                                 client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
01950                                 isc_buffer_forward(&optbuf, optlen);
01951                                 break;
01952                         case DNS_OPT_CLIENT_SUBNET:
01953                                 result = process_ecs(client, &optbuf, optlen);
01954                                 if (result != ISC_R_SUCCESS) {
01955                                         ns_client_error(client, result);
01956                                         goto cleanup;
01957                                 }
01958                                 isc_stats_increment(ns_g_server->nsstats,
01959                                                   dns_nsstatscounter_ecsopt);
01960                                 break;
01961                         default:
01962                                 isc_stats_increment(ns_g_server->nsstats,
01963                                                   dns_nsstatscounter_otheropt);
01964                                 isc_buffer_forward(&optbuf, optlen);
01965                                 break;
01966                         }
01967                 }
01968         }
01969 
01970         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in);
01971         client->attributes |= NS_CLIENTATTR_WANTOPT;
01972 
01973  cleanup:
01974         return (result);
01975 }
01976 
01977 /*
01978  * Handle an incoming request event from the socket (UDP case)
01979  * or tcpmsg (TCP case).
01980  */
01981 static void
01982 client_request(isc_task_t *task, isc_event_t *event) {
01983         ns_client_t *client;
01984         isc_socketevent_t *sevent;
01985         isc_result_t result;
01986         isc_result_t sigresult = ISC_R_SUCCESS;
01987         isc_buffer_t *buffer;
01988         isc_buffer_t tbuffer;
01989         dns_view_t *view;
01990         dns_rdataset_t *opt;
01991         dns_name_t *signame;
01992         isc_boolean_t ra;       /* Recursion available. */
01993         isc_netaddr_t netaddr;
01994         int match;
01995         dns_messageid_t id;
01996         unsigned int flags;
01997         isc_boolean_t notimp;
01998 
01999         REQUIRE(event != NULL);
02000         client = event->ev_arg;
02001         REQUIRE(NS_CLIENT_VALID(client));
02002         REQUIRE(task == client->task);
02003 
02004         INSIST(client->recursionquota == NULL);
02005 
02006         INSIST(client->state == (TCP_CLIENT(client) ?
02007                                        NS_CLIENTSTATE_READING :
02008                                        NS_CLIENTSTATE_READY));
02009 
02010         ns_client_requests++;
02011 
02012         if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
02013                 INSIST(!TCP_CLIENT(client));
02014                 sevent = (isc_socketevent_t *)event;
02015                 REQUIRE(sevent == client->recvevent);
02016                 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
02017                 isc_buffer_add(&tbuffer, sevent->n);
02018                 buffer = &tbuffer;
02019                 result = sevent->result;
02020                 if (result == ISC_R_SUCCESS) {
02021                         client->peeraddr = sevent->address;
02022                         client->peeraddr_valid = ISC_TRUE;
02023                 }
02024                 if ((sevent->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) {
02025                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02026                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(90),
02027                               "received DSCP %d", sevent->dscp);
02028                         if (client->dscp == -1)
02029                                 client->dscp = sevent->dscp;
02030                 }
02031                 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
02032                         client->attributes |= NS_CLIENTATTR_PKTINFO;
02033                         client->pktinfo = sevent->pktinfo;
02034                 }
02035                 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
02036                         client->attributes |= NS_CLIENTATTR_MULTICAST;
02037                 client->nrecvs--;
02038         } else {
02039                 INSIST(TCP_CLIENT(client));
02040                 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
02041                 REQUIRE(event->ev_sender == &client->tcpmsg);
02042                 buffer = &client->tcpmsg.buffer;
02043                 result = client->tcpmsg.result;
02044                 INSIST(client->nreads == 1);
02045                 /*
02046                  * client->peeraddr was set when the connection was accepted.
02047                  */
02048                 client->nreads--;
02049         }
02050 
02051         if (exit_check(client))
02052                 goto cleanup;
02053         client->state = client->newstate = NS_CLIENTSTATE_WORKING;
02054 
02055         isc_task_getcurrenttime(task, &client->requesttime);
02056         client->now = client->requesttime;
02057         isc_time_set(&client->tnow, client->now, 0);
02058 
02059         if (result != ISC_R_SUCCESS) {
02060                 if (TCP_CLIENT(client)) {
02061                         ns_client_next(client, result);
02062                 } else {
02063                         if  (result != ISC_R_CANCELED)
02064                                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
02065                                               NS_LOGMODULE_CLIENT,
02066                                               ISC_LOG_ERROR,
02067                                               "UDP client handler shutting "
02068                                               "down due to fatal receive "
02069                                               "error: %s",
02070                                               isc_result_totext(result));
02071                         isc_task_shutdown(client->task);
02072                 }
02073                 goto cleanup;
02074         }
02075 
02076         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
02077 
02078 #if NS_CLIENT_DROPPORT
02079         if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
02080             DROPPORT_REQUEST) {
02081                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02082                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
02083                               "dropped request: suspicious port");
02084                 ns_client_next(client, ISC_R_SUCCESS);
02085                 goto cleanup;
02086         }
02087 #endif
02088 
02089         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02090                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02091                       "%s request",
02092                       TCP_CLIENT(client) ? "TCP" : "UDP");
02093 
02094         /*
02095          * Check the blackhole ACL for UDP only, since TCP is done in
02096          * client_newconn.
02097          */
02098         if (!TCP_CLIENT(client)) {
02099                 if (ns_g_server->blackholeacl != NULL &&
02100                     dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
02101                                   &ns_g_server->aclenv,
02102                                   &match, NULL) == ISC_R_SUCCESS &&
02103                     match > 0)
02104                 {
02105                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02106                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
02107                                       "blackholed UDP datagram");
02108                         ns_client_next(client, ISC_R_SUCCESS);
02109                         goto cleanup;
02110                 }
02111         }
02112 
02113         /*
02114          * Silently drop multicast requests for the present.
02115          * XXXMPA revisit this as mDNS spec was published.
02116          */
02117         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
02118                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02119                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
02120                               "dropping multicast request");
02121                 ns_client_next(client, DNS_R_REFUSED);
02122                 goto cleanup;
02123         }
02124 
02125         result = dns_message_peekheader(buffer, &id, &flags);
02126         if (result != ISC_R_SUCCESS) {
02127                 /*
02128                  * There isn't enough header to determine whether
02129                  * this was a request or a response.  Drop it.
02130                  */
02131                 ns_client_next(client, result);
02132                 goto cleanup;
02133         }
02134 
02135         /*
02136          * The client object handles requests, not responses.
02137          * If this is a UDP response, forward it to the dispatcher.
02138          * If it's a TCP response, discard it here.
02139          */
02140         if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
02141                 if (TCP_CLIENT(client)) {
02142                         CTRACE("unexpected response");
02143                         ns_client_next(client, DNS_R_FORMERR);
02144                         goto cleanup;
02145                 } else {
02146                         dns_dispatch_importrecv(client->dispatch, event);
02147                         ns_client_next(client, ISC_R_SUCCESS);
02148                         goto cleanup;
02149                 }
02150         }
02151 
02152         /*
02153          * Update some statistics counters.  Don't count responses.
02154          */
02155         if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
02156                 isc_stats_increment(ns_g_server->nsstats,
02157                                     dns_nsstatscounter_requestv4);
02158         } else {
02159                 isc_stats_increment(ns_g_server->nsstats,
02160                                     dns_nsstatscounter_requestv6);
02161         }
02162         if (TCP_CLIENT(client))
02163                 isc_stats_increment(ns_g_server->nsstats,
02164                                     dns_nsstatscounter_requesttcp);
02165 
02166         /*
02167          * It's a request.  Parse it.
02168          */
02169         result = dns_message_parse(client->message, buffer, 0);
02170         if (result != ISC_R_SUCCESS) {
02171                 /*
02172                  * Parsing the request failed.  Send a response
02173                  * (typically FORMERR or SERVFAIL).
02174                  */
02175                 ns_client_error(client, result);
02176                 goto cleanup;
02177         }
02178 
02179         /*
02180          * Pipeline TCP query processing.
02181          */
02182         if (client->message->opcode != dns_opcode_query)
02183                 client->pipelined = ISC_FALSE;
02184         if (TCP_CLIENT(client) && client->pipelined) {
02185                 result = isc_quota_reserve(&ns_g_server->tcpquota);
02186                 if (result == ISC_R_SUCCESS)
02187                         result = ns_client_replace(client);
02188                 if (result != ISC_R_SUCCESS) {
02189                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02190                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
02191                                       "no more TCP clients(read): %s",
02192                                       isc_result_totext(result));
02193                         client->pipelined = ISC_FALSE;
02194                 }
02195         }
02196 
02197         dns_opcodestats_increment(ns_g_server->opcodestats,
02198                                   client->message->opcode);
02199         switch (client->message->opcode) {
02200         case dns_opcode_query:
02201         case dns_opcode_update:
02202         case dns_opcode_notify:
02203                 notimp = ISC_FALSE;
02204                 break;
02205         case dns_opcode_iquery:
02206         default:
02207                 notimp = ISC_TRUE;
02208                 break;
02209         }
02210 
02211         client->message->rcode = dns_rcode_noerror;
02212 
02213         /* RFC1123 section 6.1.3.2 */
02214         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
02215                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
02216 
02217         /*
02218          * Deal with EDNS.
02219          */
02220         if (ns_g_noedns)
02221                 opt = NULL;
02222         else
02223                 opt = dns_message_getopt(client->message);
02224 
02225         client->ecs_addrlen = 0;
02226         client->ecs_scope = 0;
02227 
02228         if (opt != NULL) {
02229                 /*
02230                  * Are we dropping all EDNS queries?
02231                  */
02232                 if (ns_g_dropedns) {
02233                         ns_client_next(client, ISC_R_SUCCESS);
02234                         goto cleanup;
02235                 }
02236                 result = process_opt(client, opt);
02237                 if (result != ISC_R_SUCCESS)
02238                         goto cleanup;
02239         }
02240 
02241         if (client->message->rdclass == 0) {
02242                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02243                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
02244                               "message class could not be determined");
02245                 ns_client_dumpmessage(client,
02246                                       "message class could not be determined");
02247                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
02248                 goto cleanup;
02249         }
02250 
02251         /*
02252          * Determine the destination address.  If the receiving interface is
02253          * bound to a specific address, we simply use it regardless of the
02254          * address family.  All IPv4 queries should fall into this case.
02255          * Otherwise, if this is a TCP query, get the address from the
02256          * receiving socket (this needs a system call and can be heavy).
02257          * For IPv6 UDP queries, we get this from the pktinfo structure (if
02258          * supported).
02259          * If all the attempts fail (this can happen due to memory shortage,
02260          * etc), we regard this as an error for safety.
02261          */
02262         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
02263                 isc_netaddr_fromsockaddr(&client->destaddr,
02264                                          &client->interface->addr);
02265         else {
02266                 isc_sockaddr_t sockaddr;
02267                 result = ISC_R_FAILURE;
02268 
02269                 if (TCP_CLIENT(client))
02270                         result = isc_socket_getsockname(client->tcpsocket,
02271                                                         &sockaddr);
02272                 if (result == ISC_R_SUCCESS)
02273                         isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
02274                 if (result != ISC_R_SUCCESS &&
02275                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
02276                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
02277                         /*
02278                          * XXXJT technically, we should convert the receiving
02279                          * interface ID to a proper scope zone ID.  However,
02280                          * due to the fact there is no standard API for this,
02281                          * we only handle link-local addresses and use the
02282                          * interface index as link ID.  Despite the assumption,
02283                          * it should cover most typical cases.
02284                          */
02285                         isc_netaddr_fromin6(&client->destaddr,
02286                                             &client->pktinfo.ipi6_addr);
02287                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
02288                                 isc_netaddr_setzone(&client->destaddr,
02289                                                 client->pktinfo.ipi6_ifindex);
02290                         result = ISC_R_SUCCESS;
02291                 }
02292                 if (result != ISC_R_SUCCESS) {
02293                         UNEXPECTED_ERROR(__FILE__, __LINE__,
02294                                          "failed to get request's "
02295                                          "destination: %s",
02296                                          isc_result_totext(result));
02297                         ns_client_next(client, ISC_R_SUCCESS);
02298                         goto cleanup;
02299                 }
02300         }
02301 
02302         /*
02303          * Find a view that matches the client's source address.
02304          */
02305         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
02306              view != NULL;
02307              view = ISC_LIST_NEXT(view, link)) {
02308                 if (client->message->rdclass == view->rdclass ||
02309                     client->message->rdclass == dns_rdataclass_any)
02310                 {
02311                         dns_name_t *tsig = NULL;
02312                         isc_netaddr_t *addr = NULL;
02313                         isc_uint8_t *scope = NULL;
02314 
02315                         sigresult = dns_message_rechecksig(client->message,
02316                                                            view);
02317                         if (sigresult == ISC_R_SUCCESS) {
02318                                 dns_tsigkey_t *tsigkey;
02319 
02320                                 tsigkey = client->message->tsigkey;
02321                                 tsig = dns_tsigkey_identity(tsigkey);
02322                         }
02323 
02324                         if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
02325                                 addr = &client->ecs_addr;
02326                                 scope = &client->ecs_scope;
02327                         }
02328 
02329                         if (allowed(&netaddr, tsig, addr, client->ecs_addrlen,
02330                                     scope, view->matchclients) &&
02331                             allowed(&client->destaddr, tsig, NULL,
02332                                     0, NULL, view->matchdestinations) &&
02333                             !(view->matchrecursiveonly &&
02334                             (client->message->flags & DNS_MESSAGEFLAG_RD) == 0))
02335                         {
02336                                 dns_view_attach(view, &client->view);
02337                                 break;
02338                         }
02339                 }
02340         }
02341 
02342         if (view == NULL) {
02343                 char classname[DNS_RDATACLASS_FORMATSIZE];
02344 
02345                 /*
02346                  * Do a dummy TSIG verification attempt so that the
02347                  * response will have a TSIG if the query did, as
02348                  * required by RFC2845.
02349                  */
02350                 isc_buffer_t b;
02351                 isc_region_t *r;
02352 
02353                 dns_message_resetsig(client->message);
02354 
02355                 r = dns_message_getrawmessage(client->message);
02356                 isc_buffer_init(&b, r->base, r->length);
02357                 isc_buffer_add(&b, r->length);
02358                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
02359 
02360                 dns_rdataclass_format(client->message->rdclass, classname,
02361                                       sizeof(classname));
02362                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02363                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
02364                               "no matching view in class '%s'", classname);
02365                 ns_client_dumpmessage(client, "no matching view in class");
02366                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
02367                 goto cleanup;
02368         }
02369 
02370         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02371                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
02372                       "using view '%s'", view->name);
02373 
02374         /*
02375          * Check for a signature.  We log bad signatures regardless of
02376          * whether they ultimately cause the request to be rejected or
02377          * not.  We do not log the lack of a signature unless we are
02378          * debugging.
02379          */
02380         client->signer = NULL;
02381         dns_name_init(&client->signername, NULL);
02382         result = dns_message_signer(client->message, &client->signername);
02383         if (result != ISC_R_NOTFOUND) {
02384                 signame = NULL;
02385                 if (dns_message_gettsig(client->message, &signame) != NULL) {
02386                         isc_stats_increment(ns_g_server->nsstats,
02387                                             dns_nsstatscounter_tsigin);
02388                 } else {
02389                         isc_stats_increment(ns_g_server->nsstats,
02390                                             dns_nsstatscounter_sig0in);
02391                 }
02392 
02393         }
02394         if (result == ISC_R_SUCCESS) {
02395                 char namebuf[DNS_NAME_FORMATSIZE];
02396                 dns_name_format(&client->signername, namebuf, sizeof(namebuf));
02397                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02398                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02399                               "request has valid signature: %s", namebuf);
02400                 client->signer = &client->signername;
02401         } else if (result == ISC_R_NOTFOUND) {
02402                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02403                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02404                               "request is not signed");
02405         } else if (result == DNS_R_NOIDENTITY) {
02406                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02407                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02408                               "request is signed by a nonauthoritative key");
02409         } else {
02410                 char tsigrcode[64];
02411                 isc_buffer_t b;
02412                 dns_rcode_t status;
02413                 isc_result_t tresult;
02414 
02415                 /* There is a signature, but it is bad. */
02416                 isc_stats_increment(ns_g_server->nsstats,
02417                                     dns_nsstatscounter_invalidsig);
02418                 signame = NULL;
02419                 if (dns_message_gettsig(client->message, &signame) != NULL) {
02420                         char namebuf[DNS_NAME_FORMATSIZE];
02421                         char cnamebuf[DNS_NAME_FORMATSIZE];
02422                         dns_name_format(signame, namebuf, sizeof(namebuf));
02423                         status = client->message->tsigstatus;
02424                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
02425                         tresult = dns_tsigrcode_totext(status, &b);
02426                         INSIST(tresult == ISC_R_SUCCESS);
02427                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
02428                         if (client->message->tsigkey->generated) {
02429                                 dns_name_format(client->message->tsigkey->creator,
02430                                                 cnamebuf, sizeof(cnamebuf));
02431                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02432                                               NS_LOGMODULE_CLIENT,
02433                                               ISC_LOG_ERROR,
02434                                               "request has invalid signature: "
02435                                               "TSIG %s (%s): %s (%s)", namebuf,
02436                                               cnamebuf,
02437                                               isc_result_totext(result),
02438                                               tsigrcode);
02439                         } else {
02440                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02441                                               NS_LOGMODULE_CLIENT,
02442                                               ISC_LOG_ERROR,
02443                                               "request has invalid signature: "
02444                                               "TSIG %s: %s (%s)", namebuf,
02445                                               isc_result_totext(result),
02446                                               tsigrcode);
02447                         }
02448                 } else {
02449                         status = client->message->sig0status;
02450                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
02451                         tresult = dns_tsigrcode_totext(status, &b);
02452                         INSIST(tresult == ISC_R_SUCCESS);
02453                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
02454                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02455                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
02456                                       "request has invalid signature: %s (%s)",
02457                                       isc_result_totext(result), tsigrcode);
02458                 }
02459                 /*
02460                  * Accept update messages signed by unknown keys so that
02461                  * update forwarding works transparently through slaves
02462                  * that don't have all the same keys as the master.
02463                  */
02464                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
02465                       client->message->opcode == dns_opcode_update)) {
02466                         ns_client_error(client, sigresult);
02467                         goto cleanup;
02468                 }
02469         }
02470 
02471         /*
02472          * Decide whether recursive service is available to this client.
02473          * We do this here rather than in the query code so that we can
02474          * set the RA bit correctly on all kinds of responses, not just
02475          * responses to ordinary queries.  Note if you can't query the
02476          * cache there is no point in setting RA.
02477          */
02478         ra = ISC_FALSE;
02479         if (client->view->resolver != NULL &&
02480             client->view->recursion == ISC_TRUE &&
02481             ns_client_checkaclsilent(client, NULL,
02482                                      client->view->recursionacl,
02483                                      ISC_TRUE) == ISC_R_SUCCESS &&
02484             ns_client_checkaclsilent(client, NULL,
02485                                      client->view->cacheacl,
02486                                      ISC_TRUE) == ISC_R_SUCCESS &&
02487             ns_client_checkaclsilent(client, &client->destaddr,
02488                                      client->view->recursiononacl,
02489                                      ISC_TRUE) == ISC_R_SUCCESS &&
02490             ns_client_checkaclsilent(client, &client->destaddr,
02491                                      client->view->cacheonacl,
02492                                      ISC_TRUE) == ISC_R_SUCCESS)
02493                 ra = ISC_TRUE;
02494 
02495         if (ra == ISC_TRUE)
02496                 client->attributes |= NS_CLIENTATTR_RA;
02497 
02498         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
02499                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
02500                                              "recursion not available");
02501 
02502         /*
02503          * Adjust maximum UDP response size for this client.
02504          */
02505         if (client->udpsize > 512) {
02506                 dns_peer_t *peer = NULL;
02507                 isc_uint16_t udpsize = view->maxudp;
02508                 (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
02509                 if (peer != NULL)
02510                         dns_peer_getmaxudp(peer, &udpsize);
02511                 if (client->udpsize > udpsize)
02512                         client->udpsize = udpsize;
02513         }
02514 
02515         /*
02516          * Dispatch the request.
02517          */
02518         switch (client->message->opcode) {
02519         case dns_opcode_query:
02520                 CTRACE("query");
02521                 ns_query_start(client);
02522                 break;
02523         case dns_opcode_update:
02524                 CTRACE("update");
02525                 ns_client_settimeout(client, 60);
02526                 ns_update_start(client, sigresult);
02527                 break;
02528         case dns_opcode_notify:
02529                 CTRACE("notify");
02530                 ns_client_settimeout(client, 60);
02531                 ns_notify_start(client);
02532                 break;
02533         case dns_opcode_iquery:
02534                 CTRACE("iquery");
02535                 ns_client_error(client, DNS_R_NOTIMP);
02536                 break;
02537         default:
02538                 CTRACE("unknown opcode");
02539                 ns_client_error(client, DNS_R_NOTIMP);
02540         }
02541 
02542  cleanup:
02543         return;
02544 }
02545 
02546 static void
02547 client_timeout(isc_task_t *task, isc_event_t *event) {
02548         ns_client_t *client;
02549 
02550         REQUIRE(event != NULL);
02551         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
02552                 event->ev_type == ISC_TIMEREVENT_IDLE);
02553         client = event->ev_arg;
02554         REQUIRE(NS_CLIENT_VALID(client));
02555         REQUIRE(task == client->task);
02556         REQUIRE(client->timer != NULL);
02557 
02558         UNUSED(task);
02559 
02560         CTRACE("timeout");
02561 
02562         isc_event_free(&event);
02563 
02564         if (client->shutdown != NULL) {
02565                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
02566                 client->shutdown = NULL;
02567                 client->shutdown_arg = NULL;
02568         }
02569 
02570         if (client->newstate > NS_CLIENTSTATE_READY)
02571                 client->newstate = NS_CLIENTSTATE_READY;
02572         (void)exit_check(client);
02573 }
02574 
02575 static isc_result_t
02576 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
02577         isc_mem_t *clientmctx;
02578         isc_result_t result;
02579 #if NMCTXS > 0
02580         unsigned int nextmctx;
02581 #endif
02582 
02583         MTRACE("clientmctx");
02584 
02585         /*
02586          * Caller must be holding the manager lock.
02587          */
02588         if (ns_g_clienttest) {
02589                 result = isc_mem_create(0, 0, mctxp);
02590                 if (result == ISC_R_SUCCESS)
02591                         isc_mem_setname(*mctxp, "client", NULL);
02592                 return (result);
02593         }
02594 #if NMCTXS > 0
02595         nextmctx = manager->nextmctx++;
02596         if (manager->nextmctx == NMCTXS)
02597                 manager->nextmctx = 0;
02598 
02599         INSIST(nextmctx < NMCTXS);
02600 
02601         clientmctx = manager->mctxpool[nextmctx];
02602         if (clientmctx == NULL) {
02603                 result = isc_mem_create(0, 0, &clientmctx);
02604                 if (result != ISC_R_SUCCESS)
02605                         return (result);
02606                 isc_mem_setname(clientmctx, "client", NULL);
02607 
02608                 manager->mctxpool[nextmctx] = clientmctx;
02609         }
02610 #else
02611         clientmctx = manager->mctx;
02612 #endif
02613 
02614         isc_mem_attach(clientmctx, mctxp);
02615 
02616         return (ISC_R_SUCCESS);
02617 }
02618 
02619 static isc_result_t
02620 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
02621         ns_client_t *client;
02622         isc_result_t result;
02623         isc_mem_t *mctx = NULL;
02624 
02625         /*
02626          * Caller must be holding the manager lock.
02627          *
02628          * Note: creating a client does not add the client to the
02629          * manager's client list or set the client's manager pointer.
02630          * The caller is responsible for that.
02631          */
02632 
02633         REQUIRE(clientp != NULL && *clientp == NULL);
02634 
02635         result = get_clientmctx(manager, &mctx);
02636         if (result != ISC_R_SUCCESS)
02637                 return (result);
02638 
02639         client = isc_mem_get(mctx, sizeof(*client));
02640         if (client == NULL) {
02641                 isc_mem_detach(&mctx);
02642                 return (ISC_R_NOMEMORY);
02643         }
02644         client->mctx = mctx;
02645 
02646         client->task = NULL;
02647         result = isc_task_create(manager->taskmgr, 0, &client->task);
02648         if (result != ISC_R_SUCCESS)
02649                 goto cleanup_client;
02650         isc_task_setname(client->task, "client", client);
02651 
02652         client->timer = NULL;
02653         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
02654                                   NULL, NULL, client->task, client_timeout,
02655                                   client, &client->timer);
02656         if (result != ISC_R_SUCCESS)
02657                 goto cleanup_task;
02658         client->timerset = ISC_FALSE;
02659 
02660         client->delaytimer = NULL;
02661 
02662         client->message = NULL;
02663         result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
02664                                     &client->message);
02665         if (result != ISC_R_SUCCESS)
02666                 goto cleanup_timer;
02667 
02668         /* XXXRTH  Hardwired constants */
02669 
02670         client->sendevent = isc_socket_socketevent(client->mctx, client,
02671                                                    ISC_SOCKEVENT_SENDDONE,
02672                                                    client_senddone, client);
02673         if (client->sendevent == NULL) {
02674                 result = ISC_R_NOMEMORY;
02675                 goto cleanup_message;
02676         }
02677 
02678         client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
02679         if  (client->recvbuf == NULL) {
02680                 result = ISC_R_NOMEMORY;
02681                 goto cleanup_sendevent;
02682         }
02683 
02684         client->recvevent = isc_socket_socketevent(client->mctx, client,
02685                                                    ISC_SOCKEVENT_RECVDONE,
02686                                                    client_request, client);
02687         if (client->recvevent == NULL) {
02688                 result = ISC_R_NOMEMORY;
02689                 goto cleanup_recvbuf;
02690         }
02691 
02692         client->magic = NS_CLIENT_MAGIC;
02693         client->manager = NULL;
02694         client->state = NS_CLIENTSTATE_INACTIVE;
02695         client->newstate = NS_CLIENTSTATE_MAX;
02696         client->naccepts = 0;
02697         client->nreads = 0;
02698         client->nsends = 0;
02699         client->nrecvs = 0;
02700         client->nupdates = 0;
02701         client->nctls = 0;
02702         client->references = 0;
02703         client->attributes = 0;
02704         client->view = NULL;
02705         client->dispatch = NULL;
02706         client->udpsocket = NULL;
02707         client->tcplistener = NULL;
02708         client->tcpsocket = NULL;
02709         client->tcpmsg_valid = ISC_FALSE;
02710         client->tcpbuf = NULL;
02711         client->opt = NULL;
02712         client->udpsize = 512;
02713         client->dscp = -1;
02714         client->extflags = 0;
02715         client->ednsversion = -1;
02716         client->next = NULL;
02717         client->shutdown = NULL;
02718         client->shutdown_arg = NULL;
02719         client->signer = NULL;
02720         dns_name_init(&client->signername, NULL);
02721         client->mortal = ISC_FALSE;
02722         client->pipelined = ISC_FALSE;
02723         client->tcpquota = NULL;
02724         client->recursionquota = NULL;
02725         client->interface = NULL;
02726         client->peeraddr_valid = ISC_FALSE;
02727         client->ecs_addrlen = 0;
02728         client->ecs_scope = 0;
02729 #ifdef ALLOW_FILTER_AAAA
02730         client->filter_aaaa = dns_aaaa_ok;
02731 #endif
02732         client->needshutdown = ns_g_clienttest;
02733 
02734         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
02735                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
02736                        NULL, NULL);
02737         /*
02738          * Initialize FORMERR cache to sentinel value that will not match
02739          * any actual FORMERR response.
02740          */
02741         isc_sockaddr_any(&client->formerrcache.addr);
02742         client->formerrcache.time = 0;
02743         client->formerrcache.id = 0;
02744         ISC_LINK_INIT(client, link);
02745         ISC_LINK_INIT(client, rlink);
02746         ISC_QLINK_INIT(client, ilink);
02747 
02748         /*
02749          * We call the init routines for the various kinds of client here,
02750          * after we have created an otherwise valid client, because some
02751          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
02752          */
02753         result = ns_query_init(client);
02754         if (result != ISC_R_SUCCESS)
02755                 goto cleanup_recvevent;
02756 
02757         result = isc_task_onshutdown(client->task, client_shutdown, client);
02758         if (result != ISC_R_SUCCESS)
02759                 goto cleanup_query;
02760 
02761         CTRACE("create");
02762 
02763         *clientp = client;
02764 
02765         return (ISC_R_SUCCESS);
02766 
02767  cleanup_query:
02768         ns_query_free(client);
02769 
02770  cleanup_recvevent:
02771         isc_event_free((isc_event_t **)&client->recvevent);
02772 
02773  cleanup_recvbuf:
02774         isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
02775 
02776  cleanup_sendevent:
02777         isc_event_free((isc_event_t **)&client->sendevent);
02778 
02779         client->magic = 0;
02780 
02781  cleanup_message:
02782         dns_message_destroy(&client->message);
02783 
02784  cleanup_timer:
02785         isc_timer_detach(&client->timer);
02786 
02787  cleanup_task:
02788         isc_task_detach(&client->task);
02789 
02790  cleanup_client:
02791         isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
02792 
02793         return (result);
02794 }
02795 
02796 static void
02797 client_read(ns_client_t *client) {
02798         isc_result_t result;
02799 
02800         CTRACE("read");
02801 
02802         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
02803                                         client_request, client);
02804         if (result != ISC_R_SUCCESS)
02805                 goto fail;
02806 
02807         /*
02808          * Set a timeout to limit the amount of time we will wait
02809          * for a request on this TCP connection.
02810          */
02811         ns_client_settimeout(client, 30);
02812 
02813         client->state = client->newstate = NS_CLIENTSTATE_READING;
02814         INSIST(client->nreads == 0);
02815         INSIST(client->recursionquota == NULL);
02816         client->nreads++;
02817 
02818         return;
02819  fail:
02820         ns_client_next(client, result);
02821 }
02822 
02823 static void
02824 client_newconn(isc_task_t *task, isc_event_t *event) {
02825         ns_client_t *client = event->ev_arg;
02826         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
02827         isc_result_t result;
02828 
02829         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
02830         REQUIRE(NS_CLIENT_VALID(client));
02831         REQUIRE(client->task == task);
02832 
02833         UNUSED(task);
02834 
02835         INSIST(client->state == NS_CLIENTSTATE_READY);
02836 
02837         INSIST(client->naccepts == 1);
02838         client->naccepts--;
02839 
02840         LOCK(&client->interface->lock);
02841         INSIST(client->interface->ntcpcurrent > 0);
02842         client->interface->ntcpcurrent--;
02843         UNLOCK(&client->interface->lock);
02844 
02845         /*
02846          * We must take ownership of the new socket before the exit
02847          * check to make sure it gets destroyed if we decide to exit.
02848          */
02849         if (nevent->result == ISC_R_SUCCESS) {
02850                 client->tcpsocket = nevent->newsocket;
02851                 isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
02852                 client->state = NS_CLIENTSTATE_READING;
02853                 INSIST(client->recursionquota == NULL);
02854 
02855                 (void)isc_socket_getpeername(client->tcpsocket,
02856                                              &client->peeraddr);
02857                 client->peeraddr_valid = ISC_TRUE;
02858                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02859                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02860                            "new TCP connection");
02861         } else {
02862                 /*
02863                  * XXXRTH  What should we do?  We're trying to accept but
02864                  *         it didn't work.  If we just give up, then TCP
02865                  *         service may eventually stop.
02866                  *
02867                  *         For now, we just go idle.
02868                  *
02869                  *         Going idle is probably the right thing if the
02870                  *         I/O was canceled.
02871                  */
02872                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02873                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
02874                               "accept failed: %s",
02875                               isc_result_totext(nevent->result));
02876         }
02877 
02878         if (exit_check(client))
02879                 goto freeevent;
02880 
02881         if (nevent->result == ISC_R_SUCCESS) {
02882                 int match;
02883                 isc_netaddr_t netaddr;
02884 
02885                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
02886 
02887                 if (ns_g_server->blackholeacl != NULL &&
02888                     dns_acl_match(&netaddr, NULL,
02889                                   ns_g_server->blackholeacl,
02890                                   &ns_g_server->aclenv,
02891                                   &match, NULL) == ISC_R_SUCCESS &&
02892                     match > 0)
02893                 {
02894                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
02895                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
02896                                       "blackholed connection attempt");
02897                         client->newstate = NS_CLIENTSTATE_READY;
02898                         (void)exit_check(client);
02899                         goto freeevent;
02900                 }
02901 
02902                 INSIST(client->tcpmsg_valid == ISC_FALSE);
02903                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
02904                                 &client->tcpmsg);
02905                 client->tcpmsg_valid = ISC_TRUE;
02906 
02907                 /*
02908                  * Let a new client take our place immediately, before
02909                  * we wait for a request packet.  If we don't,
02910                  * telnetting to port 53 (once per CPU) will
02911                  * deny service to legitimate TCP clients.
02912                  */
02913                 client->pipelined = ISC_FALSE;
02914                 result = isc_quota_attach(&ns_g_server->tcpquota,
02915                                           &client->tcpquota);
02916                 if (result == ISC_R_SUCCESS)
02917                         result = ns_client_replace(client);
02918                 if (result != ISC_R_SUCCESS) {
02919                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
02920                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
02921                                       "no more TCP clients(accept): %s",
02922                                       isc_result_totext(result));
02923                 } else if (ns_g_server->keepresporder == NULL ||
02924                            !allowed(&netaddr, NULL, NULL, 0, NULL,
02925                                     ns_g_server->keepresporder)) {
02926                         client->pipelined = ISC_TRUE;
02927                 }
02928 
02929                 client_read(client);
02930         }
02931 
02932  freeevent:
02933         isc_event_free(&event);
02934 }
02935 
02936 static void
02937 client_accept(ns_client_t *client) {
02938         isc_result_t result;
02939 
02940         CTRACE("accept");
02941 
02942         result = isc_socket_accept(client->tcplistener, client->task,
02943                                    client_newconn, client);
02944         if (result != ISC_R_SUCCESS) {
02945                 UNEXPECTED_ERROR(__FILE__, __LINE__,
02946                                  "isc_socket_accept() failed: %s",
02947                                  isc_result_totext(result));
02948                 /*
02949                  * XXXRTH  What should we do?  We're trying to accept but
02950                  *         it didn't work.  If we just give up, then TCP
02951                  *         service may eventually stop.
02952                  *
02953                  *         For now, we just go idle.
02954                  */
02955                 return;
02956         }
02957         INSIST(client->naccepts == 0);
02958         client->naccepts++;
02959         LOCK(&client->interface->lock);
02960         client->interface->ntcpcurrent++;
02961         UNLOCK(&client->interface->lock);
02962 }
02963 
02964 static void
02965 client_udprecv(ns_client_t *client) {
02966         isc_result_t result;
02967         isc_region_t r;
02968 
02969         CTRACE("udprecv");
02970 
02971         r.base = client->recvbuf;
02972         r.length = RECV_BUFFER_SIZE;
02973         result = isc_socket_recv2(client->udpsocket, &r, 1,
02974                                   client->task, client->recvevent, 0);
02975         if (result != ISC_R_SUCCESS) {
02976                 UNEXPECTED_ERROR(__FILE__, __LINE__,
02977                                  "isc_socket_recv2() failed: %s",
02978                                  isc_result_totext(result));
02979                 /*
02980                  * This cannot happen in the current implementation, since
02981                  * isc_socket_recv2() cannot fail if flags == 0.
02982                  *
02983                  * If this does fail, we just go idle.
02984                  */
02985                 return;
02986         }
02987         INSIST(client->nrecvs == 0);
02988         client->nrecvs++;
02989 }
02990 
02991 void
02992 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
02993         REQUIRE(NS_CLIENT_VALID(source));
02994         REQUIRE(targetp != NULL && *targetp == NULL);
02995 
02996         source->references++;
02997         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
02998                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
02999                       "ns_client_attach: ref = %d", source->references);
03000         *targetp = source;
03001 }
03002 
03003 void
03004 ns_client_detach(ns_client_t **clientp) {
03005         ns_client_t *client = *clientp;
03006 
03007         client->references--;
03008         INSIST(client->references >= 0);
03009         *clientp = NULL;
03010         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
03011                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
03012                       "ns_client_detach: ref = %d", client->references);
03013         (void)exit_check(client);
03014 }
03015 
03016 isc_boolean_t
03017 ns_client_shuttingdown(ns_client_t *client) {
03018         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
03019 }
03020 
03021 isc_result_t
03022 ns_client_replace(ns_client_t *client) {
03023         isc_result_t result;
03024         isc_boolean_t tcp;
03025 
03026         CTRACE("replace");
03027 
03028         REQUIRE(client != NULL);
03029         REQUIRE(client->manager != NULL);
03030 
03031         tcp = TCP_CLIENT(client);
03032         if (tcp && client->pipelined) {
03033                 result = get_worker(client->manager, client->interface,
03034                                     client->tcpsocket);
03035         } else {
03036                 result = get_client(client->manager, client->interface,
03037                                     client->dispatch, tcp);
03038         }
03039         if (result != ISC_R_SUCCESS)
03040                 return (result);
03041 
03042         /*
03043          * The responsibility for listening for new requests is hereby
03044          * transferred to the new client.  Therefore, the old client
03045          * should refrain from listening for any more requests.
03046          */
03047         client->mortal = ISC_TRUE;
03048 
03049         return (ISC_R_SUCCESS);
03050 }
03051 
03052 /***
03053  *** Client Manager
03054  ***/
03055 
03056 static void
03057 clientmgr_destroy(ns_clientmgr_t *manager) {
03058 #if NMCTXS > 0
03059         int i;
03060 #endif
03061 
03062         REQUIRE(ISC_LIST_EMPTY(manager->clients));
03063 
03064         MTRACE("clientmgr_destroy");
03065 
03066 #if NMCTXS > 0
03067         for (i = 0; i < NMCTXS; i++) {
03068                 if (manager->mctxpool[i] != NULL)
03069                         isc_mem_detach(&manager->mctxpool[i]);
03070         }
03071 #endif
03072 
03073         ISC_QUEUE_DESTROY(manager->inactive);
03074         DESTROYLOCK(&manager->lock);
03075         DESTROYLOCK(&manager->listlock);
03076         DESTROYLOCK(&manager->reclock);
03077         manager->magic = 0;
03078         isc_mem_put(manager->mctx, manager, sizeof(*manager));
03079 }
03080 
03081 isc_result_t
03082 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
03083                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
03084 {
03085         ns_clientmgr_t *manager;
03086         isc_result_t result;
03087 #if NMCTXS > 0
03088         int i;
03089 #endif
03090 
03091         manager = isc_mem_get(mctx, sizeof(*manager));
03092         if (manager == NULL)
03093                 return (ISC_R_NOMEMORY);
03094 
03095         result = isc_mutex_init(&manager->lock);
03096         if (result != ISC_R_SUCCESS)
03097                 goto cleanup_manager;
03098 
03099         result = isc_mutex_init(&manager->listlock);
03100         if (result != ISC_R_SUCCESS)
03101                 goto cleanup_lock;
03102 
03103         result = isc_mutex_init(&manager->reclock);
03104         if (result != ISC_R_SUCCESS)
03105                 goto cleanup_listlock;
03106 
03107         manager->mctx = mctx;
03108         manager->taskmgr = taskmgr;
03109         manager->timermgr = timermgr;
03110         manager->exiting = ISC_FALSE;
03111         ISC_LIST_INIT(manager->clients);
03112         ISC_LIST_INIT(manager->recursing);
03113         ISC_QUEUE_INIT(manager->inactive, ilink);
03114 #if NMCTXS > 0
03115         manager->nextmctx = 0;
03116         for (i = 0; i < NMCTXS; i++)
03117                 manager->mctxpool[i] = NULL; /* will be created on-demand */
03118 #endif
03119         manager->magic = MANAGER_MAGIC;
03120 
03121         MTRACE("create");
03122 
03123         *managerp = manager;
03124 
03125         return (ISC_R_SUCCESS);
03126 
03127  cleanup_listlock:
03128         (void) isc_mutex_destroy(&manager->listlock);
03129 
03130  cleanup_lock:
03131         (void) isc_mutex_destroy(&manager->lock);
03132 
03133  cleanup_manager:
03134         isc_mem_put(manager->mctx, manager, sizeof(*manager));
03135 
03136         return (result);
03137 }
03138 
03139 void
03140 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
03141         isc_result_t result;
03142         ns_clientmgr_t *manager;
03143         ns_client_t *client;
03144         isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE;
03145 
03146         REQUIRE(managerp != NULL);
03147         manager = *managerp;
03148         REQUIRE(VALID_MANAGER(manager));
03149 
03150         MTRACE("destroy");
03151 
03152         /*
03153          * Check for success because we may already be task-exclusive
03154          * at this point.  Only if we succeed at obtaining an exclusive
03155          * lock now will we need to relinquish it later.
03156          */
03157         result = isc_task_beginexclusive(ns_g_server->task);
03158         if (result == ISC_R_SUCCESS)
03159                 unlock = ISC_TRUE;
03160 
03161         manager->exiting = ISC_TRUE;
03162 
03163         for (client = ISC_LIST_HEAD(manager->clients);
03164              client != NULL;
03165              client = ISC_LIST_NEXT(client, link))
03166                 isc_task_shutdown(client->task);
03167 
03168         if (ISC_LIST_EMPTY(manager->clients))
03169                 need_destroy = ISC_TRUE;
03170 
03171         if (unlock)
03172                 isc_task_endexclusive(ns_g_server->task);
03173 
03174         if (need_destroy)
03175                 clientmgr_destroy(manager);
03176 
03177         *managerp = NULL;
03178 }
03179 
03180 static isc_result_t
03181 get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
03182            dns_dispatch_t *disp, isc_boolean_t tcp)
03183 {
03184         isc_result_t result = ISC_R_SUCCESS;
03185         isc_event_t *ev;
03186         ns_client_t *client;
03187         MTRACE("get client");
03188 
03189         REQUIRE(manager != NULL);
03190 
03191         if (manager->exiting)
03192                 return (ISC_R_SHUTTINGDOWN);
03193 
03194         /*
03195          * Allocate a client.  First try to get a recycled one;
03196          * if that fails, make a new one.
03197          */
03198         client = NULL;
03199         if (!ns_g_clienttest)
03200                 ISC_QUEUE_POP(manager->inactive, ilink, client);
03201 
03202         if (client != NULL)
03203                 MTRACE("recycle");
03204         else {
03205                 MTRACE("create new");
03206 
03207                 LOCK(&manager->lock);
03208                 result = client_create(manager, &client);
03209                 UNLOCK(&manager->lock);
03210                 if (result != ISC_R_SUCCESS)
03211                         return (result);
03212 
03213                 LOCK(&manager->listlock);
03214                 ISC_LIST_APPEND(manager->clients, client, link);
03215                 UNLOCK(&manager->listlock);
03216         }
03217 
03218         client->manager = manager;
03219         ns_interface_attach(ifp, &client->interface);
03220         client->state = NS_CLIENTSTATE_READY;
03221         INSIST(client->recursionquota == NULL);
03222 
03223         client->dscp = ifp->dscp;
03224 
03225         if (tcp) {
03226                 client->attributes |= NS_CLIENTATTR_TCP;
03227                 isc_socket_attach(ifp->tcpsocket,
03228                                   &client->tcplistener);
03229         } else {
03230                 isc_socket_t *sock;
03231 
03232                 dns_dispatch_attach(disp, &client->dispatch);
03233                 sock = dns_dispatch_getsocket(client->dispatch);
03234                 isc_socket_attach(sock, &client->udpsocket);
03235         }
03236 
03237         INSIST(client->nctls == 0);
03238         client->nctls++;
03239         ev = &client->ctlevent;
03240         isc_task_send(client->task, &ev);
03241 
03242         return (ISC_R_SUCCESS);
03243 }
03244 
03245 static isc_result_t
03246 get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock)
03247 {
03248         isc_result_t result = ISC_R_SUCCESS;
03249         isc_event_t *ev;
03250         ns_client_t *client;
03251         MTRACE("get worker");
03252 
03253         REQUIRE(manager != NULL);
03254 
03255         if (manager->exiting)
03256                 return (ISC_R_SHUTTINGDOWN);
03257 
03258         /*
03259          * Allocate a client.  First try to get a recycled one;
03260          * if that fails, make a new one.
03261          */
03262         client = NULL;
03263         if (!ns_g_clienttest)
03264                 ISC_QUEUE_POP(manager->inactive, ilink, client);
03265 
03266         if (client != NULL)
03267                 MTRACE("recycle");
03268         else {
03269                 MTRACE("create new");
03270 
03271                 LOCK(&manager->lock);
03272                 result = client_create(manager, &client);
03273                 UNLOCK(&manager->lock);
03274                 if (result != ISC_R_SUCCESS)
03275                         return (result);
03276 
03277                 LOCK(&manager->listlock);
03278                 ISC_LIST_APPEND(manager->clients, client, link);
03279                 UNLOCK(&manager->listlock);
03280         }
03281 
03282         client->manager = manager;
03283         ns_interface_attach(ifp, &client->interface);
03284         client->newstate = client->state = NS_CLIENTSTATE_WORKING;
03285         INSIST(client->recursionquota == NULL);
03286         client->tcpquota = &ns_g_server->tcpquota;
03287 
03288         client->dscp = ifp->dscp;
03289 
03290         client->attributes |= NS_CLIENTATTR_TCP;
03291         client->pipelined = ISC_TRUE;
03292 
03293         isc_socket_attach(ifp->tcpsocket, &client->tcplistener);
03294         isc_socket_attach(sock, &client->tcpsocket);
03295         isc_socket_setname(client->tcpsocket, "worker-tcp", NULL);
03296         (void)isc_socket_getpeername(client->tcpsocket, &client->peeraddr);
03297         client->peeraddr_valid = ISC_TRUE;
03298 
03299         INSIST(client->tcpmsg_valid == ISC_FALSE);
03300         dns_tcpmsg_init(client->mctx, client->tcpsocket, &client->tcpmsg);
03301         client->tcpmsg_valid = ISC_TRUE;
03302 
03303         INSIST(client->nctls == 0);
03304         client->nctls++;
03305         ev = &client->ctlevent;
03306         isc_task_send(client->task, &ev);
03307 
03308         return (ISC_R_SUCCESS);
03309 }
03310 
03311 isc_result_t
03312 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
03313                            ns_interface_t *ifp, isc_boolean_t tcp)
03314 {
03315         isc_result_t result = ISC_R_SUCCESS;
03316         unsigned int disp;
03317 
03318         REQUIRE(VALID_MANAGER(manager));
03319         REQUIRE(n > 0);
03320 
03321         MTRACE("createclients");
03322 
03323         for (disp = 0; disp < n; disp++) {
03324                 result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);
03325                 if (result != ISC_R_SUCCESS)
03326                         break;
03327         }
03328 
03329         return (result);
03330 }
03331 
03332 isc_sockaddr_t *
03333 ns_client_getsockaddr(ns_client_t *client) {
03334         return (&client->peeraddr);
03335 }
03336 
03337 isc_result_t
03338 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
03339                          dns_acl_t *acl, isc_boolean_t default_allow)
03340 {
03341         isc_result_t result;
03342         isc_netaddr_t tmpnetaddr;
03343         isc_netaddr_t *ecs_addr = NULL;
03344         isc_uint8_t ecs_addrlen = 0;
03345         int match;
03346 
03347         if (acl == NULL) {
03348                 if (default_allow)
03349                         goto allow;
03350                 else
03351                         goto deny;
03352         }
03353 
03354         if (netaddr == NULL) {
03355                 isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
03356                 netaddr = &tmpnetaddr;
03357         }
03358 
03359         if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
03360                 ecs_addr = &client->ecs_addr;
03361                 ecs_addrlen = client->ecs_addrlen;
03362         }
03363 
03364         result = dns_acl_match2(netaddr, client->signer,
03365                                 ecs_addr, ecs_addrlen, NULL, acl,
03366                                 &ns_g_server->aclenv, &match, NULL);
03367 
03368         if (result != ISC_R_SUCCESS)
03369                 goto deny; /* Internal error, already logged. */
03370 
03371         if (match > 0)
03372                 goto allow;
03373         goto deny; /* Negative match or no match. */
03374 
03375  allow:
03376         return (ISC_R_SUCCESS);
03377 
03378  deny:
03379         return (DNS_R_REFUSED);
03380 }
03381 
03382 isc_result_t
03383 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
03384                    const char *opname, dns_acl_t *acl,
03385                    isc_boolean_t default_allow, int log_level)
03386 {
03387         isc_result_t result;
03388         isc_netaddr_t netaddr;
03389 
03390         if (sockaddr != NULL)
03391                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
03392 
03393         result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
03394                                           acl, default_allow);
03395 
03396         if (result == ISC_R_SUCCESS)
03397                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
03398                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
03399                               "%s approved", opname);
03400         else
03401                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
03402                               NS_LOGMODULE_CLIENT,
03403                               log_level, "%s denied", opname);
03404         return (result);
03405 }
03406 
03407 static void
03408 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
03409         if (client->peeraddr_valid)
03410                 isc_sockaddr_format(&client->peeraddr, peerbuf,
03411                                     (unsigned int)len);
03412         else
03413                 snprintf(peerbuf, len, "@%p", client);
03414 }
03415 
03416 void
03417 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
03418                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
03419 {
03420         char msgbuf[4096];
03421         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
03422         char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
03423         const char *viewname = "";
03424         const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
03425         const char *signer = "", *qname = "";
03426         dns_name_t *q = NULL;
03427 
03428         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
03429 
03430         ns_client_name(client, peerbuf, sizeof(peerbuf));
03431 
03432         if (client->signer != NULL) {
03433                 dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
03434                 sep1 = "/key ";
03435                 signer = signerbuf;
03436         }
03437 
03438         q = client->query.origqname != NULL
03439                 ? client->query.origqname : client->query.qname;
03440         if (q != NULL) {
03441                 dns_name_format(q, qnamebuf, sizeof(qnamebuf));
03442                 sep2 = " (";
03443                 sep3 = ")";
03444                 qname = qnamebuf;
03445         }
03446 
03447         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
03448             strcmp(client->view->name, "_default") != 0) {
03449                 sep4 = ": view ";
03450                 viewname = client->view->name;
03451         }
03452 
03453         isc_log_write(ns_g_lctx, category, module, level,
03454                       "client %s%s%s%s%s%s%s%s: %s",
03455                       peerbuf, sep1, signer, sep2, qname, sep3,
03456                       sep4, viewname, msgbuf);
03457 }
03458 
03459 void
03460 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
03461            isc_logmodule_t *module, int level, const char *fmt, ...)
03462 {
03463         va_list ap;
03464 
03465         if (! isc_log_wouldlog(ns_g_lctx, level))
03466                 return;
03467 
03468         va_start(ap, fmt);
03469         ns_client_logv(client, category, module, level, fmt, ap);
03470         va_end(ap);
03471 }
03472 
03473 void
03474 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
03475                  dns_rdataclass_t rdclass, char *buf, size_t len)
03476 {
03477         char namebuf[DNS_NAME_FORMATSIZE];
03478         char typebuf[DNS_RDATATYPE_FORMATSIZE];
03479         char classbuf[DNS_RDATACLASS_FORMATSIZE];
03480 
03481         dns_name_format(name, namebuf, sizeof(namebuf));
03482         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
03483         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
03484         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
03485                        classbuf);
03486 }
03487 
03488 static void
03489 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
03490         isc_buffer_t buffer;
03491         char *buf = NULL;
03492         int len = 1024;
03493         isc_result_t result;
03494 
03495         if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
03496                 return;
03497 
03498         /*
03499          * Note that these are multiline debug messages.  We want a newline
03500          * to appear in the log after each message.
03501          */
03502 
03503         do {
03504                 buf = isc_mem_get(client->mctx, len);
03505                 if (buf == NULL)
03506                         break;
03507                 isc_buffer_init(&buffer, buf, len);
03508                 result = dns_message_totext(client->message,
03509                                             &dns_master_style_debug,
03510                                             0, &buffer);
03511                 if (result == ISC_R_NOSPACE) {
03512                         isc_mem_put(client->mctx, buf, len);
03513                         len += 1024;
03514                 } else if (result == ISC_R_SUCCESS)
03515                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
03516                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
03517                                       "%s\n%.*s", reason,
03518                                        (int)isc_buffer_usedlength(&buffer),
03519                                        buf);
03520         } while (result == ISC_R_NOSPACE);
03521 
03522         if (buf != NULL)
03523                 isc_mem_put(client->mctx, buf, len);
03524 }
03525 
03526 void
03527 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
03528         ns_client_t *client;
03529         char namebuf[DNS_NAME_FORMATSIZE];
03530         char original[DNS_NAME_FORMATSIZE];
03531         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
03532         char typebuf[DNS_RDATATYPE_FORMATSIZE];
03533         char classbuf[DNS_RDATACLASS_FORMATSIZE];
03534         const char *name;
03535         const char *sep;
03536         const char *origfor;
03537         dns_rdataset_t *rdataset;
03538 
03539         REQUIRE(VALID_MANAGER(manager));
03540 
03541         LOCK(&manager->reclock);
03542         client = ISC_LIST_HEAD(manager->recursing);
03543         while (client != NULL) {
03544                 INSIST(client->state == NS_CLIENTSTATE_RECURSING);
03545 
03546                 ns_client_name(client, peerbuf, sizeof(peerbuf));
03547                 if (client->view != NULL &&
03548                     strcmp(client->view->name, "_bind") != 0 &&
03549                     strcmp(client->view->name, "_default") != 0) {
03550                         name = client->view->name;
03551                         sep = ": view ";
03552                 } else {
03553                         name = "";
03554                         sep = "";
03555                 }
03556 
03557                 LOCK(&client->query.fetchlock);
03558                 INSIST(client->query.qname != NULL);
03559                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
03560                 if (client->query.qname != client->query.origqname &&
03561                     client->query.origqname != NULL) {
03562                         origfor = " for ";
03563                         dns_name_format(client->query.origqname, original,
03564                                         sizeof(original));
03565                 } else {
03566                         origfor = "";
03567                         original[0] = '\0';
03568                 }
03569                 rdataset = ISC_LIST_HEAD(client->query.qname->list);
03570                 if (rdataset == NULL && client->query.origqname != NULL)
03571                         rdataset = ISC_LIST_HEAD(client->query.origqname->list);
03572                 if (rdataset != NULL) {
03573                         dns_rdatatype_format(rdataset->type, typebuf,
03574                                              sizeof(typebuf));
03575                         dns_rdataclass_format(rdataset->rdclass, classbuf,
03576                                               sizeof(classbuf));
03577                 } else {
03578                         strcpy(typebuf, "-");
03579                         strcpy(classbuf, "-");
03580                 }
03581                 UNLOCK(&client->query.fetchlock);
03582                 fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
03583                         "requesttime %d\n", peerbuf, sep, name,
03584                         client->message->id, namebuf, typebuf, classbuf,
03585                         origfor, original, client->requesttime);
03586                 client = ISC_LIST_NEXT(client, rlink);
03587         }
03588         UNLOCK(&manager->reclock);
03589 }
03590 
03591 void
03592 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
03593         LOCK(&client->query.fetchlock);
03594         if (client->query.restarts > 0) {
03595                 /*
03596                  * client->query.qname was dynamically allocated.
03597                  */
03598                 dns_message_puttempname(client->message,
03599                                         &client->query.qname);
03600         }
03601         client->query.qname = name;
03602         client->query.attributes &= ~NS_QUERYATTR_REDIRECT;
03603         UNLOCK(&client->query.fetchlock);
03604 }
03605 
03606 isc_result_t
03607 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
03608         ns_client_t *client = (ns_client_t *) ci->data;
03609 
03610         REQUIRE(NS_CLIENT_VALID(client));
03611         REQUIRE(addrp != NULL);
03612 
03613         *addrp = &client->peeraddr;
03614         return (ISC_R_SUCCESS);
03615 }

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