client.c revision 443b9e6e51e5addb020fc4832e84b81a38765328
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Permission to use, copy, modify, and distribute this software for any
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * purpose with or without fee is hereby granted, provided that the above
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * copyright notice and this permission notice appear in all copies.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Important note!
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * All client state changes, other than that from idle to listening, occur
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * as a result of events. This guarantees serialization and avoids the
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * need for locking.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * If a routine is ever created that allows someone other than the client's
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * task to change the client, then the client will have to be locked.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
94bd918b63001277f1b28ae4581645f8a835688fBob Halley /* Unlocked. */
94bd918b63001277f1b28ae4581645f8a835688fBob Halley unsigned int magic;
94bd918b63001277f1b28ae4581645f8a835688fBob Halley /* Locked by lock. */
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Client object states. Ordering is significant: higher-numbered
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * states are generally "more active", meaning that the client can
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * have more dynamically allocated data, outstanding events, etc.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * In the list below, any such properties listed for state N
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * also apply to any state > N.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * To force the client into a less active state, set client->newstate
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * to that state and call exit_check(). This will cause any
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * activities defined for higher-numbered states to be aborted.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client object no longer exists.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client object exists and has a task and timer.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Its "query" struct and sendbuf are initialized.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * It is on the client manager's list of inactive clients.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * It has a message and OPT, both in the reset state.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client object is either a TCP or a UDP one, and
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * it is associated with a network interface. It is on the
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * client manager's list of active clients.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * If it is a TCP client object, it has a TCP listener socket
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * and an outstading TCP listen request.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * If it is a UDP client object, it is associated with a
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * dispatch and has an outstanding dispatch request.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client object is a TCP client object that has received
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * outstanding TCP read request. This state is not used for
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * UDP client objects.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client object has received a request and is working
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * on it. It has a view, and it may have any of a non-reset OPT,
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * recursion quota, and an outstanding write request. If it
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * is a UDP client object, it has a dispatch event.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Sentinel value used to indicate "no state". When client->newstate
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * has this value, we are not attempting to exit the current state.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Must be greater than any valid state.
94bd918b63001277f1b28ae4581645f8a835688fBob Halleystatic void clientmgr_destroy(ns_clientmgr_t *manager);
94bd918b63001277f1b28ae4581645f8a835688fBob Halleystatic isc_boolean_t exit_check(ns_client_t *client);
94bd918b63001277f1b28ae4581645f8a835688fBob Halleystatic void ns_client_endrequest(ns_client_t *client);
94bd918b63001277f1b28ae4581645f8a835688fBob Halleystatic void ns_client_checkactive(ns_client_t *client);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Format a human-readable representation of the socket address '*sa'
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * into the character array 'array', which is of size 'size'.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The resulting string is guaranteed to be null-terminated.
94bd918b63001277f1b28ae4581645f8a835688fBob Halleysockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size)
94bd918b63001277f1b28ae4581645f8a835688fBob Halley isc_buffer_init(&buf, array, size, ISC_BUFFERTYPE_TEXT);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Enter the inactive state.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * No requests are outstanding.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley ISC_LIST_UNLINK(client->manager->active, client, link);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley ISC_LIST_APPEND(client->manager->inactive, client, link);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Clean up a client object and free its memory.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * The client is in the inactive state.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * When "shuttingdown" is true, either the task has received
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * its shutdown event or no shutdown event has ever been
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * set up. Thus, we have no outstanding shutdown
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * event at this point.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley isc_mem_put(client->mctx, client->sendbuf, SEND_BUFFER_SIZE);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley dns_message_puttemprdataset(client->message, &client->opt);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley isc_mem_put(client->mctx, client, sizeof *client);
94bd918b63001277f1b28ae4581645f8a835688fBob Halleyset_timeout(ns_client_t *client, unsigned int seconds) {
94bd918b63001277f1b28ae4581645f8a835688fBob Halley result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
94bd918b63001277f1b28ae4581645f8a835688fBob Halley "setting timouet: %s",
94bd918b63001277f1b28ae4581645f8a835688fBob Halley /* Continue anyway. */
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Check for a deactivation or shutdown request and take appropriate
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * action. Returns ISC_TRUE if either is in progress; in this case
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * the caller must no longer use the client object as it may have been
94bd918b63001277f1b28ae4581645f8a835688fBob Halley INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * We need to detach from the view early when shutting down
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * the server to break the following vicious circle:
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * - The resolver will not shut down until the view refcount is zero
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * - The view refcount does not go to zero until all clients detach
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * - The client does not detach from the view until references is zero
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * - references does not go to zero until the resolver has shut down
94bd918b63001277f1b28ae4581645f8a835688fBob Halley if (client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
94bd918b63001277f1b28ae4581645f8a835688fBob Halley INSIST(client->newstate <= NS_CLIENTSTATE_READING);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * We are trying to abort request processing.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley if (! (client->nsends == 0 && client->references == 0)) {
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * Still waiting for I/O cancel completion.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * or lingering references.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * I/O cancel is complete. Burn down all state
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * related to the current request.
94bd918b63001277f1b28ae4581645f8a835688fBob Halley if (NS_CLIENTSTATE_READING == client->newstate) {
94bd918b63001277f1b28ae4581645f8a835688fBob Halley * We are trying to abort the current TCP connection,
94bd918b63001277f1b28ae4581645f8a835688fBob Halley INSIST(client->newstate <= NS_CLIENTSTATE_READY);
94bd918b63001277f1b28ae4581645f8a835688fBob Halley /* Still waiting for read cancel completion. */
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
if (! need_another_client) {
int newstate;
unsigned char *data;
isc_region_t r;
goto done;
goto done;
DNS_SECTION_QUESTION, 0);
goto done;
DNS_SECTION_ANSWER, 0);
goto renderend;
goto done;
goto renderend;
goto done;
goto done;
goto done;
done:
static inline isc_result_t
return (result);
return (result);
return (result);
return (ISC_R_SUCCESS);
peerbuf);
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
unsigned int version;
goto cleanup_serverlock;
if (version != 0) {
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_viewlock;
ISC_TRUE);
case dns_opcode_query:
case dns_opcode_update:
case dns_opcode_notify:
case dns_opcode_iquery:
static isc_result_t
return (ISC_R_NOMEMORY);
goto cleanup_client;
goto cleanup_task;
goto cleanup_task;
goto cleanup_timer;
goto cleanup_message;
goto cleanup_sendbuf;
return (ISC_R_SUCCESS);
return (result);
goto fail;
fail:
goto freeevent;
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
goto cleanup_manager;
return (ISC_R_SUCCESS);
return (result);
if (need_destroy)
REQUIRE(n > 0);
if (tcp) {
return (result);
int match;
if (default_allow)
goto allow;
goto deny;
if (match > 0)
goto allow;
return (DNS_R_SUCCESS);
deny:
return (DNS_R_REFUSED);