xref: /minix/external/bsd/bind/dist/lib/dns/request.c (revision 00b67f09)
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