mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
checkpoint; crude TCP support
This commit is contained in:
parent
f988b6764d
commit
b77cab68c6
@ -42,6 +42,8 @@
|
||||
#define MTRACE(m)
|
||||
#endif
|
||||
|
||||
#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
|
||||
|
||||
#define SEND_BUFFER_SIZE 512
|
||||
|
||||
struct ns_clientmgr {
|
||||
@ -101,14 +103,22 @@ client_free(ns_client_t *client) {
|
||||
}
|
||||
if (client->dispatch != NULL)
|
||||
dns_dispatch_detach(&client->dispatch);
|
||||
if (client->tcplistener != NULL)
|
||||
isc_socket_detach(&client->tcplistener);
|
||||
if (client->tcpsocket != NULL) {
|
||||
if (client->state == ns_clientstate_reading)
|
||||
dns_tcpmsg_cancelread(&client->tcpmsg);
|
||||
dns_tcpmsg_invalidate(&client->tcpmsg);
|
||||
isc_socket_detach(&client->tcpsocket);
|
||||
}
|
||||
isc_task_detach(&client->task);
|
||||
client->magic = 0;
|
||||
|
||||
isc_mem_put(client->mctx, client, sizeof *client);
|
||||
}
|
||||
|
||||
void
|
||||
ns_client_destroy(ns_client_t *client) {
|
||||
static void
|
||||
client_destroy(ns_client_t *client) {
|
||||
ns_clientmgr_t *manager;
|
||||
isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
|
||||
|
||||
@ -146,11 +156,14 @@ client_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
CTRACE("shutdown");
|
||||
|
||||
ns_client_destroy(client);
|
||||
client_destroy(client);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void client_read(ns_client_t *client);
|
||||
static void client_accept(ns_client_t *client);
|
||||
|
||||
void
|
||||
ns_client_next(ns_client_t *client, isc_result_t result) {
|
||||
|
||||
@ -168,15 +181,23 @@ ns_client_next(ns_client_t *client, isc_result_t result) {
|
||||
/*
|
||||
* XXXRTH If result != ISC_R_SUCCESS:
|
||||
* Log result if there is interest in doing so.
|
||||
* If this is a TCP client, close the connection.
|
||||
*/
|
||||
(void)result;
|
||||
|
||||
dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
|
||||
if (client->dispevent != NULL) {
|
||||
dns_dispatch_freeevent(client->dispatch, client->dispentry,
|
||||
&client->dispevent);
|
||||
client->state = ns_clientstate_listening;
|
||||
} else if (TCP_CLIENT(client)) {
|
||||
if (result == ISC_R_SUCCESS)
|
||||
client_read(client);
|
||||
else {
|
||||
if (client->tcpsocket != NULL) {
|
||||
dns_tcpmsg_invalidate(&client->tcpmsg);
|
||||
isc_socket_detach(&client->tcpsocket);
|
||||
}
|
||||
client_accept(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +237,10 @@ ns_client_send(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
unsigned char *data;
|
||||
isc_buffer_t buffer;
|
||||
isc_buffer_t tcpbuffer;
|
||||
isc_region_t r;
|
||||
isc_socket_t *socket;
|
||||
isc_sockaddr_t *address;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
@ -241,10 +265,23 @@ ns_client_send(ns_client_t *client) {
|
||||
|
||||
/*
|
||||
* XXXRTH The following doesn't deal with truncation, TSIGs,
|
||||
* or ENDS1 more data packets.
|
||||
* or ENDS1 more data packets. Nor do we try to use a
|
||||
* buffer bigger than 512 bytes, even if we're using
|
||||
* TCP.
|
||||
*/
|
||||
isc_buffer_init(&buffer, data, SEND_BUFFER_SIZE,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
if (TCP_CLIENT(client)) {
|
||||
/*
|
||||
* XXXRTH "tcpbuffer" is a hack to get things working.
|
||||
*/
|
||||
isc_buffer_init(&tcpbuffer, data, SEND_BUFFER_SIZE,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_init(&buffer, data + 2, SEND_BUFFER_SIZE - 2,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
} else {
|
||||
isc_buffer_init(&buffer, data, SEND_BUFFER_SIZE,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
}
|
||||
|
||||
result = dns_message_renderbegin(client->message, &buffer);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
@ -267,14 +304,22 @@ ns_client_send(ns_client_t *client) {
|
||||
result = dns_message_renderend(client->message);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
isc_buffer_used(&buffer, &r);
|
||||
/*
|
||||
* XXXRTH this only works for UDP clients.
|
||||
*/
|
||||
|
||||
if (TCP_CLIENT(client)) {
|
||||
socket = client->tcpsocket;
|
||||
address = NULL;
|
||||
isc_buffer_used(&buffer, &r);
|
||||
isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
|
||||
isc_buffer_add(&tcpbuffer, r.length);
|
||||
isc_buffer_used(&tcpbuffer, &r);
|
||||
} else {
|
||||
socket = dns_dispatch_getsocket(client->dispatch);
|
||||
address = &client->dispevent->addr;
|
||||
isc_buffer_used(&buffer, &r);
|
||||
}
|
||||
CTRACE("sendto");
|
||||
result = isc_socket_sendto(dns_dispatch_getsocket(client->dispatch),
|
||||
&r, client->task, client_senddone, client,
|
||||
&client->dispevent->addr);
|
||||
result = isc_socket_sendto(socket, &r, client->task, client_senddone,
|
||||
client, address);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
client->nsends++;
|
||||
|
||||
@ -327,28 +372,43 @@ ns_client_error(ns_client_t *client, isc_result_t result) {
|
||||
}
|
||||
|
||||
static void
|
||||
client_recv(isc_task_t *task, isc_event_t *event) {
|
||||
client_request(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client;
|
||||
dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
|
||||
dns_dispatchevent_t *devent;
|
||||
isc_result_t result;
|
||||
isc_buffer_t *buffer;
|
||||
|
||||
REQUIRE(devent != NULL);
|
||||
REQUIRE(devent->type == DNS_EVENT_DISPATCH);
|
||||
client = devent->arg;
|
||||
REQUIRE(event != NULL);
|
||||
client = event->arg;
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(task == client->task);
|
||||
REQUIRE(client->dispentry != NULL);
|
||||
|
||||
CTRACE("recv");
|
||||
if (event->type == DNS_EVENT_DISPATCH) {
|
||||
devent = (dns_dispatchevent_t *)event;
|
||||
REQUIRE(client->dispentry != NULL);
|
||||
client->dispevent = devent;
|
||||
buffer = &devent->buffer;
|
||||
result = devent->result;
|
||||
} else {
|
||||
REQUIRE(event->type == DNS_EVENT_TCPMSG);
|
||||
REQUIRE(event->sender == &client->tcpmsg);
|
||||
buffer = &client->tcpmsg.buffer;
|
||||
result = client->tcpmsg.result;
|
||||
}
|
||||
|
||||
client->dispevent = devent;
|
||||
if (devent->result != ISC_R_SUCCESS) {
|
||||
ns_client_destroy(client);
|
||||
CTRACE("request");
|
||||
|
||||
client->state = ns_clientstate_working;
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (TCP_CLIENT(client))
|
||||
ns_client_next(client, result);
|
||||
else
|
||||
isc_task_shutdown(client->task);
|
||||
return;
|
||||
}
|
||||
|
||||
client->state = ns_clientstate_working;
|
||||
result = dns_message_parse(client->message, &devent->buffer);
|
||||
result = dns_message_parse(client->message, buffer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_error(client, result);
|
||||
return;
|
||||
@ -455,6 +515,8 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
client->dispatch = NULL;
|
||||
client->dispentry = NULL;
|
||||
client->dispevent = NULL;
|
||||
client->tcplistener = NULL;
|
||||
client->tcpsocket = NULL;
|
||||
client->nsends = 0;
|
||||
client->next = NULL;
|
||||
ISC_LINK_INIT(client, link);
|
||||
@ -494,6 +556,75 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
client_read(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
|
||||
CTRACE("read");
|
||||
|
||||
result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
|
||||
client_request, client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
ns_client_next(client, result);
|
||||
client->state = ns_clientstate_reading;
|
||||
}
|
||||
|
||||
static void
|
||||
client_newconn(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client = event->arg;
|
||||
isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
|
||||
|
||||
REQUIRE(event->type == ISC_SOCKEVENT_NEWCONN);
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(client->task == task);
|
||||
|
||||
CTRACE("newconn");
|
||||
|
||||
if (nevent->result == ISC_R_SUCCESS) {
|
||||
client->tcpsocket = nevent->newsocket;
|
||||
dns_tcpmsg_init(client->mctx, client->tcpsocket,
|
||||
&client->tcpmsg);
|
||||
client_read(client);
|
||||
} else {
|
||||
/*
|
||||
* XXXRTH What should we do? We're trying to accept but
|
||||
* it didn't work. If we just give up, then TCP
|
||||
* service may eventually stop.
|
||||
*
|
||||
* For now, we just go idle.
|
||||
*
|
||||
* Going idle is probably the right thing if the
|
||||
* I/O was canceled.
|
||||
*/
|
||||
client->state = ns_clientstate_idle;
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
client_accept(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
|
||||
CTRACE("accept");
|
||||
|
||||
result = isc_socket_accept(client->tcplistener, client->task,
|
||||
client_newconn, client);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_socket_accept() failed: %s",
|
||||
isc_result_totext(result));
|
||||
/*
|
||||
* XXXRTH What should we do? We're trying to accept but
|
||||
* it didn't work. If we just give up, then TCP
|
||||
* service may eventually stop.
|
||||
*
|
||||
* For now, we just go idle.
|
||||
*/
|
||||
client->state = ns_clientstate_idle;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
*** Client Manager
|
||||
@ -578,8 +709,7 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
unsigned int n,
|
||||
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, unsigned int n,
|
||||
dns_dispatch_t *dispatch)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
@ -601,18 +731,76 @@ ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
client = NULL;
|
||||
result = client_create(manager, type, &client);
|
||||
result = client_create(manager, ns_clienttype_basic,
|
||||
&client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
client->state = ns_clientstate_listening;
|
||||
dns_dispatch_attach(dispatch, &client->dispatch);
|
||||
result = dns_dispatch_addrequest(dispatch, client->task,
|
||||
client_recv,
|
||||
client_request,
|
||||
client, &client->dispentry);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
client_free(client);
|
||||
break;
|
||||
}
|
||||
client->state = ns_clientstate_listening;
|
||||
manager->nclients++;
|
||||
ISC_LIST_APPEND(manager->clients, client, link);
|
||||
}
|
||||
if (i != 0) {
|
||||
/*
|
||||
* We managed to create at least one client, so we
|
||||
* declare victory.
|
||||
*/
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_accepttcp(ns_clientmgr_t *manager, isc_socket_t *socket,
|
||||
unsigned int n)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
unsigned int i;
|
||||
ns_client_t *client;
|
||||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
REQUIRE(n > 0);
|
||||
|
||||
MTRACE("accepttcp");
|
||||
|
||||
/*
|
||||
* XXXRTH
|
||||
*
|
||||
* This does not represent the planned method for TCP support,
|
||||
* because we are dedicating a few clients to servicing TCP requests
|
||||
* instead of allocating TCP clients from a pool and applying quotas.
|
||||
*
|
||||
* All this will be fixed later, but this code will allow parts of
|
||||
* the server that need TCP support, e.g. IXFR and AXFR, to progress.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We MUST lock the manager lock for the entire client creation
|
||||
* process. If we didn't do this, then a client could get a
|
||||
* shutdown event and disappear out from under us.
|
||||
*/
|
||||
|
||||
LOCK(&manager->lock);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
client = NULL;
|
||||
result = client_create(manager, ns_clienttype_tcp, &client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
client->state = ns_clientstate_listening;
|
||||
client->attributes |= NS_CLIENTATTR_TCP;
|
||||
isc_socket_attach(socket, &client->tcplistener);
|
||||
client_accept(client);
|
||||
manager->nclients++;
|
||||
ISC_LIST_APPEND(manager->clients, client, link);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <isc/buffer.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
#include <dns/tcpmsg.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/query.h>
|
||||
@ -30,12 +31,14 @@ typedef enum ns_clienttype {
|
||||
ns_clienttype_basic = 0,
|
||||
ns_clienttype_recursive,
|
||||
ns_clienttype_axfr,
|
||||
ns_clienttype_ixfr
|
||||
ns_clienttype_ixfr,
|
||||
ns_clienttype_tcp
|
||||
} ns_clienttype_t;
|
||||
|
||||
typedef enum {
|
||||
ns_clientstate_idle = 0,
|
||||
ns_clientstate_listening,
|
||||
ns_clientstate_reading,
|
||||
ns_clientstate_working,
|
||||
ns_clientstate_waiting
|
||||
} ns_clientstate_t;
|
||||
@ -51,6 +54,9 @@ struct ns_client {
|
||||
dns_dispatch_t * dispatch;
|
||||
dns_dispentry_t * dispentry;
|
||||
dns_dispatchevent_t * dispevent;
|
||||
isc_socket_t * tcplistener;
|
||||
isc_socket_t * tcpsocket;
|
||||
dns_tcpmsg_t tcpmsg;
|
||||
isc_timer_t * timer;
|
||||
dns_message_t * message;
|
||||
unsigned int nsends;
|
||||
@ -64,6 +70,8 @@ struct ns_client {
|
||||
#define NS_CLIENT_VALID(c) ((c) != NULL && \
|
||||
(c)->magic == NS_CLIENT_MAGIC)
|
||||
|
||||
#define NS_CLIENTATTR_TCP 0x01
|
||||
|
||||
/*
|
||||
* Note! These ns_client_ routines MUST be called ONLY from the client's
|
||||
* task in order to ensure synchronization.
|
||||
@ -91,8 +99,11 @@ void
|
||||
ns_clientmgr_destroy(ns_clientmgr_t **managerp);
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
unsigned int n,
|
||||
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, unsigned int n,
|
||||
dns_dispatch_t *dispatch);
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_accepttcp(ns_clientmgr_t *manager, isc_socket_t *socket,
|
||||
unsigned int n);
|
||||
|
||||
#endif /* NS_CLIENT_H */
|
||||
|
@ -50,12 +50,11 @@ EXTERN ns_interfacemgr_t * ns_g_interfacemgr INIT(NULL);
|
||||
EXTERN ns_clientmgr_t * ns_g_clientmgr INIT(NULL);
|
||||
EXTERN char * ns_g_version INIT(VERSION);
|
||||
|
||||
EXTERN isc_rwlock_t ns_g_viewlock;
|
||||
EXTERN dns_viewlist_t ns_g_views;
|
||||
EXTERN dns_viewmgr_t * ns_g_viewmgr INIT(NULL);
|
||||
|
||||
/* XXXRTH These are temporary. */
|
||||
EXTERN ns_dbinfolist_t ns_g_dbs;
|
||||
EXTERN dns_dbtable_t * ns_g_dbtable INIT(NULL);
|
||||
EXTERN dns_dbtable_t * ns_g_dbtable;
|
||||
|
||||
#undef EXTERN
|
||||
#undef INIT
|
||||
|
@ -163,8 +163,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
isc_result_totext(result));
|
||||
goto udp_dispatch_failure;
|
||||
}
|
||||
result = ns_clientmgr_addtodispatch(mgr->clientmgr,
|
||||
ns_clienttype_basic, ns_g_cpus,
|
||||
result = ns_clientmgr_addtodispatch(mgr->clientmgr, ns_g_cpus,
|
||||
ifp->udpdispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
@ -173,7 +172,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
goto addtodispatch_failure;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Open a TCP socket.
|
||||
*/
|
||||
@ -195,9 +193,21 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
isc_result_totext(result));
|
||||
goto tcp_bind_failure;
|
||||
}
|
||||
#else
|
||||
ifp->tcpsocket = NULL;
|
||||
#endif
|
||||
result = isc_socket_listen(ifp->tcpsocket, 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"listen TCP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto tcp_listen_failure;
|
||||
}
|
||||
result = ns_clientmgr_accepttcp(mgr->clientmgr, ifp->tcpsocket,
|
||||
ns_g_cpus);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"TCP ns_clientmgr_accepttcp(): %s",
|
||||
isc_result_totext(result));
|
||||
goto accepttcp_failure;
|
||||
}
|
||||
|
||||
ISC_LIST_APPEND(mgr->interfaces, ifp, link);
|
||||
|
||||
@ -206,6 +216,19 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
|
||||
return (DNS_R_SUCCESS);
|
||||
|
||||
accepttcp_failure:
|
||||
tcp_listen_failure:
|
||||
tcp_bind_failure:
|
||||
isc_socket_detach(&ifp->tcpsocket);
|
||||
tcp_socket_failure:
|
||||
/*
|
||||
* XXXRTH We don't currently have a way to easily stop dispatch
|
||||
* service, so we return currently return DNS_R_SUCCESS (the UDP
|
||||
* stuff will work even if TCP creation failed). This will be fixed
|
||||
* later.
|
||||
*/
|
||||
return (DNS_R_SUCCESS);
|
||||
|
||||
addtodispatch_failure:
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
udp_dispatch_failure:
|
||||
@ -232,10 +255,8 @@ ns_interface_destroy(ns_interface_t **ifpret) {
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
isc_socket_detach(&ifp->udpsocket);
|
||||
|
||||
#if 0
|
||||
isc_socket_cancel(ifp->tcpsocket, NULL, ISC_SOCKCANCEL_ALL);
|
||||
isc_socket_detach(&ifp->tcpsocket);
|
||||
#endif
|
||||
|
||||
isc_task_detach(&ifp->task);
|
||||
|
||||
|
@ -198,12 +198,14 @@ static void
|
||||
setup() {
|
||||
isc_result_t result;
|
||||
|
||||
#if 0
|
||||
ISC_LIST_INIT(ns_g_views);
|
||||
|
||||
result = isc_rwlock_init(&ns_g_viewlock, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
early_fatal("isc_rwlock_init() failed: %s",
|
||||
isc_result_totext(result));
|
||||
#endif
|
||||
|
||||
result = create_managers();
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -219,7 +221,9 @@ setup() {
|
||||
static void
|
||||
cleanup() {
|
||||
destroy_managers();
|
||||
#if 0
|
||||
isc_rwlock_destroy(&ns_g_viewlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -42,6 +42,9 @@
|
||||
|
||||
#include "../../isc/util.h" /* XXX */
|
||||
|
||||
#define PARTIALANSWER(c) (((c)->query.attributes & \
|
||||
NS_QUERYATTR_PARTIALANSWER) != 0)
|
||||
|
||||
static inline void
|
||||
query_reset(ns_client_t *client, isc_boolean_t everything) {
|
||||
isc_dynbuffer_t *dbuf, *dbuf_next;
|
||||
@ -305,7 +308,32 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
||||
(void)query_addadditional(client, fname, dns_rdatatype_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static isc_result_t
|
||||
newfind(ns_client_t *client) {
|
||||
isc_boolean_t cache_ok = ISC_FALSE;
|
||||
isc_boolean_t recursion_ok = ISC_FALSE;
|
||||
dns_db_t *db;
|
||||
|
||||
/*
|
||||
* First we must find the right database to search
|
||||
*/
|
||||
db = NULL;
|
||||
result = dns_dbtable_find(client->view->dbtable,
|
||||
client->query.qname, &db);
|
||||
if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
|
||||
if (PARTIALANSWER(client)) {
|
||||
/*
|
||||
* If we've already got an answer we can go with,
|
||||
* use it. Otherwise there's nothing we can do.
|
||||
*/
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
return (DNS_R_SERVFAIL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static isc_result_t
|
||||
find(ns_client_t *client, dns_rdatatype_t type) {
|
||||
@ -326,6 +354,12 @@ find(ns_client_t *client, dns_rdatatype_t type) {
|
||||
isc_boolean_t first_time;
|
||||
dns_rdata_t rdata;
|
||||
|
||||
/*
|
||||
* XXXRTH
|
||||
*
|
||||
* This is still jury rigged.
|
||||
*/
|
||||
|
||||
/*
|
||||
* One-time initialization.
|
||||
*/
|
||||
@ -607,7 +641,7 @@ ns_query_start(ns_client_t *client) {
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* XXXRTH comment here
|
||||
*/
|
||||
|
||||
for (rdataset = ISC_LIST_HEAD(client->query.qname->list);
|
||||
|
@ -58,278 +58,6 @@
|
||||
static ns_dbinfo_t * cache_dbi;
|
||||
static isc_task_t * server_task;
|
||||
|
||||
#if 0
|
||||
static inline isc_boolean_t
|
||||
CHECKRESULT(dns_result_t result, char *msg)
|
||||
{
|
||||
if ((result) != DNS_R_SUCCESS) {
|
||||
printf("%s: %s\n", (msg), dns_result_totext(result));
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is in bin/tests/wire_test.c, but should be in a debugging library.
|
||||
*/
|
||||
extern dns_result_t
|
||||
printmessage(dns_message_t *);
|
||||
|
||||
#define MAX_RDATASETS 25
|
||||
|
||||
static dns_result_t
|
||||
resolve_packet(isc_mem_t *mctx, dns_message_t *query, isc_buffer_t *target) {
|
||||
dns_message_t *message;
|
||||
dns_result_t result, dbresult;
|
||||
dns_name_t *qname, *fname, *rqname;
|
||||
dns_fixedname_t foundname, frqname;
|
||||
dns_rdataset_t *rds, *rdataset, rqrds, rdatasets[MAX_RDATASETS];
|
||||
unsigned int nrdatasets = 0;
|
||||
dns_dbnode_t *node;
|
||||
dns_db_t *db;
|
||||
dns_rdatasetiter_t *rdsiter;
|
||||
dns_rdatatype_t type;
|
||||
isc_boolean_t possibly_auth = ISC_FALSE;
|
||||
|
||||
message = NULL;
|
||||
result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
|
||||
CHECKRESULT(result, "dns_message_create failed");
|
||||
|
||||
message->id = query->id;
|
||||
message->rcode = dns_rcode_noerror;
|
||||
message->flags = query->flags;
|
||||
message->flags |= DNS_MESSAGEFLAG_QR;
|
||||
|
||||
result = dns_message_firstname(query, DNS_SECTION_QUESTION);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
qname = NULL;
|
||||
dns_fixedname_init(&frqname);
|
||||
rqname = dns_fixedname_name(&frqname);
|
||||
dns_message_currentname(query, DNS_SECTION_QUESTION, &qname);
|
||||
result = dns_name_concatenate(qname, NULL, rqname, NULL);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (DNS_R_UNEXPECTED);
|
||||
rds = ISC_LIST_HEAD(qname->list);
|
||||
if (rds == NULL)
|
||||
return (DNS_R_UNEXPECTED);
|
||||
type = rds->type;
|
||||
dns_rdataset_init(&rqrds);
|
||||
dns_rdataset_makequestion(&rqrds, rds->rdclass, rds->type);
|
||||
ISC_LIST_APPEND(rqname->list, &rqrds, link);
|
||||
|
||||
dns_message_addname(message, rqname, DNS_SECTION_QUESTION);
|
||||
|
||||
result = printmessage(message);
|
||||
INSIST(result == DNS_R_SUCCESS); /* XXX not in a real server */
|
||||
|
||||
/*
|
||||
* Find a database to answer the query from.
|
||||
*/
|
||||
db = NULL;
|
||||
result = dns_dbtable_find(ns_g_dbtable, qname, &db);
|
||||
if (result != DNS_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
|
||||
printf("could not find a dbtable: %s\n",
|
||||
dns_result_totext(result));
|
||||
message->rcode = dns_rcode_servfail;
|
||||
goto render;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now look for an answer in the database.
|
||||
*/
|
||||
dns_fixedname_init(&foundname);
|
||||
fname = dns_fixedname_name(&foundname);
|
||||
rdataset = &rdatasets[nrdatasets++];
|
||||
dns_rdataset_init(rdataset);
|
||||
node = NULL;
|
||||
dbresult = dns_db_find(db, qname, NULL, type, 0, 0, &node, fname,
|
||||
rdataset);
|
||||
switch (dbresult) {
|
||||
case DNS_R_SUCCESS:
|
||||
case DNS_R_DNAME:
|
||||
case DNS_R_CNAME:
|
||||
possibly_auth = ISC_TRUE;
|
||||
break;
|
||||
case DNS_R_GLUE:
|
||||
case DNS_R_ZONECUT:
|
||||
case DNS_R_DELEGATION:
|
||||
break;
|
||||
case DNS_R_NXRDATASET:
|
||||
if (dns_db_iszone(db))
|
||||
message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
dns_db_detachnode(db, &node);
|
||||
dns_db_detach(&db);
|
||||
goto render;
|
||||
case DNS_R_NXDOMAIN:
|
||||
if (dns_db_iszone(db))
|
||||
message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
dns_db_detach(&db);
|
||||
message->rcode = dns_rcode_nxdomain;
|
||||
goto render;
|
||||
default:
|
||||
printf("%s\n", dns_result_totext(result));
|
||||
dns_db_detach(&db);
|
||||
message->rcode = dns_rcode_servfail;
|
||||
goto render;
|
||||
}
|
||||
|
||||
if (dbresult == DNS_R_DELEGATION) {
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
dns_message_addname(message, fname, DNS_SECTION_AUTHORITY);
|
||||
} else if (type == dns_rdatatype_any) {
|
||||
rdsiter = NULL;
|
||||
result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
result = dns_rdatasetiter_first(rdsiter);
|
||||
while (result == DNS_R_SUCCESS) {
|
||||
dns_rdatasetiter_current(rdsiter, rdataset);
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
if (nrdatasets == MAX_RDATASETS) {
|
||||
result = DNS_R_NOSPACE;
|
||||
} else {
|
||||
rdataset = &rdatasets[nrdatasets++];
|
||||
dns_rdataset_init(rdataset);
|
||||
result = dns_rdatasetiter_next(rdsiter);
|
||||
}
|
||||
}
|
||||
if (result != DNS_R_NOMORE) {
|
||||
dns_db_detachnode(db, &node);
|
||||
dns_db_detach(&db);
|
||||
message->rcode = dns_rcode_servfail;
|
||||
goto render;
|
||||
}
|
||||
dns_message_addname(message, fname, DNS_SECTION_ANSWER);
|
||||
} else {
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
dns_message_addname(message, fname, DNS_SECTION_ANSWER);
|
||||
}
|
||||
|
||||
if (dns_db_iszone(db) && possibly_auth)
|
||||
message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
|
||||
dns_db_detachnode(db, &node);
|
||||
dns_db_detach(&db);
|
||||
|
||||
render:
|
||||
|
||||
result = dns_message_renderbegin(message, target);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_QUESTION,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_ANSWER,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_TSIG,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_renderend(message);
|
||||
|
||||
dns_message_destroy(&message);
|
||||
|
||||
return (DNS_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
char t[512];
|
||||
isc_buffer_t source;
|
||||
isc_buffer_t target;
|
||||
dns_result_t result;
|
||||
isc_region_t txr;
|
||||
dns_message_t *message;
|
||||
|
||||
/*
|
||||
* Set up the input buffer from the contents of the region passed
|
||||
* to us.
|
||||
*/
|
||||
isc_buffer_init(&source, rxr->base, rxr->length,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_add(&source, rxr->length);
|
||||
|
||||
message = NULL;
|
||||
result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
|
||||
if (CHECKRESULT(result, "dns_message_create failed")) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
result = dns_message_parse(message, &source);
|
||||
if (CHECKRESULT(result, "dns_message_parsed failed")) {
|
||||
dns_message_destroy(&message);
|
||||
return (result);
|
||||
}
|
||||
CHECKRESULT(result, "dns_message_parse failed");
|
||||
|
||||
result = printmessage(message);
|
||||
if (CHECKRESULT(result, "printmessage failed")) {
|
||||
dns_message_destroy(&message);
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_buffer_init(&target, t, sizeof(t), ISC_BUFFERTYPE_BINARY);
|
||||
result = resolve_packet(mctx, message, &target);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
dns_message_destroy(&message);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the reply out, adjusting for reslen
|
||||
*/
|
||||
isc_buffer_used(&target, &txr);
|
||||
txr.base = isc_mem_get(mctx, txr.length + reslen);
|
||||
if (txr.base == NULL) {
|
||||
dns_message_destroy(&message);
|
||||
|
||||
return (DNS_R_NOMEMORY);
|
||||
}
|
||||
|
||||
memcpy(txr.base + reslen, t, txr.length);
|
||||
rxr->base = txr.base;
|
||||
rxr->length = txr.length + reslen;
|
||||
|
||||
printf("Base == %p, length == %u\n", txr.base, txr.length);
|
||||
fflush(stdout);
|
||||
|
||||
if (want_stats)
|
||||
isc_mem_stats(mctx, stdout);
|
||||
|
||||
dns_message_destroy(&message);
|
||||
|
||||
return (DNS_R_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
static dns_result_t
|
||||
load(ns_dbinfo_t *dbi) {
|
||||
dns_fixedname_t forigin;
|
||||
@ -350,16 +78,13 @@ load(ns_dbinfo_t *dbi) {
|
||||
|
||||
result = dns_db_create(ns_g_mctx, "rbt", origin, dbi->iscache,
|
||||
dns_rdataclass_in, 0, NULL, &dbi->db);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
printf("loading %s (%s)\n", dbi->path, dbi->origin);
|
||||
result = dns_db_load(dbi->db, dbi->path);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
dns_db_detach(&dbi->db);
|
||||
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
|
||||
return (result);
|
||||
}
|
||||
printf("loaded\n");
|
||||
@ -401,14 +126,16 @@ unload_all(void) {
|
||||
|
||||
for (dbi = ISC_LIST_HEAD(ns_g_dbs); dbi != NULL; dbi = dbi_next) {
|
||||
dbi_next = ISC_LIST_NEXT(dbi, link);
|
||||
if (dns_db_iszone(dbi->db))
|
||||
dns_dbtable_remove(ns_g_dbtable, dbi->db);
|
||||
else {
|
||||
INSIST(dbi == cache_dbi);
|
||||
dns_dbtable_removedefault(ns_g_dbtable);
|
||||
cache_dbi = NULL;
|
||||
if (dbi->db != NULL) {
|
||||
if (dns_db_iszone(dbi->db))
|
||||
dns_dbtable_remove(ns_g_dbtable, dbi->db);
|
||||
else {
|
||||
INSIST(dbi == cache_dbi);
|
||||
dns_dbtable_removedefault(ns_g_dbtable);
|
||||
cache_dbi = NULL;
|
||||
}
|
||||
dns_db_detach(&dbi->db);
|
||||
}
|
||||
dns_db_detach(&dbi->db);
|
||||
ISC_LIST_UNLINK(ns_g_dbs, dbi, link);
|
||||
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
|
||||
}
|
||||
@ -456,15 +183,25 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
|
||||
isc_result_t
|
||||
ns_server_init(void) {
|
||||
isc_result_t result;
|
||||
#if 0
|
||||
dns_view_t *view = NULL;
|
||||
#endif
|
||||
|
||||
result = dns_dbtable_create(ns_g_mctx, dns_rdataclass_in,
|
||||
&ns_g_dbtable);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
#if 0
|
||||
result = dns_view_create(ns_g_viewmgr, dns_rdataclass_in, "default/IN",
|
||||
ns_g_dbtable, NULL, &view);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_dbtable;
|
||||
#endif
|
||||
|
||||
result = isc_task_create(ns_g_taskmgr, ns_g_mctx, 0, &server_task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_dbtable;
|
||||
goto cleanup_view;
|
||||
|
||||
result = isc_task_onshutdown(server_task, shutdown_server, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -479,7 +216,12 @@ ns_server_init(void) {
|
||||
cleanup_task:
|
||||
isc_task_detach(&server_task);
|
||||
|
||||
cleanup_view:
|
||||
#if 0
|
||||
dns_view_detach(&view);
|
||||
|
||||
cleanup_dbtable:
|
||||
#endif
|
||||
dns_dbtable_detach(&ns_g_dbtable);
|
||||
|
||||
return (result);
|
||||
|
Loading…
x
Reference in New Issue
Block a user