client.c revision 2d1db4e2c0f68df44bd27a530f35f1805c92d619
7d98a1783f222964bcde7d56dab77b822706204dBob Halley * Copyright (C) 1999-2001 Internet Software Consortium.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Permission to use, copy, modify, and distribute this software for any
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * purpose with or without fee is hereby granted, provided that the above
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * copyright notice and this permission notice appear in all copies.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews/* $Id: client.c,v 1.148 2001/02/12 21:45:36 bwelling Exp $ */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#endif /* DNS_OPT_NEWCODES */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Important note!
5fe5a0c02634eaadfcbc3528bf2c184557110a3bAndreas Gustafsson * All client state changes, other than that from idle to listening, occur
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * as a result of events. This guarantees serialization and avoids the
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * need for locking.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * If a routine is ever created that allows someone other than the client's
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * task to change the client, then the client will have to be locked.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#define CTRACE(m) ((void)(m))
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews#define MTRACE(m) ((void)(m))
f2fdfe7c42f3b10f3653f851ce5a0a90ee5ac1f9David Lawrence#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews /* Unlocked. */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews unsigned int magic;
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews /* Locked by lock. */
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Client object states. Ordering is significant: higher-numbered
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * states are generally "more active", meaning that the client can
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * have more dynamically allocated data, outstanding events, etc.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * In the list below, any such properties listed for state N
f2fdfe7c42f3b10f3653f851ce5a0a90ee5ac1f9David Lawrence * also apply to any state > N.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * To force the client into a less active state, set client->newstate
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * to that state and call exit_check(). This will cause any
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * activities defined for higher-numbered states to be aborted.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * The client object no longer exists.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * The client object exists and has a task and timer.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * Its "query" struct and sendbuf are initialized.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * It is on the client manager's list of inactive clients.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * It has a message and OPT, both in the reset state.
f6a9dd2c61911bf4902d6de02a18a31c9d5497f7Mark Andrews * The client object is either a TCP or a UDP one, and
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * it is associated with a network interface. It is on the
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * client manager's list of active clients.
f9aa0a668c059e0fda1b06882c68aaeb4e840e1bDavid Lawrence * If it is a TCP client object, it has a TCP listener socket
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * and an outstanding TCP listen request.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * If it is a UDP client object, it has a UDP listener socket
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * and an outstanding UDP receive request.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * The client object is a TCP client object that has received
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * outstanding TCP read request. This state is not used for
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * UDP client objects.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * The client object has received a request and is working
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * on it. It has a view, and it may have any of a non-reset OPT,
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * recursion quota, and an outstanding write request.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Sentinel value used to indicate "no state". When client->newstate
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * has this value, we are not attempting to exit the current state.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Must be greater than any valid state.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffstatic void clientmgr_destroy(ns_clientmgr_t *manager);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsstatic isc_boolean_t exit_check(ns_client_t *client);
6612c92a77160580a94f3d081bd657f809fb6e86Andreas Gustafssonstatic void ns_client_endrequest(ns_client_t *client);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsstatic void ns_client_checkactive(ns_client_t *client);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsstatic void client_start(isc_task_t *task, isc_event_t *event);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrewsstatic void client_request(isc_task_t *task, isc_event_t *event);
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * Enter the inactive state.
d0aee194aad64f4c4c54933c0250ee58d47212f4Mark Andrews * No requests are outstanding.
#ifdef DNS_OPT_NEWCODES
static isc_boolean_t
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
return (ISC_TRUE);
if (! need_another_client) {
int newstate;
static isc_result_t
unsigned char **datap)
unsigned char *data;
goto done;
goto done;
goto done;
done:
return (result);
static isc_result_t
isc_region_t r;
int match;
match > 0)
return (DNS_R_BLACKHOLED);
return (result);
unsigned char *data;
isc_region_t r;
goto done;
goto done;
goto done;
done:
unsigned char *data;
isc_region_t r;
goto done;
goto done;
goto done;
DNS_SECTION_QUESTION, 0);
goto renderend;
goto done;
DNS_SECTION_ANSWER, 0);
goto renderend;
goto done;
goto renderend;
goto done;
goto done;
goto done;
done:
#ifdef DNS_OPT_NEWCODES
static isc_result_t
int i, sizeneeded = 0;
goto fail1;
for (i=0; i<CLIENT_NUMATTRS; i++) {
goto fail2;
goto fail2;
if (sizeneeded == 0) {
goto fail2;
goto fail2;
goto fail2;
return (result);
static inline isc_result_t
return (result);
return (result);
return (result);
#ifdef DNS_OPT_NEWCODES
return (ISC_R_SUCCESS);
#ifdef DNS_OPT_NEWCODES
case DNS_OPTCODE_ZONE:
goto zonefail1;
&zonebuf,
NULL);
case DNS_OPTCODE_VIEW:
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
goto cleanup_serverlock;
unsigned int version;
#ifdef DNS_OPT_NEWCODES
goto cleanup_serverlock;
if (version != 0) {
goto cleanup_serverlock;
goto cleanup_serverlock;
int match;
match > 0))
isc_buffer_t b;
isc_region_t *r;
sizeof(classname));
goto cleanup_serverlock;
goto cleanup_viewlock;
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;
sizeof(isc_socketevent_t));
goto cleanup_sendbuf;
goto cleanup_sendevent;
sizeof(isc_socketevent_t));
goto cleanup_recvbuf;
#ifdef DNS_OPT_NEWCODES
goto cleanup_recvevent;
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);
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);