mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 16:15:27 +00:00
First pass at merging lwresd into named. Seems to work, but doesn't shut down
properly. Run named with 'named -r' to test.
This commit is contained in:
@@ -22,7 +22,8 @@ top_srcdir = @top_srcdir@
|
||||
@BIND9_INCLUDES@
|
||||
|
||||
CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \
|
||||
${DNS_INCLUDES} ${ISC_INCLUDES} ${OMAPI_INCLUDES}
|
||||
${LWRES_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \
|
||||
${OMAPI_INCLUDES}
|
||||
|
||||
CDEFINES =
|
||||
CWARNINGS =
|
||||
@@ -30,14 +31,16 @@ CWARNINGS =
|
||||
OMAPILIBS = ../../lib/omapi/libomapi.@A@
|
||||
DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_OPENSSL_LIBS@
|
||||
ISCLIBS = ../../lib/isc/libisc.@A@
|
||||
LWRESLIBS = ../../lib/lwres/liblwres.@A@
|
||||
|
||||
OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@
|
||||
DNSDEPLIBS = ../../lib/dns/libdns.@A@
|
||||
ISCDEPLIBS = ../../lib/isc/libisc.@A@
|
||||
LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
|
||||
|
||||
DEPLIBS = ${OMAPIDEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
|
||||
DEPLIBS = ${LWRESDEPLIBS} ${OMAPIDEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
|
||||
|
||||
LIBS = ${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@
|
||||
LIBS = ${LWRESLIBS} ${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@
|
||||
|
||||
SUBDIRS = unix
|
||||
|
||||
@@ -45,13 +48,17 @@ TARGETS = named
|
||||
|
||||
OBJS = client.@O@ interfacemgr.@O@ listenlist.@O@ \
|
||||
log.@O@ logconf.@O@ main.@O@ notify.@O@ omapi.@O@ \
|
||||
query.@O@ server.@O@ update.@O@ xfrout.@O@
|
||||
query.@O@ server.@O@ update.@O@ xfrout.@O@ \
|
||||
lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
|
||||
lwdgnba.@O@ lwdnoop.@O@
|
||||
|
||||
UOBJS = unix/os.@O@
|
||||
|
||||
SRCS = client.c interfacemgr.c listenlist.c \
|
||||
log.c logconf.c main.c notify.c omapi.c \
|
||||
query.c server.c update.c xfrout.c
|
||||
query.c server.c update.c xfrout.c \
|
||||
lwresd.c lwdclient.c lwderror.c lwdgabn.c \
|
||||
lwdgnba.c lwdnoop.c
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
|
@@ -52,6 +52,7 @@ EXTERN const char * ns_g_version INIT(VERSION);
|
||||
EXTERN in_port_t ns_g_port INIT(0);
|
||||
|
||||
EXTERN ns_server_t * ns_g_server INIT(NULL);
|
||||
EXTERN ns_lwresd_t * ns_g_lwresd INIT(NULL);
|
||||
|
||||
/*
|
||||
* Logging.
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#define NS_LOGMODULE_XFER_OUT (&ns_g_modules[7])
|
||||
#define NS_LOGMODULE_NOTIFY (&ns_g_modules[8])
|
||||
#define NS_LOGMODULE_OMAPI (&ns_g_modules[9])
|
||||
#define NS_LOGMODULE_LWRESD (&ns_g_modules[10])
|
||||
|
||||
isc_result_t
|
||||
ns_log_init(isc_boolean_t safe);
|
||||
|
205
bin/named/include/named/lwdclient.h
Normal file
205
bin/named/include/named/lwdclient.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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 NAMED_LWDCLIENT_H
|
||||
#define NAMED_LWDCLIENT_H 1
|
||||
|
||||
#include <isc/event.h>
|
||||
#include <isc/eventclass.h>
|
||||
#include <isc/netaddr.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
#include <lwres/lwres.h>
|
||||
|
||||
#define LWRD_EVENTCLASS ISC_EVENTCLASS(4242)
|
||||
|
||||
#define LWRD_SHUTDOWN (LWRD_EVENTCLASS + 0x0001)
|
||||
|
||||
struct ns_lwdclient {
|
||||
isc_sockaddr_t address; /* where to reply */
|
||||
ns_lwdclientmgr_t *clientmgr; /* our parent */
|
||||
ISC_LINK(ns_lwdclient_t) link;
|
||||
unsigned int state;
|
||||
void *arg; /* packet processing state */
|
||||
|
||||
/*
|
||||
* Received data info.
|
||||
*/
|
||||
unsigned char buffer[LWRES_RECVLENGTH]; /* receive buffer */
|
||||
isc_uint32_t recvlength; /* length recv'd */
|
||||
lwres_lwpacket_t pkt;
|
||||
|
||||
/*
|
||||
* Send data state. If sendbuf != buffer (that is, the send buffer
|
||||
* isn't our receive buffer) it will be freed to the lwres_context_t.
|
||||
*/
|
||||
unsigned char *sendbuf;
|
||||
isc_uint32_t sendlength;
|
||||
isc_buffer_t recv_buffer;
|
||||
|
||||
/*
|
||||
* gabn (get address by name) state info.
|
||||
*/
|
||||
dns_adbfind_t *find;
|
||||
dns_adbfind_t *v4find;
|
||||
dns_adbfind_t *v6find;
|
||||
unsigned int find_wanted; /* Addresses we want */
|
||||
dns_fixedname_t target_name;
|
||||
lwres_gabnresponse_t gabn;
|
||||
|
||||
/*
|
||||
* gnba (get name by address) state info.
|
||||
*/
|
||||
lwres_gnbaresponse_t gnba;
|
||||
dns_byaddr_t *byaddr;
|
||||
unsigned int options;
|
||||
isc_netaddr_t na;
|
||||
dns_adbaddrinfo_t *addrinfo;
|
||||
|
||||
/*
|
||||
* 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];
|
||||
isc_uint16_t aliaslen[LWRES_MAX_ALIASES];
|
||||
lwres_addr_t addrs[LWRES_MAX_ADDRS];
|
||||
};
|
||||
|
||||
/*
|
||||
* Client states.
|
||||
*
|
||||
* _IDLE The client is not doing anything at all.
|
||||
*
|
||||
* _RECV The client is waiting for data after issuing a socket recv().
|
||||
*
|
||||
* _RECVDONE Data has been received, and is being processed.
|
||||
*
|
||||
* _FINDWAIT An adb (or other) request was made that cannot be satisfied
|
||||
* immediately. An event will wake the client up.
|
||||
*
|
||||
* _SEND All data for a response has completed, and a reply was
|
||||
* sent via a socket send() call.
|
||||
*
|
||||
* Badly formatted state table:
|
||||
*
|
||||
* IDLE -> RECV when client has a recv() queued.
|
||||
*
|
||||
* RECV -> RECVDONE when recvdone event received.
|
||||
*
|
||||
* RECVDONE -> SEND if the data for a reply is at hand.
|
||||
* RECVDONE -> FINDWAIT if more searching is needed, and events will
|
||||
* eventually wake us up again.
|
||||
*
|
||||
* FINDWAIT -> SEND when enough data was received to reply.
|
||||
*
|
||||
* SEND -> IDLE when a senddone event was received.
|
||||
*
|
||||
* At any time -> IDLE on error. Sometimes this will be -> SEND
|
||||
* instead, if enough data is on hand to reply with a meaningful
|
||||
* error.
|
||||
*
|
||||
* Packets which are badly formatted may or may not get error returns.
|
||||
*/
|
||||
#define NS_LWDCLIENT_STATEIDLE 1
|
||||
#define NS_LWDCLIENT_STATERECV 2
|
||||
#define NS_LWDCLIENT_STATERECVDONE 3
|
||||
#define NS_LWDCLIENT_STATEFINDWAIT 4
|
||||
#define NS_LWDCLIENT_STATESEND 5
|
||||
#define NS_LWDCLIENT_STATESENDDONE 6
|
||||
|
||||
#define NS_LWDCLIENT_ISIDLE(c) \
|
||||
((c)->state == NS_LWDCLIENT_STATEIDLE)
|
||||
#define NS_LWDCLIENT_ISRECV(c) \
|
||||
((c)->state == NS_LWDCLIENT_STATERECV)
|
||||
#define NS_LWDCLIENT_ISRECVDONE(c) \
|
||||
((c)->state == NS_LWDCLIENT_STATERECVDONE)
|
||||
#define NS_LWDCLIENT_ISFINDWAIT(c) \
|
||||
((c)->state == NS_LWDCLIENT_STATEFINDWAIT)
|
||||
#define NS_LWDCLIENT_ISSEND(c) \
|
||||
((c)->state == NS_LWDCLIENT_STATESEND)
|
||||
|
||||
/*
|
||||
* Overall magic test that means we're not idle.
|
||||
*/
|
||||
#define NS_LWDCLIENT_ISRUNNING(c) (!NS_LWDCLIENT_ISIDLE(c))
|
||||
|
||||
#define NS_LWDCLIENT_SETIDLE(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATEIDLE)
|
||||
#define NS_LWDCLIENT_SETRECV(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATERECV)
|
||||
#define NS_LWDCLIENT_SETRECVDONE(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATERECVDONE)
|
||||
#define NS_LWDCLIENT_SETFINDWAIT(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATEFINDWAIT)
|
||||
#define NS_LWDCLIENT_SETSEND(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATESEND)
|
||||
#define NS_LWDCLIENT_SETSENDDONE(c) \
|
||||
((c)->state = NS_LWDCLIENT_STATESENDDONE)
|
||||
|
||||
struct ns_lwdclientmgr {
|
||||
isc_mem_t *mctx;
|
||||
isc_task_t *task; /* owning task */
|
||||
isc_socket_t *sock; /* socket to use */
|
||||
dns_view_t *view;
|
||||
unsigned int flags;
|
||||
lwres_context_t *lwctx; /* lightweight proto context */
|
||||
ISC_LIST(ns_lwdclient_t) idle; /* idle client slots */
|
||||
ISC_LIST(ns_lwdclient_t) running; /* running clients */
|
||||
};
|
||||
|
||||
#define NS_LWDCLIENTMGR_FLAGRECVPENDING 0x00000001
|
||||
#define NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN 0x00000002
|
||||
|
||||
void
|
||||
ns_lwdclient_initialize(ns_lwdclient_t *, ns_lwdclientmgr_t *);
|
||||
|
||||
isc_result_t
|
||||
ns_lwdclient_startrecv(ns_lwdclientmgr_t *);
|
||||
|
||||
void
|
||||
ns_lwdclient_stateidle(ns_lwdclient_t *);
|
||||
|
||||
void
|
||||
ns_lwdclient_recv(isc_task_t *, isc_event_t *);
|
||||
|
||||
void
|
||||
ns_lwdclient_shutdown(isc_task_t *, isc_event_t *);
|
||||
|
||||
void
|
||||
ns_lwdclient_send(isc_task_t *, isc_event_t *);
|
||||
|
||||
/*
|
||||
* Processing functions of various types.
|
||||
*/
|
||||
void ns_lwdclient_processgabn(ns_lwdclient_t *, lwres_buffer_t *);
|
||||
void ns_lwdclient_processgnba(ns_lwdclient_t *, lwres_buffer_t *);
|
||||
void ns_lwdclient_processnoop(ns_lwdclient_t *, lwres_buffer_t *);
|
||||
|
||||
void ns_lwdclient_errorpktsend(ns_lwdclient_t *, isc_uint32_t);
|
||||
|
||||
void DP(int level, const char *format, ...);
|
||||
void hexdump(char *msg, void *base, size_t len);
|
||||
|
||||
#endif /* NAMED_LWDCLIENT_H */
|
45
bin/named/include/named/lwresd.h
Normal file
45
bin/named/include/named/lwresd.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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 NAMED_LWRESD_H
|
||||
#define NAMED_LWRESD_H 1
|
||||
|
||||
#include <isc/types.h>
|
||||
#include <isc/sockaddr.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
struct ns_lwresd {
|
||||
isc_uint32_t magic;
|
||||
ns_lwdclientmgr_t *cmgr;
|
||||
isc_socket_t *sock;
|
||||
unsigned int ntasks;
|
||||
dns_view_t *view;
|
||||
isc_mem_t *mctx;
|
||||
isc_task_t *task;
|
||||
};
|
||||
|
||||
void
|
||||
ns_lwresd_create(isc_mem_t *mctx, dns_view_t *view, ns_lwresd_t **lwresdp);
|
||||
|
||||
isc_result_t
|
||||
ns_lwresd_createview(isc_mem_t *mctx, dns_view_t **viewp);
|
||||
|
||||
void
|
||||
ns_lwresd_destroy(ns_lwresd_t **lwresdp);
|
||||
|
||||
#endif /* NAMED_LWRESD_H */
|
@@ -26,5 +26,8 @@ typedef struct ns_query ns_query_t;
|
||||
typedef struct ns_server ns_server_t;
|
||||
typedef struct ns_interface ns_interface_t;
|
||||
typedef struct ns_interfacemgr ns_interfacemgr_t;
|
||||
typedef struct ns_lwresd ns_lwresd_t;
|
||||
typedef struct ns_lwdclient ns_lwdclient_t;
|
||||
typedef struct ns_lwdclientmgr ns_lwdclientmgr_t;
|
||||
|
||||
#endif /* NAMED_TYPES_H */
|
||||
|
@@ -45,6 +45,8 @@ static isc_logmodule_t modules[] = {
|
||||
{ "xfer-in", 0 },
|
||||
{ "xfer-out", 0 },
|
||||
{ "notify", 0 },
|
||||
{ "omapi", 0 },
|
||||
{ "lwresd", 0 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
328
bin/named/lwdclient.c
Normal file
328
bin/named/lwdclient.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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/socket.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/view.h>
|
||||
#include <dns/log.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/lwdclient.h>
|
||||
|
||||
void
|
||||
DP(int level, const char *format, ...) {
|
||||
va_list args;
|
||||
|
||||
level = 1;
|
||||
va_start(args, format);
|
||||
isc_log_vwrite(dns_lctx,
|
||||
DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
|
||||
ISC_LOG_DEBUG(level), format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
hexdump(char *msg, void *base, size_t len) {
|
||||
unsigned char *p;
|
||||
unsigned int cnt;
|
||||
char buffer[180];
|
||||
char *n;
|
||||
|
||||
p = base;
|
||||
cnt = 0;
|
||||
n = buffer;
|
||||
*n = 0;
|
||||
|
||||
printf("*** %s (%u bytes @ %p)\n", msg, len, base);
|
||||
|
||||
while (cnt < len) {
|
||||
if (cnt % 16 == 0) {
|
||||
n = buffer;
|
||||
n += sprintf(buffer, "%p: ", p);
|
||||
} else if (cnt % 8 == 0) {
|
||||
*n++ = ' ';
|
||||
*n++ = '|';
|
||||
*n = 0;
|
||||
}
|
||||
n += sprintf(n, " %02x", *p++);
|
||||
cnt++;
|
||||
|
||||
if (cnt % 16 == 0) {
|
||||
DP(80, buffer);
|
||||
n = buffer;
|
||||
*n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (n != buffer) {
|
||||
DP(80, buffer);
|
||||
n = buffer;
|
||||
*n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clientmgr_can_die(ns_lwdclientmgr_t *cm) {
|
||||
if ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) == 0)
|
||||
return;
|
||||
|
||||
if (ISC_LIST_HEAD(cm->running) != NULL)
|
||||
return;
|
||||
|
||||
lwres_context_destroy(&cm->lwctx);
|
||||
dns_view_detach(&cm->view);
|
||||
isc_task_detach(&cm->task);
|
||||
}
|
||||
|
||||
static void
|
||||
process_request(ns_lwdclient_t *client) {
|
||||
lwres_buffer_t b;
|
||||
isc_result_t result;
|
||||
|
||||
lwres_buffer_init(&b, client->buffer, client->recvlength);
|
||||
lwres_buffer_add(&b, client->recvlength);
|
||||
|
||||
result = lwres_lwpacket_parseheader(&b, &client->pkt);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
DP(50, "invalid packet header received");
|
||||
goto restart;
|
||||
}
|
||||
|
||||
DP(50, "opcode %08x", client->pkt.opcode);
|
||||
|
||||
switch (client->pkt.opcode) {
|
||||
case LWRES_OPCODE_GETADDRSBYNAME:
|
||||
ns_lwdclient_processgabn(client, &b);
|
||||
return;
|
||||
case LWRES_OPCODE_GETNAMEBYADDR:
|
||||
ns_lwdclient_processgnba(client, &b);
|
||||
return;
|
||||
case LWRES_OPCODE_NOOP:
|
||||
ns_lwdclient_processnoop(client, &b);
|
||||
return;
|
||||
default:
|
||||
DP(50, "unknown opcode %08x", client->pkt.opcode);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the packet.
|
||||
*/
|
||||
restart:
|
||||
DP(50, "restarting client %p...", client);
|
||||
ns_lwdclient_stateidle(client);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
|
||||
ns_lwdclient_t *client = ev->ev_arg;
|
||||
ns_lwdclientmgr_t *cm = client->clientmgr;
|
||||
isc_socketevent_t *dev = (isc_socketevent_t *)ev;
|
||||
|
||||
INSIST(dev->region.base == client->buffer);
|
||||
INSIST(NS_LWDCLIENT_ISRECV(client));
|
||||
|
||||
NS_LWDCLIENT_SETRECVDONE(client);
|
||||
|
||||
INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
|
||||
cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
|
||||
|
||||
DP(50, "event received: task %p, length %u, result %u (%s)",
|
||||
task, dev->n, dev->result, isc_result_totext(dev->result));
|
||||
|
||||
if (dev->result != ISC_R_SUCCESS) {
|
||||
isc_event_free(&ev);
|
||||
dev = NULL;
|
||||
|
||||
/*
|
||||
* Go idle.
|
||||
*/
|
||||
ns_lwdclient_stateidle(client);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXMLG If we wanted to run on ipv6 as well, we'd need the pktinfo
|
||||
* bits. Right now we don't, so don't remember them.
|
||||
*/
|
||||
client->recvlength = dev->n;
|
||||
client->address = dev->address;
|
||||
isc_event_free(&ev);
|
||||
dev = NULL;
|
||||
|
||||
ns_lwdclient_startrecv(cm);
|
||||
|
||||
process_request(client);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will start a new recv() on a socket for this client manager.
|
||||
*/
|
||||
isc_result_t
|
||||
ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
|
||||
ns_lwdclient_t *client;
|
||||
isc_result_t result;
|
||||
isc_region_t r;
|
||||
|
||||
if ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) != 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* If a recv is already running, don't bother.
|
||||
*/
|
||||
if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* If we have no idle slots, just return success.
|
||||
*/
|
||||
client = ISC_LIST_HEAD(cm->idle);
|
||||
if (client == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
INSIST(NS_LWDCLIENT_ISIDLE(client));
|
||||
|
||||
/*
|
||||
* Issue the recv. If it fails, return that it did.
|
||||
*/
|
||||
r.base = client->buffer;
|
||||
r.length = LWRES_RECVLENGTH;
|
||||
result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
|
||||
client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
/*
|
||||
* Set the flag to say we've issued a recv() call.
|
||||
*/
|
||||
cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;
|
||||
|
||||
/*
|
||||
* Remove the client from the idle list, and put it on the running
|
||||
* list.
|
||||
*/
|
||||
NS_LWDCLIENT_SETRECV(client);
|
||||
ISC_LIST_UNLINK(cm->idle, client, link);
|
||||
ISC_LIST_APPEND(cm->running, client, link);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwdclient_shutdown(isc_task_t *task, isc_event_t *ev) {
|
||||
ns_lwdclientmgr_t *cm = ev->ev_arg;
|
||||
|
||||
REQUIRE((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) == 0);
|
||||
|
||||
DP(50, "got shutdown event, task %p", task);
|
||||
|
||||
/*
|
||||
* Cancel any pending I/O.
|
||||
*/
|
||||
if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0)
|
||||
isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL);
|
||||
|
||||
/*
|
||||
* Run through the running client list and kill off any finds
|
||||
* in progress.
|
||||
*/
|
||||
/* XXXMLG */
|
||||
|
||||
cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
|
||||
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do all the crap needed to move a client from the run queue to the idle
|
||||
* queue.
|
||||
*/
|
||||
void
|
||||
ns_lwdclient_stateidle(ns_lwdclient_t *client) {
|
||||
ns_lwdclientmgr_t *cm;
|
||||
|
||||
cm = client->clientmgr;
|
||||
|
||||
INSIST(client->sendbuf == NULL);
|
||||
INSIST(client->sendlength == 0);
|
||||
INSIST(client->arg == NULL);
|
||||
INSIST(client->v4find == NULL);
|
||||
INSIST(client->v6find == NULL);
|
||||
|
||||
ISC_LIST_UNLINK(cm->running, client, link);
|
||||
ISC_LIST_PREPEND(cm->idle, client, link);
|
||||
|
||||
NS_LWDCLIENT_SETIDLE(client);
|
||||
|
||||
clientmgr_can_die(cm);
|
||||
|
||||
ns_lwdclient_startrecv(cm);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwdclient_send(isc_task_t *task, isc_event_t *ev) {
|
||||
ns_lwdclient_t *client = ev->ev_arg;
|
||||
ns_lwdclientmgr_t *cm = client->clientmgr;
|
||||
isc_socketevent_t *dev = (isc_socketevent_t *)ev;
|
||||
|
||||
UNUSED(task);
|
||||
UNUSED(dev);
|
||||
|
||||
INSIST(NS_LWDCLIENT_ISSEND(client));
|
||||
INSIST(client->sendbuf == dev->region.base);
|
||||
|
||||
DP(50, "task %p for client %p got send-done event", task, client);
|
||||
|
||||
if (client->sendbuf != client->buffer)
|
||||
lwres_context_freemem(cm->lwctx, client->sendbuf,
|
||||
client->sendlength);
|
||||
client->sendbuf = NULL;
|
||||
client->sendlength = 0;
|
||||
|
||||
ns_lwdclient_stateidle(client);
|
||||
|
||||
isc_event_free(&ev);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwdclient_initialize(ns_lwdclient_t *client, ns_lwdclientmgr_t *cmgr) {
|
||||
client->clientmgr = cmgr;
|
||||
ISC_LINK_INIT(client, link);
|
||||
NS_LWDCLIENT_SETIDLE(client);
|
||||
client->arg = NULL;
|
||||
|
||||
client->recvlength = 0;
|
||||
|
||||
client->sendbuf = NULL;
|
||||
client->sendlength = 0;
|
||||
|
||||
client->find = NULL;
|
||||
client->v4find = NULL;
|
||||
client->v6find = NULL;
|
||||
client->find_wanted = 0;
|
||||
|
||||
client->options = 0;
|
||||
client->byaddr = NULL;
|
||||
client->addrinfo = NULL;
|
||||
|
||||
ISC_LIST_APPEND(cmgr->idle, client, link);
|
||||
}
|
80
bin/named/lwderror.c
Normal file
80
bin/named/lwderror.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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/socket.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/lwdclient.h>
|
||||
|
||||
/*
|
||||
* Generate an error packet for the client, schedule a send, and put us in
|
||||
* the SEND state.
|
||||
*
|
||||
* The client->pkt structure will be modified to form an error return.
|
||||
* The receiver needs to verify that it is in fact an error, and do the
|
||||
* right thing with it. The opcode will be unchanged. The result needs
|
||||
* to be set before calling this function.
|
||||
*
|
||||
* The only change this code makes is to set the receive buffer size to the
|
||||
* size we use, set the reply bit, and recompute any security information.
|
||||
*/
|
||||
void
|
||||
ns_lwdclient_errorpktsend(ns_lwdclient_t *client, isc_uint32_t _result) {
|
||||
isc_result_t result;
|
||||
int lwres;
|
||||
isc_region_t r;
|
||||
lwres_buffer_t b;
|
||||
ns_lwdclientmgr_t *cm;
|
||||
|
||||
cm = client->clientmgr;
|
||||
|
||||
REQUIRE(NS_LWDCLIENT_ISRUNNING(client));
|
||||
|
||||
/*
|
||||
* Since we are only sending the packet header, we can safely toss
|
||||
* the receive buffer. This means we won't need to allocate space
|
||||
* for sending an error reply. This is a Good Thing.
|
||||
*/
|
||||
client->pkt.length = LWRES_LWPACKET_LENGTH;
|
||||
client->pkt.pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
|
||||
client->pkt.recvlength = LWRES_RECVLENGTH;
|
||||
client->pkt.authtype = 0; /* XXXMLG */
|
||||
client->pkt.authlength = 0;
|
||||
client->pkt.result = _result;
|
||||
|
||||
lwres_buffer_init(&b, client->buffer, LWRES_RECVLENGTH);
|
||||
lwres = lwres_lwpacket_renderheader(&b, &client->pkt);
|
||||
if (lwres != LWRES_R_SUCCESS) {
|
||||
ns_lwdclient_stateidle(client);
|
||||
return;
|
||||
}
|
||||
|
||||
r.base = client->buffer;
|
||||
r.length = b.used;
|
||||
client->sendbuf = client->buffer;
|
||||
result = isc_socket_sendto(cm->sock, &r, cm->task, ns_lwdclient_send,
|
||||
client, &client->address, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_lwdclient_stateidle(client);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_LWDCLIENT_SETSEND(client);
|
||||
}
|
561
bin/named/lwdgabn.c
Normal file
561
bin/named/lwdgabn.c
Normal file
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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/socket.h>
|
||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/adb.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/lwdclient.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(ns_lwdclient_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(ns_lwdclient_t *client) {
|
||||
dns_adbfind_t *v4;
|
||||
|
||||
DP(50, "cleaning up client %p", client);
|
||||
|
||||
v4 = client->v4find;
|
||||
|
||||
if (client->v4find != NULL)
|
||||
dns_adb_destroyfind(&client->v4find);
|
||||
if (client->v6find != NULL) {
|
||||
if (client->v6find == v4)
|
||||
client->v6find = NULL;
|
||||
else
|
||||
dns_adb_destroyfind(&client->v6find);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
|
||||
dns_adbaddrinfo_t *ai;
|
||||
lwres_addr_t *addr;
|
||||
int af;
|
||||
const struct sockaddr *sa;
|
||||
const struct sockaddr_in *sin;
|
||||
const struct sockaddr_in6 *sin6;
|
||||
|
||||
if (at == DNS_ADBFIND_INET)
|
||||
af = AF_INET;
|
||||
else
|
||||
af = AF_INET6;
|
||||
|
||||
ai = ISC_LIST_HEAD(find->list);
|
||||
while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) {
|
||||
sa = &ai->sockaddr.type.sa;
|
||||
if (sa->sa_family != af)
|
||||
goto next;
|
||||
|
||||
addr = &client->addrs[client->gabn.naddrs];
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
sin = &ai->sockaddr.type.sin;
|
||||
addr->family = LWRES_ADDRTYPE_V4;
|
||||
memcpy(addr->address, &sin->sin_addr, 4);
|
||||
addr->length = 4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sin6 = &ai->sockaddr.type.sin6;
|
||||
addr->family = LWRES_ADDRTYPE_V6;
|
||||
memcpy(addr->address, &sin6->sin6_addr, 16);
|
||||
addr->length = 16;
|
||||
break;
|
||||
default:
|
||||
goto next;
|
||||
}
|
||||
|
||||
DP(50, "adding address %p, family %d, length %d",
|
||||
addr->address, addr->family, addr->length);
|
||||
|
||||
client->gabn.naddrs++;
|
||||
REQUIRE(!LWRES_LINK_LINKED(addr, link));
|
||||
LWRES_LIST_APPEND(client->gabn.addrs, addr, link);
|
||||
|
||||
next:
|
||||
ai = ISC_LIST_NEXT(ai, publink);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
generate_reply(ns_lwdclient_t *client) {
|
||||
isc_result_t result;
|
||||
int lwres;
|
||||
isc_region_t r;
|
||||
lwres_buffer_t lwb;
|
||||
ns_lwdclientmgr_t *cm;
|
||||
|
||||
cm = client->clientmgr;
|
||||
lwb.base = NULL;
|
||||
|
||||
DP(50, "generating gabn reply for client %p", client);
|
||||
|
||||
/*
|
||||
* We must make certain the client->find is not still active.
|
||||
* If it is either the v4 or v6 answer, just set it to NULL and
|
||||
* let the cleanup code destroy it. Otherwise, destroy it now.
|
||||
*/
|
||||
if (client->find == client->v4find || client->find == client->v6find)
|
||||
client->find = NULL;
|
||||
else
|
||||
if (client->find != NULL)
|
||||
dns_adb_destroyfind(&client->find);
|
||||
|
||||
/*
|
||||
* perhaps there are some here?
|
||||
*/
|
||||
if (NEED_V6(client) && client->v4find != NULL)
|
||||
client->v6find = client->v4find;
|
||||
|
||||
/*
|
||||
* Run through the finds we have and wire them up to the gabn
|
||||
* structure.
|
||||
*/
|
||||
LWRES_LIST_INIT(client->gabn.addrs);
|
||||
if (client->v4find != NULL)
|
||||
setup_addresses(client, client->v4find, DNS_ADBFIND_INET);
|
||||
if (client->v6find != NULL)
|
||||
setup_addresses(client, client->v6find, DNS_ADBFIND_INET6);
|
||||
|
||||
/*
|
||||
* Render the packet.
|
||||
*/
|
||||
client->pkt.recvlength = LWRES_RECVLENGTH;
|
||||
client->pkt.authtype = 0; /* XXXMLG */
|
||||
client->pkt.authlength = 0;
|
||||
|
||||
/*
|
||||
* If there are no addresses and no aliases, return failure.
|
||||
*/
|
||||
if (client->gabn.naddrs == 0 && client->gabn.naliases == 0)
|
||||
client->pkt.result = LWRES_R_NOTFOUND;
|
||||
else
|
||||
client->pkt.result = LWRES_R_SUCCESS;
|
||||
|
||||
lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
|
||||
&client->pkt, &lwb);
|
||||
if (lwres != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
r.base = lwb.base;
|
||||
r.length = lwb.used;
|
||||
client->sendbuf = r.base;
|
||||
client->sendlength = r.length;
|
||||
result = isc_socket_sendto(cm->sock, &r, cm->task, ns_lwdclient_send,
|
||||
client, &client->address, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
NS_LWDCLIENT_SETSEND(client);
|
||||
|
||||
/*
|
||||
* All done!
|
||||
*/
|
||||
cleanup_gabn(client);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
cleanup_gabn(client);
|
||||
|
||||
if (lwb.base != NULL)
|
||||
lwres_context_freemem(client->clientmgr->lwctx,
|
||||
lwb.base, lwb.length);
|
||||
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(ns_lwdclient_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 = (char *)(b.base) + b.used;
|
||||
client->gabn.realnamelen = client->recv_buffer.used - b.used;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
store_realname(ns_lwdclient_t *client) {
|
||||
isc_buffer_t b;
|
||||
isc_result_t result;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* Save this name away as the current real name.
|
||||
*/
|
||||
client->gabn.realname = (char *) 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) {
|
||||
ns_lwdclient_t *client = ev->ev_arg;
|
||||
isc_eventtype_t evtype;
|
||||
isc_boolean_t claimed;
|
||||
|
||||
DP(50, "find done for task %p, client %p", task, client);
|
||||
|
||||
evtype = ev->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.
|
||||
*/
|
||||
claimed = ISC_FALSE;
|
||||
if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) {
|
||||
if (NEED_V4(client)) {
|
||||
client->v4find = client->find;
|
||||
claimed = ISC_TRUE;
|
||||
}
|
||||
if (NEED_V6(client)) {
|
||||
client->v6find = client->find;
|
||||
claimed = ISC_TRUE;
|
||||
}
|
||||
if (client->find != NULL) {
|
||||
if (claimed)
|
||||
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 (evtype == DNS_EVENT_ADBMOREADDRESSES) {
|
||||
start_find(client);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* An error or other strangeness happened. Drop this query.
|
||||
*/
|
||||
cleanup_gabn(client);
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
start_find(ns_lwdclient_t *client) {
|
||||
unsigned int options;
|
||||
isc_result_t result;
|
||||
isc_boolean_t claimed;
|
||||
|
||||
DP(50, "starting find for client %p", client);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
options = 0;
|
||||
options |= DNS_ADBFIND_WANTEVENT;
|
||||
options |= DNS_ADBFIND_RETURNLAME;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (NEED_V4(client))
|
||||
options |= DNS_ADBFIND_INET;
|
||||
if (NEED_V6(client))
|
||||
options |= DNS_ADBFIND_INET6;
|
||||
|
||||
find_again:
|
||||
INSIST(client->find == NULL);
|
||||
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(&client->target_name),
|
||||
client->clientmgr->view->dstport,
|
||||
&client->find);
|
||||
|
||||
/*
|
||||
* Did we get an alias? If so, save it and re-issue the query.
|
||||
*/
|
||||
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");
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
return;
|
||||
}
|
||||
goto find_again;
|
||||
}
|
||||
|
||||
DP(50, "find returned %d (%s)", result, isc_result_totext(result));
|
||||
|
||||
/*
|
||||
* Did we get an error?
|
||||
*/
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (client->find != NULL)
|
||||
dns_adb_destroyfind(&client->find);
|
||||
cleanup_gabn(client);
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
claimed = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* Did we get our answer to V4 addresses?
|
||||
*/
|
||||
if (NEED_V4(client)
|
||||
&& ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) {
|
||||
DP(50, "client %p ipv4 satisfied by find %p", client,
|
||||
client->find);
|
||||
claimed = ISC_TRUE;
|
||||
client->v4find = client->find;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we get our answer to V6 addresses?
|
||||
*/
|
||||
if (NEED_V6(client)
|
||||
&& ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) {
|
||||
DP(50, "client %p ipv6 satisfied by find %p", client,
|
||||
client->find);
|
||||
claimed = ISC_TRUE;
|
||||
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->find->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");
|
||||
if (claimed)
|
||||
client->find = NULL;
|
||||
else
|
||||
dns_adb_destroyfind(&client->find);
|
||||
|
||||
/*
|
||||
* We seem to have everything we asked for, or at least we are
|
||||
* able to respond with things we've learned.
|
||||
*/
|
||||
|
||||
generate_reply(client);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_gabn(ns_lwdclient_t *client) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize the real name and alias arrays in the reply we're
|
||||
* going to build up.
|
||||
*/
|
||||
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;
|
||||
memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
|
||||
LWRES_LINK_INIT(&client->addrs[i], link);
|
||||
}
|
||||
|
||||
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;
|
||||
LWRES_LIST_INIT(client->gabn.addrs);
|
||||
client->gabn.base = NULL;
|
||||
client->gabn.baselen = 0;
|
||||
|
||||
/*
|
||||
* Set up the internal buffer to point to the receive region.
|
||||
*/
|
||||
isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
|
||||
}
|
||||
|
||||
/*
|
||||
* When we are called, we can be assured that:
|
||||
*
|
||||
* client->sockaddr contains the address we need to reply to,
|
||||
*
|
||||
* client->pkt contains the packet header data,
|
||||
*
|
||||
* the packet "checks out" overall -- any MD5 hashes or crypto
|
||||
* bits have been verified,
|
||||
*
|
||||
* "b" points to the remaining data after the packet header
|
||||
* was parsed off.
|
||||
*
|
||||
* We are in a the RECVDONE state.
|
||||
*
|
||||
* From this state we will enter the SEND state if we happen to have
|
||||
* everything we need or we need to return an error packet, or to the
|
||||
* FINDWAIT state if we need to look things up.
|
||||
*/
|
||||
void
|
||||
ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
|
||||
isc_result_t result;
|
||||
lwres_gabnrequest_t *req;
|
||||
isc_buffer_t namebuf;
|
||||
|
||||
REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
|
||||
|
||||
req = NULL;
|
||||
|
||||
result = lwres_gabnrequest_parse(client->clientmgr->lwctx,
|
||||
b, &client->pkt, &req);
|
||||
if (result != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
isc_buffer_init(&namebuf, req->name, req->namelen);
|
||||
isc_buffer_add(&namebuf, req->namelen);
|
||||
|
||||
dns_fixedname_init(&client->target_name);
|
||||
result = dns_name_fromtext(dns_fixedname_name(&client->target_name),
|
||||
&namebuf, dns_rootname, ISC_FALSE, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
client->find_wanted = req->addrtypes;
|
||||
DP(50, "client %p looking for addrtypes %08x",
|
||||
client, client->find_wanted);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
init_gabn(client);
|
||||
|
||||
result = store_realname(client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Start the find.
|
||||
*/
|
||||
start_find(client);
|
||||
|
||||
return;
|
||||
|
||||
/*
|
||||
* We're screwed. Return an error packet to our caller.
|
||||
*/
|
||||
out:
|
||||
if (req != NULL)
|
||||
lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
|
||||
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
}
|
292
bin/named/lwdgnba.c
Normal file
292
bin/named/lwdgnba.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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/socket.h>
|
||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/adb.h>
|
||||
#include <dns/byaddr.h>
|
||||
#include <dns/result.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/lwdclient.h>
|
||||
|
||||
static void start_byaddr(ns_lwdclient_t *);
|
||||
|
||||
static void
|
||||
byaddr_done(isc_task_t *task, isc_event_t *event) {
|
||||
ns_lwdclient_t *client;
|
||||
ns_lwdclientmgr_t *cm;
|
||||
dns_byaddrevent_t *bevent;
|
||||
int lwres;
|
||||
lwres_buffer_t lwb;
|
||||
dns_name_t *name;
|
||||
isc_result_t result;
|
||||
isc_region_t r;
|
||||
isc_buffer_t b;
|
||||
lwres_gnbaresponse_t *gnba;
|
||||
isc_uint16_t naliases;
|
||||
isc_stdtime_t now;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
lwb.base = NULL;
|
||||
client = event->ev_arg;
|
||||
cm = client->clientmgr;
|
||||
INSIST(client->byaddr == (dns_byaddr_t *)event->ev_sender);
|
||||
|
||||
bevent = (dns_byaddrevent_t *)event;
|
||||
gnba = &client->gnba;
|
||||
|
||||
DP(50, "byaddr event result = %s",
|
||||
isc_result_totext(bevent->result));
|
||||
|
||||
result = bevent->result;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_byaddr_destroy(&client->byaddr);
|
||||
isc_event_free(&event);
|
||||
bevent = NULL;
|
||||
|
||||
/*
|
||||
* Were we trying bitstring or nibble mode? If bitstring,
|
||||
* and we got FORMERROR or SERVFAIL, set the flag to
|
||||
* avoid bitstring lables for 10 minutes. If we got any
|
||||
* other error (NXDOMAIN, etc) just try again without
|
||||
* bitstrings, and let our cache handle the negative answer
|
||||
* for bitstrings.
|
||||
*/
|
||||
if ((client->options & DNS_BYADDROPT_IPV6NIBBLE) != 0) {
|
||||
dns_adb_freeaddrinfo(cm->view->adb, &client->addrinfo);
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
if (result == DNS_R_FORMERR ||
|
||||
result == DNS_R_SERVFAIL ||
|
||||
result == ISC_R_FAILURE)
|
||||
dns_adb_setavoidbitstring(cm->view->adb,
|
||||
client->addrinfo, now + 600);
|
||||
|
||||
/*
|
||||
* Fall back to nibble reverse if the default of bitstrings
|
||||
* fails.
|
||||
*/
|
||||
client->options |= DNS_BYADDROPT_IPV6NIBBLE;
|
||||
|
||||
start_byaddr(client);
|
||||
return;
|
||||
}
|
||||
|
||||
name = ISC_LIST_HEAD(bevent->names);
|
||||
while (name != NULL) {
|
||||
b = client->recv_buffer;
|
||||
|
||||
result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
DP(50, "found name '%.*s'",
|
||||
client->recv_buffer.used - b.used,
|
||||
(char *)(b.base) + b.used);
|
||||
if (gnba->realname == NULL) {
|
||||
gnba->realname = (char *)(b.base) + b.used;
|
||||
gnba->realnamelen = client->recv_buffer.used - b.used;
|
||||
} else {
|
||||
naliases = gnba->naliases;
|
||||
if (naliases >= LWRES_MAX_ALIASES)
|
||||
break;
|
||||
gnba->aliases[naliases] = (char *)(b.base) + b.used;
|
||||
gnba->aliaslen[naliases] =
|
||||
client->recv_buffer.used - b.used;
|
||||
gnba->naliases++;
|
||||
}
|
||||
name = ISC_LIST_NEXT(name, link);
|
||||
}
|
||||
|
||||
dns_byaddr_destroy(&client->byaddr);
|
||||
dns_adb_freeaddrinfo(cm->view->adb, &client->addrinfo);
|
||||
isc_event_free(&event);
|
||||
|
||||
/*
|
||||
* Render the packet.
|
||||
*/
|
||||
client->pkt.recvlength = LWRES_RECVLENGTH;
|
||||
client->pkt.authtype = 0; /* XXXMLG */
|
||||
client->pkt.authlength = 0;
|
||||
client->pkt.result = LWRES_R_SUCCESS;
|
||||
|
||||
lwres = lwres_gnbaresponse_render(cm->lwctx,
|
||||
gnba, &client->pkt, &lwb);
|
||||
if (lwres != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
r.base = lwb.base;
|
||||
r.length = lwb.used;
|
||||
client->sendbuf = r.base;
|
||||
client->sendlength = r.length;
|
||||
result = isc_socket_sendto(cm->sock, &r,
|
||||
cm->task, ns_lwdclient_send,
|
||||
client, &client->address, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
NS_LWDCLIENT_SETSEND(client);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
if (client->byaddr != NULL)
|
||||
dns_byaddr_destroy(&client->byaddr);
|
||||
if (client->addrinfo != NULL)
|
||||
dns_adb_freeaddrinfo(cm->view->adb, &client->addrinfo);
|
||||
if (lwb.base != NULL)
|
||||
lwres_context_freemem(cm->lwctx,
|
||||
lwb.base, lwb.length);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
start_byaddr(ns_lwdclient_t *client) {
|
||||
isc_result_t result;
|
||||
ns_lwdclientmgr_t *cm;
|
||||
|
||||
cm = client->clientmgr;
|
||||
|
||||
INSIST(client->byaddr == NULL);
|
||||
|
||||
result = dns_byaddr_create(cm->mctx, &client->na, cm->view,
|
||||
client->options, cm->task, byaddr_done,
|
||||
client, &client->byaddr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_adb_freeaddrinfo(cm->view->adb, &client->addrinfo);
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_gnba(ns_lwdclient_t *client) {
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize the real name and alias arrays in the reply we're
|
||||
* going to build up.
|
||||
*/
|
||||
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;
|
||||
memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
|
||||
LWRES_LINK_INIT(&client->addrs[i], link);
|
||||
}
|
||||
|
||||
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 = 0;
|
||||
isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwdclient_processgnba(ns_lwdclient_t *client, lwres_buffer_t *b) {
|
||||
lwres_gnbarequest_t *req;
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t sa;
|
||||
ns_lwdclientmgr_t *cm;
|
||||
|
||||
REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
|
||||
INSIST(client->byaddr == NULL);
|
||||
|
||||
cm = client->clientmgr;
|
||||
req = NULL;
|
||||
|
||||
result = lwres_gnbarequest_parse(cm->lwctx,
|
||||
b, &client->pkt, &req);
|
||||
if (result != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
if (req->addr.address == NULL)
|
||||
goto out;
|
||||
|
||||
client->options = 0;
|
||||
if (req->addr.family == LWRES_ADDRTYPE_V4) {
|
||||
client->na.family = AF_INET;
|
||||
if (req->addr.length != 4)
|
||||
goto out;
|
||||
memcpy(&client->na.type.in, req->addr.address, 4);
|
||||
} else if (req->addr.family == LWRES_ADDRTYPE_V6) {
|
||||
client->na.family = AF_INET6;
|
||||
if (req->addr.length != 16)
|
||||
goto out;
|
||||
memcpy(&client->na.type.in6, req->addr.address, 16);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
isc_sockaddr_fromnetaddr(&sa, &client->na, 53);
|
||||
|
||||
DP(50, "client %p looking for addrtype %08x",
|
||||
client, req->addr.family);
|
||||
|
||||
/*
|
||||
* We no longer need to keep this around.
|
||||
*/
|
||||
lwres_gnbarequest_free(cm->lwctx, &req);
|
||||
|
||||
/*
|
||||
* Initialize the real name and alias arrays in the reply we're
|
||||
* going to build up.
|
||||
*/
|
||||
init_gnba(client);
|
||||
client->options = 0;
|
||||
|
||||
/*
|
||||
* See if we should skip the byaddr bit.
|
||||
*/
|
||||
INSIST(client->addrinfo == NULL);
|
||||
result = dns_adb_findaddrinfo(cm->view->adb, &sa,
|
||||
&client->addrinfo, 0);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
if (client->addrinfo->avoid_bitstring > 0)
|
||||
client->options |= DNS_BYADDROPT_IPV6NIBBLE;
|
||||
|
||||
/*
|
||||
* Start the find.
|
||||
*/
|
||||
start_byaddr(client);
|
||||
|
||||
return;
|
||||
|
||||
/*
|
||||
* We're screwed. Return an error packet to our caller.
|
||||
*/
|
||||
out:
|
||||
if (req != NULL)
|
||||
lwres_gnbarequest_free(cm->lwctx, &req);
|
||||
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
}
|
86
bin/named/lwdnoop.c
Normal file
86
bin/named/lwdnoop.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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/socket.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <named/types.h>
|
||||
#include <named/lwdclient.h>
|
||||
|
||||
void
|
||||
ns_lwdclient_processnoop(ns_lwdclient_t *client, lwres_buffer_t *b) {
|
||||
lwres_nooprequest_t *req;
|
||||
lwres_noopresponse_t resp;
|
||||
isc_result_t result;
|
||||
lwres_result_t lwres;
|
||||
isc_region_t r;
|
||||
lwres_buffer_t lwb;
|
||||
|
||||
REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
|
||||
INSIST(client->byaddr == NULL);
|
||||
|
||||
req = NULL;
|
||||
|
||||
result = lwres_nooprequest_parse(client->clientmgr->lwctx,
|
||||
b, &client->pkt, &req);
|
||||
if (result != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
client->pkt.recvlength = LWRES_RECVLENGTH;
|
||||
client->pkt.authtype = 0; /* XXXMLG */
|
||||
client->pkt.authlength = 0;
|
||||
client->pkt.result = LWRES_R_SUCCESS;
|
||||
|
||||
resp.datalength = req->datalength;
|
||||
resp.data = req->data;
|
||||
|
||||
lwres = lwres_noopresponse_render(client->clientmgr->lwctx, &resp,
|
||||
&client->pkt, &lwb);
|
||||
if (lwres != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
r.base = lwb.base;
|
||||
r.length = lwb.used;
|
||||
client->sendbuf = r.base;
|
||||
client->sendlength = r.length;
|
||||
result = isc_socket_sendto(client->clientmgr->sock, &r,
|
||||
client->clientmgr->task, ns_lwdclient_send,
|
||||
client, &client->address, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We can now destroy request.
|
||||
*/
|
||||
lwres_nooprequest_free(client->clientmgr->lwctx, &req);
|
||||
|
||||
NS_LWDCLIENT_SETSEND(client);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
if (req != NULL)
|
||||
lwres_nooprequest_free(client->clientmgr->lwctx, &req);
|
||||
|
||||
if (lwb.base != NULL)
|
||||
lwres_context_freemem(client->clientmgr->lwctx,
|
||||
lwb.base, lwb.length);
|
||||
|
||||
ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
|
||||
}
|
430
bin/named/lwresd.c
Normal file
430
bin/named/lwresd.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright (C) 2000 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Main program for the Lightweight Resolver Daemon.
|
||||
*
|
||||
* To paraphrase the old saying about X11, "It's not a lightweight deamon
|
||||
* for resolvers, it's a deamon for lightweight resolvers".
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/app.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/cache.h>
|
||||
#include <dns/db.h>
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rootns.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
#include <named/globals.h>
|
||||
#include <named/log.h>
|
||||
#include <named/lwresd.h>
|
||||
#include <named/lwdclient.h>
|
||||
#include <named/server.h>
|
||||
|
||||
#define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
|
||||
#define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
|
||||
|
||||
/*
|
||||
* The goal number of clients we can handle will be NTASKS * NRECVS.
|
||||
*/
|
||||
#define NTASKS 20 /* tasks to create to handle lwres queries */
|
||||
#define NRECVS 5 /* max clients per task */
|
||||
#define NTHREADS 1 /* # threads to create in thread manager */
|
||||
|
||||
static void
|
||||
fatal(const char *msg, isc_result_t result) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD,
|
||||
ISC_LOG_CRITICAL, "%s: %s", msg,
|
||||
isc_result_totext(result));
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD,
|
||||
ISC_LOG_CRITICAL, "exiting (due to fatal error)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrappers around our memory management stuff, for the lwres functions.
|
||||
*/
|
||||
static void *
|
||||
mem_alloc(void *arg, size_t size) {
|
||||
return (isc_mem_get(arg, size));
|
||||
}
|
||||
|
||||
static void
|
||||
mem_free(void *arg, void *mem, size_t size) {
|
||||
isc_mem_put(arg, mem, size);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_lwresd(isc_task_t *task, isc_event_t *event) {
|
||||
ns_lwresd_t *lwresd = event->ev_arg;
|
||||
unsigned int i;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
for (i = 0; i < lwresd->ntasks; i++)
|
||||
isc_task_shutdown(lwresd->cmgr[i].task);
|
||||
|
||||
/*
|
||||
* Kill off the view.
|
||||
*/
|
||||
dns_view_detach(&lwresd->view);
|
||||
|
||||
isc_task_detach(&lwresd->task);
|
||||
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_resolv_conf(isc_mem_t *mctx, isc_sockaddrlist_t forwarders) {
|
||||
lwres_context_t *lwctx;
|
||||
lwres_conf_t *lwc;
|
||||
int lwresult;
|
||||
struct in_addr ina;
|
||||
struct in6_addr ina6;
|
||||
isc_sockaddr_t *sa;
|
||||
int i;
|
||||
|
||||
lwctx = NULL;
|
||||
lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
|
||||
LWRES_CONTEXT_SERVERMODE);
|
||||
if (lwresult != LWRES_R_SUCCESS)
|
||||
return;
|
||||
|
||||
lwresult = lwres_conf_parse(lwctx, "/etc/resolv.conf");
|
||||
if (lwresult != LWRES_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
#if 1
|
||||
lwres_conf_print(lwctx, stderr);
|
||||
#endif
|
||||
|
||||
lwc = lwres_conf_get(lwctx);
|
||||
INSIST(lwc != NULL);
|
||||
|
||||
/*
|
||||
* Run through the list of nameservers, and set them to be our
|
||||
* forwarders.
|
||||
*/
|
||||
for (i = 0 ; i < lwc->nsnext ; i++) {
|
||||
switch (lwc->nameservers[i].family) {
|
||||
case AF_INET:
|
||||
sa = isc_mem_get(mctx, sizeof *sa);
|
||||
INSIST(sa != NULL);
|
||||
memcpy(&ina.s_addr, lwc->nameservers[i].address, 4);
|
||||
isc_sockaddr_fromin(sa, &ina, 53);
|
||||
ISC_LIST_APPEND(forwarders, sa, link);
|
||||
sa = NULL;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sa = isc_mem_get(mctx, sizeof *sa);
|
||||
INSIST(sa != NULL);
|
||||
memcpy(&ina6.s6_addr, lwc->nameservers[i].address, 16);
|
||||
isc_sockaddr_fromin6(sa, &ina6, 53);
|
||||
ISC_LIST_APPEND(forwarders, sa, link);
|
||||
sa = NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
lwres_conf_clear(lwctx);
|
||||
lwres_context_destroy(&lwctx);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_lwresd_createview(isc_mem_t *mctx, dns_view_t **viewp) {
|
||||
dns_cache_t *cache;
|
||||
isc_result_t result;
|
||||
dns_db_t *rootdb;
|
||||
unsigned int attrs;
|
||||
isc_sockaddr_t any4, any6;
|
||||
dns_dispatch_t *disp4 = NULL;
|
||||
dns_dispatch_t *disp6 = NULL;
|
||||
isc_sockaddrlist_t forwarders;
|
||||
dns_view_t *view;
|
||||
|
||||
REQUIRE(viewp != NULL && *viewp == NULL);
|
||||
cache = NULL;
|
||||
|
||||
/*
|
||||
* View.
|
||||
*/
|
||||
view = NULL;
|
||||
result = dns_view_create(mctx, dns_rdataclass_in, "_default", &view);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
/*
|
||||
* Cache.
|
||||
*/
|
||||
result = dns_cache_create(mctx, ns_g_taskmgr, ns_g_timermgr,
|
||||
dns_rdataclass_in, "rbt", 0, NULL, &cache);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
dns_view_setcache(view, cache);
|
||||
dns_cache_detach(&cache);
|
||||
|
||||
/*
|
||||
* Resolver.
|
||||
*
|
||||
* XXXMLG hardwired number of tasks.
|
||||
*/
|
||||
|
||||
if (isc_net_probeipv6() == ISC_R_SUCCESS) {
|
||||
isc_sockaddr_any6(&any6);
|
||||
|
||||
attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
|
||||
result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
|
||||
ns_g_taskmgr, &any6, 512, 6, 1024,
|
||||
17, 19, attrs, attrs, &disp6);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
if (isc_net_probeipv4() == ISC_R_SUCCESS) {
|
||||
isc_sockaddr_any(&any4);
|
||||
|
||||
attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
|
||||
result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
|
||||
ns_g_taskmgr, &any4, 512, 6, 1024,
|
||||
17, 19, attrs, attrs, &disp4);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
if (disp4 == NULL && disp6 == NULL)
|
||||
fatal("not listening on IPv4 or IPv6", ISC_R_FAILURE);
|
||||
|
||||
result = dns_view_createresolver(view, ns_g_taskmgr, 16,
|
||||
ns_g_socketmgr, ns_g_timermgr, 0,
|
||||
ns_g_dispatchmgr, disp4, disp6);
|
||||
if (disp4 != NULL)
|
||||
dns_dispatch_detach(&disp4);
|
||||
if (disp6 != NULL)
|
||||
dns_dispatch_detach(&disp6);
|
||||
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
|
||||
rootdb = NULL;
|
||||
result = dns_rootns_create(mctx, dns_rdataclass_in, NULL, &rootdb);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
dns_view_sethints(view, rootdb);
|
||||
dns_db_detach(&rootdb);
|
||||
|
||||
/*
|
||||
* If we have forwarders, set them here.
|
||||
*/
|
||||
ISC_LIST_INIT(forwarders);
|
||||
parse_resolv_conf(mctx, forwarders);
|
||||
if (ISC_LIST_HEAD(forwarders) != NULL) {
|
||||
isc_sockaddr_t *sa;
|
||||
|
||||
dns_resolver_setforwarders(view->resolver, &forwarders);
|
||||
dns_resolver_setfwdpolicy(view->resolver, dns_fwdpolicy_only);
|
||||
sa = ISC_LIST_HEAD(forwarders);
|
||||
while (sa != NULL) {
|
||||
ISC_LIST_UNLINK(forwarders, sa, link);
|
||||
isc_mem_put(mctx, sa, sizeof (*sa));
|
||||
sa = ISC_LIST_HEAD(forwarders);
|
||||
}
|
||||
}
|
||||
|
||||
dns_view_freeze(view);
|
||||
*viewp = view;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
out:
|
||||
dns_view_detach(&view);
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwresd_create(isc_mem_t *mctx, dns_view_t *view, ns_lwresd_t **lwresdp) {
|
||||
ns_lwresd_t *lwresd;
|
||||
isc_sockaddr_t localhost;
|
||||
struct in_addr lh_addr;
|
||||
unsigned int i, j;
|
||||
ns_lwdclient_t *client;
|
||||
isc_socket_t *sock;
|
||||
isc_result_t result;
|
||||
|
||||
sock = NULL;
|
||||
result = isc_socket_create(ns_g_socketmgr, AF_INET, isc_sockettype_udp,
|
||||
&sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_NETWORK,
|
||||
NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
|
||||
"failed to create socket: %s",
|
||||
isc_result_totext(result));
|
||||
return;
|
||||
}
|
||||
|
||||
lh_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
isc_sockaddr_fromin(&localhost, &lh_addr, LWRES_UDP_PORT);
|
||||
|
||||
result = isc_socket_bind(sock, &localhost);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_NETWORK,
|
||||
NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
|
||||
"binding lwres protocol socket to port %d: %s",
|
||||
LWRES_UDP_PORT, isc_result_totext(result));
|
||||
isc_socket_detach(&sock);
|
||||
return;
|
||||
}
|
||||
|
||||
lwresd = isc_mem_get(mctx, sizeof(*lwresd));
|
||||
if (lwresd == NULL)
|
||||
fatal("allocating lightweight resolver object", ISC_R_NOMEMORY);
|
||||
|
||||
lwresd->mctx = NULL;
|
||||
isc_mem_attach(mctx, &lwresd->mctx);
|
||||
|
||||
lwresd->sock = sock;
|
||||
|
||||
lwresd->view = NULL;
|
||||
dns_view_attach(view, &lwresd->view);
|
||||
|
||||
lwresd->task = NULL;
|
||||
result = isc_task_create(ns_g_taskmgr, 0, &lwresd->task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("allocating lightweight resolver task", result);
|
||||
isc_task_setname(lwresd->task, "lwresd", lwresd);
|
||||
result = isc_task_onshutdown(lwresd->task, shutdown_lwresd, lwresd);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fatal("allocating lwresd onshutdown event", result);
|
||||
|
||||
lwresd->cmgr = isc_mem_get(lwresd->mctx,
|
||||
sizeof(ns_lwdclientmgr_t) * NTASKS);
|
||||
if (lwresd->cmgr == NULL)
|
||||
fatal("allocating lwresd client manager", ISC_R_NOMEMORY);
|
||||
|
||||
/*
|
||||
* Create one task for each client manager.
|
||||
*/
|
||||
for (i = 0 ; i < NTASKS ; i++) {
|
||||
char name[16];
|
||||
lwresd->cmgr[i].task = NULL;
|
||||
lwresd->cmgr[i].sock = lwresd->sock;
|
||||
lwresd->cmgr[i].view = NULL;
|
||||
lwresd->cmgr[i].flags = 0;
|
||||
result = isc_task_create(ns_g_taskmgr, 0,
|
||||
&lwresd->cmgr[i].task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
result = isc_task_onshutdown(lwresd->cmgr[i].task,
|
||||
ns_lwdclient_shutdown,
|
||||
&lwresd->cmgr[i]);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
ISC_LIST_INIT(lwresd->cmgr[i].idle);
|
||||
ISC_LIST_INIT(lwresd->cmgr[i].running);
|
||||
snprintf(name, sizeof(name), "lwd client %d", i);
|
||||
isc_task_setname(lwresd->cmgr[i].task, name, &lwresd->cmgr[i]);
|
||||
lwresd->cmgr[i].mctx = lwresd->mctx;
|
||||
lwresd->cmgr[i].lwctx = NULL;
|
||||
result = lwres_context_create(&lwresd->cmgr[i].lwctx,
|
||||
lwresd->mctx,
|
||||
mem_alloc, mem_free,
|
||||
LWRES_CONTEXT_SERVERMODE);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_task_detach(&lwresd->cmgr[i].task);
|
||||
break;
|
||||
}
|
||||
dns_view_attach(lwresd->view, &lwresd->cmgr[i].view);
|
||||
}
|
||||
INSIST(i > 0);
|
||||
lwresd->ntasks = i; /* remember how many we managed to create */
|
||||
|
||||
/*
|
||||
* Now, run through each client manager and populate it with
|
||||
* client structures. Do this by creating one receive for each
|
||||
* task, in a loop, so each task has a chance of getting at least
|
||||
* one client structure.
|
||||
*/
|
||||
for (i = 0 ; i < NRECVS ; i++) {
|
||||
client = isc_mem_get(lwresd->mctx,
|
||||
sizeof(ns_lwdclient_t) * lwresd->ntasks);
|
||||
if (client == NULL)
|
||||
break;
|
||||
for (j = 0 ; j < lwresd->ntasks ; j++)
|
||||
ns_lwdclient_initialize(&client[j], &lwresd->cmgr[j]);
|
||||
}
|
||||
INSIST(i > 0);
|
||||
|
||||
/*
|
||||
* Issue one read request for each task we have.
|
||||
*/
|
||||
for (j = 0 ; j < lwresd->ntasks ; j++) {
|
||||
result = ns_lwdclient_startrecv(&lwresd->cmgr[j]);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
lwresd->magic = LWRESD_MAGIC;
|
||||
*lwresdp = lwresd;
|
||||
}
|
||||
|
||||
void
|
||||
ns_lwresd_destroy(ns_lwresd_t **lwresdp) {
|
||||
ns_lwresd_t *lwresd;
|
||||
ns_lwdclient_t *client;
|
||||
|
||||
REQUIRE(lwresdp != NULL);
|
||||
lwresd = *lwresdp;
|
||||
REQUIRE(VALID_LWRESD(lwresd));
|
||||
|
||||
/*
|
||||
* Wait for everything to die off by waiting for the sockets
|
||||
* to be detached.
|
||||
*/
|
||||
isc_socket_detach(&lwresd->sock);
|
||||
|
||||
/*
|
||||
* Free up memory allocated. This is somewhat magical. We allocated
|
||||
* the ns_lwdclient_t's in blocks, but the first task always has the
|
||||
* first pointer. Just loop here, freeing them.
|
||||
*/
|
||||
client = ISC_LIST_HEAD(lwresd->cmgr[0].idle);
|
||||
while (client != NULL) {
|
||||
ISC_LIST_UNLINK(lwresd->cmgr[0].idle, client, link);
|
||||
isc_mem_put(lwresd->mctx, client,
|
||||
sizeof(ns_lwdclient_t) * lwresd->ntasks);
|
||||
client = ISC_LIST_HEAD(lwresd->cmgr[0].idle);
|
||||
}
|
||||
INSIST(ISC_LIST_EMPTY(lwresd->cmgr[0].running));
|
||||
|
||||
lwresd->magic = 0;
|
||||
isc_mem_put(lwresd->mctx, lwresd, sizeof(*lwresd));
|
||||
*lwresdp = NULL;
|
||||
}
|
@@ -41,9 +41,11 @@
|
||||
#include <named/omapi.h>
|
||||
#include <named/os.h>
|
||||
#include <named/server.h>
|
||||
#include <named/lwresd.h>
|
||||
#include <named/main.h>
|
||||
|
||||
static isc_boolean_t want_stats = ISC_FALSE;
|
||||
static isc_boolean_t lwresd_only = ISC_FALSE;
|
||||
static const char * program_name = "named";
|
||||
|
||||
void
|
||||
@@ -176,7 +178,7 @@ parse_command_line(int argc, char *argv[]) {
|
||||
|
||||
isc_commandline_errprint = ISC_FALSE;
|
||||
while ((ch = isc_commandline_parse(argc, argv,
|
||||
"c:d:fgn:N:p:st:u:x:")) !=
|
||||
"c:d:fgn:N:p:rst:u:x:")) !=
|
||||
-1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
@@ -205,6 +207,9 @@ parse_command_line(int argc, char *argv[]) {
|
||||
isc_commandline_argument);
|
||||
ns_g_port = port;
|
||||
break;
|
||||
case 'r':
|
||||
lwresd_only = ISC_TRUE;
|
||||
break;
|
||||
case 's':
|
||||
/* XXXRTH temporary syntax */
|
||||
want_stats = ISC_TRUE;
|
||||
@@ -266,6 +271,14 @@ create_managers(void) {
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
|
||||
result = dns_dispatchmgr_create(ns_g_mctx, &ns_g_dispatchmgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"dns_dispatchmgr_create() failed: %s",
|
||||
isc_result_totext(result));
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -276,6 +289,7 @@ destroy_managers(void) {
|
||||
else
|
||||
omapi_lib_destroy();
|
||||
|
||||
dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
|
||||
/*
|
||||
* isc_taskmgr_destroy() will block until all tasks have exited,
|
||||
*/
|
||||
@@ -323,6 +337,15 @@ setup(void) {
|
||||
ns_main_earlyfatal("create_managers() failed: %s",
|
||||
isc_result_totext(result));
|
||||
|
||||
if (lwresd_only) {
|
||||
dns_view_t *view = NULL;
|
||||
result = ns_lwresd_createview(ns_g_mctx, &view);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
ns_main_earlyfatal("ns_lwresd_createview() failed: %s",
|
||||
isc_result_totext(result));
|
||||
ns_lwresd_create(ns_g_mctx, view, &ns_g_lwresd);
|
||||
dns_view_detach(&view);
|
||||
} else
|
||||
ns_server_create(ns_g_mctx, &ns_g_server);
|
||||
|
||||
result = ns_omapi_init();
|
||||
@@ -345,6 +368,9 @@ setup(void) {
|
||||
static void
|
||||
cleanup(void) {
|
||||
destroy_managers();
|
||||
if (lwresd_only)
|
||||
ns_lwresd_destroy(&ns_g_lwresd);
|
||||
else
|
||||
ns_server_destroy(&ns_g_server);
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
|
||||
ISC_LOG_NOTICE, "exiting");
|
||||
|
@@ -1443,9 +1443,6 @@ run_server(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, &ns_g_dispatchmgr),
|
||||
"creating dispatch manager");
|
||||
|
||||
CHECKFATAL(ns_clientmgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
|
||||
&server->clientmgr),
|
||||
"creating client manager");
|
||||
@@ -1498,8 +1495,6 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
|
||||
ns_interfacemgr_shutdown(server->interfacemgr);
|
||||
ns_interfacemgr_detach(&server->interfacemgr);
|
||||
|
||||
dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
|
||||
|
||||
dns_zonemgr_shutdown(server->zonemgr);
|
||||
|
||||
isc_task_detach(&server->task);
|
||||
@@ -1561,6 +1556,7 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
|
||||
server->entropy = NULL;
|
||||
CHECKFATAL(isc_entropy_create(ns_g_mctx, &server->entropy),
|
||||
"initializing entropy pool");
|
||||
(void) isc_entropy_createfilesource(server->entropy, "/dev/random", 0);
|
||||
|
||||
CHECKFATAL(dst_lib_init(ns_g_mctx, server->entropy, 0),
|
||||
"initializing DST");
|
||||
|
Reference in New Issue
Block a user