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