4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: request.c,v 1.85 2009/09/01 00:22:26 jinmei Exp */
26 #include <isc/magic.h>
29 #include <isc/timer.h>
33 #include <dns/compress.h>
34 #include <dns/dispatch.h>
35 #include <dns/events.h>
37 #include <dns/message.h>
38 #include <dns/rdata.h>
39 #include <dns/rdatastruct.h>
40 #include <dns/request.h>
41 #include <dns/result.h>
44 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
45 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
47 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
48 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
50 typedef ISC_LIST(dns_request_t
) dns_requestlist_t
;
52 #define DNS_REQUEST_NLOCKS 7
54 struct dns_requestmgr
{
62 isc_timermgr_t
*timermgr
;
63 isc_socketmgr_t
*socketmgr
;
64 isc_taskmgr_t
*taskmgr
;
65 dns_dispatchmgr_t
*dispatchmgr
;
66 dns_dispatch_t
*dispatchv4
;
67 dns_dispatch_t
*dispatchv6
;
68 isc_boolean_t exiting
;
69 isc_eventlist_t whenshutdown
;
71 isc_mutex_t locks
[DNS_REQUEST_NLOCKS
];
72 dns_requestlist_t requests
;
80 ISC_LINK(dns_request_t
) link
;
83 dns_requestevent_t
*event
;
84 dns_dispatch_t
*dispatch
;
85 dns_dispentry_t
*dispentry
;
87 dns_requestmgr_t
*requestmgr
;
89 dns_tsigkey_t
*tsigkey
;
91 isc_boolean_t canceling
; /* ctlevent outstanding */
92 isc_sockaddr_t destaddr
;
93 unsigned int udpcount
;
96 #define DNS_REQUEST_F_CONNECTING 0x0001
97 #define DNS_REQUEST_F_SENDING 0x0002
98 #define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
99 synchronously canceled */
100 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
101 #define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
102 #define DNS_REQUEST_CANCELED(r) \
103 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
104 #define DNS_REQUEST_CONNECTING(r) \
105 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
106 #define DNS_REQUEST_SENDING(r) \
107 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
108 #define DNS_REQUEST_TIMEDOUT(r) \
109 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
116 static void mgr_destroy(dns_requestmgr_t
*requestmgr
);
117 static void mgr_shutdown(dns_requestmgr_t
*requestmgr
);
118 static unsigned int mgr_gethash(dns_requestmgr_t
*requestmgr
);
119 static void send_shutdown_events(dns_requestmgr_t
*requestmgr
);
121 static isc_result_t
req_render(dns_message_t
*message
, isc_buffer_t
**buffer
,
122 unsigned int options
, isc_mem_t
*mctx
);
123 static void req_senddone(isc_task_t
*task
, isc_event_t
*event
);
124 static void req_response(isc_task_t
*task
, isc_event_t
*event
);
125 static void req_timeout(isc_task_t
*task
, isc_event_t
*event
);
126 static isc_socket_t
* req_getsocket(dns_request_t
*request
);
127 static void req_connected(isc_task_t
*task
, isc_event_t
*event
);
128 static void req_sendevent(dns_request_t
*request
, isc_result_t result
);
129 static void req_cancel(dns_request_t
*request
);
130 static void req_destroy(dns_request_t
*request
);
131 static void req_log(int level
, const char *fmt
, ...) ISC_FORMAT_PRINTF(2, 3);
132 static void do_cancel(isc_task_t
*task
, isc_event_t
*event
);
139 dns_requestmgr_create(isc_mem_t
*mctx
,
140 isc_timermgr_t
*timermgr
,
141 isc_socketmgr_t
*socketmgr
,
142 isc_taskmgr_t
*taskmgr
,
143 dns_dispatchmgr_t
*dispatchmgr
,
144 dns_dispatch_t
*dispatchv4
,
145 dns_dispatch_t
*dispatchv6
,
146 dns_requestmgr_t
**requestmgrp
)
148 dns_requestmgr_t
*requestmgr
;
149 isc_socket_t
*socket
;
152 unsigned int dispattr
;
154 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
156 REQUIRE(requestmgrp
!= NULL
&& *requestmgrp
== NULL
);
157 REQUIRE(timermgr
!= NULL
);
158 REQUIRE(socketmgr
!= NULL
);
159 REQUIRE(taskmgr
!= NULL
);
160 REQUIRE(dispatchmgr
!= NULL
);
162 if (dispatchv4
!= NULL
) {
163 dispattr
= dns_dispatch_getattributes(dispatchv4
);
164 REQUIRE((dispattr
& DNS_DISPATCHATTR_UDP
) != 0);
166 if (dispatchv6
!= NULL
) {
167 dispattr
= dns_dispatch_getattributes(dispatchv6
);
168 REQUIRE((dispattr
& DNS_DISPATCHATTR_UDP
) != 0);
171 requestmgr
= isc_mem_get(mctx
, sizeof(*requestmgr
));
172 if (requestmgr
== NULL
)
173 return (ISC_R_NOMEMORY
);
175 result
= isc_mutex_init(&requestmgr
->lock
);
176 if (result
!= ISC_R_SUCCESS
) {
177 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
180 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++) {
181 result
= isc_mutex_init(&requestmgr
->locks
[i
]);
182 if (result
!= ISC_R_SUCCESS
) {
184 DESTROYLOCK(&requestmgr
->locks
[i
]);
185 DESTROYLOCK(&requestmgr
->lock
);
186 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
190 requestmgr
->timermgr
= timermgr
;
191 requestmgr
->socketmgr
= socketmgr
;
192 requestmgr
->taskmgr
= taskmgr
;
193 requestmgr
->dispatchmgr
= dispatchmgr
;
194 requestmgr
->dispatchv4
= NULL
;
195 if (dispatchv4
!= NULL
)
196 dns_dispatch_attach(dispatchv4
, &requestmgr
->dispatchv4
);
197 requestmgr
->dispatchv6
= NULL
;
198 if (dispatchv6
!= NULL
)
199 dns_dispatch_attach(dispatchv6
, &requestmgr
->dispatchv6
);
200 requestmgr
->mctx
= NULL
;
201 isc_mem_attach(mctx
, &requestmgr
->mctx
);
202 requestmgr
->eref
= 1; /* implicit attach */
203 requestmgr
->iref
= 0;
204 ISC_LIST_INIT(requestmgr
->whenshutdown
);
205 ISC_LIST_INIT(requestmgr
->requests
);
206 requestmgr
->exiting
= ISC_FALSE
;
207 requestmgr
->hash
= 0;
208 requestmgr
->magic
= REQUESTMGR_MAGIC
;
210 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr
);
212 *requestmgrp
= requestmgr
;
213 return (ISC_R_SUCCESS
);
217 dns_requestmgr_whenshutdown(dns_requestmgr_t
*requestmgr
, isc_task_t
*task
,
218 isc_event_t
**eventp
)
223 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
225 REQUIRE(VALID_REQUESTMGR(requestmgr
));
226 REQUIRE(eventp
!= NULL
);
231 LOCK(&requestmgr
->lock
);
233 if (requestmgr
->exiting
) {
235 * We're already shutdown. Send the event.
237 event
->ev_sender
= requestmgr
;
238 isc_task_send(task
, &event
);
241 isc_task_attach(task
, &clone
);
242 event
->ev_sender
= clone
;
243 ISC_LIST_APPEND(requestmgr
->whenshutdown
, event
, ev_link
);
245 UNLOCK(&requestmgr
->lock
);
249 dns_requestmgr_shutdown(dns_requestmgr_t
*requestmgr
) {
251 REQUIRE(VALID_REQUESTMGR(requestmgr
));
253 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr
);
255 LOCK(&requestmgr
->lock
);
256 mgr_shutdown(requestmgr
);
257 UNLOCK(&requestmgr
->lock
);
261 mgr_shutdown(dns_requestmgr_t
*requestmgr
) {
262 dns_request_t
*request
;
267 if (!requestmgr
->exiting
) {
268 requestmgr
->exiting
= ISC_TRUE
;
269 for (request
= ISC_LIST_HEAD(requestmgr
->requests
);
271 request
= ISC_LIST_NEXT(request
, link
)) {
272 dns_request_cancel(request
);
274 if (requestmgr
->iref
== 0) {
275 INSIST(ISC_LIST_EMPTY(requestmgr
->requests
));
276 send_shutdown_events(requestmgr
);
282 requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
288 REQUIRE(VALID_REQUESTMGR(source
));
289 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
291 REQUIRE(!source
->exiting
);
296 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
297 source
, source
->eref
, source
->iref
);
301 requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
302 dns_requestmgr_t
*requestmgr
;
303 isc_boolean_t need_destroy
= ISC_FALSE
;
305 REQUIRE(requestmgrp
!= NULL
);
306 requestmgr
= *requestmgrp
;
307 REQUIRE(VALID_REQUESTMGR(requestmgr
));
310 LOCK(&requestmgr
->lock
);
311 INSIST(requestmgr
->iref
> 0);
314 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
315 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
317 if (requestmgr
->iref
== 0 && requestmgr
->exiting
) {
318 INSIST(ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
319 send_shutdown_events(requestmgr
);
320 if (requestmgr
->eref
== 0)
321 need_destroy
= ISC_TRUE
;
323 UNLOCK(&requestmgr
->lock
);
326 mgr_destroy(requestmgr
);
330 dns_requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
332 REQUIRE(VALID_REQUESTMGR(source
));
333 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
334 REQUIRE(!source
->exiting
);
339 UNLOCK(&source
->lock
);
341 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
342 source
, source
->eref
, source
->iref
);
346 dns_requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
347 dns_requestmgr_t
*requestmgr
;
348 isc_boolean_t need_destroy
= ISC_FALSE
;
350 REQUIRE(requestmgrp
!= NULL
);
351 requestmgr
= *requestmgrp
;
352 REQUIRE(VALID_REQUESTMGR(requestmgr
));
354 LOCK(&requestmgr
->lock
);
355 INSIST(requestmgr
->eref
> 0);
358 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
359 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
361 if (requestmgr
->eref
== 0 && requestmgr
->iref
== 0) {
362 INSIST(requestmgr
->exiting
&&
363 ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
364 need_destroy
= ISC_TRUE
;
366 UNLOCK(&requestmgr
->lock
);
369 mgr_destroy(requestmgr
);
375 send_shutdown_events(dns_requestmgr_t
*requestmgr
) {
376 isc_event_t
*event
, *next_event
;
379 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr
);
382 * Caller must be holding the manager lock.
384 for (event
= ISC_LIST_HEAD(requestmgr
->whenshutdown
);
386 event
= next_event
) {
387 next_event
= ISC_LIST_NEXT(event
, ev_link
);
388 ISC_LIST_UNLINK(requestmgr
->whenshutdown
, event
, ev_link
);
389 etask
= event
->ev_sender
;
390 event
->ev_sender
= requestmgr
;
391 isc_task_sendanddetach(&etask
, &event
);
396 mgr_destroy(dns_requestmgr_t
*requestmgr
) {
400 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
402 REQUIRE(requestmgr
->eref
== 0);
403 REQUIRE(requestmgr
->iref
== 0);
405 DESTROYLOCK(&requestmgr
->lock
);
406 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++)
407 DESTROYLOCK(&requestmgr
->locks
[i
]);
408 if (requestmgr
->dispatchv4
!= NULL
)
409 dns_dispatch_detach(&requestmgr
->dispatchv4
);
410 if (requestmgr
->dispatchv6
!= NULL
)
411 dns_dispatch_detach(&requestmgr
->dispatchv6
);
412 requestmgr
->magic
= 0;
413 mctx
= requestmgr
->mctx
;
414 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
415 isc_mem_detach(&mctx
);
419 mgr_gethash(dns_requestmgr_t
*requestmgr
) {
420 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
425 return (requestmgr
->hash
% DNS_REQUEST_NLOCKS
);
428 static inline isc_result_t
429 req_send(dns_request_t
*request
, isc_task_t
*task
, isc_sockaddr_t
*address
) {
431 isc_socket_t
*socket
;
433 unsigned int dispattr
;
435 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request
);
437 REQUIRE(VALID_REQUEST(request
));
438 dispattr
= dns_dispatch_getattributes(request
->dispatch
);
439 socket
= req_getsocket(request
);
440 isc_buffer_usedregion(request
->query
, &r
);
442 * We could connect the socket when we are using an exclusive dispatch
443 * as we do in resolver.c, but we prefer implementation simplicity
446 result
= isc_socket_sendto(socket
, &r
, task
, req_senddone
,
447 request
, address
, NULL
);
448 if (result
== ISC_R_SUCCESS
)
449 request
->flags
|= DNS_REQUEST_F_SENDING
;
454 new_request(isc_mem_t
*mctx
, dns_request_t
**requestp
)
456 dns_request_t
*request
;
458 request
= isc_mem_get(mctx
, sizeof(*request
));
460 return (ISC_R_NOMEMORY
);
466 request
->mctx
= NULL
;
468 ISC_LINK_INIT(request
, link
);
469 request
->query
= NULL
;
470 request
->answer
= NULL
;
471 request
->event
= NULL
;
472 request
->dispatch
= NULL
;
473 request
->dispentry
= NULL
;
474 request
->timer
= NULL
;
475 request
->requestmgr
= NULL
;
476 request
->tsig
= NULL
;
477 request
->tsigkey
= NULL
;
478 ISC_EVENT_INIT(&request
->ctlevent
, sizeof(request
->ctlevent
), 0, NULL
,
479 DNS_EVENT_REQUESTCONTROL
, do_cancel
, request
, NULL
,
481 request
->canceling
= ISC_FALSE
;
482 request
->udpcount
= 0;
484 isc_mem_attach(mctx
, &request
->mctx
);
486 request
->magic
= REQUEST_MAGIC
;
488 return (ISC_R_SUCCESS
);
493 isblackholed(dns_dispatchmgr_t
*dispatchmgr
, isc_sockaddr_t
*destaddr
) {
494 dns_acl_t
*blackhole
;
495 isc_netaddr_t netaddr
;
497 isc_boolean_t drop
= ISC_FALSE
;
498 char netaddrstr
[ISC_NETADDR_FORMATSIZE
];
500 blackhole
= dns_dispatchmgr_getblackhole(dispatchmgr
);
501 if (blackhole
!= NULL
) {
502 isc_netaddr_fromsockaddr(&netaddr
, destaddr
);
503 if (dns_acl_match(&netaddr
, NULL
, blackhole
,
504 NULL
, &match
, NULL
) == ISC_R_SUCCESS
&&
509 isc_netaddr_format(&netaddr
, netaddrstr
, sizeof(netaddrstr
));
510 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr
);
516 create_tcp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
517 isc_sockaddr_t
*destaddr
, dns_dispatch_t
**dispatchp
)
520 isc_socket_t
*socket
= NULL
;
523 isc_sockaddr_t bind_any
;
525 result
= isc_socket_create(requestmgr
->socketmgr
,
526 isc_sockaddr_pf(destaddr
),
527 isc_sockettype_tcp
, &socket
);
528 if (result
!= ISC_R_SUCCESS
)
530 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
531 if (srcaddr
== NULL
) {
532 isc_sockaddr_anyofpf(&bind_any
,
533 isc_sockaddr_pf(destaddr
));
534 result
= isc_socket_bind(socket
, &bind_any
, 0);
537 isc_sockaddr_setport(&src
, 0);
538 result
= isc_socket_bind(socket
, &src
, 0);
540 if (result
!= ISC_R_SUCCESS
)
544 attrs
|= DNS_DISPATCHATTR_TCP
;
545 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
546 if (isc_sockaddr_pf(destaddr
) == AF_INET
)
547 attrs
|= DNS_DISPATCHATTR_IPV4
;
549 attrs
|= DNS_DISPATCHATTR_IPV6
;
550 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
551 result
= dns_dispatch_createtcp(requestmgr
->dispatchmgr
,
552 socket
, requestmgr
->taskmgr
,
553 4096, 2, 1, 1, 3, attrs
,
556 isc_socket_detach(&socket
);
561 find_udp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
562 isc_sockaddr_t
*destaddr
, dns_dispatch_t
**dispatchp
)
564 dns_dispatch_t
*disp
= NULL
;
565 unsigned int attrs
, attrmask
;
567 if (srcaddr
== NULL
) {
568 switch (isc_sockaddr_pf(destaddr
)) {
570 disp
= requestmgr
->dispatchv4
;
574 disp
= requestmgr
->dispatchv6
;
578 return (ISC_R_NOTIMPLEMENTED
);
581 return (ISC_R_FAMILYNOSUPPORT
);
582 dns_dispatch_attach(disp
, dispatchp
);
583 return (ISC_R_SUCCESS
);
586 attrs
|= DNS_DISPATCHATTR_UDP
;
587 switch (isc_sockaddr_pf(srcaddr
)) {
589 attrs
|= DNS_DISPATCHATTR_IPV4
;
593 attrs
|= DNS_DISPATCHATTR_IPV6
;
597 return (ISC_R_NOTIMPLEMENTED
);
600 attrmask
|= DNS_DISPATCHATTR_UDP
;
601 attrmask
|= DNS_DISPATCHATTR_TCP
;
602 attrmask
|= DNS_DISPATCHATTR_IPV4
;
603 attrmask
|= DNS_DISPATCHATTR_IPV6
;
604 return (dns_dispatch_getudp(requestmgr
->dispatchmgr
,
605 requestmgr
->socketmgr
,
608 1000, 32768, 16411, 16433,
614 get_dispatch(isc_boolean_t tcp
, dns_requestmgr_t
*requestmgr
,
615 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
616 dns_dispatch_t
**dispatchp
)
620 result
= create_tcp_dispatch(requestmgr
, srcaddr
,
621 destaddr
, dispatchp
);
623 result
= find_udp_dispatch(requestmgr
, srcaddr
,
624 destaddr
, dispatchp
);
629 set_timer(isc_timer_t
*timer
, unsigned int timeout
, unsigned int udpresend
) {
631 isc_interval_t interval
;
633 isc_timertype_t timertype
;
635 isc_interval_set(&interval
, timeout
, 0);
636 result
= isc_time_nowplusinterval(&expires
, &interval
);
637 isc_interval_set(&interval
, udpresend
, 0);
639 timertype
= udpresend
!= 0 ? isc_timertype_limited
: isc_timertype_once
;
640 if (result
== ISC_R_SUCCESS
)
641 result
= isc_timer_reset(timer
, timertype
, &expires
,
642 &interval
, ISC_FALSE
);
647 dns_request_createraw(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
648 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
649 unsigned int options
, unsigned int timeout
,
650 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
651 dns_request_t
**requestp
)
653 return(dns_request_createraw3(requestmgr
, msgbuf
, srcaddr
, destaddr
,
654 options
, timeout
, 0, 0, task
, action
,
659 dns_request_createraw2(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
660 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
661 unsigned int options
, unsigned int timeout
,
662 unsigned int udptimeout
, isc_task_t
*task
,
663 isc_taskaction_t action
, void *arg
,
664 dns_request_t
**requestp
)
666 unsigned int udpretries
= 0;
669 udpretries
= timeout
/ udptimeout
;
671 return (dns_request_createraw3(requestmgr
, msgbuf
, srcaddr
, destaddr
,
672 options
, timeout
, udptimeout
,
673 udpretries
, task
, action
, arg
,
678 dns_request_createraw3(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
679 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
680 unsigned int options
, unsigned int timeout
,
681 unsigned int udptimeout
, unsigned int udpretries
,
682 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
683 dns_request_t
**requestp
)
685 dns_request_t
*request
= NULL
;
686 isc_task_t
*tclone
= NULL
;
687 isc_socket_t
*socket
= NULL
;
691 isc_boolean_t tcp
= ISC_FALSE
;
694 REQUIRE(VALID_REQUESTMGR(requestmgr
));
695 REQUIRE(msgbuf
!= NULL
);
696 REQUIRE(destaddr
!= NULL
);
697 REQUIRE(task
!= NULL
);
698 REQUIRE(action
!= NULL
);
699 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
700 REQUIRE(timeout
> 0);
702 REQUIRE(isc_sockaddr_pf(srcaddr
) == isc_sockaddr_pf(destaddr
));
704 mctx
= requestmgr
->mctx
;
706 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
708 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
709 return (DNS_R_BLACKHOLED
);
712 result
= new_request(mctx
, &request
);
713 if (result
!= ISC_R_SUCCESS
)
716 if (udptimeout
== 0 && udpretries
!= 0) {
717 udptimeout
= timeout
/ (udpretries
+ 1);
721 request
->udpcount
= udpretries
;
724 * Create timer now. We will set it below once.
726 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
727 NULL
, NULL
, task
, req_timeout
, request
,
729 if (result
!= ISC_R_SUCCESS
)
732 request
->event
= (dns_requestevent_t
*)
733 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
734 action
, arg
, sizeof(dns_requestevent_t
));
735 if (request
->event
== NULL
) {
736 result
= ISC_R_NOMEMORY
;
739 isc_task_attach(task
, &tclone
);
740 request
->event
->ev_sender
= task
;
741 request
->event
->request
= request
;
742 request
->event
->result
= ISC_R_FAILURE
;
744 isc_buffer_usedregion(msgbuf
, &r
);
745 if (r
.length
< DNS_MESSAGE_HEADERLEN
|| r
.length
> 65535) {
746 result
= DNS_R_FORMERR
;
750 if ((options
& DNS_REQUESTOPT_TCP
) != 0 || r
.length
> 512)
753 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
,
755 if (result
!= ISC_R_SUCCESS
)
758 result
= dns_dispatch_addresponse2(request
->dispatch
, destaddr
, task
,
759 req_response
, request
, &id
,
761 requestmgr
->socketmgr
);
762 if (result
!= ISC_R_SUCCESS
)
765 socket
= req_getsocket(request
);
766 INSIST(socket
!= NULL
);
768 result
= isc_buffer_allocate(mctx
, &request
->query
,
769 r
.length
+ (tcp
? 2 : 0));
770 if (result
!= ISC_R_SUCCESS
)
773 isc_buffer_putuint16(request
->query
, (isc_uint16_t
)r
.length
);
774 result
= isc_buffer_copyregion(request
->query
, &r
);
775 if (result
!= ISC_R_SUCCESS
)
778 /* Add message ID. */
779 isc_buffer_usedregion(request
->query
, &r
);
781 isc_region_consume(&r
, 2);
782 r
.base
[0] = (id
>>8) & 0xff;
783 r
.base
[1] = id
& 0xff;
785 LOCK(&requestmgr
->lock
);
786 if (requestmgr
->exiting
) {
787 UNLOCK(&requestmgr
->lock
);
788 result
= ISC_R_SHUTTINGDOWN
;
791 requestmgr_attach(requestmgr
, &request
->requestmgr
);
792 request
->hash
= mgr_gethash(requestmgr
);
793 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
794 UNLOCK(&requestmgr
->lock
);
796 result
= set_timer(request
->timer
, timeout
, tcp
? 0 : udptimeout
);
797 if (result
!= ISC_R_SUCCESS
)
800 request
->destaddr
= *destaddr
;
802 result
= isc_socket_connect(socket
, destaddr
, task
,
803 req_connected
, request
);
804 if (result
!= ISC_R_SUCCESS
)
806 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
808 result
= req_send(request
, task
, destaddr
);
809 if (result
!= ISC_R_SUCCESS
)
813 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
816 return (ISC_R_SUCCESS
);
819 LOCK(&requestmgr
->lock
);
820 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
821 UNLOCK(&requestmgr
->lock
);
825 isc_task_detach(&tclone
);
826 req_destroy(request
);
827 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
828 dns_result_totext(result
));
833 dns_request_create(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
834 isc_sockaddr_t
*address
, unsigned int options
,
836 unsigned int timeout
, isc_task_t
*task
,
837 isc_taskaction_t action
, void *arg
,
838 dns_request_t
**requestp
)
840 return (dns_request_createvia3(requestmgr
, message
, NULL
, address
,
841 options
, key
, timeout
, 0, 0, task
,
842 action
, arg
, requestp
));
846 dns_request_createvia(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
847 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
848 unsigned int options
, dns_tsigkey_t
*key
,
849 unsigned int timeout
, isc_task_t
*task
,
850 isc_taskaction_t action
, void *arg
,
851 dns_request_t
**requestp
)
853 return(dns_request_createvia3(requestmgr
, message
, srcaddr
, destaddr
,
854 options
, key
, timeout
, 0, 0, task
,
855 action
, arg
, requestp
));
859 dns_request_createvia2(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
860 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
861 unsigned int options
, dns_tsigkey_t
*key
,
862 unsigned int timeout
, unsigned int udptimeout
,
863 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
864 dns_request_t
**requestp
)
866 unsigned int udpretries
= 0;
869 udpretries
= timeout
/ udptimeout
;
870 return (dns_request_createvia3(requestmgr
, message
, srcaddr
, destaddr
,
871 options
, key
, timeout
, udptimeout
,
872 udpretries
, task
, action
, arg
,
877 dns_request_createvia3(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
878 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
879 unsigned int options
, dns_tsigkey_t
*key
,
880 unsigned int timeout
, unsigned int udptimeout
,
881 unsigned int udpretries
, isc_task_t
*task
,
882 isc_taskaction_t action
, void *arg
,
883 dns_request_t
**requestp
)
885 dns_request_t
*request
= NULL
;
886 isc_task_t
*tclone
= NULL
;
887 isc_socket_t
*socket
= NULL
;
892 isc_boolean_t setkey
= ISC_TRUE
;
894 REQUIRE(VALID_REQUESTMGR(requestmgr
));
895 REQUIRE(message
!= NULL
);
896 REQUIRE(destaddr
!= NULL
);
897 REQUIRE(task
!= NULL
);
898 REQUIRE(action
!= NULL
);
899 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
900 REQUIRE(timeout
> 0);
902 REQUIRE(isc_sockaddr_pf(srcaddr
) == isc_sockaddr_pf(destaddr
));
904 mctx
= requestmgr
->mctx
;
906 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
908 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
909 return (DNS_R_BLACKHOLED
);
912 result
= new_request(mctx
, &request
);
913 if (result
!= ISC_R_SUCCESS
)
916 if (udptimeout
== 0 && udpretries
!= 0) {
917 udptimeout
= timeout
/ (udpretries
+ 1);
921 request
->udpcount
= udpretries
;
924 * Create timer now. We will set it below once.
926 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
927 NULL
, NULL
, task
, req_timeout
, request
,
929 if (result
!= ISC_R_SUCCESS
)
932 request
->event
= (dns_requestevent_t
*)
933 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
934 action
, arg
, sizeof(dns_requestevent_t
));
935 if (request
->event
== NULL
) {
936 result
= ISC_R_NOMEMORY
;
939 isc_task_attach(task
, &tclone
);
940 request
->event
->ev_sender
= task
;
941 request
->event
->request
= request
;
942 request
->event
->result
= ISC_R_FAILURE
;
944 dns_tsigkey_attach(key
, &request
->tsigkey
);
947 tcp
= ISC_TF((options
& DNS_REQUESTOPT_TCP
) != 0);
948 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
,
950 if (result
!= ISC_R_SUCCESS
)
953 result
= dns_dispatch_addresponse2(request
->dispatch
, destaddr
, task
,
954 req_response
, request
, &id
,
956 requestmgr
->socketmgr
);
957 if (result
!= ISC_R_SUCCESS
)
959 socket
= req_getsocket(request
);
960 INSIST(socket
!= NULL
);
964 result
= dns_message_settsigkey(message
, request
->tsigkey
);
965 if (result
!= ISC_R_SUCCESS
)
968 result
= req_render(message
, &request
->query
, options
, mctx
);
969 if (result
== DNS_R_USETCP
&&
970 (options
& DNS_REQUESTOPT_TCP
) == 0) {
972 * Try again using TCP.
974 dns_message_renderreset(message
);
975 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
976 dns_dispatch_detach(&request
->dispatch
);
978 options
|= DNS_REQUESTOPT_TCP
;
982 if (result
!= ISC_R_SUCCESS
)
985 result
= dns_message_getquerytsig(message
, mctx
, &request
->tsig
);
986 if (result
!= ISC_R_SUCCESS
)
989 LOCK(&requestmgr
->lock
);
990 if (requestmgr
->exiting
) {
991 UNLOCK(&requestmgr
->lock
);
992 result
= ISC_R_SHUTTINGDOWN
;
995 requestmgr_attach(requestmgr
, &request
->requestmgr
);
996 request
->hash
= mgr_gethash(requestmgr
);
997 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
998 UNLOCK(&requestmgr
->lock
);
1000 result
= set_timer(request
->timer
, timeout
, tcp
? 0 : udptimeout
);
1001 if (result
!= ISC_R_SUCCESS
)
1004 request
->destaddr
= *destaddr
;
1006 result
= isc_socket_connect(socket
, destaddr
, task
,
1007 req_connected
, request
);
1008 if (result
!= ISC_R_SUCCESS
)
1010 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
1012 result
= req_send(request
, task
, destaddr
);
1013 if (result
!= ISC_R_SUCCESS
)
1017 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
1019 *requestp
= request
;
1020 return (ISC_R_SUCCESS
);
1023 LOCK(&requestmgr
->lock
);
1024 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
1025 UNLOCK(&requestmgr
->lock
);
1029 isc_task_detach(&tclone
);
1030 req_destroy(request
);
1031 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
1032 dns_result_totext(result
));
1037 req_render(dns_message_t
*message
, isc_buffer_t
**bufferp
,
1038 unsigned int options
, isc_mem_t
*mctx
)
1040 isc_buffer_t
*buf1
= NULL
;
1041 isc_buffer_t
*buf2
= NULL
;
1042 isc_result_t result
;
1044 isc_boolean_t tcp
= ISC_FALSE
;
1045 dns_compress_t cctx
;
1046 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
1048 REQUIRE(bufferp
!= NULL
&& *bufferp
== NULL
);
1050 req_log(ISC_LOG_DEBUG(3), "request_render");
1053 * Create buffer able to hold largest possible message.
1055 result
= isc_buffer_allocate(mctx
, &buf1
, 65535);
1056 if (result
!= ISC_R_SUCCESS
)
1059 result
= dns_compress_init(&cctx
, -1, mctx
);
1060 if (result
!= ISC_R_SUCCESS
)
1062 cleanup_cctx
= ISC_TRUE
;
1067 result
= dns_message_renderbegin(message
, &cctx
, buf1
);
1068 if (result
!= ISC_R_SUCCESS
)
1070 result
= dns_message_rendersection(message
, DNS_SECTION_QUESTION
, 0);
1071 if (result
!= ISC_R_SUCCESS
)
1073 result
= dns_message_rendersection(message
, DNS_SECTION_ANSWER
, 0);
1074 if (result
!= ISC_R_SUCCESS
)
1076 result
= dns_message_rendersection(message
, DNS_SECTION_AUTHORITY
, 0);
1077 if (result
!= ISC_R_SUCCESS
)
1079 result
= dns_message_rendersection(message
, DNS_SECTION_ADDITIONAL
, 0);
1080 if (result
!= ISC_R_SUCCESS
)
1082 result
= dns_message_renderend(message
);
1083 if (result
!= ISC_R_SUCCESS
)
1086 dns_compress_invalidate(&cctx
);
1087 cleanup_cctx
= ISC_FALSE
;
1090 * Copy rendered message to exact sized buffer.
1092 isc_buffer_usedregion(buf1
, &r
);
1093 if ((options
& DNS_REQUESTOPT_TCP
) != 0) {
1095 } else if (r
.length
> 512) {
1096 result
= DNS_R_USETCP
;
1099 result
= isc_buffer_allocate(mctx
, &buf2
, r
.length
+ (tcp
? 2 : 0));
1100 if (result
!= ISC_R_SUCCESS
)
1103 isc_buffer_putuint16(buf2
, (isc_uint16_t
)r
.length
);
1104 result
= isc_buffer_copyregion(buf2
, &r
);
1105 if (result
!= ISC_R_SUCCESS
)
1109 * Cleanup and return.
1111 isc_buffer_free(&buf1
);
1113 return (ISC_R_SUCCESS
);
1116 dns_message_renderreset(message
);
1118 isc_buffer_free(&buf1
);
1120 isc_buffer_free(&buf2
);
1122 dns_compress_invalidate(&cctx
);
1128 * If this request is no longer waiting for events,
1129 * send the completion event. This will ultimately
1130 * cause the request to be destroyed.
1133 * 'request' is locked by the caller.
1136 send_if_done(dns_request_t
*request
, isc_result_t result
) {
1137 if (!DNS_REQUEST_CONNECTING(request
) &&
1138 !DNS_REQUEST_SENDING(request
) &&
1139 !request
->canceling
)
1140 req_sendevent(request
, result
);
1144 * Handle the control event.
1147 do_cancel(isc_task_t
*task
, isc_event_t
*event
) {
1148 dns_request_t
*request
= event
->ev_arg
;
1150 INSIST(event
->ev_type
== DNS_EVENT_REQUESTCONTROL
);
1151 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1152 request
->canceling
= ISC_FALSE
;
1153 if (!DNS_REQUEST_CANCELED(request
))
1154 req_cancel(request
);
1155 send_if_done(request
, ISC_R_CANCELED
);
1156 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1160 dns_request_cancel(dns_request_t
*request
) {
1161 REQUIRE(VALID_REQUEST(request
));
1163 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request
);
1165 REQUIRE(VALID_REQUEST(request
));
1167 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1168 if (!request
->canceling
&& !DNS_REQUEST_CANCELED(request
)) {
1169 isc_event_t
*ev
= &request
->ctlevent
;
1170 isc_task_send(request
->event
->ev_sender
, &ev
);
1171 request
->canceling
= ISC_TRUE
;
1173 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1177 dns_request_getresponse(dns_request_t
*request
, dns_message_t
*message
,
1178 unsigned int options
)
1180 isc_result_t result
;
1182 REQUIRE(VALID_REQUEST(request
));
1183 REQUIRE(request
->answer
!= NULL
);
1185 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1188 result
= dns_message_setquerytsig(message
, request
->tsig
);
1189 if (result
!= ISC_R_SUCCESS
)
1191 result
= dns_message_settsigkey(message
, request
->tsigkey
);
1192 if (result
!= ISC_R_SUCCESS
)
1194 result
= dns_message_parse(message
, request
->answer
, options
);
1195 if (result
!= ISC_R_SUCCESS
)
1197 if (request
->tsigkey
!= NULL
)
1198 result
= dns_tsig_verify(request
->answer
, message
, NULL
, NULL
);
1203 dns_request_usedtcp(dns_request_t
*request
) {
1204 REQUIRE(VALID_REQUEST(request
));
1206 return (ISC_TF((request
->flags
& DNS_REQUEST_F_TCP
) != 0));
1210 dns_request_destroy(dns_request_t
**requestp
) {
1211 dns_request_t
*request
;
1213 REQUIRE(requestp
!= NULL
&& VALID_REQUEST(*requestp
));
1215 request
= *requestp
;
1217 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request
);
1219 LOCK(&request
->requestmgr
->lock
);
1220 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1221 ISC_LIST_UNLINK(request
->requestmgr
->requests
, request
, link
);
1222 INSIST(!DNS_REQUEST_CONNECTING(request
));
1223 INSIST(!DNS_REQUEST_SENDING(request
));
1224 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1225 UNLOCK(&request
->requestmgr
->lock
);
1228 * These should have been cleaned up by req_cancel() before
1229 * the completion event was sent.
1231 INSIST(!ISC_LINK_LINKED(request
, link
));
1232 INSIST(request
->dispentry
== NULL
);
1233 INSIST(request
->dispatch
== NULL
);
1234 INSIST(request
->timer
== NULL
);
1236 req_destroy(request
);
1242 *** Private: request.
1245 static isc_socket_t
*
1246 req_getsocket(dns_request_t
*request
) {
1247 unsigned int dispattr
;
1248 isc_socket_t
*socket
;
1250 dispattr
= dns_dispatch_getattributes(request
->dispatch
);
1251 if ((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0) {
1252 INSIST(request
->dispentry
!= NULL
);
1253 socket
= dns_dispatch_getentrysocket(request
->dispentry
);
1255 socket
= dns_dispatch_getsocket(request
->dispatch
);
1261 req_connected(isc_task_t
*task
, isc_event_t
*event
) {
1262 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1263 isc_result_t result
;
1264 dns_request_t
*request
= event
->ev_arg
;
1266 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1267 REQUIRE(VALID_REQUEST(request
));
1268 REQUIRE(DNS_REQUEST_CONNECTING(request
));
1270 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request
);
1272 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1273 request
->flags
&= ~DNS_REQUEST_F_CONNECTING
;
1275 if (DNS_REQUEST_CANCELED(request
)) {
1277 * Send delayed event.
1279 if (DNS_REQUEST_TIMEDOUT(request
))
1280 send_if_done(request
, ISC_R_TIMEDOUT
);
1282 send_if_done(request
, ISC_R_CANCELED
);
1284 dns_dispatch_starttcp(request
->dispatch
);
1285 result
= sevent
->result
;
1286 if (result
== ISC_R_SUCCESS
)
1287 result
= req_send(request
, task
, NULL
);
1289 if (result
!= ISC_R_SUCCESS
) {
1290 req_cancel(request
);
1291 send_if_done(request
, ISC_R_CANCELED
);
1294 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1295 isc_event_free(&event
);
1299 req_senddone(isc_task_t
*task
, isc_event_t
*event
) {
1300 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1301 dns_request_t
*request
= event
->ev_arg
;
1303 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1304 REQUIRE(VALID_REQUEST(request
));
1305 REQUIRE(DNS_REQUEST_SENDING(request
));
1307 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request
);
1311 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1312 request
->flags
&= ~DNS_REQUEST_F_SENDING
;
1314 if (DNS_REQUEST_CANCELED(request
)) {
1316 * Send delayed event.
1318 if (DNS_REQUEST_TIMEDOUT(request
))
1319 send_if_done(request
, ISC_R_TIMEDOUT
);
1321 send_if_done(request
, ISC_R_CANCELED
);
1322 } else if (sevent
->result
!= ISC_R_SUCCESS
) {
1323 req_cancel(request
);
1324 send_if_done(request
, ISC_R_CANCELED
);
1326 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1328 isc_event_free(&event
);
1332 req_response(isc_task_t
*task
, isc_event_t
*event
) {
1333 isc_result_t result
;
1334 dns_request_t
*request
= event
->ev_arg
;
1335 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
1338 REQUIRE(VALID_REQUEST(request
));
1339 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
1343 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request
,
1344 dns_result_totext(devent
->result
));
1346 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1347 result
= devent
->result
;
1348 if (result
!= ISC_R_SUCCESS
)
1352 * Copy buffer to request.
1354 isc_buffer_usedregion(&devent
->buffer
, &r
);
1355 result
= isc_buffer_allocate(request
->mctx
, &request
->answer
,
1357 if (result
!= ISC_R_SUCCESS
)
1359 result
= isc_buffer_copyregion(request
->answer
, &r
);
1360 if (result
!= ISC_R_SUCCESS
)
1361 isc_buffer_free(&request
->answer
);
1366 dns_dispatch_removeresponse(&request
->dispentry
, &devent
);
1367 req_cancel(request
);
1369 * Send completion event.
1371 send_if_done(request
, result
);
1372 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1376 req_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1377 dns_request_t
*request
= event
->ev_arg
;
1378 isc_result_t result
;
1380 REQUIRE(VALID_REQUEST(request
));
1382 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request
);
1385 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1386 if (event
->ev_type
== ISC_TIMEREVENT_TICK
&&
1387 request
->udpcount
-- != 0) {
1388 if (! DNS_REQUEST_SENDING(request
)) {
1389 result
= req_send(request
, task
, &request
->destaddr
);
1390 if (result
!= ISC_R_SUCCESS
) {
1391 req_cancel(request
);
1392 send_if_done(request
, result
);
1396 request
->flags
|= DNS_REQUEST_F_TIMEDOUT
;
1397 req_cancel(request
);
1398 send_if_done(request
, ISC_R_TIMEDOUT
);
1400 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1401 isc_event_free(&event
);
1405 req_sendevent(dns_request_t
*request
, isc_result_t result
) {
1408 REQUIRE(VALID_REQUEST(request
));
1410 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request
);
1413 * Lock held by caller.
1415 task
= request
->event
->ev_sender
;
1416 request
->event
->ev_sender
= request
;
1417 request
->event
->result
= result
;
1418 isc_task_sendanddetach(&task
, (isc_event_t
**)&request
->event
);
1422 req_destroy(dns_request_t
*request
) {
1425 REQUIRE(VALID_REQUEST(request
));
1427 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request
);
1430 if (request
->query
!= NULL
)
1431 isc_buffer_free(&request
->query
);
1432 if (request
->answer
!= NULL
)
1433 isc_buffer_free(&request
->answer
);
1434 if (request
->event
!= NULL
)
1435 isc_event_free((isc_event_t
**)&request
->event
);
1436 if (request
->dispentry
!= NULL
)
1437 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1438 if (request
->dispatch
!= NULL
)
1439 dns_dispatch_detach(&request
->dispatch
);
1440 if (request
->timer
!= NULL
)
1441 isc_timer_detach(&request
->timer
);
1442 if (request
->tsig
!= NULL
)
1443 isc_buffer_free(&request
->tsig
);
1444 if (request
->tsigkey
!= NULL
)
1445 dns_tsigkey_detach(&request
->tsigkey
);
1446 if (request
->requestmgr
!= NULL
)
1447 requestmgr_detach(&request
->requestmgr
);
1448 mctx
= request
->mctx
;
1449 isc_mem_put(mctx
, request
, sizeof(*request
));
1450 isc_mem_detach(&mctx
);
1454 * Stop the current request. Must be called from the request's task.
1457 req_cancel(dns_request_t
*request
) {
1458 isc_socket_t
*socket
;
1459 unsigned int dispattr
;
1461 REQUIRE(VALID_REQUEST(request
));
1463 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request
);
1466 * Lock held by caller.
1468 request
->flags
|= DNS_REQUEST_F_CANCELED
;
1470 if (request
->timer
!= NULL
)
1471 isc_timer_detach(&request
->timer
);
1472 dispattr
= dns_dispatch_getattributes(request
->dispatch
);
1474 if (DNS_REQUEST_CONNECTING(request
) || DNS_REQUEST_SENDING(request
)) {
1475 if ((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0) {
1476 if (request
->dispentry
!= NULL
) {
1477 socket
= dns_dispatch_getentrysocket(
1478 request
->dispentry
);
1481 socket
= dns_dispatch_getsocket(request
->dispatch
);
1482 if (DNS_REQUEST_CONNECTING(request
) && socket
!= NULL
)
1483 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_CONNECT
);
1484 if (DNS_REQUEST_SENDING(request
) && socket
!= NULL
)
1485 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_SEND
);
1487 if (request
->dispentry
!= NULL
)
1488 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1489 dns_dispatch_detach(&request
->dispatch
);
1493 req_log(int level
, const char *fmt
, ...) {
1497 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
1498 DNS_LOGMODULE_REQUEST
, level
, fmt
, ap
);