Commit 60cfce12 authored by Michael Graff's avatar Michael Graff
Browse files

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'.
parent e535faec
......@@ -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);
......
......@@ -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);
......
......@@ -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));
......@@ -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++) {
......
......@@ -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));
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment