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'.
This commit is contained in:
Michael Graff
1999-01-29 06:18:43 +00:00
parent e535faecc7
commit 60cfce122f
5 changed files with 161 additions and 33 deletions

View File

@@ -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);

View File

@@ -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, &region, 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, &region, 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, &region, 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, &region, 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);

View File

@@ -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));

View File

@@ -21,6 +21,8 @@
#include <isc/socket.h>
#include <isc/timer.h>
#include <dns/result.h>
#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, &region, 0);
if (result == DNS_R_SUCCESS) {
isc_socket_sendto(sock, &region, 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, &region, 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++) {

View File

@@ -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));