request.c revision 046a9aca49bdc25bd57d75fd0dd34c021722f095
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews/*
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence * Copyright (C) 2000 Internet Software Consortium.
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt *
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * Permission to use, copy, modify, and distribute this software for any
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * purpose with or without fee is hereby granted, provided that the above
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt * copyright notice and this permission notice appear in all copies.
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence *
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews */
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence/* $Id: request.c,v 1.46 2000/12/31 05:05:34 marka Exp $ */
101a7960b7989a18d873f3302b3b2415aeafb108Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <config.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
a14613fce99dee3cad5bf842fd6be78f8e463582Brian Wellington#include <isc/mem.h>
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence#include <isc/task.h>
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence#include <isc/timer.h>
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence#include <isc/util.h>
279c6ec074be17dce62dd1b2c6ed7c2cc56a7b78David Lawrence
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <dns/acl.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/dispatch.h>
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson#include <dns/events.h>
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson#include <dns/log.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/message.h>
a30e7fc23415fd238d067a8a871607bca36068baMichael Graff#include <dns/rdata.h>
a30e7fc23415fd238d067a8a871607bca36068baMichael Graff#include <dns/rdatastruct.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#include <dns/request.h>
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley#include <dns/result.h>
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley#include <dns/tsig.h>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley#define REQUESTMGR_MAGIC 0x5271754dU /* RquM */
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley#define VALID_REQUESTMGR(mgr) ((mgr) != NULL && \
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (mgr)->magic == REQUESTMGR_MAGIC)
dc97fe4ed08488d314ab5bc8e99ed839542cf411David Lawrence
dc97fe4ed08488d314ab5bc8e99ed839542cf411David Lawrence#define REQUEST_MAGIC 0x52717521U /* Rqu! */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#define VALID_REQUEST(request) ((request) != NULL && \
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley (request)->magic == REQUEST_MAGIC)
8d4257cff01b3821abcb9a21f46c6c6a43bb1e72Bob Halley
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeintypedef ISC_LIST(dns_request_t) dns_requestlist_t;
50453ad879d0d93854de5a3385776bd799e8f35cBob Halley
50453ad879d0d93854de5a3385776bd799e8f35cBob Halley#define DNS_REQUEST_NLOCKS 7
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
7005cfed8cd3296d356883dcb414979f22e06b13Brian Wellingtonstruct dns_requestmgr {
7005cfed8cd3296d356883dcb414979f22e06b13Brian Wellington isc_int32_t magic;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_mutex_t lock;
6f7660093e70d3a7c80738b681ac0f5c1b661c00Mark Andrews isc_mem_t *mctx;
6f7660093e70d3a7c80738b681ac0f5c1b661c00Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein /* locked */
d8dcd6ad4617cc8d7df979bd62101fa9c4bac1bcBob Halley isc_int32_t eref;
d8dcd6ad4617cc8d7df979bd62101fa9c4bac1bcBob Halley isc_int32_t iref;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_timermgr_t *timermgr;
baf7c7e589f313f10b29d9119811fc4d36c2e4bcMark Andrews isc_socketmgr_t *socketmgr;
baf7c7e589f313f10b29d9119811fc4d36c2e4bcMark Andrews isc_taskmgr_t *taskmgr;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_dispatchmgr_t *dispatchmgr;
a30e7fc23415fd238d067a8a871607bca36068baMichael Graff dns_dispatch_t *dispatchv4;
a30e7fc23415fd238d067a8a871607bca36068baMichael Graff dns_dispatch_t *dispatchv6;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_boolean_t exiting;
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley isc_eventlist_t whenshutdown;
194b6a25192581bbc8ec731e32e8989042b202a4Michael Graff unsigned int hash;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_mutex_t locks[DNS_REQUEST_NLOCKS];
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews dns_requestlist_t requests;
6286983c506433d642b23e64845c50be30f2a7f6Mark Andrews};
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
8313838954d67250d0ed7edf67fba5da0790d1a7Michael Graffstruct dns_request {
8313838954d67250d0ed7edf67fba5da0790d1a7Michael Graff isc_int32_t magic;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int hash;
8313838954d67250d0ed7edf67fba5da0790d1a7Michael Graff isc_mem_t *mctx;
8313838954d67250d0ed7edf67fba5da0790d1a7Michael Graff isc_int32_t flags;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ISC_LINK(dns_request_t) link;
703e1c0bb66f3cd3d300358ca0c1fdf3cb5fb1c5Brian Wellington isc_buffer_t *query;
703e1c0bb66f3cd3d300358ca0c1fdf3cb5fb1c5Brian Wellington isc_buffer_t *answer;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_requestevent_t *event;
b15c543f7957fbb4284f0fc20b3278f2a411d272Mark Andrews dns_dispatch_t *dispatch;
b15c543f7957fbb4284f0fc20b3278f2a411d272Mark Andrews dns_dispentry_t *dispentry;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_timer_t *timer;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_requestmgr_t *requestmgr;
0eb2572d79822d02ea05448ce4e5f1759c73d171Michael Graff isc_buffer_t *tsig;
0eb2572d79822d02ea05448ce4e5f1759c73d171Michael Graff dns_tsigkey_t *tsigkey;
0eb2572d79822d02ea05448ce4e5f1759c73d171Michael Graff
0eb2572d79822d02ea05448ce4e5f1759c73d171Michael Graff};
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
4108eed5092156cf0407a97a9bd8ab7775164694Brian Wellington#define DNS_REQUEST_F_CONNECTING 0x0001
4108eed5092156cf0407a97a9bd8ab7775164694Brian Wellington#define DNS_REQUEST_F_SENDING 0x0002
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#define DNS_REQUEST_F_CANCELED 0x0004
3f123dcc2fe5d2cd08ca91b732741d86a4036906Brian Wellington#define DNS_REQUEST_F_TIMEDOUT 0x0008 /* cancelled due to a timeout */
3f123dcc2fe5d2cd08ca91b732741d86a4036906Brian Wellington#define DNS_REQUEST_F_TCP 0x0010 /* This request used TCP */
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein#define DNS_REQUEST_CANCELED(r) \
64b92523f9333ba053f4b2860335583be455b0b3Brian Wellington (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
64b92523f9333ba053f4b2860335583be455b0b3Brian Wellington#define DNS_REQUEST_CONNECTING(r) \
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence#define DNS_REQUEST_SENDING(r) \
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence#define DNS_REQUEST_TIMEDOUT(r) \
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence
876753d5ce1be48f3218fb4875fac501f8adfd6cDavid Lawrence
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein/***
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence *** Forward
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence ***/
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrencestatic void mgr_destroy(dns_requestmgr_t *requestmgr);
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrencestatic void mgr_shutdown(dns_requestmgr_t *requestmgr);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinstatic unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrencestatic void send_shutdown_events(dns_requestmgr_t *requestmgr);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrence
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinstatic isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein unsigned int options, isc_mem_t *mctx);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrencestatic void req_senddone(isc_task_t *task, isc_event_t *event);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrencestatic void req_response(isc_task_t *task, isc_event_t *event);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrencestatic void req_timeout(isc_task_t *task, isc_event_t *event);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeinstatic void req_connected(isc_task_t *task, isc_event_t *event);
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrencestatic void req_sendevent(dns_request_t *request, isc_result_t result);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsstatic void req_cancel(dns_request_t *request);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsstatic void req_destroy(dns_request_t *request);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsstatic void req_log(int level, const char *fmt, ...);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews/***
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews *** Public
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews ***/
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
49a2cf8f211213712d452287ae8e121cf59e3178David Lawrenceisc_result_t
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austeindns_requestmgr_create(isc_mem_t *mctx,
529ff4b4959fb157194f985394951108ff5286e4Brian Wellington isc_timermgr_t *timermgr,
a14613fce99dee3cad5bf842fd6be78f8e463582Brian Wellington isc_socketmgr_t *socketmgr,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isc_taskmgr_t *taskmgr,
489b76292622f5bc18bf1a18845f8166a73bd797Brian Wellington dns_dispatchmgr_t *dispatchmgr,
489b76292622f5bc18bf1a18845f8166a73bd797Brian Wellington dns_dispatch_t *dispatchv4,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_dispatch_t *dispatchv6,
bff8ac12a8c099257bdbf7d0c55d2d5b77591926Mark Andrews dns_requestmgr_t **requestmgrp)
bff8ac12a8c099257bdbf7d0c55d2d5b77591926Mark Andrews{
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein dns_requestmgr_t *requestmgr;
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson isc_socket_t *socket;
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson isc_result_t result;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein int i;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
cffc2e06f906dd048af4cc27d487deb157f5a082Mark Andrews
cffc2e06f906dd048af4cc27d487deb157f5a082Mark Andrews REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
cffc2e06f906dd048af4cc27d487deb157f5a082Mark Andrews REQUIRE(timermgr != NULL);
43fe2897fc80bbec2115310ca79d432a252f3ea4Mark Andrews REQUIRE(socketmgr != NULL);
43fe2897fc80bbec2115310ca79d432a252f3ea4Mark Andrews REQUIRE(taskmgr != NULL);
43fe2897fc80bbec2115310ca79d432a252f3ea4Mark Andrews REQUIRE(dispatchmgr != NULL);
70e854766f5304f43e94212dc38ebaefe214148cMark Andrews if (dispatchv4 != NULL) {
70e854766f5304f43e94212dc38ebaefe214148cMark Andrews socket = dns_dispatch_getsocket(dispatchv4);
70e854766f5304f43e94212dc38ebaefe214148cMark Andrews REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
43501e6570e9081d459fb5c1a81b73c2c53c5df0Mark Andrews }
43501e6570e9081d459fb5c1a81b73c2c53c5df0Mark Andrews if (dispatchv6 != NULL) {
43501e6570e9081d459fb5c1a81b73c2c53c5df0Mark Andrews socket = dns_dispatch_getsocket(dispatchv6);
43501e6570e9081d459fb5c1a81b73c2c53c5df0Mark Andrews REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
2b66a51a7d72e9cc07917fb583ad528b0539d2a3Mark Andrews }
2b66a51a7d72e9cc07917fb583ad528b0539d2a3Mark Andrews
2b66a51a7d72e9cc07917fb583ad528b0539d2a3Mark Andrews requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
8b56b8956fc1e6c70efacb4f71db28d0d1f0c577Mark Andrews if (requestmgr == NULL)
8b56b8956fc1e6c70efacb4f71db28d0d1f0c577Mark Andrews return (ISC_R_NOMEMORY);
8b56b8956fc1e6c70efacb4f71db28d0d1f0c577Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews result = isc_mutex_init(&requestmgr->lock);
64b92523f9333ba053f4b2860335583be455b0b3Brian Wellington if (result != ISC_R_SUCCESS) {
64b92523f9333ba053f4b2860335583be455b0b3Brian Wellington isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews return (result);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley }
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews result = isc_mutex_init(&requestmgr->locks[i]);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews if (result != ISC_R_SUCCESS) {
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews while (--i >= 0)
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews DESTROYLOCK(&requestmgr->locks[i]);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews DESTROYLOCK(&requestmgr->lock);
289ae548d52bc8f982d9823af64cafda7bd92232Mark Andrews isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews return (result);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->timermgr = timermgr;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->socketmgr = socketmgr;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->taskmgr = taskmgr;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt requestmgr->dispatchmgr = dispatchmgr;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt requestmgr->dispatchv4 = NULL;
0415ca35ada2cac6a86127eaca64f3a997aea121Evan Hunt if (dispatchv4 != NULL)
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->dispatchv6 = NULL;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews if (dispatchv6 != NULL)
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->mctx = NULL;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews isc_mem_attach(mctx, &requestmgr->mctx);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->eref = 1; /* implict attach */
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->iref = 0;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews ISC_LIST_INIT(requestmgr->whenshutdown);
23ac30603a7639bea1d331537634b079b046b122Mark Andrews ISC_LIST_INIT(requestmgr->requests);
23ac30603a7639bea1d331537634b079b046b122Mark Andrews requestmgr->exiting = ISC_FALSE;
23ac30603a7639bea1d331537634b079b046b122Mark Andrews requestmgr->hash = 0;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->magic = REQUESTMGR_MAGIC;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
c870001ae1bff0e38f622c4ed56872c7f1d2d336Mark Andrews
c870001ae1bff0e38f622c4ed56872c7f1d2d336Mark Andrews *requestmgrp = requestmgr;
c870001ae1bff0e38f622c4ed56872c7f1d2d336Mark Andrews return (ISC_R_SUCCESS);
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews}
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrews
186e7f37c9fc985a7a7264cc8170e48a25bed434Mark Andrewsvoid
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsdns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley isc_event_t **eventp)
5c00d1c90030a311d2700970fa7cffc8f828a48cBob Halley{
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews isc_task_t *clone;
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews isc_event_t *event;
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews REQUIRE(eventp != NULL);
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson event = *eventp;
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews *eventp = NULL;
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews LOCK(&requestmgr->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews if (requestmgr->exiting) {
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews /*
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews * We're already shutdown. Send the event.
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews */
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews event->ev_sender = requestmgr;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews isc_task_send(task, &event);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews } else {
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews clone = NULL;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews isc_task_attach(task, &clone);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews event->ev_sender = clone;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews }
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews UNLOCK(&requestmgr->lock);
dc2a0aa7aaa8b85398ae183c7274c0eeec5009afMark Andrews}
101a7960b7989a18d873f3302b3b2415aeafb108Mark Andrews
101a7960b7989a18d873f3302b3b2415aeafb108Mark Andrewsvoid
101a7960b7989a18d873f3302b3b2415aeafb108Mark Andrewsdns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
146484aced3e6c1b9cc88db5e75b8cbfd166f701Mark Andrews
146484aced3e6c1b9cc88db5e75b8cbfd166f701Mark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
146484aced3e6c1b9cc88db5e75b8cbfd166f701Mark Andrews
2b50e0d877db0d668f363d50914232f82ad8c454Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
2b50e0d877db0d668f363d50914232f82ad8c454Mark Andrews
2b50e0d877db0d668f363d50914232f82ad8c454Mark Andrews LOCK(&requestmgr->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews mgr_shutdown(requestmgr);
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington UNLOCK(&requestmgr->lock);
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellington}
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f8727bd90366af835f551da1b5e1fdfcd2d3d01fBrian Wellingtonstatic void
134ba0e08a0ae9a564a8d8628fc633377d3fc239Bob Halleymgr_shutdown(dns_requestmgr_t *requestmgr) {
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews dns_request_t *request;
203596d27c225ea195e4faad4f19388c6e96ac80Bob Halley
203596d27c225ea195e4faad4f19388c6e96ac80Bob Halley req_log(ISC_LOG_DEBUG(3), "mgr_shutdown: %p", requestmgr);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews /*
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews * Caller holds lock.
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews */
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson if (!requestmgr->exiting) {
fd837244be31850a764863688bce11df9ce972f4Andreas Gustafsson requestmgr->exiting = ISC_TRUE;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews for (request = ISC_LIST_HEAD(requestmgr->requests);
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley request != NULL;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley request = ISC_LIST_NEXT(request, link)) {
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews dns_request_cancel(request);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews if (requestmgr->iref == 0) {
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews INSIST(ISC_LIST_EMPTY(requestmgr->requests));
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews send_shutdown_events(requestmgr);
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews}
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsstatic void
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halleyrequestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
15bfd48fc5552ff1aae766021f42a250c001a098Michael Graff
e7fb847ed570dd8c1bcdacabb3d69bd81feb79aeMark Andrews /*
e7fb847ed570dd8c1bcdacabb3d69bd81feb79aeMark Andrews * Locked by caller.
e7fb847ed570dd8c1bcdacabb3d69bd81feb79aeMark Andrews */
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews REQUIRE(VALID_REQUESTMGR(source));
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews REQUIRE(targetp != NULL && *targetp == NULL);
4423c99613db1399dbb5c51e86ef0d351a1418c2Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews REQUIRE(!source->exiting);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
882350d11c90de9de6fc1cead25690c8114b0b95Michael Graff source->iref++;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews *targetp = source;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
15bfd48fc5552ff1aae766021f42a250c001a098Michael Graff req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews source, source->eref, source->iref);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews}
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsstatic void
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsrequestmgr_detach(dns_requestmgr_t **requestmgrp) {
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews dns_requestmgr_t *requestmgr;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews isc_boolean_t need_destroy = ISC_FALSE;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews REQUIRE(requestmgrp != NULL);
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews requestmgr = *requestmgrp;
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews REQUIRE(VALID_REQUESTMGR(requestmgr));
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews *requestmgrp = NULL;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews LOCK(&requestmgr->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews INSIST(requestmgr->iref > 0);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr->iref--;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews requestmgr, requestmgr->eref, requestmgr->iref);
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews if (requestmgr->iref == 0 && requestmgr->exiting) {
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
577ca1471960830304d1d2b9bd543fa469af51c1Mark Andrews send_shutdown_events(requestmgr);
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews if (requestmgr->eref == 0)
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews need_destroy = ISC_TRUE;
cae2cb086244dfb883739edbe79e34756079f70eMark Andrews }
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews UNLOCK(&requestmgr->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews if (need_destroy)
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews mgr_destroy(requestmgr);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews}
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrewsvoid
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrewsdns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews REQUIRE(VALID_REQUESTMGR(source));
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews REQUIRE(targetp != NULL && *targetp == NULL);
281bfa2a98f1d1721538086e1b550185559f1d8bMark Andrews REQUIRE(!source->exiting);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
7de2c6e6d51f38daeb2d346f3f21dc01ccece6daEvan Hunt LOCK(&source->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews source->eref++;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews *targetp = source;
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews UNLOCK(&source->lock);
f54d0c9c6e65de367d4ef08f51d22a2fb4c56208Mark Andrews
6e9efadbea9febb0494e713e54dfea6f7ef70383Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
6e9efadbea9febb0494e713e54dfea6f7ef70383Mark Andrews source, source->eref, source->iref);
6e9efadbea9febb0494e713e54dfea6f7ef70383Mark Andrews}
8486ce1efa5deded85415d21d5696e5a51c63357Mark Andrews
8486ce1efa5deded85415d21d5696e5a51c63357Mark Andrewsvoid
8486ce1efa5deded85415d21d5696e5a51c63357Mark Andrewsdns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
8486ce1efa5deded85415d21d5696e5a51c63357Mark Andrews dns_requestmgr_t *requestmgr;
isc_boolean_t need_destroy = ISC_FALSE;
REQUIRE(requestmgrp != NULL);
requestmgr = *requestmgrp;
REQUIRE(VALID_REQUESTMGR(requestmgr));
LOCK(&requestmgr->lock);
INSIST(requestmgr->eref > 0);
requestmgr->eref--;
req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
requestmgr, requestmgr->eref, requestmgr->iref);
if (requestmgr->eref == 0 && requestmgr->iref == 0) {
INSIST(requestmgr->exiting &&
ISC_LIST_HEAD(requestmgr->requests) == NULL);
need_destroy = ISC_TRUE;
}
UNLOCK(&requestmgr->lock);
if (need_destroy)
mgr_destroy(requestmgr);
*requestmgrp = NULL;
}
static void
send_shutdown_events(dns_requestmgr_t *requestmgr) {
isc_event_t *event, *next_event;
isc_task_t *etask;
req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
/*
* Caller must be holding the manager lock.
*/
for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
event != NULL;
event = next_event) {
next_event = ISC_LIST_NEXT(event, ev_link);
ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
etask = event->ev_sender;
event->ev_sender = requestmgr;
isc_task_sendanddetach(&etask, &event);
}
}
static void
mgr_destroy(dns_requestmgr_t *requestmgr) {
int i;
isc_mem_t *mctx;
req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
REQUIRE(requestmgr->eref == 0);
REQUIRE(requestmgr->iref == 0);
DESTROYLOCK(&requestmgr->lock);
for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
DESTROYLOCK(&requestmgr->locks[i]);
if (requestmgr->dispatchv4 != NULL)
dns_dispatch_detach(&requestmgr->dispatchv4);
if (requestmgr->dispatchv6 != NULL)
dns_dispatch_detach(&requestmgr->dispatchv6);
requestmgr->magic = 0;
mctx = requestmgr->mctx;
isc_mem_put(mctx, requestmgr, sizeof *requestmgr);
isc_mem_detach(&mctx);
}
static unsigned int
mgr_gethash(dns_requestmgr_t *requestmgr) {
req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
/*
* Locked by caller.
*/
requestmgr->hash++;
return(requestmgr->hash % DNS_REQUEST_NLOCKS);
}
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;
isc_result_t result;
req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
REQUIRE(VALID_REQUEST(request));
socket = dns_dispatch_getsocket(request->dispatch);
isc_buffer_usedregion(request->query, &r);
result = isc_socket_sendto(socket, &r, task, req_senddone,
request, address, NULL);
if (result == ISC_R_SUCCESS)
request->flags |= DNS_REQUEST_F_SENDING;
return (result);
}
isc_result_t
dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
unsigned int options, unsigned int timeout,
isc_task_t *task, isc_taskaction_t action, void *arg,
dns_request_t **requestp)
{
dns_request_t *request = NULL;
isc_task_t *tclone = NULL;
isc_socket_t *socket = NULL;
isc_result_t result;
isc_mem_t *mctx;
isc_sockaddr_t bind_any;
isc_sockaddr_t src;
isc_interval_t interval;
dns_messageid_t id;
isc_time_t expires;
unsigned int attrs;
isc_boolean_t tcp = ISC_FALSE;
isc_region_t r;
dns_acl_t *blackhole = NULL;
REQUIRE(VALID_REQUESTMGR(requestmgr));
REQUIRE(msgbuf != NULL);
REQUIRE(destaddr != NULL);
REQUIRE(task != NULL);
REQUIRE(action != NULL);
REQUIRE(requestp != NULL && *requestp == NULL);
REQUIRE(timeout > 0);
if (srcaddr != NULL)
REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
mctx = requestmgr->mctx;
req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
(void)dns_dispatchmgr_getblackhole(requestmgr->dispatchmgr,
&blackhole);
if (blackhole != NULL) {
isc_netaddr_t netaddr;
int match;
isc_boolean_t drop = ISC_FALSE;
isc_netaddr_fromsockaddr(&netaddr, destaddr);
if (dns_acl_match(&netaddr, NULL, blackhole,
NULL, &match, NULL) == ISC_R_SUCCESS &&
match > 0)
drop = ISC_TRUE;
dns_acl_detach(&blackhole);
if (drop) {
char netaddrstr[ISC_NETADDR_FORMATSIZE];
isc_netaddr_format(&netaddr, netaddrstr,
sizeof(netaddrstr));
req_log(ISC_LOG_DEBUG(10), "blackholed address %s",
netaddrstr);
return (DNS_R_BLACKHOLED);
}
}
request = isc_mem_get(mctx, sizeof(*request));
if (request == NULL) {
return (ISC_R_NOMEMORY);
}
/*
* Zero structure.
*/
request->magic = 0;
request->mctx = NULL;
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;
request->tsig = NULL;
request->tsigkey = NULL;
/*
* 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 *)
isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
action, arg, sizeof (dns_requestevent_t));
if (request->event == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
isc_task_attach(task, &tclone);
request->event->ev_sender = task;
request->event->request = request;
request->event->result = ISC_R_FAILURE;
isc_buffer_usedregion(msgbuf, &r);
if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
result = DNS_R_FORMERR;
goto cleanup;
}
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
tcp = ISC_TRUE;
if (tcp) {
result = isc_socket_create(requestmgr->socketmgr,
isc_sockaddr_pf(destaddr),
isc_sockettype_tcp, &socket);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (srcaddr == NULL) {
isc_sockaddr_anyofpf(&bind_any,
isc_sockaddr_pf(destaddr));
result = isc_socket_bind(socket, &bind_any);
} else {
src = *srcaddr;
isc_sockaddr_setport(&src, 0);
result = isc_socket_bind(socket, &src);
}
if (result != ISC_R_SUCCESS) {
isc_socket_detach(&socket);
goto cleanup;
}
attrs = 0;
attrs |= DNS_DISPATCHATTR_TCP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
if (isc_sockaddr_pf(destaddr) == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
socket, requestmgr->taskmgr,
4096, 2, 1, 1, 3, attrs,
&request->dispatch);
isc_socket_detach(&socket);
if (result != ISC_R_SUCCESS)
goto cleanup;
} else {
dns_dispatch_t *disp = NULL;
if (srcaddr == NULL) {
switch (isc_sockaddr_pf(destaddr)) {
case PF_INET:
disp = requestmgr->dispatchv4;
break;
case PF_INET6:
disp = requestmgr->dispatchv6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
if (disp == NULL) {
result = ISC_R_FAMILYNOSUPPORT;
goto cleanup;
}
dns_dispatch_attach(disp, &request->dispatch);
} else {
unsigned int attrs, attrmask;
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
switch (isc_sockaddr_pf(srcaddr)) {
case PF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case PF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP;
attrmask |= DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4;
attrmask |= DNS_DISPATCHATTR_IPV6;
result = dns_dispatch_getudp(requestmgr->dispatchmgr,
requestmgr->socketmgr,
requestmgr->taskmgr,
srcaddr, 4096,
1000, 32768, 16411, 16433,
attrs, attrmask,
&request->dispatch);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
}
socket = dns_dispatch_getsocket(request->dispatch);
INSIST(socket != NULL);
result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
req_response, request, &id,
&request->dispentry);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = isc_buffer_allocate(mctx, &request->query,
r.length + (tcp ? 2 : 0));
if (result != ISC_R_SUCCESS)
goto cleanup;
if (tcp)
isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
result = isc_buffer_copyregion(request->query, &r);
if (result != ISC_R_SUCCESS)
goto cleanup;
/* Add message ID. */
isc_buffer_usedregion(request->query, &r);
if (tcp)
isc_region_consume(&r, 2);
r.base[0] = (id>>8) & 0xff;
r.base[1] = id & 0xff;
isc_mem_attach(mctx, &request->mctx);
LOCK(&requestmgr->lock);
if (requestmgr->exiting) {
UNLOCK(&requestmgr->lock);
result = ISC_R_SHUTTINGDOWN;
goto cleanup;
}
requestmgr_attach(requestmgr, &request->requestmgr);
request->hash = mgr_gethash(requestmgr);
request->magic = REQUEST_MAGIC;
ISC_LIST_APPEND(requestmgr->requests, request, link);
UNLOCK(&requestmgr->lock);
isc_interval_set(&interval, timeout, 0);
result = isc_time_nowplusinterval(&expires, &interval);
if (result != ISC_R_SUCCESS)
goto unlink;
result = isc_timer_reset(request->timer, isc_timertype_once,
&expires, NULL, ISC_FALSE);
if (result != ISC_R_SUCCESS)
goto unlink;
if ((options & DNS_REQUESTOPT_TCP) != 0) {
result = isc_socket_connect(socket, destaddr, task,
req_connected, request);
if (result != ISC_R_SUCCESS)
goto unlink;
request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
} else {
result = req_send(request, task, destaddr);
if (result != ISC_R_SUCCESS)
goto unlink;
}
req_log(ISC_LOG_DEBUG(3), "dns_request_create: request %p", request);
*requestp = request;
return (ISC_R_SUCCESS);
unlink:
LOCK(&requestmgr->lock);
ISC_LIST_UNLINK(requestmgr->requests, request, link);
UNLOCK(&requestmgr->lock);
cleanup:
if (request->requestmgr != NULL)
requestmgr_detach(&request->requestmgr);
if (request->dispentry != NULL)
dns_dispatch_removeresponse(&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);
if (tclone != NULL)
isc_task_detach(&tclone);
if (request->mctx != NULL)
isc_mem_detach(&request->mctx);
isc_mem_put(mctx, request, sizeof *request);
req_log(ISC_LOG_DEBUG(3), "dns_request_create: failed %s",
dns_result_totext(result));
return (result);
}
isc_result_t
dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_sockaddr_t *address, unsigned int options,
dns_tsigkey_t *key,
unsigned int timeout, isc_task_t *task,
isc_taskaction_t action, void *arg,
dns_request_t **requestp)
{
return(dns_request_createvia(requestmgr, message, NULL, address,
options, key, timeout, task, action,
arg, requestp));
}
isc_result_t
dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
unsigned int options, dns_tsigkey_t *key,
unsigned int timeout, isc_task_t *task,
isc_taskaction_t action, void *arg,
dns_request_t **requestp)
{
dns_request_t *request = NULL;
isc_task_t *tclone = NULL;
isc_socket_t *socket = NULL;
isc_result_t result;
isc_mem_t *mctx;
isc_sockaddr_t bind_any;
isc_sockaddr_t src;
isc_interval_t interval;
dns_messageid_t id;
isc_time_t expires;
unsigned int attrs;
dns_acl_t *blackhole = NULL;
REQUIRE(VALID_REQUESTMGR(requestmgr));
REQUIRE(message != NULL);
REQUIRE(destaddr != NULL);
REQUIRE(task != NULL);
REQUIRE(action != NULL);
REQUIRE(requestp != NULL && *requestp == NULL);
REQUIRE(timeout > 0);
if (srcaddr != NULL)
REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
mctx = requestmgr->mctx;
req_log(ISC_LOG_DEBUG(3), "dns_request_create");
(void)dns_dispatchmgr_getblackhole(requestmgr->dispatchmgr,
&blackhole);
if (blackhole != NULL) {
isc_netaddr_t netaddr;
int match;
isc_boolean_t drop = ISC_FALSE;
isc_netaddr_fromsockaddr(&netaddr, destaddr);
if (dns_acl_match(&netaddr, NULL, blackhole,
NULL, &match, NULL) == ISC_R_SUCCESS &&
match > 0)
drop = ISC_TRUE;
dns_acl_detach(&blackhole);
if (drop) {
char netaddrstr[ISC_NETADDR_FORMATSIZE];
isc_netaddr_format(&netaddr, netaddrstr,
sizeof(netaddrstr));
req_log(ISC_LOG_DEBUG(10), "blackholed address %s",
netaddrstr);
return (DNS_R_BLACKHOLED);
}
}
request = isc_mem_get(mctx, sizeof(*request));
if (request == NULL) {
return (ISC_R_NOMEMORY);
}
/*
* Zero structure.
*/
request->magic = 0;
request->mctx = NULL;
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;
request->tsig = NULL;
request->tsigkey = NULL;
/*
* 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 *)
isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
action, arg, sizeof (dns_requestevent_t));
if (request->event == NULL) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
isc_task_attach(task, &tclone);
request->event->ev_sender = task;
request->event->request = request;
request->event->result = ISC_R_FAILURE;
if (key != NULL)
dns_tsigkey_attach(key, &request->tsigkey);
use_tcp:
if ((options & DNS_REQUESTOPT_TCP) != 0) {
result = isc_socket_create(requestmgr->socketmgr,
isc_sockaddr_pf(destaddr),
isc_sockettype_tcp, &socket);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (srcaddr == NULL) {
isc_sockaddr_anyofpf(&bind_any,
isc_sockaddr_pf(destaddr));
result = isc_socket_bind(socket, &bind_any);
} else {
src = *srcaddr;
isc_sockaddr_setport(&src, 0);
result = isc_socket_bind(socket, &src);
}
if (result != ISC_R_SUCCESS) {
isc_socket_detach(&socket);
goto cleanup;
}
attrs = 0;
attrs |= DNS_DISPATCHATTR_TCP;
attrs |= DNS_DISPATCHATTR_PRIVATE;
if (isc_sockaddr_pf(destaddr) == AF_INET)
attrs |= DNS_DISPATCHATTR_IPV4;
else
attrs |= DNS_DISPATCHATTR_IPV6;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
socket, requestmgr->taskmgr,
4096, 2, 1, 1, 3, attrs,
&request->dispatch);
isc_socket_detach(&socket);
if (result != ISC_R_SUCCESS)
goto cleanup;
} else {
dns_dispatch_t *disp = NULL;
if (srcaddr == NULL) {
switch (isc_sockaddr_pf(destaddr)) {
case PF_INET:
disp = requestmgr->dispatchv4;
break;
case PF_INET6:
disp = requestmgr->dispatchv6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
if (disp == NULL) {
result = ISC_R_FAMILYNOSUPPORT;
goto cleanup;
}
dns_dispatch_attach(disp, &request->dispatch);
} else {
unsigned int attrs, attrmask;
attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP;
switch (isc_sockaddr_pf(srcaddr)) {
case PF_INET:
attrs |= DNS_DISPATCHATTR_IPV4;
break;
case PF_INET6:
attrs |= DNS_DISPATCHATTR_IPV6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP;
attrmask |= DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4;
attrmask |= DNS_DISPATCHATTR_IPV6;
result = dns_dispatch_getudp(requestmgr->dispatchmgr,
requestmgr->socketmgr,
requestmgr->taskmgr,
srcaddr, 4096,
1000, 32768, 16411, 16433,
attrs, attrmask,
&request->dispatch);
if (result != ISC_R_SUCCESS)
goto cleanup;
}
}
socket = dns_dispatch_getsocket(request->dispatch);
INSIST(socket != NULL);
result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
req_response, request, &id,
&request->dispentry);
if (result != ISC_R_SUCCESS)
goto cleanup;
message->id = id;
dns_message_settsigkey(message, request->tsigkey);
result = req_render(message, &request->query, options, mctx);
if (result == DNS_R_USETCP &&
(options & DNS_REQUESTOPT_TCP) == 0) {
/*
* Try again using TCP.
*/
dns_message_renderreset(message);
dns_dispatch_removeresponse(&request->dispentry, NULL);
dns_dispatch_detach(&request->dispatch);
socket = NULL;
options |= DNS_REQUESTOPT_TCP;
goto use_tcp;
}
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_getquerytsig(message, mctx, &request->tsig);
if (result != ISC_R_SUCCESS)
goto cleanup;
isc_mem_attach(mctx, &request->mctx);
LOCK(&requestmgr->lock);
if (requestmgr->exiting) {
UNLOCK(&requestmgr->lock);
result = ISC_R_SHUTTINGDOWN;
goto cleanup;
}
requestmgr_attach(requestmgr, &request->requestmgr);
request->hash = mgr_gethash(requestmgr);
request->magic = REQUEST_MAGIC;
ISC_LIST_APPEND(requestmgr->requests, request, link);
UNLOCK(&requestmgr->lock);
isc_interval_set(&interval, timeout, 0);
result = isc_time_nowplusinterval(&expires, &interval);
if (result != ISC_R_SUCCESS)
goto unlink;
result = isc_timer_reset(request->timer, isc_timertype_once,
&expires, NULL, ISC_FALSE);
if (result != ISC_R_SUCCESS)
goto unlink;
if ((options & DNS_REQUESTOPT_TCP) != 0) {
result = isc_socket_connect(socket, destaddr, task,
req_connected, request);
if (result != ISC_R_SUCCESS)
goto unlink;
request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
} else {
result = req_send(request, task, destaddr);
if (result != ISC_R_SUCCESS)
goto unlink;
}
req_log(ISC_LOG_DEBUG(3), "dns_request_create: request %p", request);
*requestp = request;
return (ISC_R_SUCCESS);
unlink:
LOCK(&requestmgr->lock);
ISC_LIST_UNLINK(requestmgr->requests, request, link);
UNLOCK(&requestmgr->lock);
cleanup:
if (request->requestmgr != NULL)
requestmgr_detach(&request->requestmgr);
if (request->dispentry != NULL)
dns_dispatch_removeresponse(&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);
if (tclone != NULL)
isc_task_detach(&tclone);
if (request->mctx != NULL)
isc_mem_detach(&request->mctx);
isc_mem_put(mctx, request, sizeof *request);
req_log(ISC_LOG_DEBUG(3), "dns_request_create: failed %s",
dns_result_totext(result));
return (result);
}
static isc_result_t
req_render(dns_message_t *message, isc_buffer_t **bufferp,
unsigned int options, isc_mem_t *mctx)
{
isc_buffer_t *buf1 = NULL;
isc_buffer_t *buf2 = NULL;
isc_result_t result;
isc_region_t r;
isc_boolean_t tcp = ISC_FALSE;
REQUIRE(bufferp != NULL && *bufferp == NULL);
req_log(ISC_LOG_DEBUG(3), "request_render");
/*
* Create buffer able to hold largest possible message.
*/
result = isc_buffer_allocate(mctx, &buf1, 65535);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Render message.
*/
result = dns_message_renderbegin(message, buf1);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_message_renderend(message);
if (result != ISC_R_SUCCESS)
goto cleanup;
/*
* Copy rendered message to exact sized buffer.
*/
isc_buffer_usedregion(buf1, &r);
if ((options & DNS_REQUESTOPT_TCP) != 0) {
tcp = ISC_TRUE;
} else if (r.length > 512) {
result = DNS_R_USETCP;
goto cleanup;
}
result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
if (result != ISC_R_SUCCESS)
goto cleanup;
if (tcp)
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:
dns_message_renderreset(message);
if (buf1 != NULL)
isc_buffer_free(&buf1);
if (buf2 != NULL)
isc_buffer_free(&buf2);
return (result);
}
isc_result_t
dns_request_cancel(dns_request_t *request) {
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
REQUIRE(VALID_REQUEST(request));
LOCK(&request->requestmgr->locks[request->hash]);
if (!DNS_REQUEST_CANCELED(request)) {
req_cancel(request);
if (!DNS_REQUEST_CONNECTING(request) &&
!DNS_REQUEST_SENDING(request))
req_sendevent(request, ISC_R_CANCELED);
}
UNLOCK(&request->requestmgr->locks[request->hash]);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_request_getresponse(dns_request_t *request, dns_message_t *message,
unsigned int options)
{
isc_result_t result;
REQUIRE(VALID_REQUEST(request));
REQUIRE(request->answer != NULL);
req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
request);
dns_message_setquerytsig(message, request->tsig);
dns_message_settsigkey(message, request->tsigkey);
result = dns_message_parse(message, request->answer, options);
if (result != ISC_R_SUCCESS)
return (result);
if (request->tsigkey != NULL)
result = dns_tsig_verify(request->answer, message, NULL, NULL);
return (result);
}
isc_boolean_t
dns_request_usedtcp(dns_request_t *request) {
REQUIRE(VALID_REQUEST(request));
return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
}
void
dns_request_destroy(dns_request_t **requestp) {
dns_request_t *request;
REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
request = *requestp;
req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
LOCK(&request->requestmgr->locks[request->hash]);
LOCK(&request->requestmgr->lock);
ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
UNLOCK(&request->requestmgr->lock);
INSIST(!DNS_REQUEST_CONNECTING(request));
INSIST(!DNS_REQUEST_SENDING(request));
UNLOCK(&request->requestmgr->locks[request->hash]);
req_destroy(request);
*requestp = NULL;
}
/***
*** Private: request.
***/
static void
req_connected(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
isc_result_t result;
dns_request_t *request = event->ev_arg;
REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
REQUIRE(VALID_REQUEST(request));
REQUIRE(DNS_REQUEST_CONNECTING(request));
req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
LOCK(&request->requestmgr->locks[request->hash]);
request->flags &= ~DNS_REQUEST_F_CONNECTING;
if (DNS_REQUEST_CANCELED(request)) {
/*
* Send delayed event.
*/
if (DNS_REQUEST_TIMEDOUT(request))
req_sendevent(request, ISC_R_TIMEDOUT);
else
req_sendevent(request, ISC_R_CANCELED);
} else {
dns_dispatch_starttcp(request->dispatch);
result = sevent->result;
if (result == ISC_R_SUCCESS)
result = req_send(request, task, NULL);
if (sevent->result != ISC_R_SUCCESS) {
req_cancel(request);
req_sendevent(request, ISC_R_CANCELED);
}
}
UNLOCK(&request->requestmgr->locks[request->hash]);
isc_event_free(&event);
}
static void
req_senddone(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
dns_request_t *request = event->ev_arg;
REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
REQUIRE(VALID_REQUEST(request));
REQUIRE(DNS_REQUEST_SENDING(request));
req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
UNUSED(task);
LOCK(&request->requestmgr->locks[request->hash]);
request->flags &= ~DNS_REQUEST_F_SENDING;
if (DNS_REQUEST_CANCELED(request)) {
/*
* Send delayed event.
*/
if (DNS_REQUEST_TIMEDOUT(request))
req_sendevent(request, ISC_R_TIMEDOUT);
else
req_sendevent(request, ISC_R_CANCELED);
} else if (sevent->result != ISC_R_SUCCESS) {
req_cancel(request);
req_sendevent(request, ISC_R_CANCELED);
}
UNLOCK(&request->requestmgr->locks[request->hash]);
isc_event_free(&event);
}
static void
req_response(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
dns_request_t *request = event->ev_arg;
dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
isc_region_t r;
REQUIRE(VALID_REQUEST(request));
REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
UNUSED(task);
req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
dns_result_totext(devent->result));
LOCK(&request->requestmgr->locks[request->hash]);
result = devent->result;
if (result != ISC_R_SUCCESS)
goto done;
/*
* Copy buffer to request.
*/
isc_buffer_usedregion(&devent->buffer, &r);
result = isc_buffer_allocate(request->mctx, &request->answer,
r.length);
if (result != ISC_R_SUCCESS)
goto done;
result = isc_buffer_copyregion(request->answer, &r);
if (result != ISC_R_SUCCESS)
isc_buffer_free(&request->answer);
done:
/*
* Cleanup.
*/
dns_dispatch_removeresponse(&request->dispentry, &devent);
req_cancel(request);
/*
* Send completion event.
*/
req_sendevent(request, result);
UNLOCK(&request->requestmgr->locks[request->hash]);
}
static void
req_timeout(isc_task_t *task, isc_event_t *event) {
dns_request_t *request = event->ev_arg;
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
UNUSED(task);
LOCK(&request->requestmgr->locks[request->hash]);
request->flags |= DNS_REQUEST_F_TIMEDOUT;
req_cancel(request);
if (!DNS_REQUEST_CONNECTING(request) &&
!DNS_REQUEST_SENDING(request))
req_sendevent(request, ISC_R_TIMEDOUT);
UNLOCK(&request->requestmgr->locks[request->hash]);
isc_event_free(&event);
}
static void
req_sendevent(dns_request_t *request, isc_result_t result) {
isc_task_t *task;
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
/*
* Lock held by caller.
*/
task = request->event->ev_sender;
request->event->ev_sender = request;
request->event->result = result;
isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
}
static void
req_destroy(dns_request_t *request) {
isc_mem_t *mctx;
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
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->dispentry, NULL);
if (request->dispatch != NULL)
dns_dispatch_detach(&request->dispatch);
if (request->timer != NULL)
isc_timer_detach(&request->timer);
if (request->tsig != NULL)
isc_buffer_free(&request->tsig);
if (request->tsigkey != NULL)
dns_tsigkey_detach(&request->tsigkey);
requestmgr_detach(&request->requestmgr);
mctx = request->mctx;
isc_mem_put(mctx, request, sizeof(*request));
isc_mem_detach(&mctx);
}
static void
req_cancel(dns_request_t *request) {
isc_socket_t *socket;
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
/*
* Lock held by caller.
*/
request->flags |= DNS_REQUEST_F_CANCELED;
if (request->timer != NULL)
isc_timer_detach(&request->timer);
if (request->dispentry != NULL)
dns_dispatch_removeresponse(&request->dispentry, NULL);
if (DNS_REQUEST_CONNECTING(request)) {
socket = dns_dispatch_getsocket(request->dispatch);
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
}
if (DNS_REQUEST_SENDING(request)) {
socket = dns_dispatch_getsocket(request->dispatch);
isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
}
dns_dispatch_detach(&request->dispatch);
}
static void
req_log(int level, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_REQUEST, level, fmt, ap);
va_end(ap);
}