client.c revision 83c0ef88159fcae73fdbf8fe04d220c1878cce3e
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2003 Internet Software Consortium.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Permission to use, copy, modify, and/or distribute this software for any
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
1d78c8d7cd619df2255ec52d69b0dd0d8850293fBrian Wellington/* $Id: client.c,v 1.283 2011/11/07 23:03:09 each Exp $ */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Client Routines
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington * Important note!
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * All client state changes, other than that from idle to listening, occur
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * as a result of events. This guarantees serialization and avoids the
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * need for locking.
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington * If a routine is ever created that allows someone other than the client's
0e0e575ec135a983a53c501cf48734b823361ab4Brian Wellington * task to change the client, then the client will have to be locked.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define CTRACE(m) ((void)(m))
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define MTRACE(m) ((void)(m))
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Number of 'mctx pools' for clients. (Should this be configurable?)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * When enabling threads, we use a pool of memory contexts shared by
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * client objects, since concurrent access to a shared context would cause
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * heavy contentions. The above constant is expected to be enough for
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * completely avoiding contentions among threads for an authoritative-only
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * If named with built without thread, simply share manager's context. Using
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * a separate context in this case would simply waste memory.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer/*% nameserver client manager structure */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Unlocked. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int magic;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* The queue object has its own locks */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer client_queue_t inactive; /*%< To be recycled */
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington /* Lock covers manager state. */
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington /* Lock covers the clients list */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer client_list_t clients; /*%< All active clients */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Lock covers the recursing list */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer client_list_t recursing; /*%< Recursing clients */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*%< mctx pool for clients. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * Client object states. Ordering is significant: higher-numbered
cc48bb397fa6ba889f25157840492e68114dec8fBrian Wellington * states are generally "more active", meaning that the client can
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * have more dynamically allocated data, outstanding events, etc.
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * In the list below, any such properties listed for state N
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * also apply to any state > N.
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * To force the client into a less active state, set client->newstate
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * to that state and call exit_check(). This will cause any
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington * activities defined for higher-numbered states to be aborted.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object no longer exists.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object exists and has a task and timer.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * Its "query" struct and sendbuf are initialized.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * It is on the client manager's list of inactive clients.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * It has a message and OPT, both in the reset state.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object is either a TCP or a UDP one, and
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * it is associated with a network interface. It is on the
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * client manager's list of active clients.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * If it is a TCP client object, it has a TCP listener socket
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * and an outstanding TCP listen request.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * If it is a UDP client object, it has a UDP listener socket
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * and an outstanding UDP receive request.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object is a TCP client object that has received
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * outstanding TCP read request. This state is not used for
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * UDP client objects.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object has received a request and is working
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * on it. It has a view, and it may have any of a non-reset OPT,
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * recursion quota, and an outstanding write request.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * The client object is recursing. It will be on the 'recursing'
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * Sentinel value used to indicate "no state". When client->newstate
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * has this value, we are not attempting to exit the current state.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * Must be greater than any valid state.
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * Enable ns_client_dropport() by default.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic void client_accept(ns_client_t *client);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstatic void client_udprecv(ns_client_t *client);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic void clientmgr_destroy(ns_clientmgr_t *manager);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic isc_boolean_t exit_check(ns_client_t *client);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsstatic void ns_client_endrequest(ns_client_t *client);
7ddb4c86a95ab721a70d406821352ce7b730a1bdAndreas Gustafssonstatic void client_start(isc_task_t *task, isc_event_t *event);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic void client_request(isc_task_t *task, isc_event_t *event);
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafssonstatic void ns_client_dumpmessage(ns_client_t *client, const char *reason);
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafssonstatic isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ISC_LIST_APPEND(client->manager->recursing, client, rlink);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerns_client_killoldestquery(ns_client_t *client) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer oldest = ISC_LIST_HEAD(client->manager->recursing);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafssonns_client_settimeout(ns_client_t *client, unsigned int seconds) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington ns_client_log(client, NS_LOGCATEGORY_CLIENT,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence "setting timeout: %s",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Continue anyway. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Check for a deactivation or shutdown request and take appropriate
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * action. Returns ISC_TRUE if either is in progress; in this case
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * the caller must no longer use the client object as it may have been
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST(client->newstate < NS_CLIENTSTATE_RECURSING);
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * We need to detach from the view early when shutting down
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * the server to break the following vicious circle:
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * - The resolver will not shut down until the view refcount is zero
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * - The view refcount does not go to zero until all clients detach
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafsson * - The client does not detach from the view until references is zero
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * - references does not go to zero until the resolver has shut down
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafsson * Keep the view attached until any outstanding updates complete.
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafsson client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafsson if (client->state == NS_CLIENTSTATE_WORKING ||
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST(client->newstate <= NS_CLIENTSTATE_READING);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * Let the update processing complete.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * We are trying to abort request processing.
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson if (! (client->nsends == 0 && client->nrecvs == 0 &&
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson * Still waiting for I/O cancel completion.
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson * or lingering references.
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson * I/O cancel is complete. Burn down all state
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson * related to the current request. Ensure that
93988fb202645e5d06b337b8e3e20765a467149dAndreas Gustafsson * the client is no longer on the recursing list.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * We need to check whether the client is still linked,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * because it may already have been removed from the
e56101fa6876c876d9957c23784b6493cdb05e09Brian Wellington * recursing list by ns_client_killoldestquery()
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (client->state == NS_CLIENTSTATE_RECURSING) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (NS_CLIENTSTATE_READING == client->newstate) {
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson if (client->state == NS_CLIENTSTATE_READING) {
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * We are trying to abort the current TCP connection,
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson INSIST(client->newstate <= NS_CLIENTSTATE_READY);
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson /* Still waiting for read cancel completion. */
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * Now the client is ready to accept a new TCP connection
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * or UDP request, but we may have enough clients doing
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * that already. Check whether this client needs to remain
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * active and force it to go inactive if not.
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * UDP clients go inactive at this point, but TCP clients
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * may remain active if we have fewer active TCP client
b4876b6ddf706977153954507b498baf79a23442Andreas Gustafsson * objects than desired due to an earlier quota exhaustion.
7804502532d6e2eee80083431a22eb5d957f52a0Michael Sawyer if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {
7804502532d6e2eee80083431a22eb5d957f52a0Michael Sawyer * We don't need the client; send it to the inactive
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * queue for recycling.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (client->newstate > NS_CLIENTSTATE_INACTIVE)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if (NS_CLIENTSTATE_READY == client->newstate) {
46e349e515e0b992ecafdc9597f9d5ee0cf81b2aBrian Wellington if (client->state == NS_CLIENTSTATE_READY) {
46e349e515e0b992ecafdc9597f9d5ee0cf81b2aBrian Wellington INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
46e349e515e0b992ecafdc9597f9d5ee0cf81b2aBrian Wellington * We are trying to enter the inactive state.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer isc_socket_cancel(client->tcplistener, client->task,
f900be21902d02418c2c71ffed754fb3f9f54cffMichael Sawyer /* Still waiting for accept cancel completion. */
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson /* Accept cancel is complete. */
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson isc_socket_cancel(client->udpsocket, client->task,
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson /* Still waiting for recv cancel completion. */
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson /* Still waiting for control event to be delivered */
688a4c50c2025a683d8d2bf5bb53a591556df4fcAndreas Gustafsson /* Deactivate the client. */
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer * Put the client on the inactive list. If we are aiming for
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer * the "freed" state, it will be removed from the inactive
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer * list shortly, and we need to keep the manager locked until
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer * that has been done, lest the manager decide to reactivate
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer * the dying client inbetween.
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer ISC_QUEUE_PUSH(manager->inactive, client, ilink);
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer if (client->state == NS_CLIENTSTATE_INACTIVE) {
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer INSIST(client->newstate == NS_CLIENTSTATE_FREED);
d7a2e0511222811b96f2e8757272ee383ec7b5e6Michael Sawyer * We are trying to free the client.
d7a2e0511222811b96f2e8757272ee383ec7b5e6Michael Sawyer * When "shuttingdown" is true, either the task has received
20b6f1e657d049d9fdb251a0846465bff9b95948Andreas Gustafsson * its shutdown event or no shutdown event has ever been
d7a2e0511222811b96f2e8757272ee383ec7b5e6Michael Sawyer * set up. Thus, we have no outstanding shutdown
d7a2e0511222811b96f2e8757272ee383ec7b5e6Michael Sawyer * event at this point.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
20b6f1e657d049d9fdb251a0846465bff9b95948Andreas Gustafsson isc_event_free((isc_event_t **)&client->sendevent);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_event_free((isc_event_t **)&client->recvevent);
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer INSIST(dns_rdataset_isassociated(client->opt));
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer ISC_LIST_UNLINK(manager->clients, client, link);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Detaching the task must be done after unlinking from
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * the manager's lists because the manager accesses
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * client->task.
ee4429e13e08f30c366cdc5d10585388b8a9f212Michael Sawyer * Check that there are no other external references to
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * the memory context.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer * The client's task has received the client's control event
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer * as part of the startup process.
aa2c453d3c6e416b56b29247bedd9a0af2721e93Mark Andrewsclient_start(isc_task_t *task, isc_event_t *event) {
aa2c453d3c6e416b56b29247bedd9a0af2721e93Mark Andrews ns_client_t *client = (ns_client_t *) event->ev_arg;
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer * The client's task has received a shutdown event.
32e783c745299f838dd7cf8ffe2032775a80f1d0Andreas Gustafssonclient_shutdown(isc_task_t *task, isc_event_t *event) {
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
5d20773abcdf9ff3afe14a349413174f94594188Michael Sawyer (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer INSIST(client->state == NS_CLIENTSTATE_WORKING ||
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer INSIST(dns_rdataset_isassociated(client->opt));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer dns_message_puttemprdataset(client->message, &client->opt);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Clear all client attributes that are specific to
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * the request; that's all except the TCP flag.
20b6f1e657d049d9fdb251a0846465bff9b95948Andreas Gustafssonns_client_next(ns_client_t *client, isc_result_t result) {
20b6f1e657d049d9fdb251a0846465bff9b95948Andreas Gustafsson REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
20b6f1e657d049d9fdb251a0846465bff9b95948Andreas Gustafsson client->state == NS_CLIENTSTATE_READING);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
07a926724c0a91d85b85a94441938d0094e88cffMark Andrews "request failed: %s", isc_result_totext(result));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * An error processing a TCP request may have left
07a926724c0a91d85b85a94441938d0094e88cffMark Andrews * the connection out of sync. To be safe, we always
07a926724c0a91d85b85a94441938d0094e88cffMark Andrews * sever the connection when result != ISC_R_SUCCESS.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
e412ae947df6de858883564b8676a9650df70d9aMark Andrewsclient_senddone(isc_task_t *task, isc_event_t *event) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_socketevent_t *sevent = (isc_socketevent_t *) event;
f900be21902d02418c2c71ffed754fb3f9f54cffMichael Sawyer REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
5f01e77fc23fe9665fa2b8acd0a0c5bfbf61d61dBrian Wellington ns_client_log(client, NS_LOGCATEGORY_CLIENT,
5f01e77fc23fe9665fa2b8acd0a0c5bfbf61d61dBrian Wellington "error sending response: %s",
07a926724c0a91d85b85a94441938d0094e88cffMark Andrews isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * We only want to fail with ISC_R_NOSPACE when called from
37e6e0ca1337351642798b1a6aa24ae40bf86399Andreas Gustafsson * ns_client_sendraw() and not when called from ns_client_send(),
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * tcpbuffer is NULL when called from ns_client_sendraw() and
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * length != 0. tcpbuffer != NULL when called from ns_client_send()
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * and length == 0.
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyerclient_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer isc_buffer_t *tcpbuffer, isc_uint32_t length,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char *sendbuf, unsigned char **datap)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char *data;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_buffer_putuint16(buffer, (isc_uint16_t)length);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerclient_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellington unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
e42c402595802edceafbd3e5338dda011fbbcdb6Michael Sawyer isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
6c6a62933dda281cb9193de1d54d4c9e74515f5aMichael Sawyer result = isc_socket_sendto2(socket, &r, client->task,
ad7bb5bff3e796f5648835bf87a203d23d8319e4David Lawrence if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
b266f8fc42702debc6bd89365273223fa89cd8ddBrian Wellingtonns_client_sendraw(ns_client_t *client, dns_message_t *message) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned char *data;
goto done;
goto done;
goto done;
done:
unsigned char *data;
isc_region_t r;
unsigned int render_opts;
unsigned int preferred_glue;
render_opts = 0;
#ifdef ALLOW_FILTER_AAAA_ON_V4
preferred_glue = 0;
goto done;
goto done;
goto done;
goto done;
DNS_SECTION_QUESTION, 0);
goto renderend;
goto done;
goto renderend;
goto done;
goto renderend;
goto done;
goto done;
goto done;
if (cleanup_cctx) {
if (opt_included) {
done:
if (cleanup_cctx)
#define DROPPORT_NO 0
switch (port) {
return (DROPPORT_REQUEST);
return (DROPPORT_RESPONSE);
return (DROPPORT_NO);
DROPPORT_NO) {
isc_buffer_t b;
static inline isc_result_t
return (result);
return (result);
return (result);
goto no_nsid;
goto no_nsid;
== ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
static inline isc_boolean_t
int match;
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
if (!match)
int match;
unsigned int flags;
goto cleanup;
goto cleanup;
goto cleanup;
match > 0)
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
case dns_opcode_query:
case dns_opcode_update:
case dns_opcode_notify:
case dns_opcode_iquery:
goto cleanup;
goto cleanup;
goto cleanup;
&sockaddr);
goto cleanup;
view);
isc_buffer_t b;
isc_region_t *r;
sizeof(classname));
goto cleanup;
isc_buffer_t b;
goto cleanup;
case dns_opcode_query:
case dns_opcode_update:
case dns_opcode_notify:
case dns_opcode_iquery:
static isc_result_t
#if NMCTXS > 0
unsigned int nextmctx;
if (ns_g_clienttest) {
return (result);
#if NMCTXS > 0
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
return (result);
return (ISC_R_NOMEMORY);
goto cleanup_client;
goto cleanup_task;
goto cleanup_timer;
sizeof(isc_socketevent_t));
goto cleanup_message;
goto cleanup_sendevent;
sizeof(isc_socketevent_t));
goto cleanup_recvbuf;
goto cleanup_recvevent;
goto cleanup_query;
return (ISC_R_SUCCESS);
return (result);
goto fail;
fail:
goto freeevent;
int match;
match > 0)
goto freeevent;
isc_region_t r;
return (result);
return (ISC_R_SUCCESS);
#if NMCTXS > 0
#if NMCTXS > 0
for (i = 0; i < NMCTXS; i++) {
#if NMCTXS > 0
return (ISC_R_NOMEMORY);
goto cleanup_manager;
goto cleanup_lock;
goto cleanup_listlock;
#if NMCTXS > 0
for (i = 0; i < NMCTXS; i++)
return (ISC_R_SUCCESS);
return (result);
if (need_destroy)
static isc_result_t
if (!ns_g_clienttest)
return (result);
if (tcp) {
return (ISC_R_SUCCESS);
unsigned int disp;
REQUIRE(n > 0);
return (result);
int match;
if (default_allow)
goto allow;
goto deny;
if (match > 0)
goto allow;
return (ISC_R_SUCCESS);
deny:
return (DNS_R_REFUSED);
return (result);
if (q != NULL) {
classbuf);
0, &buffer);
buf);
const char *name;
const char *sep;
const char *origfor;
sizeof(original));
sizeof(typebuf));
sizeof(classbuf));
return (ISC_R_SUCCESS);