2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00
This commit is contained in:
Bob Halley
1999-07-24 01:17:44 +00:00
parent af59277d9b
commit 7e6c9a9a73
10 changed files with 3421 additions and 0 deletions

568
bin/named/client.c Normal file
View File

@@ -0,0 +1,568 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <isc/assertions.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/result.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <dns/dispatch.h>
#include <dns/events.h>
#include <dns/message.h>
#include <named/client.h>
#include <named/query.h>
#include "../../isc/util.h" /* XXX */
#define NS_CLIENT_TRACE
#ifdef NS_CLIENT_TRACE
#include <stdio.h>
#define CTRACE(m) printf("client %p: %s\n", client, (m))
#define MTRACE(m) printf("clientmgr %p: %s\n", manager, (m))
#else
#define CTRACE(m)
#define MTRACE(m)
#endif
#define SEND_BUFFER_SIZE 512
struct ns_clientmgr {
/* Unlocked. */
unsigned int magic;
isc_mem_t * mctx;
isc_taskmgr_t * taskmgr;
isc_timermgr_t * timermgr;
isc_mutex_t lock;
/* Locked by lock. */
isc_boolean_t exiting;
unsigned int nclients;
ISC_LIST(ns_client_t) clients;
};
#define MANAGER_MAGIC 0x4E53436DU /* NSCm */
#define VALID_MANAGER(m) ((m) != NULL && \
(m)->magic == MANAGER_MAGIC)
static void clientmgr_destroy(ns_clientmgr_t *manager);
/***
*** Client
***/
/*
* Important note!
*
* All client state changes, other than that from idle to listening, occur
* as a result of events. This guarantees serialization and avoids the
* need for locking.
*
* If a routine is ever created that allows someone other than the client's
* task to change the client, then the client will have to be locked.
*/
static inline void
client_free(ns_client_t *client) {
dns_dispatchevent_t **deventp;
CTRACE("free");
isc_mempool_destroy(&client->sendbufs);
dns_message_destroy(&client->message);
isc_timer_detach(&client->timer);
if (client->dispentry != NULL) {
if (client->dispevent != NULL)
deventp = &client->dispevent;
else
deventp = NULL;
dns_dispatch_removerequest(client->dispatch,
&client->dispentry,
deventp);
}
if (client->dispatch != NULL)
dns_dispatch_detach(&client->dispatch);
isc_task_detach(&client->task);
client->magic = 0;
isc_mem_put(client->manager->mctx, client, sizeof *client);
}
void
ns_client_destroy(ns_client_t *client) {
ns_clientmgr_t *manager;
isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
REQUIRE(NS_CLIENT_VALID(client));
CTRACE("destroy");
manager = client->manager;
LOCK(&manager->lock);
INSIST(manager->nclients > 0);
manager->nclients--;
if (manager->nclients == 0 && manager->exiting)
need_clientmgr_destroy = ISC_TRUE;
ISC_LIST_UNLINK(manager->clients, client, link);
UNLOCK(&manager->lock);
client_free(client);
if (need_clientmgr_destroy)
clientmgr_destroy(manager);
}
static void
client_shutdown(isc_task_t *task, isc_event_t *event) {
ns_client_t *client;
REQUIRE(event != NULL);
REQUIRE(event->type == ISC_TASKEVENT_SHUTDOWN);
client = event->arg;
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(task == client->task);
CTRACE("shutdown");
ns_client_destroy(client);
isc_event_free(&event);
}
void
ns_client_next(ns_client_t *client, isc_result_t result) {
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(client->state == ns_clientstate_listening ||
client->state == ns_clientstate_working);
CTRACE("next");
/*
* 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;
}
}
static void client_send(ns_client_t *client);
static void
client_senddone(isc_task_t *task, isc_event_t *event) {
ns_client_t *client;
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
REQUIRE(sevent != NULL);
REQUIRE(sevent->common.type == ISC_SOCKEVENT_SENDDONE);
client = sevent->common.arg;
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(task == client->task);
CTRACE("senddone");
client->nsends--;
isc_mempool_put(client->sendbufs, sevent->region.base);
isc_event_free(&event);
/*
* If all of its sendbufs buffers were busy, the client might be
* waiting for one to become available.
*/
if (client->state == ns_clientstate_waiting) {
client->state = ns_clientstate_working;
client_send(client);
return;
}
/* XXXRTH need to add exit draining mode. */
}
static void
client_send(ns_client_t *client) {
isc_result_t result;
unsigned char *data;
isc_buffer_t buffer;
isc_region_t r;
REQUIRE(NS_CLIENT_VALID(client));
CTRACE("send");
data = isc_mempool_get(client->sendbufs);
if (data == NULL) {
CTRACE("no buffers available");
if (client->nsends > 0) {
/*
* We couldn't get memory, but there is at least one
* send outstanding. We arrange to be restarted when a
* send completes.
*/
CTRACE("waiting");
INSIST(client->state == ns_clientstate_working);
client->state = ns_clientstate_waiting;
} else
ns_client_next(client, ISC_R_NOMEMORY);
return;
}
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;
result = dns_message_rendersection(client->message,
DNS_SECTION_QUESTION, 0, 0);
if (result != ISC_R_SUCCESS)
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. */
CTRACE("sendto");
result = isc_socket_sendto(dns_dispatch_getsocket(client->dispatch),
&r, client->task, client_senddone, client,
&client->dispevent->addr);
if (result == ISC_R_SUCCESS)
client->nsends++;
done:
if (result != ISC_R_SUCCESS)
isc_mempool_put(client->sendbufs, data);
ns_client_next(client, result);
}
void
ns_client_error(ns_client_t *client, isc_result_t result) {
dns_rcode_t rcode;
REQUIRE(NS_CLIENT_VALID(client));
CTRACE("error");
rcode = dns_result_torcode(result);
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);
}
static void
client_recv(isc_task_t *task, isc_event_t *event) {
ns_client_t *client;
dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
isc_result_t result;
REQUIRE(devent != NULL);
REQUIRE(devent->type == DNS_EVENT_DISPATCH);
client = devent->arg;
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(task == client->task);
REQUIRE(client->dispentry != NULL);
CTRACE("recv");
client->dispevent = devent;
if (devent->result != ISC_R_SUCCESS) {
ns_client_destroy(client);
return;
}
client->state = ns_clientstate_working;
result = dns_message_parse(client->message, &devent->buffer);
if (result != ISC_R_SUCCESS) {
ns_client_error(client, result);
return;
}
INSIST((client->message->flags & DNS_MESSAGEFLAG_QR) == 0);
/*
* 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);
default:
CTRACE("unknown opcode");
ns_client_error(client, DNS_R_NOTIMP);
}
}
static void
client_timeout(isc_task_t *task, isc_event_t *event) {
ns_client_t *client;
REQUIRE(event != NULL);
REQUIRE(event->type == ISC_TIMEREVENT_LIFE ||
event->type == ISC_TIMEREVENT_IDLE);
client = event->arg;
REQUIRE(NS_CLIENT_VALID(client));
REQUIRE(task == client->task);
REQUIRE(client->timer != NULL);
CTRACE("timeout");
isc_event_free(&event);
ns_client_next(client, ISC_R_TIMEDOUT);
}
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;
/*
* Caller must be holding the manager lock.
*
* Note: creating a client does not add the client to the manager's
* client list. The caller is responsible for that.
*/
REQUIRE(clientp != NULL && *clientp == NULL);
client = isc_mem_get(manager->mctx, sizeof *client);
if (client == NULL)
return (ISC_R_NOMEMORY);
client->task = NULL;
result = isc_task_create(manager->taskmgr, manager->mctx, 0,
&client->task);
if (result != ISC_R_SUCCESS)
goto cleanup_client;
result = isc_task_onshutdown(client->task, client_shutdown, client);
if (result != ISC_R_SUCCESS)
goto cleanup_task;
client->timer = NULL;
result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
NULL, NULL, client->task, client_timeout,
client, &client->timer);
if (result != ISC_R_SUCCESS)
goto cleanup_task;
client->message = NULL;
result = dns_message_create(manager->mctx, DNS_MESSAGE_INTENTPARSE,
&client->message);
if (result != ISC_R_SUCCESS)
goto cleanup_timer;
/* XXXRTH Hardwired constants */
client->sendbufs = NULL;
result = isc_mempool_create(manager->mctx, SEND_BUFFER_SIZE,
&client->sendbufs);
if (result != ISC_R_SUCCESS)
goto cleanup_message;
isc_mempool_setfreemax(client->sendbufs, 3);
isc_mempool_setmaxalloc(client->sendbufs, 3);
client->manager = manager;
client->type = type;
client->state = ns_clientstate_idle;
client->attributes = 0;
client->dispatch = NULL;
client->dispentry = NULL;
client->dispevent = NULL;
client->nsends = 0;
ISC_LINK_INIT(client, link);
client->magic = NS_CLIENT_MAGIC;
CTRACE("create");
*clientp = client;
return (ISC_R_SUCCESS);
cleanup_message:
dns_message_destroy(&client->message);
cleanup_timer:
isc_timer_detach(&client->timer);
cleanup_task:
isc_task_detach(&client->task);
cleanup_client:
isc_mem_put(manager->mctx, client, sizeof *client);
return (result);
}
/***
*** Client Manager
***/
static void
clientmgr_destroy(ns_clientmgr_t *manager) {
REQUIRE(manager->nclients == 0);
REQUIRE(ISC_LIST_EMPTY(manager->clients));
MTRACE("clientmgr_destroy");
manager->magic = 0;
isc_mem_put(manager->mctx, manager, sizeof *manager);
}
isc_result_t
ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
{
ns_clientmgr_t *manager;
isc_result_t result;
manager = isc_mem_get(mctx, sizeof *manager);
if (manager == NULL)
return (ISC_R_NOMEMORY);
result = isc_mutex_init(&manager->lock);
if (result != ISC_R_SUCCESS)
goto cleanup_manager;
manager->mctx = mctx;
manager->taskmgr = taskmgr;
manager->timermgr = timermgr;
manager->exiting = ISC_FALSE;
manager->nclients = 0;
ISC_LIST_INIT(manager->clients);
manager->magic = MANAGER_MAGIC;
MTRACE("create");
*managerp = manager;
return (ISC_R_SUCCESS);
cleanup_manager:
isc_mem_put(manager->mctx, manager, sizeof *manager);
return (result);
}
void
ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
ns_clientmgr_t *manager;
ns_client_t *client;
isc_boolean_t need_destroy = ISC_FALSE;
REQUIRE(managerp != NULL);
manager = *managerp;
REQUIRE(VALID_MANAGER(manager));
MTRACE("destroy");
LOCK(&manager->lock);
manager->exiting = ISC_TRUE;
for (client = ISC_LIST_HEAD(manager->clients);
client != NULL;
client = ISC_LIST_NEXT(client, link))
isc_task_shutdown(client->task);
if (ISC_LIST_EMPTY(manager->clients))
need_destroy = ISC_TRUE;
UNLOCK(&manager->lock);
if (need_destroy)
clientmgr_destroy(manager);
*managerp = NULL;
}
isc_result_t
ns_clientmgr_addtodispatch(ns_clientmgr_t *manager, ns_clienttype_t type,
unsigned int n,
dns_dispatch_t *dispatch)
{
isc_result_t result = ISC_R_SUCCESS;
unsigned int i;
ns_client_t *client;
REQUIRE(VALID_MANAGER(manager));
REQUIRE(n > 0);
MTRACE("addtodispatch");
/*
* 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, type, &client);
if (result != ISC_R_SUCCESS)
break;
dns_dispatch_attach(dispatch, &client->dispatch);
result = dns_dispatch_addrequest(dispatch, client->task,
client_recv,
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);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef NS_CLIENT_H
#define NS_CLIENT_H 1
#include <isc/types.h>
#include <isc/buffer.h>
#include <dns/types.h>
#include <named/types.h>
typedef enum ns_clienttype {
ns_clienttype_basic = 0,
ns_clienttype_recursive,
ns_clienttype_axfr,
ns_clienttype_ixfr
} ns_clienttype_t;
typedef enum {
ns_clientstate_idle = 0,
ns_clientstate_listening,
ns_clientstate_working,
ns_clientstate_waiting
} ns_clientstate_t;
struct ns_client {
unsigned int magic;
ns_clientmgr_t * manager;
ns_clienttype_t type;
ns_clientstate_t state;
unsigned int attributes;
isc_task_t * task;
dns_dispatch_t * dispatch;
dns_dispentry_t * dispentry;
dns_dispatchevent_t * dispevent;
isc_timer_t * timer;
dns_message_t * message;
unsigned int nsends;
isc_mempool_t * sendbufs;
ISC_LINK(struct ns_client) link;
};
#define NS_CLIENT_MAGIC 0x4E534363U /* NSCc */
#define NS_CLIENT_VALID(c) ((c) != NULL && \
(c)->magic == NS_CLIENT_MAGIC)
/*
* Note! These ns_client_ routines MUST be called ONLY from the client's
* task in order to ensure synchronization.
*/
void
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_destroy(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);
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,
dns_dispatch_t *dispatch);
#endif /* NS_CLIENT_H */

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef NS_GLOBALS_H
#define NS_GLOBALS_H 1
#include <isc/types.h>
#include <isc/rwlock.h>
#include <dns/types.h>
#include <named/types.h>
#include <named/interfacemgr.h>
#undef EXTERN
#undef INIT
#ifdef NS_MAIN
#define EXTERN
#define INIT(v) = (v)
#else
#define EXTERN extern
#define INIT(v)
#endif
EXTERN isc_mem_t * ns_g_mctx INIT(NULL);
EXTERN unsigned int ns_g_cpus INIT(1);
EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL);
/*
* XXXRTH We're going to want multiple timer managers eventually. One
* for really short timers, another for client timers, and one
* for zone timers.
*/
EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL);
EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL);
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;
/* XXXRTH This next one is temporary. */
EXTERN ns_dbinfolist_t ns_g_dbs;
#undef EXTERN
#undef INIT
#endif /* NS_GLOBALS_H */

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef NS_QUERY_H
#define NS_QUERY_H 1
#include <named/types.h>
void ns_query_start(ns_client_t *client);
#endif /* NS_QUERY_H */

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef NS_SERVER_H
#define NS_SERVER_H 1
#include <isc/types.h>
isc_result_t ns_server_init(void);
#endif /* NS_SERVER_H */

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef NS_TYPES_H
#define NS_TYPES_H 1
#include <isc/list.h>
#include <dns/types.h>
typedef struct ns_client ns_client_t;
typedef struct ns_clientmgr ns_clientmgr_t;
/*
* XXXRTH This stuff is temporary. As soon as we have zone and config
* support, it will go away.
*/
typedef struct ns_dbinfo {
char * path;
char * origin;
isc_boolean_t iscache;
dns_db_t * db;
ISC_LINK(struct ns_dbinfo) link;
} ns_dbinfo_t;
typedef ISC_LIST(ns_dbinfo_t) ns_dbinfolist_t;
/*
* XXXRTH End of temporary stuff.
*/
#endif /* NS_TYPES_H */

263
bin/named/main.c Normal file
View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h> /* XXXRTH Naughty. Needed for getopt(). */
#include <isc/app.h>
#include <isc/error.h>
#include <isc/boolean.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <dns/dbtable.h>
#include <dns/result.h>
#include <dst/result.h>
#define NS_MAIN 1
#include <named/globals.h>
#include <named/client.h>
#include <named/interfacemgr.h>
#include <named/server.h>
static isc_boolean_t want_stats = ISC_FALSE;
static void
early_fatal(char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, "\n");
exit(1);
}
static void
usage(void) {
fprintf(stderr,
"usage: named [[-c cachefile] ...] [[-z zonefile] ...]\n");
fprintf(stderr,
" [-s] [-N number of cpus]\n");
}
static void
parse_command_line(int argc, char *argv[]) {
char *origintext;
int ch;
ns_dbinfo_t *dbi;
/*+ XXXRTH we need a veneered getopt() */
while ((ch = getopt(argc, argv, "c:N:sz:")) != -1) {
switch (ch) {
case 'c':
/* XXXRTH temporary syntax */
dbi = isc_mem_get(ns_g_mctx, sizeof *dbi);
if (dbi == NULL)
early_fatal("creating cache info failed");
dbi->path = optarg;
dbi->origin = ".";
dbi->iscache = ISC_TRUE;
dbi->db = NULL;
ISC_LINK_INIT(dbi, link);
ISC_LIST_APPEND(ns_g_dbs, dbi, link);
break;
case 'N':
ns_g_cpus = atoi(optarg);
if (ns_g_cpus == 0)
ns_g_cpus = 1;
break;
case 's':
/* XXXRTH temporary syntax */
want_stats = ISC_TRUE;
break;
case 'z':
/* XXXRTH temporary syntax */
origintext = strrchr(optarg, '/');
if (origintext == NULL)
origintext = optarg;
else
origintext++; /* Skip '/'. */
dbi = isc_mem_get(ns_g_mctx, sizeof *dbi);
if (dbi == NULL)
early_fatal("creating zone info failed");
dbi->path = optarg;
dbi->origin = origintext;
dbi->iscache = ISC_FALSE;
dbi->db = NULL;
ISC_LINK_INIT(dbi, link);
ISC_LIST_APPEND(ns_g_dbs, dbi, link);
break;
case '?':
usage();
early_fatal("unknown command line argument");
break;
default:
early_fatal("getopt() returned %d", ch);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
usage();
early_fatal("extra command line arguments");
}
}
static isc_result_t
create_managers() {
isc_result_t result;
result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"ns_taskmgr_create() failed: %s\n",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"ns_timermgr_create() failed: %s\n",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = isc_socketmgr_create(ns_g_mctx, &ns_g_socketmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_socketmgr_create() failed: %s\n",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = ns_clientmgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
&ns_g_clientmgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"ns_clientmgr_create() failed: %s\n",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
result = ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
ns_g_socketmgr, ns_g_clientmgr,
&ns_g_interfacemgr);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"ns_interfacemgr_create() failed: %s\n",
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
static void
destroy_managers(void) {
/*
* The interface manager owns tasks, so we have to destroy it before
* we destroy the task manager.
*/
ns_interfacemgr_destroy(&ns_g_interfacemgr);
/*
* isc_taskmgr_destroy() will block until all tasks have exited,
*/
isc_taskmgr_destroy(&ns_g_taskmgr);
isc_timermgr_destroy(&ns_g_timermgr);
isc_socketmgr_destroy(&ns_g_socketmgr);
ns_clientmgr_destroy(&ns_g_clientmgr);
}
static void
setup() {
isc_result_t result;
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));
result = create_managers();
if (result != ISC_R_SUCCESS)
early_fatal("create_managers() failed: %s",
isc_result_totext(result));
result = ns_server_init();
if (result != ISC_R_SUCCESS)
early_fatal("ns_server_init() failed: %s",
isc_result_totext(result));
}
static void
cleanup() {
destroy_managers();
isc_rwlock_destroy(&ns_g_viewlock);
}
int
main(int argc, char *argv[]) {
isc_result_t result;
result = isc_app_start();
if (result != ISC_R_SUCCESS)
early_fatal("isc_app_start() failed: %s",
isc_result_totext(result));
result = isc_mem_create(0, 0, &ns_g_mctx);
if (result != ISC_R_SUCCESS)
early_fatal("isc_mem_create() failed: %s",
isc_result_totext(result));
dns_result_register();
dst_result_register();
parse_command_line(argc, argv);
setup();
/*
* Start things running and then wait for a shutdown request.
*/
result = isc_app_run();
if (result != ISC_R_SUCCESS)
UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run(): %s",
isc_result_totext(result));
cleanup();
if (want_stats)
isc_mem_stats(ns_g_mctx, stdout);
isc_mem_destroy(&ns_g_mctx);
isc_app_finish();
return (0);
}

209
bin/named/query.c Normal file
View File

@@ -0,0 +1,209 @@
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <isc/assertions.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/result.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <dns/dispatch.h>
#include <dns/events.h>
#include <named/client.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;
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, &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 */
/*
* Find a database to answer the query from.
*/
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;
}
/*
* 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);
}
void
ns_query_start(ns_client_t *client) {
}

1011
doc/rfc/rfc1876.txt Normal file

File diff suppressed because it is too large Load Diff

1123
doc/rfc/rfc2168.txt Normal file

File diff suppressed because it is too large Load Diff