0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000-2002, 2004-2016 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewstypedef ISC_LIST(dns_request_t) dns_requestlist_t;
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews /* locked */
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson isc_boolean_t canceling; /* ctlevent outstanding */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
8068ceb2a9cc56d18016c3cd94a09e4bb0bc7b0dAndreas Gustafsson synchronously canceled */
bdfaef63f576f810fab27f64395faccf2fcd9434Francis Dupont#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void mgr_destroy(dns_requestmgr_t *requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsstatic void mgr_shutdown(dns_requestmgr_t *requestmgr);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrewsstatic unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsstatic void send_shutdown_events(dns_requestmgr_t *requestmgr);
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrewsstatic isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
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);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉static isc_socket_t * req_getsocket(dns_request_t *request);
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_destroy(dns_request_t *request);
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafssonstatic void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssonstatic void do_cancel(isc_task_t *task, isc_event_t *event);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 dispattr = dns_dispatch_getattributes(dispatchv4);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 dispattr = dns_dispatch_getattributes(dispatchv6);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews result = isc_mutex_init(&requestmgr->locks[i]);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews while (--i >= 0)
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington * We're already shutdown. Send the event.
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Caller holds lock.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews for (request = ISC_LIST_HEAD(requestmgr->requests);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsrequestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * Locked by caller.
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington REQUIRE(targetp != NULL && *targetp == NULL);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrewsrequestmgr_detach(dns_requestmgr_t **requestmgrp) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
8b61d2012063306528286680bd9f086fa868d86eMark Andrews requestmgr, requestmgr->eref, requestmgr->iref);
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews if (requestmgr->iref == 0 && requestmgr->exiting) {
4be19dcd14cea678511f1d1b269ab89273e987eeMark Andrews INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington REQUIRE(targetp != NULL && *targetp == NULL);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
8b61d2012063306528286680bd9f086fa868d86eMark Andrews requestmgr, requestmgr->eref, requestmgr->iref);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews if (requestmgr->eref == 0 && requestmgr->iref == 0) {
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewssend_shutdown_events(dns_requestmgr_t *requestmgr) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews * Caller must be holding the manager lock.
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrewsstatic unsigned int
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * Locked by caller.
668eb43f1f24c887b6972f6a1610b4b38b281080Brian Wellington return (requestmgr->hash % DNS_REQUEST_NLOCKS);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * We could connect the socket when we are using an exclusive dispatch
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * as we do in resolver.c, but we prefer implementation simplicity
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 * at this moment.
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews sendevent = isc_socket_socketevent(request->mctx, sock,
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews result = isc_socket_sendto2(sock, &r, task, address, NULL,
307d2084502eddc7ce921e5ce439aec3531d90e0Tatuya JINMEI 神明達哉new_request(isc_mem_t *mctx, dns_request_t **requestp)
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington request = isc_mem_get(mctx, sizeof(*request));
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington * Zero structure.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsisblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
97f26b88f62b10a9c26a91ebe8387d2e498c2d00Andreas Gustafsson blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
ff62d4458acda2110a3763ec576a4f728450662cEvan Huntcreate_tcp_dispatch(isc_boolean_t newtcp, isc_boolean_t share,
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews isc_boolean_t *connected, dns_dispatch_t **dispatchp)
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt result = dns_dispatch_gettcp2(requestmgr->dispatchmgr,
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt isc_sockaddr_format(destaddr, peer, sizeof(peer));
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt "connection to %s",
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt } else if (!newtcp) {
ffeaac1d826b541af39d7b20b9b68ff19ff01832Mark Andrews result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr,
ffeaac1d826b541af39d7b20b9b68ff19ff01832Mark Andrews isc_sockaddr_format(destaddr, peer, sizeof(peer));
ffeaac1d826b541af39d7b20b9b68ff19ff01832Mark Andrews req_log(ISC_LOG_DEBUG(1), "attached to existing TCP "
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = isc_socket_create(requestmgr->socketmgr,
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews result = dns_dispatch_createtcp2(requestmgr->dispatchmgr,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrewsfind_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews return (dns_dispatch_getudp(requestmgr->dispatchmgr,
ff62d4458acda2110a3763ec576a4f728450662cEvan Huntget_dispatch(isc_boolean_t tcp, isc_boolean_t newtcp, isc_boolean_t share,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt result = create_tcp_dispatch(newtcp, share, requestmgr,
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = find_udp_dispatch(requestmgr, srcaddr,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrewsset_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews result = isc_time_nowplusinterval(&expires, &interval);
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews result = isc_timer_reset(timer, timertype, &expires,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrewsdns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews isc_task_t *task, isc_taskaction_t action, void *arg,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return(dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrewsdns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graffdns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff unsigned int udptimeout, unsigned int udpretries,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff isc_task_t *task, isc_taskaction_t action, void *arg,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews REQUIRE(requestp != NULL && *requestp == NULL);
6ef15459b8fd3fc8b5672da4ad72c19a755dbe45Mark Andrews REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (isblackholed(requestmgr->dispatchmgr, destaddr))
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews * Create timer now. We will set it below once.
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson action, arg, sizeof(dns_requestevent_t));
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt result = get_dispatch(tcp, newtcp, share, requestmgr,
ffeaac1d826b541af39d7b20b9b68ff19ff01832Mark Andrews result = dns_dispatch_addresponse3(request->dispatch, dispopt,
ffeaac1d826b541af39d7b20b9b68ff19ff01832Mark Andrews if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) {
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews result = isc_buffer_allocate(mctx, &request->query,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews result = isc_buffer_copyregion(request->query, &r);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews /* Add message ID. */
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews requestmgr_attach(requestmgr, &request->requestmgr);
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews ISC_LIST_APPEND(requestmgr->requests, request, link);
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews result = isc_socket_connect(sock, destaddr, task,
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews result = req_send(request, task, connected ? NULL : destaddr);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
056141f2878d1046306ef0ba035263a00de57f98Mark Andrews ISC_LIST_UNLINK(requestmgr->requests, request, link);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrewsdns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_request_createvia4(requestmgr, message, NULL, address,
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrewsdns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
04c22ceaf2d3812eaab69d79958d0e0d62048cd2Mark Andrews isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return(dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrewsdns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff unsigned int timeout, unsigned int udptimeout,
cf70df7d0e24401a358f0b9c1a616ad0e8c783a6Mark Andrews isc_task_t *task, isc_taskaction_t action, void *arg,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graffdns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff unsigned int timeout, unsigned int udptimeout,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
67adc03ef81fb610f8df093b17f55275ee816754Evan Huntdns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
1e9f7a42bcfdfaa0ad314bed46e6c1297cdd0348Tinderbox User unsigned int udptimeout, unsigned int udpretries,
67adc03ef81fb610f8df093b17f55275ee816754Evan Hunt isc_task_t *task, isc_taskaction_t action, void *arg,
b54630c4518a1a173fee3478f4bf51dff450b6dcMark Andrews REQUIRE(requestp != NULL && *requestp == NULL);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
ffff5d67926821d3db8df63bdd84a9cb1ce56739Evan Hunt isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr))
7c2dce3c4d2c863ff268576f13c4ddd6f29d67edMark Andrews if (isblackholed(requestmgr->dispatchmgr, destaddr))
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Create timer now. We will set it below once.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson action, arg, sizeof(dns_requestevent_t));
c27767a7b946f4c6f08d33129691e2d6339e8350Brian Wellington dns_tsigkey_attach(key, &request->tsigkey);
dcc7ea97174501f0409c0c919b3ca04083e4e1b8Andreas Gustafsson tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
ff62d4458acda2110a3763ec576a4f728450662cEvan Hunt share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = dns_message_settsigkey(message, request->tsigkey);
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews result = req_render(message, &request->query, options, mctx);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Try again using TCP.
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff dns_dispatch_removeresponse(&request->dispentry, NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_getquerytsig(message, mctx, &request->tsig);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews requestmgr_attach(requestmgr, &request->requestmgr);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews ISC_LIST_APPEND(requestmgr->requests, request, link);
e903df2f012869e36251e9a76b13a9aa228fb1acMichael Graff result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews result = isc_socket_connect(sock, destaddr, task,
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
74717eef53ba5d6aefc80eb262bbb090ff4bb3b5Mark Andrews result = req_send(request, task, connected ? NULL : destaddr);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews ISC_LIST_UNLINK(requestmgr->requests, request, link);
dac1e1dd18b62be8cc3bec1a3656968b7b8633e6Brian Wellington req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrewsreq_render(dns_message_t *message, isc_buffer_t **bufferp,
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Create buffer able to hold largest possible message.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(mctx, &buf1, 65535);
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington result = dns_compress_init(&cctx, -1, mctx);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Render message.
e43b9a20054cdda6946ab758e1c2005f2b25641aBrian Wellington result = dns_message_renderbegin(message, &cctx, buf1);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Copy rendered message to exact sized buffer.
559bb1016f1b00a3661cb2790dc837a977057b86Mark Andrews result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews * Cleanup and return.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * If this request is no longer waiting for events,
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * send the completion event. This will ultimately
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * cause the request to be destroyed.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * 'request' is locked by the caller.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssonsend_if_done(dns_request_t *request, isc_result_t result) {
936036e82337c5aba40e735e5b46f9112869772fMark Andrews if (request->event != NULL && !request->canceling)
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * Handle the control event.
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafssondo_cancel(isc_task_t *task, isc_event_t *event) {
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson LOCK(&request->requestmgr->locks[request->hash]);
2cf81a3d8a8a12e81a762a0bc3d46e0b117733bfAutomatic Updater UNLOCK(&request->requestmgr->locks[request->hash]);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews LOCK(&request->requestmgr->locks[request->hash]);
8f17525ebc8ab06446b613f56972dcf063548141Andreas Gustafsson if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson isc_task_send(request->event->ev_sender, &ev);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
59abb512d344bfa09012cc11b7d814966f035da4Mark Andrewsdns_request_getresponse(dns_request_t *request, dns_message_t *message,
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = dns_message_setquerytsig(message, request->tsig);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson result = dns_message_settsigkey(message, request->tsigkey);
6850cdd4497424c9d42ade487edfde9fb9a47de9Brian Wellington result = dns_message_parse(message, request->answer, options);
2483a850e8b82230331defb0e22c67f6b46cfb38Brian Wellington result = dns_tsig_verify(request->answer, message, NULL, NULL);
7ed73313b1c129c7134d7d33beb82c85bd6d1df4Mark Andrews return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews LOCK(&request->requestmgr->locks[request->hash]);
9cb39bbe40998ee14df86609da806441b9e144ceAndreas Gustafsson ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson INSIST(!DNS_REQUEST_CONNECTING(request));
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * These should have been cleaned up by req_cancel() before
8126e45e8cc3fd54517c034dd30a42928f5206e3Andreas Gustafsson * the completion event was sent.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews *** Private: request.
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 dispattr = dns_dispatch_getattributes(request->dispatch);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews sock = dns_dispatch_getentrysocket(request->dispentry);
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews sock = dns_dispatch_getsocket(request->dispatch);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_connected(isc_task_t *task, isc_event_t *event) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2c12768b4306035c208afc92bace4f3501f051f7Michael Sawyer REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
f53848e17123569387b279578f0100dca5407da5Mark Andrews LOCK(&request->requestmgr->locks[request->hash]);
0ad8ee89c532951a55b7de25317eeca2c3b2ed63Andreas Gustafsson * Send delayed event.
f53848e17123569387b279578f0100dca5407da5Mark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_senddone(isc_task_t *task, isc_event_t *event) {
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews LOCK(&request->requestmgr->locks[request->hash]);
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews * Send delayed event.
046a9aca49bdc25bd57d75fd0dd34c021722f095Mark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_response(isc_task_t *task, isc_event_t *event) {
34ee961fa2f0f5f2ee3cff40fdb4d7d7b48b7728Mark Andrews dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews LOCK(&request->requestmgr->locks[request->hash]);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Copy buffer to request.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(request->mctx, &request->answer,
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews result = isc_buffer_copyregion(request->answer, &r);
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff dns_dispatch_removeresponse(&request->dispentry, &devent);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews * Send completion event.
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_timeout(isc_task_t *task, isc_event_t *event) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews LOCK(&request->requestmgr->locks[request->hash]);
897f762e3caf052688d4ec7b725746cfef09b058Andreas Gustafsson result = req_send(request, task, &request->destaddr);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews UNLOCK(&request->requestmgr->locks[request->hash]);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrewsreq_sendevent(dns_request_t *request, isc_result_t result) {
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
440164d3e36353a4b9801fcc05fe66b6cf1fb8ceMark Andrews * Lock held by caller.
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
78da321b437bbb690ef570ccf17dcc8583a5a4a0Mark Andrews isc_event_free((isc_event_t **)&request->event);
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff dns_dispatch_removeresponse(&request->dispentry, NULL);
8068ceb2a9cc56d18016c3cd94a09e4bb0bc7b0dAndreas Gustafsson * Stop the current request. Must be called from the request's task.
8b61d2012063306528286680bd9f086fa868d86eMark Andrews req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
a5c30de2601a1d130a15a78cf3dc7610a02b2d85Mark Andrews * Lock held by caller.
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 dispattr = dns_dispatch_getattributes(request->dispatch);
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
386d3a99c190bad55edf44d076e6bd087e230ab8Tatuya JINMEI 神明達哉 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews sock = dns_dispatch_getsocket(request->dispatch);
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews if (DNS_REQUEST_CONNECTING(request) && sock != NULL)
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT);
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews if (DNS_REQUEST_SENDING(request) && sock != NULL)
af669cb4fd7ecfb67ed145b176e5e764b249573bMark Andrews isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
46993e1d9d18410a5852b7d990338b70b158855cMichael Graff dns_dispatch_removeresponse(&request->dispentry, NULL);