request.c revision 78da321b437bbb690ef570ccf17dcc8583a5a4a0
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/*
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Copyright (C) 2000 Internet Software Consortium.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Permission to use, copy, modify, and distribute this software for any
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * purpose with or without fee is hereby granted, provided that the above
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * copyright notice and this permission notice appear in all copies.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * SOFTWARE.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#include <config.h>
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/assertions.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/buffer.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/event.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/net.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/mutex.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/region.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/socket.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/task.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/timer.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <isc/util.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <dns/dispatch.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <dns/events.h>
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews#include <dns/message.h>
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#include <dns/request.h>
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define REQUESTMGR_MAGIC 0x5271754dU /* RquM */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define VALID_REQUESTMGR(mgr) ((mgr) != NULL && \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews (mgr)->magic == REQUESTMGR_MAGIC)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define REQUEST_MAGIC 0x52717521U /* Rqu! */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews#define VALID_REQUEST(request) ((request) != NULL && \
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews (request)->magic == REQUEST_MAGIC)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#if 1
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define TRACE(x) printf(x)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#else
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define TRACE(x)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#endif
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewstypedef ISC_LIST(dns_request_t) dns_requestlist_t;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstruct dns_requestmgr {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_int32_t magic;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mutex_t lock;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mem_t *mctx;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* locked */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_int32_t references;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_timermgr_t *timermgr;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socketmgr_t *socketmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_dispatch_t *dispatchv4;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_dispatch_t *dispatchv6;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_boolean_t exiting;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_eventlist_t whenshutdown;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_requestlist_t requests;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews};
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstruct dns_request {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_int32_t magic;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_mem_t *mctx;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_int32_t flags;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LINK(dns_request_t) link;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_t *query;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_t *answer;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_requestevent_t *event;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_t *dispatch;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispentry_t *dispentry;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_timer_t *timer;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_requestmgr_t *requestmgr;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews};
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_REQUEST_F_CONNECTING 0x0001
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_REQUEST_F_CANCELED 0x0002
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_REQUEST_CANCELED(r) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews#define DNS_REQUEST_CONNECTING(r) \
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/***
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *** Forward
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ***/
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void mgr_destroy(dns_requestmgr_t *requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void mgr_shutdown(dns_requestmgr_t *requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void send_shutdown_events(dns_requestmgr_t *requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsstatic isc_result_t render(dns_message_t *message, isc_buffer_t **buffer,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_mem_t *mctx);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_senddone(isc_task_t *task, isc_event_t *event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_response(isc_task_t *task, isc_event_t *event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_timeout(isc_task_t *task, isc_event_t *event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_connected(isc_task_t *task, isc_event_t *event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_sendevent(dns_request_t *request, isc_result_t result);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_cancel(dns_request_t *request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void req_destroy(dns_request_t *request);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews/***
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *** Public
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ***/
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_result_t
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsdns_requestmgr_create(isc_mem_t *mctx,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_timermgr_t *timermgr,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socketmgr_t *socketmgr,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_t *dispatchv4,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_t *dispatchv6,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_requestmgr_t **requestmgrp)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews{
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_requestmgr_t *requestmgr;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_socket_t *socket;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_result_t result;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(timermgr != NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(socketmgr != NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (dispatchv4 != NULL) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews socket = dns_dispatch_getsocket(dispatchv4);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (dispatchv6 != NULL) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews socket = dns_dispatch_getsocket(dispatchv6);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (requestmgr == NULL)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_R_NOMEMORY);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = isc_mutex_init(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (result != DNS_R_SUCCESS) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (result);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->timermgr = timermgr;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews requestmgr->socketmgr = socketmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->dispatchv4 = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (dispatchv4 != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->dispatchv6 = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (dispatchv6 != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->mctx = mctx;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->references = 1; /* implict attach */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ISC_LIST_INIT(requestmgr->whenshutdown);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_INIT(requestmgr->requests);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->exiting = ISC_FALSE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->magic = REQUESTMGR_MAGIC;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *requestmgrp = requestmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_R_SUCCESS);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_event_t **eventp)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews{
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_task_t *clone;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_event_t *event;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(eventp != NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event = *eventp;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *eventp = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews LOCK(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (requestmgr->exiting) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * We're already shutdown. Send the event.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event->sender = requestmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_task_send(task, &event);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews } else {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews clone = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_task_attach(task, &clone);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event->sender = clone;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews ISC_LIST_APPEND(requestmgr->whenshutdown, event, link);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews UNLOCK(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews LOCK(&requestmgr->lock);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews mgr_shutdown(requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews UNLOCK(&requestmgr->lock);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsmgr_shutdown(dns_requestmgr_t *requestmgr) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_t *request;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Caller holds lock.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (!requestmgr->exiting) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->exiting = ISC_TRUE;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews for (request = ISC_LIST_HEAD(requestmgr->requests);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request != NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request = ISC_LIST_NEXT(request, link)) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_cancel(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews send_shutdown_events(requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_REQUESTMGR(source));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(targetp != NULL && *targetp == NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews LOCK(&source->lock);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(!source->exiting);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(source->references > 0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews source->references++;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(source->references != 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews UNLOCK(&source->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *targetp = source;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_requestmgr_t *requestmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_boolean_t need_destroy = ISC_FALSE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(requestmgrp != NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews requestmgr = *requestmgrp;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews LOCK(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews INSIST(requestmgr->references > 0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr->references--;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (requestmgr->references == 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(requestmgr->exiting &&
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_HEAD(requestmgr->requests) == NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews need_destroy = ISC_TRUE;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews UNLOCK(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (need_destroy)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews mgr_destroy(requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews *requestmgrp = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewssend_shutdown_events(dns_requestmgr_t *requestmgr) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_event_t *event, *next_event;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_task_t *etask;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /*
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Caller must be holding the manager lock.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews */
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event != NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event = next_event) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews next_event = ISC_LIST_NEXT(event, link);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews ISC_LIST_UNLINK(requestmgr->whenshutdown, event, link);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews etask = event->sender;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews event->sender = requestmgr;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_task_sendanddetach(&etask, &event);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews }
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsmgr_destroy(dns_requestmgr_t *requestmgr) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(requestmgr->references == 0);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mutex_destroy(&requestmgr->lock);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (requestmgr->dispatchv4 != NULL)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_dispatch_detach(&requestmgr->dispatchv4);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews if (requestmgr->dispatchv4 != NULL)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_dispatch_detach(&requestmgr->dispatchv4);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews requestmgr->magic = 0;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mem_put(requestmgr->mctx, requestmgr, sizeof *requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic inline isc_result_t
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_region_t r;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socket_t *socket;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews socket = dns_dispatch_getsocket(request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_used(request->query, &r);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (isc_socket_sendto(socket, &r, task, req_senddone,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request, address, NULL));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_result_t
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_sockaddr_t *address, unsigned int options,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews unsigned int timeout, isc_task_t *task,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_taskaction_t action, void *arg,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews dns_request_t **requestp)
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews{
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_request_t *request = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_task_t *tclone = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_socket_t *socket = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_result_t result;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_mem_t *mctx;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_interval_t interval;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_messageid_t id;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_time_t expires;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(message != NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(address != NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(task != NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(action != NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(requestp != NULL && *requestp == NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(timeout > 0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews mctx = requestmgr->mctx;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews request = isc_mem_get(mctx, sizeof(*request));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (request == NULL) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_R_NOMEMORY);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Zero structure.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->magic = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->mctx = mctx;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->flags = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LINK_INIT(request, link);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->query = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->answer = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->dispatch = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->dispentry = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->timer = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->requestmgr = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_requestmgr_attach(requestmgr, &request->requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Create timer now. We will set it below once.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews NULL, NULL, task, req_timeout, request,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->timer);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto cleanup;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event = (dns_requestevent_t *)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews action, arg, sizeof (dns_requestevent_t));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->event == NULL) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = ISC_R_NOMEMORY;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_task_attach(task, &tclone);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event->sender = task;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event->request = request;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event->result = ISC_R_FAILURE;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews use_tcp:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((options & DNS_REQUESTOPT_TCP) != 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_socket_create(requestmgr->socketmgr,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_sockaddr_pf(address),
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_sockettype_tcp, &socket);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_dispatch_create(mctx, socket, task,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews 4096, 2, 1, 1, 3, NULL,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispatch);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_socket_detach(&socket);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews } else {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews switch (isc_sockaddr_pf(address)) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews case PF_INET:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_attach(requestmgr->dispatchv4,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispatch);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews break;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews case PF_INET6:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_attach(requestmgr->dispatchv6,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispatch);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews break;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews default:
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = DNS_R_NOTIMPLEMENTED;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews socket = dns_dispatch_getsocket(request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews INSIST(socket != NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = dns_dispatch_addresponse(request->dispatch, address, task,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_response, request, &id,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews &request->dispentry);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews message->id = id;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = render(message, &request->query, mctx);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result == DNS_R_USETCP &&
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews (options & DNS_REQUESTOPT_TCP) == 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Try again using TCP.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_message_renderreset(message);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_removeresponse(request->dispatch,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispentry, NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_detach(&request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews socket = NULL;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_free(&request->query);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews options |= DNS_REQUESTOPT_TCP;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto use_tcp;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS && result != DNS_R_USETCP)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews request->magic = REQUEST_MAGIC;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews LOCK(&requestmgr->lock);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_APPEND(requestmgr->requests, request, link);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews UNLOCK(&requestmgr->lock);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_interval_set(&interval, timeout, 0);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_time_nowplusinterval(&expires, &interval);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_timer_reset(request->timer, isc_timertype_once,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &expires, NULL, ISC_FALSE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto cleanup;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if ((options & DNS_REQUESTOPT_TCP) != 0) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_socket_connect(socket, address, task,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_connected, request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto cleanup;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->flags |= DNS_REQUEST_F_CONNECTING;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews } else {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = req_send(request, task, address);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto cleanup;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *requestp = request;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews return (ISC_R_SUCCESS);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews cleanup:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->dispentry != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_removeresponse(request->dispatch,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispentry, NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->dispatch != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_detach(&request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->event != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_event_free((isc_event_t **)&request->event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->query != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_free(&request->query);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->timer != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_timer_detach(&request->timer);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (tclone != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_task_detach(&tclone);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->magic = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_mem_put(mctx, request, sizeof *request);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (result);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsstatic isc_result_t
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsrender(dns_message_t *message, isc_buffer_t **bufferp, isc_mem_t *mctx) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_t *buf1 = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_t *buf2 = NULL;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_result_t result;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_region_t r;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(bufferp != NULL && *bufferp == NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews TRACE("render\n");
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Create buffer able to hold largest possible message.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = isc_buffer_allocate(mctx, &buf1, 65535,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews ISC_BUFFERTYPE_BINARY);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (result);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Render message.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_renderbegin(message, buf1);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_renderend(message);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != DNS_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Copy rendered message to exact sized buffer.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_used(buf1, &r);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = isc_buffer_allocate(mctx, &buf2, r.length +
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews ((r.length > 512) ? 2 : 0),
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews ISC_BUFFERTYPE_BINARY);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (r.length > 512) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews }
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = isc_buffer_copyregion(buf2, &r);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto cleanup;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Cleanup and return.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_free(&buf1);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews *bufferp = buf2;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (ISC_R_SUCCESS);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews cleanup:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_message_renderreset(message);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (buf1 != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_free(&buf1);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (buf2 != NULL)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_free(&buf2);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (result);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_result_t
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_request_cancel(dns_request_t *request) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(VALID_REQUEST(request));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (!DNS_REQUEST_CANCELED(request)) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_cancel(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_sendevent(request, ISC_R_CANCELED);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews return (ISC_R_SUCCESS);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsisc_result_t
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_request_getresponse(dns_request_t *request, dns_message_t *message) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_REQUEST(request));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(request->answer != NULL);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews return (dns_message_parse(message, request->answer, ISC_TRUE));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsvoid
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_request_destroy(dns_request_t **requestp) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_t *request;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request = *requestp;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews LOCK(&request->requestmgr->lock);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews UNLOCK(&request->requestmgr->lock);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (!DNS_REQUEST_CONNECTING(request))
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_destroy(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *requestp = NULL;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews/***
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *** Private: request.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ***/
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_connected(isc_task_t *task, isc_event_t *event) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_result_t result;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_request_t *request = event->arg;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(event->type == ISC_SOCKEVENT_SENDDONE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(DNS_REQUEST_CONNECTING(request));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews TRACE("req_connected\n");
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->flags &= ~DNS_REQUEST_F_CONNECTING;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (DNS_REQUEST_CANCELED(request)) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_destroy(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews } else {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = sevent->result;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result == ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = req_send(request, task, NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (sevent->result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_cancel(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_event_free(&event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_senddone(isc_task_t *task, isc_event_t *event) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_t *request = event->arg;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(event->type == ISC_SOCKEVENT_SENDDONE);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews TRACE("req_senddone\n");
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews (void)task;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews if (sevent->result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_request_cancel(request);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_event_free(&event);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_response(isc_task_t *task, isc_event_t *event) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_result_t result;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_request_t *request = event->arg;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_region_t r;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(VALID_REQUEST(request));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews REQUIRE(event->type == DNS_EVENT_DISPATCH);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews UNUSED(task);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews TRACE("req_response\n");
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = devent->result;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews goto done;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Copy buffer to request.
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_used(&devent->buffer, &r);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_buffer_allocate(request->mctx, &request->answer, r.length,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_BUFFERTYPE_BINARY);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews goto done;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_buffer_copyregion(request->answer, &r);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (result != ISC_R_SUCCESS)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_free(&request->answer);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews done:
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Cleanup.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_removeresponse(request->dispatch, &request->dispentry,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &devent);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_cancel(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews /*
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Send completion event.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews */
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_sendevent(request, result);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_timeout(isc_task_t *task, isc_event_t *event) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_request_t *request = event->arg;
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews TRACE("req_timeout\n");
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews UNUSED(task);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_cancel(request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews req_sendevent(request, ISC_R_TIMEDOUT);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_event_free(&event);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_sendevent(dns_request_t *request, isc_result_t result) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_task_t *task;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews task = request->event->sender;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event->sender = request;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->event->result = result;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_destroy(dns_request_t *request) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->magic = 0;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->query != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_free(&request->query);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->answer != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_buffer_free(&request->answer);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->event != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_event_free((isc_event_t **)&request->event);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->dispentry != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_removeresponse(request->dispatch,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispentry, NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->dispatch != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_detach(&request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->timer != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_timer_detach(&request->timer);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_requestmgr_detach(&request->requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_mem_put(request->mctx, request, sizeof(*request));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_cancel(dns_request_t *request) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socket_t *socket;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews request->flags |= DNS_REQUEST_F_CANCELED;
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->timer != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_timer_detach(&request->timer);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (request->dispentry != NULL)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_removeresponse(request->dispatch,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews &request->dispentry, NULL);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews dns_dispatch_detach(&request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews if (DNS_REQUEST_CONNECTING(request)) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews socket = dns_dispatch_getsocket(request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews }
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews}