2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-23 18:49:54 +00:00
bind/lib/dns/tcpmsg.c

245 lines
5.8 KiB
C
Raw Normal View History

1999-09-16 00:02:20 +00:00
/*
* Copyright (C) 2004-2007, 2015 Internet Systems Consortium, Inc. ("ISC")
2001-01-09 22:01:04 +00:00
* Copyright (C) 1999-2001 Internet Software Consortium.
*
2007-06-18 23:47:57 +00:00
* Permission to use, copy, modify, and/or distribute this software for any
1999-09-16 00:02:20 +00:00
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
2004-03-05 05:14:21 +00:00
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC 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.
1999-09-16 00:02:20 +00:00
*/
1999-07-10 00:15:53 +00:00
2007-06-19 23:47:24 +00:00
/* $Id: tcpmsg.c,v 1.31 2007/06/19 23:47:16 tbox Exp $ */
/*! \file */
2000-06-22 22:00:42 +00:00
1999-07-10 00:15:53 +00:00
#include <config.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/task.h>
1999-12-16 22:24:22 +00:00
#include <isc/util.h>
1999-07-10 00:15:53 +00:00
#include <dns/events.h>
#include <dns/result.h>
#include <dns/tcpmsg.h>
#ifdef TCPMSG_DEBUG
#include <stdio.h> /* Required for printf. */
1999-07-10 00:15:53 +00:00
#define XDEBUG(x) printf x
#else
#define XDEBUG(x)
#endif
#define TCPMSG_MAGIC ISC_MAGIC('T', 'C', 'P', 'm')
#define VALID_TCPMSG(foo) ISC_MAGIC_VALID(foo, TCPMSG_MAGIC)
1999-07-10 00:15:53 +00:00
static void recv_length(isc_task_t *, isc_event_t *);
static void recv_message(isc_task_t *, isc_event_t *);
static void
recv_length(isc_task_t *task, isc_event_t *ev_in) {
1999-07-10 00:15:53 +00:00
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
isc_event_t *dev;
dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
1999-07-10 00:15:53 +00:00
isc_region_t region;
isc_result_t result;
INSIST(VALID_TCPMSG(tcpmsg));
dev = &tcpmsg->event;
tcpmsg->address = ev->address;
1999-07-10 00:15:53 +00:00
if (ev->result != ISC_R_SUCCESS) {
tcpmsg->result = ev->result;
goto send_and_free;
}
/*
* Success.
1999-07-10 00:15:53 +00:00
*/
tcpmsg->size = ntohs(tcpmsg->size);
if (tcpmsg->size == 0) {
tcpmsg->result = ISC_R_UNEXPECTEDEND;
1999-07-10 00:15:53 +00:00
goto send_and_free;
}
1999-07-10 00:53:57 +00:00
if (tcpmsg->size > tcpmsg->maxsize) {
2000-05-15 21:14:38 +00:00
tcpmsg->result = ISC_R_RANGE;
1999-07-10 00:15:53 +00:00
goto send_and_free;
}
region.base = isc_mem_get(tcpmsg->mctx, tcpmsg->size);
region.length = tcpmsg->size;
if (region.base == NULL) {
tcpmsg->result = ISC_R_NOMEMORY;
goto send_and_free;
}
XDEBUG(("Allocated %d bytes\n", tcpmsg->size));
1999-07-10 00:15:53 +00:00
isc_buffer_init(&tcpmsg->buffer, region.base, region.length);
result = isc_socket_recv(tcpmsg->sock, &region, 0,
1999-07-10 00:15:53 +00:00
task, recv_message, tcpmsg);
if (result != ISC_R_SUCCESS) {
tcpmsg->result = result;
goto send_and_free;
}
isc_event_free(&ev_in);
return;
send_and_free:
isc_task_send(tcpmsg->task, &dev);
1999-07-10 00:15:53 +00:00
tcpmsg->task = NULL;
isc_event_free(&ev_in);
return;
}
static void
recv_message(isc_task_t *task, isc_event_t *ev_in) {
1999-07-10 00:15:53 +00:00
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
isc_event_t *dev;
dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
1999-07-10 00:15:53 +00:00
(void)task;
INSIST(VALID_TCPMSG(tcpmsg));
dev = &tcpmsg->event;
tcpmsg->address = ev->address;
1999-07-10 00:15:53 +00:00
if (ev->result != ISC_R_SUCCESS) {
tcpmsg->result = ev->result;
goto send_and_free;
}
tcpmsg->result = ISC_R_SUCCESS;
isc_buffer_add(&tcpmsg->buffer, ev->n);
XDEBUG(("Received %d bytes (of %d)\n", ev->n, tcpmsg->size));
1999-07-10 00:15:53 +00:00
send_and_free:
isc_task_send(tcpmsg->task, &dev);
1999-07-10 00:15:53 +00:00
tcpmsg->task = NULL;
isc_event_free(&ev_in);
}
void
dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg) {
1999-07-10 00:15:53 +00:00
REQUIRE(mctx != NULL);
REQUIRE(sock != NULL);
REQUIRE(tcpmsg != NULL);
tcpmsg->magic = TCPMSG_MAGIC;
tcpmsg->size = 0;
tcpmsg->buffer.base = NULL;
tcpmsg->buffer.length = 0;
tcpmsg->maxsize = 65535; /* Largest message possible. */
1999-07-10 00:15:53 +00:00
tcpmsg->mctx = mctx;
tcpmsg->sock = sock;
tcpmsg->task = NULL; /* None yet. */
tcpmsg->result = ISC_R_UNEXPECTED; /* None yet. */
/*
* Should probably initialize the event here, but it can wait.
*/
1999-07-10 00:15:53 +00:00
}
void
dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize) {
1999-07-10 00:15:53 +00:00
REQUIRE(VALID_TCPMSG(tcpmsg));
REQUIRE(maxsize < 65536);
tcpmsg->maxsize = maxsize;
}
isc_result_t
1999-07-10 00:15:53 +00:00
dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
isc_task_t *task, isc_taskaction_t action, void *arg)
{
isc_result_t result;
isc_region_t region;
REQUIRE(VALID_TCPMSG(tcpmsg));
REQUIRE(task != NULL);
REQUIRE(tcpmsg->task == NULL); /* not currently in use */
if (tcpmsg->buffer.base != NULL) {
isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
tcpmsg->buffer.length);
tcpmsg->buffer.base = NULL;
tcpmsg->buffer.length = 0;
}
tcpmsg->task = task;
tcpmsg->action = action;
tcpmsg->arg = arg;
tcpmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0,
1999-07-30 13:33:47 +00:00
DNS_EVENT_TCPMSG, action, arg, tcpmsg,
1999-07-10 00:15:53 +00:00
NULL, NULL);
region.base = (unsigned char *)&tcpmsg->size;
1999-07-13 19:42:01 +00:00
region.length = 2; /* isc_uint16_t */
result = isc_socket_recv(tcpmsg->sock, &region, 0,
1999-07-10 00:15:53 +00:00
tcpmsg->task, recv_length, tcpmsg);
if (result != ISC_R_SUCCESS)
tcpmsg->task = NULL;
1999-07-10 00:15:53 +00:00
return (result);
}
void
dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg) {
1999-07-10 00:15:53 +00:00
REQUIRE(VALID_TCPMSG(tcpmsg));
1999-07-10 00:53:57 +00:00
isc_socket_cancel(tcpmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
1999-07-10 00:15:53 +00:00
}
void
dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer) {
1999-07-10 00:15:53 +00:00
REQUIRE(VALID_TCPMSG(tcpmsg));
REQUIRE(buffer != NULL);
*buffer = tcpmsg->buffer;
tcpmsg->buffer.base = NULL;
1999-07-10 00:15:53 +00:00
tcpmsg->buffer.length = 0;
}
#if 0
void
dns_tcpmsg_freebuffer(dns_tcpmsg_t *tcpmsg) {
REQUIRE(VALID_TCPMSG(tcpmsg));
if (tcpmsg->buffer.base == NULL)
return;
isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base, tcpmsg->buffer.length);
tcpmsg->buffer.base = NULL;
tcpmsg->buffer.length = 0;
}
#endif
1999-07-10 00:15:53 +00:00
void
dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg) {
1999-07-10 00:15:53 +00:00
REQUIRE(VALID_TCPMSG(tcpmsg));
tcpmsg->magic = 0;
if (tcpmsg->buffer.base != NULL) {
isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
tcpmsg->buffer.length);
tcpmsg->buffer.base = NULL;
tcpmsg->buffer.length = 0;
}
}