From b77cab68c65633bc534090b09fbac743b161f9b7 Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Thu, 5 Aug 1999 01:51:32 +0000 Subject: [PATCH] checkpoint; crude TCP support --- bin/named/client.c | 252 +++++++++++++++++++++--- bin/named/include/named/client.h | 17 +- bin/named/include/named/globals.h | 5 +- bin/named/interfacemgr.c | 37 +++- bin/named/main.c | 4 + bin/named/query.c | 38 +++- bin/named/server.c | 310 +++--------------------------- 7 files changed, 331 insertions(+), 332 deletions(-) diff --git a/bin/named/client.c b/bin/named/client.c index 5a6eb30414..d2ee0ee4e5 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -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); } diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index ffc70255e5..3afe53657f 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -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 */ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 34e6bdbf2b..40335c3826 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.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 diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index 212f803b47..834eee0d6c 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -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); diff --git a/bin/named/main.c b/bin/named/main.c index e81f6b48e2..ea3851dbff 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -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 diff --git a/bin/named/query.c b/bin/named/query.c index a2e7eef604..ff6c7b7d6c 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -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); diff --git a/bin/named/server.c b/bin/named/server.c index a958d81b34..9afbe24d17 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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);