Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / request.c
blob0b16a0b1845ca7277bdabf53824362a61bb35456
1 /*
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 $ */
20 #include <config.h>
22 #include <isc/magic.h>
23 #include <isc/mem.h>
24 #include <isc/task.h>
25 #include <isc/timer.h>
26 #include <isc/util.h>
28 #include <dns/acl.h>
29 #include <dns/compress.h>
30 #include <dns/dispatch.h>
31 #include <dns/events.h>
32 #include <dns/log.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>
38 #include <dns/tsig.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 {
51 unsigned int magic;
52 isc_mutex_t lock;
53 isc_mem_t *mctx;
55 /* locked */
56 isc_int32_t eref;
57 isc_int32_t iref;
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;
66 unsigned int hash;
67 isc_mutex_t locks[DNS_REQUEST_NLOCKS];
68 dns_requestlist_t requests;
71 struct dns_request {
72 unsigned int magic;
73 unsigned int hash;
74 isc_mem_t *mctx;
75 isc_int32_t flags;
76 ISC_LINK(dns_request_t) link;
77 isc_buffer_t *query;
78 isc_buffer_t *answer;
79 dns_requestevent_t *event;
80 dns_dispatch_t *dispatch;
81 dns_dispentry_t *dispentry;
82 isc_timer_t *timer;
83 dns_requestmgr_t *requestmgr;
84 isc_buffer_t *tsig;
85 dns_tsigkey_t *tsigkey;
86 isc_event_t ctlevent;
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)
106 /***
107 *** Forward
108 ***/
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);
127 /***
128 *** Public
129 ***/
131 isc_result_t
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;
143 isc_result_t result;
144 int i;
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));
169 return (result);
171 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
172 result = isc_mutex_init(&requestmgr->locks[i]);
173 if (result != ISC_R_SUCCESS) {
174 while (--i >= 0)
175 DESTROYLOCK(&requestmgr->locks[i]);
176 DESTROYLOCK(&requestmgr->lock);
177 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
178 return (result);
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);
207 void
208 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
209 isc_event_t **eventp)
211 isc_task_t *clone;
212 isc_event_t *event;
214 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
216 REQUIRE(VALID_REQUESTMGR(requestmgr));
217 REQUIRE(eventp != NULL);
219 event = *eventp;
220 *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);
230 } else {
231 clone = NULL;
232 isc_task_attach(task, &clone);
233 event->ev_sender = clone;
234 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
236 UNLOCK(&requestmgr->lock);
239 void
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);
251 static void
252 mgr_shutdown(dns_requestmgr_t *requestmgr) {
253 dns_request_t *request;
256 * Caller holds lock.
258 if (!requestmgr->exiting) {
259 requestmgr->exiting = ISC_TRUE;
260 for (request = ISC_LIST_HEAD(requestmgr->requests);
261 request != NULL;
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);
272 static void
273 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
276 * Locked by caller.
279 REQUIRE(VALID_REQUESTMGR(source));
280 REQUIRE(targetp != NULL && *targetp == NULL);
282 REQUIRE(!source->exiting);
284 source->iref++;
285 *targetp = source;
287 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
288 source, source->eref, source->iref);
291 static void
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));
300 *requestmgrp = NULL;
301 LOCK(&requestmgr->lock);
302 INSIST(requestmgr->iref > 0);
303 requestmgr->iref--;
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);
316 if (need_destroy)
317 mgr_destroy(requestmgr);
320 void
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);
327 LOCK(&source->lock);
328 source->eref++;
329 *targetp = source;
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);
336 void
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);
347 requestmgr->eref--;
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);
359 if (need_destroy)
360 mgr_destroy(requestmgr);
362 *requestmgrp = NULL;
365 static void
366 send_shutdown_events(dns_requestmgr_t *requestmgr) {
367 isc_event_t *event, *next_event;
368 isc_task_t *etask;
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);
376 event != NULL;
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);
386 static void
387 mgr_destroy(dns_requestmgr_t *requestmgr) {
388 int i;
389 isc_mem_t *mctx;
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);
409 static unsigned int
410 mgr_gethash(dns_requestmgr_t *requestmgr) {
411 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
413 * Locked by caller.
415 requestmgr->hash++;
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) {
421 isc_region_t r;
422 isc_socket_t *socket;
423 isc_result_t result;
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;
434 return (result);
437 static isc_result_t
438 new_request(isc_mem_t *mctx, dns_request_t **requestp) {
439 dns_request_t *request;
441 request = isc_mem_get(mctx, sizeof(*request));
442 if (request == NULL)
443 return (ISC_R_NOMEMORY);
446 * Zero structure.
448 request->magic = 0;
449 request->mctx = NULL;
450 request->flags = 0;
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,
463 NULL, NULL);
464 request->canceling = ISC_FALSE;
466 isc_mem_attach(mctx, &request->mctx);
468 request->magic = REQUEST_MAGIC;
469 *requestp = request;
470 return (ISC_R_SUCCESS);
474 static isc_boolean_t
475 isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
476 dns_acl_t *blackhole;
477 isc_netaddr_t netaddr;
478 int match;
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 &&
487 match > 0)
488 drop = ISC_TRUE;
490 if (drop) {
491 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
492 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
494 return (drop);
497 static isc_result_t
498 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
499 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
501 isc_result_t result;
502 isc_socket_t *socket = NULL;
503 isc_sockaddr_t src;
504 unsigned int attrs;
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)
511 return (result);
512 if (srcaddr == NULL) {
513 isc_sockaddr_anyofpf(&bind_any,
514 isc_sockaddr_pf(destaddr));
515 result = isc_socket_bind(socket, &bind_any);
516 } else {
517 src = *srcaddr;
518 isc_sockaddr_setport(&src, 0);
519 result = isc_socket_bind(socket, &src);
521 if (result != ISC_R_SUCCESS)
522 goto cleanup;
523 attrs = 0;
524 attrs |= DNS_DISPATCHATTR_TCP;
525 attrs |= DNS_DISPATCHATTR_PRIVATE;
526 if (isc_sockaddr_pf(destaddr) == AF_INET)
527 attrs |= DNS_DISPATCHATTR_IPV4;
528 else
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,
534 dispatchp);
535 cleanup:
536 isc_socket_detach(&socket);
537 return (result);
540 static isc_result_t
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)) {
549 case PF_INET:
550 disp = requestmgr->dispatchv4;
551 break;
553 case PF_INET6:
554 disp = requestmgr->dispatchv6;
555 break;
557 default:
558 return (ISC_R_NOTIMPLEMENTED);
560 if (disp == NULL)
561 return (ISC_R_FAMILYNOSUPPORT);
562 dns_dispatch_attach(disp, dispatchp);
563 return (ISC_R_SUCCESS);
565 attrs = 0;
566 attrs |= DNS_DISPATCHATTR_UDP;
567 switch (isc_sockaddr_pf(srcaddr)) {
568 case PF_INET:
569 attrs |= DNS_DISPATCHATTR_IPV4;
570 break;
572 case PF_INET6:
573 attrs |= DNS_DISPATCHATTR_IPV6;
574 break;
576 default:
577 return (ISC_R_NOTIMPLEMENTED);
579 attrmask = 0;
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,
586 requestmgr->taskmgr,
587 srcaddr, 4096,
588 1000, 32768, 16411, 16433,
589 attrs, attrmask,
590 dispatchp));
593 static isc_result_t
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)
598 isc_result_t result;
599 if (tcp)
600 result = create_tcp_dispatch(requestmgr, srcaddr,
601 destaddr, dispatchp);
602 else
603 result = find_udp_dispatch(requestmgr, srcaddr,
604 destaddr, dispatchp);
605 return (result);
608 static isc_result_t
609 set_timer(isc_timer_t *timer, unsigned int timeout) {
610 isc_time_t expires;
611 isc_interval_t interval;
612 isc_result_t result;
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,
619 NULL, ISC_FALSE);
620 return (result);
623 isc_result_t
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;
633 isc_result_t result;
634 isc_mem_t *mctx;
635 dns_messageid_t id;
636 isc_boolean_t tcp = ISC_FALSE;
637 isc_region_t r;
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);
646 if (srcaddr != NULL)
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);
656 request = NULL;
657 result = new_request(mctx, &request);
658 if (result != ISC_R_SUCCESS)
659 return (result);
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,
666 &request->timer);
667 if (result != ISC_R_SUCCESS)
668 goto cleanup;
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;
675 goto cleanup;
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;
685 goto cleanup;
688 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
689 tcp = ISC_TRUE;
691 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
692 &request->dispatch);
693 if (result != ISC_R_SUCCESS)
694 goto cleanup;
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)
702 goto cleanup;
704 result = isc_buffer_allocate(mctx, &request->query,
705 r.length + (tcp ? 2 : 0));
706 if (result != ISC_R_SUCCESS)
707 goto cleanup;
708 if (tcp)
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)
712 goto cleanup;
714 /* Add message ID. */
715 isc_buffer_usedregion(request->query, &r);
716 if (tcp)
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;
725 goto cleanup;
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)
734 goto unlink;
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)
740 goto unlink;
741 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
742 } else {
743 result = req_send(request, task, destaddr);
744 if (result != ISC_R_SUCCESS)
745 goto unlink;
748 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
749 request);
750 *requestp = request;
751 return (ISC_R_SUCCESS);
753 unlink:
754 LOCK(&requestmgr->lock);
755 ISC_LIST_UNLINK(requestmgr->requests, request, link);
756 UNLOCK(&requestmgr->lock);
758 cleanup:
759 if (tclone != NULL)
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));
764 return (result);
767 isc_result_t
768 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
769 isc_sockaddr_t *address, unsigned int options,
770 dns_tsigkey_t *key,
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,
777 arg, requestp));
780 isc_result_t
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;
791 isc_result_t result;
792 isc_mem_t *mctx;
793 dns_messageid_t id;
794 isc_boolean_t tcp;
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);
804 if (srcaddr != NULL)
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);
814 request = NULL;
815 result = new_request(mctx, &request);
816 if (result != ISC_R_SUCCESS)
817 return (result);
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,
824 &request->timer);
825 if (result != ISC_R_SUCCESS)
826 goto cleanup;
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;
833 goto cleanup;
835 isc_task_attach(task, &tclone);
836 request->event->ev_sender = task;
837 request->event->request = request;
838 request->event->result = ISC_R_FAILURE;
839 if (key != NULL)
840 dns_tsigkey_attach(key, &request->tsigkey);
842 use_tcp:
843 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
844 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
845 &request->dispatch);
846 if (result != ISC_R_SUCCESS)
847 goto cleanup;
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)
855 goto cleanup;
857 message->id = id;
858 if (setkey)
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);
869 socket = NULL;
870 options |= DNS_REQUESTOPT_TCP;
871 setkey = ISC_FALSE;
872 goto use_tcp;
874 if (result != ISC_R_SUCCESS)
875 goto cleanup;
877 result = dns_message_getquerytsig(message, mctx, &request->tsig);
878 if (result != ISC_R_SUCCESS)
879 goto cleanup;
881 LOCK(&requestmgr->lock);
882 if (requestmgr->exiting) {
883 UNLOCK(&requestmgr->lock);
884 result = ISC_R_SHUTTINGDOWN;
885 goto cleanup;
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)
894 goto unlink;
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)
900 goto unlink;
901 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
902 } else {
903 result = req_send(request, task, destaddr);
904 if (result != ISC_R_SUCCESS)
905 goto unlink;
908 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
909 request);
910 *requestp = request;
911 return (ISC_R_SUCCESS);
913 unlink:
914 LOCK(&requestmgr->lock);
915 ISC_LIST_UNLINK(requestmgr->requests, request, link);
916 UNLOCK(&requestmgr->lock);
918 cleanup:
919 if (tclone != NULL)
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));
924 return (result);
927 static isc_result_t
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;
933 isc_result_t result;
934 isc_region_t r;
935 isc_boolean_t tcp = ISC_FALSE;
936 dns_compress_t cctx;
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)
948 return (result);
950 result = dns_compress_init(&cctx, -1, mctx);
951 if (result != ISC_R_SUCCESS)
952 return (result);
953 cleanup_cctx = ISC_TRUE;
956 * Render message.
958 result = dns_message_renderbegin(message, &cctx, buf1);
959 if (result != ISC_R_SUCCESS)
960 goto cleanup;
961 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
962 if (result != ISC_R_SUCCESS)
963 goto cleanup;
964 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
965 if (result != ISC_R_SUCCESS)
966 goto cleanup;
967 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
968 if (result != ISC_R_SUCCESS)
969 goto cleanup;
970 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
971 if (result != ISC_R_SUCCESS)
972 goto cleanup;
973 result = dns_message_renderend(message);
974 if (result != ISC_R_SUCCESS)
975 goto cleanup;
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) {
985 tcp = ISC_TRUE;
986 } else if (r.length > 512) {
987 result = DNS_R_USETCP;
988 goto cleanup;
990 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
991 if (result != ISC_R_SUCCESS)
992 goto cleanup;
993 if (tcp)
994 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
995 result = isc_buffer_copyregion(buf2, &r);
996 if (result != ISC_R_SUCCESS)
997 goto cleanup;
1000 * Cleanup and return.
1002 isc_buffer_free(&buf1);
1003 *bufferp = buf2;
1004 return (ISC_R_SUCCESS);
1006 cleanup:
1007 dns_message_renderreset(message);
1008 if (buf1 != NULL)
1009 isc_buffer_free(&buf1);
1010 if (buf2 != NULL)
1011 isc_buffer_free(&buf2);
1012 if (cleanup_cctx)
1013 dns_compress_invalidate(&cctx);
1014 return (result);
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.
1023 * Requires:
1024 * 'request' is locked by the caller.
1026 static void
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.
1037 static void
1038 do_cancel(isc_task_t *task, isc_event_t *event) {
1039 dns_request_t *request = event->ev_arg;
1040 UNUSED(task);
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]);
1050 isc_result_t
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);
1068 isc_result_t
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",
1078 request);
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)
1084 return (result);
1085 if (request->tsigkey != NULL)
1086 result = dns_tsig_verify(request->answer, message, NULL, NULL);
1087 return (result);
1090 isc_boolean_t
1091 dns_request_usedtcp(dns_request_t *request) {
1092 REQUIRE(VALID_REQUEST(request));
1094 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
1097 void
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);
1126 *requestp = NULL;
1129 /***
1130 *** Private: request.
1131 ***/
1133 static void
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);
1154 else
1155 send_if_done(request, ISC_R_CANCELED);
1156 } else {
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);
1171 static void
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);
1182 UNUSED(task);
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);
1193 else
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);
1204 static void
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;
1209 isc_region_t r;
1211 REQUIRE(VALID_REQUEST(request));
1212 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
1214 UNUSED(task);
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)
1222 goto done;
1225 * Copy buffer to request.
1227 isc_buffer_usedregion(&devent->buffer, &r);
1228 result = isc_buffer_allocate(request->mctx, &request->answer,
1229 r.length);
1230 if (result != ISC_R_SUCCESS)
1231 goto done;
1232 result = isc_buffer_copyregion(request->answer, &r);
1233 if (result != ISC_R_SUCCESS)
1234 isc_buffer_free(&request->answer);
1235 done:
1237 * Cleanup.
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]);
1248 static void
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);
1256 UNUSED(task);
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);
1265 static void
1266 req_sendevent(dns_request_t *request, isc_result_t result) {
1267 isc_task_t *task;
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);
1282 static void
1283 req_destroy(dns_request_t *request) {
1284 isc_mem_t *mctx;
1286 REQUIRE(VALID_REQUEST(request));
1288 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
1290 request->magic = 0;
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.
1317 static void
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);
1345 static void
1346 req_log(int level, const char *fmt, ...) {
1347 va_list ap;
1349 va_start(ap, fmt);
1350 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1351 DNS_LOGMODULE_REQUEST, level, fmt, ap);
1352 va_end(ap);