2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: request.c,v 1.64.2.2 2004/03/09 06:11:06 marka Exp $ */
22 #include <isc/magic.h>
25 #include <isc/timer.h>
29 #include <dns/compress.h>
30 #include <dns/dispatch.h>
31 #include <dns/events.h>
33 #include <dns/message.h>
34 #include <dns/rdata.h>
35 #include <dns/rdatastruct.h>
36 #include <dns/request.h>
37 #include <dns/result.h>
40 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
41 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
43 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
44 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
46 typedef ISC_LIST(dns_request_t
) dns_requestlist_t
;
48 #define DNS_REQUEST_NLOCKS 7
50 struct dns_requestmgr
{
58 isc_timermgr_t
*timermgr
;
59 isc_socketmgr_t
*socketmgr
;
60 isc_taskmgr_t
*taskmgr
;
61 dns_dispatchmgr_t
*dispatchmgr
;
62 dns_dispatch_t
*dispatchv4
;
63 dns_dispatch_t
*dispatchv6
;
64 isc_boolean_t exiting
;
65 isc_eventlist_t whenshutdown
;
67 isc_mutex_t locks
[DNS_REQUEST_NLOCKS
];
68 dns_requestlist_t requests
;
76 ISC_LINK(dns_request_t
) link
;
79 dns_requestevent_t
*event
;
80 dns_dispatch_t
*dispatch
;
81 dns_dispentry_t
*dispentry
;
83 dns_requestmgr_t
*requestmgr
;
85 dns_tsigkey_t
*tsigkey
;
87 isc_boolean_t canceling
; /* ctlevent outstanding */
90 #define DNS_REQUEST_F_CONNECTING 0x0001
91 #define DNS_REQUEST_F_SENDING 0x0002
92 #define DNS_REQUEST_F_CANCELED 0x0004 /* ctlevent received, or otherwise
93 synchronously canceled */
94 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /* cancelled due to a timeout */
95 #define DNS_REQUEST_F_TCP 0x0010 /* This request used TCP */
96 #define DNS_REQUEST_CANCELED(r) \
97 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
98 #define DNS_REQUEST_CONNECTING(r) \
99 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
100 #define DNS_REQUEST_SENDING(r) \
101 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
102 #define DNS_REQUEST_TIMEDOUT(r) \
103 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
110 static void mgr_destroy(dns_requestmgr_t
*requestmgr
);
111 static void mgr_shutdown(dns_requestmgr_t
*requestmgr
);
112 static unsigned int mgr_gethash(dns_requestmgr_t
*requestmgr
);
113 static void send_shutdown_events(dns_requestmgr_t
*requestmgr
);
115 static isc_result_t
req_render(dns_message_t
*message
, isc_buffer_t
**buffer
,
116 unsigned int options
, isc_mem_t
*mctx
);
117 static void req_senddone(isc_task_t
*task
, isc_event_t
*event
);
118 static void req_response(isc_task_t
*task
, isc_event_t
*event
);
119 static void req_timeout(isc_task_t
*task
, isc_event_t
*event
);
120 static void req_connected(isc_task_t
*task
, isc_event_t
*event
);
121 static void req_sendevent(dns_request_t
*request
, isc_result_t result
);
122 static void req_cancel(dns_request_t
*request
);
123 static void req_destroy(dns_request_t
*request
);
124 static void req_log(int level
, const char *fmt
, ...) ISC_FORMAT_PRINTF(2, 3);
125 static void do_cancel(isc_task_t
*task
, isc_event_t
*event
);
132 dns_requestmgr_create(isc_mem_t
*mctx
,
133 isc_timermgr_t
*timermgr
,
134 isc_socketmgr_t
*socketmgr
,
135 isc_taskmgr_t
*taskmgr
,
136 dns_dispatchmgr_t
*dispatchmgr
,
137 dns_dispatch_t
*dispatchv4
,
138 dns_dispatch_t
*dispatchv6
,
139 dns_requestmgr_t
**requestmgrp
)
141 dns_requestmgr_t
*requestmgr
;
142 isc_socket_t
*socket
;
146 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
148 REQUIRE(requestmgrp
!= NULL
&& *requestmgrp
== NULL
);
149 REQUIRE(timermgr
!= NULL
);
150 REQUIRE(socketmgr
!= NULL
);
151 REQUIRE(taskmgr
!= NULL
);
152 REQUIRE(dispatchmgr
!= NULL
);
153 if (dispatchv4
!= NULL
) {
154 socket
= dns_dispatch_getsocket(dispatchv4
);
155 REQUIRE(isc_socket_gettype(socket
) == isc_sockettype_udp
);
157 if (dispatchv6
!= NULL
) {
158 socket
= dns_dispatch_getsocket(dispatchv6
);
159 REQUIRE(isc_socket_gettype(socket
) == isc_sockettype_udp
);
162 requestmgr
= isc_mem_get(mctx
, sizeof(*requestmgr
));
163 if (requestmgr
== NULL
)
164 return (ISC_R_NOMEMORY
);
166 result
= isc_mutex_init(&requestmgr
->lock
);
167 if (result
!= ISC_R_SUCCESS
) {
168 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
171 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++) {
172 result
= isc_mutex_init(&requestmgr
->locks
[i
]);
173 if (result
!= ISC_R_SUCCESS
) {
175 DESTROYLOCK(&requestmgr
->locks
[i
]);
176 DESTROYLOCK(&requestmgr
->lock
);
177 isc_mem_put(mctx
, requestmgr
, sizeof(*requestmgr
));
181 requestmgr
->timermgr
= timermgr
;
182 requestmgr
->socketmgr
= socketmgr
;
183 requestmgr
->taskmgr
= taskmgr
;
184 requestmgr
->dispatchmgr
= dispatchmgr
;
185 requestmgr
->dispatchv4
= NULL
;
186 if (dispatchv4
!= NULL
)
187 dns_dispatch_attach(dispatchv4
, &requestmgr
->dispatchv4
);
188 requestmgr
->dispatchv6
= NULL
;
189 if (dispatchv6
!= NULL
)
190 dns_dispatch_attach(dispatchv6
, &requestmgr
->dispatchv6
);
191 requestmgr
->mctx
= NULL
;
192 isc_mem_attach(mctx
, &requestmgr
->mctx
);
193 requestmgr
->eref
= 1; /* implict attach */
194 requestmgr
->iref
= 0;
195 ISC_LIST_INIT(requestmgr
->whenshutdown
);
196 ISC_LIST_INIT(requestmgr
->requests
);
197 requestmgr
->exiting
= ISC_FALSE
;
198 requestmgr
->hash
= 0;
199 requestmgr
->magic
= REQUESTMGR_MAGIC
;
201 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr
);
203 *requestmgrp
= requestmgr
;
204 return (ISC_R_SUCCESS
);
208 dns_requestmgr_whenshutdown(dns_requestmgr_t
*requestmgr
, isc_task_t
*task
,
209 isc_event_t
**eventp
)
214 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
216 REQUIRE(VALID_REQUESTMGR(requestmgr
));
217 REQUIRE(eventp
!= NULL
);
222 LOCK(&requestmgr
->lock
);
224 if (requestmgr
->exiting
) {
226 * We're already shutdown. Send the event.
228 event
->ev_sender
= requestmgr
;
229 isc_task_send(task
, &event
);
232 isc_task_attach(task
, &clone
);
233 event
->ev_sender
= clone
;
234 ISC_LIST_APPEND(requestmgr
->whenshutdown
, event
, ev_link
);
236 UNLOCK(&requestmgr
->lock
);
240 dns_requestmgr_shutdown(dns_requestmgr_t
*requestmgr
) {
242 REQUIRE(VALID_REQUESTMGR(requestmgr
));
244 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr
);
246 LOCK(&requestmgr
->lock
);
247 mgr_shutdown(requestmgr
);
248 UNLOCK(&requestmgr
->lock
);
252 mgr_shutdown(dns_requestmgr_t
*requestmgr
) {
253 dns_request_t
*request
;
258 if (!requestmgr
->exiting
) {
259 requestmgr
->exiting
= ISC_TRUE
;
260 for (request
= ISC_LIST_HEAD(requestmgr
->requests
);
262 request
= ISC_LIST_NEXT(request
, link
)) {
263 dns_request_cancel(request
);
265 if (requestmgr
->iref
== 0) {
266 INSIST(ISC_LIST_EMPTY(requestmgr
->requests
));
267 send_shutdown_events(requestmgr
);
273 requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
279 REQUIRE(VALID_REQUESTMGR(source
));
280 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
282 REQUIRE(!source
->exiting
);
287 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
288 source
, source
->eref
, source
->iref
);
292 requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
293 dns_requestmgr_t
*requestmgr
;
294 isc_boolean_t need_destroy
= ISC_FALSE
;
296 REQUIRE(requestmgrp
!= NULL
);
297 requestmgr
= *requestmgrp
;
298 REQUIRE(VALID_REQUESTMGR(requestmgr
));
301 LOCK(&requestmgr
->lock
);
302 INSIST(requestmgr
->iref
> 0);
305 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
306 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
308 if (requestmgr
->iref
== 0 && requestmgr
->exiting
) {
309 INSIST(ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
310 send_shutdown_events(requestmgr
);
311 if (requestmgr
->eref
== 0)
312 need_destroy
= ISC_TRUE
;
314 UNLOCK(&requestmgr
->lock
);
317 mgr_destroy(requestmgr
);
321 dns_requestmgr_attach(dns_requestmgr_t
*source
, dns_requestmgr_t
**targetp
) {
323 REQUIRE(VALID_REQUESTMGR(source
));
324 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
325 REQUIRE(!source
->exiting
);
330 UNLOCK(&source
->lock
);
332 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
333 source
, source
->eref
, source
->iref
);
337 dns_requestmgr_detach(dns_requestmgr_t
**requestmgrp
) {
338 dns_requestmgr_t
*requestmgr
;
339 isc_boolean_t need_destroy
= ISC_FALSE
;
341 REQUIRE(requestmgrp
!= NULL
);
342 requestmgr
= *requestmgrp
;
343 REQUIRE(VALID_REQUESTMGR(requestmgr
));
345 LOCK(&requestmgr
->lock
);
346 INSIST(requestmgr
->eref
> 0);
349 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
350 requestmgr
, requestmgr
->eref
, requestmgr
->iref
);
352 if (requestmgr
->eref
== 0 && requestmgr
->iref
== 0) {
353 INSIST(requestmgr
->exiting
&&
354 ISC_LIST_HEAD(requestmgr
->requests
) == NULL
);
355 need_destroy
= ISC_TRUE
;
357 UNLOCK(&requestmgr
->lock
);
360 mgr_destroy(requestmgr
);
366 send_shutdown_events(dns_requestmgr_t
*requestmgr
) {
367 isc_event_t
*event
, *next_event
;
370 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr
);
373 * Caller must be holding the manager lock.
375 for (event
= ISC_LIST_HEAD(requestmgr
->whenshutdown
);
377 event
= next_event
) {
378 next_event
= ISC_LIST_NEXT(event
, ev_link
);
379 ISC_LIST_UNLINK(requestmgr
->whenshutdown
, event
, ev_link
);
380 etask
= event
->ev_sender
;
381 event
->ev_sender
= requestmgr
;
382 isc_task_sendanddetach(&etask
, &event
);
387 mgr_destroy(dns_requestmgr_t
*requestmgr
) {
391 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
393 REQUIRE(requestmgr
->eref
== 0);
394 REQUIRE(requestmgr
->iref
== 0);
396 DESTROYLOCK(&requestmgr
->lock
);
397 for (i
= 0; i
< DNS_REQUEST_NLOCKS
; i
++)
398 DESTROYLOCK(&requestmgr
->locks
[i
]);
399 if (requestmgr
->dispatchv4
!= NULL
)
400 dns_dispatch_detach(&requestmgr
->dispatchv4
);
401 if (requestmgr
->dispatchv6
!= NULL
)
402 dns_dispatch_detach(&requestmgr
->dispatchv6
);
403 requestmgr
->magic
= 0;
404 mctx
= requestmgr
->mctx
;
405 isc_mem_put(mctx
, requestmgr
, sizeof *requestmgr
);
406 isc_mem_detach(&mctx
);
410 mgr_gethash(dns_requestmgr_t
*requestmgr
) {
411 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
416 return (requestmgr
->hash
% DNS_REQUEST_NLOCKS
);
419 static inline isc_result_t
420 req_send(dns_request_t
*request
, isc_task_t
*task
, isc_sockaddr_t
*address
) {
422 isc_socket_t
*socket
;
425 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request
);
427 REQUIRE(VALID_REQUEST(request
));
428 socket
= dns_dispatch_getsocket(request
->dispatch
);
429 isc_buffer_usedregion(request
->query
, &r
);
430 result
= isc_socket_sendto(socket
, &r
, task
, req_senddone
,
431 request
, address
, NULL
);
432 if (result
== ISC_R_SUCCESS
)
433 request
->flags
|= DNS_REQUEST_F_SENDING
;
438 new_request(isc_mem_t
*mctx
, dns_request_t
**requestp
) {
439 dns_request_t
*request
;
441 request
= isc_mem_get(mctx
, sizeof(*request
));
443 return (ISC_R_NOMEMORY
);
449 request
->mctx
= NULL
;
451 ISC_LINK_INIT(request
, link
);
452 request
->query
= NULL
;
453 request
->answer
= NULL
;
454 request
->event
= NULL
;
455 request
->dispatch
= NULL
;
456 request
->dispentry
= NULL
;
457 request
->timer
= NULL
;
458 request
->requestmgr
= NULL
;
459 request
->tsig
= NULL
;
460 request
->tsigkey
= NULL
;
461 ISC_EVENT_INIT(&request
->ctlevent
, sizeof(request
->ctlevent
), 0, NULL
,
462 DNS_EVENT_REQUESTCONTROL
, do_cancel
, request
, NULL
,
464 request
->canceling
= ISC_FALSE
;
466 isc_mem_attach(mctx
, &request
->mctx
);
468 request
->magic
= REQUEST_MAGIC
;
470 return (ISC_R_SUCCESS
);
475 isblackholed(dns_dispatchmgr_t
*dispatchmgr
, isc_sockaddr_t
*destaddr
) {
476 dns_acl_t
*blackhole
;
477 isc_netaddr_t netaddr
;
479 isc_boolean_t drop
= ISC_FALSE
;
480 char netaddrstr
[ISC_NETADDR_FORMATSIZE
];
482 blackhole
= dns_dispatchmgr_getblackhole(dispatchmgr
);
483 if (blackhole
!= NULL
) {
484 isc_netaddr_fromsockaddr(&netaddr
, destaddr
);
485 if (dns_acl_match(&netaddr
, NULL
, blackhole
,
486 NULL
, &match
, NULL
) == ISC_R_SUCCESS
&&
491 isc_netaddr_format(&netaddr
, netaddrstr
, sizeof(netaddrstr
));
492 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr
);
498 create_tcp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
499 isc_sockaddr_t
*destaddr
, dns_dispatch_t
**dispatchp
)
502 isc_socket_t
*socket
= NULL
;
505 isc_sockaddr_t bind_any
;
507 result
= isc_socket_create(requestmgr
->socketmgr
,
508 isc_sockaddr_pf(destaddr
),
509 isc_sockettype_tcp
, &socket
);
510 if (result
!= ISC_R_SUCCESS
)
512 if (srcaddr
== NULL
) {
513 isc_sockaddr_anyofpf(&bind_any
,
514 isc_sockaddr_pf(destaddr
));
515 result
= isc_socket_bind(socket
, &bind_any
);
518 isc_sockaddr_setport(&src
, 0);
519 result
= isc_socket_bind(socket
, &src
);
521 if (result
!= ISC_R_SUCCESS
)
524 attrs
|= DNS_DISPATCHATTR_TCP
;
525 attrs
|= DNS_DISPATCHATTR_PRIVATE
;
526 if (isc_sockaddr_pf(destaddr
) == AF_INET
)
527 attrs
|= DNS_DISPATCHATTR_IPV4
;
529 attrs
|= DNS_DISPATCHATTR_IPV6
;
530 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
531 result
= dns_dispatch_createtcp(requestmgr
->dispatchmgr
,
532 socket
, requestmgr
->taskmgr
,
533 4096, 2, 1, 1, 3, attrs
,
536 isc_socket_detach(&socket
);
541 find_udp_dispatch(dns_requestmgr_t
*requestmgr
, isc_sockaddr_t
*srcaddr
,
542 isc_sockaddr_t
*destaddr
, dns_dispatch_t
**dispatchp
)
544 dns_dispatch_t
*disp
= NULL
;
545 unsigned int attrs
, attrmask
;
547 if (srcaddr
== NULL
) {
548 switch (isc_sockaddr_pf(destaddr
)) {
550 disp
= requestmgr
->dispatchv4
;
554 disp
= requestmgr
->dispatchv6
;
558 return (ISC_R_NOTIMPLEMENTED
);
561 return (ISC_R_FAMILYNOSUPPORT
);
562 dns_dispatch_attach(disp
, dispatchp
);
563 return (ISC_R_SUCCESS
);
566 attrs
|= DNS_DISPATCHATTR_UDP
;
567 switch (isc_sockaddr_pf(srcaddr
)) {
569 attrs
|= DNS_DISPATCHATTR_IPV4
;
573 attrs
|= DNS_DISPATCHATTR_IPV6
;
577 return (ISC_R_NOTIMPLEMENTED
);
580 attrmask
|= DNS_DISPATCHATTR_UDP
;
581 attrmask
|= DNS_DISPATCHATTR_TCP
;
582 attrmask
|= DNS_DISPATCHATTR_IPV4
;
583 attrmask
|= DNS_DISPATCHATTR_IPV6
;
584 return (dns_dispatch_getudp(requestmgr
->dispatchmgr
,
585 requestmgr
->socketmgr
,
588 1000, 32768, 16411, 16433,
594 get_dispatch(isc_boolean_t tcp
, dns_requestmgr_t
*requestmgr
,
595 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
596 dns_dispatch_t
**dispatchp
)
600 result
= create_tcp_dispatch(requestmgr
, srcaddr
,
601 destaddr
, dispatchp
);
603 result
= find_udp_dispatch(requestmgr
, srcaddr
,
604 destaddr
, dispatchp
);
609 set_timer(isc_timer_t
*timer
, unsigned int timeout
) {
611 isc_interval_t interval
;
614 isc_interval_set(&interval
, timeout
, 0);
615 result
= isc_time_nowplusinterval(&expires
, &interval
);
617 if (result
== ISC_R_SUCCESS
)
618 result
= isc_timer_reset(timer
, isc_timertype_once
, &expires
,
624 dns_request_createraw(dns_requestmgr_t
*requestmgr
, isc_buffer_t
*msgbuf
,
625 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
626 unsigned int options
, unsigned int timeout
,
627 isc_task_t
*task
, isc_taskaction_t action
, void *arg
,
628 dns_request_t
**requestp
)
630 dns_request_t
*request
= NULL
;
631 isc_task_t
*tclone
= NULL
;
632 isc_socket_t
*socket
= NULL
;
636 isc_boolean_t tcp
= ISC_FALSE
;
639 REQUIRE(VALID_REQUESTMGR(requestmgr
));
640 REQUIRE(msgbuf
!= NULL
);
641 REQUIRE(destaddr
!= NULL
);
642 REQUIRE(task
!= NULL
);
643 REQUIRE(action
!= NULL
);
644 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
645 REQUIRE(timeout
> 0);
647 REQUIRE(isc_sockaddr_pf(srcaddr
) == isc_sockaddr_pf(destaddr
));
649 mctx
= requestmgr
->mctx
;
651 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
653 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
654 return (DNS_R_BLACKHOLED
);
657 result
= new_request(mctx
, &request
);
658 if (result
!= ISC_R_SUCCESS
)
662 * Create timer now. We will set it below once.
664 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
665 NULL
, NULL
, task
, req_timeout
, request
,
667 if (result
!= ISC_R_SUCCESS
)
670 request
->event
= (dns_requestevent_t
*)
671 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
672 action
, arg
, sizeof (dns_requestevent_t
));
673 if (request
->event
== NULL
) {
674 result
= ISC_R_NOMEMORY
;
677 isc_task_attach(task
, &tclone
);
678 request
->event
->ev_sender
= task
;
679 request
->event
->request
= request
;
680 request
->event
->result
= ISC_R_FAILURE
;
682 isc_buffer_usedregion(msgbuf
, &r
);
683 if (r
.length
< DNS_MESSAGE_HEADERLEN
|| r
.length
> 65535) {
684 result
= DNS_R_FORMERR
;
688 if ((options
& DNS_REQUESTOPT_TCP
) != 0 || r
.length
> 512)
691 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
,
693 if (result
!= ISC_R_SUCCESS
)
696 socket
= dns_dispatch_getsocket(request
->dispatch
);
697 INSIST(socket
!= NULL
);
698 result
= dns_dispatch_addresponse(request
->dispatch
, destaddr
, task
,
699 req_response
, request
, &id
,
700 &request
->dispentry
);
701 if (result
!= ISC_R_SUCCESS
)
704 result
= isc_buffer_allocate(mctx
, &request
->query
,
705 r
.length
+ (tcp
? 2 : 0));
706 if (result
!= ISC_R_SUCCESS
)
709 isc_buffer_putuint16(request
->query
, (isc_uint16_t
)r
.length
);
710 result
= isc_buffer_copyregion(request
->query
, &r
);
711 if (result
!= ISC_R_SUCCESS
)
714 /* Add message ID. */
715 isc_buffer_usedregion(request
->query
, &r
);
717 isc_region_consume(&r
, 2);
718 r
.base
[0] = (id
>>8) & 0xff;
719 r
.base
[1] = id
& 0xff;
721 LOCK(&requestmgr
->lock
);
722 if (requestmgr
->exiting
) {
723 UNLOCK(&requestmgr
->lock
);
724 result
= ISC_R_SHUTTINGDOWN
;
727 requestmgr_attach(requestmgr
, &request
->requestmgr
);
728 request
->hash
= mgr_gethash(requestmgr
);
729 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
730 UNLOCK(&requestmgr
->lock
);
732 result
= set_timer(request
->timer
, timeout
);
733 if (result
!= ISC_R_SUCCESS
)
736 if ((options
& DNS_REQUESTOPT_TCP
) != 0) {
737 result
= isc_socket_connect(socket
, destaddr
, task
,
738 req_connected
, request
);
739 if (result
!= ISC_R_SUCCESS
)
741 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
743 result
= req_send(request
, task
, destaddr
);
744 if (result
!= ISC_R_SUCCESS
)
748 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
751 return (ISC_R_SUCCESS
);
754 LOCK(&requestmgr
->lock
);
755 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
756 UNLOCK(&requestmgr
->lock
);
760 isc_task_detach(&tclone
);
761 req_destroy(request
);
762 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
763 dns_result_totext(result
));
768 dns_request_create(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
769 isc_sockaddr_t
*address
, unsigned int options
,
771 unsigned int timeout
, isc_task_t
*task
,
772 isc_taskaction_t action
, void *arg
,
773 dns_request_t
**requestp
)
775 return (dns_request_createvia(requestmgr
, message
, NULL
, address
,
776 options
, key
, timeout
, task
, action
,
781 dns_request_createvia(dns_requestmgr_t
*requestmgr
, dns_message_t
*message
,
782 isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
783 unsigned int options
, dns_tsigkey_t
*key
,
784 unsigned int timeout
, isc_task_t
*task
,
785 isc_taskaction_t action
, void *arg
,
786 dns_request_t
**requestp
)
788 dns_request_t
*request
= NULL
;
789 isc_task_t
*tclone
= NULL
;
790 isc_socket_t
*socket
= NULL
;
795 isc_boolean_t setkey
= ISC_TRUE
;
797 REQUIRE(VALID_REQUESTMGR(requestmgr
));
798 REQUIRE(message
!= NULL
);
799 REQUIRE(destaddr
!= NULL
);
800 REQUIRE(task
!= NULL
);
801 REQUIRE(action
!= NULL
);
802 REQUIRE(requestp
!= NULL
&& *requestp
== NULL
);
803 REQUIRE(timeout
> 0);
805 REQUIRE(isc_sockaddr_pf(srcaddr
) == isc_sockaddr_pf(destaddr
));
807 mctx
= requestmgr
->mctx
;
809 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
811 if (isblackholed(requestmgr
->dispatchmgr
, destaddr
))
812 return (DNS_R_BLACKHOLED
);
815 result
= new_request(mctx
, &request
);
816 if (result
!= ISC_R_SUCCESS
)
820 * Create timer now. We will set it below once.
822 result
= isc_timer_create(requestmgr
->timermgr
, isc_timertype_inactive
,
823 NULL
, NULL
, task
, req_timeout
, request
,
825 if (result
!= ISC_R_SUCCESS
)
828 request
->event
= (dns_requestevent_t
*)
829 isc_event_allocate(mctx
, task
, DNS_EVENT_REQUESTDONE
,
830 action
, arg
, sizeof (dns_requestevent_t
));
831 if (request
->event
== NULL
) {
832 result
= ISC_R_NOMEMORY
;
835 isc_task_attach(task
, &tclone
);
836 request
->event
->ev_sender
= task
;
837 request
->event
->request
= request
;
838 request
->event
->result
= ISC_R_FAILURE
;
840 dns_tsigkey_attach(key
, &request
->tsigkey
);
843 tcp
= ISC_TF((options
& DNS_REQUESTOPT_TCP
) != 0);
844 result
= get_dispatch(tcp
, requestmgr
, srcaddr
, destaddr
,
846 if (result
!= ISC_R_SUCCESS
)
849 socket
= dns_dispatch_getsocket(request
->dispatch
);
850 INSIST(socket
!= NULL
);
851 result
= dns_dispatch_addresponse(request
->dispatch
, destaddr
, task
,
852 req_response
, request
, &id
,
853 &request
->dispentry
);
854 if (result
!= ISC_R_SUCCESS
)
859 dns_message_settsigkey(message
, request
->tsigkey
);
860 result
= req_render(message
, &request
->query
, options
, mctx
);
861 if (result
== DNS_R_USETCP
&&
862 (options
& DNS_REQUESTOPT_TCP
) == 0) {
864 * Try again using TCP.
866 dns_message_renderreset(message
);
867 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
868 dns_dispatch_detach(&request
->dispatch
);
870 options
|= DNS_REQUESTOPT_TCP
;
874 if (result
!= ISC_R_SUCCESS
)
877 result
= dns_message_getquerytsig(message
, mctx
, &request
->tsig
);
878 if (result
!= ISC_R_SUCCESS
)
881 LOCK(&requestmgr
->lock
);
882 if (requestmgr
->exiting
) {
883 UNLOCK(&requestmgr
->lock
);
884 result
= ISC_R_SHUTTINGDOWN
;
887 requestmgr_attach(requestmgr
, &request
->requestmgr
);
888 request
->hash
= mgr_gethash(requestmgr
);
889 ISC_LIST_APPEND(requestmgr
->requests
, request
, link
);
890 UNLOCK(&requestmgr
->lock
);
892 result
= set_timer(request
->timer
, timeout
);
893 if (result
!= ISC_R_SUCCESS
)
896 if ((options
& DNS_REQUESTOPT_TCP
) != 0) {
897 result
= isc_socket_connect(socket
, destaddr
, task
,
898 req_connected
, request
);
899 if (result
!= ISC_R_SUCCESS
)
901 request
->flags
|= DNS_REQUEST_F_CONNECTING
|DNS_REQUEST_F_TCP
;
903 result
= req_send(request
, task
, destaddr
);
904 if (result
!= ISC_R_SUCCESS
)
908 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
911 return (ISC_R_SUCCESS
);
914 LOCK(&requestmgr
->lock
);
915 ISC_LIST_UNLINK(requestmgr
->requests
, request
, link
);
916 UNLOCK(&requestmgr
->lock
);
920 isc_task_detach(&tclone
);
921 req_destroy(request
);
922 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
923 dns_result_totext(result
));
928 req_render(dns_message_t
*message
, isc_buffer_t
**bufferp
,
929 unsigned int options
, isc_mem_t
*mctx
)
931 isc_buffer_t
*buf1
= NULL
;
932 isc_buffer_t
*buf2
= NULL
;
935 isc_boolean_t tcp
= ISC_FALSE
;
937 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
939 REQUIRE(bufferp
!= NULL
&& *bufferp
== NULL
);
941 req_log(ISC_LOG_DEBUG(3), "request_render");
944 * Create buffer able to hold largest possible message.
946 result
= isc_buffer_allocate(mctx
, &buf1
, 65535);
947 if (result
!= ISC_R_SUCCESS
)
950 result
= dns_compress_init(&cctx
, -1, mctx
);
951 if (result
!= ISC_R_SUCCESS
)
953 cleanup_cctx
= ISC_TRUE
;
958 result
= dns_message_renderbegin(message
, &cctx
, buf1
);
959 if (result
!= ISC_R_SUCCESS
)
961 result
= dns_message_rendersection(message
, DNS_SECTION_QUESTION
, 0);
962 if (result
!= ISC_R_SUCCESS
)
964 result
= dns_message_rendersection(message
, DNS_SECTION_ANSWER
, 0);
965 if (result
!= ISC_R_SUCCESS
)
967 result
= dns_message_rendersection(message
, DNS_SECTION_AUTHORITY
, 0);
968 if (result
!= ISC_R_SUCCESS
)
970 result
= dns_message_rendersection(message
, DNS_SECTION_ADDITIONAL
, 0);
971 if (result
!= ISC_R_SUCCESS
)
973 result
= dns_message_renderend(message
);
974 if (result
!= ISC_R_SUCCESS
)
977 dns_compress_invalidate(&cctx
);
978 cleanup_cctx
= ISC_FALSE
;
981 * Copy rendered message to exact sized buffer.
983 isc_buffer_usedregion(buf1
, &r
);
984 if ((options
& DNS_REQUESTOPT_TCP
) != 0) {
986 } else if (r
.length
> 512) {
987 result
= DNS_R_USETCP
;
990 result
= isc_buffer_allocate(mctx
, &buf2
, r
.length
+ (tcp
? 2 : 0));
991 if (result
!= ISC_R_SUCCESS
)
994 isc_buffer_putuint16(buf2
, (isc_uint16_t
)r
.length
);
995 result
= isc_buffer_copyregion(buf2
, &r
);
996 if (result
!= ISC_R_SUCCESS
)
1000 * Cleanup and return.
1002 isc_buffer_free(&buf1
);
1004 return (ISC_R_SUCCESS
);
1007 dns_message_renderreset(message
);
1009 isc_buffer_free(&buf1
);
1011 isc_buffer_free(&buf2
);
1013 dns_compress_invalidate(&cctx
);
1019 * If this request is no longer waiting for events,
1020 * send the completion event. This will ultimately
1021 * cause the request to be destroyed.
1024 * 'request' is locked by the caller.
1027 send_if_done(dns_request_t
*request
, isc_result_t result
) {
1028 if (!DNS_REQUEST_CONNECTING(request
) &&
1029 !DNS_REQUEST_SENDING(request
) &&
1030 !request
->canceling
)
1031 req_sendevent(request
, result
);
1035 * Handle the control event.
1038 do_cancel(isc_task_t
*task
, isc_event_t
*event
) {
1039 dns_request_t
*request
= event
->ev_arg
;
1041 INSIST(event
->ev_type
== DNS_EVENT_REQUESTCONTROL
);
1042 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1043 request
->canceling
= ISC_FALSE
;
1044 if (!DNS_REQUEST_CANCELED(request
))
1045 req_cancel(request
);
1046 send_if_done(request
, ISC_R_CANCELED
);
1047 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1051 dns_request_cancel(dns_request_t
*request
) {
1052 REQUIRE(VALID_REQUEST(request
));
1054 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request
);
1056 REQUIRE(VALID_REQUEST(request
));
1058 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1059 if (!request
->canceling
&& !DNS_REQUEST_CANCELED(request
)) {
1060 isc_event_t
*ev
= &request
->ctlevent
;
1061 isc_task_send(request
->event
->ev_sender
, &ev
);
1062 request
->canceling
= ISC_TRUE
;
1064 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1065 return (ISC_R_SUCCESS
);
1069 dns_request_getresponse(dns_request_t
*request
, dns_message_t
*message
,
1070 unsigned int options
)
1072 isc_result_t result
;
1074 REQUIRE(VALID_REQUEST(request
));
1075 REQUIRE(request
->answer
!= NULL
);
1077 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1080 dns_message_setquerytsig(message
, request
->tsig
);
1081 dns_message_settsigkey(message
, request
->tsigkey
);
1082 result
= dns_message_parse(message
, request
->answer
, options
);
1083 if (result
!= ISC_R_SUCCESS
)
1085 if (request
->tsigkey
!= NULL
)
1086 result
= dns_tsig_verify(request
->answer
, message
, NULL
, NULL
);
1091 dns_request_usedtcp(dns_request_t
*request
) {
1092 REQUIRE(VALID_REQUEST(request
));
1094 return (ISC_TF((request
->flags
& DNS_REQUEST_F_TCP
) != 0));
1098 dns_request_destroy(dns_request_t
**requestp
) {
1099 dns_request_t
*request
;
1101 REQUIRE(requestp
!= NULL
&& VALID_REQUEST(*requestp
));
1103 request
= *requestp
;
1105 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request
);
1107 LOCK(&request
->requestmgr
->lock
);
1108 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1109 ISC_LIST_UNLINK(request
->requestmgr
->requests
, request
, link
);
1110 INSIST(!DNS_REQUEST_CONNECTING(request
));
1111 INSIST(!DNS_REQUEST_SENDING(request
));
1112 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1113 UNLOCK(&request
->requestmgr
->lock
);
1116 * These should have been cleaned up by req_cancel() before
1117 * the completion event was sent.
1119 INSIST(!ISC_LINK_LINKED(request
, link
));
1120 INSIST(request
->dispentry
== NULL
);
1121 INSIST(request
->dispatch
== NULL
);
1122 INSIST(request
->timer
== NULL
);
1124 req_destroy(request
);
1130 *** Private: request.
1134 req_connected(isc_task_t
*task
, isc_event_t
*event
) {
1135 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1136 isc_result_t result
;
1137 dns_request_t
*request
= event
->ev_arg
;
1139 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
1140 REQUIRE(VALID_REQUEST(request
));
1141 REQUIRE(DNS_REQUEST_CONNECTING(request
));
1143 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request
);
1145 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1146 request
->flags
&= ~DNS_REQUEST_F_CONNECTING
;
1148 if (DNS_REQUEST_CANCELED(request
)) {
1150 * Send delayed event.
1152 if (DNS_REQUEST_TIMEDOUT(request
))
1153 send_if_done(request
, ISC_R_TIMEDOUT
);
1155 send_if_done(request
, ISC_R_CANCELED
);
1157 dns_dispatch_starttcp(request
->dispatch
);
1158 result
= sevent
->result
;
1159 if (result
== ISC_R_SUCCESS
)
1160 result
= req_send(request
, task
, NULL
);
1162 if (result
!= ISC_R_SUCCESS
) {
1163 req_cancel(request
);
1164 send_if_done(request
, ISC_R_CANCELED
);
1167 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1168 isc_event_free(&event
);
1172 req_senddone(isc_task_t
*task
, isc_event_t
*event
) {
1173 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
1174 dns_request_t
*request
= event
->ev_arg
;
1176 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1177 REQUIRE(VALID_REQUEST(request
));
1178 REQUIRE(DNS_REQUEST_SENDING(request
));
1180 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request
);
1184 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1185 request
->flags
&= ~DNS_REQUEST_F_SENDING
;
1187 if (DNS_REQUEST_CANCELED(request
)) {
1189 * Send delayed event.
1191 if (DNS_REQUEST_TIMEDOUT(request
))
1192 send_if_done(request
, ISC_R_TIMEDOUT
);
1194 send_if_done(request
, ISC_R_CANCELED
);
1195 } else if (sevent
->result
!= ISC_R_SUCCESS
) {
1196 req_cancel(request
);
1197 send_if_done(request
, ISC_R_CANCELED
);
1199 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1201 isc_event_free(&event
);
1205 req_response(isc_task_t
*task
, isc_event_t
*event
) {
1206 isc_result_t result
;
1207 dns_request_t
*request
= event
->ev_arg
;
1208 dns_dispatchevent_t
*devent
= (dns_dispatchevent_t
*)event
;
1211 REQUIRE(VALID_REQUEST(request
));
1212 REQUIRE(event
->ev_type
== DNS_EVENT_DISPATCH
);
1216 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request
,
1217 dns_result_totext(devent
->result
));
1219 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1220 result
= devent
->result
;
1221 if (result
!= ISC_R_SUCCESS
)
1225 * Copy buffer to request.
1227 isc_buffer_usedregion(&devent
->buffer
, &r
);
1228 result
= isc_buffer_allocate(request
->mctx
, &request
->answer
,
1230 if (result
!= ISC_R_SUCCESS
)
1232 result
= isc_buffer_copyregion(request
->answer
, &r
);
1233 if (result
!= ISC_R_SUCCESS
)
1234 isc_buffer_free(&request
->answer
);
1239 dns_dispatch_removeresponse(&request
->dispentry
, &devent
);
1240 req_cancel(request
);
1242 * Send completion event.
1244 send_if_done(request
, result
);
1245 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1249 req_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1250 dns_request_t
*request
= event
->ev_arg
;
1252 REQUIRE(VALID_REQUEST(request
));
1254 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request
);
1257 LOCK(&request
->requestmgr
->locks
[request
->hash
]);
1258 request
->flags
|= DNS_REQUEST_F_TIMEDOUT
;
1259 req_cancel(request
);
1260 send_if_done(request
, ISC_R_TIMEDOUT
);
1261 UNLOCK(&request
->requestmgr
->locks
[request
->hash
]);
1262 isc_event_free(&event
);
1266 req_sendevent(dns_request_t
*request
, isc_result_t result
) {
1269 REQUIRE(VALID_REQUEST(request
));
1271 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request
);
1274 * Lock held by caller.
1276 task
= request
->event
->ev_sender
;
1277 request
->event
->ev_sender
= request
;
1278 request
->event
->result
= result
;
1279 isc_task_sendanddetach(&task
, (isc_event_t
**)&request
->event
);
1283 req_destroy(dns_request_t
*request
) {
1286 REQUIRE(VALID_REQUEST(request
));
1288 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request
);
1291 if (request
->query
!= NULL
)
1292 isc_buffer_free(&request
->query
);
1293 if (request
->answer
!= NULL
)
1294 isc_buffer_free(&request
->answer
);
1295 if (request
->event
!= NULL
)
1296 isc_event_free((isc_event_t
**)&request
->event
);
1297 if (request
->dispentry
!= NULL
)
1298 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1299 if (request
->dispatch
!= NULL
)
1300 dns_dispatch_detach(&request
->dispatch
);
1301 if (request
->timer
!= NULL
)
1302 isc_timer_detach(&request
->timer
);
1303 if (request
->tsig
!= NULL
)
1304 isc_buffer_free(&request
->tsig
);
1305 if (request
->tsigkey
!= NULL
)
1306 dns_tsigkey_detach(&request
->tsigkey
);
1307 if (request
->requestmgr
!= NULL
)
1308 requestmgr_detach(&request
->requestmgr
);
1309 mctx
= request
->mctx
;
1310 isc_mem_put(mctx
, request
, sizeof(*request
));
1311 isc_mem_detach(&mctx
);
1315 * Stop the current request. Must be called from the request's task.
1318 req_cancel(dns_request_t
*request
) {
1319 isc_socket_t
*socket
;
1321 REQUIRE(VALID_REQUEST(request
));
1323 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request
);
1326 * Lock held by caller.
1328 request
->flags
|= DNS_REQUEST_F_CANCELED
;
1330 if (request
->timer
!= NULL
)
1331 isc_timer_detach(&request
->timer
);
1332 if (request
->dispentry
!= NULL
)
1333 dns_dispatch_removeresponse(&request
->dispentry
, NULL
);
1334 if (DNS_REQUEST_CONNECTING(request
)) {
1335 socket
= dns_dispatch_getsocket(request
->dispatch
);
1336 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_CONNECT
);
1338 if (DNS_REQUEST_SENDING(request
)) {
1339 socket
= dns_dispatch_getsocket(request
->dispatch
);
1340 isc_socket_cancel(socket
, NULL
, ISC_SOCKCANCEL_SEND
);
1342 dns_dispatch_detach(&request
->dispatch
);
1346 req_log(int level
, const char *fmt
, ...) {
1350 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
1351 DNS_LOGMODULE_REQUEST
, level
, fmt
, ap
);