1 /* $NetBSD: request.c,v 1.9 2015/07/08 17:28:59 christos Exp $ */
4 * Copyright (C) 2004-2015 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.
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
;
97 #define DNS_REQUEST_F_CONNECTING 0x0001
98 #define DNS_REQUEST_F_SENDING 0x0002
99 #define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
100 synchronously canceled */
101 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
102 #define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
103 #define DNS_REQUEST_CANCELED(r) \
104 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
105 #define DNS_REQUEST_CONNECTING(r) \
106 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
107 #define DNS_REQUEST_SENDING(r) \
108 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
109 #define DNS_REQUEST_TIMEDOUT(r) \
110 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
117 static void mgr_destroy(dns_requestmgr_t
*requestmgr
);
118 static void mgr_shutdown(dns_requestmgr_t
*requestmgr
);
119 static unsigned int mgr_gethash(dns_requestmgr_t
*requestmgr
);
120 static void send_shutdown_events(dns_requestmgr_t
*requestmgr
);
122 static isc_result_t
req_render(dns_message_t
*message
, isc_buffer_t
**buffer
,
123 unsigned int options
, isc_mem_t
*mctx
);
124 static void req_senddone(isc_task_t
*task
, isc_event_t
*event
);
125 static void req_response(isc_task_t
*task
, isc_event_t
*event
);
126 static void req_timeout(isc_task_t
*task
, isc_event_t
*event
);
127 static isc_socket_t
* req_getsocket(dns_request_t
*request
);
128 static void req_connected(isc_task_t
*task
, isc_event_t
*event
);
129 static void req_sendevent(dns_request_t
*request
, isc_result_t result
);
130 static void req_cancel(dns_request_t
*request
);
131 static void req_destroy(dns_request_t
*request
);
132 static void req_log(int level
, const char *fmt
, ...) ISC_FORMAT_PRINTF(2, 3);
133 static void do_cancel(isc_task_t
*task
, isc_event_t
*event
);
140 dns_requestmgr_create(isc_mem_t
*mctx
,
141 isc_timermgr_t
*timermgr
,
142 isc_socketmgr_t
*socketmgr
,
143 isc_taskmgr_t
*taskmgr
,
144 dns_dispatchmgr_t
*dispatchmgr
,
145 dns_dispatch_t
*dispatchv4
,
146 dns_dispatch_t
*dispatchv6
,
147 dns_requestmgr_t
**requestmgrp
)
149 dns_requestmgr_t
*requestmgr
;
150 isc_socket_t
*socket
;
153 unsigned int dispattr
;
155 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
157 REQUIRE(requestmgrp
!= NULL
&& *requestmgrp
== NULL
);
158 REQUIRE(timermgr
!= NULL
);
159 REQUIRE(socketmgr
!= NULL
);
160 REQUIRE(taskmgr
!= NULL
);
161 REQUIRE(dispatchmgr
!= NULL
);
163 if (dispatchv4
!= NULL
) {
164 dispattr
= dns_dispatch_getattributes(dispatchv4
);
165 REQUIRE((dispattr
& DNS_DISPATCHATTR_UDP
) != 0);
167 if (dispatchv6
!= NULL
) {
168 dispattr
= dns_dispatch_getattributes(dispatchv6
);
169 REQUIRE((dispattr
& DNS_DISPATCHATTR_UDP
) != 0);
172 requestmgr
= isc_mem_get(mctx
, sizeof(*requestmgr
));
173 if (requestmgr
== NULL
)
174 return (ISC_R_NOMEMORY
);
176 result
= isc_mutex_init(&requestmgr
->lock
);
177 if (result
!= ISC_R_SUCCESS
) {
178 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
181 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++) {
182 result
= isc_mutex_init(&requestmgr
->locks
[i
]);
183 if (result
!= ISC_R_SUCCESS
) {
185 DESTROYLOCK(&requestmgr
->locks
[i
]);
186 DESTROYLOCK(&requestmgr
->lock
);
187 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
191 requestmgr
->timermgr
= timermgr
;
192 requestmgr
->socketmgr
= socketmgr
;
193 requestmgr
->taskmgr
= taskmgr
;
194 requestmgr
->dispatchmgr
= dispatchmgr
;
195 requestmgr
->dispatchv4
= NULL
;
196 if (dispatchv4
!= NULL
)
197 dns_dispatch_attach(dispatchv4
, &requestmgr
->dispatchv4
);
198 requestmgr
->dispatchv6
= NULL
;
199 if (dispatchv6
!= NULL
)
200 dns_dispatch_attach(dispatchv6
, &requestmgr
->dispatchv6
);
201 requestmgr
->mctx
= NULL
;
202 isc_mem_attach(mctx
, &requestmgr
->mctx
);
203 requestmgr
->eref
= 1; /* implicit attach */
204 requestmgr
->iref
= 0;
205 ISC_LIST_INIT(requestmgr
->whenshutdown
);
206 ISC_LIST_INIT(requestmgr
->requests
);
207 requestmgr
->exiting
= ISC_FALSE
;
208 requestmgr
->hash
= 0;
209 requestmgr
->magic
= REQUESTMGR_MAGIC
;
211 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr
);
213 *requestmgrp
= requestmgr
;
214 return (ISC_R_SUCCESS
);
218 dns_requestmgr_whenshutdown(dns_requestmgr_t
*requestmgr
, isc_task_t
*task
,
219 isc_event_t
**eventp
)
224 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
226 REQUIRE(VALID_REQUESTMGR(requestmgr
));
227 REQUIRE(eventp
!= NULL
);
232 LOCK(&requestmgr
->lock
);
234 if (requestmgr
->exiting
) {
236 * We're already shutdown. Send the event.
238 event
->ev_sender
= requestmgr
;
239 isc_task_send(task
, &event
);
242 isc_task_attach(task
, &clone
);
243 event
->ev_sender
= clone
;
244 ISC_LIST_APPEND(requestmgr
->whenshutdown
, event
, ev_link
);
246 UNLOCK(&requestmgr
->lock
);
250 dns_requestmgr_shutdown(dns_requestmgr_t
*requestmgr
) {
252 REQUIRE(VALID_REQUESTMGR(requestmgr
));
254 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr
);
256 LOCK(&requestmgr
->lock
);
257 mgr_shutdown(requestmgr
);
258 UNLOCK(&requestmgr
->lock
);
262 mgr_shutdown(dns_requestmgr_t
*requestmgr
) {
263 dns_request_t
*request
;
268 if (!requestmgr
->exiting
) {
269 requestmgr
->exiting
= ISC_TRUE
;
270 for (request
= ISC_LIST_HEAD(requestmgr
->requests
);
272 request
= ISC_LIST_NEXT(request
, link
)) {
273 dns_request_cancel(request
);
275 if (requestmgr
->iref
== 0) {
276 INSIST(ISC_LIST_EMPTY(requestmgr
->requests
));
277 send_shutdown_events(requestmgr
);
283 requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
289 REQUIRE(VALID_REQUESTMGR(source
));
290 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
292 REQUIRE(!source
->exiting
);
297 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
298 source
, source
->eref
, source
->iref
);
302 requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
303 dns_requestmgr_t
*requestmgr
;
304 isc_boolean_t need_destroy
= ISC_FALSE
;
306 REQUIRE(requestmgrp
!= NULL
);
307 requestmgr
= *requestmgrp
;
308 REQUIRE(VALID_REQUESTMGR(requestmgr
));
311 LOCK(&requestmgr
->lock
);
312 INSIST(requestmgr
->iref
> 0);
315 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
316 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
318 if (requestmgr
->iref
== 0 && requestmgr
->exiting
) {
319 INSIST(ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
320 send_shutdown_events(requestmgr
);
321 if (requestmgr
->eref
== 0)
322 need_destroy
= ISC_TRUE
;
324 UNLOCK(&requestmgr
->lock
);
327 mgr_destroy(requestmgr
);
331 dns_requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
333 REQUIRE(VALID_REQUESTMGR(source
));
334 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
335 REQUIRE(!source
->exiting
);
340 UNLOCK(&source
->lock
);
342 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
343 source
, source
->eref
, source
->iref
);
347 dns_requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
348 dns_requestmgr_t
*requestmgr
;
349 isc_boolean_t need_destroy
= ISC_FALSE
;
351 REQUIRE(requestmgrp
!= NULL
);
352 requestmgr
= *requestmgrp
;
353 REQUIRE(VALID_REQUESTMGR(requestmgr
));
355 LOCK(&requestmgr
->lock
);
356 INSIST(requestmgr
->eref
> 0);
359 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
360 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
362 if (requestmgr
->eref
== 0 && requestmgr
->iref
== 0) {
363 INSIST(requestmgr
->exiting
&&
364 ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
365 need_destroy
= ISC_TRUE
;
367 UNLOCK(&requestmgr
->lock
);
370 mgr_destroy(requestmgr
);
376 send_shutdown_events(dns_requestmgr_t
*requestmgr
) {
377 isc_event_t
*event
, *next_event
;
380 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr
);
383 * Caller must be holding the manager lock.
385 for (event
= ISC_LIST_HEAD(requestmgr
->whenshutdown
);
387 event
= next_event
) {
388 next_event
= ISC_LIST_NEXT(event
, ev_link
);
389 ISC_LIST_UNLINK(requestmgr
->whenshutdown
, event
, ev_link
);
390 etask
= event
->ev_sender
;
391 event
->ev_sender
= requestmgr
;
392 isc_task_sendanddetach(&etask
, &event
);
397 mgr_destroy(dns_requestmgr_t
*requestmgr
) {
401 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
403 REQUIRE(requestmgr
->eref
== 0);
404 REQUIRE(requestmgr
->iref
== 0);
406 DESTROYLOCK(&requestmgr
->lock
);
407 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++)
408 DESTROYLOCK(&requestmgr
->locks
[i
]);
409 if (requestmgr
->dispatchv4
!= NULL
)
410 dns_dispatch_detach(&requestmgr
->dispatchv4
);
411 if (requestmgr
->dispatchv6
!= NULL
)
412 dns_dispatch_detach(&requestmgr
->dispatchv6
);
413 requestmgr
->magic
= 0;
414 mctx
= requestmgr
->mctx
;
415 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
416 isc_mem_detach(&mctx
);
420 mgr_gethash(dns_requestmgr_t
*requestmgr
) {
421 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
426 return (requestmgr
->hash
% DNS_REQUEST_NLOCKS
);
429 static inline isc_result_t
430 req_send(dns_request_t
*request
, isc_task_t
*task
, isc_sockaddr_t
*address
) {
432 isc_socket_t
*socket
;
433 isc_socketevent_t
*sendevent
;
436 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request
);
438 REQUIRE(VALID_REQUEST(request
));
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 sendevent
= isc_socket_socketevent(request
->mctx
, socket
,
447 ISC_SOCKEVENT_SENDDONE
,
448 req_senddone
, request
);
449 if (sendevent
== NULL
)
450 return (ISC_R_NOMEMORY
);
451 if (request
->dscp
== -1) {
452 sendevent
->attributes
&= ~ISC_SOCKEVENTATTR_DSCP
;
455 sendevent
->attributes
|= ISC_SOCKEVENTATTR_DSCP
;
456 sendevent
->dscp
= request
->dscp
;
459 result
= isc_socket_sendto2(socket
, &r
, task
, address
, NULL
,
461 if (result
== ISC_R_SUCCESS
)
462 request
->flags
|= DNS_REQUEST_F_SENDING
;
467 new_request(isc_mem_t
*mctx
, dns_request_t
**requestp
)
469 dns_request_t
*request
;
471 request
= isc_mem_get(mctx
, sizeof(*request
));
473 return (ISC_R_NOMEMORY
);
479 request
->mctx
= NULL
;
481 ISC_LINK_INIT(request
, link
);
482 request
->query
= NULL
;
483 request
->answer
= NULL
;
484 request
->event
= NULL
;
485 request
->dispatch
= NULL
;
486 request
->dispentry
= NULL
;
487 request
->timer
= NULL
;
488 request
->requestmgr
= NULL
;
489 request
->tsig
= NULL
;
490 request
->tsigkey
= NULL
;
492 ISC_EVENT_INIT(&request
->ctlevent
, sizeof(request
->ctlevent
), 0, NULL
,
493 DNS_EVENT_REQUESTCONTROL
, do_cancel
, request
, NULL
,
495 request
->canceling
= ISC_FALSE
;
496 request
->udpcount
= 0;
498 isc_mem_attach(mctx
, &request
->mctx
);
500 request
->magic
= REQUEST_MAGIC
;
502 return (ISC_R_SUCCESS
);
507 isblackholed(dns_dispatchmgr_t
*dispatchmgr
, isc_sockaddr_t
*destaddr
) {
508 dns_acl_t
*blackhole
;
509 isc_netaddr_t netaddr
;
511 isc_boolean_t drop
= ISC_FALSE
;
512 char netaddrstr
[ISC_NETADDR_FORMATSIZE
];
514 blackhole
= dns_dispatchmgr_getblackhole(dispatchmgr
);
515 if (blackhole
!= NULL
) {
516 isc_netaddr_fromsockaddr(&netaddr
, destaddr
);
517 if (dns_acl_match(&netaddr
, NULL
, blackhole
,
518 NULL
, &match
, NULL
) == ISC_R_SUCCESS
&&
523 isc_netaddr_format(&netaddr
, netaddrstr
, sizeof(netaddrstr
));
524 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr
);
530 create_tcp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
531 isc_sockaddr_t
*destaddr
, isc_dscp_t dscp
,
532 dns_dispatch_t
**dispatchp
)
535 isc_socket_t
*socket
= NULL
;
538 isc_sockaddr_t bind_any
;
540 result
= isc_socket_create(requestmgr
->socketmgr
,
541 isc_sockaddr_pf(destaddr
),
542 isc_sockettype_tcp
, &socket
);
543 if (result
!= ISC_R_SUCCESS
)
545 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
546 if (srcaddr
== NULL
) {
547 isc_sockaddr_anyofpf(&bind_any
,
548 isc_sockaddr_pf(destaddr
));
549 result
= isc_socket_bind(socket
, &bind_any
, 0);
552 isc_sockaddr_setport(&src
, 0);
553 result
= isc_socket_bind(socket
, &src
, 0);
555 if (result
!= ISC_R_SUCCESS
)
560 attrs
|= DNS_DISPATCHATTR_TCP
;
561 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
562 if (isc_sockaddr_pf(destaddr
) == AF_INET
)
563 attrs
|= DNS_DISPATCHATTR_IPV4
;
565 attrs
|= DNS_DISPATCHATTR_IPV6
;
566 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
568 isc_socket_dscp(socket
, dscp
);
569 result
= dns_dispatch_createtcp(requestmgr
->dispatchmgr
,
570 socket
, requestmgr
->taskmgr
,
571 4096, 2, 1, 1, 3, attrs
,
574 isc_socket_detach(&socket
);
579 find_udp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
580 isc_sockaddr_t
*destaddr
, dns_dispatch_t
**dispatchp
)
582 dns_dispatch_t
*disp
= NULL
;
583 unsigned int attrs
, attrmask
;
585 if (srcaddr
== NULL
) {
586 switch (isc_sockaddr_pf(destaddr
)) {
588 disp
= requestmgr
->dispatchv4
;
592 disp
= requestmgr
->dispatchv6
;
596 return (ISC_R_NOTIMPLEMENTED
);
599 return (ISC_R_FAMILYNOSUPPORT
);
600 dns_dispatch_attach(disp
, dispatchp
);
601 return (ISC_R_SUCCESS
);
604 attrs
|= DNS_DISPATCHATTR_UDP
;
605 switch (isc_sockaddr_pf(srcaddr
)) {
607 attrs
|= DNS_DISPATCHATTR_IPV4
;
611 attrs
|= DNS_DISPATCHATTR_IPV6
;
615 return (ISC_R_NOTIMPLEMENTED
);
618 attrmask
|= DNS_DISPATCHATTR_UDP
;
619 attrmask
|= DNS_DISPATCHATTR_TCP
;
620 attrmask
|= DNS_DISPATCHATTR_IPV4
;
621 attrmask
|= DNS_DISPATCHATTR_IPV6
;
622 return (dns_dispatch_getudp(requestmgr
->dispatchmgr
,
623 requestmgr
->socketmgr
,
626 32768, 32768, 16411, 16433,
632 get_dispatch(isc_boolean_t tcp
, dns_requestmgr_t
*requestmgr
,
633 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
634 isc_dscp_t dscp
, dns_dispatch_t
**dispatchp
)
638 result
= create_tcp_dispatch(requestmgr
, srcaddr
,
639 destaddr
, dscp
, dispatchp
);
641 result
= find_udp_dispatch(requestmgr
, srcaddr
,
642 destaddr
, dispatchp
);
647 set_timer(isc_timer_t
*timer
, unsigned int timeout
, unsigned int udpresend
) {
649 isc_interval_t interval
;
651 isc_timertype_t timertype
;
653 isc_interval_set(&interval
, timeout
, 0);
654 result
= isc_time_nowplusinterval(&expires
, &interval
);
655 isc_interval_set(&interval
, udpresend
, 0);
657 timertype
= udpresend
!= 0 ? isc_timertype_limited
: isc_timertype_once
;
658 if (result
== ISC_R_SUCCESS
)
659 result
= isc_timer_reset(timer
, timertype
, &expires
,
660 &interval
, ISC_FALSE
);
665 dns_request_createraw(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
666 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
667 unsigned int options
, unsigned int timeout
,
668 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
669 dns_request_t
**requestp
)
671 return(dns_request_createraw4(requestmgr
, msgbuf
, srcaddr
, destaddr
,
672 -1, options
, timeout
, 0, 0, task
, action
,
677 dns_request_createraw2(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
678 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
679 unsigned int options
, unsigned int timeout
,
680 unsigned int udptimeout
, isc_task_t
*task
,
681 isc_taskaction_t action
, void *arg
,
682 dns_request_t
**requestp
)
684 unsigned int udpretries
= 0;
687 udpretries
= timeout
/ udptimeout
;
689 return (dns_request_createraw4(requestmgr
, msgbuf
, srcaddr
, destaddr
,
690 -1, options
, timeout
, udptimeout
,
691 udpretries
, task
, action
, arg
,
696 dns_request_createraw3(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
697 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
698 unsigned int options
, unsigned int timeout
,
699 unsigned int udptimeout
, unsigned int udpretries
,
700 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
701 dns_request_t
**requestp
)
703 return (dns_request_createraw4(requestmgr
, msgbuf
, srcaddr
, destaddr
,
704 -1, options
, timeout
, udptimeout
,
705 udpretries
, task
, action
, arg
,
710 dns_request_createraw4(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
711 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
712 isc_dscp_t dscp
, unsigned int options
,
713 unsigned int timeout
, unsigned int udptimeout
,
714 unsigned int udpretries
, isc_task_t
*task
,
715 isc_taskaction_t action
, void *arg
,
716 dns_request_t
**requestp
)
718 dns_request_t
*request
= NULL
;
719 isc_task_t
*tclone
= NULL
;
720 isc_socket_t
*socket
= NULL
;
724 isc_boolean_t tcp
= ISC_FALSE
;
726 unsigned int dispopt
= 0;
728 REQUIRE(VALID_REQUESTMGR(requestmgr
));
729 REQUIRE(msgbuf
!= NULL
);
730 REQUIRE(destaddr
!= NULL
);
731 REQUIRE(task
!= NULL
);
732 REQUIRE(action
!= NULL
);
733 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
734 REQUIRE(timeout
> 0);
736 REQUIRE(isc_sockaddr_pf(srcaddr
) == isc_sockaddr_pf(destaddr
));
738 mctx
= requestmgr
->mctx
;
740 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
742 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
743 return (DNS_R_BLACKHOLED
);
746 result
= new_request(mctx
, &request
);
747 if (result
!= ISC_R_SUCCESS
)
750 if (udptimeout
== 0 && udpretries
!= 0) {
751 udptimeout
= timeout
/ (udpretries
+ 1);
755 request
->udpcount
= udpretries
;
756 request
->dscp
= dscp
;
759 * Create timer now. We will set it below once.
761 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
762 NULL
, NULL
, task
, req_timeout
, request
,
764 if (result
!= ISC_R_SUCCESS
)
767 request
->event
= (dns_requestevent_t
*)
768 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
769 action
, arg
, sizeof(dns_requestevent_t
));
770 if (request
->event
== NULL
) {
771 result
= ISC_R_NOMEMORY
;
774 isc_task_attach(task
, &tclone
);
775 request
->event
->ev_sender
= task
;
776 request
->event
->request
= request
;
777 request
->event
->result
= ISC_R_FAILURE
;
779 isc_buffer_usedregion(msgbuf
, &r
);
780 if (r
.length
< DNS_MESSAGE_HEADERLEN
|| r
.length
> 65535) {
781 result
= DNS_R_FORMERR
;
785 if ((options
& DNS_REQUESTOPT_TCP
) != 0 || r
.length
> 512)
788 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
, dscp
,
790 if (result
!= ISC_R_SUCCESS
)
793 if ((options
& DNS_REQUESTOPT_FIXEDID
) != 0) {
794 id
= (r
.base
[0] << 8) | r
.base
[1];
795 dispopt
|= DNS_DISPATCHOPT_FIXEDID
;
798 result
= dns_dispatch_addresponse3(request
->dispatch
, dispopt
,
799 destaddr
, task
, req_response
,
800 request
, &id
, &request
->dispentry
,
801 requestmgr
->socketmgr
);
802 if (result
!= ISC_R_SUCCESS
)
805 socket
= req_getsocket(request
);
806 INSIST(socket
!= NULL
);
808 result
= isc_buffer_allocate(mctx
, &request
->query
,
809 r
.length
+ (tcp
? 2 : 0));
810 if (result
!= ISC_R_SUCCESS
)
813 isc_buffer_putuint16(request
->query
, (isc_uint16_t
)r
.length
);
814 result
= isc_buffer_copyregion(request
->query
, &r
);
815 if (result
!= ISC_R_SUCCESS
)
818 /* Add message ID. */
819 isc_buffer_usedregion(request
->query
, &r
);
821 isc_region_consume(&r
, 2);
822 r
.base
[0] = (id
>>8) & 0xff;
823 r
.base
[1] = id
& 0xff;
825 LOCK(&requestmgr
->lock
);
826 if (requestmgr
->exiting
) {
827 UNLOCK(&requestmgr
->lock
);
828 result
= ISC_R_SHUTTINGDOWN
;
831 requestmgr_attach(requestmgr
, &request
->requestmgr
);
832 request
->hash
= mgr_gethash(requestmgr
);
833 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
834 UNLOCK(&requestmgr
->lock
);
836 result
= set_timer(request
->timer
, timeout
, tcp
? 0 : udptimeout
);
837 if (result
!= ISC_R_SUCCESS
)
840 request
->destaddr
= *destaddr
;
842 result
= isc_socket_connect(socket
, destaddr
, task
,
843 req_connected
, request
);
844 if (result
!= ISC_R_SUCCESS
)
846 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
848 result
= req_send(request
, task
, destaddr
);
849 if (result
!= ISC_R_SUCCESS
)
853 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
856 return (ISC_R_SUCCESS
);
859 LOCK(&requestmgr
->lock
);
860 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
861 UNLOCK(&requestmgr
->lock
);
865 isc_task_detach(&tclone
);
866 req_destroy(request
);
867 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
868 dns_result_totext(result
));
873 dns_request_create(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
874 isc_sockaddr_t
*address
, unsigned int options
,
876 unsigned int timeout
, isc_task_t
*task
,
877 isc_taskaction_t action
, void *arg
,
878 dns_request_t
**requestp
)
880 return (dns_request_createvia4(requestmgr
, message
, NULL
, address
,
881 -1, options
, key
, timeout
, 0, 0, task
,
882 action
, arg
, requestp
));
886 dns_request_createvia(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
887 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
888 unsigned int options
, dns_tsigkey_t
*key
,
889 unsigned int timeout
, isc_task_t
*task
,
890 isc_taskaction_t action
, void *arg
,
891 dns_request_t
**requestp
)
893 return(dns_request_createvia4(requestmgr
, message
, srcaddr
, destaddr
,
894 -1, options
, key
, timeout
, 0, 0, task
,
895 action
, arg
, requestp
));
899 dns_request_createvia2(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
900 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
901 unsigned int options
, dns_tsigkey_t
*key
,
902 unsigned int timeout
, unsigned int udptimeout
,
903 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
904 dns_request_t
**requestp
)
906 unsigned int udpretries
= 0;
909 udpretries
= timeout
/ udptimeout
;
910 return (dns_request_createvia4(requestmgr
, message
, srcaddr
, destaddr
,
911 -1, options
, key
, timeout
, udptimeout
,
912 udpretries
, task
, action
, arg
,
917 dns_request_createvia3(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
918 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
919 unsigned int options
, dns_tsigkey_t
*key
,
920 unsigned int timeout
, unsigned int udptimeout
,
921 unsigned int udpretries
, isc_task_t
*task
,
922 isc_taskaction_t action
, void *arg
,
923 dns_request_t
**requestp
)
925 return (dns_request_createvia4(requestmgr
, message
, srcaddr
, destaddr
,
926 -1, options
, key
, timeout
, udptimeout
,
927 udpretries
, task
, action
, arg
,
932 dns_request_createvia4(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
933 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
934 isc_dscp_t dscp
, unsigned int options
,
935 dns_tsigkey_t
*key
, unsigned int timeout
,
936 unsigned int udptimeout
, unsigned int udpretries
,
937 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
938 dns_request_t
**requestp
)
940 dns_request_t
*request
= NULL
;
941 isc_task_t
*tclone
= NULL
;
942 isc_socket_t
*socket
= NULL
;
947 isc_boolean_t setkey
= ISC_TRUE
;
949 REQUIRE(VALID_REQUESTMGR(requestmgr
));
950 REQUIRE(message
!= NULL
);
951 REQUIRE(destaddr
!= NULL
);
952 REQUIRE(task
!= NULL
);
953 REQUIRE(action
!= NULL
);
954 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
955 REQUIRE(timeout
> 0);
957 mctx
= requestmgr
->mctx
;
959 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
961 if (srcaddr
!= NULL
&&
962 isc_sockaddr_pf(srcaddr
) != isc_sockaddr_pf(destaddr
))
963 return (ISC_R_FAMILYMISMATCH
);
965 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
966 return (DNS_R_BLACKHOLED
);
969 result
= new_request(mctx
, &request
);
970 if (result
!= ISC_R_SUCCESS
)
973 if (udptimeout
== 0 && udpretries
!= 0) {
974 udptimeout
= timeout
/ (udpretries
+ 1);
978 request
->udpcount
= udpretries
;
979 request
->dscp
= dscp
;
982 * Create timer now. We will set it below once.
984 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
985 NULL
, NULL
, task
, req_timeout
, request
,
987 if (result
!= ISC_R_SUCCESS
)
990 request
->event
= (dns_requestevent_t
*)
991 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
992 action
, arg
, sizeof(dns_requestevent_t
));
993 if (request
->event
== NULL
) {
994 result
= ISC_R_NOMEMORY
;
997 isc_task_attach(task
, &tclone
);
998 request
->event
->ev_sender
= task
;
999 request
->event
->request
= request
;
1000 request
->event
->result
= ISC_R_FAILURE
;
1002 dns_tsigkey_attach(key
, &request
->tsigkey
);
1005 tcp
= ISC_TF((options
& DNS_REQUESTOPT_TCP
) != 0);
1006 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
, dscp
,
1007 &request
->dispatch
);
1008 if (result
!= ISC_R_SUCCESS
)
1011 result
= dns_dispatch_addresponse2(request
->dispatch
, destaddr
, task
,
1012 req_response
, request
, &id
,
1013 &request
->dispentry
,
1014 requestmgr
->socketmgr
);
1015 if (result
!= ISC_R_SUCCESS
)
1017 socket
= req_getsocket(request
);
1018 INSIST(socket
!= NULL
);
1022 result
= dns_message_settsigkey(message
, request
->tsigkey
);
1023 if (result
!= ISC_R_SUCCESS
)
1026 result
= req_render(message
, &request
->query
, options
, mctx
);
1027 if (result
== DNS_R_USETCP
&&
1028 (options
& DNS_REQUESTOPT_TCP
) == 0) {
1030 * Try again using TCP.
1032 dns_message_renderreset(message
);
1033 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1034 dns_dispatch_detach(&request
->dispatch
);
1036 options
|= DNS_REQUESTOPT_TCP
;
1040 if (result
!= ISC_R_SUCCESS
)
1043 result
= dns_message_getquerytsig(message
, mctx
, &request
->tsig
);
1044 if (result
!= ISC_R_SUCCESS
)
1047 LOCK(&requestmgr
->lock
);
1048 if (requestmgr
->exiting
) {
1049 UNLOCK(&requestmgr
->lock
);
1050 result
= ISC_R_SHUTTINGDOWN
;
1053 requestmgr_attach(requestmgr
, &request
->requestmgr
);
1054 request
->hash
= mgr_gethash(requestmgr
);
1055 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
1056 UNLOCK(&requestmgr
->lock
);
1058 result
= set_timer(request
->timer
, timeout
, tcp
? 0 : udptimeout
);
1059 if (result
!= ISC_R_SUCCESS
)
1062 request
->destaddr
= *destaddr
;
1064 result
= isc_socket_connect(socket
, destaddr
, task
,
1065 req_connected
, request
);
1066 if (result
!= ISC_R_SUCCESS
)
1068 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
1070 result
= req_send(request
, task
, destaddr
);
1071 if (result
!= ISC_R_SUCCESS
)
1075 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
1077 *requestp
= request
;
1078 return (ISC_R_SUCCESS
);
1081 LOCK(&requestmgr
->lock
);
1082 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
1083 UNLOCK(&requestmgr
->lock
);
1087 isc_task_detach(&tclone
);
1088 req_destroy(request
);
1089 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
1090 dns_result_totext(result
));
1095 req_render(dns_message_t
*message
, isc_buffer_t
**bufferp
,
1096 unsigned int options
, isc_mem_t
*mctx
)
1098 isc_buffer_t
*buf1
= NULL
;
1099 isc_buffer_t
*buf2
= NULL
;
1100 isc_result_t result
;
1102 isc_boolean_t tcp
= ISC_FALSE
;
1103 dns_compress_t cctx
;
1104 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
1106 REQUIRE(bufferp
!= NULL
&& *bufferp
== NULL
);
1108 req_log(ISC_LOG_DEBUG(3), "request_render");
1111 * Create buffer able to hold largest possible message.
1113 result
= isc_buffer_allocate(mctx
, &buf1
, 65535);
1114 if (result
!= ISC_R_SUCCESS
)
1117 result
= dns_compress_init(&cctx
, -1, mctx
);
1118 if (result
!= ISC_R_SUCCESS
)
1120 cleanup_cctx
= ISC_TRUE
;
1122 if ((options
& DNS_REQUESTOPT_CASE
) != 0)
1123 dns_compress_setsensitive(&cctx
, ISC_TRUE
);
1128 result
= dns_message_renderbegin(message
, &cctx
, buf1
);
1129 if (result
!= ISC_R_SUCCESS
)
1131 result
= dns_message_rendersection(message
, DNS_SECTION_QUESTION
, 0);
1132 if (result
!= ISC_R_SUCCESS
)
1134 result
= dns_message_rendersection(message
, DNS_SECTION_ANSWER
, 0);
1135 if (result
!= ISC_R_SUCCESS
)
1137 result
= dns_message_rendersection(message
, DNS_SECTION_AUTHORITY
, 0);
1138 if (result
!= ISC_R_SUCCESS
)
1140 result
= dns_message_rendersection(message
, DNS_SECTION_ADDITIONAL
, 0);
1141 if (result
!= ISC_R_SUCCESS
)
1143 result
= dns_message_renderend(message
);
1144 if (result
!= ISC_R_SUCCESS
)
1147 dns_compress_invalidate(&cctx
);
1148 cleanup_cctx
= ISC_FALSE
;
1151 * Copy rendered message to exact sized buffer.
1153 isc_buffer_usedregion(buf1
, &r
);
1154 if ((options
& DNS_REQUESTOPT_TCP
) != 0) {
1156 } else if (r
.length
> 512) {
1157 result
= DNS_R_USETCP
;
1160 result
= isc_buffer_allocate(mctx
, &buf2
, r
.length
+ (tcp
? 2 : 0));
1161 if (result
!= ISC_R_SUCCESS
)
1164 isc_buffer_putuint16(buf2
, (isc_uint16_t
)r
.length
);
1165 result
= isc_buffer_copyregion(buf2
, &r
);
1166 if (result
!= ISC_R_SUCCESS
)
1170 * Cleanup and return.
1172 isc_buffer_free(&buf1
);
1174 return (ISC_R_SUCCESS
);
1177 dns_message_renderreset(message
);
1179 isc_buffer_free(&buf1
);
1181 isc_buffer_free(&buf2
);
1183 dns_compress_invalidate(&cctx
);
1189 * If this request is no longer waiting for events,
1190 * send the completion event. This will ultimately
1191 * cause the request to be destroyed.
1194 * 'request' is locked by the caller.
1197 send_if_done(dns_request_t
*request
, isc_result_t result
) {
1198 if (request
->event
!= NULL
&& !request
->canceling
)
1199 req_sendevent(request
, result
);
1203 * Handle the control event.
1206 do_cancel(isc_task_t
*task
, isc_event_t
*event
) {
1207 dns_request_t
*request
= event
->ev_arg
;
1209 INSIST(event
->ev_type
== DNS_EVENT_REQUESTCONTROL
);
1210 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1211 request
->canceling
= ISC_FALSE
;
1212 if (!DNS_REQUEST_CANCELED(request
))
1213 req_cancel(request
);
1214 send_if_done(request
, ISC_R_CANCELED
);
1215 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1219 dns_request_cancel(dns_request_t
*request
) {
1220 REQUIRE(VALID_REQUEST(request
));
1222 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request
);
1224 REQUIRE(VALID_REQUEST(request
));
1226 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1227 if (!request
->canceling
&& !DNS_REQUEST_CANCELED(request
)) {
1228 isc_event_t
*ev
= &request
->ctlevent
;
1229 isc_task_send(request
->event
->ev_sender
, &ev
);
1230 request
->canceling
= ISC_TRUE
;
1232 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1236 dns_request_getresponse(dns_request_t
*request
, dns_message_t
*message
,
1237 unsigned int options
)
1239 isc_result_t result
;
1241 REQUIRE(VALID_REQUEST(request
));
1242 REQUIRE(request
->answer
!= NULL
);
1244 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1247 result
= dns_message_setquerytsig(message
, request
->tsig
);
1248 if (result
!= ISC_R_SUCCESS
)
1250 result
= dns_message_settsigkey(message
, request
->tsigkey
);
1251 if (result
!= ISC_R_SUCCESS
)
1253 result
= dns_message_parse(message
, request
->answer
, options
);
1254 if (result
!= ISC_R_SUCCESS
)
1256 if (request
->tsigkey
!= NULL
)
1257 result
= dns_tsig_verify(request
->answer
, message
, NULL
, NULL
);
1262 dns_request_usedtcp(dns_request_t
*request
) {
1263 REQUIRE(VALID_REQUEST(request
));
1265 return (ISC_TF((request
->flags
& DNS_REQUEST_F_TCP
) != 0));
1269 dns_request_destroy(dns_request_t
**requestp
) {
1270 dns_request_t
*request
;
1272 REQUIRE(requestp
!= NULL
&& VALID_REQUEST(*requestp
));
1274 request
= *requestp
;
1276 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request
);
1278 LOCK(&request
->requestmgr
->lock
);
1279 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1280 ISC_LIST_UNLINK(request
->requestmgr
->requests
, request
, link
);
1281 INSIST(!DNS_REQUEST_CONNECTING(request
));
1282 INSIST(!DNS_REQUEST_SENDING(request
));
1283 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1284 UNLOCK(&request
->requestmgr
->lock
);
1287 * These should have been cleaned up by req_cancel() before
1288 * the completion event was sent.
1290 INSIST(!ISC_LINK_LINKED(request
, link
));
1291 INSIST(request
->dispentry
== NULL
);
1292 INSIST(request
->dispatch
== NULL
);
1293 INSIST(request
->timer
== NULL
);
1295 req_destroy(request
);
1301 *** Private: request.
1304 static isc_socket_t
*
1305 req_getsocket(dns_request_t
*request
) {
1306 unsigned int dispattr
;
1307 isc_socket_t
*socket
;
1309 dispattr
= dns_dispatch_getattributes(request
->dispatch
);
1310 if ((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0) {
1311 INSIST(request
->dispentry
!= NULL
);
1312 socket
= dns_dispatch_getentrysocket(request
->dispentry
);
1314 socket
= dns_dispatch_getsocket(request
->dispatch
);
1320 req_connected(isc_task_t
*task
, isc_event_t
*event
) {
1321 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1322 isc_result_t result
;
1323 dns_request_t
*request
= event
->ev_arg
;
1325 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1326 REQUIRE(VALID_REQUEST(request
));
1327 REQUIRE(DNS_REQUEST_CONNECTING(request
));
1329 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request
);
1331 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1332 request
->flags
&= ~DNS_REQUEST_F_CONNECTING
;
1334 if (DNS_REQUEST_CANCELED(request
)) {
1336 * Send delayed event.
1338 if (DNS_REQUEST_TIMEDOUT(request
))
1339 send_if_done(request
, ISC_R_TIMEDOUT
);
1341 send_if_done(request
, ISC_R_CANCELED
);
1343 dns_dispatch_starttcp(request
->dispatch
);
1344 result
= sevent
->result
;
1345 if (result
== ISC_R_SUCCESS
)
1346 result
= req_send(request
, task
, NULL
);
1348 if (result
!= ISC_R_SUCCESS
) {
1349 req_cancel(request
);
1350 send_if_done(request
, ISC_R_CANCELED
);
1353 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1354 isc_event_free(&event
);
1358 req_senddone(isc_task_t
*task
, isc_event_t
*event
) {
1359 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1360 dns_request_t
*request
= event
->ev_arg
;
1362 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1363 REQUIRE(VALID_REQUEST(request
));
1364 REQUIRE(DNS_REQUEST_SENDING(request
));
1366 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request
);
1370 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1371 request
->flags
&= ~DNS_REQUEST_F_SENDING
;
1373 if (DNS_REQUEST_CANCELED(request
)) {
1375 * Send delayed event.
1377 if (DNS_REQUEST_TIMEDOUT(request
))
1378 send_if_done(request
, ISC_R_TIMEDOUT
);
1380 send_if_done(request
, ISC_R_CANCELED
);
1381 } else if (sevent
->result
!= ISC_R_SUCCESS
) {
1382 req_cancel(request
);
1383 send_if_done(request
, ISC_R_CANCELED
);
1385 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1387 isc_event_free(&event
);
1391 req_response(isc_task_t
*task
, isc_event_t
*event
) {
1392 isc_result_t result
;
1393 dns_request_t
*request
= event
->ev_arg
;
1394 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
1397 REQUIRE(VALID_REQUEST(request
));
1398 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
1402 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request
,
1403 dns_result_totext(devent
->result
));
1405 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1406 result
= devent
->result
;
1407 if (result
!= ISC_R_SUCCESS
)
1411 * Copy buffer to request.
1413 isc_buffer_usedregion(&devent
->buffer
, &r
);
1414 result
= isc_buffer_allocate(request
->mctx
, &request
->answer
,
1416 if (result
!= ISC_R_SUCCESS
)
1418 result
= isc_buffer_copyregion(request
->answer
, &r
);
1419 if (result
!= ISC_R_SUCCESS
)
1420 isc_buffer_free(&request
->answer
);
1425 dns_dispatch_removeresponse(&request
->dispentry
, &devent
);
1426 req_cancel(request
);
1428 * Send completion event.
1430 send_if_done(request
, result
);
1431 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1435 req_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1436 dns_request_t
*request
= event
->ev_arg
;
1437 isc_result_t result
;
1439 REQUIRE(VALID_REQUEST(request
));
1441 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request
);
1444 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1445 if (event
->ev_type
== ISC_TIMEREVENT_TICK
&&
1446 request
->udpcount
-- != 0) {
1447 if (! DNS_REQUEST_SENDING(request
)) {
1448 result
= req_send(request
, task
, &request
->destaddr
);
1449 if (result
!= ISC_R_SUCCESS
) {
1450 req_cancel(request
);
1451 send_if_done(request
, result
);
1455 request
->flags
|= DNS_REQUEST_F_TIMEDOUT
;
1456 req_cancel(request
);
1457 send_if_done(request
, ISC_R_TIMEDOUT
);
1459 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1460 isc_event_free(&event
);
1464 req_sendevent(dns_request_t
*request
, isc_result_t result
) {
1467 REQUIRE(VALID_REQUEST(request
));
1469 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request
);
1472 * Lock held by caller.
1474 task
= request
->event
->ev_sender
;
1475 request
->event
->ev_sender
= request
;
1476 request
->event
->result
= result
;
1477 isc_task_sendanddetach(&task
, (isc_event_t
**)(void *)&request
->event
);
1481 req_destroy(dns_request_t
*request
) {
1484 REQUIRE(VALID_REQUEST(request
));
1486 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request
);
1489 if (request
->query
!= NULL
)
1490 isc_buffer_free(&request
->query
);
1491 if (request
->answer
!= NULL
)
1492 isc_buffer_free(&request
->answer
);
1493 if (request
->event
!= NULL
)
1494 isc_event_free((isc_event_t
**)(void *)&request
->event
);
1495 if (request
->dispentry
!= NULL
)
1496 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1497 if (request
->dispatch
!= NULL
)
1498 dns_dispatch_detach(&request
->dispatch
);
1499 if (request
->timer
!= NULL
)
1500 isc_timer_detach(&request
->timer
);
1501 if (request
->tsig
!= NULL
)
1502 isc_buffer_free(&request
->tsig
);
1503 if (request
->tsigkey
!= NULL
)
1504 dns_tsigkey_detach(&request
->tsigkey
);
1505 if (request
->requestmgr
!= NULL
)
1506 requestmgr_detach(&request
->requestmgr
);
1507 mctx
= request
->mctx
;
1508 isc_mem_put(mctx
, request
, sizeof(*request
));
1509 isc_mem_detach(&mctx
);
1513 * Stop the current request. Must be called from the request's task.
1516 req_cancel(dns_request_t
*request
) {
1517 isc_socket_t
*socket
;
1518 unsigned int dispattr
;
1520 REQUIRE(VALID_REQUEST(request
));
1522 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request
);
1525 * Lock held by caller.
1527 request
->flags
|= DNS_REQUEST_F_CANCELED
;
1529 if (request
->timer
!= NULL
)
1530 isc_timer_detach(&request
->timer
);
1531 dispattr
= dns_dispatch_getattributes(request
->dispatch
);
1533 if (DNS_REQUEST_CONNECTING(request
) || DNS_REQUEST_SENDING(request
)) {
1534 if ((dispattr
& DNS_DISPATCHATTR_EXCLUSIVE
) != 0) {
1535 if (request
->dispentry
!= NULL
) {
1536 socket
= dns_dispatch_getentrysocket(
1537 request
->dispentry
);
1540 socket
= dns_dispatch_getsocket(request
->dispatch
);
1541 if (DNS_REQUEST_CONNECTING(request
) && socket
!= NULL
)
1542 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_CONNECT
);
1543 if (DNS_REQUEST_SENDING(request
) && socket
!= NULL
)
1544 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_SEND
);
1546 if (request
->dispentry
!= NULL
)
1547 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1548 dns_dispatch_detach(&request
->dispatch
);
1552 req_log(int level
, const char *fmt
, ...) {
1556 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
1557 DNS_LOGMODULE_REQUEST
, level
, fmt
, ap
);