client.c revision bf08eb90e44ed8717d538442600c4ad11adac61d
c40e033d2170ec5bd55124bbb034528888b1a76fTinderbox User * Copyright (C) 1999 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * copyright notice and this permission notice appear in all copies.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
53f0234c3e3a845245042affb1f20a189d8791b9Automatic Updater * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
c1d7e0562f6a72ecc07ab5140cf2b88183adbd08Francis Dupont#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
76af83c9adb772f7b045c62cf8b411165bfaa5efMark Andrews /* Unlocked. */
c1d7e0562f6a72ecc07ab5140cf2b88183adbd08Francis Dupont unsigned int magic;
8e73941f33fad57111142a62d99717abc001912eMark Andrews /* Locked by lock. */
c1d7e0562f6a72ecc07ab5140cf2b88183adbd08Francis Dupontstatic void clientmgr_destroy(ns_clientmgr_t *manager);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * Important note!
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt * All client state changes, other than that from idle to listening, occur
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * as a result of events. This guarantees serialization and avoids the
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * need for locking.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * If a routine is ever created that allows someone other than the client's
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * task to change the client, then the client will have to be locked.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * Free a client immediately if possible, otherwise start
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * shutting it down and postpone freeing to later.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * When "shuttingdown" is true, either the task has received
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * its shutdown event or no shutdown event has ever been
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * set up. Thus, we have no outstanding shutdown
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * event at this point.
c1d7e0562f6a72ecc07ab5140cf2b88183adbd08Francis Dupont isc_socket_cancel(client->tcplistener, client->task,
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff socket = dns_dispatch_getsocket(client->dispatch);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff isc_socket_cancel(socket, client->task, ISC_SOCKCANCEL_SEND);
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * We need to detach from the view early, because when shutting
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * down the server, resolver shutdown does not begin until
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * happen until the view refcount goes to zero.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff if (!(client->nreads == 0 && client->naccepts == 0 &&
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff client->nsends == 0 && client->nwaiting == 0)) {
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff /* Still waiting for events. */
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff /* We have received our last event. */
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff INSIST(dns_rdataset_isassociated(client->opt));
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff dns_message_puttemprdataset(client->message, &client->opt);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff if (manager->nclients == 0 && manager->exiting)
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff ISC_LIST_UNLINK(manager->clients, client, link);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff isc_mem_put(client->mctx, client, sizeof *client);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * The client's task has received a shutdown event.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graffclient_shutdown(isc_task_t *task, isc_event_t *event) {
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff REQUIRE(event->type == ISC_TASKEVENT_SHUTDOWN);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graffstatic void client_accept(ns_client_t *client);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graffns_client_next(ns_client_t *client, isc_result_t result) {
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * XXXRTH If result != ISC_R_SUCCESS:
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * Log result if there is interest in doing so.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff INSIST(dns_rdataset_isassociated(client->opt));
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff dns_message_puttemprdataset(client->message, &client->opt);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * This client object is supposed to die now, but if we
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * have fewer client objects than planned due to
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * quota exhaustion, don't.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff isc_boolean_t need_another_client = ISC_FALSE;
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt * The UDP client quota is enforced by making
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * requests fail rather than by not listening
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * for new ones. Therefore, there is always a
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * full set of UDP clients listening.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff /* XXX should put in "idle client pool" instead. */
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt * Give the processed dispatch event back to the dispatch.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * This tells the dispatch that we are ready to receive
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * the next event.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence dns_dispatch_freeevent(client->dispatch, client->dispentry,
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * There was an error processing a TCP request.
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * It may have have left the connection out of
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * sync. Close the connection and listen for a
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * There should be no outstanding read
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * request on the TCP socket at this point,
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff * therefore invalidating the tcpmsg is safe.
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Huntclient_senddone(isc_task_t *task, isc_event_t *event) {
bb2d54f1b3654857b8cb0209612ed847afbd9d3cMichael Graff isc_socketevent_t *sevent = (isc_socketevent_t *)event;
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont REQUIRE(sevent->type == ISC_SOCKEVENT_SENDDONE);
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont isc_mempool_put(client->sendbufs, sevent->region.base);
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont * If all of its sendbufs buffers were busy, the client might be
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont * waiting for one to become available.
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont /* XXXRTH need to add exit draining mode. */
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont unsigned char *data;
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews if ((client->attributes & NS_CLIENTATTR_RA) != 0)
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews * We couldn't get memory, but there is at least one
f9c410d93711fbf312a0162f1e2d3f2a5ede69afFrancis Dupont * send outstanding. We arrange to be restarted when a
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews * send completes.
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);
unsigned int version;
if (version != 0) {
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_sendbufs;
return (ISC_R_SUCCESS);
return (result);
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);