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