client.c revision 8378b720cd276e0c401fb937ad018593b095bf74
4a979d35776321abc952346ba128d1a3cef730ceAutomatic Updater * Copyright (C) 1999, 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
1633838b8255282d10af15c5c84cee5a51466712Bob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * Important note!
27809a2ee5db141b684e53bf1d94da26e9f92d3aMark Andrews * All client state changes, other than that from idle to listening, occur
ea872078bfa9473cfe9c89b474dae2496377797bDavid Lawrence * as a result of events. This guarantees serialization and avoids the
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * need for locking.
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * If a routine is ever created that allows someone other than the client's
e76d4c91bfadf823f04dcca1c1c5bcc14c67671dAndreas Gustafsson * task to change the client, then the client will have to be locked.
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley#define CTRACE(m) ((void)(m))
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley#define MTRACE(m) ((void)(m))
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews /* Unlocked. */
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews unsigned int magic;
8343d55b3d97923fa444ea9b92aae2ec60ffd40fMark Andrews /* Locked by lock. */
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * Client object states. Ordering is significant: higher-numbered
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * states are generally "more active", meaning that the client can
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * have more dynamically allocated data, outstanding events, etc.
355cc22e32085faeb553fe6c37de69e83b9d5191Andreas Gustafsson * In the list below, any such properties listed for state N
355cc22e32085faeb553fe6c37de69e83b9d5191Andreas Gustafsson * also apply to any state > N.
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * To force the client into a less active state, set client->newstate
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * to that state and call exit_check(). This will cause any
6c6ceac1bc66812f6e0097dcf5fd8b901c3fecd1Andreas Gustafsson * activities defined for higher-numbered states to be aborted.
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * The client object no longer exists.
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * The client object exists and has a task and timer.
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * Its "query" struct and sendbuf are initialized.
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * It is on the client manager's list of inactive clients.
9fbefe0ace2ae7dba287f914b278153004bef428Bob Halley * It has a message and OPT, both in the reset state.
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * The client object is either a TCP or a UDP one, and
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * it is associated with a network interface. It is on the
6c6ceac1bc66812f6e0097dcf5fd8b901c3fecd1Andreas Gustafsson * client manager's list of active clients.
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley * If it is a TCP client object, it has a TCP listener socket
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * and an outstading TCP listen request.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * If it is a UDP client object, it is associated with a
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * dispatch and has an outstanding dispatch request.
e35c1bb3ecd9a6597360b9160b397c8053af69bfDanny Mayer * The client object is a TCP client object that has received
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * outstanding TCP read request. This state is not used for
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * UDP client objects.
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * The client object has received a request and is working
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * on it. It has a view, and it may have any of a non-reset OPT,
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * recursion quota, and an outstanding write request. If it
d5069ac954d067aa45ad395fc338f7e499b834c1David Lawrence * is a UDP client object, it has a dispatch event.
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * Sentinel value used to indicate "no state". When client->newstate
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halley * has this value, we are not attempting to exit the current state.
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Must be greater than any valid state.
0fc87fa2f38df7b293b650deacfa5e6c3d50eff9Bob Halleystatic void clientmgr_destroy(ns_clientmgr_t *manager);
b592e197fe354d7258dc4166fce0a9425a338b0bBob Halleystatic isc_boolean_t exit_check(ns_client_t *client);
b592e197fe354d7258dc4166fce0a9425a338b0bBob Halleystatic void ns_client_endrequest(ns_client_t *client);
b592e197fe354d7258dc4166fce0a9425a338b0bBob Halleystatic void ns_client_checkactive(ns_client_t *client);
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence * Format a human-readable representation of the socket address '*sa'
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * into the character array 'array', which is of size 'size'.
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * The resulting string is guaranteed to be null-terminated.
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrencesockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size)
6fa1cb5754695d550a58c6e8978fda65f5146af7David Lawrence isc_buffer_init(&buf, array, size, ISC_BUFFERTYPE_TEXT);
b592e197fe354d7258dc4166fce0a9425a338b0bBob Halley * Enter the inactive state.
585529aaeb95a71cd3d95df2602a4688fc7c3292David Lawrence * No requests are outstanding.
d3e7d196cd14fc3095ce97846a66cd49fc6fee6dDavid Lawrence ISC_LIST_UNLINK(client->manager->active, client, link);
4d6964d70a114b53a11a3bd778d9b8f5179a7934Bob Halley ISC_LIST_APPEND(client->manager->inactive, client, link);
1d9958c6cc291916010779792f0fbdf6cd5ba368Mark Andrews * Clean up a client object and free its memory.
28b863e609ff2d97b78663b46894494cfa2ea411Mark Andrews * The client is in the inactive state.
1d9958c6cc291916010779792f0fbdf6cd5ba368Mark Andrews isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
28b863e609ff2d97b78663b46894494cfa2ea411Mark Andrews * When "shuttingdown" is true, either the task has received
28b863e609ff2d97b78663b46894494cfa2ea411Mark Andrews * its shutdown event or no shutdown event has ever been
11d732daac76a24a0f3e5948a2758a4b866a0825David Lawrence * set up. Thus, we have no outstanding shutdown
6c6ceac1bc66812f6e0097dcf5fd8b901c3fecd1Andreas Gustafsson * event at this point.
11d732daac76a24a0f3e5948a2758a4b866a0825David Lawrence REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
1d9958c6cc291916010779792f0fbdf6cd5ba368Mark Andrews isc_mem_put(client->mctx, client->sendbuf, SEND_BUFFER_SIZE);
ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ecAndreas Gustafsson INSIST(dns_rdataset_isassociated(client->opt));
ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ecAndreas Gustafsson dns_message_puttemprdataset(client->message, &client->opt);
b38ab99bdc833da490c0ca0cbd05fb9d54dff997Andreas Gustafsson ISC_LIST_UNLINK(*client->list, client, link);
ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ecAndreas Gustafsson isc_mem_put(client->mctx, client, sizeof *client);
6ebd91a0c7f4c62a501b67adce4a6800d8b7dfacAutomatic Updaterset_timeout(ns_client_t *client, unsigned int seconds) {
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews "setting timouet: %s",
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews /* Continue anyway. */
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * Check for a deactivation or shutdown request and take appropriate
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * action. Returns ISC_TRUE if either is in progress; in this case
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * the caller must no longer use the client object as it may have been
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * We need to detach from the view early when shutting down
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * the server to break the following vicious circle:
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * - The resolver will not shut down until the view refcount is zero
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * - The view refcount does not go to zero until all clients detach
aeff7de836558fa8002ab5db35292d2bb6450da8Evan Hunt * - The client does not detach from the view until references is zero
socket =
return (ISC_TRUE);
return (ISC_TRUE);
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);
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
unsigned int version;
goto cleanup_serverlock;
if (version != 0) {
goto cleanup_serverlock;
int match;
match > 0))
goto cleanup_serverlock;
goto cleanup_viewlock;
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 (ISC_R_SUCCESS);
deny:
return (DNS_R_REFUSED);