2 * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 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.1.10.9 2006/08/21 00:50:48 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 */
88 isc_sockaddr_t destaddr;
89 unsigned int udpcount;
92 #define DNS_REQUEST_F_CONNECTING 0x0001
93 #define DNS_REQUEST_F_SENDING 0x0002
94 #define DNS_REQUEST_F_CANCELED 0x0004 /* ctlevent received, or otherwise
95 synchronously canceled */
96 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /* cancelled due to a timeout */
97 #define DNS_REQUEST_F_TCP 0x0010 /* This request used TCP */
98 #define DNS_REQUEST_CANCELED(r) \
99 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
100 #define DNS_REQUEST_CONNECTING(r) \
101 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
102 #define DNS_REQUEST_SENDING(r) \
103 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
104 #define DNS_REQUEST_TIMEDOUT(r) \
105 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
112 static void mgr_destroy(dns_requestmgr_t *requestmgr);
113 static void mgr_shutdown(dns_requestmgr_t *requestmgr);
114 static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
115 static void send_shutdown_events(dns_requestmgr_t *requestmgr);
117 static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
118 unsigned int options, isc_mem_t *mctx);
119 static void req_senddone(isc_task_t *task, isc_event_t *event);
120 static void req_response(isc_task_t *task, isc_event_t *event);
121 static void req_timeout(isc_task_t *task, isc_event_t *event);
122 static void req_connected(isc_task_t *task, isc_event_t *event);
123 static void req_sendevent(dns_request_t *request, isc_result_t result);
124 static void req_cancel(dns_request_t *request);
125 static void req_destroy(dns_request_t *request);
126 static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
127 static void do_cancel(isc_task_t *task, isc_event_t *event);
134 dns_requestmgr_create(isc_mem_t *mctx,
135 isc_timermgr_t *timermgr,
136 isc_socketmgr_t *socketmgr,
137 isc_taskmgr_t *taskmgr,
138 dns_dispatchmgr_t *dispatchmgr,
139 dns_dispatch_t *dispatchv4,
140 dns_dispatch_t *dispatchv6,
141 dns_requestmgr_t **requestmgrp)
143 dns_requestmgr_t *requestmgr;
144 isc_socket_t *socket;
148 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
150 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
151 REQUIRE(timermgr != NULL);
152 REQUIRE(socketmgr != NULL);
153 REQUIRE(taskmgr != NULL);
154 REQUIRE(dispatchmgr != NULL);
155 if (dispatchv4 != NULL) {
156 socket = dns_dispatch_getsocket(dispatchv4);
157 REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
159 if (dispatchv6 != NULL) {
160 socket = dns_dispatch_getsocket(dispatchv6);
161 REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
164 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
165 if (requestmgr == NULL)
166 return (ISC_R_NOMEMORY);
168 result = isc_mutex_init(&requestmgr->lock);
169 if (result != ISC_R_SUCCESS) {
170 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
173 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
174 result = isc_mutex_init(&requestmgr->locks[i]);
175 if (result != ISC_R_SUCCESS) {
177 DESTROYLOCK(&requestmgr->locks[i]);
178 DESTROYLOCK(&requestmgr->lock);
179 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
183 requestmgr->timermgr = timermgr;
184 requestmgr->socketmgr = socketmgr;
185 requestmgr->taskmgr = taskmgr;
186 requestmgr->dispatchmgr = dispatchmgr;
187 requestmgr->dispatchv4 = NULL;
188 if (dispatchv4 != NULL)
189 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
190 requestmgr->dispatchv6 = NULL;
191 if (dispatchv6 != NULL)
192 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
193 requestmgr->mctx = NULL;
194 isc_mem_attach(mctx, &requestmgr->mctx);
195 requestmgr->eref = 1; /* implict attach */
196 requestmgr->iref = 0;
197 ISC_LIST_INIT(requestmgr->whenshutdown);
198 ISC_LIST_INIT(requestmgr->requests);
199 requestmgr->exiting = ISC_FALSE;
200 requestmgr->hash = 0;
201 requestmgr->magic = REQUESTMGR_MAGIC;
203 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
205 *requestmgrp = requestmgr;
206 return (ISC_R_SUCCESS);
210 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
211 isc_event_t **eventp)
216 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
218 REQUIRE(VALID_REQUESTMGR(requestmgr));
219 REQUIRE(eventp != NULL);
224 LOCK(&requestmgr->lock);
226 if (requestmgr->exiting) {
228 * We're already shutdown. Send the event.
230 event->ev_sender = requestmgr;
231 isc_task_send(task, &event);
234 isc_task_attach(task, &clone);
235 event->ev_sender = clone;
236 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
238 UNLOCK(&requestmgr->lock);
242 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
244 REQUIRE(VALID_REQUESTMGR(requestmgr));
246 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
248 LOCK(&requestmgr->lock);
249 mgr_shutdown(requestmgr);
250 UNLOCK(&requestmgr->lock);
254 mgr_shutdown(dns_requestmgr_t *requestmgr) {
255 dns_request_t *request;
260 if (!requestmgr->exiting) {
261 requestmgr->exiting = ISC_TRUE;
262 for (request = ISC_LIST_HEAD(requestmgr->requests);
264 request = ISC_LIST_NEXT(request, link)) {
265 dns_request_cancel(request);
267 if (requestmgr->iref == 0) {
268 INSIST(ISC_LIST_EMPTY(requestmgr->requests));
269 send_shutdown_events(requestmgr);
275 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
281 REQUIRE(VALID_REQUESTMGR(source));
282 REQUIRE(targetp != NULL && *targetp == NULL);
284 REQUIRE(!source->exiting);
289 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
290 source, source->eref, source->iref);
294 requestmgr_detach(dns_requestmgr_t **requestmgrp) {
295 dns_requestmgr_t *requestmgr;
296 isc_boolean_t need_destroy = ISC_FALSE;
298 REQUIRE(requestmgrp != NULL);
299 requestmgr = *requestmgrp;
300 REQUIRE(VALID_REQUESTMGR(requestmgr));
303 LOCK(&requestmgr->lock);
304 INSIST(requestmgr->iref > 0);
307 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
308 requestmgr, requestmgr->eref, requestmgr->iref);
310 if (requestmgr->iref == 0 && requestmgr->exiting) {
311 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
312 send_shutdown_events(requestmgr);
313 if (requestmgr->eref == 0)
314 need_destroy = ISC_TRUE;
316 UNLOCK(&requestmgr->lock);
319 mgr_destroy(requestmgr);
323 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
325 REQUIRE(VALID_REQUESTMGR(source));
326 REQUIRE(targetp != NULL && *targetp == NULL);
327 REQUIRE(!source->exiting);
332 UNLOCK(&source->lock);
334 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
335 source, source->eref, source->iref);
339 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
340 dns_requestmgr_t *requestmgr;
341 isc_boolean_t need_destroy = ISC_FALSE;
343 REQUIRE(requestmgrp != NULL);
344 requestmgr = *requestmgrp;
345 REQUIRE(VALID_REQUESTMGR(requestmgr));
347 LOCK(&requestmgr->lock);
348 INSIST(requestmgr->eref > 0);
351 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
352 requestmgr, requestmgr->eref, requestmgr->iref);
354 if (requestmgr->eref == 0 && requestmgr->iref == 0) {
355 INSIST(requestmgr->exiting &&
356 ISC_LIST_HEAD(requestmgr->requests) == NULL);
357 need_destroy = ISC_TRUE;
359 UNLOCK(&requestmgr->lock);
362 mgr_destroy(requestmgr);
368 send_shutdown_events(dns_requestmgr_t *requestmgr) {
369 isc_event_t *event, *next_event;
372 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
375 * Caller must be holding the manager lock.
377 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
379 event = next_event) {
380 next_event = ISC_LIST_NEXT(event, ev_link);
381 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
382 etask = event->ev_sender;
383 event->ev_sender = requestmgr;
384 isc_task_sendanddetach(&etask, &event);
389 mgr_destroy(dns_requestmgr_t *requestmgr) {
393 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
395 REQUIRE(requestmgr->eref == 0);
396 REQUIRE(requestmgr->iref == 0);
398 DESTROYLOCK(&requestmgr->lock);
399 for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
400 DESTROYLOCK(&requestmgr->locks[i]);
401 if (requestmgr->dispatchv4 != NULL)
402 dns_dispatch_detach(&requestmgr->dispatchv4);
403 if (requestmgr->dispatchv6 != NULL)
404 dns_dispatch_detach(&requestmgr->dispatchv6);
405 requestmgr->magic = 0;
406 mctx = requestmgr->mctx;
407 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
408 isc_mem_detach(&mctx);
412 mgr_gethash(dns_requestmgr_t *requestmgr) {
413 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
418 return (requestmgr->hash % DNS_REQUEST_NLOCKS);
421 static inline isc_result_t
422 req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
424 isc_socket_t *socket;
427 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
429 REQUIRE(VALID_REQUEST(request));
430 socket = dns_dispatch_getsocket(request->dispatch);
431 isc_buffer_usedregion(request->query, &r);
432 result = isc_socket_sendto(socket, &r, task, req_senddone,
433 request, address, NULL);
434 if (result == ISC_R_SUCCESS)
435 request->flags |= DNS_REQUEST_F_SENDING;
440 new_request(isc_mem_t *mctx, dns_request_t **requestp) {
441 dns_request_t *request;
443 request = isc_mem_get(mctx, sizeof(*request));
445 return (ISC_R_NOMEMORY);
451 request->mctx = NULL;
453 ISC_LINK_INIT(request, link);
454 request->query = NULL;
455 request->answer = NULL;
456 request->event = NULL;
457 request->dispatch = NULL;
458 request->dispentry = NULL;
459 request->timer = NULL;
460 request->requestmgr = NULL;
461 request->tsig = NULL;
462 request->tsigkey = NULL;
463 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
464 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
466 request->canceling = ISC_FALSE;
467 request->udpcount = 0;
469 isc_mem_attach(mctx, &request->mctx);
471 request->magic = REQUEST_MAGIC;
473 return (ISC_R_SUCCESS);
478 isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
479 dns_acl_t *blackhole;
480 isc_netaddr_t netaddr;
482 isc_boolean_t drop = ISC_FALSE;
483 char netaddrstr[ISC_NETADDR_FORMATSIZE];
485 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
486 if (blackhole != NULL) {
487 isc_netaddr_fromsockaddr(&netaddr, destaddr);
488 if (dns_acl_match(&netaddr, NULL, blackhole,
489 NULL, &match, NULL) == ISC_R_SUCCESS &&
494 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
495 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
501 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
502 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
505 isc_socket_t *socket = NULL;
508 isc_sockaddr_t bind_any;
510 result = isc_socket_create(requestmgr->socketmgr,
511 isc_sockaddr_pf(destaddr),
512 isc_sockettype_tcp, &socket);
513 if (result != ISC_R_SUCCESS)
515 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
516 if (srcaddr == NULL) {
517 isc_sockaddr_anyofpf(&bind_any,
518 isc_sockaddr_pf(destaddr));
519 result = isc_socket_bind(socket, &bind_any);
522 isc_sockaddr_setport(&src, 0);
523 result = isc_socket_bind(socket, &src);
525 if (result != ISC_R_SUCCESS)
529 attrs |= DNS_DISPATCHATTR_TCP;
530 attrs |= DNS_DISPATCHATTR_PRIVATE;
531 if (isc_sockaddr_pf(destaddr) == AF_INET)
532 attrs |= DNS_DISPATCHATTR_IPV4;
534 attrs |= DNS_DISPATCHATTR_IPV6;
535 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
536 result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
537 socket, requestmgr->taskmgr,
538 4096, 2, 1, 1, 3, attrs,
541 isc_socket_detach(&socket);
546 find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
547 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
549 dns_dispatch_t *disp = NULL;
550 unsigned int attrs, attrmask;
552 if (srcaddr == NULL) {
553 switch (isc_sockaddr_pf(destaddr)) {
555 disp = requestmgr->dispatchv4;
559 disp = requestmgr->dispatchv6;
563 return (ISC_R_NOTIMPLEMENTED);
566 return (ISC_R_FAMILYNOSUPPORT);
567 dns_dispatch_attach(disp, dispatchp);
568 return (ISC_R_SUCCESS);
571 attrs |= DNS_DISPATCHATTR_UDP;
572 switch (isc_sockaddr_pf(srcaddr)) {
574 attrs |= DNS_DISPATCHATTR_IPV4;
578 attrs |= DNS_DISPATCHATTR_IPV6;
582 return (ISC_R_NOTIMPLEMENTED);
585 attrmask |= DNS_DISPATCHATTR_UDP;
586 attrmask |= DNS_DISPATCHATTR_TCP;
587 attrmask |= DNS_DISPATCHATTR_IPV4;
588 attrmask |= DNS_DISPATCHATTR_IPV6;
589 return (dns_dispatch_getudp(requestmgr->dispatchmgr,
590 requestmgr->socketmgr,
593 1000, 32768, 16411, 16433,
599 get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
600 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
601 dns_dispatch_t **dispatchp)
605 result = create_tcp_dispatch(requestmgr, srcaddr,
606 destaddr, dispatchp);
608 result = find_udp_dispatch(requestmgr, srcaddr,
609 destaddr, dispatchp);
614 set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
616 isc_interval_t interval;
618 isc_timertype_t timertype;
620 isc_interval_set(&interval, timeout, 0);
621 result = isc_time_nowplusinterval(&expires, &interval);
622 isc_interval_set(&interval, udpresend, 0);
624 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
625 if (result == ISC_R_SUCCESS)
626 result = isc_timer_reset(timer, timertype, &expires,
627 &interval, ISC_FALSE);
632 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
633 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
634 unsigned int options, unsigned int timeout,
635 isc_task_t *task, isc_taskaction_t action, void *arg,
636 dns_request_t **requestp)
638 return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
639 options, timeout, 0, 0, task, action,
644 dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
645 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
646 unsigned int options, unsigned int timeout,
647 unsigned int udptimeout, isc_task_t *task,
648 isc_taskaction_t action, void *arg,
649 dns_request_t **requestp)
651 unsigned int udpretries = 0;
654 udpretries = timeout / udptimeout;
656 return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
657 options, timeout, udptimeout,
658 udpretries, task, action, arg,
663 dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
664 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
665 unsigned int options, unsigned int timeout,
666 unsigned int udptimeout, unsigned int udpretries,
667 isc_task_t *task, isc_taskaction_t action, void *arg,
668 dns_request_t **requestp)
670 dns_request_t *request = NULL;
671 isc_task_t *tclone = NULL;
672 isc_socket_t *socket = NULL;
676 isc_boolean_t tcp = ISC_FALSE;
679 REQUIRE(VALID_REQUESTMGR(requestmgr));
680 REQUIRE(msgbuf != NULL);
681 REQUIRE(destaddr != NULL);
682 REQUIRE(task != NULL);
683 REQUIRE(action != NULL);
684 REQUIRE(requestp != NULL && *requestp == NULL);
685 REQUIRE(timeout > 0);
687 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
689 mctx = requestmgr->mctx;
691 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
693 if (isblackholed(requestmgr->dispatchmgr, destaddr))
694 return (DNS_R_BLACKHOLED);
697 result = new_request(mctx, &request);
698 if (result != ISC_R_SUCCESS)
701 if (udptimeout == 0 && udpretries != 0) {
702 udptimeout = timeout / (udpretries + 1);
706 request->udpcount = udpretries;
709 * Create timer now. We will set it below once.
711 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
712 NULL, NULL, task, req_timeout, request,
714 if (result != ISC_R_SUCCESS)
717 request->event = (dns_requestevent_t *)
718 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
719 action, arg, sizeof(dns_requestevent_t));
720 if (request->event == NULL) {
721 result = ISC_R_NOMEMORY;
724 isc_task_attach(task, &tclone);
725 request->event->ev_sender = task;
726 request->event->request = request;
727 request->event->result = ISC_R_FAILURE;
729 isc_buffer_usedregion(msgbuf, &r);
730 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
731 result = DNS_R_FORMERR;
735 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
738 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
740 if (result != ISC_R_SUCCESS)
743 socket = dns_dispatch_getsocket(request->dispatch);
744 INSIST(socket != NULL);
745 result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
746 req_response, request, &id,
747 &request->dispentry);
748 if (result != ISC_R_SUCCESS)
751 result = isc_buffer_allocate(mctx, &request->query,
752 r.length + (tcp ? 2 : 0));
753 if (result != ISC_R_SUCCESS)
756 isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
757 result = isc_buffer_copyregion(request->query, &r);
758 if (result != ISC_R_SUCCESS)
761 /* Add message ID. */
762 isc_buffer_usedregion(request->query, &r);
764 isc_region_consume(&r, 2);
765 r.base[0] = (id>>8) & 0xff;
766 r.base[1] = id & 0xff;
768 LOCK(&requestmgr->lock);
769 if (requestmgr->exiting) {
770 UNLOCK(&requestmgr->lock);
771 result = ISC_R_SHUTTINGDOWN;
774 requestmgr_attach(requestmgr, &request->requestmgr);
775 request->hash = mgr_gethash(requestmgr);
776 ISC_LIST_APPEND(requestmgr->requests, request, link);
777 UNLOCK(&requestmgr->lock);
779 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
780 if (result != ISC_R_SUCCESS)
783 request->destaddr = *destaddr;
785 result = isc_socket_connect(socket, destaddr, task,
786 req_connected, request);
787 if (result != ISC_R_SUCCESS)
789 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
791 result = req_send(request, task, destaddr);
792 if (result != ISC_R_SUCCESS)
796 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
799 return (ISC_R_SUCCESS);
802 LOCK(&requestmgr->lock);
803 ISC_LIST_UNLINK(requestmgr->requests, request, link);
804 UNLOCK(&requestmgr->lock);
808 isc_task_detach(&tclone);
809 req_destroy(request);
810 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
811 dns_result_totext(result));
816 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
817 isc_sockaddr_t *address, unsigned int options,
819 unsigned int timeout, isc_task_t *task,
820 isc_taskaction_t action, void *arg,
821 dns_request_t **requestp)
823 return (dns_request_createvia3(requestmgr, message, NULL, address,
824 options, key, timeout, 0, 0, task,
825 action, arg, requestp));
829 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
830 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
831 unsigned int options, dns_tsigkey_t *key,
832 unsigned int timeout, isc_task_t *task,
833 isc_taskaction_t action, void *arg,
834 dns_request_t **requestp)
836 return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
837 options, key, timeout, 0, 0, task,
838 action, arg, requestp));
842 dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
843 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
844 unsigned int options, dns_tsigkey_t *key,
845 unsigned int timeout, unsigned int udptimeout,
846 isc_task_t *task, isc_taskaction_t action, void *arg,
847 dns_request_t **requestp)
849 unsigned int udpretries = 0;
852 udpretries = timeout / udptimeout;
853 return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
854 options, key, timeout, udptimeout,
855 udpretries, task, action, arg,
860 dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
861 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
862 unsigned int options, dns_tsigkey_t *key,
863 unsigned int timeout, unsigned int udptimeout,
864 unsigned int udpretries, isc_task_t *task,
865 isc_taskaction_t action, void *arg,
866 dns_request_t **requestp)
868 dns_request_t *request = NULL;
869 isc_task_t *tclone = NULL;
870 isc_socket_t *socket = NULL;
875 isc_boolean_t setkey = ISC_TRUE;
877 REQUIRE(VALID_REQUESTMGR(requestmgr));
878 REQUIRE(message != NULL);
879 REQUIRE(destaddr != NULL);
880 REQUIRE(task != NULL);
881 REQUIRE(action != NULL);
882 REQUIRE(requestp != NULL && *requestp == NULL);
883 REQUIRE(timeout > 0);
885 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
887 mctx = requestmgr->mctx;
889 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
891 if (isblackholed(requestmgr->dispatchmgr, destaddr))
892 return (DNS_R_BLACKHOLED);
895 result = new_request(mctx, &request);
896 if (result != ISC_R_SUCCESS)
899 if (udptimeout == 0 && udpretries != 0) {
900 udptimeout = timeout / (udpretries + 1);
904 request->udpcount = udpretries;
907 * Create timer now. We will set it below once.
909 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
910 NULL, NULL, task, req_timeout, request,
912 if (result != ISC_R_SUCCESS)
915 request->event = (dns_requestevent_t *)
916 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
917 action, arg, sizeof(dns_requestevent_t));
918 if (request->event == NULL) {
919 result = ISC_R_NOMEMORY;
922 isc_task_attach(task, &tclone);
923 request->event->ev_sender = task;
924 request->event->request = request;
925 request->event->result = ISC_R_FAILURE;
927 dns_tsigkey_attach(key, &request->tsigkey);
930 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
931 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
933 if (result != ISC_R_SUCCESS)
936 socket = dns_dispatch_getsocket(request->dispatch);
937 INSIST(socket != NULL);
938 result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
939 req_response, request, &id,
940 &request->dispentry);
941 if (result != ISC_R_SUCCESS)
946 result = dns_message_settsigkey(message, request->tsigkey);
947 if (result != ISC_R_SUCCESS)
950 result = req_render(message, &request->query, options, mctx);
951 if (result == DNS_R_USETCP &&
952 (options & DNS_REQUESTOPT_TCP) == 0) {
954 * Try again using TCP.
956 dns_message_renderreset(message);
957 dns_dispatch_removeresponse(&request->dispentry, NULL);
958 dns_dispatch_detach(&request->dispatch);
960 options |= DNS_REQUESTOPT_TCP;
964 if (result != ISC_R_SUCCESS)
967 result = dns_message_getquerytsig(message, mctx, &request->tsig);
968 if (result != ISC_R_SUCCESS)
971 LOCK(&requestmgr->lock);
972 if (requestmgr->exiting) {
973 UNLOCK(&requestmgr->lock);
974 result = ISC_R_SHUTTINGDOWN;
977 requestmgr_attach(requestmgr, &request->requestmgr);
978 request->hash = mgr_gethash(requestmgr);
979 ISC_LIST_APPEND(requestmgr->requests, request, link);
980 UNLOCK(&requestmgr->lock);
982 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
983 if (result != ISC_R_SUCCESS)
986 request->destaddr = *destaddr;
988 result = isc_socket_connect(socket, destaddr, task,
989 req_connected, request);
990 if (result != ISC_R_SUCCESS)
992 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
994 result = req_send(request, task, destaddr);
995 if (result != ISC_R_SUCCESS)
999 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
1001 *requestp = request;
1002 return (ISC_R_SUCCESS);
1005 LOCK(&requestmgr->lock);
1006 ISC_LIST_UNLINK(requestmgr->requests, request, link);
1007 UNLOCK(&requestmgr->lock);
1011 isc_task_detach(&tclone);
1012 req_destroy(request);
1013 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
1014 dns_result_totext(result));
1019 req_render(dns_message_t *message, isc_buffer_t **bufferp,
1020 unsigned int options, isc_mem_t *mctx)
1022 isc_buffer_t *buf1 = NULL;
1023 isc_buffer_t *buf2 = NULL;
1024 isc_result_t result;
1026 isc_boolean_t tcp = ISC_FALSE;
1027 dns_compress_t cctx;
1028 isc_boolean_t cleanup_cctx = ISC_FALSE;
1030 REQUIRE(bufferp != NULL && *bufferp == NULL);
1032 req_log(ISC_LOG_DEBUG(3), "request_render");
1035 * Create buffer able to hold largest possible message.
1037 result = isc_buffer_allocate(mctx, &buf1, 65535);
1038 if (result != ISC_R_SUCCESS)
1041 result = dns_compress_init(&cctx, -1, mctx);
1042 if (result != ISC_R_SUCCESS)
1044 cleanup_cctx = ISC_TRUE;
1049 result = dns_message_renderbegin(message, &cctx, buf1);
1050 if (result != ISC_R_SUCCESS)
1052 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
1053 if (result != ISC_R_SUCCESS)
1055 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
1056 if (result != ISC_R_SUCCESS)
1058 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
1059 if (result != ISC_R_SUCCESS)
1061 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
1062 if (result != ISC_R_SUCCESS)
1064 result = dns_message_renderend(message);
1065 if (result != ISC_R_SUCCESS)
1068 dns_compress_invalidate(&cctx);
1069 cleanup_cctx = ISC_FALSE;
1072 * Copy rendered message to exact sized buffer.
1074 isc_buffer_usedregion(buf1, &r);
1075 if ((options & DNS_REQUESTOPT_TCP) != 0) {
1077 } else if (r.length > 512) {
1078 result = DNS_R_USETCP;
1081 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
1082 if (result != ISC_R_SUCCESS)
1085 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
1086 result = isc_buffer_copyregion(buf2, &r);
1087 if (result != ISC_R_SUCCESS)
1091 * Cleanup and return.
1093 isc_buffer_free(&buf1);
1095 return (ISC_R_SUCCESS);
1098 dns_message_renderreset(message);
1100 isc_buffer_free(&buf1);
1102 isc_buffer_free(&buf2);
1104 dns_compress_invalidate(&cctx);
1110 * If this request is no longer waiting for events,
1111 * send the completion event. This will ultimately
1112 * cause the request to be destroyed.
1115 * 'request' is locked by the caller.
1118 send_if_done(dns_request_t *request, isc_result_t result) {
1119 if (!DNS_REQUEST_CONNECTING(request) &&
1120 !DNS_REQUEST_SENDING(request) &&
1121 !request->canceling)
1122 req_sendevent(request, result);
1126 * Handle the control event.
1129 do_cancel(isc_task_t *task, isc_event_t *event) {
1130 dns_request_t *request = event->ev_arg;
1132 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
1133 LOCK(&request->requestmgr->locks[request->hash]);
1134 request->canceling = ISC_FALSE;
1135 if (!DNS_REQUEST_CANCELED(request))
1136 req_cancel(request);
1137 send_if_done(request, ISC_R_CANCELED);
1138 UNLOCK(&request->requestmgr->locks[request->hash]);
1142 dns_request_cancel(dns_request_t *request) {
1143 REQUIRE(VALID_REQUEST(request));
1145 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
1147 REQUIRE(VALID_REQUEST(request));
1149 LOCK(&request->requestmgr->locks[request->hash]);
1150 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
1151 isc_event_t *ev = &request->ctlevent;
1152 isc_task_send(request->event->ev_sender, &ev);
1153 request->canceling = ISC_TRUE;
1155 UNLOCK(&request->requestmgr->locks[request->hash]);
1159 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
1160 unsigned int options)
1162 isc_result_t result;
1164 REQUIRE(VALID_REQUEST(request));
1165 REQUIRE(request->answer != NULL);
1167 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1170 result = dns_message_setquerytsig(message, request->tsig);
1171 if (result != ISC_R_SUCCESS)
1173 result = dns_message_settsigkey(message, request->tsigkey);
1174 if (result != ISC_R_SUCCESS)
1176 result = dns_message_parse(message, request->answer, options);
1177 if (result != ISC_R_SUCCESS)
1179 if (request->tsigkey != NULL)
1180 result = dns_tsig_verify(request->answer, message, NULL, NULL);
1185 dns_request_usedtcp(dns_request_t *request) {
1186 REQUIRE(VALID_REQUEST(request));
1188 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
1192 dns_request_destroy(dns_request_t **requestp) {
1193 dns_request_t *request;
1195 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
1197 request = *requestp;
1199 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
1201 LOCK(&request->requestmgr->lock);
1202 LOCK(&request->requestmgr->locks[request->hash]);
1203 ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
1204 INSIST(!DNS_REQUEST_CONNECTING(request));
1205 INSIST(!DNS_REQUEST_SENDING(request));
1206 UNLOCK(&request->requestmgr->locks[request->hash]);
1207 UNLOCK(&request->requestmgr->lock);
1210 * These should have been cleaned up by req_cancel() before
1211 * the completion event was sent.
1213 INSIST(!ISC_LINK_LINKED(request, link));
1214 INSIST(request->dispentry == NULL);
1215 INSIST(request->dispatch == NULL);
1216 INSIST(request->timer == NULL);
1218 req_destroy(request);
1224 *** Private: request.
1228 req_connected(isc_task_t *task, isc_event_t *event) {
1229 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1230 isc_result_t result;
1231 dns_request_t *request = event->ev_arg;
1233 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1234 REQUIRE(VALID_REQUEST(request));
1235 REQUIRE(DNS_REQUEST_CONNECTING(request));
1237 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
1239 LOCK(&request->requestmgr->locks[request->hash]);
1240 request->flags &= ~DNS_REQUEST_F_CONNECTING;
1242 if (DNS_REQUEST_CANCELED(request)) {
1244 * Send delayed event.
1246 if (DNS_REQUEST_TIMEDOUT(request))
1247 send_if_done(request, ISC_R_TIMEDOUT);
1249 send_if_done(request, ISC_R_CANCELED);
1251 dns_dispatch_starttcp(request->dispatch);
1252 result = sevent->result;
1253 if (result == ISC_R_SUCCESS)
1254 result = req_send(request, task, NULL);
1256 if (result != ISC_R_SUCCESS) {
1257 req_cancel(request);
1258 send_if_done(request, ISC_R_CANCELED);
1261 UNLOCK(&request->requestmgr->locks[request->hash]);
1262 isc_event_free(&event);
1266 req_senddone(isc_task_t *task, isc_event_t *event) {
1267 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1268 dns_request_t *request = event->ev_arg;
1270 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1271 REQUIRE(VALID_REQUEST(request));
1272 REQUIRE(DNS_REQUEST_SENDING(request));
1274 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
1278 LOCK(&request->requestmgr->locks[request->hash]);
1279 request->flags &= ~DNS_REQUEST_F_SENDING;
1281 if (DNS_REQUEST_CANCELED(request)) {
1283 * Send delayed event.
1285 if (DNS_REQUEST_TIMEDOUT(request))
1286 send_if_done(request, ISC_R_TIMEDOUT);
1288 send_if_done(request, ISC_R_CANCELED);
1289 } else if (sevent->result != ISC_R_SUCCESS) {
1290 req_cancel(request);
1291 send_if_done(request, ISC_R_CANCELED);
1293 UNLOCK(&request->requestmgr->locks[request->hash]);
1295 isc_event_free(&event);
1299 req_response(isc_task_t *task, isc_event_t *event) {
1300 isc_result_t result;
1301 dns_request_t *request = event->ev_arg;
1302 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
1305 REQUIRE(VALID_REQUEST(request));
1306 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
1310 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
1311 dns_result_totext(devent->result));
1313 LOCK(&request->requestmgr->locks[request->hash]);
1314 result = devent->result;
1315 if (result != ISC_R_SUCCESS)
1319 * Copy buffer to request.
1321 isc_buffer_usedregion(&devent->buffer, &r);
1322 result = isc_buffer_allocate(request->mctx, &request->answer,
1324 if (result != ISC_R_SUCCESS)
1326 result = isc_buffer_copyregion(request->answer, &r);
1327 if (result != ISC_R_SUCCESS)
1328 isc_buffer_free(&request->answer);
1333 dns_dispatch_removeresponse(&request->dispentry, &devent);
1334 req_cancel(request);
1336 * Send completion event.
1338 send_if_done(request, result);
1339 UNLOCK(&request->requestmgr->locks[request->hash]);
1343 req_timeout(isc_task_t *task, isc_event_t *event) {
1344 dns_request_t *request = event->ev_arg;
1345 isc_result_t result;
1347 REQUIRE(VALID_REQUEST(request));
1349 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
1352 LOCK(&request->requestmgr->locks[request->hash]);
1353 if (event->ev_type == ISC_TIMEREVENT_TICK &&
1354 request->udpcount-- != 0) {
1355 if (! DNS_REQUEST_SENDING(request)) {
1356 result = req_send(request, task, &request->destaddr);
1357 if (result != ISC_R_SUCCESS) {
1358 req_cancel(request);
1359 send_if_done(request, result);
1363 request->flags |= DNS_REQUEST_F_TIMEDOUT;
1364 req_cancel(request);
1365 send_if_done(request, ISC_R_TIMEDOUT);
1367 UNLOCK(&request->requestmgr->locks[request->hash]);
1368 isc_event_free(&event);
1372 req_sendevent(dns_request_t *request, isc_result_t result) {
1375 REQUIRE(VALID_REQUEST(request));
1377 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
1380 * Lock held by caller.
1382 task = request->event->ev_sender;
1383 request->event->ev_sender = request;
1384 request->event->result = result;
1385 isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
1389 req_destroy(dns_request_t *request) {
1392 REQUIRE(VALID_REQUEST(request));
1394 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
1397 if (request->query != NULL)
1398 isc_buffer_free(&request->query);
1399 if (request->answer != NULL)
1400 isc_buffer_free(&request->answer);
1401 if (request->event != NULL)
1402 isc_event_free((isc_event_t **)&request->event);
1403 if (request->dispentry != NULL)
1404 dns_dispatch_removeresponse(&request->dispentry, NULL);
1405 if (request->dispatch != NULL)
1406 dns_dispatch_detach(&request->dispatch);
1407 if (request->timer != NULL)
1408 isc_timer_detach(&request->timer);
1409 if (request->tsig != NULL)
1410 isc_buffer_free(&request->tsig);
1411 if (request->tsigkey != NULL)
1412 dns_tsigkey_detach(&request->tsigkey);
1413 if (request->requestmgr != NULL)
1414 requestmgr_detach(&request->requestmgr);
1415 mctx = request->mctx;
1416 isc_mem_put(mctx, request, sizeof(*request));
1417 isc_mem_detach(&mctx);
1421 * Stop the current request. Must be called from the request's task.
1424 req_cancel(dns_request_t *request) {
1425 isc_socket_t *socket;
1427 REQUIRE(VALID_REQUEST(request));
1429 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
1432 * Lock held by caller.
1434 request->flags |= DNS_REQUEST_F_CANCELED;
1436 if (request->timer != NULL)
1437 isc_timer_detach(&request->timer);
1438 if (request->dispentry != NULL)
1439 dns_dispatch_removeresponse(&request->dispentry, NULL);
1440 if (DNS_REQUEST_CONNECTING(request)) {
1441 socket = dns_dispatch_getsocket(request->dispatch);
1442 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
1444 if (DNS_REQUEST_SENDING(request)) {
1445 socket = dns_dispatch_getsocket(request->dispatch);
1446 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
1448 dns_dispatch_detach(&request->dispatch);
1452 req_log(int level, const char *fmt, ...) {
1456 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1457 DNS_LOGMODULE_REQUEST, level, fmt, ap);