1 /*
2 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 Internet Software Consortium.
4 *
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.
8 *
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.
16 */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/magic.h>
25 #include <isc/mem.h>
26 #include <isc/task.h>
27 #include <isc/timer.h>
28 #include <isc/util.h>
29
30 #include <dns/acl.h>
31 #include <dns/compress.h>
32 #include <dns/dispatch.h>
33 #include <dns/events.h>
34 #include <dns/log.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>
40 #include <dns/tsig.h>
41
42 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
43 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
44
45 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
46 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
47
48 typedef ISC_LIST(dns_request_t) dns_requestlist_t;
49
50 #define DNS_REQUEST_NLOCKS 7
51
52 struct dns_requestmgr {
53 unsigned int magic;
54 isc_mutex_t lock;
55 isc_mem_t *mctx;
56
57 /* locked */
58 isc_int32_t eref;
59 isc_int32_t iref;
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;
68 unsigned int hash;
69 isc_mutex_t locks[DNS_REQUEST_NLOCKS];
70 dns_requestlist_t requests;
71 };
72
73 struct dns_request {
74 unsigned int magic;
75 unsigned int hash;
76 isc_mem_t *mctx;
77 isc_int32_t flags;
78 ISC_LINK(dns_request_t) link;
79 isc_buffer_t *query;
80 isc_buffer_t *answer;
81 dns_requestevent_t *event;
82 dns_dispatch_t *dispatch;
83 dns_dispentry_t *dispentry;
84 isc_timer_t *timer;
85 dns_requestmgr_t *requestmgr;
86 isc_buffer_t *tsig;
87 dns_tsigkey_t *tsigkey;
88 isc_event_t ctlevent;
89 isc_boolean_t canceling; /* ctlevent outstanding */
90 isc_sockaddr_t destaddr;
91 unsigned int udpcount;
92 };
93
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 /*%< canceled 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)
108
109
110 /***
111 *** Forward
112 ***/
113
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);
118
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 isc_socket_t * req_getsocket(dns_request_t *request);
125 static void req_connected(isc_task_t *task, isc_event_t *event);
126 static void req_sendevent(dns_request_t *request, isc_result_t result);
127 static void req_cancel(dns_request_t *request);
128 static void req_destroy(dns_request_t *request);
129 static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
130 static void do_cancel(isc_task_t *task, isc_event_t *event);
131
132 /***
133 *** Public
134 ***/
135
136 isc_result_t
dns_requestmgr_create(isc_mem_t * mctx,isc_timermgr_t * timermgr,isc_socketmgr_t * socketmgr,isc_taskmgr_t * taskmgr,dns_dispatchmgr_t * dispatchmgr,dns_dispatch_t * dispatchv4,dns_dispatch_t * dispatchv6,dns_requestmgr_t ** requestmgrp)137 dns_requestmgr_create(isc_mem_t *mctx,
138 isc_timermgr_t *timermgr,
139 isc_socketmgr_t *socketmgr,
140 isc_taskmgr_t *taskmgr,
141 dns_dispatchmgr_t *dispatchmgr,
142 dns_dispatch_t *dispatchv4,
143 dns_dispatch_t *dispatchv6,
144 dns_requestmgr_t **requestmgrp)
145 {
146 dns_requestmgr_t *requestmgr;
147 isc_socket_t *sock;
148 isc_result_t result;
149 int i;
150 unsigned int dispattr;
151
152 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
153
154 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
155 REQUIRE(timermgr != NULL);
156 REQUIRE(socketmgr != NULL);
157 REQUIRE(taskmgr != NULL);
158 REQUIRE(dispatchmgr != NULL);
159 UNUSED(sock);
160 if (dispatchv4 != NULL) {
161 dispattr = dns_dispatch_getattributes(dispatchv4);
162 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
163 }
164 if (dispatchv6 != NULL) {
165 dispattr = dns_dispatch_getattributes(dispatchv6);
166 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
167 }
168
169 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
170 if (requestmgr == NULL)
171 return (ISC_R_NOMEMORY);
172
173 result = isc_mutex_init(&requestmgr->lock);
174 if (result != ISC_R_SUCCESS) {
175 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
176 return (result);
177 }
178 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
179 result = isc_mutex_init(&requestmgr->locks[i]);
180 if (result != ISC_R_SUCCESS) {
181 while (--i >= 0)
182 DESTROYLOCK(&requestmgr->locks[i]);
183 DESTROYLOCK(&requestmgr->lock);
184 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
185 return (result);
186 }
187 }
188 requestmgr->timermgr = timermgr;
189 requestmgr->socketmgr = socketmgr;
190 requestmgr->taskmgr = taskmgr;
191 requestmgr->dispatchmgr = dispatchmgr;
192 requestmgr->dispatchv4 = NULL;
193 if (dispatchv4 != NULL)
194 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
195 requestmgr->dispatchv6 = NULL;
196 if (dispatchv6 != NULL)
197 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
198 requestmgr->mctx = NULL;
199 isc_mem_attach(mctx, &requestmgr->mctx);
200 requestmgr->eref = 1; /* implicit attach */
201 requestmgr->iref = 0;
202 ISC_LIST_INIT(requestmgr->whenshutdown);
203 ISC_LIST_INIT(requestmgr->requests);
204 requestmgr->exiting = ISC_FALSE;
205 requestmgr->hash = 0;
206 requestmgr->magic = REQUESTMGR_MAGIC;
207
208 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
209
210 *requestmgrp = requestmgr;
211 return (ISC_R_SUCCESS);
212 }
213
214 void
dns_requestmgr_whenshutdown(dns_requestmgr_t * requestmgr,isc_task_t * task,isc_event_t ** eventp)215 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
216 isc_event_t **eventp)
217 {
218 isc_task_t *clone;
219 isc_event_t *event;
220
221 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
222
223 REQUIRE(VALID_REQUESTMGR(requestmgr));
224 REQUIRE(eventp != NULL);
225
226 event = *eventp;
227 *eventp = NULL;
228
229 LOCK(&requestmgr->lock);
230
231 if (requestmgr->exiting) {
232 /*
233 * We're already shutdown. Send the event.
234 */
235 event->ev_sender = requestmgr;
236 isc_task_send(task, &event);
237 } else {
238 clone = NULL;
239 isc_task_attach(task, &clone);
240 event->ev_sender = clone;
241 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
242 }
243 UNLOCK(&requestmgr->lock);
244 }
245
246 void
dns_requestmgr_shutdown(dns_requestmgr_t * requestmgr)247 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
248
249 REQUIRE(VALID_REQUESTMGR(requestmgr));
250
251 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
252
253 LOCK(&requestmgr->lock);
254 mgr_shutdown(requestmgr);
255 UNLOCK(&requestmgr->lock);
256 }
257
258 static void
mgr_shutdown(dns_requestmgr_t * requestmgr)259 mgr_shutdown(dns_requestmgr_t *requestmgr) {
260 dns_request_t *request;
261
262 /*
263 * Caller holds lock.
264 */
265 if (!requestmgr->exiting) {
266 requestmgr->exiting = ISC_TRUE;
267 for (request = ISC_LIST_HEAD(requestmgr->requests);
268 request != NULL;
269 request = ISC_LIST_NEXT(request, link)) {
270 dns_request_cancel(request);
271 }
272 if (requestmgr->iref == 0) {
273 INSIST(ISC_LIST_EMPTY(requestmgr->requests));
274 send_shutdown_events(requestmgr);
275 }
276 }
277 }
278
279 static void
requestmgr_attach(dns_requestmgr_t * source,dns_requestmgr_t ** targetp)280 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
281
282 /*
283 * Locked by caller.
284 */
285
286 REQUIRE(VALID_REQUESTMGR(source));
287 REQUIRE(targetp != NULL && *targetp == NULL);
288
289 REQUIRE(!source->exiting);
290
291 source->iref++;
292 *targetp = source;
293
294 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
295 source, source->eref, source->iref);
296 }
297
298 static void
requestmgr_detach(dns_requestmgr_t ** requestmgrp)299 requestmgr_detach(dns_requestmgr_t **requestmgrp) {
300 dns_requestmgr_t *requestmgr;
301 isc_boolean_t need_destroy = ISC_FALSE;
302
303 REQUIRE(requestmgrp != NULL);
304 requestmgr = *requestmgrp;
305 REQUIRE(VALID_REQUESTMGR(requestmgr));
306
307 *requestmgrp = NULL;
308 LOCK(&requestmgr->lock);
309 INSIST(requestmgr->iref > 0);
310 requestmgr->iref--;
311
312 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
313 requestmgr, requestmgr->eref, requestmgr->iref);
314
315 if (requestmgr->iref == 0 && requestmgr->exiting) {
316 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
317 send_shutdown_events(requestmgr);
318 if (requestmgr->eref == 0)
319 need_destroy = ISC_TRUE;
320 }
321 UNLOCK(&requestmgr->lock);
322
323 if (need_destroy)
324 mgr_destroy(requestmgr);
325 }
326
327 void
dns_requestmgr_attach(dns_requestmgr_t * source,dns_requestmgr_t ** targetp)328 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
329
330 REQUIRE(VALID_REQUESTMGR(source));
331 REQUIRE(targetp != NULL && *targetp == NULL);
332 REQUIRE(!source->exiting);
333
334 LOCK(&source->lock);
335 source->eref++;
336 *targetp = source;
337 UNLOCK(&source->lock);
338
339 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
340 source, source->eref, source->iref);
341 }
342
343 void
dns_requestmgr_detach(dns_requestmgr_t ** requestmgrp)344 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
345 dns_requestmgr_t *requestmgr;
346 isc_boolean_t need_destroy = ISC_FALSE;
347
348 REQUIRE(requestmgrp != NULL);
349 requestmgr = *requestmgrp;
350 REQUIRE(VALID_REQUESTMGR(requestmgr));
351
352 LOCK(&requestmgr->lock);
353 INSIST(requestmgr->eref > 0);
354 requestmgr->eref--;
355
356 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
357 requestmgr, requestmgr->eref, requestmgr->iref);
358
359 if (requestmgr->eref == 0 && requestmgr->iref == 0) {
360 INSIST(requestmgr->exiting &&
361 ISC_LIST_HEAD(requestmgr->requests) == NULL);
362 need_destroy = ISC_TRUE;
363 }
364 UNLOCK(&requestmgr->lock);
365
366 if (need_destroy)
367 mgr_destroy(requestmgr);
368
369 *requestmgrp = NULL;
370 }
371
372 static void
send_shutdown_events(dns_requestmgr_t * requestmgr)373 send_shutdown_events(dns_requestmgr_t *requestmgr) {
374 isc_event_t *event, *next_event;
375 isc_task_t *etask;
376
377 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
378
379 /*
380 * Caller must be holding the manager lock.
381 */
382 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
383 event != NULL;
384 event = next_event) {
385 next_event = ISC_LIST_NEXT(event, ev_link);
386 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
387 etask = event->ev_sender;
388 event->ev_sender = requestmgr;
389 isc_task_sendanddetach(&etask, &event);
390 }
391 }
392
393 static void
mgr_destroy(dns_requestmgr_t * requestmgr)394 mgr_destroy(dns_requestmgr_t *requestmgr) {
395 int i;
396 isc_mem_t *mctx;
397
398 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
399
400 REQUIRE(requestmgr->eref == 0);
401 REQUIRE(requestmgr->iref == 0);
402
403 DESTROYLOCK(&requestmgr->lock);
404 for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
405 DESTROYLOCK(&requestmgr->locks[i]);
406 if (requestmgr->dispatchv4 != NULL)
407 dns_dispatch_detach(&requestmgr->dispatchv4);
408 if (requestmgr->dispatchv6 != NULL)
409 dns_dispatch_detach(&requestmgr->dispatchv6);
410 requestmgr->magic = 0;
411 mctx = requestmgr->mctx;
412 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
413 isc_mem_detach(&mctx);
414 }
415
416 static unsigned int
mgr_gethash(dns_requestmgr_t * requestmgr)417 mgr_gethash(dns_requestmgr_t *requestmgr) {
418 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
419 /*
420 * Locked by caller.
421 */
422 requestmgr->hash++;
423 return (requestmgr->hash % DNS_REQUEST_NLOCKS);
424 }
425
426 static inline isc_result_t
req_send(dns_request_t * request,isc_task_t * task,isc_sockaddr_t * address)427 req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
428 isc_region_t r;
429 isc_socket_t *sock;
430 isc_result_t result;
431
432 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
433
434 REQUIRE(VALID_REQUEST(request));
435 sock = req_getsocket(request);
436 isc_buffer_usedregion(request->query, &r);
437 /*
438 * We could connect the socket when we are using an exclusive dispatch
439 * as we do in resolver.c, but we prefer implementation simplicity
440 * at this moment.
441 */
442 result = isc_socket_sendto(sock, &r, task, req_senddone,
443 request, address, NULL);
444 if (result == ISC_R_SUCCESS)
445 request->flags |= DNS_REQUEST_F_SENDING;
446 return (result);
447 }
448
449 static isc_result_t
new_request(isc_mem_t * mctx,dns_request_t ** requestp)450 new_request(isc_mem_t *mctx, dns_request_t **requestp)
451 {
452 dns_request_t *request;
453
454 request = isc_mem_get(mctx, sizeof(*request));
455 if (request == NULL)
456 return (ISC_R_NOMEMORY);
457
458 /*
459 * Zero structure.
460 */
461 request->magic = 0;
462 request->mctx = NULL;
463 request->flags = 0;
464 ISC_LINK_INIT(request, link);
465 request->query = NULL;
466 request->answer = NULL;
467 request->event = NULL;
468 request->dispatch = NULL;
469 request->dispentry = NULL;
470 request->timer = NULL;
471 request->requestmgr = NULL;
472 request->tsig = NULL;
473 request->tsigkey = NULL;
474 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
475 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
476 NULL, NULL);
477 request->canceling = ISC_FALSE;
478 request->udpcount = 0;
479
480 isc_mem_attach(mctx, &request->mctx);
481
482 request->magic = REQUEST_MAGIC;
483 *requestp = request;
484 return (ISC_R_SUCCESS);
485 }
486
487
488 static isc_boolean_t
isblackholed(dns_dispatchmgr_t * dispatchmgr,isc_sockaddr_t * destaddr)489 isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
490 dns_acl_t *blackhole;
491 isc_netaddr_t netaddr;
492 int match;
493 isc_boolean_t drop = ISC_FALSE;
494 char netaddrstr[ISC_NETADDR_FORMATSIZE];
495
496 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
497 if (blackhole != NULL) {
498 isc_netaddr_fromsockaddr(&netaddr, destaddr);
499 if (dns_acl_match(&netaddr, NULL, blackhole,
500 NULL, &match, NULL) == ISC_R_SUCCESS &&
501 match > 0)
502 drop = ISC_TRUE;
503 }
504 if (drop) {
505 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
506 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
507 }
508 return (drop);
509 }
510
511 static isc_result_t
create_tcp_dispatch(dns_requestmgr_t * requestmgr,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,dns_dispatch_t ** dispatchp)512 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
513 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
514 {
515 isc_result_t result;
516 isc_socket_t *sock = NULL;
517 isc_sockaddr_t src;
518 unsigned int attrs;
519 isc_sockaddr_t bind_any;
520
521 result = isc_socket_create(requestmgr->socketmgr,
522 isc_sockaddr_pf(destaddr),
523 isc_sockettype_tcp, &sock);
524 if (result != ISC_R_SUCCESS)
525 return (result);
526 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
527 if (srcaddr == NULL) {
528 isc_sockaddr_anyofpf(&bind_any,
529 isc_sockaddr_pf(destaddr));
530 result = isc_socket_bind(sock, &bind_any, 0);
531 } else {
532 src = *srcaddr;
533 isc_sockaddr_setport(&src, 0);
534 result = isc_socket_bind(sock, &src, 0);
535 }
536 if (result != ISC_R_SUCCESS)
537 goto cleanup;
538 #endif
539 attrs = 0;
540 attrs |= DNS_DISPATCHATTR_TCP;
541 attrs |= DNS_DISPATCHATTR_PRIVATE;
542 if (isc_sockaddr_pf(destaddr) == AF_INET)
543 attrs |= DNS_DISPATCHATTR_IPV4;
544 else
545 attrs |= DNS_DISPATCHATTR_IPV6;
546 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
547 result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
548 sock, requestmgr->taskmgr,
549 4096, 2, 1, 1, 3, attrs,
550 dispatchp);
551 cleanup:
552 isc_socket_detach(&sock);
553 return (result);
554 }
555
556 static isc_result_t
find_udp_dispatch(dns_requestmgr_t * requestmgr,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,dns_dispatch_t ** dispatchp)557 find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
558 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
559 {
560 dns_dispatch_t *disp = NULL;
561 unsigned int attrs, attrmask;
562
563 if (srcaddr == NULL) {
564 switch (isc_sockaddr_pf(destaddr)) {
565 case PF_INET:
566 disp = requestmgr->dispatchv4;
567 break;
568
569 case PF_INET6:
570 disp = requestmgr->dispatchv6;
571 break;
572
573 default:
574 return (ISC_R_NOTIMPLEMENTED);
575 }
576 if (disp == NULL)
577 return (ISC_R_FAMILYNOSUPPORT);
578 dns_dispatch_attach(disp, dispatchp);
579 return (ISC_R_SUCCESS);
580 }
581 attrs = 0;
582 attrs |= DNS_DISPATCHATTR_UDP;
583 switch (isc_sockaddr_pf(srcaddr)) {
584 case PF_INET:
585 attrs |= DNS_DISPATCHATTR_IPV4;
586 break;
587
588 case PF_INET6:
589 attrs |= DNS_DISPATCHATTR_IPV6;
590 break;
591
592 default:
593 return (ISC_R_NOTIMPLEMENTED);
594 }
595 attrmask = 0;
596 attrmask |= DNS_DISPATCHATTR_UDP;
597 attrmask |= DNS_DISPATCHATTR_TCP;
598 attrmask |= DNS_DISPATCHATTR_IPV4;
599 attrmask |= DNS_DISPATCHATTR_IPV6;
600 return (dns_dispatch_getudp(requestmgr->dispatchmgr,
601 requestmgr->socketmgr,
602 requestmgr->taskmgr,
603 srcaddr, 4096,
604 1000, 32768, 16411, 16433,
605 attrs, attrmask,
606 dispatchp));
607 }
608
609 static isc_result_t
get_dispatch(isc_boolean_t tcp,dns_requestmgr_t * requestmgr,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,dns_dispatch_t ** dispatchp)610 get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
611 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
612 dns_dispatch_t **dispatchp)
613 {
614 isc_result_t result;
615 if (tcp)
616 result = create_tcp_dispatch(requestmgr, srcaddr,
617 destaddr, dispatchp);
618 else
619 result = find_udp_dispatch(requestmgr, srcaddr,
620 destaddr, dispatchp);
621 return (result);
622 }
623
624 static isc_result_t
set_timer(isc_timer_t * timer,unsigned int timeout,unsigned int udpresend)625 set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
626 isc_time_t expires;
627 isc_interval_t interval;
628 isc_result_t result;
629 isc_timertype_t timertype;
630
631 isc_interval_set(&interval, timeout, 0);
632 result = isc_time_nowplusinterval(&expires, &interval);
633 isc_interval_set(&interval, udpresend, 0);
634
635 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
636 if (result == ISC_R_SUCCESS)
637 result = isc_timer_reset(timer, timertype, &expires,
638 &interval, ISC_FALSE);
639 return (result);
640 }
641
642 isc_result_t
dns_request_createraw(dns_requestmgr_t * requestmgr,isc_buffer_t * msgbuf,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,unsigned int timeout,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)643 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
644 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
645 unsigned int options, unsigned int timeout,
646 isc_task_t *task, isc_taskaction_t action, void *arg,
647 dns_request_t **requestp)
648 {
649 return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
650 options, timeout, 0, 0, task, action,
651 arg, requestp));
652 }
653
654 isc_result_t
dns_request_createraw2(dns_requestmgr_t * requestmgr,isc_buffer_t * msgbuf,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,unsigned int timeout,unsigned int udptimeout,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)655 dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
656 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
657 unsigned int options, unsigned int timeout,
658 unsigned int udptimeout, isc_task_t *task,
659 isc_taskaction_t action, void *arg,
660 dns_request_t **requestp)
661 {
662 unsigned int udpretries = 0;
663
664 if (udptimeout != 0)
665 udpretries = timeout / udptimeout;
666
667 return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
668 options, timeout, udptimeout,
669 udpretries, task, action, arg,
670 requestp));
671 }
672
673 isc_result_t
dns_request_createraw3(dns_requestmgr_t * requestmgr,isc_buffer_t * msgbuf,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,unsigned int timeout,unsigned int udptimeout,unsigned int udpretries,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)674 dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
675 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
676 unsigned int options, unsigned int timeout,
677 unsigned int udptimeout, unsigned int udpretries,
678 isc_task_t *task, isc_taskaction_t action, void *arg,
679 dns_request_t **requestp)
680 {
681 dns_request_t *request = NULL;
682 isc_task_t *tclone = NULL;
683 isc_socket_t *sock = NULL;
684 isc_result_t result;
685 isc_mem_t *mctx;
686 dns_messageid_t id;
687 isc_boolean_t tcp = ISC_FALSE;
688 isc_region_t r;
689 unsigned int dispopt = 0;
690
691 REQUIRE(VALID_REQUESTMGR(requestmgr));
692 REQUIRE(msgbuf != NULL);
693 REQUIRE(destaddr != NULL);
694 REQUIRE(task != NULL);
695 REQUIRE(action != NULL);
696 REQUIRE(requestp != NULL && *requestp == NULL);
697 REQUIRE(timeout > 0);
698 if (srcaddr != NULL)
699 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
700
701 mctx = requestmgr->mctx;
702
703 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
704
705 if (isblackholed(requestmgr->dispatchmgr, destaddr))
706 return (DNS_R_BLACKHOLED);
707
708 request = NULL;
709 result = new_request(mctx, &request);
710 if (result != ISC_R_SUCCESS)
711 return (result);
712
713 if (udptimeout == 0 && udpretries != 0) {
714 udptimeout = timeout / (udpretries + 1);
715 if (udptimeout == 0)
716 udptimeout = 1;
717 }
718 request->udpcount = udpretries;
719
720 /*
721 * Create timer now. We will set it below once.
722 */
723 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
724 NULL, NULL, task, req_timeout, request,
725 &request->timer);
726 if (result != ISC_R_SUCCESS)
727 goto cleanup;
728
729 request->event = (dns_requestevent_t *)
730 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
731 action, arg, sizeof(dns_requestevent_t));
732 if (request->event == NULL) {
733 result = ISC_R_NOMEMORY;
734 goto cleanup;
735 }
736 isc_task_attach(task, &tclone);
737 request->event->ev_sender = task;
738 request->event->request = request;
739 request->event->result = ISC_R_FAILURE;
740
741 isc_buffer_usedregion(msgbuf, &r);
742 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
743 result = DNS_R_FORMERR;
744 goto cleanup;
745 }
746
747 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
748 tcp = ISC_TRUE;
749
750 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
751 &request->dispatch);
752 if (result != ISC_R_SUCCESS)
753 goto cleanup;
754
755 if ((options & DNS_REQUESTOPT_FIXEDID) != 0) {
756 id = (r.base[0] << 8) | r.base[1];
757 dispopt |= DNS_DISPATCHOPT_FIXEDID;
758 }
759
760 result = dns_dispatch_addresponse3(request->dispatch, dispopt,
761 destaddr, task, req_response,
762 request, &id, &request->dispentry,
763 requestmgr->socketmgr);
764 if (result != ISC_R_SUCCESS)
765 goto cleanup;
766
767 sock = req_getsocket(request);
768 INSIST(sock != NULL);
769
770 result = isc_buffer_allocate(mctx, &request->query,
771 r.length + (tcp ? 2 : 0));
772 if (result != ISC_R_SUCCESS)
773 goto cleanup;
774 if (tcp)
775 isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
776 result = isc_buffer_copyregion(request->query, &r);
777 if (result != ISC_R_SUCCESS)
778 goto cleanup;
779
780 /* Add message ID. */
781 isc_buffer_usedregion(request->query, &r);
782 if (tcp)
783 isc_region_consume(&r, 2);
784 r.base[0] = (id>>8) & 0xff;
785 r.base[1] = id & 0xff;
786
787 LOCK(&requestmgr->lock);
788 if (requestmgr->exiting) {
789 UNLOCK(&requestmgr->lock);
790 result = ISC_R_SHUTTINGDOWN;
791 goto cleanup;
792 }
793 requestmgr_attach(requestmgr, &request->requestmgr);
794 request->hash = mgr_gethash(requestmgr);
795 ISC_LIST_APPEND(requestmgr->requests, request, link);
796 UNLOCK(&requestmgr->lock);
797
798 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
799 if (result != ISC_R_SUCCESS)
800 goto unlink;
801
802 request->destaddr = *destaddr;
803 if (tcp) {
804 result = isc_socket_connect(sock, destaddr, task,
805 req_connected, request);
806 if (result != ISC_R_SUCCESS)
807 goto unlink;
808 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
809 } else {
810 result = req_send(request, task, destaddr);
811 if (result != ISC_R_SUCCESS)
812 goto unlink;
813 }
814
815 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
816 request);
817 *requestp = request;
818 return (ISC_R_SUCCESS);
819
820 unlink:
821 LOCK(&requestmgr->lock);
822 ISC_LIST_UNLINK(requestmgr->requests, request, link);
823 UNLOCK(&requestmgr->lock);
824
825 cleanup:
826 if (tclone != NULL)
827 isc_task_detach(&tclone);
828 req_destroy(request);
829 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
830 dns_result_totext(result));
831 return (result);
832 }
833
834 isc_result_t
dns_request_create(dns_requestmgr_t * requestmgr,dns_message_t * message,isc_sockaddr_t * address,unsigned int options,dns_tsigkey_t * key,unsigned int timeout,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)835 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
836 isc_sockaddr_t *address, unsigned int options,
837 dns_tsigkey_t *key,
838 unsigned int timeout, isc_task_t *task,
839 isc_taskaction_t action, void *arg,
840 dns_request_t **requestp)
841 {
842 return (dns_request_createvia3(requestmgr, message, NULL, address,
843 options, key, timeout, 0, 0, task,
844 action, arg, requestp));
845 }
846
847 isc_result_t
dns_request_createvia(dns_requestmgr_t * requestmgr,dns_message_t * message,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,dns_tsigkey_t * key,unsigned int timeout,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)848 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
849 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
850 unsigned int options, dns_tsigkey_t *key,
851 unsigned int timeout, isc_task_t *task,
852 isc_taskaction_t action, void *arg,
853 dns_request_t **requestp)
854 {
855 return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
856 options, key, timeout, 0, 0, task,
857 action, arg, requestp));
858 }
859
860 isc_result_t
dns_request_createvia2(dns_requestmgr_t * requestmgr,dns_message_t * message,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,dns_tsigkey_t * key,unsigned int timeout,unsigned int udptimeout,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)861 dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
862 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
863 unsigned int options, dns_tsigkey_t *key,
864 unsigned int timeout, unsigned int udptimeout,
865 isc_task_t *task, isc_taskaction_t action, void *arg,
866 dns_request_t **requestp)
867 {
868 unsigned int udpretries = 0;
869
870 if (udptimeout != 0)
871 udpretries = timeout / udptimeout;
872 return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
873 options, key, timeout, udptimeout,
874 udpretries, task, action, arg,
875 requestp));
876 }
877
878 isc_result_t
dns_request_createvia3(dns_requestmgr_t * requestmgr,dns_message_t * message,isc_sockaddr_t * srcaddr,isc_sockaddr_t * destaddr,unsigned int options,dns_tsigkey_t * key,unsigned int timeout,unsigned int udptimeout,unsigned int udpretries,isc_task_t * task,isc_taskaction_t action,void * arg,dns_request_t ** requestp)879 dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
880 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
881 unsigned int options, dns_tsigkey_t *key,
882 unsigned int timeout, unsigned int udptimeout,
883 unsigned int udpretries, isc_task_t *task,
884 isc_taskaction_t action, void *arg,
885 dns_request_t **requestp)
886 {
887 dns_request_t *request = NULL;
888 isc_task_t *tclone = NULL;
889 isc_socket_t *sock = NULL;
890 isc_result_t result;
891 isc_mem_t *mctx;
892 dns_messageid_t id;
893 isc_boolean_t tcp;
894 isc_boolean_t settsigkey = ISC_TRUE;
895
896 REQUIRE(VALID_REQUESTMGR(requestmgr));
897 REQUIRE(message != NULL);
898 REQUIRE(destaddr != NULL);
899 REQUIRE(task != NULL);
900 REQUIRE(action != NULL);
901 REQUIRE(requestp != NULL && *requestp == NULL);
902 REQUIRE(timeout > 0);
903
904 mctx = requestmgr->mctx;
905
906 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
907
908 if (srcaddr != NULL &&
909 isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr))
910 return (ISC_R_FAMILYMISMATCH);
911
912 if (isblackholed(requestmgr->dispatchmgr, destaddr))
913 return (DNS_R_BLACKHOLED);
914
915 request = NULL;
916 result = new_request(mctx, &request);
917 if (result != ISC_R_SUCCESS)
918 return (result);
919
920 if (udptimeout == 0 && udpretries != 0) {
921 udptimeout = timeout / (udpretries + 1);
922 if (udptimeout == 0)
923 udptimeout = 1;
924 }
925 request->udpcount = udpretries;
926
927 /*
928 * Create timer now. We will set it below once.
929 */
930 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
931 NULL, NULL, task, req_timeout, request,
932 &request->timer);
933 if (result != ISC_R_SUCCESS)
934 goto cleanup;
935
936 request->event = (dns_requestevent_t *)
937 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
938 action, arg, sizeof(dns_requestevent_t));
939 if (request->event == NULL) {
940 result = ISC_R_NOMEMORY;
941 goto cleanup;
942 }
943 isc_task_attach(task, &tclone);
944 request->event->ev_sender = task;
945 request->event->request = request;
946 request->event->result = ISC_R_FAILURE;
947 if (key != NULL)
948 dns_tsigkey_attach(key, &request->tsigkey);
949
950 use_tcp:
951 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
952 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
953 &request->dispatch);
954 if (result != ISC_R_SUCCESS)
955 goto cleanup;
956
957 result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
958 req_response, request, &id,
959 &request->dispentry,
960 requestmgr->socketmgr);
961 if (result != ISC_R_SUCCESS)
962 goto cleanup;
963 sock = req_getsocket(request);
964 INSIST(sock != NULL);
965
966 message->id = id;
967 if (settsigkey) {
968 result = dns_message_settsigkey(message, request->tsigkey);
969 if (result != ISC_R_SUCCESS)
970 goto cleanup;
971 }
972 result = req_render(message, &request->query, options, mctx);
973 if (result == DNS_R_USETCP &&
974 (options & DNS_REQUESTOPT_TCP) == 0) {
975 /*
976 * Try again using TCP.
977 */
978 dns_message_renderreset(message);
979 dns_dispatch_removeresponse(&request->dispentry, NULL);
980 dns_dispatch_detach(&request->dispatch);
981 sock = NULL;
982 options |= DNS_REQUESTOPT_TCP;
983 settsigkey = ISC_FALSE;
984 goto use_tcp;
985 }
986 if (result != ISC_R_SUCCESS)
987 goto cleanup;
988
989 result = dns_message_getquerytsig(message, mctx, &request->tsig);
990 if (result != ISC_R_SUCCESS)
991 goto cleanup;
992
993 LOCK(&requestmgr->lock);
994 if (requestmgr->exiting) {
995 UNLOCK(&requestmgr->lock);
996 result = ISC_R_SHUTTINGDOWN;
997 goto cleanup;
998 }
999 requestmgr_attach(requestmgr, &request->requestmgr);
1000 request->hash = mgr_gethash(requestmgr);
1001 ISC_LIST_APPEND(requestmgr->requests, request, link);
1002 UNLOCK(&requestmgr->lock);
1003
1004 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
1005 if (result != ISC_R_SUCCESS)
1006 goto unlink;
1007
1008 request->destaddr = *destaddr;
1009 if (tcp) {
1010 result = isc_socket_connect(sock, destaddr, task,
1011 req_connected, request);
1012 if (result != ISC_R_SUCCESS)
1013 goto unlink;
1014 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
1015 } else {
1016 result = req_send(request, task, destaddr);
1017 if (result != ISC_R_SUCCESS)
1018 goto unlink;
1019 }
1020
1021 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
1022 request);
1023 *requestp = request;
1024 return (ISC_R_SUCCESS);
1025
1026 unlink:
1027 LOCK(&requestmgr->lock);
1028 ISC_LIST_UNLINK(requestmgr->requests, request, link);
1029 UNLOCK(&requestmgr->lock);
1030
1031 cleanup:
1032 if (tclone != NULL)
1033 isc_task_detach(&tclone);
1034 req_destroy(request);
1035 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
1036 dns_result_totext(result));
1037 return (result);
1038 }
1039
1040 static isc_result_t
req_render(dns_message_t * message,isc_buffer_t ** bufferp,unsigned int options,isc_mem_t * mctx)1041 req_render(dns_message_t *message, isc_buffer_t **bufferp,
1042 unsigned int options, isc_mem_t *mctx)
1043 {
1044 isc_buffer_t *buf1 = NULL;
1045 isc_buffer_t *buf2 = NULL;
1046 isc_result_t result;
1047 isc_region_t r;
1048 isc_boolean_t tcp = ISC_FALSE;
1049 dns_compress_t cctx;
1050 isc_boolean_t cleanup_cctx = ISC_FALSE;
1051
1052 REQUIRE(bufferp != NULL && *bufferp == NULL);
1053
1054 req_log(ISC_LOG_DEBUG(3), "request_render");
1055
1056 /*
1057 * Create buffer able to hold largest possible message.
1058 */
1059 result = isc_buffer_allocate(mctx, &buf1, 65535);
1060 if (result != ISC_R_SUCCESS)
1061 return (result);
1062
1063 result = dns_compress_init(&cctx, -1, mctx);
1064 if (result != ISC_R_SUCCESS)
1065 return (result);
1066 cleanup_cctx = ISC_TRUE;
1067
1068 if ((options & DNS_REQUESTOPT_CASE) != 0)
1069 dns_compress_setsensitive(&cctx, ISC_TRUE);
1070
1071 /*
1072 * Render message.
1073 */
1074 result = dns_message_renderbegin(message, &cctx, buf1);
1075 if (result != ISC_R_SUCCESS)
1076 goto cleanup;
1077 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
1078 if (result != ISC_R_SUCCESS)
1079 goto cleanup;
1080 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
1081 if (result != ISC_R_SUCCESS)
1082 goto cleanup;
1083 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
1084 if (result != ISC_R_SUCCESS)
1085 goto cleanup;
1086 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
1087 if (result != ISC_R_SUCCESS)
1088 goto cleanup;
1089 result = dns_message_renderend(message);
1090 if (result != ISC_R_SUCCESS)
1091 goto cleanup;
1092
1093 dns_compress_invalidate(&cctx);
1094 cleanup_cctx = ISC_FALSE;
1095
1096 /*
1097 * Copy rendered message to exact sized buffer.
1098 */
1099 isc_buffer_usedregion(buf1, &r);
1100 if ((options & DNS_REQUESTOPT_TCP) != 0) {
1101 tcp = ISC_TRUE;
1102 } else if (r.length > 512) {
1103 result = DNS_R_USETCP;
1104 goto cleanup;
1105 }
1106 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
1107 if (result != ISC_R_SUCCESS)
1108 goto cleanup;
1109 if (tcp)
1110 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
1111 result = isc_buffer_copyregion(buf2, &r);
1112 if (result != ISC_R_SUCCESS)
1113 goto cleanup;
1114
1115 /*
1116 * Cleanup and return.
1117 */
1118 isc_buffer_free(&buf1);
1119 *bufferp = buf2;
1120 return (ISC_R_SUCCESS);
1121
1122 cleanup:
1123 dns_message_renderreset(message);
1124 if (buf1 != NULL)
1125 isc_buffer_free(&buf1);
1126 if (buf2 != NULL)
1127 isc_buffer_free(&buf2);
1128 if (cleanup_cctx)
1129 dns_compress_invalidate(&cctx);
1130 return (result);
1131 }
1132
1133
1134 /*
1135 * If this request is no longer waiting for events,
1136 * send the completion event. This will ultimately
1137 * cause the request to be destroyed.
1138 *
1139 * Requires:
1140 * 'request' is locked by the caller.
1141 */
1142 static void
send_if_done(dns_request_t * request,isc_result_t result)1143 send_if_done(dns_request_t *request, isc_result_t result) {
1144 if (request->event != NULL && !request->canceling)
1145 req_sendevent(request, result);
1146 }
1147
1148 /*
1149 * Handle the control event.
1150 */
1151 static void
do_cancel(isc_task_t * task,isc_event_t * event)1152 do_cancel(isc_task_t *task, isc_event_t *event) {
1153 dns_request_t *request = event->ev_arg;
1154 UNUSED(task);
1155 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
1156 LOCK(&request->requestmgr->locks[request->hash]);
1157 request->canceling = ISC_FALSE;
1158 if (!DNS_REQUEST_CANCELED(request))
1159 req_cancel(request);
1160 send_if_done(request, ISC_R_CANCELED);
1161 UNLOCK(&request->requestmgr->locks[request->hash]);
1162 }
1163
1164 void
dns_request_cancel(dns_request_t * request)1165 dns_request_cancel(dns_request_t *request) {
1166 REQUIRE(VALID_REQUEST(request));
1167
1168 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
1169
1170 REQUIRE(VALID_REQUEST(request));
1171
1172 LOCK(&request->requestmgr->locks[request->hash]);
1173 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
1174 isc_event_t *ev = &request->ctlevent;
1175 isc_task_send(request->event->ev_sender, &ev);
1176 request->canceling = ISC_TRUE;
1177 }
1178 UNLOCK(&request->requestmgr->locks[request->hash]);
1179 }
1180
1181 isc_result_t
dns_request_getresponse(dns_request_t * request,dns_message_t * message,unsigned int options)1182 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
1183 unsigned int options)
1184 {
1185 isc_result_t result;
1186
1187 REQUIRE(VALID_REQUEST(request));
1188 REQUIRE(request->answer != NULL);
1189
1190 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
1191 request);
1192
1193 result = dns_message_setquerytsig(message, request->tsig);
1194 if (result != ISC_R_SUCCESS)
1195 return (result);
1196 result = dns_message_settsigkey(message, request->tsigkey);
1197 if (result != ISC_R_SUCCESS)
1198 return (result);
1199 result = dns_message_parse(message, request->answer, options);
1200 if (result != ISC_R_SUCCESS)
1201 return (result);
1202 if (request->tsigkey != NULL)
1203 result = dns_tsig_verify(request->answer, message, NULL, NULL);
1204 return (result);
1205 }
1206
1207 isc_boolean_t
dns_request_usedtcp(dns_request_t * request)1208 dns_request_usedtcp(dns_request_t *request) {
1209 REQUIRE(VALID_REQUEST(request));
1210
1211 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
1212 }
1213
1214 void
dns_request_destroy(dns_request_t ** requestp)1215 dns_request_destroy(dns_request_t **requestp) {
1216 dns_request_t *request;
1217
1218 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
1219
1220 request = *requestp;
1221
1222 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
1223
1224 LOCK(&request->requestmgr->lock);
1225 LOCK(&request->requestmgr->locks[request->hash]);
1226 ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
1227 INSIST(!DNS_REQUEST_CONNECTING(request));
1228 INSIST(!DNS_REQUEST_SENDING(request));
1229 UNLOCK(&request->requestmgr->locks[request->hash]);
1230 UNLOCK(&request->requestmgr->lock);
1231
1232 /*
1233 * These should have been cleaned up by req_cancel() before
1234 * the completion event was sent.
1235 */
1236 INSIST(!ISC_LINK_LINKED(request, link));
1237 INSIST(request->dispentry == NULL);
1238 INSIST(request->dispatch == NULL);
1239 INSIST(request->timer == NULL);
1240
1241 req_destroy(request);
1242
1243 *requestp = NULL;
1244 }
1245
1246 /***
1247 *** Private: request.
1248 ***/
1249
1250 static isc_socket_t *
req_getsocket(dns_request_t * request)1251 req_getsocket(dns_request_t *request) {
1252 unsigned int dispattr;
1253 isc_socket_t *sock;
1254
1255 dispattr = dns_dispatch_getattributes(request->dispatch);
1256 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
1257 INSIST(request->dispentry != NULL);
1258 sock = dns_dispatch_getentrysocket(request->dispentry);
1259 } else
1260 sock = dns_dispatch_getsocket(request->dispatch);
1261
1262 return (sock);
1263 }
1264
1265 static void
req_connected(isc_task_t * task,isc_event_t * event)1266 req_connected(isc_task_t *task, isc_event_t *event) {
1267 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1268 isc_result_t result;
1269 dns_request_t *request = event->ev_arg;
1270
1271 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1272 REQUIRE(VALID_REQUEST(request));
1273 REQUIRE(DNS_REQUEST_CONNECTING(request));
1274
1275 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
1276
1277 LOCK(&request->requestmgr->locks[request->hash]);
1278 request->flags &= ~DNS_REQUEST_F_CONNECTING;
1279
1280 if (DNS_REQUEST_CANCELED(request)) {
1281 /*
1282 * Send delayed event.
1283 */
1284 if (DNS_REQUEST_TIMEDOUT(request))
1285 send_if_done(request, ISC_R_TIMEDOUT);
1286 else
1287 send_if_done(request, ISC_R_CANCELED);
1288 } else {
1289 dns_dispatch_starttcp(request->dispatch);
1290 result = sevent->result;
1291 if (result == ISC_R_SUCCESS)
1292 result = req_send(request, task, NULL);
1293
1294 if (result != ISC_R_SUCCESS) {
1295 req_cancel(request);
1296 send_if_done(request, ISC_R_CANCELED);
1297 }
1298 }
1299 UNLOCK(&request->requestmgr->locks[request->hash]);
1300 isc_event_free(&event);
1301 }
1302
1303 static void
req_senddone(isc_task_t * task,isc_event_t * event)1304 req_senddone(isc_task_t *task, isc_event_t *event) {
1305 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1306 dns_request_t *request = event->ev_arg;
1307
1308 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1309 REQUIRE(VALID_REQUEST(request));
1310 REQUIRE(DNS_REQUEST_SENDING(request));
1311
1312 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
1313
1314 UNUSED(task);
1315
1316 LOCK(&request->requestmgr->locks[request->hash]);
1317 request->flags &= ~DNS_REQUEST_F_SENDING;
1318
1319 if (DNS_REQUEST_CANCELED(request)) {
1320 /*
1321 * Send delayed event.
1322 */
1323 if (DNS_REQUEST_TIMEDOUT(request))
1324 send_if_done(request, ISC_R_TIMEDOUT);
1325 else
1326 send_if_done(request, ISC_R_CANCELED);
1327 } else if (sevent->result != ISC_R_SUCCESS) {
1328 req_cancel(request);
1329 send_if_done(request, ISC_R_CANCELED);
1330 }
1331 UNLOCK(&request->requestmgr->locks[request->hash]);
1332
1333 isc_event_free(&event);
1334 }
1335
1336 static void
req_response(isc_task_t * task,isc_event_t * event)1337 req_response(isc_task_t *task, isc_event_t *event) {
1338 isc_result_t result;
1339 dns_request_t *request = event->ev_arg;
1340 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
1341 isc_region_t r;
1342
1343 REQUIRE(VALID_REQUEST(request));
1344 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
1345
1346 UNUSED(task);
1347
1348 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
1349 dns_result_totext(devent->result));
1350
1351 LOCK(&request->requestmgr->locks[request->hash]);
1352 result = devent->result;
1353 if (result != ISC_R_SUCCESS)
1354 goto done;
1355
1356 /*
1357 * Copy buffer to request.
1358 */
1359 isc_buffer_usedregion(&devent->buffer, &r);
1360 result = isc_buffer_allocate(request->mctx, &request->answer,
1361 r.length);
1362 if (result != ISC_R_SUCCESS)
1363 goto done;
1364 result = isc_buffer_copyregion(request->answer, &r);
1365 if (result != ISC_R_SUCCESS)
1366 isc_buffer_free(&request->answer);
1367 done:
1368 /*
1369 * Cleanup.
1370 */
1371 dns_dispatch_removeresponse(&request->dispentry, &devent);
1372 req_cancel(request);
1373 /*
1374 * Send completion event.
1375 */
1376 send_if_done(request, result);
1377 UNLOCK(&request->requestmgr->locks[request->hash]);
1378 }
1379
1380 static void
req_timeout(isc_task_t * task,isc_event_t * event)1381 req_timeout(isc_task_t *task, isc_event_t *event) {
1382 dns_request_t *request = event->ev_arg;
1383 isc_result_t result;
1384
1385 REQUIRE(VALID_REQUEST(request));
1386
1387 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
1388
1389 UNUSED(task);
1390 LOCK(&request->requestmgr->locks[request->hash]);
1391 if (event->ev_type == ISC_TIMEREVENT_TICK &&
1392 request->udpcount-- != 0) {
1393 if (! DNS_REQUEST_SENDING(request)) {
1394 result = req_send(request, task, &request->destaddr);
1395 if (result != ISC_R_SUCCESS) {
1396 req_cancel(request);
1397 send_if_done(request, result);
1398 }
1399 }
1400 } else {
1401 request->flags |= DNS_REQUEST_F_TIMEDOUT;
1402 req_cancel(request);
1403 send_if_done(request, ISC_R_TIMEDOUT);
1404 }
1405 UNLOCK(&request->requestmgr->locks[request->hash]);
1406 isc_event_free(&event);
1407 }
1408
1409 static void
req_sendevent(dns_request_t * request,isc_result_t result)1410 req_sendevent(dns_request_t *request, isc_result_t result) {
1411 isc_task_t *task;
1412
1413 REQUIRE(VALID_REQUEST(request));
1414
1415 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
1416
1417 /*
1418 * Lock held by caller.
1419 */
1420 task = request->event->ev_sender;
1421 request->event->ev_sender = request;
1422 request->event->result = result;
1423 isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
1424 }
1425
1426 static void
req_destroy(dns_request_t * request)1427 req_destroy(dns_request_t *request) {
1428 isc_mem_t *mctx;
1429
1430 REQUIRE(VALID_REQUEST(request));
1431
1432 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
1433
1434 request->magic = 0;
1435 if (request->query != NULL)
1436 isc_buffer_free(&request->query);
1437 if (request->answer != NULL)
1438 isc_buffer_free(&request->answer);
1439 if (request->event != NULL)
1440 isc_event_free((isc_event_t **)&request->event);
1441 if (request->dispentry != NULL)
1442 dns_dispatch_removeresponse(&request->dispentry, NULL);
1443 if (request->dispatch != NULL)
1444 dns_dispatch_detach(&request->dispatch);
1445 if (request->timer != NULL)
1446 isc_timer_detach(&request->timer);
1447 if (request->tsig != NULL)
1448 isc_buffer_free(&request->tsig);
1449 if (request->tsigkey != NULL)
1450 dns_tsigkey_detach(&request->tsigkey);
1451 if (request->requestmgr != NULL)
1452 requestmgr_detach(&request->requestmgr);
1453 mctx = request->mctx;
1454 isc_mem_put(mctx, request, sizeof(*request));
1455 isc_mem_detach(&mctx);
1456 }
1457
1458 /*
1459 * Stop the current request. Must be called from the request's task.
1460 */
1461 static void
req_cancel(dns_request_t * request)1462 req_cancel(dns_request_t *request) {
1463 isc_socket_t *sock;
1464 unsigned int dispattr;
1465
1466 REQUIRE(VALID_REQUEST(request));
1467
1468 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
1469
1470 /*
1471 * Lock held by caller.
1472 */
1473 request->flags |= DNS_REQUEST_F_CANCELED;
1474
1475 if (request->timer != NULL)
1476 isc_timer_detach(&request->timer);
1477 dispattr = dns_dispatch_getattributes(request->dispatch);
1478 sock = NULL;
1479 if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
1480 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
1481 if (request->dispentry != NULL) {
1482 sock = dns_dispatch_getentrysocket(
1483 request->dispentry);
1484 }
1485 } else
1486 sock = dns_dispatch_getsocket(request->dispatch);
1487 if (DNS_REQUEST_CONNECTING(request) && sock != NULL)
1488 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT);
1489 if (DNS_REQUEST_SENDING(request) && sock != NULL)
1490 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
1491 }
1492 if (request->dispentry != NULL)
1493 dns_dispatch_removeresponse(&request->dispentry, NULL);
1494 dns_dispatch_detach(&request->dispatch);
1495 }
1496
1497 static void
req_log(int level,const char * fmt,...)1498 req_log(int level, const char *fmt, ...) {
1499 va_list ap;
1500
1501 va_start(ap, fmt);
1502 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1503 DNS_LOGMODULE_REQUEST, level, fmt, ap);
1504 va_end(ap);
1505 }
1506