mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-03 22:08:25 -04:00
checkpoint
This commit is contained in:
parent
5fc1b54cc6
commit
b4d7972545
6 changed files with 354 additions and 176 deletions
|
|
@ -40,9 +40,9 @@ LIBS = ${DEPLIBS} \
|
|||
|
||||
TARGETS = named
|
||||
|
||||
OBJS = client.o interfacemgr.o main.o server.o
|
||||
OBJS = client.o interfacemgr.o main.o query.o server.o
|
||||
|
||||
SRCS = client.c interfacemgr.c main.c server.c
|
||||
SRCS = client.c interfacemgr.c main.c query.c server.c
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
|
|
|
|||
|
|
@ -84,9 +84,19 @@ static void clientmgr_destroy(ns_clientmgr_t *manager);
|
|||
static inline void
|
||||
client_free(ns_client_t *client) {
|
||||
dns_dispatchevent_t **deventp;
|
||||
isc_dynbuffer_t *dbuf, *dbuf_next;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
CTRACE("free");
|
||||
|
||||
mctx = client->manager->mctx;
|
||||
for (dbuf = ISC_LIST_HEAD(client->namebufs);
|
||||
dbuf != NULL;
|
||||
dbuf = dbuf_next) {
|
||||
dbuf_next = ISC_LIST_NEXT(dbuf, link);
|
||||
isc_dynbuffer_free(mctx, &dbuf);
|
||||
}
|
||||
ISC_LIST_INIT(client->namebufs);
|
||||
isc_mempool_destroy(&client->sendbufs);
|
||||
dns_message_destroy(&client->message);
|
||||
isc_timer_detach(&client->timer);
|
||||
|
|
@ -104,7 +114,7 @@ client_free(ns_client_t *client) {
|
|||
isc_task_detach(&client->task);
|
||||
client->magic = 0;
|
||||
|
||||
isc_mem_put(client->manager->mctx, client, sizeof *client);
|
||||
isc_mem_put(mctx, client, sizeof *client);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -153,6 +163,7 @@ client_shutdown(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
void
|
||||
ns_client_next(ns_client_t *client, isc_result_t result) {
|
||||
isc_dynbuffer_t *dbuf, *dbuf_next;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(client->state == ns_clientstate_listening ||
|
||||
|
|
@ -167,6 +178,22 @@ ns_client_next(ns_client_t *client, isc_result_t result) {
|
|||
*/
|
||||
(void)result;
|
||||
|
||||
/*
|
||||
* Reset any changes made by answering a query. XXXRTH Should this
|
||||
* be in query.c? We'll free all but one namebuf.
|
||||
*/
|
||||
client->qname = NULL;
|
||||
INSIST(!ISC_LIST_EMPTY(client->namebufs));
|
||||
for (dbuf = ISC_LIST_HEAD(client->namebufs);
|
||||
dbuf != NULL;
|
||||
dbuf = dbuf_next) {
|
||||
dbuf_next = ISC_LIST_NEXT(dbuf, link);
|
||||
if (dbuf_next != NULL) {
|
||||
ISC_LIST_UNLINK(client->namebufs, dbuf, link);
|
||||
isc_dynbuffer_free(client->manager->mctx, &dbuf);
|
||||
}
|
||||
}
|
||||
|
||||
dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
|
||||
if (client->dispevent != NULL) {
|
||||
dns_dispatch_freeevent(client->dispatch, client->dispentry,
|
||||
|
|
@ -175,8 +202,6 @@ ns_client_next(ns_client_t *client, isc_result_t result) {
|
|||
}
|
||||
}
|
||||
|
||||
static void client_send(ns_client_t *client);
|
||||
|
||||
static void
|
||||
client_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client;
|
||||
|
|
@ -202,14 +227,14 @@ client_senddone(isc_task_t *task, isc_event_t *event) {
|
|||
*/
|
||||
if (client->state == ns_clientstate_waiting) {
|
||||
client->state = ns_clientstate_working;
|
||||
client_send(client);
|
||||
ns_client_send(client);
|
||||
return;
|
||||
}
|
||||
/* XXXRTH need to add exit draining mode. */
|
||||
}
|
||||
|
||||
static void
|
||||
client_send(ns_client_t *client) {
|
||||
void
|
||||
ns_client_send(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
unsigned char *data;
|
||||
isc_buffer_t buffer;
|
||||
|
|
@ -236,6 +261,10 @@ client_send(ns_client_t *client) {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXRTH The following doesn't deal with truncation, TSIGs,
|
||||
* or ENDS1 more data packets.
|
||||
*/
|
||||
isc_buffer_init(&buffer, data, SEND_BUFFER_SIZE,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
result = dns_message_renderbegin(client->message, &buffer);
|
||||
|
|
@ -245,11 +274,25 @@ client_send(ns_client_t *client) {
|
|||
DNS_SECTION_QUESTION, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
result = dns_message_rendersection(client->message,
|
||||
DNS_SECTION_ANSWER, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
result = dns_message_rendersection(client->message,
|
||||
DNS_SECTION_AUTHORITY, 0, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
result = dns_message_rendersection(client->message,
|
||||
DNS_SECTION_ADDITIONAL, 0, 0);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
|
||||
goto done;
|
||||
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. */
|
||||
/*
|
||||
* XXXRTH this only works for UDP clients.
|
||||
*/
|
||||
CTRACE("sendto");
|
||||
result = isc_socket_sendto(dns_dispatch_getsocket(client->dispatch),
|
||||
&r, client->task, client_senddone, client,
|
||||
|
|
@ -274,13 +317,19 @@ ns_client_error(ns_client_t *client, isc_result_t result) {
|
|||
|
||||
rcode = dns_result_torcode(result);
|
||||
|
||||
/*
|
||||
* client->message may be an in-progress reply that we had trouble
|
||||
* with, in which case QR will be set. We need to clear QR before
|
||||
* calling dns_message_reply() to avoid triggering an assertion.
|
||||
*/
|
||||
client->message->flags &= ~DNS_MESSAGEFLAG_QR;
|
||||
result = dns_message_reply(client->message, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_next(client, result);
|
||||
return;
|
||||
}
|
||||
client->message->rcode = rcode;
|
||||
client_send(client);
|
||||
ns_client_send(client);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -312,16 +361,16 @@ client_recv(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
INSIST((client->message->flags & DNS_MESSAGEFLAG_QR) == 0);
|
||||
|
||||
/* XXXRTH Find view here. */
|
||||
|
||||
/*
|
||||
* Dispatch the request.
|
||||
*/
|
||||
switch (client->message->opcode) {
|
||||
#if 0
|
||||
case dns_opcode_query:
|
||||
CTRACE("query");
|
||||
ns_query_start(client);
|
||||
break;
|
||||
#endif
|
||||
case dns_opcode_iquery:
|
||||
CTRACE("iquery");
|
||||
ns_client_error(client, DNS_R_REFUSED);
|
||||
|
|
@ -350,12 +399,30 @@ client_timeout(isc_task_t *task, isc_event_t *event) {
|
|||
ns_client_next(client, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_client_newnamebuf(ns_client_t *client) {
|
||||
isc_dynbuffer_t *dbuf;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
dbuf = NULL;
|
||||
result = isc_dynbuffer_allocate(client->manager->mctx, &dbuf, 1024,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
ISC_LIST_APPEND(client->namebufs, dbuf, link);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
||||
ns_client_t **clientp)
|
||||
{
|
||||
ns_client_t *client;
|
||||
isc_result_t result;
|
||||
isc_dynbuffer_t *dbuf;
|
||||
|
||||
/*
|
||||
* Caller must be holding the manager lock.
|
||||
|
|
@ -401,6 +468,11 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
|||
isc_mempool_setfreemax(client->sendbufs, 3);
|
||||
isc_mempool_setmaxalloc(client->sendbufs, 3);
|
||||
|
||||
/*
|
||||
* We do the rest of the initialization here because the
|
||||
* ns_client_newnamebuf() call below REQUIREs a valid client.
|
||||
*/
|
||||
client->magic = NS_CLIENT_MAGIC;
|
||||
client->manager = manager;
|
||||
client->type = type;
|
||||
client->state = ns_clientstate_idle;
|
||||
|
|
@ -408,9 +480,15 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
|||
client->dispatch = NULL;
|
||||
client->dispentry = NULL;
|
||||
client->dispevent = NULL;
|
||||
client->qname = NULL;
|
||||
client->nsends = 0;
|
||||
ISC_LIST_INIT(client->namebufs);
|
||||
ISC_LINK_INIT(client, link);
|
||||
client->magic = NS_CLIENT_MAGIC;
|
||||
|
||||
dbuf = NULL;
|
||||
result = ns_client_newnamebuf(client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_sendbufs;
|
||||
|
||||
CTRACE("create");
|
||||
|
||||
|
|
@ -418,6 +496,9 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
|
|||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_sendbufs:
|
||||
isc_mempool_destroy(&client->sendbufs);
|
||||
|
||||
cleanup_message:
|
||||
dns_message_destroy(&client->message);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ struct ns_client {
|
|||
dns_dispatchevent_t * dispevent;
|
||||
isc_timer_t * timer;
|
||||
dns_message_t * message;
|
||||
dns_name_t * qname;
|
||||
unsigned int nsends;
|
||||
isc_mempool_t * sendbufs;
|
||||
ISC_LIST(isc_dynbuffer_t) namebufs;
|
||||
ISC_LINK(struct ns_client) link;
|
||||
};
|
||||
|
||||
|
|
@ -70,9 +72,15 @@ ns_client_error(ns_client_t *client, isc_result_t result);
|
|||
void
|
||||
ns_client_next(ns_client_t *client, isc_result_t result);
|
||||
|
||||
void
|
||||
ns_client_send(ns_client_t *client);
|
||||
|
||||
void
|
||||
ns_client_destroy(ns_client_t *client);
|
||||
|
||||
isc_result_t
|
||||
ns_client_newnamebuf(ns_client_t *client);
|
||||
|
||||
isc_result_t
|
||||
ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, ns_clientmgr_t **managerp);
|
||||
|
|
|
|||
|
|
@ -53,8 +53,9 @@ EXTERN char * ns_g_version INIT(VERSION);
|
|||
EXTERN isc_rwlock_t ns_g_viewlock;
|
||||
EXTERN dns_viewlist_t ns_g_views;
|
||||
|
||||
/* XXXRTH This next one is temporary. */
|
||||
/* XXXRTH These are temporary. */
|
||||
EXTERN ns_dbinfolist_t ns_g_dbs;
|
||||
EXTERN dns_dbtable_t * ns_g_dbtable INIT(NULL);
|
||||
|
||||
#undef EXTERN
|
||||
#undef INIT
|
||||
|
|
|
|||
|
|
@ -18,192 +18,280 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <isc/assertions.h>
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/event.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbtable.h>
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
|
||||
#include <named/client.h>
|
||||
#include <named/events.h>
|
||||
#include <named/globals.h>
|
||||
#include <named/query.h>
|
||||
|
||||
#include "../../isc/util.h" /* XXX */
|
||||
|
||||
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;
|
||||
static isc_result_t
|
||||
find(ns_client_t *client, dns_rdatatype_t type) {
|
||||
isc_result_t result;
|
||||
dns_dbnode_t *node;
|
||||
dns_db_t *db;
|
||||
dns_name_t *fname, *tname;
|
||||
dns_rdataset_t *rdataset;
|
||||
dns_rdatasetiter_t *rdsiter;
|
||||
dns_rdatatype_t type;
|
||||
isc_boolean_t possibly_auth = ISC_FALSE;
|
||||
|
||||
message = NULL;
|
||||
result = dns_message_create(mctx, &message, DNS_MESSAGE_INTENTRENDER);
|
||||
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 */
|
||||
unsigned int section;
|
||||
isc_dynbuffer_t *dbuf;
|
||||
isc_region_t r;
|
||||
isc_buffer_t b;
|
||||
unsigned int cname_hops;
|
||||
unsigned int dname_hops;
|
||||
isc_boolean_t auth;
|
||||
isc_boolean_t again;
|
||||
isc_boolean_t first_time;
|
||||
dns_rdata_t rdata;
|
||||
|
||||
/*
|
||||
* Find a database to answer the query from.
|
||||
* One-time initialization.
|
||||
*/
|
||||
db = NULL;
|
||||
result = dns_dbtable_find(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;
|
||||
}
|
||||
|
||||
cname_hops = 0;
|
||||
dname_hops = 0;
|
||||
auth = ISC_FALSE;
|
||||
first_time = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* Now look for an answer in the database.
|
||||
* Find answers to questions.
|
||||
*/
|
||||
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:
|
||||
do {
|
||||
/*
|
||||
* Per iteration initialization.
|
||||
*/
|
||||
section = DNS_SECTION_ANSWER;
|
||||
again = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* Get the resources we'll need.
|
||||
*/
|
||||
dbuf = ISC_LIST_TAIL(client->namebufs);
|
||||
isc_buffer_available(&dbuf->buffer, &r);
|
||||
if (r.length < 255) {
|
||||
result = ns_client_newnamebuf(client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dbuf = ISC_LIST_TAIL(client->namebufs);
|
||||
isc_buffer_available(&dbuf->buffer, &r);
|
||||
INSIST(r.length >= 255);
|
||||
}
|
||||
isc_buffer_init(&b, r.base, r.length, ISC_BUFFERTYPE_BINARY);
|
||||
fname = NULL;
|
||||
result = dns_message_gettempname(client->message, &fname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dns_name_init(fname, NULL);
|
||||
dns_name_setbuffer(fname, &b);
|
||||
rdataset = NULL;
|
||||
result = dns_message_gettemprdataset(client->message,
|
||||
&rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dns_rdataset_init(rdataset);
|
||||
|
||||
/*
|
||||
* Find a database to answer the query.
|
||||
*/
|
||||
db = NULL;
|
||||
result = dns_dbtable_find(ns_g_dbtable, client->qname, &db);
|
||||
if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
|
||||
if (first_time)
|
||||
return (DNS_R_SERVFAIL);
|
||||
else
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now look for an answer in the database.
|
||||
*/
|
||||
if (dns_db_iszone(db))
|
||||
message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
auth = ISC_TRUE;
|
||||
node = NULL;
|
||||
result = dns_db_find(db, client->qname, NULL, type, 0, 0,
|
||||
&node, fname, rdataset);
|
||||
switch (result) {
|
||||
case DNS_R_SUCCESS:
|
||||
case DNS_R_DNAME:
|
||||
break;
|
||||
case DNS_R_CNAME:
|
||||
again = ISC_TRUE;
|
||||
cname_hops++;
|
||||
tname = NULL;
|
||||
result = dns_message_gettempname(client->message,
|
||||
&tname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rdataset;
|
||||
result = dns_rdataset_first(rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_rdataset;
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
r.base = rdata.data;
|
||||
r.length = rdata.length;
|
||||
dns_name_init(tname, NULL);
|
||||
dns_name_fromregion(tname, &r);
|
||||
client->qname = tname;
|
||||
break;
|
||||
case DNS_R_GLUE:
|
||||
case DNS_R_ZONECUT:
|
||||
case DNS_R_DELEGATION:
|
||||
auth = ISC_FALSE;
|
||||
break;
|
||||
case DNS_R_NXRDATASET:
|
||||
result = ISC_R_SUCCESS;
|
||||
goto cleanup_node;
|
||||
case DNS_R_NXDOMAIN:
|
||||
if (first_time)
|
||||
client->message->rcode = dns_rcode_nxdomain;
|
||||
result = ISC_R_SUCCESS;
|
||||
goto cleanup_db;
|
||||
default:
|
||||
result = DNS_R_SERVFAIL;
|
||||
goto cleanup_db;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record the space we consumed from the namebuf.
|
||||
*/
|
||||
dns_name_toregion(fname, &r);
|
||||
isc_buffer_add(&dbuf->buffer, r.length);
|
||||
|
||||
/*
|
||||
* This is not strictly necessary, but is done to emphasize
|
||||
* that the name's dedicated buffer, which is on our stack,
|
||||
* is no longer used. It also prevents any later accidental
|
||||
* use of the dedicated buffer.
|
||||
*/
|
||||
dns_name_setbuffer(fname, NULL);
|
||||
|
||||
if (result == DNS_R_DELEGATION) {
|
||||
/*
|
||||
* XXXRTH This is where we'll set up a resolver
|
||||
* fetch if recursion is allowed. We'll need
|
||||
* to handle the glue case too.
|
||||
* Also, we'll probably need to split find()
|
||||
* up into a series of event callbacks.
|
||||
*/
|
||||
section = DNS_SECTION_AUTHORITY;
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
} else if (type == dns_rdatatype_any) {
|
||||
/*
|
||||
* XXXRTH Need to handle zonecuts with special case
|
||||
* code.
|
||||
*/
|
||||
rdsiter = NULL;
|
||||
result = dns_db_allrdatasets(db, node, NULL, 0,
|
||||
&rdsiter);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_rdatasetiter_first(rdsiter);
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
dns_rdatasetiter_current(rdsiter, rdataset);
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
result = dns_message_gettemprdataset(
|
||||
client->message,
|
||||
&rdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_rdataset_init(rdataset);
|
||||
result = dns_rdatasetiter_next(rdsiter);
|
||||
}
|
||||
}
|
||||
if (result != DNS_R_NOMORE) {
|
||||
result = DNS_R_SERVFAIL;
|
||||
goto cleanup_node;
|
||||
}
|
||||
} else
|
||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||
|
||||
dns_message_addname(client->message, fname, section);
|
||||
|
||||
if (!auth && !first_time)
|
||||
client->message->flags &= ~DNS_MESSAGEFLAG_AA;
|
||||
|
||||
first_time = ISC_FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
} while (again && cname_hops < 8 && dname_hops < 16);
|
||||
|
||||
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);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
if (dns_db_iszone(db) && possibly_auth)
|
||||
message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
cleanup_rdataset:
|
||||
dns_rdataset_disassociate(rdataset);
|
||||
|
||||
cleanup_node:
|
||||
dns_db_detachnode(db, &node);
|
||||
|
||||
cleanup_db:
|
||||
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);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
ns_query_start(ns_client_t *client) {
|
||||
isc_result_t result;
|
||||
dns_rdataset_t *rdataset;
|
||||
unsigned int nquestions = 0;
|
||||
|
||||
result = dns_message_reply(client->message, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_next(client, result);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume authoritative response until it is known to be
|
||||
* otherwise.
|
||||
*/
|
||||
client->message->flags |= DNS_MESSAGEFLAG_AA;
|
||||
|
||||
/*
|
||||
* Answer each question.
|
||||
*/
|
||||
result = dns_message_firstname(client->message, DNS_SECTION_QUESTION);
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
nquestions++;
|
||||
client->qname = NULL;
|
||||
dns_message_currentname(client->message, DNS_SECTION_QUESTION,
|
||||
&client->qname);
|
||||
for (rdataset = ISC_LIST_HEAD(client->qname->list);
|
||||
rdataset != NULL;
|
||||
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
||||
result = find(client, rdataset->type);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_error(client, result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
result = dns_message_nextname(client->message,
|
||||
DNS_SECTION_QUESTION);
|
||||
}
|
||||
if (result != ISC_R_NOMORE) {
|
||||
ns_client_error(client, result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nquestions == 0) {
|
||||
ns_client_error(client, DNS_R_FORMERR);
|
||||
return;
|
||||
}
|
||||
|
||||
ns_client_send(client);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@
|
|||
#include "interfacemgr.h"
|
||||
#endif
|
||||
|
||||
static dns_dbtable_t * dbtable;
|
||||
static ns_dbinfo_t * cache_dbi;
|
||||
static isc_task_t * server_task;
|
||||
|
||||
|
|
@ -129,7 +128,7 @@ resolve_packet(isc_mem_t *mctx, dns_message_t *query, isc_buffer_t *target) {
|
|||
* Find a database to answer the query from.
|
||||
*/
|
||||
db = NULL;
|
||||
result = dns_dbtable_find(dbtable, qname, &db);
|
||||
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));
|
||||
|
|
@ -367,10 +366,10 @@ load(ns_dbinfo_t *dbi) {
|
|||
|
||||
if (dbi->iscache) {
|
||||
INSIST(cache_dbi == NULL);
|
||||
dns_dbtable_adddefault(dbtable, dbi->db);
|
||||
dns_dbtable_adddefault(ns_g_dbtable, dbi->db);
|
||||
cache_dbi = dbi;
|
||||
} else {
|
||||
if (dns_dbtable_add(dbtable, dbi->db) != DNS_R_SUCCESS) {
|
||||
if (dns_dbtable_add(ns_g_dbtable, dbi->db) != DNS_R_SUCCESS) {
|
||||
dns_db_detach(&dbi->db);
|
||||
isc_mem_put(ns_g_mctx, dbi, sizeof *dbi);
|
||||
return (result);
|
||||
|
|
@ -403,10 +402,10 @@ 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(dbtable, dbi->db);
|
||||
dns_dbtable_remove(ns_g_dbtable, dbi->db);
|
||||
else {
|
||||
INSIST(dbi == cache_dbi);
|
||||
dns_dbtable_removedefault(dbtable);
|
||||
dns_dbtable_removedefault(ns_g_dbtable);
|
||||
cache_dbi = NULL;
|
||||
}
|
||||
dns_db_detach(&dbi->db);
|
||||
|
|
@ -449,7 +448,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
|
|||
(void)task;
|
||||
printf("server shutting down\n");
|
||||
unload_all();
|
||||
dns_dbtable_detach(&dbtable);
|
||||
dns_dbtable_detach(&ns_g_dbtable);
|
||||
isc_task_detach(&server_task);
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
|
@ -458,7 +457,8 @@ isc_result_t
|
|||
ns_server_init(void) {
|
||||
isc_result_t result;
|
||||
|
||||
result = dns_dbtable_create(ns_g_mctx, dns_rdataclass_in, &dbtable);
|
||||
result = dns_dbtable_create(ns_g_mctx, dns_rdataclass_in,
|
||||
&ns_g_dbtable);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
|
|
@ -480,7 +480,7 @@ ns_server_init(void) {
|
|||
isc_task_detach(&server_task);
|
||||
|
||||
cleanup_dbtable:
|
||||
dns_dbtable_detach(&dbtable);
|
||||
dns_dbtable_detach(&ns_g_dbtable);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue