checkpoint; no memory leaks, finds run

This commit is contained in:
Michael Graff
2000-01-26 01:18:55 +00:00
parent 0974e30e20
commit ab41280797
4 changed files with 320 additions and 76 deletions

View File

@@ -58,6 +58,18 @@ hexdump(char *msg, void *base, size_t len)
printf("\n");
}
void
DP(int level, char *format, ...)
{
va_list args;
va_start(args, format);
isc_log_vwrite(dns_lctx,
DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
ISC_LOG_DEBUG(level), format, args);
va_end(args);
}
static void
clientmgr_can_die(clientmgr_t *cm)
{
@@ -276,6 +288,8 @@ client_send(isc_task_t *task, isc_event_t *ev)
INSIST(CLIENT_ISSEND(client));
INSIST(client->sendbuf == dev->region.base);
printf("Task %p for client %p got send-done event\n", task, client);
if (client->sendbuf != client->buffer)
lwres_context_freemem(cm->lwctx, client->sendbuf,
client->sendlength);
@@ -287,8 +301,6 @@ client_send(isc_task_t *task, isc_event_t *ev)
void
client_initialize(client_t *client, clientmgr_t *cmgr)
{
int i;
client->clientmgr = cmgr;
ISC_LINK_INIT(client, link);
CLIENT_SETIDLE(client);
@@ -299,15 +311,69 @@ client_initialize(client_t *client, clientmgr_t *cmgr)
client->sendbuf = NULL;
client->sendlength = 0;
client->find = NULL;
client->v4find = NULL;
client->v6find = NULL;
client->find_pending = 0;
client->find_wanted = 0;
for (i = 0 ; i < LWRES_MAX_ALIASES ; i++)
client->aliases[i] = NULL;
client->naliases = 0;
ISC_LIST_APPEND(cmgr->idle, client, link);
}
void
client_init_aliases(client_t *client)
{
int i;
for (i = 0 ; i < LWRES_MAX_ALIASES ; i++) {
client->aliases[i] = NULL;
client->aliaslen[i] = 0;
}
for (i = 0 ; i < LWRES_MAX_ADDRS ; i++) {
client->addrs[i].family = 0;
client->addrs[i].length = 0;
client->addrs[i].address = NULL;
}
}
void
client_init_gabn(client_t *client)
{
/*
* Initialize the real name and alias arrays in the reply we're
* going to build up.
*/
client_init_aliases(client);
client->gabn.naliases = 0;
client->gabn.naddrs = 0;
client->gabn.realname = NULL;
client->gabn.aliases = client->aliases;
client->gabn.realnamelen = 0;
client->gabn.aliaslen = client->aliaslen;
client->gabn.addrs = client->addrs;
client->gabn.base = NULL;
client->gabn.baselen = NULL;
/*
* Set up the internal buffer to point to the receive region.
*/
isc_buffer_init(&client->recv_buffer, client->buffer,
LWRES_RECVLENGTH, ISC_BUFFERTYPE_TEXT);
}
void
client_init_gnba(client_t *client)
{
/*
* Initialize the real name and alias arrays in the reply we're
* going to build up.
*/
client_init_aliases(client);
client->gnba.naliases = 0;
client->gnba.realname = NULL;
client->gnba.aliases = client->aliases;
client->gnba.realnamelen = 0;
client->gnba.aliaslen = client->aliaslen;
client->gnba.base = NULL;
client->gnba.baselen = NULL;
}

View File

@@ -21,6 +21,7 @@
#include <isc/event.h>
#include <isc/eventclass.h>
#include <isc/list.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
@@ -32,6 +33,7 @@
#include <dns/master.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/log.h>
#define LWRD_EVENTCLASS ISC_EVENTCLASS(4242)
@@ -64,12 +66,13 @@ struct client_s {
/*
* gabn (get address by name) state info.
*/
dns_adbfind_t *find;
dns_adbfind_t *v4find;
dns_adbfind_t *v6find;
unsigned int find_pending; /* Addresses remaining */
unsigned int find_wanted; /* Addresses we want */
dns_fixedname_t target_name;
lwres_gabnresponse_t gabn;
isc_buffer_t recv_buffer;
/*
* gnba (get name by address) state info.
@@ -77,15 +80,16 @@ struct client_s {
lwres_gnbaresponse_t gnba;
/*
* Alias info. This is copied up to the gabn/gnba structures
* eventually.
* Alias and address info. This is copied up to the gabn/gnba
* structures eventually.
*
* XXXMLG We can keep all of this in a client since we only service
* three packet types right now. If we started handling more,
* we'd need to use "arg" above and allocate/destroy things.
*/
char *aliases[LWRES_MAX_ALIASES];
unsigned int naliases;
u_int16_t aliaslen[LWRES_MAX_ALIASES];
lwres_addr_t addrs[LWRES_MAX_ADDRS];
};
/*
@@ -179,4 +183,10 @@ void process_noop(client_t *, lwres_buffer_t *);
void error_pkt_send(client_t *, isc_uint32_t);
void client_init_aliases(client_t *);
void client_init_gabn(client_t *);
void client_init_gnba(client_t *);
void DP(int level, char *format, ...);
#endif /* LWD_CLIENT_H */

View File

@@ -23,6 +23,7 @@
#include <isc/assertions.h>
#include <isc/event.h>
#include <isc/mem.h>
#include <isc/log.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
@@ -30,6 +31,7 @@
#include <isc/util.h>
#include <dns/rootns.h>
#include <dns/log.h>
#include <lwres/lwres.h>
@@ -136,6 +138,8 @@ main(int argc, char **argv)
isc_result_t result;
unsigned int i, j;
client_t *client;
isc_logdestination_t destination;
isc_log_t *lctx;
UNUSED(argc);
UNUSED(argv);
@@ -149,8 +153,31 @@ main(int argc, char **argv)
result = isc_mem_create(0, 0, &mem);
INSIST(result == ISC_R_SUCCESS);
cmgr = isc_mem_get(mem, sizeof(clientmgr_t) * NTASKS);
INSIST(cmgr != NULL);
/*
* Set up logging.
*/
lctx = NULL;
result = isc_log_create(mem, &lctx);
INSIST(result == ISC_R_SUCCESS);
result = dns_log_init(lctx);
INSIST(result == ISC_R_SUCCESS);
destination.file.stream = stderr;
destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0;
result = isc_log_createchannel(lctx, "_default",
ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC,
&destination, ISC_LOG_PRINTTIME);
INSIST(result == ISC_R_SUCCESS);
result = isc_log_usechannel(lctx, "_default", NULL, NULL);
INSIST(result == ISC_R_SUCCESS);
/*
* Set the initial debug level.
*/
isc_log_setdebuglevel(lctx, 99);
/*
* Create a task manager.
@@ -196,6 +223,9 @@ main(int argc, char **argv)
result = isc_socket_bind(sock, &localhost);
INSIST(result == ISC_R_SUCCESS);
cmgr = isc_mem_get(mem, sizeof(clientmgr_t) * NTASKS);
INSIST(cmgr != NULL);
/*
* Create one task for each client manager.
*/
@@ -308,6 +338,8 @@ main(int argc, char **argv)
isc_mem_put(mem, cmgr, sizeof(clientmgr_t) * NTASKS);
cmgr = NULL;
isc_log_destroy(&lctx);
/*
* Kill the memory system.
*/

View File

@@ -28,30 +28,152 @@
#include <isc/util.h>
#include <dns/fixedname.h>
#include <dns/adb.h>
#include <dns/events.h>
#include <lwres/lwres.h>
#include <lwres/result.h>
#include "client.h"
#define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
&& ((c)->v4find == NULL))
#define NEED_V6(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \
&& ((c)->v6find == NULL))
static void start_find(client_t *);
/*
* Destroy any finds. This can be used to "start over from scratch" and
* should only be called when events are _not_ being generated by the finds.
*/
static void
cleanup_gabn(client_t *client)
{
DP(50, "Cleaning up client %p\n");
if (client->v4find != NULL)
dns_adb_destroyfind(&client->v4find);
if (client->v6find != NULL)
dns_adb_destroyfind(&client->v6find);
}
static void
generate_reply(client_t *client)
{
DP(50, "Generating gabn reply for client %p\n");
cleanup_gabn(client);
client_state_idle(client);
}
/*
* Take the current real name, move it to an alias slot (if any are
* open) then put this new name in as the real name for the target.
*
* Return success if it can be rendered, otherwise failure. Note that
* not having enough alias slots open is NOT a failure.
*/
static isc_result_t
add_alias(client_t *client)
{
isc_buffer_t b;
isc_result_t result;
isc_uint16_t naliases;
b = client->recv_buffer;
/*
* Render the new name to the buffer.
*/
result = dns_name_totext(dns_fixedname_name(&client->target_name),
ISC_TRUE, &client->recv_buffer);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Are there any open slots?
*/
naliases = client->gabn.naliases;
if (naliases < LWRES_MAX_ALIASES) {
client->gabn.aliases[naliases] = client->gabn.realname;
client->gabn.aliaslen[naliases] = client->gabn.realnamelen;
client->gabn.naliases++;
}
/*
* Save this name away as the current real name.
*/
client->gabn.realname = b.base + b.used;
client->gabn.realnamelen = client->recv_buffer.used - b.used;
return (ISC_R_SUCCESS);
}
static void
process_gabn_finddone(isc_task_t *task, isc_event_t *ev)
{
client_t *client = ev->arg;
isc_eventtype_t result;
dns_adb_destroyfind(&client->v4find);
DP(50, "Find done for task %p, client %p", task, client);
result = ev->type;
isc_event_free(&ev);
/*
* No more info to be had? If so, we have all the good stuff
* right now, so we can render things.
*/
if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
if (NEED_V4(client)) {
client->v4find = client->find;
client->find = NULL;
} else if (NEED_V6(client)) {
client->v6find = client->find;
client->find = NULL;
} else {
dns_adb_destroyfind(&client->find);
}
generate_reply(client);
return;
}
/*
* We probably don't need this find anymore. We're either going to
* reissue it, or an error occurred. Either way, we're done with
* it.
*/
if ((client->find != client->v4find)
&& (client->find != client->v6find)) {
dns_adb_destroyfind(&client->find);
} else {
client->find = NULL;
}
/*
* We have some new information we can gather. Run off and fetch
* it.
*/
if (result == DNS_EVENT_ADBMOREADDRESSES) {
start_find(client);
return;
}
/*
* An error or other strangeness happened. Drop this query.
*/
cleanup_gabn(client);
error_pkt_send(client, LWRES_R_FAILURE);
}
static isc_result_t
start_v4find(client_t *client)
static void
start_find(client_t *client)
{
unsigned int options;
isc_result_t result;
dns_fixedname_t cname;
printf("Starting v4 find for client %p\n", client);
DP(50, "Starting find for client %p", client);
/*
* Issue a find for the name contained in the request. We won't
@@ -60,78 +182,89 @@ start_v4find(client_t *client)
*/
options = 0;
options |= DNS_ADBFIND_WANTEVENT;
options |= DNS_ADBFIND_INET;
/*
* Set the bits up here to mark that we want this address family
* and that we do not currently have a find pending. We will
* set that bit again below if it turns out we will get an event.
*/
INSIST((client->find_wanted & LWRES_ADDRTYPE_V4) != 0);
client->find_pending &= LWRES_ADDRTYPE_V4;
if (NEED_V4(client))
options |= DNS_ADBFIND_INET;
if (NEED_V6(client))
options |= DNS_ADBFIND_INET6;
dns_fixedname_init(&cname);
if (client->v4find != NULL)
dns_adb_destroyfind(&client->v4find);
INSIST(client->find == NULL);
find_again:
result = dns_adb_createfind(client->clientmgr->view->adb,
client->clientmgr->task,
process_gabn_finddone, client,
dns_fixedname_name(&client->target_name),
dns_rootname, options, 0,
dns_fixedname_name(&cname),
dns_fixedname_name(&client->target_name),
&client->v4find);
/*
* If we're going to get an event, set our internal pending flag.
* Did we get an error?
*/
if ((client->v4find->options & DNS_ADBFIND_WANTEVENT) != 0)
client->find_pending |= LWRES_ADDRTYPE_V4;
/*
* If we get here, we either have a find pending, or we have
* data. If we have all the data there is to be had, mark us as done.
* Otherwise, leave us running and let our event callback call
* us again.
*
* Eventually we'll get a valid result, either a list of addresses
* or failure.
*/
switch (result) {
if (result != ISC_R_SUCCESS && result != DNS_R_ALIAS) {
error_pkt_send(client, LWRES_R_FAILURE);
return;
}
/*
* If there is an event pending, wait for it. The event callback
* will kill this fetch and reissue it.
* Did we get an alias? If so, save it and re-issue the query.
*/
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
start_v6find(client_t *client)
{
unsigned int options;
isc_result_t result;
printf("Starting v6 find for client %p\n", client);
if (result == DNS_R_ALIAS) {
DP(50, "Found alias, restarting query.");
dns_adb_destroyfind(&client->find);
cleanup_gabn(client);
result = add_alias(client);
if (result != ISC_R_SUCCESS) {
DP(50, "Out of buffer space adding alias");
error_pkt_send(client, LWRES_R_FAILURE);
return;
}
goto find_again;
}
/*
* Issue a find for the name contained in the request. We won't
* set the bit that says "anything is good enough" -- we want it
* all.
* Did we get our answer to V4 addresses?
*/
options = 0;
options |= DNS_ADBFIND_WANTEVENT;
options |= DNS_ADBFIND_INET6;
if (NEED_V4(client)
&& ((client->find->query_pending & DNS_ADBFIND_INET) == 0))
client->v4find = client->find;
/*
* If there is an event pending, wait for it. The event callback
* will kill this fetch and reissue it.
* Did we get our answer to V6 addresses?
*/
return (ISC_R_NOTIMPLEMENTED);
}
if (NEED_V6(client)
&& ((client->find->query_pending & DNS_ADBFIND_INET6) == 0))
client->v6find = client->find;
/*
* If we're going to get an event, set our internal pending flag
* and return. When we get an event back we'll do the right
* thing, basically by calling this function again, perhaps with a
* new target name.
*
* If we have both v4 and v6, and we are still getting an event,
* we have a programming error, so die hard.
*/
if ((client->v4find->options & DNS_ADBFIND_WANTEVENT) != 0) {
DP(50, "Event will be sent.");
INSIST(client->v4find == NULL || client->v6find == NULL);
return;
}
DP(50, "No event will be sent.");
/*
* We seem to have everything we asked for, or at least we are
* able to respond with things we've learned.
*/
generate_reply(client);
}
/*
* When we are called, we can be assured that:
@@ -178,27 +311,30 @@ process_gabn(client_t *client, lwres_buffer_t *b)
if (result != ISC_R_SUCCESS)
goto out;
client->find_pending = 0;
client->find_wanted = req->addrtypes;
if ((req->addrtypes & LWRES_ADDRTYPE_V4) != 0) {
result = start_v4find(client);
if (result != ISC_R_SUCCESS)
goto out;
}
if ((req->addrtypes & LWRES_ADDRTYPE_V6) != 0) {
result = start_v6find(client);
if (result != ISC_R_SUCCESS)
goto out;
}
/*
* Start the find.
*/
start_find(client);
/*
* We no longer need to keep this around. Return success, and
* let the find*() functions drive us from now on.
* We no longer need to keep this around.
*/
lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
/*
* Initialize the real name and alias arrays in the reply we're
* going to build up.
*/
client_init_gabn(client);
/*
* Do we have all the bits we need to generate a reply?
*/
if (client->find == NULL) { /* XXXMLG */
}
return;
/*