diff --git a/bin/lwresd/Makefile.in b/bin/lwresd/Makefile.in index a105cf5f79..f6328905f1 100644 --- a/bin/lwresd/Makefile.in +++ b/bin/lwresd/Makefile.in @@ -36,9 +36,9 @@ LIBS = ${DEPLIBS} \ TARGETS = lwresd -OBJS = main.@O@ client.@O@ +OBJS = main.@O@ client.@O@ process.@O@ -SRCS = main.c client.c +SRCS = main.c client.c process.c @BIND9_MAKE_RULES@ diff --git a/bin/lwresd/client.c b/bin/lwresd/client.c index 3c0e9264e0..8699a45e06 100644 --- a/bin/lwresd/client.c +++ b/bin/lwresd/client.c @@ -67,6 +67,7 @@ clientmgr_can_die(clientmgr_t *cm) if (ISC_LIST_HEAD(cm->running) != NULL) return; + lwres_context_destroy(&cm->lwctx); dns_view_detach(&cm->view); isc_task_detach(&cm->task); } @@ -94,27 +95,30 @@ process_request(client_t *client) switch (pkt.opcode) { case LWRES_OPCODE_GETADDRSBYNAME: + result = process_gabn(client, &b, &pkt); break; case LWRES_OPCODE_GETNAMEBYADDR: + result = process_gnba(client, &b, &pkt); break; case LWRES_OPCODE_NOOP: + result = process_noop(client, &b, &pkt); break; default: printf("Unknown opcode %08x\n", pkt.opcode); goto restart; } - goto restart; /* XXXMLG temporary */ - /* * We're working on something, so stay in the run queue. */ - return; + if (result == ISC_R_SUCCESS) + return; restart: - client->isidle = ISC_TRUE; + printf("restarting client %p...\n", client); + client->state = CLIENT_STATE_IDLE; ISC_LIST_UNLINK(cm->running, client, link); - ISC_LIST_APPEND(cm->idle, client, link); + ISC_LIST_PREPEND(cm->idle, client, link); client_start_recv(cm); } @@ -125,6 +129,9 @@ client_recv(isc_task_t *task, isc_event_t *ev) clientmgr_t *cm = client->clientmgr; isc_socketevent_t *dev = (isc_socketevent_t *)ev; + INSIST(CLIENT_ISRECV(client)); + CLIENT_SETRECVDONE(client); + INSIST((cm->flags & CLIENTMGR_FLAG_RECVPENDING) != 0); cm->flags &= ~CLIENTMGR_FLAG_RECVPENDING; @@ -138,7 +145,7 @@ client_recv(isc_task_t *task, isc_event_t *ev) /* * Go idle. */ - client->isidle = ISC_TRUE; + CLIENT_SETIDLE(client); ISC_LIST_UNLINK(cm->running, client, link); ISC_LIST_APPEND(cm->idle, client, link); @@ -180,7 +187,7 @@ client_start_recv(clientmgr_t *cm) client = ISC_LIST_HEAD(cm->idle); if (client == NULL) return (ISC_R_SUCCESS); - INSIST(client->isidle); + INSIST(CLIENT_ISIDLE(client)); /* * Issue the recv. If it fails, return that it did. @@ -201,7 +208,7 @@ client_start_recv(clientmgr_t *cm) * Remove the client from the idle list, and put it on the running * list. */ - client->isidle = ISC_FALSE; + CLIENT_SETRECV(client); ISC_LIST_UNLINK(cm->idle, client, link); ISC_LIST_APPEND(cm->running, client, link); diff --git a/bin/lwresd/client.h b/bin/lwresd/client.h index 08486b048e..e99ea58f42 100644 --- a/bin/lwresd/client.h +++ b/bin/lwresd/client.h @@ -45,17 +45,76 @@ struct client_s { unsigned char buffer[LWRES_RECVLENGTH]; /* receive buffer */ isc_uint32_t length; /* length recv'd */ - isc_boolean_t isidle; + unsigned int state; ISC_LINK(client_t) link; }; +/* + * Client states. + * + * _IDLE The client is not doing anything at all. + * + * _RECV The client is waiting for data after issuing a socket recv(). + * + * _RECVDONE Data has been received, and is being processed. + * + * _FINDWAIT An adb (or other) request was made that cannot be satisfied + * immediately. An event will wake the client up. + * + * _SEND All data for a response has completed, and a reply was + * sent via a socket send() call. + * + * _SENDDONE The send done event was received. + * + * Badly formatted state table: + * + * IDLE -> RECV when client has a recv() queued. + * + * RECV -> RECVDONE when recvdone event received. + * + * RECVDONE -> SEND if the data for a reply is at hand. + * RECVDONE -> FINDWAIT if more searching is needed, and events will + * eventually wake us up again. + * + * FINDWAIT -> SEND when enough data was received to reply. + * + * SENDDONE -> IDLE when a senddone event was received. + * + * At any time -> IDLE on error. Sometimes this will be -> SEND + * instead, if enough data is on hand to reply with a meaningful + * error. + * + * Packets which are badly formatted may or may not get error returns. + */ +#define CLIENT_STATE_IDLE 1 +#define CLIENT_STATE_RECV 2 +#define CLIENT_STATE_RECVDONE 3 +#define CLIENT_STATE_FINDWAIT 4 +#define CLIENT_STATE_SEND 5 +#define CLIENT_STATE_SENDDONE 6 + +#define CLIENT_ISIDLE(c) ((c)->state == CLIENT_STATE_IDLE) +#define CLIENT_ISRECV(c) ((c)->state == CLIENT_STATE_RECV) +#define CLIENT_ISRECVDONE(c) ((c)->state == CLIENT_STATE_RECVDONE) +#define CLIENT_ISFINDWAIT(c) ((c)->state == CLIENT_STATE_FINDWAIT) +#define CLIENT_ISSEND(c) ((c)->state == CLIENT_STATE_SEND) +#define CLIENT_ISSENDDONE(c) ((c)->state == CLIENT_STATE_SENDDONE) + +#define CLIENT_SETIDLE(c) ((c)->state = CLIENT_STATE_IDLE) +#define CLIENT_SETRECV(c) ((c)->state = CLIENT_STATE_RECV) +#define CLIENT_SETRECVDONE(c) ((c)->state = CLIENT_STATE_RECVDONE) +#define CLIENT_SETFINDWAIT(c) ((c)->state = CLIENT_STATE_FINDWAIT) +#define CLIENT_SETSEND(c) ((c)->state = CLIENT_STATE_SEND) +#define CLIENT_SETSENDDONE(c) ((c)->state = CLIENT_STATE_SENDDONE) + struct clientmgr_s { isc_task_t *task; /* owning task */ isc_socket_t *sock; /* socket to use */ dns_view_t *view; unsigned int flags; isc_event_t sdev; /* shutdown event */ + lwres_context_t *lwctx; /* lightweight proto context */ ISC_LIST(client_t) idle; /* idle client slots */ ISC_LIST(client_t) running; /* running clients */ }; @@ -67,4 +126,11 @@ void client_recv(isc_task_t *, isc_event_t *); void client_shutdown(isc_task_t *, isc_event_t *); isc_result_t client_start_recv(clientmgr_t *); +/* + * Processing functions of various types. + */ +isc_result_t process_gabn(client_t *, lwres_buffer_t *, lwres_lwpacket_t *); +isc_result_t process_gnba(client_t *, lwres_buffer_t *, lwres_lwpacket_t *); +isc_result_t process_noop(client_t *, lwres_buffer_t *, lwres_lwpacket_t *); + #endif /* LWD_CLIENT_H */ diff --git a/bin/lwresd/main.c b/bin/lwresd/main.c index 1062248ff9..af0b53a4bf 100644 --- a/bin/lwresd/main.c +++ b/bin/lwresd/main.c @@ -188,6 +188,21 @@ out: return (result); } +/* + * Wrappers around our memory management stuff, for the lwres functions. + */ +static void * +mem_alloc(void *arg, size_t size) +{ + return (isc_mem_get(arg, size)); +} + +static void +mem_free(void *arg, void *mem, size_t size) +{ + isc_mem_put(arg, mem, size); +} + int main(int argc, char **argv) { @@ -264,7 +279,7 @@ main(int argc, char **argv) for (i = 0 ; i < NTASKS ; i++) { cmgr[i].task = NULL; cmgr[i].sock = sock; - dns_view_attach(view, &cmgr[i].view); + cmgr[i].view = NULL; cmgr[i].flags = 0; ISC_EVENT_INIT(&cmgr[i].sdev, sizeof(isc_event_t), ISC_EVENTATTR_NOPURGE, @@ -274,7 +289,16 @@ main(int argc, char **argv) ISC_LIST_INIT(cmgr[i].idle); ISC_LIST_INIT(cmgr[i].running); result = isc_task_create(taskmgr, mem, 0, &cmgr[i].task); - INSIST(result == ISC_R_SUCCESS); + if (result != ISC_R_SUCCESS) + break; + cmgr[i].lwctx = NULL; + result = lwres_context_create(&cmgr[i].lwctx, mem, + mem_alloc, mem_free); + if (result != ISC_R_SUCCESS) { + isc_task_detach(&cmgr[i].task); + break; + } + dns_view_attach(view, &cmgr[i].view); } INSIST(i > 0); ntasks = i; /* remember how many we managed to create */ @@ -293,7 +317,7 @@ main(int argc, char **argv) client[j].clientmgr = &cmgr[j]; ISC_LINK_INIT(&client[j], link); ISC_LIST_APPEND(cmgr[j].idle, &client[j], link); - client[j].isidle = ISC_TRUE; + CLIENT_SETIDLE(&client[j]); } } INSIST(i > 0); diff --git a/bin/lwresd/process.c b/bin/lwresd/process.c new file mode 100644 index 0000000000..18268483a4 --- /dev/null +++ b/bin/lwresd/process.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "client.h" + +isc_result_t +process_gabn(client_t *client, lwres_buffer_t *b, lwres_lwpacket_t *pkt) +{ + return (ISC_R_NOTIMPLEMENTED); +} + +isc_result_t +process_gnba(client_t *client, lwres_buffer_t *b, lwres_lwpacket_t *pkt) +{ + return (ISC_R_NOTIMPLEMENTED); +} + +isc_result_t +process_noop(client_t *client, lwres_buffer_t *b, lwres_lwpacket_t *pkt) +{ + lwres_lwpacket_t pkt; + + return (ISC_R_NOTIMPLEMENTED); +}