2000-02-24 14:31:43 +00:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
#include <isc/assertions.h>
|
|
|
|
#include <isc/buffer.h>
|
|
|
|
#include <isc/event.h>
|
|
|
|
#include <isc/net.h>
|
|
|
|
#include <isc/mutex.h>
|
|
|
|
#include <isc/region.h>
|
|
|
|
#include <isc/socket.h>
|
|
|
|
#include <isc/task.h>
|
|
|
|
#include <isc/timer.h>
|
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <dns/dispatch.h>
|
|
|
|
#include <dns/events.h>
|
|
|
|
#include <dns/message.h>
|
2000-02-24 14:31:43 +00:00
|
|
|
#include <dns/request.h>
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
#define REQUESTMGR_MAGIC 0x5271754dU /* RquM */
|
2000-02-24 14:31:43 +00:00
|
|
|
#define VALID_REQUESTMGR(mgr) ((mgr) != NULL && \
|
|
|
|
(mgr)->magic == REQUESTMGR_MAGIC)
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
#define REQUEST_MAGIC 0x52717521U /* Rqu! */
|
2000-02-24 14:31:43 +00:00
|
|
|
#define VALID_REQUEST(request) ((request) != NULL && \
|
|
|
|
(request)->magic == REQUEST_MAGIC)
|
|
|
|
|
2000-03-20 12:42:35 +00:00
|
|
|
#if 0
|
2000-04-18 08:27:48 +00:00
|
|
|
#define TRACE(x) printf x
|
2000-03-20 12:22:02 +00:00
|
|
|
#else
|
|
|
|
#define TRACE(x)
|
|
|
|
#endif
|
|
|
|
typedef ISC_LIST(dns_request_t) dns_requestlist_t;
|
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
#define DNS_REQUEST_NLOCKS 7
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
struct dns_requestmgr {
|
|
|
|
isc_int32_t magic;
|
|
|
|
isc_mutex_t lock;
|
|
|
|
isc_mem_t *mctx;
|
|
|
|
|
|
|
|
/* locked */
|
2000-04-18 08:27:48 +00:00
|
|
|
isc_int32_t eref;
|
|
|
|
isc_int32_t iref;
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_timermgr_t *timermgr;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_socketmgr_t *socketmgr;
|
2000-02-24 14:31:43 +00:00
|
|
|
dns_dispatch_t *dispatchv4;
|
|
|
|
dns_dispatch_t *dispatchv6;
|
|
|
|
isc_boolean_t exiting;
|
|
|
|
isc_eventlist_t whenshutdown;
|
2000-03-22 07:00:39 +00:00
|
|
|
unsigned int hash;
|
|
|
|
isc_mutex_t locks[DNS_REQUEST_NLOCKS];
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_requestlist_t requests;
|
2000-02-24 14:31:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct dns_request {
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_int32_t magic;
|
2000-03-22 07:00:39 +00:00
|
|
|
unsigned int hash;
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_mem_t *mctx;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_int32_t flags;
|
|
|
|
ISC_LINK(dns_request_t) link;
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_buffer_t *query;
|
|
|
|
isc_buffer_t *answer;
|
|
|
|
dns_requestevent_t *event;
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_dispatch_t *dispatch;
|
2000-03-13 20:43:39 +00:00
|
|
|
dns_dispentry_t *dispentry;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_timer_t *timer;
|
|
|
|
dns_requestmgr_t *requestmgr;
|
2000-03-13 20:43:39 +00:00
|
|
|
};
|
2000-02-24 14:31:43 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
#define DNS_REQUEST_F_CONNECTING 0x0001
|
|
|
|
#define DNS_REQUEST_F_CANCELED 0x0002
|
|
|
|
#define DNS_REQUEST_CANCELED(r) \
|
|
|
|
(((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
|
|
|
|
#define DNS_REQUEST_CONNECTING(r) \
|
|
|
|
(((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
/***
|
|
|
|
*** Forward
|
|
|
|
***/
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
static void mgr_destroy(dns_requestmgr_t *requestmgr);
|
|
|
|
static void mgr_shutdown(dns_requestmgr_t *requestmgr);
|
2000-03-22 07:00:39 +00:00
|
|
|
static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
|
2000-02-24 14:31:43 +00:00
|
|
|
static void send_shutdown_events(dns_requestmgr_t *requestmgr);
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
static isc_result_t render(dns_message_t *message, isc_buffer_t **buffer,
|
|
|
|
isc_mem_t *mctx);
|
2000-03-20 12:22:02 +00:00
|
|
|
static void req_senddone(isc_task_t *task, isc_event_t *event);
|
|
|
|
static void req_response(isc_task_t *task, isc_event_t *event);
|
|
|
|
static void req_timeout(isc_task_t *task, isc_event_t *event);
|
|
|
|
static void req_connected(isc_task_t *task, isc_event_t *event);
|
|
|
|
static void req_sendevent(dns_request_t *request, isc_result_t result);
|
|
|
|
static void req_cancel(dns_request_t *request);
|
|
|
|
static void req_destroy(dns_request_t *request);
|
2000-02-24 14:31:43 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
*** Public
|
|
|
|
***/
|
|
|
|
|
|
|
|
isc_result_t
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_requestmgr_create(isc_mem_t *mctx,
|
|
|
|
isc_timermgr_t *timermgr,
|
|
|
|
isc_socketmgr_t *socketmgr,
|
|
|
|
dns_dispatch_t *dispatchv4,
|
|
|
|
dns_dispatch_t *dispatchv6,
|
|
|
|
dns_requestmgr_t **requestmgrp)
|
|
|
|
{
|
2000-02-24 14:31:43 +00:00
|
|
|
dns_requestmgr_t *requestmgr;
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_socket_t *socket;
|
|
|
|
isc_result_t result;
|
2000-03-22 07:00:39 +00:00
|
|
|
int i;
|
2000-02-24 14:31:43 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_requestmgr_create\n"));
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
|
2000-03-20 12:22:02 +00:00
|
|
|
REQUIRE(timermgr != NULL);
|
|
|
|
REQUIRE(socketmgr != NULL);
|
2000-02-24 14:31:43 +00:00
|
|
|
if (dispatchv4 != NULL) {
|
|
|
|
socket = dns_dispatch_getsocket(dispatchv4);
|
2000-03-20 12:22:02 +00:00
|
|
|
REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
if (dispatchv6 != NULL) {
|
|
|
|
socket = dns_dispatch_getsocket(dispatchv6);
|
2000-03-20 12:22:02 +00:00
|
|
|
REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
|
|
|
|
if (requestmgr == NULL)
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
result = isc_mutex_init(&requestmgr->lock);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
|
|
|
|
return (result);
|
|
|
|
}
|
2000-03-22 07:00:39 +00:00
|
|
|
for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
|
|
|
|
result = isc_mutex_init(&requestmgr->locks[i]);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-03-22 07:00:39 +00:00
|
|
|
while (--i >= 0)
|
|
|
|
isc_mutex_destroy(&requestmgr->locks[i]);
|
|
|
|
isc_mutex_destroy(&requestmgr->lock);
|
2000-04-18 08:27:48 +00:00
|
|
|
isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
|
2000-03-22 07:00:39 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
2000-02-24 14:31:43 +00:00
|
|
|
requestmgr->timermgr = timermgr;
|
2000-03-20 12:22:02 +00:00
|
|
|
requestmgr->socketmgr = socketmgr;
|
2000-02-24 14:31:43 +00:00
|
|
|
requestmgr->dispatchv4 = NULL;
|
2000-03-13 20:43:39 +00:00
|
|
|
if (dispatchv4 != NULL)
|
|
|
|
dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
|
2000-02-24 14:31:43 +00:00
|
|
|
requestmgr->dispatchv6 = NULL;
|
|
|
|
if (dispatchv6 != NULL)
|
2000-03-13 20:43:39 +00:00
|
|
|
dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
|
2000-04-18 08:27:48 +00:00
|
|
|
requestmgr->mctx = NULL;
|
|
|
|
isc_mem_attach(mctx, &requestmgr->mctx);
|
|
|
|
requestmgr->eref = 1; /* implict attach */
|
|
|
|
requestmgr->iref = 0;
|
2000-02-24 14:31:43 +00:00
|
|
|
ISC_LIST_INIT(requestmgr->whenshutdown);
|
2000-03-20 12:22:02 +00:00
|
|
|
ISC_LIST_INIT(requestmgr->requests);
|
2000-02-24 14:31:43 +00:00
|
|
|
requestmgr->exiting = ISC_FALSE;
|
2000-03-22 07:00:39 +00:00
|
|
|
requestmgr->hash = 0;
|
2000-02-24 14:31:43 +00:00
|
|
|
requestmgr->magic = REQUESTMGR_MAGIC;
|
|
|
|
*requestmgrp = requestmgr;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
|
|
|
|
isc_event_t **eventp)
|
|
|
|
{
|
|
|
|
isc_task_t *clone;
|
|
|
|
isc_event_t *event;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_requestmgr_whenshutdown\n"));
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
REQUIRE(VALID_REQUESTMGR(requestmgr));
|
|
|
|
REQUIRE(eventp != NULL);
|
|
|
|
|
|
|
|
event = *eventp;
|
|
|
|
*eventp = NULL;
|
|
|
|
|
|
|
|
LOCK(&requestmgr->lock);
|
|
|
|
|
|
|
|
if (requestmgr->exiting) {
|
|
|
|
/*
|
|
|
|
* We're already shutdown. Send the event.
|
|
|
|
*/
|
2000-04-17 19:22:44 +00:00
|
|
|
event->ev_sender = requestmgr;
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_task_send(task, &event);
|
|
|
|
} else {
|
|
|
|
clone = NULL;
|
|
|
|
isc_task_attach(task, &clone);
|
2000-04-17 19:22:44 +00:00
|
|
|
event->ev_sender = clone;
|
|
|
|
ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
UNLOCK(&requestmgr->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
|
|
|
|
|
|
|
|
REQUIRE(VALID_REQUESTMGR(requestmgr));
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_requestmgr_shutdown\n"));
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
LOCK(&requestmgr->lock);
|
2000-03-20 12:22:02 +00:00
|
|
|
mgr_shutdown(requestmgr);
|
|
|
|
UNLOCK(&requestmgr->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mgr_shutdown(dns_requestmgr_t *requestmgr) {
|
|
|
|
dns_request_t *request;
|
2000-04-18 08:27:48 +00:00
|
|
|
|
|
|
|
TRACE(("mgr_shutdown\n"));
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
/*
|
|
|
|
* Caller holds lock.
|
|
|
|
*/
|
2000-02-24 14:31:43 +00:00
|
|
|
if (!requestmgr->exiting) {
|
|
|
|
requestmgr->exiting = ISC_TRUE;
|
2000-03-20 12:22:02 +00:00
|
|
|
for (request = ISC_LIST_HEAD(requestmgr->requests);
|
|
|
|
request != NULL;
|
|
|
|
request = ISC_LIST_NEXT(request, link)) {
|
|
|
|
dns_request_cancel(request);
|
|
|
|
}
|
2000-04-18 08:27:48 +00:00
|
|
|
if (ISC_LIST_EMPTY(requestmgr->requests))
|
|
|
|
send_shutdown_events(requestmgr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Locked by caller.
|
|
|
|
*/
|
|
|
|
|
|
|
|
TRACE(("requestmgr_attach\n"));
|
|
|
|
|
|
|
|
REQUIRE(VALID_REQUESTMGR(source));
|
|
|
|
REQUIRE(targetp != NULL && *targetp == NULL);
|
|
|
|
|
|
|
|
REQUIRE(!source->exiting);
|
|
|
|
|
|
|
|
source->iref++;
|
|
|
|
*targetp = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
requestmgr_detach(dns_requestmgr_t **requestmgrp) {
|
|
|
|
dns_requestmgr_t *requestmgr;
|
|
|
|
isc_boolean_t need_destroy =ISC_FALSE;
|
|
|
|
|
|
|
|
TRACE(("requestmgr_detach\n"));
|
|
|
|
REQUIRE(requestmgrp != NULL);
|
|
|
|
requestmgr = *requestmgrp;
|
|
|
|
REQUIRE(VALID_REQUESTMGR(requestmgr));
|
|
|
|
*requestmgrp = NULL;
|
|
|
|
LOCK(&requestmgr->lock);
|
|
|
|
INSIST(requestmgr->iref > 0);
|
|
|
|
requestmgr->iref--;
|
|
|
|
if (requestmgr->eref == 0 && requestmgr->iref == 0) {
|
|
|
|
INSIST(requestmgr->exiting &&
|
|
|
|
ISC_LIST_HEAD(requestmgr->requests) == NULL);
|
2000-02-24 14:31:43 +00:00
|
|
|
send_shutdown_events(requestmgr);
|
2000-04-18 08:27:48 +00:00
|
|
|
need_destroy = ISC_TRUE;
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
2000-04-18 08:27:48 +00:00
|
|
|
UNLOCK(&requestmgr->lock);
|
|
|
|
|
|
|
|
if (need_destroy)
|
|
|
|
mgr_destroy(requestmgr);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
|
|
|
|
|
|
|
|
REQUIRE(VALID_REQUESTMGR(source));
|
|
|
|
REQUIRE(targetp != NULL && *targetp == NULL);
|
2000-03-13 20:43:39 +00:00
|
|
|
REQUIRE(!source->exiting);
|
2000-02-24 14:31:43 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_requestmgr_attach\n"));
|
2000-02-24 14:31:43 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
LOCK(&source->lock);
|
|
|
|
source->eref++;
|
2000-02-24 14:31:43 +00:00
|
|
|
*targetp = source;
|
2000-04-18 08:27:48 +00:00
|
|
|
UNLOCK(&source->lock);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
|
|
|
|
dns_requestmgr_t *requestmgr;
|
|
|
|
isc_boolean_t need_destroy = ISC_FALSE;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_requestmgr_detach\n"));
|
2000-02-24 14:31:43 +00:00
|
|
|
REQUIRE(requestmgrp != NULL);
|
2000-03-13 20:43:39 +00:00
|
|
|
requestmgr = *requestmgrp;
|
2000-02-24 14:31:43 +00:00
|
|
|
REQUIRE(VALID_REQUESTMGR(requestmgr));
|
|
|
|
|
|
|
|
LOCK(&requestmgr->lock);
|
2000-04-18 08:27:48 +00:00
|
|
|
INSIST(requestmgr->eref > 0);
|
|
|
|
requestmgr->eref--;
|
|
|
|
if (requestmgr->eref == 0 && requestmgr->iref == 0) {
|
2000-03-20 12:22:02 +00:00
|
|
|
INSIST(requestmgr->exiting &&
|
|
|
|
ISC_LIST_HEAD(requestmgr->requests) == NULL);
|
2000-04-18 08:27:48 +00:00
|
|
|
need_destroy = ISC_TRUE;
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
2000-03-13 20:43:39 +00:00
|
|
|
UNLOCK(&requestmgr->lock);
|
2000-02-24 14:31:43 +00:00
|
|
|
|
|
|
|
if (need_destroy)
|
2000-03-20 12:22:02 +00:00
|
|
|
mgr_destroy(requestmgr);
|
2000-02-24 14:31:43 +00:00
|
|
|
|
|
|
|
*requestmgrp = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
send_shutdown_events(dns_requestmgr_t *requestmgr) {
|
|
|
|
isc_event_t *event, *next_event;
|
|
|
|
isc_task_t *etask;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("send_shutdown_events\n"));
|
2000-02-24 14:31:43 +00:00
|
|
|
/*
|
|
|
|
* Caller must be holding the manager lock.
|
|
|
|
*/
|
|
|
|
for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
|
|
|
|
event != NULL;
|
|
|
|
event = next_event) {
|
2000-04-17 19:22:44 +00:00
|
|
|
next_event = ISC_LIST_NEXT(event, ev_link);
|
|
|
|
ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
|
|
|
|
etask = event->ev_sender;
|
|
|
|
event->ev_sender = requestmgr;
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_task_sendanddetach(&etask, &event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-03-20 12:22:02 +00:00
|
|
|
mgr_destroy(dns_requestmgr_t *requestmgr) {
|
2000-03-22 07:00:39 +00:00
|
|
|
int i;
|
2000-04-18 08:27:48 +00:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
|
|
|
|
TRACE(("mgr_destroy\n"));
|
2000-03-22 07:00:39 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
REQUIRE(requestmgr->eref == 0);
|
|
|
|
REQUIRE(requestmgr->iref == 0);
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_mutex_destroy(&requestmgr->lock);
|
2000-03-22 07:00:39 +00:00
|
|
|
for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
|
|
|
|
isc_mutex_destroy(&requestmgr->locks[i]);
|
2000-02-24 14:31:43 +00:00
|
|
|
if (requestmgr->dispatchv4 != NULL)
|
|
|
|
dns_dispatch_detach(&requestmgr->dispatchv4);
|
2000-04-18 08:27:48 +00:00
|
|
|
if (requestmgr->dispatchv6 != NULL)
|
|
|
|
dns_dispatch_detach(&requestmgr->dispatchv6);
|
2000-03-13 20:43:39 +00:00
|
|
|
requestmgr->magic = 0;
|
2000-04-18 08:27:48 +00:00
|
|
|
mctx = requestmgr->mctx;
|
|
|
|
isc_mem_put(mctx, requestmgr, sizeof *requestmgr);
|
|
|
|
isc_mem_detach(&mctx);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
static unsigned int
|
|
|
|
mgr_gethash(dns_requestmgr_t *requestmgr) {
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("mgr_gethash\n"));
|
2000-03-22 07:00:39 +00:00
|
|
|
/*
|
|
|
|
* Locked by caller.
|
|
|
|
*/
|
|
|
|
requestmgr->hash++;
|
|
|
|
return(requestmgr->hash % DNS_REQUEST_NLOCKS);
|
|
|
|
}
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
static inline isc_result_t
|
|
|
|
req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
|
|
|
|
isc_region_t r;
|
|
|
|
isc_socket_t *socket;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_send\n"));
|
2000-03-20 12:22:02 +00:00
|
|
|
socket = dns_dispatch_getsocket(request->dispatch);
|
|
|
|
isc_buffer_used(request->query, &r);
|
|
|
|
return (isc_socket_sendto(socket, &r, task, req_senddone,
|
|
|
|
request, address, NULL));
|
|
|
|
}
|
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
|
|
|
|
isc_sockaddr_t *address, unsigned int options,
|
|
|
|
unsigned int timeout, isc_task_t *task,
|
|
|
|
isc_taskaction_t action, void *arg,
|
|
|
|
dns_request_t **requestp)
|
|
|
|
{
|
2000-03-13 20:43:39 +00:00
|
|
|
dns_request_t *request = NULL;
|
|
|
|
isc_task_t *tclone = NULL;
|
|
|
|
isc_socket_t *socket = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_mem_t *mctx;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_interval_t interval;
|
|
|
|
dns_messageid_t id;
|
|
|
|
isc_time_t expires;
|
2000-02-24 14:31:43 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_REQUESTMGR(requestmgr));
|
|
|
|
REQUIRE(message != NULL);
|
2000-03-13 20:43:39 +00:00
|
|
|
REQUIRE(address != NULL);
|
2000-02-24 14:31:43 +00:00
|
|
|
REQUIRE(task != NULL);
|
|
|
|
REQUIRE(action != NULL);
|
|
|
|
REQUIRE(requestp != NULL && *requestp == NULL);
|
|
|
|
REQUIRE(timeout > 0);
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_request_create\n"));
|
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
mctx = requestmgr->mctx;
|
|
|
|
|
|
|
|
request = isc_mem_get(mctx, sizeof(*request));
|
|
|
|
if (request == NULL) {
|
2000-03-20 12:22:02 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2000-03-13 20:43:39 +00:00
|
|
|
}
|
2000-03-20 12:22:02 +00:00
|
|
|
/*
|
|
|
|
* Zero structure.
|
|
|
|
*/
|
|
|
|
request->magic = 0;
|
2000-04-18 08:27:48 +00:00
|
|
|
request->mctx = NULL;
|
2000-03-20 12:22:02 +00:00
|
|
|
request->flags = 0;
|
|
|
|
ISC_LINK_INIT(request, link);
|
|
|
|
request->query = NULL;
|
|
|
|
request->answer = NULL;
|
|
|
|
request->event = NULL;
|
|
|
|
request->dispatch = NULL;
|
|
|
|
request->dispentry = NULL;
|
|
|
|
request->timer = NULL;
|
|
|
|
request->requestmgr = NULL;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
/*
|
|
|
|
* Create timer now. We will set it below once.
|
|
|
|
*/
|
|
|
|
result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
|
|
|
|
NULL, NULL, task, req_timeout, request,
|
|
|
|
&request->timer);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
request->event = (dns_requestevent_t *)
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
|
|
|
|
action, arg, sizeof (dns_requestevent_t));
|
2000-03-20 12:22:02 +00:00
|
|
|
if (request->event == NULL) {
|
2000-03-13 20:43:39 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
isc_task_attach(task, &tclone);
|
2000-04-17 19:22:44 +00:00
|
|
|
request->event->ev_sender = task;
|
2000-03-20 12:22:02 +00:00
|
|
|
request->event->request = request;
|
|
|
|
request->event->result = ISC_R_FAILURE;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
use_tcp:
|
|
|
|
if ((options & DNS_REQUESTOPT_TCP) != 0) {
|
|
|
|
result = isc_socket_create(requestmgr->socketmgr,
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_sockaddr_pf(address),
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_sockettype_tcp, &socket);
|
2000-03-13 20:43:39 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
result = dns_dispatch_create(mctx, socket, task,
|
|
|
|
4096, 2, 1, 1, 3, NULL,
|
2000-03-20 12:22:02 +00:00
|
|
|
&request->dispatch);
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_socket_detach(&socket);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
switch (isc_sockaddr_pf(address)) {
|
|
|
|
case PF_INET:
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_dispatch_attach(requestmgr->dispatchv4,
|
|
|
|
&request->dispatch);
|
2000-03-13 20:43:39 +00:00
|
|
|
break;
|
|
|
|
case PF_INET6:
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_dispatch_attach(requestmgr->dispatchv6,
|
|
|
|
&request->dispatch);
|
2000-03-13 20:43:39 +00:00
|
|
|
break;
|
|
|
|
default:
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOTIMPLEMENTED;
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
2000-03-20 12:22:02 +00:00
|
|
|
socket = dns_dispatch_getsocket(request->dispatch);
|
|
|
|
INSIST(socket != NULL);
|
|
|
|
result = dns_dispatch_addresponse(request->dispatch, address, task,
|
|
|
|
req_response, request, &id,
|
2000-03-13 20:43:39 +00:00
|
|
|
&request->dispentry);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
message->id = id;
|
|
|
|
result = render(message, &request->query, mctx);
|
|
|
|
if (result == DNS_R_USETCP &&
|
|
|
|
(options & DNS_REQUESTOPT_TCP) == 0) {
|
|
|
|
/*
|
|
|
|
* Try again using TCP.
|
|
|
|
*/
|
|
|
|
dns_message_renderreset(message);
|
|
|
|
dns_dispatch_removeresponse(request->dispatch,
|
|
|
|
&request->dispentry, NULL);
|
|
|
|
dns_dispatch_detach(&request->dispatch);
|
|
|
|
socket = NULL;
|
|
|
|
isc_buffer_free(&request->query);
|
|
|
|
options |= DNS_REQUESTOPT_TCP;
|
|
|
|
goto use_tcp;
|
|
|
|
}
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_USETCP)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
isc_mem_attach(mctx, &request->mctx);
|
2000-03-20 12:22:02 +00:00
|
|
|
LOCK(&requestmgr->lock);
|
2000-04-18 08:27:48 +00:00
|
|
|
if (requestmgr->exiting) {
|
|
|
|
UNLOCK(&requestmgr->lock);
|
|
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
requestmgr_attach(requestmgr, &request->requestmgr);
|
2000-03-22 07:00:39 +00:00
|
|
|
request->hash = mgr_gethash(requestmgr);
|
2000-04-18 08:27:48 +00:00
|
|
|
request->magic = REQUEST_MAGIC;
|
2000-03-20 12:22:02 +00:00
|
|
|
ISC_LIST_APPEND(requestmgr->requests, request, link);
|
|
|
|
UNLOCK(&requestmgr->lock);
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_interval_set(&interval, timeout, 0);
|
|
|
|
result = isc_time_nowplusinterval(&expires, &interval);
|
2000-03-13 20:43:39 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-04-18 08:27:48 +00:00
|
|
|
goto unlink;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
result = isc_timer_reset(request->timer, isc_timertype_once,
|
|
|
|
&expires, NULL, ISC_FALSE);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-04-18 08:27:48 +00:00
|
|
|
goto unlink;
|
2000-03-20 12:22:02 +00:00
|
|
|
|
|
|
|
if ((options & DNS_REQUESTOPT_TCP) != 0) {
|
|
|
|
result = isc_socket_connect(socket, address, task,
|
|
|
|
req_connected, request);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-04-18 08:27:48 +00:00
|
|
|
goto unlink;
|
2000-03-20 12:22:02 +00:00
|
|
|
request->flags |= DNS_REQUEST_F_CONNECTING;
|
|
|
|
} else {
|
|
|
|
result = req_send(request, task, address);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-04-18 08:27:48 +00:00
|
|
|
goto unlink;
|
2000-03-20 12:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*requestp = request;
|
2000-02-24 14:31:43 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
unlink:
|
|
|
|
LOCK(&requestmgr->lock);
|
|
|
|
ISC_LIST_UNLINK(requestmgr->requests, request, link);
|
|
|
|
UNLOCK(&requestmgr->lock);
|
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
cleanup:
|
2000-03-22 07:00:39 +00:00
|
|
|
if (request->requestmgr != NULL)
|
2000-04-18 08:27:48 +00:00
|
|
|
requestmgr_detach(&request->requestmgr);
|
2000-03-20 12:22:02 +00:00
|
|
|
if (request->dispentry != NULL)
|
|
|
|
dns_dispatch_removeresponse(request->dispatch,
|
|
|
|
&request->dispentry, NULL);
|
|
|
|
if (request->dispatch != NULL)
|
|
|
|
dns_dispatch_detach(&request->dispatch);
|
|
|
|
if (request->event != NULL)
|
|
|
|
isc_event_free((isc_event_t **)&request->event);
|
|
|
|
if (request->query != NULL)
|
|
|
|
isc_buffer_free(&request->query);
|
|
|
|
if (request->timer != NULL)
|
|
|
|
isc_timer_detach(&request->timer);
|
2000-03-13 20:43:39 +00:00
|
|
|
if (tclone != NULL)
|
|
|
|
isc_task_detach(&tclone);
|
2000-04-18 08:27:48 +00:00
|
|
|
if (request->mctx != NULL)
|
|
|
|
isc_mem_detach(&request->mctx);
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_mem_put(mctx, request, sizeof *request);
|
2000-03-13 20:43:39 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
render(dns_message_t *message, isc_buffer_t **bufferp, isc_mem_t *mctx) {
|
|
|
|
isc_buffer_t *buf1 = NULL;
|
|
|
|
isc_buffer_t *buf2 = NULL;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
REQUIRE(bufferp != NULL && *bufferp == NULL);
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("render\n"));
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
/*
|
|
|
|
* Create buffer able to hold largest possible message.
|
|
|
|
*/
|
|
|
|
result = isc_buffer_allocate(mctx, &buf1, 65535,
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Render message.
|
|
|
|
*/
|
|
|
|
result = dns_message_renderbegin(message, buf1);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_renderend(message);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy rendered message to exact sized buffer.
|
|
|
|
*/
|
|
|
|
isc_buffer_used(buf1, &r);
|
|
|
|
result = isc_buffer_allocate(mctx, &buf2, r.length +
|
|
|
|
((r.length > 512) ? 2 : 0),
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
if (r.length > 512) {
|
|
|
|
isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
|
|
|
|
}
|
|
|
|
result = isc_buffer_copyregion(buf2, &r);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup and return.
|
|
|
|
*/
|
|
|
|
isc_buffer_free(&buf1);
|
|
|
|
*bufferp = buf2;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
cleanup:
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_message_renderreset(message);
|
2000-03-13 20:43:39 +00:00
|
|
|
if (buf1 != NULL)
|
|
|
|
isc_buffer_free(&buf1);
|
|
|
|
if (buf2 != NULL)
|
|
|
|
isc_buffer_free(&buf2);
|
|
|
|
return (result);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_request_cancel(dns_request_t *request) {
|
2000-03-20 12:22:02 +00:00
|
|
|
REQUIRE(VALID_REQUEST(request));
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_request_cancel\n"));
|
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
LOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-20 12:22:02 +00:00
|
|
|
if (!DNS_REQUEST_CANCELED(request)) {
|
|
|
|
req_cancel(request);
|
|
|
|
req_sendevent(request, ISC_R_CANCELED);
|
|
|
|
}
|
2000-03-22 07:00:39 +00:00
|
|
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-20 12:22:02 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-02-24 14:31:43 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_request_getresponse(dns_request_t *request, dns_message_t *message) {
|
2000-03-13 20:43:39 +00:00
|
|
|
REQUIRE(VALID_REQUEST(request));
|
|
|
|
REQUIRE(request->answer != NULL);
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("dns_request_getresponse\n"));
|
|
|
|
|
2000-03-13 20:43:39 +00:00
|
|
|
return (dns_message_parse(message, request->answer, ISC_TRUE));
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_request_destroy(dns_request_t **requestp) {
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_request_t *request;
|
2000-03-22 07:00:39 +00:00
|
|
|
isc_boolean_t need_destroy = ISC_FALSE;
|
2000-03-20 12:22:02 +00:00
|
|
|
|
|
|
|
REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
|
2000-04-18 08:27:48 +00:00
|
|
|
|
|
|
|
TRACE(("dns_request_destroy\n"));
|
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
request = *requestp;
|
2000-03-22 07:00:39 +00:00
|
|
|
LOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-20 12:22:02 +00:00
|
|
|
LOCK(&request->requestmgr->lock);
|
|
|
|
ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
|
|
|
|
UNLOCK(&request->requestmgr->lock);
|
|
|
|
if (!DNS_REQUEST_CONNECTING(request))
|
2000-03-22 07:00:39 +00:00
|
|
|
need_destroy = ISC_TRUE;
|
|
|
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
|
|
|
|
|
|
|
if (need_destroy)
|
2000-03-20 12:22:02 +00:00
|
|
|
req_destroy(request);
|
2000-03-22 07:00:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
*requestp = NULL;
|
2000-02-24 14:31:43 +00:00
|
|
|
}
|
2000-03-20 12:22:02 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
*** Private: request.
|
|
|
|
***/
|
2000-03-13 20:43:39 +00:00
|
|
|
|
|
|
|
static void
|
2000-03-20 12:22:02 +00:00
|
|
|
req_connected(isc_task_t *task, isc_event_t *event) {
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_result_t result;
|
2000-04-17 19:22:44 +00:00
|
|
|
dns_request_t *request = event->ev_arg;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
|
2000-03-20 12:22:02 +00:00
|
|
|
REQUIRE(DNS_REQUEST_CONNECTING(request));
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_connected\n"));
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
request->flags &= ~DNS_REQUEST_F_CONNECTING;
|
|
|
|
|
|
|
|
if (DNS_REQUEST_CANCELED(request)) {
|
|
|
|
req_destroy(request);
|
|
|
|
} else {
|
|
|
|
result = sevent->result;
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = req_send(request, task, NULL);
|
|
|
|
|
|
|
|
if (sevent->result != ISC_R_SUCCESS)
|
|
|
|
dns_request_cancel(request);
|
|
|
|
}
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
req_senddone(isc_task_t *task, isc_event_t *event) {
|
|
|
|
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
|
2000-04-17 19:22:44 +00:00
|
|
|
dns_request_t *request = event->ev_arg;
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_senddone\n"));
|
2000-03-13 20:43:39 +00:00
|
|
|
(void)task;
|
|
|
|
|
|
|
|
if (sevent->result != ISC_R_SUCCESS)
|
2000-03-20 12:22:02 +00:00
|
|
|
dns_request_cancel(request);
|
2000-03-13 20:43:39 +00:00
|
|
|
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-03-20 12:22:02 +00:00
|
|
|
req_response(isc_task_t *task, isc_event_t *event) {
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_result_t result;
|
2000-04-17 19:22:44 +00:00
|
|
|
dns_request_t *request = event->ev_arg;
|
2000-03-13 20:43:39 +00:00
|
|
|
dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_region_t r;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_REQUEST(request));
|
2000-04-17 19:22:44 +00:00
|
|
|
REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-03-20 12:22:02 +00:00
|
|
|
UNUSED(task);
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_response: %s\n", dns_result_totext(devent->result)));
|
2000-03-20 12:22:02 +00:00
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
LOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-20 12:22:02 +00:00
|
|
|
result = devent->result;
|
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-03-13 20:43:39 +00:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
/*
|
2000-03-20 12:22:02 +00:00
|
|
|
* Copy buffer to request.
|
2000-03-13 20:43:39 +00:00
|
|
|
*/
|
2000-03-20 12:22:02 +00:00
|
|
|
isc_buffer_used(&devent->buffer, &r);
|
|
|
|
result = isc_buffer_allocate(request->mctx, &request->answer, r.length,
|
|
|
|
ISC_BUFFERTYPE_BINARY);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto done;
|
|
|
|
result = isc_buffer_copyregion(request->answer, &r);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
isc_buffer_free(&request->answer);
|
2000-03-13 20:43:39 +00:00
|
|
|
done:
|
2000-03-20 12:22:02 +00:00
|
|
|
/*
|
|
|
|
* Cleanup.
|
|
|
|
*/
|
|
|
|
dns_dispatch_removeresponse(request->dispatch, &request->dispentry,
|
|
|
|
&devent);
|
|
|
|
req_cancel(request);
|
|
|
|
/*
|
|
|
|
* Send completion event.
|
|
|
|
*/
|
|
|
|
req_sendevent(request, result);
|
2000-03-22 07:00:39 +00:00
|
|
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-13 20:43:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-03-20 12:22:02 +00:00
|
|
|
req_timeout(isc_task_t *task, isc_event_t *event) {
|
2000-04-17 19:22:44 +00:00
|
|
|
dns_request_t *request = event->ev_arg;
|
2000-03-13 20:43:39 +00:00
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_timeout\n"));
|
2000-03-20 12:22:02 +00:00
|
|
|
UNUSED(task);
|
2000-03-22 07:00:39 +00:00
|
|
|
LOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-20 12:22:02 +00:00
|
|
|
req_cancel(request);
|
|
|
|
req_sendevent(request, ISC_R_TIMEDOUT);
|
2000-03-22 07:00:39 +00:00
|
|
|
UNLOCK(&request->requestmgr->locks[request->hash]);
|
2000-03-13 20:43:39 +00:00
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
2000-03-20 12:22:02 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
req_sendevent(dns_request_t *request, isc_result_t result) {
|
|
|
|
isc_task_t *task;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_sendevent\n"));
|
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
/*
|
|
|
|
* Lock held by caller.
|
|
|
|
*/
|
2000-04-17 19:22:44 +00:00
|
|
|
task = request->event->ev_sender;
|
|
|
|
request->event->ev_sender = request;
|
2000-03-20 12:22:02 +00:00
|
|
|
request->event->result = result;
|
|
|
|
isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
req_destroy(dns_request_t *request) {
|
2000-04-18 08:27:48 +00:00
|
|
|
isc_mem_t *mctx;
|
|
|
|
|
|
|
|
TRACE(("req_destroy\n"));
|
2000-03-20 12:22:02 +00:00
|
|
|
|
|
|
|
request->magic = 0;
|
|
|
|
if (request->query != NULL)
|
|
|
|
isc_buffer_free(&request->query);
|
|
|
|
if (request->answer != NULL)
|
|
|
|
isc_buffer_free(&request->answer);
|
|
|
|
if (request->event != NULL)
|
|
|
|
isc_event_free((isc_event_t **)&request->event);
|
|
|
|
if (request->dispentry != NULL)
|
|
|
|
dns_dispatch_removeresponse(request->dispatch,
|
|
|
|
&request->dispentry, NULL);
|
|
|
|
if (request->dispatch != NULL)
|
|
|
|
dns_dispatch_detach(&request->dispatch);
|
|
|
|
if (request->timer != NULL)
|
|
|
|
isc_timer_detach(&request->timer);
|
2000-04-18 08:27:48 +00:00
|
|
|
requestmgr_detach(&request->requestmgr);
|
|
|
|
mctx = request->mctx;
|
|
|
|
isc_mem_put(mctx, request, sizeof(*request));
|
|
|
|
isc_mem_detach(&mctx);
|
2000-03-20 12:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
req_cancel(dns_request_t *request) {
|
|
|
|
isc_socket_t *socket;
|
|
|
|
|
2000-04-18 08:27:48 +00:00
|
|
|
TRACE(("req_cancel\n"));
|
|
|
|
|
2000-03-22 07:00:39 +00:00
|
|
|
/*
|
2000-04-18 08:27:48 +00:00
|
|
|
* Lock held by caller.
|
2000-03-22 07:00:39 +00:00
|
|
|
*/
|
2000-03-20 12:22:02 +00:00
|
|
|
request->flags |= DNS_REQUEST_F_CANCELED;
|
|
|
|
|
|
|
|
if (request->timer != NULL)
|
|
|
|
isc_timer_detach(&request->timer);
|
|
|
|
if (request->dispentry != NULL)
|
|
|
|
dns_dispatch_removeresponse(request->dispatch,
|
|
|
|
&request->dispentry, NULL);
|
|
|
|
if (DNS_REQUEST_CONNECTING(request)) {
|
|
|
|
socket = dns_dispatch_getsocket(request->dispatch);
|
|
|
|
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
|
|
|
|
}
|
2000-04-18 08:27:48 +00:00
|
|
|
dns_dispatch_detach(&request->dispatch);
|
2000-03-20 12:22:02 +00:00
|
|
|
}
|