From 60cfce122f8a8af6c992be6c66a1fccac166f771 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Fri, 29 Jan 1999 06:18:43 +0000 Subject: [PATCH] Code up a dispatch() function which will just return server failure for now. This makes dig work, and shows that we can actually transmit as well as receive. Both UDP and TCP connections work, with the restriction that a full message must be contained in each TCP write, not split across two seperate tcp 'packets'. --- bin/named/server.c | 50 ++++++++++++++++++++++++--- bin/named/tcpclient.c | 78 +++++++++++++++++++++++++++++++++++-------- bin/named/tcpclient.h | 6 +++- bin/named/udpclient.c | 54 ++++++++++++++++++++++-------- bin/named/udpclient.h | 6 +++- 5 files changed, 161 insertions(+), 33 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 94864342c3..b1242d75bc 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -51,6 +51,46 @@ isc_mem_t *mctx = NULL; +/* + * Process the wire format message given in r, and return a new packet to + * transmit. + * + * Return of DNS_R_SUCCESS means r->base is a newly allocated region of + * memory, and r->length is its length. The actual for-transmit packet + * begins at (r->length + reslen) to reserve (reslen) bytes at the front + * of the packet for transmission specific details. + */ +static dns_result_t +dispatch(isc_mem_t *mctx, isc_region_t *rxr, unsigned int reslen) +{ + isc_region_t txr; + unsigned char *cp; + + /* + * XXX for now, just SERVFAIL everything. + */ + txr.length = rxr->length + reslen; + txr.base = isc_mem_get(mctx, txr.length); + if (txr.base == NULL) + return (DNS_R_NOMEMORY); + + memcpy(txr.base + reslen, rxr->base, rxr->length); + + cp = txr.base + reslen; + cp += 2; + *cp |= 0x80; /* set QR to response */ + *cp++ &= 0xf9; /* clear AA, TC */ + *cp++ = 2; /* SERVFAIL */ + + rxr->base = txr.base; + rxr->length = txr.length; + + isc_mem_stats(mctx, stdout); + + return (DNS_R_SUCCESS); +} + + int main(int argc, char *argv[]) { @@ -95,8 +135,9 @@ main(int argc, char *argv[]) (int)addrlen) == ISC_R_SUCCESS); ludp = udp_listener_allocate(mctx, workers); - RUNTIME_CHECK(udp_listener_start(ludp, so0, manager, workers, - workers, 0) == ISC_R_SUCCESS); + RUNTIME_CHECK(udp_listener_start(ludp, so0, manager, + workers, workers, 0, + dispatch) == ISC_R_SUCCESS); isc_mem_stats(mctx, stdout); @@ -114,8 +155,9 @@ main(int argc, char *argv[]) (int)addrlen) == ISC_R_SUCCESS); ltcp = tcp_listener_allocate(mctx, workers); - RUNTIME_CHECK(tcp_listener_start(ltcp, so1, manager, workers, - workers, 0) == ISC_R_SUCCESS); + RUNTIME_CHECK(tcp_listener_start(ltcp, so1, manager, + workers, workers, 0, + dispatch) == ISC_R_SUCCESS); isc_mem_stats(mctx, stdout); diff --git a/bin/named/tcpclient.c b/bin/named/tcpclient.c index a2652ad644..c4fdcb7477 100644 --- a/bin/named/tcpclient.c +++ b/bin/named/tcpclient.c @@ -202,6 +202,9 @@ tcp_recv_req(isc_task_t *task, isc_event_t *event) isc_socketevent_t *dev; tcp_cctx_t *ctx; isc_region_t region; + unsigned char *cp; + isc_uint16_t len; + dns_result_t result; sock = event->sender; dev = (isc_socketevent_t *)event; @@ -236,18 +239,37 @@ tcp_recv_req(isc_task_t *task, isc_event_t *event) dump_packet(ctx->buf, dev->n); /* - * release memory + * Call the dispatch() function to actually process this packet. + * If it returns ISC_R_SUCCESS, we have a packet to transmit. + * do so. If it returns anything else, drop this connection. */ - isc_mem_put(ctx->mctx, ctx->buf, ctx->buflen); + region.base = ctx->buf; + region.length = dev->n; + result = ctx->parent->dispatch(ctx->mctx, ®ion, 2); + isc_mem_put(ctx->mctx, ctx->buf, ctx->buflen); /* clean up request */ ctx->buf = NULL; /* - * Queue up another receive. + * Failure. Close TCP client. */ - region.base = (unsigned char *)&ctx->buflen; - region.length = 2; - isc_socket_recv(sock, ®ion, ISC_FALSE, - task, tcp_recv_len, event->arg); + if (result != DNS_R_SUCCESS) { + tcp_restart(task, ctx); + + isc_event_free(&event); + + return; + } + + /* + * Success. Send the packet, after filling in the length at the + * front of the packet. + */ + len = region.length - 2; + cp = region.base; + *cp++ = (len & 0xff00) >> 8; + *cp++ = (len & 0x00ff); + + isc_socket_send(sock, ®ion, task, tcp_send, ctx); isc_event_free(&event); } @@ -308,16 +330,43 @@ tcp_send(isc_task_t *task, isc_event_t *event) { isc_socket_t *sock; isc_socketevent_t *dev; + tcp_cctx_t *ctx; + isc_region_t region; sock = event->sender; dev = (isc_socketevent_t *)event; + ctx = (tcp_cctx_t *)(event->arg); - printf("my_send: %s task %p\n\t(sock %p, base %p, length %d, n %d, result %d)\n", - (char *)(event->arg), task, sock, - dev->region.base, dev->region.length, + printf("tcp_send: task %u\n\t(base %p, length %d, n %d, result %d)\n", + ctx->slot, dev->region.base, dev->region.length, dev->n, dev->result); - isc_mem_put(event->mctx, dev->region.base, dev->region.length); + /* + * release memory regardless of outcome. + */ + isc_mem_put(ctx->mctx, dev->region.base, dev->region.length); + + if (dev->result == ISC_R_CANCELED) { + isc_task_shutdown(task); + + isc_event_free(&event); + + return; + } + if (dev->result != ISC_R_SUCCESS) { + tcp_restart(task, ctx); + + isc_event_free(&event); + + return; + } + + /* + * Queue up another receive. + */ + region.base = (unsigned char *)&ctx->buflen; + region.length = 2; + isc_socket_recv(sock, ®ion, ISC_FALSE, task, tcp_recv_len, ctx); isc_event_free(&event); } @@ -353,14 +402,17 @@ tcp_listener_allocate(isc_mem_t *mctx, u_int nwmax) isc_result_t tcp_listener_start(tcp_listener_t *l, isc_socket_t *sock, isc_taskmgr_t *tmgr, - u_int nwstart, u_int nwkeep, u_int nwtimeout) + u_int nwstart, u_int nwkeep, u_int nwtimeout, + dns_result_t (*dispatch)(isc_mem_t *, isc_region_t *, + unsigned int)) { u_int i; - isc_region_t region; LOCK(&l->lock); INSIST(l->nwactive == 0); + INSIST(dispatch != NULL); + l->dispatch = dispatch; l->sock = sock; RUNTIME_CHECK(isc_socket_listen(sock, 0) == ISC_R_SUCCESS); diff --git a/bin/named/tcpclient.h b/bin/named/tcpclient.h index 94d14f8953..53a17e48ca 100644 --- a/bin/named/tcpclient.h +++ b/bin/named/tcpclient.h @@ -21,6 +21,7 @@ struct __tcp_listener { u_int nwkeep; /* workers to keep */ u_int nwmax; /* workers max */ isc_mem_t *mctx; + dns_result_t (*dispatch)(isc_mem_t *, isc_region_t *, unsigned int); isc_mutex_t lock; /* locked */ @@ -33,4 +34,7 @@ tcp_listener_t *tcp_listener_allocate(isc_mem_t *mctx, u_int nwmax); isc_result_t tcp_listener_start(tcp_listener_t *l, isc_socket_t *sock, isc_taskmgr_t *tmgr, - u_int nwstart, u_int nwkeep, u_int nwtimeout); + u_int nwstart, u_int nwkeep, u_int nwtimeout, + dns_result_t (*dispatch)(isc_mem_t *, + isc_region_t *, + unsigned int)); diff --git a/bin/named/udpclient.c b/bin/named/udpclient.c index cf1a4886f8..70a4f2193e 100644 --- a/bin/named/udpclient.c +++ b/bin/named/udpclient.c @@ -21,6 +21,8 @@ #include #include +#include + #define LOCK(lp) \ RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS) #define UNLOCK(lp) \ @@ -74,6 +76,7 @@ udp_shutdown(isc_task_t *task, isc_event_t *event) { udp_cctx_t *ctx; udp_listener_t *l; + isc_socket_t *sock; ctx = (udp_cctx_t *)(event->arg); l = ctx->parent; @@ -91,10 +94,11 @@ udp_shutdown(isc_task_t *task, isc_event_t *event) l->tasks[ctx->slot] = NULL; l->ctxs[ctx->slot] = NULL; - isc_socket_cancel(l->sock, task, ISC_SOCKCANCEL_ALL); - l->nwactive--; + sock = l->sock; + isc_socket_detach(&sock); + UNLOCK(&l->lock); printf("Final shutdown slot %u\n", ctx->slot); @@ -109,6 +113,8 @@ udp_recv(isc_task_t *task, isc_event_t *event) isc_socket_t *sock; isc_socketevent_t *dev; udp_cctx_t *ctx; + dns_result_t result; + isc_region_t region; sock = event->sender; dev = (isc_socketevent_t *)event; @@ -123,14 +129,10 @@ udp_recv(isc_task_t *task, isc_event_t *event) ntohs(dev->address.type.sin.sin_port)); if (dev->result != ISC_R_SUCCESS) { - isc_socket_detach(&sock); - - udp_cctx_free(ctx); + isc_task_shutdown(task); isc_event_free(&event); - isc_task_shutdown(task); - return; } @@ -139,8 +141,14 @@ udp_recv(isc_task_t *task, isc_event_t *event) */ dump_packet(ctx->buf, dev->n); - isc_socket_recv(sock, &dev->region, ISC_FALSE, - task, udp_recv, event->arg); + region.base = ctx->buf; + region.length = dev->n; + result = ctx->parent->dispatch(ctx->mctx, ®ion, 0); + + if (result == DNS_R_SUCCESS) { + isc_socket_sendto(sock, ®ion, task, udp_send, ctx, + &dev->address, dev->addrlength); + } isc_event_free(&event); } @@ -150,16 +158,30 @@ udp_send(isc_task_t *task, isc_event_t *event) { isc_socket_t *sock; isc_socketevent_t *dev; + udp_cctx_t *ctx; + isc_region_t region; sock = event->sender; dev = (isc_socketevent_t *)event; + ctx = (udp_cctx_t *)(event->arg); - printf("my_send: %s task %p\n\t(sock %p, base %p, length %d, n %d, result %d)\n", - (char *)(event->arg), task, sock, - dev->region.base, dev->region.length, + printf("udp_send: task %u\n\t(base %p, length %d, n %d, result %d)\n", + ctx->slot, dev->region.base, dev->region.length, dev->n, dev->result); - isc_mem_put(event->mctx, dev->region.base, dev->region.length); + isc_mem_put(ctx->mctx, dev->region.base, dev->region.length); + + if (dev->result != ISC_R_SUCCESS) { + isc_task_shutdown(task); + + isc_event_free(&event); + + return; + } + + region.base = ctx->buf; + region.length = UDP_INPUT_BUFFER_SIZE; + isc_socket_recv(sock, ®ion, ISC_FALSE, task, udp_recv, ctx); isc_event_free(&event); } @@ -195,14 +217,18 @@ udp_listener_allocate(isc_mem_t *mctx, u_int nwmax) isc_result_t udp_listener_start(udp_listener_t *l, isc_socket_t *sock, isc_taskmgr_t *tmgr, - u_int nwstart, u_int nwkeep, u_int nwtimeout) + u_int nwstart, u_int nwkeep, u_int nwtimeout, + dns_result_t (*dispatch)(isc_mem_t *, isc_region_t *, + unsigned int)) { u_int i; isc_region_t region; LOCK(&l->lock); INSIST(l->nwactive == 0); + INSIST(dispatch != NULL); + l->dispatch = dispatch; l->sock = sock; for (i = 0 ; i < nwstart ; i++) { diff --git a/bin/named/udpclient.h b/bin/named/udpclient.h index abf0ef23f7..60fc89c6c5 100644 --- a/bin/named/udpclient.h +++ b/bin/named/udpclient.h @@ -21,6 +21,7 @@ struct __udp_listener { u_int nwkeep; /* workers to keep */ u_int nwmax; /* workers max */ isc_mem_t *mctx; + dns_result_t (*dispatch)(isc_mem_t *, isc_region_t *, unsigned int); isc_mutex_t lock; /* locked */ @@ -33,4 +34,7 @@ udp_listener_t *udp_listener_allocate(isc_mem_t *mctx, u_int nwmax); isc_result_t udp_listener_start(udp_listener_t *l, isc_socket_t *sock, isc_taskmgr_t *tmgr, - u_int nwstart, u_int nwkeep, u_int nwtimeout); + u_int nwstart, u_int nwkeep, u_int nwtimeout, + dns_result_t (*dispatch)(isc_mem_t *, + isc_region_t *, + unsigned int));