2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

checkpoint; crude TCP support

This commit is contained in:
Bob Halley 1999-08-05 01:51:32 +00:00
parent f988b6764d
commit b77cab68c6
7 changed files with 331 additions and 332 deletions

View File

@ -42,6 +42,8 @@
#define MTRACE(m) #define MTRACE(m)
#endif #endif
#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
#define SEND_BUFFER_SIZE 512 #define SEND_BUFFER_SIZE 512
struct ns_clientmgr { struct ns_clientmgr {
@ -101,14 +103,22 @@ client_free(ns_client_t *client) {
} }
if (client->dispatch != NULL) if (client->dispatch != NULL)
dns_dispatch_detach(&client->dispatch); 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); isc_task_detach(&client->task);
client->magic = 0; client->magic = 0;
isc_mem_put(client->mctx, client, sizeof *client); isc_mem_put(client->mctx, client, sizeof *client);
} }
void static void
ns_client_destroy(ns_client_t *client) { client_destroy(ns_client_t *client) {
ns_clientmgr_t *manager; ns_clientmgr_t *manager;
isc_boolean_t need_clientmgr_destroy = ISC_FALSE; isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
@ -146,11 +156,14 @@ client_shutdown(isc_task_t *task, isc_event_t *event) {
CTRACE("shutdown"); CTRACE("shutdown");
ns_client_destroy(client); client_destroy(client);
isc_event_free(&event); isc_event_free(&event);
} }
static void client_read(ns_client_t *client);
static void client_accept(ns_client_t *client);
void void
ns_client_next(ns_client_t *client, isc_result_t result) { 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: * XXXRTH If result != ISC_R_SUCCESS:
* Log result if there is interest in doing so. * 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); dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
if (client->dispevent != NULL) { if (client->dispevent != NULL) {
dns_dispatch_freeevent(client->dispatch, client->dispentry, dns_dispatch_freeevent(client->dispatch, client->dispentry,
&client->dispevent); &client->dispevent);
client->state = ns_clientstate_listening; 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; isc_result_t result;
unsigned char *data; unsigned char *data;
isc_buffer_t buffer; isc_buffer_t buffer;
isc_buffer_t tcpbuffer;
isc_region_t r; isc_region_t r;
isc_socket_t *socket;
isc_sockaddr_t *address;
REQUIRE(NS_CLIENT_VALID(client)); 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, * 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, if (TCP_CLIENT(client)) {
ISC_BUFFERTYPE_BINARY); /*
* 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); result = dns_message_renderbegin(client->message, &buffer);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto done; goto done;
@ -267,14 +304,22 @@ ns_client_send(ns_client_t *client) {
result = dns_message_renderend(client->message); result = dns_message_renderend(client->message);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto done; goto done;
isc_buffer_used(&buffer, &r);
/* if (TCP_CLIENT(client)) {
* XXXRTH this only works for UDP clients. 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"); CTRACE("sendto");
result = isc_socket_sendto(dns_dispatch_getsocket(client->dispatch), result = isc_socket_sendto(socket, &r, client->task, client_senddone,
&r, client->task, client_senddone, client, client, address);
&client->dispevent->addr);
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
client->nsends++; client->nsends++;
@ -327,28 +372,43 @@ ns_client_error(ns_client_t *client, isc_result_t result) {
} }
static void 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; ns_client_t *client;
dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; dns_dispatchevent_t *devent;
isc_result_t result; isc_result_t result;
isc_buffer_t *buffer;
REQUIRE(devent != NULL); REQUIRE(event != NULL);
REQUIRE(devent->type == DNS_EVENT_DISPATCH); client = event->arg;
client = devent->arg;
REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(task == client->task); 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; CTRACE("request");
if (devent->result != ISC_R_SUCCESS) {
ns_client_destroy(client); 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; return;
} }
client->state = ns_clientstate_working; result = dns_message_parse(client->message, buffer);
result = dns_message_parse(client->message, &devent->buffer);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
ns_client_error(client, result); ns_client_error(client, result);
return; return;
@ -455,6 +515,8 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
client->dispatch = NULL; client->dispatch = NULL;
client->dispentry = NULL; client->dispentry = NULL;
client->dispevent = NULL; client->dispevent = NULL;
client->tcplistener = NULL;
client->tcpsocket = NULL;
client->nsends = 0; client->nsends = 0;
client->next = NULL; client->next = NULL;
ISC_LINK_INIT(client, link); ISC_LINK_INIT(client, link);
@ -494,6 +556,75 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
return (result); 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 *** Client Manager
@ -578,8 +709,7 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
} }
isc_result_t isc_result_t
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type, ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, unsigned int n,
unsigned int n,
dns_dispatch_t *dispatch) dns_dispatch_t *dispatch)
{ {
isc_result_t result = ISC_R_SUCCESS; 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++) { for (i = 0; i < n; i++) {
client = NULL; client = NULL;
result = client_create(manager, type, &client); result = client_create(manager, ns_clienttype_basic,
&client);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
break; break;
client->state = ns_clientstate_listening;
dns_dispatch_attach(dispatch, &client->dispatch); dns_dispatch_attach(dispatch, &client->dispatch);
result = dns_dispatch_addrequest(dispatch, client->task, result = dns_dispatch_addrequest(dispatch, client->task,
client_recv, client_request,
client, &client->dispentry); client, &client->dispentry);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
client_free(client); client_free(client);
break; 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++; manager->nclients++;
ISC_LIST_APPEND(manager->clients, client, link); ISC_LIST_APPEND(manager->clients, client, link);
} }

View File

@ -22,6 +22,7 @@
#include <isc/buffer.h> #include <isc/buffer.h>
#include <dns/types.h> #include <dns/types.h>
#include <dns/tcpmsg.h>
#include <named/types.h> #include <named/types.h>
#include <named/query.h> #include <named/query.h>
@ -30,12 +31,14 @@ typedef enum ns_clienttype {
ns_clienttype_basic = 0, ns_clienttype_basic = 0,
ns_clienttype_recursive, ns_clienttype_recursive,
ns_clienttype_axfr, ns_clienttype_axfr,
ns_clienttype_ixfr ns_clienttype_ixfr,
ns_clienttype_tcp
} ns_clienttype_t; } ns_clienttype_t;
typedef enum { typedef enum {
ns_clientstate_idle = 0, ns_clientstate_idle = 0,
ns_clientstate_listening, ns_clientstate_listening,
ns_clientstate_reading,
ns_clientstate_working, ns_clientstate_working,
ns_clientstate_waiting ns_clientstate_waiting
} ns_clientstate_t; } ns_clientstate_t;
@ -51,6 +54,9 @@ struct ns_client {
dns_dispatch_t * dispatch; dns_dispatch_t * dispatch;
dns_dispentry_t * dispentry; dns_dispentry_t * dispentry;
dns_dispatchevent_t * dispevent; dns_dispatchevent_t * dispevent;
isc_socket_t * tcplistener;
isc_socket_t * tcpsocket;
dns_tcpmsg_t tcpmsg;
isc_timer_t * timer; isc_timer_t * timer;
dns_message_t * message; dns_message_t * message;
unsigned int nsends; unsigned int nsends;
@ -64,6 +70,8 @@ struct ns_client {
#define NS_CLIENT_VALID(c) ((c) != NULL && \ #define NS_CLIENT_VALID(c) ((c) != NULL && \
(c)->magic == NS_CLIENT_MAGIC) (c)->magic == NS_CLIENT_MAGIC)
#define NS_CLIENTATTR_TCP 0x01
/* /*
* Note! These ns_client_ routines MUST be called ONLY from the client's * Note! These ns_client_ routines MUST be called ONLY from the client's
* task in order to ensure synchronization. * task in order to ensure synchronization.
@ -91,8 +99,11 @@ void
ns_clientmgr_destroy(ns_clientmgr_t **managerp); ns_clientmgr_destroy(ns_clientmgr_t **managerp);
isc_result_t isc_result_t
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type, ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, unsigned int n,
unsigned int n,
dns_dispatch_t *dispatch); 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 */ #endif /* NS_CLIENT_H */

View File

@ -50,12 +50,11 @@ EXTERN ns_interfacemgr_t * ns_g_interfacemgr INIT(NULL);
EXTERN ns_clientmgr_t * ns_g_clientmgr INIT(NULL); EXTERN ns_clientmgr_t * ns_g_clientmgr INIT(NULL);
EXTERN char * ns_g_version INIT(VERSION); EXTERN char * ns_g_version INIT(VERSION);
EXTERN isc_rwlock_t ns_g_viewlock; EXTERN dns_viewmgr_t * ns_g_viewmgr INIT(NULL);
EXTERN dns_viewlist_t ns_g_views;
/* XXXRTH These are temporary. */ /* XXXRTH These are temporary. */
EXTERN ns_dbinfolist_t ns_g_dbs; 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 EXTERN
#undef INIT #undef INIT

View File

@ -163,8 +163,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
isc_result_totext(result)); isc_result_totext(result));
goto udp_dispatch_failure; goto udp_dispatch_failure;
} }
result = ns_clientmgr_addtodispatch(mgr->clientmgr, result = ns_clientmgr_addtodispatch(mgr->clientmgr, ns_g_cpus,
ns_clienttype_basic, ns_g_cpus,
ifp->udpdispatch); ifp->udpdispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
@ -173,7 +172,6 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
goto addtodispatch_failure; goto addtodispatch_failure;
} }
#if 0
/* /*
* Open a TCP socket. * Open a TCP socket.
*/ */
@ -195,9 +193,21 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
isc_result_totext(result)); isc_result_totext(result));
goto tcp_bind_failure; goto tcp_bind_failure;
} }
#else result = isc_socket_listen(ifp->tcpsocket, 0);
ifp->tcpsocket = NULL; if (result != ISC_R_SUCCESS) {
#endif 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); 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); 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: addtodispatch_failure:
dns_dispatch_detach(&ifp->udpdispatch); dns_dispatch_detach(&ifp->udpdispatch);
udp_dispatch_failure: udp_dispatch_failure:
@ -232,10 +255,8 @@ ns_interface_destroy(ns_interface_t **ifpret) {
dns_dispatch_detach(&ifp->udpdispatch); dns_dispatch_detach(&ifp->udpdispatch);
isc_socket_detach(&ifp->udpsocket); isc_socket_detach(&ifp->udpsocket);
#if 0
isc_socket_cancel(ifp->tcpsocket, NULL, ISC_SOCKCANCEL_ALL); isc_socket_cancel(ifp->tcpsocket, NULL, ISC_SOCKCANCEL_ALL);
isc_socket_detach(&ifp->tcpsocket); isc_socket_detach(&ifp->tcpsocket);
#endif
isc_task_detach(&ifp->task); isc_task_detach(&ifp->task);

View File

@ -198,12 +198,14 @@ static void
setup() { setup() {
isc_result_t result; isc_result_t result;
#if 0
ISC_LIST_INIT(ns_g_views); ISC_LIST_INIT(ns_g_views);
result = isc_rwlock_init(&ns_g_viewlock, 0, 0); result = isc_rwlock_init(&ns_g_viewlock, 0, 0);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
early_fatal("isc_rwlock_init() failed: %s", early_fatal("isc_rwlock_init() failed: %s",
isc_result_totext(result)); isc_result_totext(result));
#endif
result = create_managers(); result = create_managers();
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
@ -219,7 +221,9 @@ setup() {
static void static void
cleanup() { cleanup() {
destroy_managers(); destroy_managers();
#if 0
isc_rwlock_destroy(&ns_g_viewlock); isc_rwlock_destroy(&ns_g_viewlock);
#endif
} }
int int

View File

@ -42,6 +42,9 @@
#include "../../isc/util.h" /* XXX */ #include "../../isc/util.h" /* XXX */
#define PARTIALANSWER(c) (((c)->query.attributes & \
NS_QUERYATTR_PARTIALANSWER) != 0)
static inline void static inline void
query_reset(ns_client_t *client, isc_boolean_t everything) { query_reset(ns_client_t *client, isc_boolean_t everything) {
isc_dynbuffer_t *dbuf, *dbuf_next; 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); (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 static isc_result_t
find(ns_client_t *client, dns_rdatatype_t type) { 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; isc_boolean_t first_time;
dns_rdata_t rdata; dns_rdata_t rdata;
/*
* XXXRTH
*
* This is still jury rigged.
*/
/* /*
* One-time initialization. * 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); for (rdataset = ISC_LIST_HEAD(client->query.qname->list);

View File

@ -58,278 +58,6 @@
static ns_dbinfo_t * cache_dbi; static ns_dbinfo_t * cache_dbi;
static isc_task_t * server_task; 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 static dns_result_t
load(ns_dbinfo_t *dbi) { load(ns_dbinfo_t *dbi) {
dns_fixedname_t forigin; dns_fixedname_t forigin;
@ -350,16 +78,13 @@ load(ns_dbinfo_t *dbi) {
result = dns_db_create(ns_g_mctx, "rbt", origin, dbi->iscache, result = dns_db_create(ns_g_mctx, "rbt", origin, dbi->iscache,
dns_rdataclass_in, 0, NULL, &dbi->db); dns_rdataclass_in, 0, NULL, &dbi->db);
if (result != DNS_R_SUCCESS) { if (result != DNS_R_SUCCESS)
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
return (result); return (result);
}
printf("loading %s (%s)\n", dbi->path, dbi->origin); printf("loading %s (%s)\n", dbi->path, dbi->origin);
result = dns_db_load(dbi->db, dbi->path); result = dns_db_load(dbi->db, dbi->path);
if (result != DNS_R_SUCCESS) { if (result != DNS_R_SUCCESS) {
dns_db_detach(&dbi->db); dns_db_detach(&dbi->db);
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
return (result); return (result);
} }
printf("loaded\n"); printf("loaded\n");
@ -401,14 +126,16 @@ unload_all(void) {
for (dbi = ISC_LIST_HEAD(ns_g_dbs); dbi != NULL; dbi = dbi_next) { for (dbi = ISC_LIST_HEAD(ns_g_dbs); dbi != NULL; dbi = dbi_next) {
dbi_next = ISC_LIST_NEXT(dbi, link); dbi_next = ISC_LIST_NEXT(dbi, link);
if (dns_db_iszone(dbi->db)) if (dbi->db != NULL) {
dns_dbtable_remove(ns_g_dbtable, dbi->db); if (dns_db_iszone(dbi->db))
else { dns_dbtable_remove(ns_g_dbtable, dbi->db);
INSIST(dbi == cache_dbi); else {
dns_dbtable_removedefault(ns_g_dbtable); INSIST(dbi == cache_dbi);
cache_dbi = NULL; 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_LIST_UNLINK(ns_g_dbs, dbi, link);
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi); 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 isc_result_t
ns_server_init(void) { ns_server_init(void) {
isc_result_t result; isc_result_t result;
#if 0
dns_view_t *view = NULL;
#endif
result = dns_dbtable_create(ns_g_mctx, dns_rdataclass_in, result = dns_dbtable_create(ns_g_mctx, dns_rdataclass_in,
&ns_g_dbtable); &ns_g_dbtable);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); 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); result = isc_task_create(ns_g_taskmgr, ns_g_mctx, 0, &server_task);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup_dbtable; goto cleanup_view;
result = isc_task_onshutdown(server_task, shutdown_server, NULL); result = isc_task_onshutdown(server_task, shutdown_server, NULL);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
@ -479,7 +216,12 @@ ns_server_init(void) {
cleanup_task: cleanup_task:
isc_task_detach(&server_task); isc_task_detach(&server_task);
cleanup_view:
#if 0
dns_view_detach(&view);
cleanup_dbtable: cleanup_dbtable:
#endif
dns_dbtable_detach(&ns_g_dbtable); dns_dbtable_detach(&ns_g_dbtable);
return (result); return (result);