Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dispatch.c,v 1.16 2026/06/19 20:09:59 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <inttypes.h>
     19 #include <stdbool.h>
     20 #include <stdlib.h>
     21 #include <sys/types.h>
     22 #include <unistd.h>
     23 
     24 #include <isc/async.h>
     25 #include <isc/hash.h>
     26 #include <isc/hashmap.h>
     27 #include <isc/loop.h>
     28 #include <isc/mem.h>
     29 #include <isc/mutex.h>
     30 #include <isc/net.h>
     31 #include <isc/netmgr.h>
     32 #include <isc/portset.h>
     33 #include <isc/random.h>
     34 #include <isc/stats.h>
     35 #include <isc/string.h>
     36 #include <isc/tid.h>
     37 #include <isc/time.h>
     38 #include <isc/tls.h>
     39 #include <isc/urcu.h>
     40 #include <isc/util.h>
     41 
     42 #include <dns/acl.h>
     43 #include <dns/dispatch.h>
     44 #include <dns/log.h>
     45 #include <dns/message.h>
     46 #include <dns/stats.h>
     47 #include <dns/transport.h>
     48 #include <dns/types.h>
     49 
     50 /*
     51  * Maximum number of queries to pipeline on a single shared TCP dispatch.
     52  * Once reached, the dispatch is removed from the hash table so new queries
     53  * get a fresh connection.  Can be overridden via 'named -T tcppipelining=N'.
     54  */
     55 size_t dns_dispatch_tcppipelining = 256;
     56 
     57 typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
     58 
     59 struct dns_dispatchmgr {
     60 	/* Unlocked. */
     61 	unsigned int magic;
     62 	isc_refcount_t references;
     63 	isc_mem_t *mctx;
     64 	dns_acl_t *blackhole;
     65 	isc_stats_t *stats;
     66 	isc_nm_t *nm;
     67 
     68 	uint32_t nloops;
     69 
     70 	struct cds_lfht **tcps;
     71 
     72 	struct cds_lfht *qids;
     73 
     74 	in_port_t *v4ports;    /*%< available ports for IPv4 */
     75 	unsigned int nv4ports; /*%< # of available ports for IPv4 */
     76 	in_port_t *v6ports;    /*%< available ports for IPv6 */
     77 	unsigned int nv6ports; /*%< # of available ports for IPv6 */
     78 };
     79 
     80 typedef enum {
     81 	DNS_DISPATCHSTATE_NONE = 0UL,
     82 	DNS_DISPATCHSTATE_CONNECTING,
     83 	DNS_DISPATCHSTATE_CONNECTED,
     84 	DNS_DISPATCHSTATE_CANCELED,
     85 } dns_dispatchstate_t;
     86 
     87 struct dns_dispentry {
     88 	unsigned int magic;
     89 	isc_refcount_t references;
     90 	isc_mem_t *mctx;
     91 	dns_dispatch_t *disp;
     92 	isc_loop_t *loop;
     93 	isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */
     94 	dns_dispatchstate_t state;
     95 	dns_transport_t *transport;
     96 	isc_tlsctx_cache_t *tlsctx_cache;
     97 	unsigned int retries;
     98 	unsigned int timeout;
     99 	isc_time_t start;
    100 	isc_sockaddr_t local;
    101 	isc_sockaddr_t peer;
    102 	in_port_t port;
    103 	dns_messageid_t id;
    104 	dispatch_cb_t connected;
    105 	dispatch_cb_t sent;
    106 	dispatch_cb_t response;
    107 	void *arg;
    108 	bool reading;
    109 	isc_result_t result;
    110 	ISC_LINK(dns_dispentry_t) alink;
    111 	ISC_LINK(dns_dispentry_t) plink;
    112 	ISC_LINK(dns_dispentry_t) rlink;
    113 
    114 	struct cds_lfht_node ht_node;
    115 	struct rcu_head rcu_head;
    116 };
    117 
    118 struct dns_dispatch {
    119 	/* Unlocked. */
    120 	unsigned int magic; /*%< magic */
    121 	uint32_t tid;
    122 	isc_socktype_t socktype;
    123 	isc_refcount_t references;
    124 	isc_mem_t *mctx;
    125 	dns_dispatchmgr_t *mgr;	    /*%< dispatch manager */
    126 	isc_nmhandle_t *handle;	    /*%< netmgr handle for TCP connection */
    127 	isc_sockaddr_t local;	    /*%< local address */
    128 	isc_sockaddr_t peer;	    /*%< peer address (TCP) */
    129 	dns_transport_t *transport; /*%< TCP transport parameters */
    130 
    131 	dns_dispatchopt_t options;
    132 	dns_dispatchstate_t state;
    133 	dns_dispatchtype_t disptype;
    134 
    135 	dns_messageid_t nextid; /*%< next sequential QID for TCP */
    136 
    137 	bool reading;
    138 
    139 	dns_displist_t pending;
    140 	dns_displist_t active;
    141 
    142 	uint_fast32_t requests; /*%< how many requests we have */
    143 
    144 	unsigned int timedout;
    145 
    146 	struct cds_lfht_node ht_node;
    147 	struct rcu_head rcu_head;
    148 };
    149 
    150 #define RESPONSE_MAGIC	  ISC_MAGIC('D', 'r', 's', 'p')
    151 #define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
    152 
    153 #define DISPATCH_MAGIC	  ISC_MAGIC('D', 'i', 's', 'p')
    154 #define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
    155 
    156 #define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
    157 #define VALID_DISPATCHMGR(e)  ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
    158 
    159 #if DNS_DISPATCH_TRACE
    160 #define dns_dispentry_ref(ptr) \
    161 	dns_dispentry__ref(ptr, __func__, __FILE__, __LINE__)
    162 #define dns_dispentry_unref(ptr) \
    163 	dns_dispentry__unref(ptr, __func__, __FILE__, __LINE__)
    164 #define dns_dispentry_attach(ptr, ptrp) \
    165 	dns_dispentry__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
    166 #define dns_dispentry_detach(ptrp) \
    167 	dns_dispentry__detach(ptrp, __func__, __FILE__, __LINE__)
    168 ISC_REFCOUNT_TRACE_DECL(dns_dispentry);
    169 #else
    170 ISC_REFCOUNT_DECL(dns_dispentry);
    171 #endif
    172 
    173 /*
    174  * The number of attempts to find unique <addr, port, query_id> combination
    175  */
    176 #define QID_MAX_TRIES 64
    177 
    178 /*
    179  * Initial and minimum QID table sizes.
    180  */
    181 #define QIDS_INIT_SIZE (1 << 4) /* Must be power of 2 */
    182 #define QIDS_MIN_SIZE  (1 << 4) /* Must be power of 2 */
    183 
    184 /*
    185  * Statics.
    186  */
    187 static void
    188 dispatchmgr_destroy(dns_dispatchmgr_t *mgr);
    189 
    190 static void
    191 udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
    192 	 void *arg);
    193 static void
    194 tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
    195 	 void *arg);
    196 static void
    197 dispentry_cancel(dns_dispentry_t *resp, isc_result_t result);
    198 static isc_result_t
    199 dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
    200 		   uint32_t tid, dns_dispatch_t **dispp);
    201 static void
    202 udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp);
    203 static void
    204 udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp);
    205 static void
    206 tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp);
    207 static void
    208 tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
    209 		     int32_t timeout);
    210 static void
    211 udp_dispatch_getnext(dns_dispentry_t *resp, int32_t timeout);
    212 
    213 static const char *
    214 socktype2str(dns_dispentry_t *resp) {
    215 	dns_transport_type_t transport_type = DNS_TRANSPORT_UDP;
    216 	dns_dispatch_t *disp = resp->disp;
    217 
    218 	if (disp->socktype == isc_socktype_tcp) {
    219 		if (resp->transport != NULL) {
    220 			transport_type =
    221 				dns_transport_get_type(resp->transport);
    222 		} else {
    223 			transport_type = DNS_TRANSPORT_TCP;
    224 		}
    225 	}
    226 
    227 	switch (transport_type) {
    228 	case DNS_TRANSPORT_UDP:
    229 		return "UDP";
    230 	case DNS_TRANSPORT_TCP:
    231 		return "TCP";
    232 	case DNS_TRANSPORT_TLS:
    233 		return "TLS";
    234 	case DNS_TRANSPORT_HTTP:
    235 		return "HTTP";
    236 	default:
    237 		return "<unexpected>";
    238 	}
    239 }
    240 
    241 static const char *
    242 state2str(dns_dispatchstate_t state) {
    243 	switch (state) {
    244 	case DNS_DISPATCHSTATE_NONE:
    245 		return "none";
    246 	case DNS_DISPATCHSTATE_CONNECTING:
    247 		return "connecting";
    248 	case DNS_DISPATCHSTATE_CONNECTED:
    249 		return "connected";
    250 	case DNS_DISPATCHSTATE_CANCELED:
    251 		return "canceled";
    252 	default:
    253 		return "<unexpected>";
    254 	}
    255 }
    256 
    257 static void
    258 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)
    259 	ISC_FORMAT_PRINTF(3, 4);
    260 
    261 static void
    262 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
    263 	char msgbuf[2048];
    264 	va_list ap;
    265 
    266 	if (!isc_log_wouldlog(dns_lctx, level)) {
    267 		return;
    268 	}
    269 
    270 	va_start(ap, fmt);
    271 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    272 	va_end(ap);
    273 
    274 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    275 		      DNS_LOGMODULE_DISPATCH, level, "dispatchmgr %p: %s", mgr,
    276 		      msgbuf);
    277 }
    278 
    279 static void
    280 inc_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
    281 	if (mgr->stats != NULL) {
    282 		isc_stats_increment(mgr->stats, counter);
    283 	}
    284 }
    285 
    286 static void
    287 dec_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) {
    288 	if (mgr->stats != NULL) {
    289 		isc_stats_decrement(mgr->stats, counter);
    290 	}
    291 }
    292 
    293 static void
    294 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
    295 	ISC_FORMAT_PRINTF(3, 4);
    296 
    297 static void
    298 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {
    299 	char msgbuf[2048];
    300 	va_list ap;
    301 	int r;
    302 
    303 	if (!isc_log_wouldlog(dns_lctx, level)) {
    304 		return;
    305 	}
    306 
    307 	va_start(ap, fmt);
    308 	r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    309 	if (r < 0) {
    310 		msgbuf[0] = '\0';
    311 	} else if ((unsigned int)r >= sizeof(msgbuf)) {
    312 		/* Truncated */
    313 		msgbuf[sizeof(msgbuf) - 1] = '\0';
    314 	}
    315 	va_end(ap);
    316 
    317 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
    318 		      DNS_LOGMODULE_DISPATCH, level, "dispatch %p: %s", disp,
    319 		      msgbuf);
    320 }
    321 
    322 static void
    323 dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...)
    324 	ISC_FORMAT_PRINTF(3, 4);
    325 
    326 static void
    327 dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...) {
    328 	char msgbuf[2048];
    329 	va_list ap;
    330 	int r;
    331 
    332 	if (!isc_log_wouldlog(dns_lctx, level)) {
    333 		return;
    334 	}
    335 
    336 	va_start(ap, fmt);
    337 	r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
    338 	if (r < 0) {
    339 		msgbuf[0] = '\0';
    340 	} else if ((unsigned int)r >= sizeof(msgbuf)) {
    341 		/* Truncated */
    342 		msgbuf[sizeof(msgbuf) - 1] = '\0';
    343 	}
    344 	va_end(ap);
    345 
    346 	dispatch_log(resp->disp, level, "%s response %p: %s",
    347 		     socktype2str(resp), resp, msgbuf);
    348 }
    349 
    350 /*%
    351  * Choose a random port number for a dispatch entry.
    352  */
    353 static isc_result_t
    354 setup_socket(dns_dispatch_t *disp, dns_dispentry_t *resp,
    355 	     const isc_sockaddr_t *dest, in_port_t *portp) {
    356 	dns_dispatchmgr_t *mgr = disp->mgr;
    357 	unsigned int nports;
    358 	in_port_t *ports = NULL;
    359 	in_port_t port = *portp;
    360 
    361 	if (resp->retries++ > 5) {
    362 		return ISC_R_FAILURE;
    363 	}
    364 
    365 	if (isc_sockaddr_pf(&disp->local) == AF_INET) {
    366 		nports = mgr->nv4ports;
    367 		ports = mgr->v4ports;
    368 	} else {
    369 		nports = mgr->nv6ports;
    370 		ports = mgr->v6ports;
    371 	}
    372 	if (nports == 0) {
    373 		return ISC_R_ADDRNOTAVAIL;
    374 	}
    375 
    376 	resp->local = disp->local;
    377 	resp->peer = *dest;
    378 
    379 	if (port == 0) {
    380 		port = ports[isc_random_uniform(nports)];
    381 		isc_sockaddr_setport(&resp->local, port);
    382 		*portp = port;
    383 	}
    384 	resp->port = port;
    385 
    386 	return ISC_R_SUCCESS;
    387 }
    388 
    389 static uint32_t
    390 qid_hash(const dns_dispentry_t *dispentry) {
    391 	isc_hash32_t hash;
    392 
    393 	isc_hash32_init(&hash);
    394 
    395 	isc_sockaddr_hash_ex(&hash, &dispentry->peer, true);
    396 	isc_hash32_hash(&hash, &dispentry->id, sizeof(dispentry->id), true);
    397 	isc_hash32_hash(&hash, &dispentry->port, sizeof(dispentry->port), true);
    398 
    399 	return isc_hash32_finalize(&hash);
    400 }
    401 
    402 static int
    403 qid_match(struct cds_lfht_node *node, const void *key0) {
    404 	const dns_dispentry_t *dispentry =
    405 		caa_container_of(node, dns_dispentry_t, ht_node);
    406 	const dns_dispentry_t *key = key0;
    407 
    408 	return dispentry->id == key->id && dispentry->port == key->port &&
    409 	       isc_sockaddr_equal(&dispentry->peer, &key->peer);
    410 }
    411 
    412 static void
    413 dispentry_destroy_rcu(struct rcu_head *rcu_head) {
    414 	dns_dispentry_t *resp = caa_container_of(rcu_head, dns_dispentry_t,
    415 						 rcu_head);
    416 	isc_mem_putanddetach(&resp->mctx, resp, sizeof(*resp));
    417 }
    418 
    419 static void
    420 dispentry_destroy(dns_dispentry_t *resp) {
    421 	dns_dispatch_t *disp = resp->disp;
    422 
    423 	/*
    424 	 * We need to call this from here in case there's an external event that
    425 	 * shuts down our dispatch (like ISC_R_SHUTTINGDOWN).
    426 	 */
    427 	dispentry_cancel(resp, ISC_R_CANCELED);
    428 
    429 	INSIST(disp->requests > 0);
    430 	disp->requests--;
    431 
    432 	resp->magic = 0;
    433 
    434 	INSIST(!ISC_LINK_LINKED(resp, plink));
    435 	INSIST(!ISC_LINK_LINKED(resp, alink));
    436 	INSIST(!ISC_LINK_LINKED(resp, rlink));
    437 
    438 	dispentry_log(resp, ISC_LOG_DEBUG(90), "destroying");
    439 
    440 	if (resp->handle != NULL) {
    441 		dispentry_log(resp, ISC_LOG_DEBUG(90),
    442 			      "detaching handle %p from %p", resp->handle,
    443 			      &resp->handle);
    444 		isc_nmhandle_detach(&resp->handle);
    445 	}
    446 
    447 	if (resp->tlsctx_cache != NULL) {
    448 		isc_tlsctx_cache_detach(&resp->tlsctx_cache);
    449 	}
    450 
    451 	if (resp->transport != NULL) {
    452 		dns_transport_detach(&resp->transport);
    453 	}
    454 
    455 	dns_dispatch_detach(&disp); /* DISPATCH001 */
    456 
    457 	call_rcu(&resp->rcu_head, dispentry_destroy_rcu);
    458 }
    459 
    460 #if DNS_DISPATCH_TRACE
    461 ISC_REFCOUNT_TRACE_IMPL(dns_dispentry, dispentry_destroy);
    462 #else
    463 ISC_REFCOUNT_IMPL(dns_dispentry, dispentry_destroy);
    464 #endif
    465 
    466 /*
    467  * How long in milliseconds has it been since this dispentry
    468  * started reading?
    469  */
    470 static unsigned int
    471 dispentry_runtime(dns_dispentry_t *resp, const isc_time_t *now) {
    472 	if (isc_time_isepoch(&resp->start)) {
    473 		return 0;
    474 	}
    475 
    476 	return isc_time_microdiff(now, &resp->start) / 1000;
    477 }
    478 
    479 /*
    480  * General flow:
    481  *
    482  * If I/O result == CANCELED or error, free the buffer.
    483  *
    484  * If query, free the buffer, restart.
    485  *
    486  * If response:
    487  *	Allocate event, fill in details.
    488  *		If cannot allocate, free buffer, restart.
    489  *	find target.  If not found, free buffer, restart.
    490  *	if event queue is not empty, queue.  else, send.
    491  *	restart.
    492  */
    493 static void
    494 udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
    495 	 void *arg) {
    496 	dns_dispentry_t *resp = (dns_dispentry_t *)arg;
    497 	dns_dispatch_t *disp = NULL;
    498 	dns_messageid_t id;
    499 	isc_result_t dres;
    500 	isc_buffer_t source;
    501 	unsigned int flags;
    502 	isc_sockaddr_t peer;
    503 	isc_netaddr_t netaddr;
    504 	int match, timeout = 0;
    505 	bool respond = true;
    506 	isc_time_t now;
    507 
    508 	REQUIRE(VALID_RESPONSE(resp));
    509 	REQUIRE(VALID_DISPATCH(resp->disp));
    510 
    511 	disp = resp->disp;
    512 
    513 	REQUIRE(disp->tid == isc_tid());
    514 	INSIST(resp->reading);
    515 	resp->reading = false;
    516 
    517 	if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
    518 		/*
    519 		 * Nobody is interested in the callback if the response
    520 		 * has been canceled already.  Detach from the response
    521 		 * and the handle.
    522 		 */
    523 		respond = false;
    524 		eresult = ISC_R_CANCELED;
    525 	}
    526 
    527 	dispentry_log(resp, ISC_LOG_DEBUG(90),
    528 		      "read callback:%s, requests %" PRIuFAST32,
    529 		      isc_result_totext(eresult), disp->requests);
    530 
    531 	if (eresult != ISC_R_SUCCESS) {
    532 		/*
    533 		 * This is most likely a network error on a connected
    534 		 * socket, a timeout, or the query has been canceled.
    535 		 * It makes no sense to check the address or parse the
    536 		 * packet, but we can return the error to the caller.
    537 		 */
    538 		goto done;
    539 	}
    540 
    541 	peer = isc_nmhandle_peeraddr(handle);
    542 	isc_netaddr_fromsockaddr(&netaddr, &peer);
    543 
    544 	/*
    545 	 * If this is from a blackholed address, drop it.
    546 	 */
    547 	if (disp->mgr->blackhole != NULL &&
    548 	    dns_acl_match(&netaddr, NULL, disp->mgr->blackhole, NULL, &match,
    549 			  NULL) == ISC_R_SUCCESS &&
    550 	    match > 0)
    551 	{
    552 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(10))) {
    553 			char netaddrstr[ISC_NETADDR_FORMATSIZE];
    554 			isc_netaddr_format(&netaddr, netaddrstr,
    555 					   sizeof(netaddrstr));
    556 			dispentry_log(resp, ISC_LOG_DEBUG(10),
    557 				      "blackholed packet from %s", netaddrstr);
    558 		}
    559 		goto next;
    560 	}
    561 
    562 	/*
    563 	 * Peek into the buffer to see what we can see.
    564 	 */
    565 	id = resp->id;
    566 	isc_buffer_init(&source, region->base, region->length);
    567 	isc_buffer_add(&source, region->length);
    568 	dres = dns_message_peekheader(&source, &id, &flags);
    569 	if (dres != ISC_R_SUCCESS) {
    570 		char netaddrstr[ISC_NETADDR_FORMATSIZE];
    571 		isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
    572 		dispentry_log(resp, ISC_LOG_DEBUG(10),
    573 			      "got garbage packet from %s", netaddrstr);
    574 		goto next;
    575 	}
    576 
    577 	dispentry_log(resp, ISC_LOG_DEBUG(92),
    578 		      "got valid DNS message header, /QR %c, id %u",
    579 		      ((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id);
    580 
    581 	/*
    582 	 * Look at the message flags.  If it's a query, ignore it.
    583 	 */
    584 	if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
    585 		goto next;
    586 	}
    587 
    588 	/*
    589 	 * The QID and the address must match the expected ones.  A
    590 	 * mismatch can happen during normal operation only when a stale
    591 	 * response from a previous query arrives late, which is rare in
    592 	 * practice; treat any mismatch as a possible spoofing attempt and
    593 	 * let the caller retry over TCP to prevent off-path spoofing.
    594 	 */
    595 	if (resp->id != id || !isc_sockaddr_equal(&peer, &resp->peer)) {
    596 		dispentry_log(resp, ISC_LOG_DEBUG(90),
    597 			      "response doesn't match");
    598 		inc_stats(disp->mgr, dns_resstatscounter_mismatch);
    599 		eresult = DNS_R_MISMATCH;
    600 		goto done;
    601 	}
    602 
    603 	/*
    604 	 * We have the right resp, so call the caller back.
    605 	 */
    606 	goto done;
    607 
    608 next:
    609 	/*
    610 	 * This is the wrong response.  Check whether there is still enough
    611 	 * time to wait for the correct one to arrive before the timeout fires.
    612 	 */
    613 	now = isc_loop_now(resp->loop);
    614 	if (resp->timeout > 0) {
    615 		timeout = resp->timeout - dispentry_runtime(resp, &now);
    616 		if (timeout <= 0) {
    617 			/*
    618 			 * The time window for receiving the correct response is
    619 			 * already closed, libuv has just not processed the
    620 			 * socket timer yet.  Invoke the read callback,
    621 			 * indicating a timeout.
    622 			 */
    623 			eresult = ISC_R_TIMEDOUT;
    624 			goto done;
    625 		}
    626 	}
    627 
    628 	/*
    629 	 * Do not invoke the read callback just yet and instead wait for the
    630 	 * proper response to arrive until the original timeout fires.
    631 	 */
    632 	respond = false;
    633 	udp_dispatch_getnext(resp, timeout);
    634 
    635 done:
    636 	if (respond) {
    637 		dispentry_log(resp, ISC_LOG_DEBUG(90),
    638 			      "UDP read callback on %p: %s", handle,
    639 			      isc_result_totext(eresult));
    640 		resp->response(eresult, region, resp->arg);
    641 	}
    642 
    643 	dns_dispentry_detach(&resp); /* DISPENTRY003 */
    644 }
    645 
    646 static isc_result_t
    647 tcp_recv_oldest(dns_dispatch_t *disp, dns_dispentry_t **respp) {
    648 	dns_dispentry_t *resp = NULL;
    649 	resp = ISC_LIST_HEAD(disp->active);
    650 	if (resp != NULL) {
    651 		disp->timedout++;
    652 
    653 		*respp = resp;
    654 		return ISC_R_TIMEDOUT;
    655 	}
    656 
    657 	return ISC_R_NOTFOUND;
    658 }
    659 
    660 static isc_result_t
    661 tcp_recv_success(dns_dispatch_t *disp, isc_region_t *region,
    662 		 dns_dispentry_t **respp) {
    663 	isc_buffer_t source;
    664 	dns_messageid_t id;
    665 	unsigned int flags;
    666 	isc_result_t result = ISC_R_SUCCESS;
    667 
    668 	dispatch_log(disp, ISC_LOG_DEBUG(90),
    669 		     "TCP read success, length == %d, addr = %p",
    670 		     region->length, region->base);
    671 
    672 	/*
    673 	 * Peek into the buffer to see what we can see.
    674 	 */
    675 	isc_buffer_init(&source, region->base, region->length);
    676 	isc_buffer_add(&source, region->length);
    677 	result = dns_message_peekheader(&source, &id, &flags);
    678 	if (result != ISC_R_SUCCESS) {
    679 		dispatch_log(disp, ISC_LOG_DEBUG(10), "got garbage packet");
    680 		return ISC_R_UNEXPECTED;
    681 	}
    682 
    683 	dispatch_log(disp, ISC_LOG_DEBUG(92),
    684 		     "got valid DNS message header, /QR %c, id %u",
    685 		     ((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id);
    686 
    687 	/*
    688 	 * Look at the message flags.  If it's a query, ignore it and keep
    689 	 * reading.
    690 	 */
    691 	if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
    692 		dispatch_log(disp, ISC_LOG_DEBUG(10),
    693 			     "got DNS query instead of answer");
    694 		return ISC_R_UNEXPECTED;
    695 	}
    696 
    697 	/*
    698 	 * We have a valid response; find the associated dispentry by
    699 	 * scanning disp->active.  With sequential IDs and a bounded
    700 	 * pipelining limit this is a short linear scan.
    701 	 */
    702 	dns_dispentry_t *resp = NULL, *r = NULL;
    703 	ISC_LIST_FOREACH(disp->active, r, alink) {
    704 		if (r->id == id) {
    705 			resp = r;
    706 			break;
    707 		}
    708 	}
    709 
    710 	if (resp != NULL) {
    711 		*respp = resp;
    712 	} else {
    713 		result = ISC_R_NOTFOUND;
    714 	}
    715 	dispatch_log(disp, ISC_LOG_DEBUG(90), "search for response: %s",
    716 		     isc_result_totext(result));
    717 
    718 	return result;
    719 }
    720 
    721 static void
    722 tcp_recv_add(dns_displist_t *resps, dns_dispentry_t *resp,
    723 	     isc_result_t result) {
    724 	dns_dispentry_ref(resp); /* DISPENTRY009 */
    725 	ISC_LIST_UNLINK(resp->disp->active, resp, alink);
    726 	ISC_LIST_APPEND(*resps, resp, rlink);
    727 	INSIST(resp->reading);
    728 	resp->reading = false;
    729 	resp->result = result;
    730 }
    731 
    732 static void
    733 tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps,
    734 		  isc_result_t result) {
    735 	dns_dispentry_t *resp = NULL, *next = NULL;
    736 
    737 	/*
    738 	 * If there are any active responses, shut them all down.
    739 	 */
    740 	for (resp = ISC_LIST_HEAD(disp->active); resp != NULL; resp = next) {
    741 		next = ISC_LIST_NEXT(resp, alink);
    742 		tcp_recv_add(resps, resp, result);
    743 	}
    744 	disp->state = DNS_DISPATCHSTATE_CANCELED;
    745 }
    746 
    747 static void
    748 tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) {
    749 	dns_dispentry_t *resp = NULL, *next = NULL;
    750 
    751 	for (resp = ISC_LIST_HEAD(*resps); resp != NULL; resp = next) {
    752 		next = ISC_LIST_NEXT(resp, rlink);
    753 		ISC_LIST_UNLINK(*resps, resp, rlink);
    754 
    755 		dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s",
    756 			      isc_result_totext(resp->result));
    757 		resp->response(resp->result, region, resp->arg);
    758 		dns_dispentry_detach(&resp); /* DISPENTRY009 */
    759 	}
    760 }
    761 
    762 /*
    763  * General flow:
    764  *
    765  * If I/O result == CANCELED, EOF, or error, notify everyone as the
    766  * various queues drain.
    767  *
    768  * If response:
    769  *	Allocate event, fill in details.
    770  *		If cannot allocate, restart.
    771  *	find target.  If not found, restart.
    772  *	if event queue is not empty, queue.  else, send.
    773  *	restart.
    774  */
    775 static void
    776 tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
    777 	 void *arg) {
    778 	dns_dispatch_t *disp = (dns_dispatch_t *)arg;
    779 	dns_dispentry_t *resp = NULL;
    780 	char buf[ISC_SOCKADDR_FORMATSIZE];
    781 	isc_sockaddr_t peer;
    782 	dns_displist_t resps = ISC_LIST_INITIALIZER;
    783 	isc_time_t now;
    784 	int timeout = 0;
    785 
    786 	REQUIRE(VALID_DISPATCH(disp));
    787 
    788 	REQUIRE(disp->tid == isc_tid());
    789 	INSIST(disp->reading);
    790 	disp->reading = false;
    791 
    792 	dispatch_log(disp, ISC_LOG_DEBUG(90),
    793 		     "TCP read:%s:requests %" PRIuFAST32,
    794 		     isc_result_totext(result), disp->requests);
    795 
    796 	peer = isc_nmhandle_peeraddr(handle);
    797 
    798 	rcu_read_lock();
    799 	/*
    800 	 * Phase 1: Process timeout and success.
    801 	 */
    802 	switch (result) {
    803 	case ISC_R_TIMEDOUT:
    804 		/*
    805 		 * Time out the oldest response in the active queue.
    806 		 */
    807 		result = tcp_recv_oldest(disp, &resp);
    808 		break;
    809 	case ISC_R_SUCCESS:
    810 		/* We got an answer */
    811 		result = tcp_recv_success(disp, region, &resp);
    812 		break;
    813 
    814 	default:
    815 		break;
    816 	}
    817 
    818 	if (resp != NULL) {
    819 		tcp_recv_add(&resps, resp, result);
    820 	}
    821 
    822 	/*
    823 	 * Phase 2: Look if we timed out before.
    824 	 */
    825 
    826 	if (result == ISC_R_NOTFOUND) {
    827 		if (disp->timedout > 0) {
    828 			/* There was active query that timed-out before */
    829 			disp->timedout--;
    830 		} else {
    831 			result = ISC_R_UNEXPECTED;
    832 		}
    833 	}
    834 
    835 	/*
    836 	 * Phase 3: Trigger timeouts.  It's possible that the responses would
    837 	 * have been timed out out already, but non-matching TCP reads have
    838 	 * prevented this.
    839 	 */
    840 	resp = ISC_LIST_HEAD(disp->active);
    841 	if (resp != NULL) {
    842 		now = isc_loop_now(resp->loop);
    843 	}
    844 	while (resp != NULL) {
    845 		dns_dispentry_t *next = ISC_LIST_NEXT(resp, alink);
    846 
    847 		if (resp->timeout > 0) {
    848 			timeout = resp->timeout - dispentry_runtime(resp, &now);
    849 			if (timeout <= 0) {
    850 				tcp_recv_add(&resps, resp, ISC_R_TIMEDOUT);
    851 			}
    852 		}
    853 
    854 		resp = next;
    855 	}
    856 
    857 	/*
    858 	 * Phase 4: log if we errored out.
    859 	 */
    860 	switch (result) {
    861 	case ISC_R_SUCCESS:
    862 	case ISC_R_TIMEDOUT:
    863 	case ISC_R_NOTFOUND:
    864 		break;
    865 
    866 	case ISC_R_SHUTTINGDOWN:
    867 	case ISC_R_CANCELED:
    868 	case ISC_R_EOF:
    869 	case ISC_R_CONNECTIONRESET:
    870 		isc_sockaddr_format(&peer, buf, sizeof(buf));
    871 		dispatch_log(disp, ISC_LOG_DEBUG(90),
    872 			     "shutting down TCP: %s: %s", buf,
    873 			     isc_result_totext(result));
    874 		tcp_recv_shutdown(disp, &resps, result);
    875 		break;
    876 	default:
    877 		isc_sockaddr_format(&peer, buf, sizeof(buf));
    878 		dispatch_log(disp, ISC_LOG_ERROR,
    879 			     "shutting down due to TCP "
    880 			     "receive error: %s: %s",
    881 			     buf, isc_result_totext(result));
    882 		tcp_recv_shutdown(disp, &resps, result);
    883 		break;
    884 	}
    885 
    886 	/*
    887 	 * Phase 5: Resume reading if there are still active responses
    888 	 */
    889 	resp = ISC_LIST_HEAD(disp->active);
    890 	if (resp != NULL) {
    891 		if (resp->timeout > 0) {
    892 			timeout = resp->timeout - dispentry_runtime(resp, &now);
    893 			INSIST(timeout > 0);
    894 		}
    895 		tcp_startrecv(disp, resp);
    896 		if (timeout > 0) {
    897 			isc_nmhandle_settimeout(handle, timeout);
    898 		}
    899 	}
    900 
    901 	rcu_read_unlock();
    902 
    903 	/*
    904 	 * Phase 6: Process all scheduled callbacks.
    905 	 */
    906 	tcp_recv_processall(&resps, region);
    907 
    908 	dns_dispatch_detach(&disp); /* DISPATCH002 */
    909 }
    910 
    911 /*%
    912  * Create a temporary port list to set the initial default set of dispatch
    913  * ephemeral ports.  This is almost meaningless as the application will
    914  * normally set the ports explicitly, but is provided to fill some minor corner
    915  * cases.
    916  */
    917 static void
    918 create_default_portset(isc_mem_t *mctx, int family, isc_portset_t **portsetp) {
    919 	in_port_t low, high;
    920 
    921 	isc_net_getportrange(family, &low, &high);
    922 
    923 	isc_portset_create(mctx, portsetp);
    924 	isc_portset_addrange(*portsetp, low, high);
    925 }
    926 
    927 static isc_result_t
    928 setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
    929 	      isc_portset_t *v6portset) {
    930 	in_port_t *v4ports, *v6ports, p = 0;
    931 	unsigned int nv4ports, nv6ports, i4 = 0, i6 = 0;
    932 
    933 	nv4ports = isc_portset_nports(v4portset);
    934 	nv6ports = isc_portset_nports(v6portset);
    935 
    936 	v4ports = NULL;
    937 	if (nv4ports != 0) {
    938 		v4ports = isc_mem_cget(mgr->mctx, nv4ports, sizeof(in_port_t));
    939 	}
    940 	v6ports = NULL;
    941 	if (nv6ports != 0) {
    942 		v6ports = isc_mem_cget(mgr->mctx, nv6ports, sizeof(in_port_t));
    943 	}
    944 
    945 	do {
    946 		if (isc_portset_isset(v4portset, p)) {
    947 			INSIST(i4 < nv4ports);
    948 			v4ports[i4++] = p;
    949 		}
    950 		if (isc_portset_isset(v6portset, p)) {
    951 			INSIST(i6 < nv6ports);
    952 			v6ports[i6++] = p;
    953 		}
    954 	} while (p++ < 65535);
    955 	INSIST(i4 == nv4ports && i6 == nv6ports);
    956 
    957 	if (mgr->v4ports != NULL) {
    958 		isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports,
    959 			     sizeof(in_port_t));
    960 	}
    961 	mgr->v4ports = v4ports;
    962 	mgr->nv4ports = nv4ports;
    963 
    964 	if (mgr->v6ports != NULL) {
    965 		isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports,
    966 			     sizeof(in_port_t));
    967 	}
    968 	mgr->v6ports = v6ports;
    969 	mgr->nv6ports = nv6ports;
    970 
    971 	return ISC_R_SUCCESS;
    972 }
    973 
    974 /*
    975  * Publics.
    976  */
    977 
    978 isc_result_t
    979 dns_dispatchmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t *nm,
    980 		       dns_dispatchmgr_t **mgrp) {
    981 	dns_dispatchmgr_t *mgr = NULL;
    982 	isc_portset_t *v4portset = NULL;
    983 	isc_portset_t *v6portset = NULL;
    984 
    985 	REQUIRE(mctx != NULL);
    986 	REQUIRE(mgrp != NULL && *mgrp == NULL);
    987 
    988 	mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
    989 	*mgr = (dns_dispatchmgr_t){
    990 		.magic = 0,
    991 		.nloops = isc_loopmgr_nloops(loopmgr),
    992 	};
    993 
    994 #if DNS_DISPATCH_TRACE
    995 	fprintf(stderr, "dns_dispatchmgr__init:%s:%s:%d:%p->references = 1\n",
    996 		__func__, __FILE__, __LINE__, mgr);
    997 #endif
    998 	isc_refcount_init(&mgr->references, 1);
    999 
   1000 	isc_mem_attach(mctx, &mgr->mctx);
   1001 	isc_nm_attach(nm, &mgr->nm);
   1002 
   1003 	mgr->tcps = isc_mem_cget(mgr->mctx, mgr->nloops, sizeof(mgr->tcps[0]));
   1004 	for (size_t i = 0; i < mgr->nloops; i++) {
   1005 		mgr->tcps[i] = cds_lfht_new(
   1006 			2, 2, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
   1007 			NULL);
   1008 	}
   1009 
   1010 	create_default_portset(mgr->mctx, AF_INET, &v4portset);
   1011 	create_default_portset(mgr->mctx, AF_INET6, &v6portset);
   1012 
   1013 	setavailports(mgr, v4portset, v6portset);
   1014 
   1015 	isc_portset_destroy(mgr->mctx, &v4portset);
   1016 	isc_portset_destroy(mgr->mctx, &v6portset);
   1017 
   1018 	mgr->qids = cds_lfht_new(QIDS_INIT_SIZE, QIDS_MIN_SIZE, 0,
   1019 				 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
   1020 				 NULL);
   1021 
   1022 	mgr->magic = DNS_DISPATCHMGR_MAGIC;
   1023 
   1024 	*mgrp = mgr;
   1025 	return ISC_R_SUCCESS;
   1026 }
   1027 
   1028 #if DNS_DISPATCH_TRACE
   1029 ISC_REFCOUNT_TRACE_IMPL(dns_dispatchmgr, dispatchmgr_destroy);
   1030 #else
   1031 ISC_REFCOUNT_IMPL(dns_dispatchmgr, dispatchmgr_destroy);
   1032 #endif
   1033 
   1034 void
   1035 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) {
   1036 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1037 	if (mgr->blackhole != NULL) {
   1038 		dns_acl_detach(&mgr->blackhole);
   1039 	}
   1040 	dns_acl_attach(blackhole, &mgr->blackhole);
   1041 }
   1042 
   1043 dns_acl_t *
   1044 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) {
   1045 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1046 	return mgr->blackhole;
   1047 }
   1048 
   1049 isc_result_t
   1050 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
   1051 			      isc_portset_t *v6portset) {
   1052 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1053 	return setavailports(mgr, v4portset, v6portset);
   1054 }
   1055 
   1056 static void
   1057 dispatchmgr_destroy(dns_dispatchmgr_t *mgr) {
   1058 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1059 
   1060 	isc_refcount_destroy(&mgr->references);
   1061 
   1062 	mgr->magic = 0;
   1063 
   1064 	RUNTIME_CHECK(!cds_lfht_destroy(mgr->qids, NULL));
   1065 
   1066 	for (size_t i = 0; i < mgr->nloops; i++) {
   1067 		RUNTIME_CHECK(!cds_lfht_destroy(mgr->tcps[i], NULL));
   1068 	}
   1069 	isc_mem_cput(mgr->mctx, mgr->tcps, mgr->nloops, sizeof(mgr->tcps[0]));
   1070 
   1071 	if (mgr->blackhole != NULL) {
   1072 		dns_acl_detach(&mgr->blackhole);
   1073 	}
   1074 
   1075 	if (mgr->stats != NULL) {
   1076 		isc_stats_detach(&mgr->stats);
   1077 	}
   1078 
   1079 	if (mgr->v4ports != NULL) {
   1080 		isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports,
   1081 			     sizeof(in_port_t));
   1082 	}
   1083 	if (mgr->v6ports != NULL) {
   1084 		isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports,
   1085 			     sizeof(in_port_t));
   1086 	}
   1087 
   1088 	isc_nm_detach(&mgr->nm);
   1089 
   1090 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t));
   1091 }
   1092 
   1093 void
   1094 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) {
   1095 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1096 	REQUIRE(mgr->stats == NULL);
   1097 
   1098 	isc_stats_attach(stats, &mgr->stats);
   1099 }
   1100 
   1101 /*
   1102  * Allocate and set important limits.
   1103  */
   1104 static void
   1105 dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, uint32_t tid,
   1106 		  dns_dispatch_t **dispp) {
   1107 	dns_dispatch_t *disp = NULL;
   1108 
   1109 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1110 	REQUIRE(dispp != NULL && *dispp == NULL);
   1111 
   1112 	/*
   1113 	 * Set up the dispatcher, mostly.  Don't bother setting some of
   1114 	 * the options that are controlled by tcp vs. udp, etc.
   1115 	 */
   1116 
   1117 	disp = isc_mem_get(mgr->mctx, sizeof(*disp));
   1118 	*disp = (dns_dispatch_t){
   1119 		.socktype = type,
   1120 		.active = ISC_LIST_INITIALIZER,
   1121 		.pending = ISC_LIST_INITIALIZER,
   1122 		.tid = tid,
   1123 		.magic = DISPATCH_MAGIC,
   1124 	};
   1125 
   1126 	isc_mem_attach(mgr->mctx, &disp->mctx);
   1127 
   1128 	dns_dispatchmgr_attach(mgr, &disp->mgr);
   1129 #if DNS_DISPATCH_TRACE
   1130 	fprintf(stderr, "dns_dispatch__init:%s:%s:%d:%p->references = 1\n",
   1131 		__func__, __FILE__, __LINE__, disp);
   1132 #endif
   1133 	isc_refcount_init(&disp->references, 1); /* DISPATCH000 */
   1134 
   1135 	*dispp = disp;
   1136 }
   1137 
   1138 struct dispatch_key {
   1139 	const isc_sockaddr_t *local;
   1140 	const isc_sockaddr_t *peer;
   1141 	const dns_transport_t *transport;
   1142 	const dns_dispatchtype_t disptype;
   1143 };
   1144 
   1145 static uint32_t
   1146 dispatch_hash(struct dispatch_key *key) {
   1147 	isc_hash32_t hash;
   1148 
   1149 	isc_hash32_init(&hash);
   1150 
   1151 	isc_sockaddr_hash_ex(&hash, key->peer, false);
   1152 	if (key->local != NULL) {
   1153 		isc_sockaddr_hash_ex(&hash, key->local, true);
   1154 	}
   1155 	if (key->transport != NULL) {
   1156 		uintptr_t transport = (uintptr_t)key->transport;
   1157 		isc_hash32_hash(&hash, &transport, sizeof(transport), true);
   1158 	}
   1159 	isc_hash32_hash(&hash, &key->disptype, sizeof(key->disptype), true);
   1160 
   1161 	return isc_hash32_finalize(&hash);
   1162 }
   1163 
   1164 static int
   1165 dispatch_match(struct cds_lfht_node *node, const void *key0) {
   1166 	dns_dispatch_t *disp = caa_container_of(node, dns_dispatch_t, ht_node);
   1167 	const struct dispatch_key *key = key0;
   1168 	isc_sockaddr_t local;
   1169 	isc_sockaddr_t peer;
   1170 
   1171 	if (disp->handle != NULL) {
   1172 		local = isc_nmhandle_localaddr(disp->handle);
   1173 		peer = isc_nmhandle_peeraddr(disp->handle);
   1174 	} else {
   1175 		local = disp->local;
   1176 		peer = disp->peer;
   1177 	}
   1178 
   1179 	return disp->disptype == key->disptype &&
   1180 	       isc_sockaddr_equal(&peer, key->peer) &&
   1181 	       disp->transport == key->transport &&
   1182 	       (key->local == NULL || isc_sockaddr_equal(&local, key->local));
   1183 }
   1184 
   1185 static isc_result_t
   1186 dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
   1187 		const isc_sockaddr_t *destaddr, dns_transport_t *transport,
   1188 		dns_dispatchtype_t disptype, dns_dispatch_t **dispp) {
   1189 	dns_dispatch_t *disp_connected = NULL;
   1190 	dns_dispatch_t *disp_fallback = NULL;
   1191 	isc_result_t result = ISC_R_NOTFOUND;
   1192 	uint32_t tid = isc_tid();
   1193 
   1194 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1195 	REQUIRE(destaddr != NULL);
   1196 	REQUIRE(dispp != NULL && *dispp == NULL);
   1197 
   1198 	struct dispatch_key key = {
   1199 		.local = localaddr,
   1200 		.peer = destaddr,
   1201 		.transport = transport,
   1202 		.disptype = disptype,
   1203 	};
   1204 
   1205 	rcu_read_lock();
   1206 	struct cds_lfht_iter iter;
   1207 	dns_dispatch_t *disp = NULL;
   1208 	cds_lfht_for_each_entry_duplicate(mgr->tcps[tid], dispatch_hash(&key),
   1209 					  dispatch_match, &key, &iter, disp,
   1210 					  ht_node) {
   1211 		INSIST(disp->tid == isc_tid());
   1212 		INSIST(disp->socktype == isc_socktype_tcp);
   1213 
   1214 		switch (disp->state) {
   1215 		case DNS_DISPATCHSTATE_NONE:
   1216 			/* A dispatch in indeterminate state, skip it */
   1217 			break;
   1218 		case DNS_DISPATCHSTATE_CONNECTED:
   1219 			/* We found a connected dispatch */
   1220 			dns_dispatch_attach(disp, &disp_connected);
   1221 			break;
   1222 		case DNS_DISPATCHSTATE_CONNECTING:
   1223 			/* We found "a" dispatch, store it for later */
   1224 			if (disp_fallback == NULL) {
   1225 				dns_dispatch_attach(disp, &disp_fallback);
   1226 			}
   1227 			break;
   1228 		case DNS_DISPATCHSTATE_CANCELED:
   1229 			/* A canceled dispatch, skip it. */
   1230 			break;
   1231 		default:
   1232 			UNREACHABLE();
   1233 		}
   1234 
   1235 		if (disp_connected != NULL) {
   1236 			break;
   1237 		}
   1238 	}
   1239 	rcu_read_unlock();
   1240 
   1241 	if (disp_connected != NULL) {
   1242 		/* We found connected dispatch */
   1243 		INSIST(disp_connected->handle != NULL);
   1244 
   1245 		*dispp = disp_connected;
   1246 		disp_connected = NULL;
   1247 
   1248 		result = ISC_R_SUCCESS;
   1249 
   1250 		if (disp_fallback != NULL) {
   1251 			dns_dispatch_detach(&disp_fallback);
   1252 		}
   1253 	} else if (disp_fallback != NULL) {
   1254 		*dispp = disp_fallback;
   1255 
   1256 		result = ISC_R_SUCCESS;
   1257 	}
   1258 
   1259 	return result;
   1260 }
   1261 
   1262 static void
   1263 dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
   1264 		   const isc_sockaddr_t *destaddr, dns_transport_t *transport,
   1265 		   dns_dispatchtype_t disptype, dns_dispatchopt_t options,
   1266 		   dns_dispatch_t **dispp) {
   1267 	dns_dispatch_t *disp = NULL;
   1268 	uint32_t tid = isc_tid();
   1269 
   1270 	dispatch_allocate(mgr, isc_socktype_tcp, tid, &disp);
   1271 
   1272 	disp->disptype = disptype;
   1273 	disp->nextid = isc_random16();
   1274 	disp->options = options;
   1275 	disp->peer = *destaddr;
   1276 	if (transport != NULL) {
   1277 		dns_transport_attach(transport, &disp->transport);
   1278 	}
   1279 
   1280 	if (localaddr != NULL) {
   1281 		disp->local = *localaddr;
   1282 	} else {
   1283 		int pf;
   1284 		pf = isc_sockaddr_pf(destaddr);
   1285 		isc_sockaddr_anyofpf(&disp->local, pf);
   1286 		isc_sockaddr_setport(&disp->local, 0);
   1287 	}
   1288 
   1289 	/*
   1290 	 * Append it to the dispatcher list.
   1291 	 */
   1292 	if ((options & DNS_DISPATCHOPT_FIXEDID) == 0) {
   1293 		struct dispatch_key key = {
   1294 			.local = &disp->local,
   1295 			.peer = &disp->peer,
   1296 			.transport = transport,
   1297 			.disptype = disptype,
   1298 		};
   1299 		rcu_read_lock();
   1300 		cds_lfht_add(mgr->tcps[tid], dispatch_hash(&key),
   1301 			     &disp->ht_node);
   1302 		rcu_read_unlock();
   1303 	}
   1304 
   1305 	*dispp = disp;
   1306 }
   1307 
   1308 isc_result_t
   1309 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
   1310 		       const isc_sockaddr_t *destaddr,
   1311 		       dns_transport_t *transport, dns_dispatchtype_t disptype,
   1312 		       dns_dispatchopt_t options, dns_dispatch_t **dispp) {
   1313 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1314 	REQUIRE(destaddr != NULL);
   1315 
   1316 	isc_result_t result;
   1317 
   1318 	if ((options & DNS_DISPATCHOPT_FIXEDID) == 0 &&
   1319 	    disptype != DNS_DISPATCHTYPE_XFRIN)
   1320 	{
   1321 		result = dispatch_gettcp(mgr, localaddr, destaddr, transport,
   1322 					 disptype, dispp);
   1323 		if (result == ISC_R_SUCCESS) {
   1324 			if (isc_log_wouldlog(dns_lctx, 90)) {
   1325 				char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   1326 
   1327 				isc_sockaddr_format(&(*dispp)->local, addrbuf,
   1328 						    ISC_SOCKADDR_FORMATSIZE);
   1329 
   1330 				mgr_log(mgr, ISC_LOG_DEBUG(90),
   1331 					"dns_dispatch_createtcp: reused TCP "
   1332 					"dispatch %p for "
   1333 					"%s",
   1334 					*dispp, addrbuf);
   1335 			}
   1336 			return result;
   1337 		}
   1338 	}
   1339 
   1340 	/*
   1341 	 * Otherwise allocate new TCP dispatch.
   1342 	 */
   1343 
   1344 	dispatch_createtcp(mgr, localaddr, destaddr, transport, disptype,
   1345 			   options, dispp);
   1346 
   1347 	if (isc_log_wouldlog(dns_lctx, 90)) {
   1348 		char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   1349 
   1350 		isc_sockaddr_format(&(*dispp)->local, addrbuf,
   1351 				    ISC_SOCKADDR_FORMATSIZE);
   1352 
   1353 		mgr_log(mgr, ISC_LOG_DEBUG(90),
   1354 			"dns_dispatch_createtcp: created TCP dispatch %p for "
   1355 			"%s",
   1356 			*dispp, addrbuf);
   1357 	}
   1358 
   1359 	return ISC_R_SUCCESS;
   1360 }
   1361 
   1362 isc_result_t
   1363 dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
   1364 		       dns_dispatch_t **dispp) {
   1365 	isc_result_t result;
   1366 	dns_dispatch_t *disp = NULL;
   1367 
   1368 	REQUIRE(VALID_DISPATCHMGR(mgr));
   1369 	REQUIRE(localaddr != NULL);
   1370 	REQUIRE(dispp != NULL && *dispp == NULL);
   1371 
   1372 	result = dispatch_createudp(mgr, localaddr, isc_tid(), &disp);
   1373 	if (result == ISC_R_SUCCESS) {
   1374 		*dispp = disp;
   1375 	}
   1376 
   1377 	return result;
   1378 }
   1379 
   1380 static isc_result_t
   1381 dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr,
   1382 		   uint32_t tid, dns_dispatch_t **dispp) {
   1383 	isc_result_t result = ISC_R_SUCCESS;
   1384 	dns_dispatch_t *disp = NULL;
   1385 	isc_sockaddr_t sa_any;
   1386 
   1387 	/*
   1388 	 * Check whether this address/port is available locally.
   1389 	 */
   1390 	isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
   1391 	if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
   1392 		result = isc_nm_checkaddr(localaddr, isc_socktype_udp);
   1393 		if (result != ISC_R_SUCCESS) {
   1394 			return result;
   1395 		}
   1396 	}
   1397 
   1398 	dispatch_allocate(mgr, isc_socktype_udp, tid, &disp);
   1399 
   1400 	if (isc_log_wouldlog(dns_lctx, 90)) {
   1401 		char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   1402 
   1403 		isc_sockaddr_format(localaddr, addrbuf,
   1404 				    ISC_SOCKADDR_FORMATSIZE);
   1405 		mgr_log(mgr, ISC_LOG_DEBUG(90),
   1406 			"dispatch_createudp: created UDP dispatch %p for %s",
   1407 			disp, addrbuf);
   1408 	}
   1409 
   1410 	disp->local = *localaddr;
   1411 
   1412 	/*
   1413 	 * Don't append it to the dispatcher list, we don't care about UDP, only
   1414 	 * TCP should be searched
   1415 	 *
   1416 	 * ISC_LIST_APPEND(mgr->list, disp, link);
   1417 	 */
   1418 
   1419 	*dispp = disp;
   1420 
   1421 	return result;
   1422 }
   1423 
   1424 static void
   1425 dispatch_destroy_rcu(struct rcu_head *rcu_head) {
   1426 	dns_dispatch_t *disp = caa_container_of(rcu_head, dns_dispatch_t,
   1427 						rcu_head);
   1428 
   1429 	isc_mem_putanddetach(&disp->mctx, disp, sizeof(*disp));
   1430 }
   1431 
   1432 static void
   1433 dispatch_destroy(dns_dispatch_t *disp) {
   1434 	dns_dispatchmgr_t *mgr = disp->mgr;
   1435 	uint32_t tid = isc_tid();
   1436 
   1437 	disp->magic = 0;
   1438 
   1439 	if ((disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 &&
   1440 	    disp->socktype == isc_socktype_tcp)
   1441 	{
   1442 		(void)cds_lfht_del(mgr->tcps[tid], &disp->ht_node);
   1443 	}
   1444 
   1445 	INSIST(disp->requests == 0);
   1446 	INSIST(ISC_LIST_EMPTY(disp->pending));
   1447 	INSIST(ISC_LIST_EMPTY(disp->active));
   1448 
   1449 	dispatch_log(disp, ISC_LOG_DEBUG(90), "destroying dispatch %p", disp);
   1450 
   1451 	if (disp->handle) {
   1452 		dispatch_log(disp, ISC_LOG_DEBUG(90),
   1453 			     "detaching TCP handle %p from %p", disp->handle,
   1454 			     &disp->handle);
   1455 		isc_nmhandle_detach(&disp->handle);
   1456 	}
   1457 	if (disp->transport != NULL) {
   1458 		dns_transport_detach(&disp->transport);
   1459 	}
   1460 	dns_dispatchmgr_detach(&disp->mgr);
   1461 
   1462 	call_rcu(&disp->rcu_head, dispatch_destroy_rcu);
   1463 }
   1464 
   1465 #if DNS_DISPATCH_TRACE
   1466 ISC_REFCOUNT_TRACE_IMPL(dns_dispatch, dispatch_destroy);
   1467 #else
   1468 ISC_REFCOUNT_IMPL(dns_dispatch, dispatch_destroy);
   1469 #endif
   1470 
   1471 isc_result_t
   1472 dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop,
   1473 		 dns_dispatchopt_t options, unsigned int timeout,
   1474 		 const isc_sockaddr_t *dest, dns_transport_t *transport,
   1475 		 isc_tlsctx_cache_t *tlsctx_cache, dispatch_cb_t connected,
   1476 		 dispatch_cb_t sent, dispatch_cb_t response, void *arg,
   1477 		 dns_messageid_t *idp, dns_dispentry_t **respp) {
   1478 	REQUIRE(VALID_DISPATCH(disp));
   1479 	REQUIRE(dest != NULL);
   1480 	REQUIRE(respp != NULL && *respp == NULL);
   1481 	REQUIRE(idp != NULL);
   1482 	REQUIRE(disp->socktype == isc_socktype_tcp ||
   1483 		disp->socktype == isc_socktype_udp);
   1484 	REQUIRE(connected != NULL);
   1485 	REQUIRE(response != NULL);
   1486 	REQUIRE(sent != NULL);
   1487 	REQUIRE(loop != NULL);
   1488 	REQUIRE(disp->tid == isc_tid());
   1489 	REQUIRE(disp->transport == transport);
   1490 
   1491 	if (disp->state == DNS_DISPATCHSTATE_CANCELED) {
   1492 		return ISC_R_CANCELED;
   1493 	}
   1494 
   1495 	in_port_t localport = isc_sockaddr_getport(&disp->local);
   1496 	dns_dispentry_t *resp = isc_mem_get(disp->mctx, sizeof(*resp));
   1497 	*resp = (dns_dispentry_t){
   1498 		.timeout = timeout,
   1499 		.port = localport,
   1500 		.peer = *dest,
   1501 		.loop = loop,
   1502 		.connected = connected,
   1503 		.sent = sent,
   1504 		.response = response,
   1505 		.arg = arg,
   1506 		.alink = ISC_LINK_INITIALIZER,
   1507 		.plink = ISC_LINK_INITIALIZER,
   1508 		.rlink = ISC_LINK_INITIALIZER,
   1509 		.magic = RESPONSE_MAGIC,
   1510 	};
   1511 
   1512 #if DNS_DISPATCH_TRACE
   1513 	fprintf(stderr, "dns_dispentry__init:%s:%s:%d:%p->references = 1\n",
   1514 		__func__, __FILE__, __LINE__, resp);
   1515 #endif
   1516 	isc_refcount_init(&resp->references, 1); /* DISPENTRY000 */
   1517 
   1518 	if (disp->socktype == isc_socktype_udp) {
   1519 		isc_result_t result = setup_socket(disp, resp, dest,
   1520 						   &localport);
   1521 		if (result != ISC_R_SUCCESS) {
   1522 			isc_mem_put(disp->mctx, resp, sizeof(*resp));
   1523 			inc_stats(disp->mgr, dns_resstatscounter_dispsockfail);
   1524 			return result;
   1525 		}
   1526 	}
   1527 
   1528 	isc_result_t result = ISC_R_NOMORE;
   1529 	rcu_read_lock();
   1530 
   1531 	if (disp->socktype == isc_socktype_tcp) {
   1532 		/*
   1533 		 * TCP dispentries don't use the global QID hash table.
   1534 		 * Responses are matched by scanning disp->active, and
   1535 		 * sequential per-dispatch IDs (bounded by the pipelining
   1536 		 * limit) are guaranteed to be unique within the dispatch.
   1537 		 * FIXEDID TCP dispatches are always fresh and isolated
   1538 		 * (see dns_dispatch_createtcp), so the caller-supplied ID
   1539 		 * can't collide either.
   1540 		 */
   1541 		resp->id = ((options & DNS_DISPATCHOPT_FIXEDID) != 0)
   1542 				   ? *idp
   1543 				   : disp->nextid++;
   1544 		result = ISC_R_SUCCESS;
   1545 	} else {
   1546 		size_t i = 0;
   1547 		do {
   1548 			/*
   1549 			 * Try somewhat hard to find a unique random ID
   1550 			 * (or use the fixed ID if DNS_DISPATCHOPT_FIXEDID
   1551 			 * is set).
   1552 			 */
   1553 			resp->id = ((options & DNS_DISPATCHOPT_FIXEDID) != 0)
   1554 					   ? *idp
   1555 					   : (dns_messageid_t)isc_random16();
   1556 
   1557 			struct cds_lfht_node *node = cds_lfht_add_unique(
   1558 				disp->mgr->qids, qid_hash(resp), qid_match,
   1559 				resp, &resp->ht_node);
   1560 
   1561 			if (node != &resp->ht_node) {
   1562 				if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) {
   1563 					/*
   1564 					 * When using fixed ID, we either
   1565 					 * must use it or fail.
   1566 					 */
   1567 					goto fail;
   1568 				}
   1569 			} else {
   1570 				result = ISC_R_SUCCESS;
   1571 				break;
   1572 			}
   1573 		} while (i++ < QID_MAX_TRIES);
   1574 	}
   1575 fail:
   1576 	if (result != ISC_R_SUCCESS) {
   1577 		isc_mem_put(disp->mctx, resp, sizeof(*resp));
   1578 		rcu_read_unlock();
   1579 		return result;
   1580 	}
   1581 
   1582 	isc_mem_attach(disp->mctx, &resp->mctx);
   1583 
   1584 	if (transport != NULL) {
   1585 		dns_transport_attach(transport, &resp->transport);
   1586 	}
   1587 
   1588 	if (tlsctx_cache != NULL) {
   1589 		isc_tlsctx_cache_attach(tlsctx_cache, &resp->tlsctx_cache);
   1590 	}
   1591 
   1592 	dns_dispatch_attach(disp, &resp->disp); /* DISPATCH001 */
   1593 
   1594 	disp->requests++;
   1595 
   1596 	/*
   1597 	 * If this shared TCP dispatch has reached the pipelining limit,
   1598 	 * remove it from the hash table so new queries get a fresh
   1599 	 * connection.  The dispatch continues to serve its existing
   1600 	 * queries until they complete.
   1601 	 */
   1602 	if (disp->socktype == isc_socktype_tcp &&
   1603 	    (disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 &&
   1604 	    disp->requests >= dns_dispatch_tcppipelining)
   1605 	{
   1606 		(void)cds_lfht_del(disp->mgr->tcps[isc_tid()], &disp->ht_node);
   1607 	}
   1608 
   1609 	inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp)
   1610 				     ? dns_resstatscounter_disprequdp
   1611 				     : dns_resstatscounter_dispreqtcp);
   1612 
   1613 	rcu_read_unlock();
   1614 
   1615 	*idp = resp->id;
   1616 	*respp = resp;
   1617 
   1618 	return ISC_R_SUCCESS;
   1619 }
   1620 
   1621 isc_result_t
   1622 dns_dispatch_getnext(dns_dispentry_t *resp) {
   1623 	REQUIRE(VALID_RESPONSE(resp));
   1624 	REQUIRE(VALID_DISPATCH(resp->disp));
   1625 
   1626 	dns_dispatch_t *disp = resp->disp;
   1627 	isc_result_t result = ISC_R_SUCCESS;
   1628 	int32_t timeout = 0;
   1629 
   1630 	dispentry_log(resp, ISC_LOG_DEBUG(90), "getnext for QID %d", resp->id);
   1631 
   1632 	if (resp->timeout > 0) {
   1633 		isc_time_t now = isc_loop_now(resp->loop);
   1634 		timeout = resp->timeout - dispentry_runtime(resp, &now);
   1635 		if (timeout <= 0) {
   1636 			return ISC_R_TIMEDOUT;
   1637 		}
   1638 	}
   1639 
   1640 	REQUIRE(disp->tid == isc_tid());
   1641 	switch (disp->socktype) {
   1642 	case isc_socktype_udp:
   1643 		udp_dispatch_getnext(resp, timeout);
   1644 		break;
   1645 	case isc_socktype_tcp:
   1646 		tcp_dispatch_getnext(disp, resp, timeout);
   1647 		break;
   1648 	default:
   1649 		UNREACHABLE();
   1650 	}
   1651 
   1652 	return result;
   1653 }
   1654 
   1655 /*
   1656  * NOTE: Must be RCU read locked!
   1657  */
   1658 static void
   1659 udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
   1660 	REQUIRE(VALID_RESPONSE(resp));
   1661 	REQUIRE(VALID_DISPATCH(resp->disp));
   1662 	REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr));
   1663 
   1664 	dns_dispatch_t *disp = resp->disp;
   1665 	bool respond = false;
   1666 
   1667 	REQUIRE(disp->tid == isc_tid());
   1668 	dispentry_log(resp, ISC_LOG_DEBUG(90),
   1669 		      "canceling response: %s, %s/%s (%s/%s), "
   1670 		      "requests %" PRIuFAST32,
   1671 		      isc_result_totext(result), state2str(resp->state),
   1672 		      resp->reading ? "reading" : "not reading",
   1673 		      state2str(disp->state),
   1674 		      disp->reading ? "reading" : "not reading",
   1675 		      disp->requests);
   1676 
   1677 	if (ISC_LINK_LINKED(resp, alink)) {
   1678 		ISC_LIST_UNLINK(disp->active, resp, alink);
   1679 	}
   1680 
   1681 	switch (resp->state) {
   1682 	case DNS_DISPATCHSTATE_NONE:
   1683 		break;
   1684 
   1685 	case DNS_DISPATCHSTATE_CONNECTING:
   1686 		break;
   1687 
   1688 	case DNS_DISPATCHSTATE_CONNECTED:
   1689 		if (resp->reading) {
   1690 			respond = true;
   1691 			dispentry_log(resp, ISC_LOG_DEBUG(90),
   1692 				      "canceling read on %p", resp->handle);
   1693 			isc_nm_cancelread(resp->handle);
   1694 		}
   1695 		break;
   1696 
   1697 	case DNS_DISPATCHSTATE_CANCELED:
   1698 		goto unlock;
   1699 
   1700 	default:
   1701 		UNREACHABLE();
   1702 	}
   1703 
   1704 	dec_stats(disp->mgr, dns_resstatscounter_disprequdp);
   1705 
   1706 	(void)cds_lfht_del(disp->mgr->qids, &resp->ht_node);
   1707 
   1708 	resp->state = DNS_DISPATCHSTATE_CANCELED;
   1709 
   1710 unlock:
   1711 	if (respond) {
   1712 		dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s",
   1713 			      isc_result_totext(result));
   1714 		resp->response(result, NULL, resp->arg);
   1715 	}
   1716 }
   1717 
   1718 /*
   1719  * NOTE: Must be RCU read locked!
   1720  */
   1721 static void
   1722 tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
   1723 	REQUIRE(VALID_RESPONSE(resp));
   1724 	REQUIRE(VALID_DISPATCH(resp->disp));
   1725 	REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr));
   1726 
   1727 	dns_dispatch_t *disp = resp->disp;
   1728 	dns_displist_t resps = ISC_LIST_INITIALIZER;
   1729 
   1730 	REQUIRE(disp->tid == isc_tid());
   1731 	dispentry_log(resp, ISC_LOG_DEBUG(90),
   1732 		      "canceling response: %s, %s/%s (%s/%s), "
   1733 		      "requests %" PRIuFAST32,
   1734 		      isc_result_totext(result), state2str(resp->state),
   1735 		      resp->reading ? "reading" : "not reading",
   1736 		      state2str(disp->state),
   1737 		      disp->reading ? "reading" : "not reading",
   1738 		      disp->requests);
   1739 
   1740 	switch (resp->state) {
   1741 	case DNS_DISPATCHSTATE_NONE:
   1742 		break;
   1743 
   1744 	case DNS_DISPATCHSTATE_CONNECTING:
   1745 		break;
   1746 
   1747 	case DNS_DISPATCHSTATE_CONNECTED:
   1748 		if (resp->reading) {
   1749 			tcp_recv_add(&resps, resp, ISC_R_CANCELED);
   1750 		}
   1751 
   1752 		INSIST(!ISC_LINK_LINKED(resp, alink));
   1753 
   1754 		if (ISC_LIST_EMPTY(disp->active)) {
   1755 			INSIST(disp->handle != NULL);
   1756 
   1757 #if DISPATCH_TCP_KEEPALIVE
   1758 			/*
   1759 			 * This is an experimental code that keeps the TCP
   1760 			 * connection open for 1 second before it is finally
   1761 			 * closed.  By keeping the TCP connection open, it can
   1762 			 * be reused by dns_request that uses
   1763 			 * dns_dispatch_gettcp() to join existing TCP
   1764 			 * connections.
   1765 			 *
   1766 			 * It is disabled for now, because it changes the
   1767 			 * behaviour, but I am keeping the code here for future
   1768 			 * reference when we improve the dns_dispatch to reuse
   1769 			 * the TCP connections also in the resolver.
   1770 			 *
   1771 			 * The TCP connection reuse should be seamless and not
   1772 			 * require any extra handling on the client side though.
   1773 			 */
   1774 			isc_nmhandle_cleartimeout(disp->handle);
   1775 			isc_nmhandle_settimeout(disp->handle, 1000);
   1776 
   1777 			if (!disp->reading) {
   1778 				dispentry_log(resp, ISC_LOG_DEBUG(90),
   1779 					      "final 1 second timeout on %p",
   1780 					      disp->handle);
   1781 				tcp_startrecv(disp, NULL);
   1782 			}
   1783 #else
   1784 			if (disp->reading) {
   1785 				dispentry_log(resp, ISC_LOG_DEBUG(90),
   1786 					      "canceling read on %p",
   1787 					      disp->handle);
   1788 				isc_nm_cancelread(disp->handle);
   1789 			}
   1790 #endif
   1791 		}
   1792 		break;
   1793 
   1794 	case DNS_DISPATCHSTATE_CANCELED:
   1795 		goto unlock;
   1796 
   1797 	default:
   1798 		UNREACHABLE();
   1799 	}
   1800 
   1801 	dec_stats(disp->mgr, dns_resstatscounter_dispreqtcp);
   1802 
   1803 	resp->state = DNS_DISPATCHSTATE_CANCELED;
   1804 
   1805 unlock:
   1806 
   1807 	/*
   1808 	 * NOTE: Calling the response callback directly from here should be done
   1809 	 * asynchronously, as the dns_dispatch_done() is usually called directly
   1810 	 * from the response callback, so there's a slight chance that the call
   1811 	 * stack will get higher here, but it's mitigated by the ".reading"
   1812 	 * flag, so we don't ever go into a loop.
   1813 	 */
   1814 
   1815 	tcp_recv_processall(&resps, NULL);
   1816 }
   1817 
   1818 static void
   1819 dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
   1820 	REQUIRE(VALID_RESPONSE(resp));
   1821 	REQUIRE(VALID_DISPATCH(resp->disp));
   1822 
   1823 	dns_dispatch_t *disp = resp->disp;
   1824 
   1825 	rcu_read_lock();
   1826 	switch (disp->socktype) {
   1827 	case isc_socktype_udp:
   1828 		udp_dispentry_cancel(resp, result);
   1829 		break;
   1830 	case isc_socktype_tcp:
   1831 		tcp_dispentry_cancel(resp, result);
   1832 		break;
   1833 	default:
   1834 		UNREACHABLE();
   1835 	}
   1836 	rcu_read_unlock();
   1837 }
   1838 
   1839 void
   1840 dns_dispatch_done(dns_dispentry_t **respp) {
   1841 	REQUIRE(VALID_RESPONSE(*respp));
   1842 
   1843 	dns_dispentry_t *resp = *respp;
   1844 	*respp = NULL;
   1845 
   1846 	dispentry_cancel(resp, ISC_R_CANCELED);
   1847 	dns_dispentry_detach(&resp); /* DISPENTRY000 */
   1848 }
   1849 
   1850 static void
   1851 udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp) {
   1852 	REQUIRE(VALID_RESPONSE(resp));
   1853 
   1854 	dispentry_log(resp, ISC_LOG_DEBUG(90), "attaching handle %p to %p",
   1855 		      handle, &resp->handle);
   1856 	isc_nmhandle_attach(handle, &resp->handle);
   1857 	dns_dispentry_ref(resp); /* DISPENTRY003 */
   1858 	dispentry_log(resp, ISC_LOG_DEBUG(90), "reading");
   1859 	isc_nm_read(resp->handle, udp_recv, resp);
   1860 	resp->reading = true;
   1861 }
   1862 
   1863 static void
   1864 tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
   1865 	REQUIRE(VALID_DISPATCH(disp));
   1866 	REQUIRE(disp->socktype == isc_socktype_tcp);
   1867 
   1868 	dns_dispatch_ref(disp); /* DISPATCH002 */
   1869 	if (resp != NULL) {
   1870 		dispentry_log(resp, ISC_LOG_DEBUG(90), "reading from %p",
   1871 			      disp->handle);
   1872 		INSIST(!isc_time_isepoch(&resp->start));
   1873 	} else {
   1874 		dispatch_log(disp, ISC_LOG_DEBUG(90),
   1875 			     "TCP reading without response from %p",
   1876 			     disp->handle);
   1877 	}
   1878 	isc_nm_read(disp->handle, tcp_recv, disp);
   1879 	disp->reading = true;
   1880 }
   1881 
   1882 static void
   1883 resp_connected(void *arg) {
   1884 	dns_dispentry_t *resp = arg;
   1885 	dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
   1886 		      isc_result_totext(resp->result));
   1887 
   1888 	resp->connected(resp->result, NULL, resp->arg);
   1889 	dns_dispentry_detach(&resp); /* DISPENTRY005 */
   1890 }
   1891 
   1892 static void
   1893 tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
   1894 	dns_dispatch_t *disp = (dns_dispatch_t *)arg;
   1895 	dns_dispentry_t *resp = NULL;
   1896 	dns_dispentry_t *next = NULL;
   1897 	dns_displist_t resps = ISC_LIST_INITIALIZER;
   1898 
   1899 	if (isc_log_wouldlog(dns_lctx, 90)) {
   1900 		char localbuf[ISC_SOCKADDR_FORMATSIZE];
   1901 		char peerbuf[ISC_SOCKADDR_FORMATSIZE];
   1902 		if (handle != NULL) {
   1903 			isc_sockaddr_t local = isc_nmhandle_localaddr(handle);
   1904 			isc_sockaddr_t peer = isc_nmhandle_peeraddr(handle);
   1905 
   1906 			isc_sockaddr_format(&local, localbuf,
   1907 					    ISC_SOCKADDR_FORMATSIZE);
   1908 			isc_sockaddr_format(&peer, peerbuf,
   1909 					    ISC_SOCKADDR_FORMATSIZE);
   1910 		} else {
   1911 			isc_sockaddr_format(&disp->local, localbuf,
   1912 					    ISC_SOCKADDR_FORMATSIZE);
   1913 			isc_sockaddr_format(&disp->peer, peerbuf,
   1914 					    ISC_SOCKADDR_FORMATSIZE);
   1915 		}
   1916 
   1917 		dispatch_log(disp, ISC_LOG_DEBUG(90),
   1918 			     "connected from %s to %s: %s", localbuf, peerbuf,
   1919 			     isc_result_totext(eresult));
   1920 	}
   1921 
   1922 	REQUIRE(disp->tid == isc_tid());
   1923 	INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING);
   1924 
   1925 	/*
   1926 	 * If there are pending responses, call the connect
   1927 	 * callbacks for all of them.
   1928 	 */
   1929 	for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) {
   1930 		next = ISC_LIST_NEXT(resp, plink);
   1931 		ISC_LIST_UNLINK(disp->pending, resp, plink);
   1932 		ISC_LIST_APPEND(resps, resp, rlink);
   1933 		resp->result = eresult;
   1934 
   1935 		if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
   1936 			resp->result = ISC_R_CANCELED;
   1937 		} else if (eresult == ISC_R_SUCCESS) {
   1938 			resp->state = DNS_DISPATCHSTATE_CONNECTED;
   1939 			ISC_LIST_APPEND(disp->active, resp, alink);
   1940 			resp->reading = true;
   1941 			dispentry_log(resp, ISC_LOG_DEBUG(90), "start reading");
   1942 		} else {
   1943 			resp->state = DNS_DISPATCHSTATE_NONE;
   1944 		}
   1945 	}
   1946 
   1947 	if (ISC_LIST_EMPTY(disp->active)) {
   1948 		/* All responses have been canceled */
   1949 		disp->state = DNS_DISPATCHSTATE_CANCELED;
   1950 	} else if (eresult == ISC_R_SUCCESS) {
   1951 		disp->state = DNS_DISPATCHSTATE_CONNECTED;
   1952 		isc_nmhandle_attach(handle, &disp->handle);
   1953 		tcp_startrecv(disp, resp);
   1954 	} else {
   1955 		disp->state = DNS_DISPATCHSTATE_NONE;
   1956 	}
   1957 
   1958 	for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
   1959 		next = ISC_LIST_NEXT(resp, rlink);
   1960 		ISC_LIST_UNLINK(resps, resp, rlink);
   1961 
   1962 		resp_connected(resp);
   1963 	}
   1964 
   1965 	dns_dispatch_detach(&disp); /* DISPATCH003 */
   1966 }
   1967 
   1968 static void
   1969 udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
   1970 	dns_dispentry_t *resp = (dns_dispentry_t *)arg;
   1971 	dns_dispatch_t *disp = resp->disp;
   1972 
   1973 	dispentry_log(resp, ISC_LOG_DEBUG(90), "connected: %s",
   1974 		      isc_result_totext(eresult));
   1975 
   1976 	REQUIRE(disp->tid == isc_tid());
   1977 	switch (resp->state) {
   1978 	case DNS_DISPATCHSTATE_CANCELED:
   1979 		eresult = ISC_R_CANCELED;
   1980 		ISC_LIST_UNLINK(disp->pending, resp, plink);
   1981 		goto unlock;
   1982 	case DNS_DISPATCHSTATE_CONNECTING:
   1983 		ISC_LIST_UNLINK(disp->pending, resp, plink);
   1984 		break;
   1985 	default:
   1986 		UNREACHABLE();
   1987 	}
   1988 
   1989 	switch (eresult) {
   1990 	case ISC_R_CANCELED:
   1991 		break;
   1992 	case ISC_R_SUCCESS:
   1993 		resp->state = DNS_DISPATCHSTATE_CONNECTED;
   1994 		udp_startrecv(handle, resp);
   1995 		break;
   1996 	case ISC_R_NOPERM:
   1997 	case ISC_R_ADDRINUSE: {
   1998 		in_port_t localport = isc_sockaddr_getport(&disp->local);
   1999 		isc_result_t result;
   2000 
   2001 		/* probably a port collision; try a different one */
   2002 		result = setup_socket(disp, resp, &resp->peer, &localport);
   2003 		if (result == ISC_R_SUCCESS) {
   2004 			udp_dispatch_connect(disp, resp);
   2005 			goto detach;
   2006 		}
   2007 		resp->state = DNS_DISPATCHSTATE_NONE;
   2008 		break;
   2009 	}
   2010 	default:
   2011 		resp->state = DNS_DISPATCHSTATE_NONE;
   2012 		break;
   2013 	}
   2014 unlock:
   2015 
   2016 	dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s",
   2017 		      isc_result_totext(eresult));
   2018 	resp->connected(eresult, NULL, resp->arg);
   2019 
   2020 detach:
   2021 	dns_dispentry_detach(&resp); /* DISPENTRY004 */
   2022 }
   2023 
   2024 static void
   2025 udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
   2026 	REQUIRE(disp->tid == isc_tid());
   2027 	resp->state = DNS_DISPATCHSTATE_CONNECTING;
   2028 	resp->start = isc_loop_now(resp->loop);
   2029 	dns_dispentry_ref(resp); /* DISPENTRY004 */
   2030 	ISC_LIST_APPEND(disp->pending, resp, plink);
   2031 
   2032 	isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer,
   2033 			  udp_connected, resp, resp->timeout);
   2034 }
   2035 
   2036 static inline const char *
   2037 get_tls_sni_hostname(dns_dispentry_t *resp) {
   2038 	char *hostname = NULL;
   2039 
   2040 	if (resp->transport != NULL) {
   2041 		hostname = dns_transport_get_remote_hostname(resp->transport);
   2042 	}
   2043 
   2044 	if (hostname == NULL) {
   2045 		return NULL;
   2046 	}
   2047 
   2048 	if (isc_tls_valid_sni_hostname(hostname)) {
   2049 		return hostname;
   2050 	}
   2051 
   2052 	return NULL;
   2053 }
   2054 
   2055 static isc_result_t
   2056 tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
   2057 	dns_transport_type_t transport_type = DNS_TRANSPORT_TCP;
   2058 	isc_tlsctx_t *tlsctx = NULL;
   2059 	isc_tlsctx_client_session_cache_t *sess_cache = NULL;
   2060 
   2061 	if (resp->transport != NULL) {
   2062 		transport_type = dns_transport_get_type(resp->transport);
   2063 	}
   2064 
   2065 	if (transport_type == DNS_TRANSPORT_TLS) {
   2066 		isc_result_t result;
   2067 
   2068 		result = dns_transport_get_tlsctx(
   2069 			resp->transport, &resp->peer, resp->tlsctx_cache,
   2070 			resp->mctx, &tlsctx, &sess_cache);
   2071 
   2072 		if (result != ISC_R_SUCCESS) {
   2073 			return result;
   2074 		}
   2075 		INSIST(tlsctx != NULL);
   2076 	}
   2077 
   2078 	/* Check whether the dispatch is already connecting or connected. */
   2079 	REQUIRE(disp->tid == isc_tid());
   2080 	switch (disp->state) {
   2081 	case DNS_DISPATCHSTATE_NONE:
   2082 		/* First connection, continue with connecting */
   2083 		disp->state = DNS_DISPATCHSTATE_CONNECTING;
   2084 		resp->state = DNS_DISPATCHSTATE_CONNECTING;
   2085 		resp->start = isc_loop_now(resp->loop);
   2086 		dns_dispentry_ref(resp); /* DISPENTRY005 */
   2087 		ISC_LIST_APPEND(disp->pending, resp, plink);
   2088 
   2089 		char localbuf[ISC_SOCKADDR_FORMATSIZE];
   2090 		char peerbuf[ISC_SOCKADDR_FORMATSIZE];
   2091 
   2092 		isc_sockaddr_format(&disp->local, localbuf,
   2093 				    ISC_SOCKADDR_FORMATSIZE);
   2094 		isc_sockaddr_format(&disp->peer, peerbuf,
   2095 				    ISC_SOCKADDR_FORMATSIZE);
   2096 
   2097 		dns_dispatch_ref(disp); /* DISPATCH003 */
   2098 		dispentry_log(resp, ISC_LOG_DEBUG(90),
   2099 			      "connecting from %s to %s, timeout %u", localbuf,
   2100 			      peerbuf, resp->timeout);
   2101 
   2102 		const char *hostname = get_tls_sni_hostname(resp);
   2103 
   2104 		isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local,
   2105 					&disp->peer, tcp_connected, disp,
   2106 					resp->timeout, tlsctx, hostname,
   2107 					sess_cache, ISC_NM_PROXY_NONE, NULL);
   2108 		break;
   2109 
   2110 	case DNS_DISPATCHSTATE_CONNECTING:
   2111 		/* Connection pending; add resp to the list */
   2112 		resp->state = DNS_DISPATCHSTATE_CONNECTING;
   2113 		resp->start = isc_loop_now(resp->loop);
   2114 		dns_dispentry_ref(resp); /* DISPENTRY005 */
   2115 		ISC_LIST_APPEND(disp->pending, resp, plink);
   2116 		break;
   2117 
   2118 	case DNS_DISPATCHSTATE_CONNECTED:
   2119 		resp->state = DNS_DISPATCHSTATE_CONNECTED;
   2120 		resp->start = isc_loop_now(resp->loop);
   2121 
   2122 		/* Add the resp to the reading list */
   2123 		ISC_LIST_APPEND(disp->active, resp, alink);
   2124 		dispentry_log(resp, ISC_LOG_DEBUG(90),
   2125 			      "already connected; attaching");
   2126 		resp->reading = true;
   2127 
   2128 		if (!disp->reading) {
   2129 			/* Restart the reading */
   2130 			tcp_startrecv(disp, resp);
   2131 		}
   2132 
   2133 		/* Already connected; call the connected cb asynchronously */
   2134 		dns_dispentry_ref(resp); /* DISPENTRY005 */
   2135 		isc_async_run(resp->loop, resp_connected, resp);
   2136 		break;
   2137 
   2138 	default:
   2139 		UNREACHABLE();
   2140 	}
   2141 
   2142 	return ISC_R_SUCCESS;
   2143 }
   2144 
   2145 isc_result_t
   2146 dns_dispatch_connect(dns_dispentry_t *resp) {
   2147 	REQUIRE(VALID_RESPONSE(resp));
   2148 	REQUIRE(VALID_DISPATCH(resp->disp));
   2149 
   2150 	dns_dispatch_t *disp = resp->disp;
   2151 
   2152 	switch (disp->socktype) {
   2153 	case isc_socktype_tcp:
   2154 		return tcp_dispatch_connect(disp, resp);
   2155 
   2156 	case isc_socktype_udp:
   2157 		udp_dispatch_connect(disp, resp);
   2158 		return ISC_R_SUCCESS;
   2159 
   2160 	default:
   2161 		UNREACHABLE();
   2162 	}
   2163 }
   2164 
   2165 static void
   2166 send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
   2167 	dns_dispentry_t *resp = (dns_dispentry_t *)cbarg;
   2168 
   2169 	REQUIRE(VALID_RESPONSE(resp));
   2170 
   2171 	dns_dispatch_t *disp = resp->disp;
   2172 
   2173 	REQUIRE(VALID_DISPATCH(disp));
   2174 
   2175 	dispentry_log(resp, ISC_LOG_DEBUG(90), "sent: %s",
   2176 		      isc_result_totext(result));
   2177 
   2178 	resp->sent(result, NULL, resp->arg);
   2179 
   2180 	if (result != ISC_R_SUCCESS) {
   2181 		dispentry_cancel(resp, result);
   2182 	}
   2183 
   2184 	dns_dispentry_detach(&resp); /* DISPENTRY007 */
   2185 	isc_nmhandle_detach(&handle);
   2186 }
   2187 
   2188 static void
   2189 tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
   2190 		     int32_t timeout) {
   2191 	REQUIRE(timeout <= INT16_MAX);
   2192 
   2193 	dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading");
   2194 
   2195 	if (!resp->reading) {
   2196 		ISC_LIST_APPEND(disp->active, resp, alink);
   2197 		resp->reading = true;
   2198 	}
   2199 
   2200 	if (disp->reading) {
   2201 		return;
   2202 	}
   2203 
   2204 	if (timeout > 0) {
   2205 		isc_nmhandle_settimeout(disp->handle, timeout);
   2206 	}
   2207 
   2208 	dns_dispatch_ref(disp); /* DISPATCH002 */
   2209 	isc_nm_read(disp->handle, tcp_recv, disp);
   2210 	disp->reading = true;
   2211 }
   2212 
   2213 static void
   2214 udp_dispatch_getnext(dns_dispentry_t *resp, int32_t timeout) {
   2215 	REQUIRE(timeout <= INT16_MAX);
   2216 
   2217 	if (resp->reading) {
   2218 		return;
   2219 	}
   2220 
   2221 	if (timeout > 0) {
   2222 		isc_nmhandle_settimeout(resp->handle, timeout);
   2223 	}
   2224 
   2225 	dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading");
   2226 
   2227 	dns_dispentry_ref(resp); /* DISPENTRY003 */
   2228 	isc_nm_read(resp->handle, udp_recv, resp);
   2229 	resp->reading = true;
   2230 }
   2231 
   2232 void
   2233 dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
   2234 	REQUIRE(VALID_RESPONSE(resp));
   2235 	REQUIRE(VALID_DISPATCH(resp->disp));
   2236 
   2237 	dns_dispatch_t *disp = resp->disp;
   2238 
   2239 	dispentry_log(resp, ISC_LOG_DEBUG(90), "resume");
   2240 
   2241 	REQUIRE(disp->tid == isc_tid());
   2242 	switch (disp->socktype) {
   2243 	case isc_socktype_udp: {
   2244 		udp_dispatch_getnext(resp, timeout);
   2245 		break;
   2246 	}
   2247 	case isc_socktype_tcp:
   2248 		INSIST(disp->timedout > 0);
   2249 		disp->timedout--;
   2250 		tcp_dispatch_getnext(disp, resp, timeout);
   2251 		break;
   2252 	default:
   2253 		UNREACHABLE();
   2254 	}
   2255 }
   2256 
   2257 void
   2258 dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r) {
   2259 	REQUIRE(VALID_RESPONSE(resp));
   2260 	REQUIRE(VALID_DISPATCH(resp->disp));
   2261 
   2262 	dns_dispatch_t *disp = resp->disp;
   2263 	isc_nmhandle_t *sendhandle = NULL;
   2264 
   2265 	dispentry_log(resp, ISC_LOG_DEBUG(90), "sending");
   2266 	switch (disp->socktype) {
   2267 	case isc_socktype_udp:
   2268 		isc_nmhandle_attach(resp->handle, &sendhandle);
   2269 		break;
   2270 	case isc_socktype_tcp:
   2271 		isc_nmhandle_attach(disp->handle, &sendhandle);
   2272 		break;
   2273 	default:
   2274 		UNREACHABLE();
   2275 	}
   2276 	dns_dispentry_ref(resp); /* DISPENTRY007 */
   2277 	isc_nm_send(sendhandle, r, send_done, resp);
   2278 }
   2279 
   2280 isc_result_t
   2281 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
   2282 	REQUIRE(VALID_DISPATCH(disp));
   2283 	REQUIRE(addrp != NULL);
   2284 
   2285 	if (disp->socktype == isc_socktype_udp) {
   2286 		*addrp = disp->local;
   2287 		return ISC_R_SUCCESS;
   2288 	}
   2289 	return ISC_R_NOTIMPLEMENTED;
   2290 }
   2291 
   2292 isc_result_t
   2293 dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) {
   2294 	REQUIRE(VALID_RESPONSE(resp));
   2295 	REQUIRE(VALID_DISPATCH(resp->disp));
   2296 	REQUIRE(addrp != NULL);
   2297 
   2298 	dns_dispatch_t *disp = resp->disp;
   2299 
   2300 	switch (disp->socktype) {
   2301 	case isc_socktype_tcp:
   2302 		*addrp = disp->local;
   2303 		return ISC_R_SUCCESS;
   2304 	case isc_socktype_udp:
   2305 		*addrp = isc_nmhandle_localaddr(resp->handle);
   2306 		return ISC_R_SUCCESS;
   2307 	default:
   2308 		UNREACHABLE();
   2309 	}
   2310 }
   2311 
   2312 dns_dispatch_t *
   2313 dns_dispatchset_get(dns_dispatchset_t *dset) {
   2314 	uint32_t tid = isc_tid();
   2315 
   2316 	/* check that dispatch set is configured */
   2317 	if (dset == NULL || dset->ndisp == 0) {
   2318 		return NULL;
   2319 	}
   2320 
   2321 	INSIST(tid < dset->ndisp);
   2322 
   2323 	return dset->dispatches[tid];
   2324 }
   2325 
   2326 isc_result_t
   2327 dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source,
   2328 		       dns_dispatchset_t **dsetp, uint32_t ndisp) {
   2329 	isc_result_t result;
   2330 	dns_dispatchset_t *dset = NULL;
   2331 	dns_dispatchmgr_t *mgr = NULL;
   2332 	size_t i;
   2333 
   2334 	REQUIRE(VALID_DISPATCH(source));
   2335 	REQUIRE(source->socktype == isc_socktype_udp);
   2336 	REQUIRE(dsetp != NULL && *dsetp == NULL);
   2337 
   2338 	mgr = source->mgr;
   2339 
   2340 	dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t));
   2341 	*dset = (dns_dispatchset_t){ .ndisp = ndisp };
   2342 
   2343 	isc_mem_attach(mctx, &dset->mctx);
   2344 
   2345 	dset->dispatches = isc_mem_cget(dset->mctx, ndisp,
   2346 					sizeof(dns_dispatch_t *));
   2347 
   2348 	dset->dispatches[0] = NULL;
   2349 	dns_dispatch_attach(source, &dset->dispatches[0]); /* DISPATCH004 */
   2350 
   2351 	for (i = 1; i < dset->ndisp; i++) {
   2352 		result = dispatch_createudp(mgr, &source->local, i,
   2353 					    &dset->dispatches[i]);
   2354 		if (result != ISC_R_SUCCESS) {
   2355 			goto fail;
   2356 		}
   2357 	}
   2358 
   2359 	*dsetp = dset;
   2360 
   2361 	return ISC_R_SUCCESS;
   2362 
   2363 fail:
   2364 	for (size_t j = 0; j < i; j++) {
   2365 		dns_dispatch_detach(&(dset->dispatches[j])); /* DISPATCH004 */
   2366 	}
   2367 	isc_mem_cput(dset->mctx, dset->dispatches, ndisp,
   2368 		     sizeof(dns_dispatch_t *));
   2369 
   2370 	isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
   2371 	return result;
   2372 }
   2373 
   2374 void
   2375 dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
   2376 	REQUIRE(dsetp != NULL && *dsetp != NULL);
   2377 
   2378 	dns_dispatchset_t *dset = *dsetp;
   2379 	*dsetp = NULL;
   2380 
   2381 	for (size_t i = 0; i < dset->ndisp; i++) {
   2382 		dns_dispatch_detach(&(dset->dispatches[i])); /* DISPATCH004 */
   2383 	}
   2384 	isc_mem_cput(dset->mctx, dset->dispatches, dset->ndisp,
   2385 		     sizeof(dns_dispatch_t *));
   2386 	isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
   2387 }
   2388 
   2389 isc_result_t
   2390 dns_dispatch_checkperm(dns_dispatch_t *disp) {
   2391 	REQUIRE(VALID_DISPATCH(disp));
   2392 
   2393 	if (disp->handle == NULL || disp->socktype == isc_socktype_udp) {
   2394 		return ISC_R_NOPERM;
   2395 	}
   2396 
   2397 	return isc_nm_xfr_checkperm(disp->handle);
   2398 }
   2399