2 * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.72.18.5.42.2 2008/07/23 07:28:56 tbox Exp $ */
24 #include <isc/magic.h>
27 #include <isc/timer.h>
31 #include <dns/compress.h>
32 #include <dns/dispatch.h>
33 #include <dns/events.h>
35 #include <dns/message.h>
36 #include <dns/rdata.h>
37 #include <dns/rdatastruct.h>
38 #include <dns/request.h>
39 #include <dns/result.h>
42 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
43 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
45 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
46 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
48 typedef ISC_LIST(dns_request_t) dns_requestlist_t;
50 #define DNS_REQUEST_NLOCKS 7
52 struct dns_requestmgr {
60 isc_timermgr_t *timermgr;
61 isc_socketmgr_t *socketmgr;
62 isc_taskmgr_t *taskmgr;
63 dns_dispatchmgr_t *dispatchmgr;
64 dns_dispatch_t *dispatchv4;
65 dns_dispatch_t *dispatchv6;
66 isc_boolean_t exiting;
67 isc_eventlist_t whenshutdown;
69 isc_mutex_t locks[DNS_REQUEST_NLOCKS];
70 dns_requestlist_t requests;
78 ISC_LINK(dns_request_t) link;
81 dns_requestevent_t *event;
82 dns_dispatch_t *dispatch;
83 dns_dispentry_t *dispentry;
85 dns_requestmgr_t *requestmgr;
87 dns_tsigkey_t *tsigkey;
89 isc_boolean_t canceling; /* ctlevent outstanding */
90 isc_sockaddr_t destaddr;
91 unsigned int udpcount;
94 #define DNS_REQUEST_F_CONNECTING 0x0001
95 #define DNS_REQUEST_F_SENDING 0x0002
96 #define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
97 synchronously canceled */
98 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< cancelled due to a timeout */
99 #define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
100 #define DNS_REQUEST_CANCELED(r) \
101 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
102 #define DNS_REQUEST_CONNECTING(r) \
103 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
104 #define DNS_REQUEST_SENDING(r) \
105 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
106 #define DNS_REQUEST_TIMEDOUT(r) \
107 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
114 static void mgr_destroy(dns_requestmgr_t *requestmgr);
115 static void mgr_shutdown(dns_requestmgr_t *requestmgr);
116 static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
117 static void send_shutdown_events(dns_requestmgr_t *requestmgr);
119 static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
120 unsigned int options, isc_mem_t *mctx);
121 static void req_senddone(isc_task_t *task, isc_event_t *event);
122 static void req_response(isc_task_t *task, isc_event_t *event);
123 static void req_timeout(isc_task_t *task, isc_event_t *event);
124 static void req_connected(isc_task_t *task, isc_event_t *event);
125 static void req_sendevent(dns_request_t *request, isc_result_t result);
126 static void req_cancel(dns_request_t *request);
127 static void req_destroy(dns_request_t *request);
128 static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
129 static void do_cancel(isc_task_t *task, isc_event_t *event);
136 dns_requestmgr_create(isc_mem_t *mctx,
137 isc_timermgr_t *timermgr,
138 isc_socketmgr_t *socketmgr,
139 isc_taskmgr_t *taskmgr,
140 dns_dispatchmgr_t *dispatchmgr,
141 dns_dispatch_t *dispatchv4,
142 dns_dispatch_t *dispatchv6,
143 dns_requestmgr_t **requestmgrp)
145 dns_requestmgr_t *requestmgr;
146 isc_socket_t *socket;
150 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
152 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
153 REQUIRE(timermgr != NULL);
154 REQUIRE(socketmgr != NULL);
155 REQUIRE(taskmgr != NULL);
156 REQUIRE(dispatchmgr != NULL);
157 if (dispatchv4 != NULL) {
158 socket = dns_dispatch_getsocket(dispatchv4);
159 REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
161 if (dispatchv6 != NULL) {
162 socket = dns_dispatch_getsocket(dispatchv6);
163 REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
166 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
167 if (requestmgr == NULL)
168 return (ISC_R_NOMEMORY);
170 result = isc_mutex_init(&requestmgr->lock);
171 if (result != ISC_R_SUCCESS) {
172 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
175 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
176 result = isc_mutex_init(&requestmgr->locks[i]);
177 if (result != ISC_R_SUCCESS) {
179 DESTROYLOCK(&requestmgr->locks[i]);
180 DESTROYLOCK(&requestmgr->lock);
181 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
185 requestmgr->timermgr = timermgr;
186 requestmgr->socketmgr = socketmgr;
187 requestmgr->taskmgr = taskmgr;
188 requestmgr->dispatchmgr = dispatchmgr;
189 requestmgr->dispatchv4 = NULL;
190 if (dispatchv4 != NULL)
191 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
192 requestmgr->dispatchv6 = NULL;
193 if (dispatchv6 != NULL)
194 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
195 requestmgr->mctx = NULL;
196 isc_mem_attach(mctx, &requestmgr->mctx);
197 requestmgr->eref = 1; /* implict attach */
198 requestmgr->iref = 0;
199 ISC_LIST_INIT(requestmgr->whenshutdown);
200 ISC_LIST_INIT(requestmgr->requests);
201 requestmgr->exiting = ISC_FALSE;
202 requestmgr->hash = 0;
203 requestmgr->magic = REQUESTMGR_MAGIC;
205 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
207 *requestmgrp = requestmgr;
208 return (ISC_R_SUCCESS);
212 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
213 isc_event_t **eventp)
218 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
220 REQUIRE(VALID_REQUESTMGR(requestmgr));
221 REQUIRE(eventp != NULL);
226 LOCK(&requestmgr->lock);
228 if (requestmgr->exiting) {
230 * We're already shutdown. Send the event.
232 event->ev_sender = requestmgr;
233 isc_task_send(task, &event);
236 isc_task_attach(task, &clone);
237 event->ev_sender = clone;
238 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
240 UNLOCK(&requestmgr->lock);
244 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
246 REQUIRE(VALID_REQUESTMGR(requestmgr));
248 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
250 LOCK(&requestmgr->lock);
251 mgr_shutdown(requestmgr);
252 UNLOCK(&requestmgr->lock);
256 mgr_shutdown(dns_requestmgr_t *requestmgr) {
257 dns_request_t *request;
262 if (!requestmgr->exiting) {
263 requestmgr->exiting = ISC_TRUE;
264 for (request = ISC_LIST_HEAD(requestmgr->requests);
266 request = ISC_LIST_NEXT(request, link)) {
267 dns_request_cancel(request);
269 if (requestmgr->iref == 0) {
270 INSIST(ISC_LIST_EMPTY(requestmgr->requests));
271 send_shutdown_events(requestmgr);
277 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
283 REQUIRE(VALID_REQUESTMGR(source));
284 REQUIRE(targetp != NULL && *targetp == NULL);
286 REQUIRE(!source->exiting);
291 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
292 source, source->eref, source->iref);
296 requestmgr_detach(dns_requestmgr_t **requestmgrp) {
297 dns_requestmgr_t *requestmgr;
298 isc_boolean_t need_destroy = ISC_FALSE;
300 REQUIRE(requestmgrp != NULL);
301 requestmgr = *requestmgrp;
302 REQUIRE(VALID_REQUESTMGR(requestmgr));
305 LOCK(&requestmgr->lock);
306 INSIST(requestmgr->iref > 0);
309 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
310 requestmgr, requestmgr->eref, requestmgr->iref);
312 if (requestmgr->iref == 0 && requestmgr->exiting) {
313 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
314 send_shutdown_events(requestmgr);
315 if (requestmgr->eref == 0)
316 need_destroy = ISC_TRUE;
318 UNLOCK(&requestmgr->lock);
321 mgr_destroy(requestmgr);
325 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
327 REQUIRE(VALID_REQUESTMGR(source));
328 REQUIRE(targetp != NULL && *targetp == NULL);
329 REQUIRE(!source->exiting);
334 UNLOCK(&source->lock);
336 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
337 source, source->eref, source->iref);
341 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
342 dns_requestmgr_t *requestmgr;
343 isc_boolean_t need_destroy = ISC_FALSE;
345 REQUIRE(requestmgrp != NULL);
346 requestmgr = *requestmgrp;
347 REQUIRE(VALID_REQUESTMGR(requestmgr));
349 LOCK(&requestmgr->lock);
350 INSIST(requestmgr->eref > 0);
353 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
354 requestmgr, requestmgr->eref, requestmgr->iref);
356 if (requestmgr->eref == 0 && requestmgr->iref == 0) {
357 INSIST(requestmgr->exiting &&
358 ISC_LIST_HEAD(requestmgr->requests) == NULL);
359 need_destroy = ISC_TRUE;
361 UNLOCK(&requestmgr->lock);
364 mgr_destroy(requestmgr);
370 send_shutdown_events(dns_requestmgr_t *requestmgr) {
371 isc_event_t *event, *next_event;
374 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
377 * Caller must be holding the manager lock.
379 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
381 event = next_event) {
382 next_event = ISC_LIST_NEXT(event, ev_link);
383 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
384 etask = event->ev_sender;
385 event->ev_sender = requestmgr;
386 isc_task_sendanddetach(&etask, &event);
391 mgr_destroy(dns_requestmgr_t *requestmgr) {
395 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
397 REQUIRE(requestmgr->eref == 0);
398 REQUIRE(requestmgr->iref == 0);
400 DESTROYLOCK(&requestmgr->lock);
401 for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
402 DESTROYLOCK(&requestmgr->locks[i]);
403 if (requestmgr->dispatchv4 != NULL)
404 dns_dispatch_detach(&requestmgr->dispatchv4);
405 if (requestmgr->dispatchv6 != NULL)
406 dns_dispatch_detach(&requestmgr->dispatchv6);
407 requestmgr->magic = 0;
408 mctx = requestmgr->mctx;
409 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
410 isc_mem_detach(&mctx);
414 mgr_gethash(dns_requestmgr_t *requestmgr) {
415 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
420 return (requestmgr->hash % DNS_REQUEST_NLOCKS);
423 static inline isc_result_t
424 req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
426 isc_socket_t *socket;
429 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
431 REQUIRE(VALID_REQUEST(request));
432 socket = dns_dispatch_getsocket(request->dispatch);
433 isc_buffer_usedregion(request->query, &r);
434 result = isc_socket_sendto(socket, &r, task, req_senddone,
435 request, address, NULL);
436 if (result == ISC_R_SUCCESS)
437 request->flags |= DNS_REQUEST_F_SENDING;
442 new_request(isc_mem_t *mctx, dns_request_t **requestp) {
443 dns_request_t *request;
445 request = isc_mem_get(mctx, sizeof(*request));
447 return (ISC_R_NOMEMORY);
453 request->mctx = NULL;
455 ISC_LINK_INIT(request, link);
456 request->query = NULL;
457 request->answer = NULL;
458 request->event = NULL;
459 request->dispatch = NULL;
460 request->dispentry = NULL;
461 request->timer = NULL;
462 request->requestmgr = NULL;
463 request->tsig = NULL;
464 request->tsigkey = NULL;
465 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
466 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
468 request->canceling = ISC_FALSE;
469 request->udpcount = 0;
471 isc_mem_attach(mctx, &request->mctx);
473 request->magic = REQUEST_MAGIC;
475 return (ISC_R_SUCCESS);
480 isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
481 dns_acl_t *blackhole;
482 isc_netaddr_t netaddr;
484 isc_boolean_t drop = ISC_FALSE;
485 char netaddrstr[ISC_NETADDR_FORMATSIZE];
487 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
488 if (blackhole != NULL) {
489 isc_netaddr_fromsockaddr(&netaddr, destaddr);
490 if (dns_acl_match(&netaddr, NULL, blackhole,
491 NULL, &match, NULL) == ISC_R_SUCCESS &&
496 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
497 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
503 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
504 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
507 isc_socket_t *socket = NULL;
510 isc_sockaddr_t bind_any;
512 result = isc_socket_create(requestmgr->socketmgr,
513 isc_sockaddr_pf(destaddr),
514 isc_sockettype_tcp, &socket);
515 if (result != ISC_R_SUCCESS)
517 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
518 if (srcaddr == NULL) {
519 isc_sockaddr_anyofpf(&bind_any,
520 isc_sockaddr_pf(destaddr));
521 result = isc_socket_bind(socket, &bind_any, 0);
524 isc_sockaddr_setport(&src, 0);
525 result = isc_socket_bind(socket, &src, 0);
527 if (result != ISC_R_SUCCESS)
531 attrs |= DNS_DISPATCHATTR_TCP;
532 attrs |= DNS_DISPATCHATTR_PRIVATE;
533 if (isc_sockaddr_pf(destaddr) == AF_INET)
534 attrs |= DNS_DISPATCHATTR_IPV4;
536 attrs |= DNS_DISPATCHATTR_IPV6;
537 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
538 result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
539 socket, requestmgr->taskmgr,
540 4096, 2, 1, 1, 3, attrs,
543 isc_socket_detach(&socket);
548 find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
549 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
551 dns_dispatch_t *disp = NULL;
552 unsigned int attrs, attrmask;
554 if (srcaddr == NULL) {
555 switch (isc_sockaddr_pf(destaddr)) {
557 disp = requestmgr->dispatchv4;
561 disp = requestmgr->dispatchv6;
565 return (ISC_R_NOTIMPLEMENTED);
568 return (ISC_R_FAMILYNOSUPPORT);
569 dns_dispatch_attach(disp, dispatchp);
570 return (ISC_R_SUCCESS);
573 attrs |= DNS_DISPATCHATTR_UDP;
574 switch (isc_sockaddr_pf(srcaddr)) {
576 attrs |= DNS_DISPATCHATTR_IPV4;
580 attrs |= DNS_DISPATCHATTR_IPV6;
584 return (ISC_R_NOTIMPLEMENTED);
587 attrmask |= DNS_DISPATCHATTR_UDP;
588 attrmask |= DNS_DISPATCHATTR_TCP;
589 attrmask |= DNS_DISPATCHATTR_IPV4;
590 attrmask |= DNS_DISPATCHATTR_IPV6;
591 return (dns_dispatch_getudp(requestmgr->dispatchmgr,
592 requestmgr->socketmgr,
595 1000, 32768, 16411, 16433,
601 get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
602 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
603 dns_dispatch_t **dispatchp)
607 result = create_tcp_dispatch(requestmgr, srcaddr,
608 destaddr, dispatchp);
610 result = find_udp_dispatch(requestmgr, srcaddr,
611 destaddr, dispatchp);
616 set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
618 isc_interval_t interval;
620 isc_timertype_t timertype;
622 isc_interval_set(&interval, timeout, 0);
623 result = isc_time_nowplusinterval(&expires, &interval);
624 isc_interval_set(&interval, udpresend, 0);
626 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
627 if (result == ISC_R_SUCCESS)
628 result = isc_timer_reset(timer, timertype, &expires,
629 &interval, ISC_FALSE);
634 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
635 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
636 unsigned int options, unsigned int timeout,
637 isc_task_t *task, isc_taskaction_t action, void *arg,
638 dns_request_t **requestp)
640 return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
641 options, timeout, 0, 0, task, action,
646 dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
647 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
648 unsigned int options, unsigned int timeout,
649 unsigned int udptimeout, isc_task_t *task,
650 isc_taskaction_t action, void *arg,
651 dns_request_t **requestp)
653 unsigned int udpretries = 0;
656 udpretries = timeout / udptimeout;
658 return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
659 options, timeout, udptimeout,
660 udpretries, task, action, arg,
665 dns_request_createraw3(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 unsigned int udptimeout, unsigned int udpretries,
669 isc_task_t *task, isc_taskaction_t action, void *arg,
670 dns_request_t **requestp)
672 dns_request_t *request = NULL;
673 isc_task_t *tclone = NULL;
674 isc_socket_t *socket = NULL;
678 isc_boolean_t tcp = ISC_FALSE;
681 REQUIRE(VALID_REQUESTMGR(requestmgr));
682 REQUIRE(msgbuf != NULL);
683 REQUIRE(destaddr != NULL);
684 REQUIRE(task != NULL);
685 REQUIRE(action != NULL);
686 REQUIRE(requestp != NULL && *requestp == NULL);
687 REQUIRE(timeout > 0);
689 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
691 mctx = requestmgr->mctx;
693 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
695 if (isblackholed(requestmgr->dispatchmgr, destaddr))
696 return (DNS_R_BLACKHOLED);
699 result = new_request(mctx, &request);
700 if (result != ISC_R_SUCCESS)
703 if (udptimeout == 0 && udpretries != 0) {
704 udptimeout = timeout / (udpretries + 1);
708 request->udpcount = udpretries;
711 * Create timer now. We will set it below once.
713 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
714 NULL, NULL, task, req_timeout, request,
716 if (result != ISC_R_SUCCESS)
719 request->event = (dns_requestevent_t *)
720 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
721 action, arg, sizeof(dns_requestevent_t));
722 if (request->event == NULL) {
723 result = ISC_R_NOMEMORY;
726 isc_task_attach(task, &tclone);
727 request->event->ev_sender = task;
728 request->event->request = request;
729 request->event->result = ISC_R_FAILURE;
731 isc_buffer_usedregion(msgbuf, &r);
732 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
733 result = DNS_R_FORMERR;
737 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
740 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
742 if (result != ISC_R_SUCCESS)
745 socket = dns_dispatch_getsocket(request->dispatch);
746 INSIST(socket != NULL);
747 result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
748 req_response, request, &id,
749 &request->dispentry);
750 if (result != ISC_R_SUCCESS)
753 result = isc_buffer_allocate(mctx, &request->query,
754 r.length + (tcp ? 2 : 0));
755 if (result != ISC_R_SUCCESS)
758 isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
759 result = isc_buffer_copyregion(request->query, &r);
760 if (result != ISC_R_SUCCESS)
763 /* Add message ID. */
764 isc_buffer_usedregion(request->query, &r);
766 isc_region_consume(&r, 2);
767 r.base[0] = (id>>8) & 0xff;
768 r.base[1] = id & 0xff;
770 LOCK(&requestmgr->lock);
771 if (requestmgr->exiting) {
772 UNLOCK(&requestmgr->lock);
773 result = ISC_R_SHUTTINGDOWN;
776 requestmgr_attach(requestmgr, &request->requestmgr);
777 request->hash = mgr_gethash(requestmgr);
778 ISC_LIST_APPEND(requestmgr->requests, request, link);
779 UNLOCK(&requestmgr->lock);
781 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
782 if (result != ISC_R_SUCCESS)
785 request->destaddr = *destaddr;
787 result = isc_socket_connect(socket, destaddr, task,
788 req_connected, request);
789 if (result != ISC_R_SUCCESS)
791 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
793 result = req_send(request, task, destaddr);
794 if (result != ISC_R_SUCCESS)
798 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
801 return (ISC_R_SUCCESS);
804 LOCK(&requestmgr->lock);
805 ISC_LIST_UNLINK(requestmgr->requests, request, link);
806 UNLOCK(&requestmgr->lock);
810 isc_task_detach(&tclone);
811 req_destroy(request);
812 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
813 dns_result_totext(result));
818 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
819 isc_sockaddr_t *address, unsigned int options,
821 unsigned int timeout, isc_task_t *task,
822 isc_taskaction_t action, void *arg,
823 dns_request_t **requestp)
825 return (dns_request_createvia3(requestmgr, message, NULL, address,
826 options, key, timeout, 0, 0, task,
827 action, arg, requestp));
831 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
832 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
833 unsigned int options, dns_tsigkey_t *key,
834 unsigned int timeout, isc_task_t *task,
835 isc_taskaction_t action, void *arg,
836 dns_request_t **requestp)
838 return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
839 options, key, timeout, 0, 0, task,
840 action, arg, requestp));
844 dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
845 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
846 unsigned int options, dns_tsigkey_t *key,
847 unsigned int timeout, unsigned int udptimeout,
848 isc_task_t *task, isc_taskaction_t action, void *arg,
849 dns_request_t **requestp)
851 unsigned int udpretries = 0;
854 udpretries = timeout / udptimeout;
855 return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
856 options, key, timeout, udptimeout,
857 udpretries, task, action, arg,
862 dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
863 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
864 unsigned int options, dns_tsigkey_t *key,
865 unsigned int timeout, unsigned int udptimeout,
866 unsigned int udpretries, isc_task_t *task,
867 isc_taskaction_t action, void *arg,
868 dns_request_t **requestp)
870 dns_request_t *request = NULL;
871 isc_task_t *tclone = NULL;
872 isc_socket_t *socket = NULL;
877 isc_boolean_t setkey = ISC_TRUE;
879 REQUIRE(VALID_REQUESTMGR(requestmgr));
880 REQUIRE(message != NULL);
881 REQUIRE(destaddr != NULL);
882 REQUIRE(task != NULL);
883 REQUIRE(action != NULL);
884 REQUIRE(requestp != NULL && *requestp == NULL);
885 REQUIRE(timeout > 0);
887 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
889 mctx = requestmgr->mctx;
891 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
893 if (isblackholed(requestmgr->dispatchmgr, destaddr))
894 return (DNS_R_BLACKHOLED);
897 result = new_request(mctx, &request);
898 if (result != ISC_R_SUCCESS)
901 if (udptimeout == 0 && udpretries != 0) {
902 udptimeout = timeout / (udpretries + 1);
906 request->udpcount = udpretries;
909 * Create timer now. We will set it below once.
911 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
912 NULL, NULL, task, req_timeout, request,
914 if (result != ISC_R_SUCCESS)
917 request->event = (dns_requestevent_t *)
918 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
919 action, arg, sizeof(dns_requestevent_t));
920 if (request->event == NULL) {
921 result = ISC_R_NOMEMORY;
924 isc_task_attach(task, &tclone);
925 request->event->ev_sender = task;
926 request->event->request = request;
927 request->event->result = ISC_R_FAILURE;
929 dns_tsigkey_attach(key, &request->tsigkey);
932 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
933 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
935 if (result != ISC_R_SUCCESS)
938 socket = dns_dispatch_getsocket(request->dispatch);
939 INSIST(socket != NULL);
940 result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
941 req_response, request, &id,
942 &request->dispentry);
943 if (result != ISC_R_SUCCESS)
948 result = dns_message_settsigkey(message, request->tsigkey);
949 if (result != ISC_R_SUCCESS)
952 result = req_render(message, &request->query, options, mctx);
953 if (result == DNS_R_USETCP &&
954 (options & DNS_REQUESTOPT_TCP) == 0) {
956 * Try again using TCP.
958 dns_message_renderreset(message);
959 dns_dispatch_removeresponse(&request->dispentry, NULL);
960 dns_dispatch_detach(&request->dispatch);
962 options |= DNS_REQUESTOPT_TCP;
966 if (result != ISC_R_SUCCESS)
969 result = dns_message_getquerytsig(message, mctx, &request->tsig);
970 if (result != ISC_R_SUCCESS)
973 LOCK(&requestmgr->lock);
974 if (requestmgr->exiting) {
975 UNLOCK(&requestmgr->lock);
976 result = ISC_R_SHUTTINGDOWN;
979 requestmgr_attach(requestmgr, &request->requestmgr);
980 request->hash = mgr_gethash(requestmgr);
981 ISC_LIST_APPEND(requestmgr->requests, request, link);
982 UNLOCK(&requestmgr->lock);
984 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
985 if (result != ISC_R_SUCCESS)
988 request->destaddr = *destaddr;
990 result = isc_socket_connect(socket, destaddr, task,
991 req_connected, request);
992 if (result != ISC_R_SUCCESS)
994 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
996 result = req_send(request, task, destaddr);
997 if (result != ISC_R_SUCCESS)
1001 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
1003 *requestp = request;
1004 return (ISC_R_SUCCESS);
1007 LOCK(&requestmgr->lock);
1008 ISC_LIST_UNLINK(requestmgr->requests, request, link);
1009 UNLOCK(&requestmgr->lock);
1013 isc_task_detach(&tclone);
1014 req_destroy(request);
1015 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
1016 dns_result_totext(result));
1021 req_render(dns_message_t *message, isc_buffer_t **bufferp,
1022 unsigned int options, isc_mem_t *mctx)
1024 isc_buffer_t *buf1 = NULL;
1025 isc_buffer_t *buf2 = NULL;
1026 isc_result_t result;
1028 isc_boolean_t tcp = ISC_FALSE;
1029 dns_compress_t cctx;
1030 isc_boolean_t cleanup_cctx = ISC_FALSE;
1032 REQUIRE(bufferp != NULL && *bufferp == NULL);
1034 req_log(ISC_LOG_DEBUG(3), "request_render");
1037 * Create buffer able to hold largest possible message.
1039 result = isc_buffer_allocate(mctx, &buf1, 65535);
1040 if (result != ISC_R_SUCCESS)
1043 result = dns_compress_init(&cctx, -1, mctx);
1044 if (result != ISC_R_SUCCESS)
1046 cleanup_cctx = ISC_TRUE;
1051 result = dns_message_renderbegin(message, &cctx, buf1);
1052 if (result != ISC_R_SUCCESS)
1054 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
1055 if (result != ISC_R_SUCCESS)
1057 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
1058 if (result != ISC_R_SUCCESS)
1060 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
1061 if (result != ISC_R_SUCCESS)
1063 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
1064 if (result != ISC_R_SUCCESS)
1066 result = dns_message_renderend(message);
1067 if (result != ISC_R_SUCCESS)
1070 dns_compress_invalidate(&cctx);
1071 cleanup_cctx = ISC_FALSE;
1074 * Copy rendered message to exact sized buffer.
1076 isc_buffer_usedregion(buf1, &r);
1077 if ((options & DNS_REQUESTOPT_TCP) != 0) {
1079 } else if (r.length > 512) {
1080 result = DNS_R_USETCP;
1083 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
1084 if (result != ISC_R_SUCCESS)
1087 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
1088 result = isc_buffer_copyregion(buf2, &r);
1089 if (result != ISC_R_SUCCESS)
1093 * Cleanup and return.
1095 isc_buffer_free(&buf1);
1097 return (ISC_R_SUCCESS);
1100 dns_message_renderreset(message);
1102 isc_buffer_free(&buf1);
1104 isc_buffer_free(&buf2);
1106 dns_compress_invalidate(&cctx);
1112 * If this request is no longer waiting for events,
1113 * send the completion event. This will ultimately
1114 * cause the request to be destroyed.
1117 * 'request' is locked by the caller.
1120 send_if_done(dns_request_t *request, isc_result_t result) {
1121 if (!DNS_REQUEST_CONNECTING(request) &&
1122 !DNS_REQUEST_SENDING(request) &&
1123 !request->canceling)
1124 req_sendevent(request, result);
1128 * Handle the control event.
1131 do_cancel(isc_task_t *task, isc_event_t *event) {
1132 dns_request_t *request = event->ev_arg;
1134 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
1135 LOCK(&request->requestmgr->locks[request->hash]);
1136 request->canceling = ISC_FALSE;
1137 if (!DNS_REQUEST_CANCELED(request))
1138 req_cancel(request);
1139 send_if_done(request, ISC_R_CANCELED);
1140 UNLOCK(&request->requestmgr->locks[request->hash]);
1144 dns_request_cancel(dns_request_t *request) {
1145 REQUIRE(VALID_REQUEST(request));
1147 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
1149 REQUIRE(VALID_REQUEST(request));
1151 LOCK(&request->requestmgr->locks[request->hash]);
1152 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
1153 isc_event_t *ev = &request->ctlevent;
1154 isc_task_send(request->event->ev_sender, &ev);
1155 request->canceling = ISC_TRUE;
1157 UNLOCK(&request->requestmgr->locks[request->hash]);
1161 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
1162 unsigned int options)
1164 isc_result_t result;
1166 REQUIRE(VALID_REQUEST(request));
1167 REQUIRE(request->answer != NULL);
1169 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1172 result = dns_message_setquerytsig(message, request->tsig);
1173 if (result != ISC_R_SUCCESS)
1175 result = dns_message_settsigkey(message, request->tsigkey);
1176 if (result != ISC_R_SUCCESS)
1178 result = dns_message_parse(message, request->answer, options);
1179 if (result != ISC_R_SUCCESS)
1181 if (request->tsigkey != NULL)
1182 result = dns_tsig_verify(request->answer, message, NULL, NULL);
1187 dns_request_usedtcp(dns_request_t *request) {
1188 REQUIRE(VALID_REQUEST(request));
1190 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
1194 dns_request_destroy(dns_request_t **requestp) {
1195 dns_request_t *request;
1197 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
1199 request = *requestp;
1201 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
1203 LOCK(&request->requestmgr->lock);
1204 LOCK(&request->requestmgr->locks[request->hash]);
1205 ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
1206 INSIST(!DNS_REQUEST_CONNECTING(request));
1207 INSIST(!DNS_REQUEST_SENDING(request));
1208 UNLOCK(&request->requestmgr->locks[request->hash]);
1209 UNLOCK(&request->requestmgr->lock);
1212 * These should have been cleaned up by req_cancel() before
1213 * the completion event was sent.
1215 INSIST(!ISC_LINK_LINKED(request, link));
1216 INSIST(request->dispentry == NULL);
1217 INSIST(request->dispatch == NULL);
1218 INSIST(request->timer == NULL);
1220 req_destroy(request);
1226 *** Private: request.
1230 req_connected(isc_task_t *task, isc_event_t *event) {
1231 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1232 isc_result_t result;
1233 dns_request_t *request = event->ev_arg;
1235 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1236 REQUIRE(VALID_REQUEST(request));
1237 REQUIRE(DNS_REQUEST_CONNECTING(request));
1239 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
1241 LOCK(&request->requestmgr->locks[request->hash]);
1242 request->flags &= ~DNS_REQUEST_F_CONNECTING;
1244 if (DNS_REQUEST_CANCELED(request)) {
1246 * Send delayed event.
1248 if (DNS_REQUEST_TIMEDOUT(request))
1249 send_if_done(request, ISC_R_TIMEDOUT);
1251 send_if_done(request, ISC_R_CANCELED);
1253 dns_dispatch_starttcp(request->dispatch);
1254 result = sevent->result;
1255 if (result == ISC_R_SUCCESS)
1256 result = req_send(request, task, NULL);
1258 if (result != ISC_R_SUCCESS) {
1259 req_cancel(request);
1260 send_if_done(request, ISC_R_CANCELED);
1263 UNLOCK(&request->requestmgr->locks[request->hash]);
1264 isc_event_free(&event);
1268 req_senddone(isc_task_t *task, isc_event_t *event) {
1269 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1270 dns_request_t *request = event->ev_arg;
1272 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1273 REQUIRE(VALID_REQUEST(request));
1274 REQUIRE(DNS_REQUEST_SENDING(request));
1276 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
1280 LOCK(&request->requestmgr->locks[request->hash]);
1281 request->flags &= ~DNS_REQUEST_F_SENDING;
1283 if (DNS_REQUEST_CANCELED(request)) {
1285 * Send delayed event.
1287 if (DNS_REQUEST_TIMEDOUT(request))
1288 send_if_done(request, ISC_R_TIMEDOUT);
1290 send_if_done(request, ISC_R_CANCELED);
1291 } else if (sevent->result != ISC_R_SUCCESS) {
1292 req_cancel(request);
1293 send_if_done(request, ISC_R_CANCELED);
1295 UNLOCK(&request->requestmgr->locks[request->hash]);
1297 isc_event_free(&event);
1301 req_response(isc_task_t *task, isc_event_t *event) {
1302 isc_result_t result;
1303 dns_request_t *request = event->ev_arg;
1304 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
1307 REQUIRE(VALID_REQUEST(request));
1308 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
1312 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
1313 dns_result_totext(devent->result));
1315 LOCK(&request->requestmgr->locks[request->hash]);
1316 result = devent->result;
1317 if (result != ISC_R_SUCCESS)
1321 * Copy buffer to request.
1323 isc_buffer_usedregion(&devent->buffer, &r);
1324 result = isc_buffer_allocate(request->mctx, &request->answer,
1326 if (result != ISC_R_SUCCESS)
1328 result = isc_buffer_copyregion(request->answer, &r);
1329 if (result != ISC_R_SUCCESS)
1330 isc_buffer_free(&request->answer);
1335 dns_dispatch_removeresponse(&request->dispentry, &devent);
1336 req_cancel(request);
1338 * Send completion event.
1340 send_if_done(request, result);
1341 UNLOCK(&request->requestmgr->locks[request->hash]);
1345 req_timeout(isc_task_t *task, isc_event_t *event) {
1346 dns_request_t *request = event->ev_arg;
1347 isc_result_t result;
1349 REQUIRE(VALID_REQUEST(request));
1351 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
1354 LOCK(&request->requestmgr->locks[request->hash]);
1355 if (event->ev_type == ISC_TIMEREVENT_TICK &&
1356 request->udpcount-- != 0) {
1357 if (! DNS_REQUEST_SENDING(request)) {
1358 result = req_send(request, task, &request->destaddr);
1359 if (result != ISC_R_SUCCESS) {
1360 req_cancel(request);
1361 send_if_done(request, result);
1365 request->flags |= DNS_REQUEST_F_TIMEDOUT;
1366 req_cancel(request);
1367 send_if_done(request, ISC_R_TIMEDOUT);
1369 UNLOCK(&request->requestmgr->locks[request->hash]);
1370 isc_event_free(&event);
1374 req_sendevent(dns_request_t *request, isc_result_t result) {
1377 REQUIRE(VALID_REQUEST(request));
1379 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
1382 * Lock held by caller.
1384 task = request->event->ev_sender;
1385 request->event->ev_sender = request;
1386 request->event->result = result;
1387 isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
1391 req_destroy(dns_request_t *request) {
1394 REQUIRE(VALID_REQUEST(request));
1396 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
1399 if (request->query != NULL)
1400 isc_buffer_free(&request->query);
1401 if (request->answer != NULL)
1402 isc_buffer_free(&request->answer);
1403 if (request->event != NULL)
1404 isc_event_free((isc_event_t **)&request->event);
1405 if (request->dispentry != NULL)
1406 dns_dispatch_removeresponse(&request->dispentry, NULL);
1407 if (request->dispatch != NULL)
1408 dns_dispatch_detach(&request->dispatch);
1409 if (request->timer != NULL)
1410 isc_timer_detach(&request->timer);
1411 if (request->tsig != NULL)
1412 isc_buffer_free(&request->tsig);
1413 if (request->tsigkey != NULL)
1414 dns_tsigkey_detach(&request->tsigkey);
1415 if (request->requestmgr != NULL)
1416 requestmgr_detach(&request->requestmgr);
1417 mctx = request->mctx;
1418 isc_mem_put(mctx, request, sizeof(*request));
1419 isc_mem_detach(&mctx);
1423 * Stop the current request. Must be called from the request's task.
1426 req_cancel(dns_request_t *request) {
1427 isc_socket_t *socket;
1429 REQUIRE(VALID_REQUEST(request));
1431 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
1434 * Lock held by caller.
1436 request->flags |= DNS_REQUEST_F_CANCELED;
1438 if (request->timer != NULL)
1439 isc_timer_detach(&request->timer);
1440 if (request->dispentry != NULL)
1441 dns_dispatch_removeresponse(&request->dispentry, NULL);
1442 if (DNS_REQUEST_CONNECTING(request)) {
1443 socket = dns_dispatch_getsocket(request->dispatch);
1444 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
1446 if (DNS_REQUEST_SENDING(request)) {
1447 socket = dns_dispatch_getsocket(request->dispatch);
1448 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
1450 dns_dispatch_detach(&request->dispatch);
1454 req_log(int level, const char *fmt, ...) {
1458 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1459 DNS_LOGMODULE_REQUEST, level, fmt, ap);