Home | History | Annotate | Line # | Download | only in netmgr
      1 /*	$NetBSD: netmgr.c,v 1.16 2026/04/08 00:16:16 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 #include <assert.h>
     17 #include <inttypes.h>
     18 #include <unistd.h>
     19 
     20 #include <isc/async.h>
     21 #include <isc/atomic.h>
     22 #include <isc/backtrace.h>
     23 #include <isc/barrier.h>
     24 #include <isc/buffer.h>
     25 #include <isc/condition.h>
     26 #include <isc/errno.h>
     27 #include <isc/job.h>
     28 #include <isc/list.h>
     29 #include <isc/log.h>
     30 #include <isc/loop.h>
     31 #include <isc/magic.h>
     32 #include <isc/mem.h>
     33 #include <isc/netaddr.h>
     34 #include <isc/netmgr.h>
     35 #include <isc/quota.h>
     36 #include <isc/random.h>
     37 #include <isc/refcount.h>
     38 #include <isc/region.h>
     39 #include <isc/result.h>
     40 #include <isc/sockaddr.h>
     41 #include <isc/stats.h>
     42 #include <isc/strerr.h>
     43 #include <isc/thread.h>
     44 #include <isc/tid.h>
     45 #include <isc/tls.h>
     46 #include <isc/util.h>
     47 #include <isc/uv.h>
     48 
     49 #include "../loop_p.h"
     50 #include "netmgr-int.h"
     51 #include "openssl_shim.h"
     52 
     53 /*%
     54  * Shortcut index arrays to get access to statistics counters.
     55  */
     56 
     57 static const isc_statscounter_t udp4statsindex[] = {
     58 	isc_sockstatscounter_udp4open,
     59 	isc_sockstatscounter_udp4openfail,
     60 	isc_sockstatscounter_udp4close,
     61 	isc_sockstatscounter_udp4bindfail,
     62 	isc_sockstatscounter_udp4connectfail,
     63 	isc_sockstatscounter_udp4connect,
     64 	-1,
     65 	-1,
     66 	isc_sockstatscounter_udp4sendfail,
     67 	isc_sockstatscounter_udp4recvfail,
     68 	isc_sockstatscounter_udp4active,
     69 	-1,
     70 };
     71 
     72 static const isc_statscounter_t udp6statsindex[] = {
     73 	isc_sockstatscounter_udp6open,
     74 	isc_sockstatscounter_udp6openfail,
     75 	isc_sockstatscounter_udp6close,
     76 	isc_sockstatscounter_udp6bindfail,
     77 	isc_sockstatscounter_udp6connectfail,
     78 	isc_sockstatscounter_udp6connect,
     79 	-1,
     80 	-1,
     81 	isc_sockstatscounter_udp6sendfail,
     82 	isc_sockstatscounter_udp6recvfail,
     83 	isc_sockstatscounter_udp6active,
     84 	-1,
     85 };
     86 
     87 static const isc_statscounter_t tcp4statsindex[] = {
     88 	isc_sockstatscounter_tcp4open,	      isc_sockstatscounter_tcp4openfail,
     89 	isc_sockstatscounter_tcp4close,	      isc_sockstatscounter_tcp4bindfail,
     90 	isc_sockstatscounter_tcp4connectfail, isc_sockstatscounter_tcp4connect,
     91 	isc_sockstatscounter_tcp4acceptfail,  isc_sockstatscounter_tcp4accept,
     92 	isc_sockstatscounter_tcp4sendfail,    isc_sockstatscounter_tcp4recvfail,
     93 	isc_sockstatscounter_tcp4active,      isc_sockstatscounter_tcp4clients,
     94 };
     95 
     96 static const isc_statscounter_t tcp6statsindex[] = {
     97 	isc_sockstatscounter_tcp6open,	      isc_sockstatscounter_tcp6openfail,
     98 	isc_sockstatscounter_tcp6close,	      isc_sockstatscounter_tcp6bindfail,
     99 	isc_sockstatscounter_tcp6connectfail, isc_sockstatscounter_tcp6connect,
    100 	isc_sockstatscounter_tcp6acceptfail,  isc_sockstatscounter_tcp6accept,
    101 	isc_sockstatscounter_tcp6sendfail,    isc_sockstatscounter_tcp6recvfail,
    102 	isc_sockstatscounter_tcp6active,      isc_sockstatscounter_tcp6clients,
    103 };
    104 
    105 static void
    106 nmsocket_maybe_destroy(isc_nmsocket_t *sock FLARG);
    107 static void
    108 nmhandle_free(isc_nmsocket_t *sock, isc_nmhandle_t *handle);
    109 
    110 /*%<
    111  * Issue a 'handle closed' callback on the socket.
    112  */
    113 
    114 static void
    115 shutdown_walk_cb(uv_handle_t *handle, void *arg);
    116 
    117 static void
    118 networker_teardown(void *arg) {
    119 	isc__networker_t *worker = arg;
    120 	isc_loop_t *loop = worker->loop;
    121 
    122 	worker->shuttingdown = true;
    123 
    124 	isc__netmgr_log(worker->netmgr, ISC_LOG_DEBUG(1),
    125 			"Shutting down network manager worker on loop %p(%d)",
    126 			loop, isc_tid());
    127 
    128 	uv_walk(&loop->loop, shutdown_walk_cb, NULL);
    129 
    130 	isc__networker_detach(&worker);
    131 }
    132 
    133 static void
    134 netmgr_teardown(void *arg) {
    135 	isc_nm_t *netmgr = (void *)arg;
    136 
    137 	if (atomic_compare_exchange_strong_acq_rel(&netmgr->shuttingdown,
    138 						   &(bool){ false }, true))
    139 	{
    140 		isc__netmgr_log(netmgr, ISC_LOG_DEBUG(1),
    141 				"Shutting down network manager");
    142 	}
    143 }
    144 
    145 #if HAVE_DECL_UV_UDP_LINUX_RECVERR
    146 #define MINIMAL_UV_VERSION UV_VERSION(1, 42, 0)
    147 #elif HAVE_DECL_UV_UDP_MMSG_FREE
    148 #define MINIMAL_UV_VERSION UV_VERSION(1, 40, 0)
    149 #elif HAVE_DECL_UV_UDP_RECVMMSG
    150 #define MAXIMAL_UV_VERSION UV_VERSION(1, 39, 99)
    151 #define MINIMAL_UV_VERSION UV_VERSION(1, 37, 0)
    152 #else
    153 #define MAXIMAL_UV_VERSION UV_VERSION(1, 34, 99)
    154 #define MINIMAL_UV_VERSION UV_VERSION(1, 34, 0)
    155 #endif
    156 
    157 void
    158 isc_netmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t **netmgrp) {
    159 	isc_nm_t *netmgr = NULL;
    160 	in_port_t port_low, port_high;
    161 
    162 #ifdef MAXIMAL_UV_VERSION
    163 	if (uv_version() > MAXIMAL_UV_VERSION) {
    164 		FATAL_ERROR("libuv version too new: running with libuv %s "
    165 			    "when compiled with libuv %s will lead to "
    166 			    "libuv failures",
    167 			    uv_version_string(), UV_VERSION_STRING);
    168 	}
    169 #endif /* MAXIMAL_UV_VERSION */
    170 
    171 	if (uv_version() < MINIMAL_UV_VERSION) {
    172 		FATAL_ERROR("libuv version too old: running with libuv %s "
    173 			    "when compiled with libuv %s will lead to "
    174 			    "libuv failures",
    175 			    uv_version_string(), UV_VERSION_STRING);
    176 	}
    177 
    178 	netmgr = isc_mem_get(mctx, sizeof(*netmgr));
    179 	*netmgr = (isc_nm_t){
    180 		.loopmgr = loopmgr,
    181 		.nloops = isc_loopmgr_nloops(loopmgr),
    182 	};
    183 
    184 	isc_mem_attach(mctx, &netmgr->mctx);
    185 	isc_refcount_init(&netmgr->references, 1);
    186 	atomic_init(&netmgr->maxudp, 0);
    187 	atomic_init(&netmgr->shuttingdown, false);
    188 	atomic_init(&netmgr->recv_tcp_buffer_size, 0);
    189 	atomic_init(&netmgr->send_tcp_buffer_size, 0);
    190 	atomic_init(&netmgr->recv_udp_buffer_size, 0);
    191 	atomic_init(&netmgr->send_udp_buffer_size, 0);
    192 	atomic_init(&netmgr->port_low4, 0);
    193 	atomic_init(&netmgr->port_high4, 65535);
    194 	atomic_init(&netmgr->port_low6, 0);
    195 	atomic_init(&netmgr->port_high6, 65535);
    196 
    197 #if HAVE_SO_REUSEPORT_LB
    198 	netmgr->load_balance_sockets = true;
    199 #else
    200 	netmgr->load_balance_sockets = false;
    201 #endif
    202 
    203 	/*
    204 	 * Default TCP timeout values.
    205 	 * May be updated by isc_nm_tcptimeouts().
    206 	 */
    207 	atomic_init(&netmgr->init, 30000);
    208 	atomic_init(&netmgr->idle, 30000);
    209 	atomic_init(&netmgr->keepalive, 30000);
    210 	atomic_init(&netmgr->advertised, 30000);
    211 
    212 	netmgr->workers = isc_mem_cget(mctx, netmgr->nloops,
    213 				       sizeof(netmgr->workers[0]));
    214 
    215 	isc_loopmgr_teardown(loopmgr, netmgr_teardown, netmgr);
    216 
    217 	netmgr->magic = NM_MAGIC;
    218 
    219 	for (size_t i = 0; i < netmgr->nloops; i++) {
    220 		isc_loop_t *loop = isc_loop_get(netmgr->loopmgr, i);
    221 		isc__networker_t *worker = &netmgr->workers[i];
    222 
    223 		*worker = (isc__networker_t){
    224 			.recvbuf = isc_mem_get(loop->mctx,
    225 					       ISC_NETMGR_RECVBUF_SIZE),
    226 			.active_sockets = ISC_LIST_INITIALIZER,
    227 		};
    228 
    229 		isc_nm_attach(netmgr, &worker->netmgr);
    230 
    231 		isc_mem_attach(loop->mctx, &worker->mctx);
    232 
    233 		isc_mempool_create(worker->mctx, sizeof(isc_nmsocket_t),
    234 				   &worker->nmsocket_pool);
    235 		isc_mempool_setfreemax(worker->nmsocket_pool,
    236 				       ISC_NM_NMSOCKET_MAX);
    237 
    238 		isc_mempool_create(worker->mctx, sizeof(isc__nm_uvreq_t),
    239 				   &worker->uvreq_pool);
    240 		isc_mempool_setfreemax(worker->uvreq_pool, ISC_NM_UVREQS_MAX);
    241 
    242 		isc_loop_attach(loop, &worker->loop);
    243 		isc_loop_teardown(loop, networker_teardown, worker);
    244 		isc_refcount_init(&worker->references, 1);
    245 	}
    246 
    247 	*netmgrp = netmgr;
    248 
    249 	/*
    250 	 * Set the initial port range for IP_LOCAL_PORT_RANGE.
    251 	 */
    252 	isc_net_getportrange(AF_INET, &port_low, &port_high);
    253 	isc_netmgr_portrange(netmgr, AF_INET, port_low, port_high);
    254 
    255 	isc_net_getportrange(AF_INET6, &port_low, &port_high);
    256 	isc_netmgr_portrange(netmgr, AF_INET6, port_low, port_high);
    257 }
    258 
    259 /*
    260  * Free the resources of the network manager.
    261  */
    262 static void
    263 nm_destroy(isc_nm_t **mgr0) {
    264 	REQUIRE(VALID_NM(*mgr0));
    265 
    266 	isc_nm_t *mgr = *mgr0;
    267 	*mgr0 = NULL;
    268 
    269 	isc_refcount_destroy(&mgr->references);
    270 
    271 	mgr->magic = 0;
    272 
    273 	if (mgr->stats != NULL) {
    274 		isc_stats_detach(&mgr->stats);
    275 	}
    276 
    277 	isc_mem_cput(mgr->mctx, mgr->workers, mgr->nloops,
    278 		     sizeof(mgr->workers[0]));
    279 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
    280 }
    281 
    282 void
    283 isc_nm_attach(isc_nm_t *mgr, isc_nm_t **dst) {
    284 	REQUIRE(VALID_NM(mgr));
    285 	REQUIRE(dst != NULL && *dst == NULL);
    286 
    287 	isc_refcount_increment(&mgr->references);
    288 
    289 	*dst = mgr;
    290 }
    291 
    292 void
    293 isc_nm_detach(isc_nm_t **mgr0) {
    294 	isc_nm_t *mgr = NULL;
    295 
    296 	REQUIRE(mgr0 != NULL);
    297 	REQUIRE(VALID_NM(*mgr0));
    298 
    299 	mgr = *mgr0;
    300 	*mgr0 = NULL;
    301 
    302 	if (isc_refcount_decrement(&mgr->references) == 1) {
    303 		nm_destroy(&mgr);
    304 	}
    305 }
    306 
    307 void
    308 isc_netmgr_destroy(isc_nm_t **netmgrp) {
    309 	isc_nm_t *mgr = NULL;
    310 
    311 	REQUIRE(VALID_NM(*netmgrp));
    312 
    313 	mgr = *netmgrp;
    314 	*netmgrp = NULL;
    315 
    316 	REQUIRE(isc_refcount_decrement(&mgr->references) == 1);
    317 	nm_destroy(&mgr);
    318 }
    319 
    320 void
    321 isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp) {
    322 	REQUIRE(VALID_NM(mgr));
    323 
    324 	atomic_store_relaxed(&mgr->maxudp, maxudp);
    325 }
    326 
    327 int
    328 isc_nmhandle_getfd(isc_nmhandle_t *handle) {
    329 	REQUIRE(VALID_NMHANDLE(handle));
    330 
    331 	return (handle->sock->fd);
    332 }
    333 
    334 void
    335 isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout) {
    336 	REQUIRE(VALID_NMHANDLE(handle));
    337 	REQUIRE(VALID_NMSOCK(handle->sock));
    338 	REQUIRE(handle->sock->tid == isc_tid());
    339 
    340 	switch (handle->sock->type) {
    341 	case isc_nm_tcpsocket:
    342 	case isc_nm_udpsocket:
    343 		handle->sock->write_timeout = write_timeout;
    344 		break;
    345 	case isc_nm_tlssocket:
    346 		isc__nmhandle_tls_setwritetimeout(handle, write_timeout);
    347 		break;
    348 	case isc_nm_streamdnssocket:
    349 		isc__nmhandle_streamdns_setwritetimeout(handle, write_timeout);
    350 		break;
    351 	case isc_nm_proxystreamsocket:
    352 		isc__nmhandle_proxystream_setwritetimeout(handle,
    353 							  write_timeout);
    354 		break;
    355 	case isc_nm_proxyudpsocket:
    356 		isc__nmhandle_proxyudp_setwritetimeout(handle, write_timeout);
    357 		break;
    358 	default:
    359 		UNREACHABLE();
    360 		break;
    361 	}
    362 }
    363 
    364 void
    365 isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle,
    366 		   uint32_t keepalive, uint32_t advertised) {
    367 	REQUIRE(VALID_NM(mgr));
    368 
    369 	atomic_store_relaxed(&mgr->init, init);
    370 	atomic_store_relaxed(&mgr->idle, idle);
    371 	atomic_store_relaxed(&mgr->keepalive, keepalive);
    372 	atomic_store_relaxed(&mgr->advertised, advertised);
    373 }
    374 
    375 void
    376 isc_nm_setnetbuffers(isc_nm_t *mgr, int32_t recv_tcp, int32_t send_tcp,
    377 		     int32_t recv_udp, int32_t send_udp) {
    378 	REQUIRE(VALID_NM(mgr));
    379 
    380 	atomic_store_relaxed(&mgr->recv_tcp_buffer_size, recv_tcp);
    381 	atomic_store_relaxed(&mgr->send_tcp_buffer_size, send_tcp);
    382 	atomic_store_relaxed(&mgr->recv_udp_buffer_size, recv_udp);
    383 	atomic_store_relaxed(&mgr->send_udp_buffer_size, send_udp);
    384 }
    385 
    386 bool
    387 isc_nm_getloadbalancesockets(isc_nm_t *mgr) {
    388 	REQUIRE(VALID_NM(mgr));
    389 
    390 	return mgr->load_balance_sockets;
    391 }
    392 
    393 void
    394 isc_nm_setloadbalancesockets(isc_nm_t *mgr, ISC_ATTR_UNUSED bool enabled) {
    395 	REQUIRE(VALID_NM(mgr));
    396 
    397 #if HAVE_SO_REUSEPORT_LB
    398 	mgr->load_balance_sockets = enabled;
    399 #endif
    400 }
    401 
    402 void
    403 isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
    404 		   uint32_t *keepalive, uint32_t *advertised) {
    405 	REQUIRE(VALID_NM(mgr));
    406 
    407 	SET_IF_NOT_NULL(initial, atomic_load_relaxed(&mgr->init));
    408 
    409 	SET_IF_NOT_NULL(idle, atomic_load_relaxed(&mgr->idle));
    410 
    411 	SET_IF_NOT_NULL(keepalive, atomic_load_relaxed(&mgr->keepalive));
    412 
    413 	SET_IF_NOT_NULL(advertised, atomic_load_relaxed(&mgr->advertised));
    414 }
    415 
    416 bool
    417 isc__nmsocket_active(isc_nmsocket_t *sock) {
    418 	REQUIRE(VALID_NMSOCK(sock));
    419 
    420 	return sock->active;
    421 }
    422 
    423 void
    424 isc___nmsocket_attach(isc_nmsocket_t *sock, isc_nmsocket_t **target FLARG) {
    425 	REQUIRE(VALID_NMSOCK(sock));
    426 	REQUIRE(target != NULL && *target == NULL);
    427 
    428 	isc_nmsocket_t *rsock = NULL;
    429 
    430 	if (sock->parent != NULL) {
    431 		rsock = sock->parent;
    432 		INSIST(rsock->parent == NULL); /* sanity check */
    433 	} else {
    434 		rsock = sock;
    435 	}
    436 
    437 	NETMGR_TRACE_LOG("isc__nmsocket_attach():%p->references = %" PRIuFAST32
    438 			 "\n",
    439 			 rsock, isc_refcount_current(&rsock->references) + 1);
    440 
    441 	isc_refcount_increment0(&rsock->references);
    442 
    443 	*target = sock;
    444 }
    445 
    446 /*
    447  * Free all resources inside a socket (including its children if any).
    448  */
    449 static void
    450 nmsocket_cleanup(void *arg) {
    451 	isc_nmsocket_t *sock = arg;
    452 
    453 	REQUIRE(VALID_NMSOCK(sock));
    454 	REQUIRE(!isc__nmsocket_active(sock));
    455 
    456 	isc_nmhandle_t *handle = NULL;
    457 	isc__networker_t *worker = sock->worker;
    458 
    459 	isc_refcount_destroy(&sock->references);
    460 
    461 	isc__nm_decstats(sock, STATID_ACTIVE);
    462 
    463 	REQUIRE(!sock->destroying);
    464 	sock->destroying = true;
    465 
    466 	if (sock->parent == NULL && sock->children != NULL) {
    467 		/*
    468 		 * We shouldn't be here unless there are no active handles,
    469 		 * so we can clean up and free the children.
    470 		 */
    471 		for (size_t i = 0; i < sock->nchildren; i++) {
    472 			isc_refcount_decrementz(&sock->children[i].references);
    473 			nmsocket_cleanup(&sock->children[i]);
    474 		}
    475 
    476 		/*
    477 		 * Now free them.
    478 		 */
    479 		isc_mem_cput(sock->worker->mctx, sock->children,
    480 			     sock->nchildren, sizeof(*sock));
    481 		sock->children = NULL;
    482 		sock->nchildren = 0;
    483 	}
    484 
    485 	sock->statichandle = NULL;
    486 
    487 	if (sock->outerhandle != NULL) {
    488 		isc_nmhandle_detach(&sock->outerhandle);
    489 	}
    490 
    491 	if (sock->outer != NULL) {
    492 		isc__nmsocket_detach(&sock->outer);
    493 	}
    494 
    495 	while ((handle = ISC_LIST_HEAD(sock->inactive_handles)) != NULL) {
    496 		ISC_LIST_DEQUEUE(sock->inactive_handles, handle, inactive_link);
    497 		nmhandle_free(sock, handle);
    498 	}
    499 
    500 	INSIST(sock->server == NULL);
    501 	sock->pquota = NULL;
    502 
    503 	isc__nm_tls_cleanup_data(sock);
    504 #if HAVE_LIBNGHTTP2
    505 	isc__nm_http_cleanup_data(sock);
    506 #endif
    507 	isc__nm_streamdns_cleanup_data(sock);
    508 	isc__nm_proxystream_cleanup_data(sock);
    509 	isc__nm_proxyudp_cleanup_data(sock);
    510 
    511 	if (sock->barriers_initialised) {
    512 		isc_barrier_destroy(&sock->listen_barrier);
    513 		isc_barrier_destroy(&sock->stop_barrier);
    514 	}
    515 
    516 	sock->magic = 0;
    517 
    518 	/* Don't free child socket */
    519 	if (sock->parent == NULL) {
    520 		REQUIRE(sock->tid == isc_tid());
    521 
    522 		ISC_LIST_UNLINK(worker->active_sockets, sock, active_link);
    523 
    524 		isc_mempool_put(worker->nmsocket_pool, sock);
    525 	}
    526 
    527 	isc__networker_detach(&worker);
    528 }
    529 
    530 static bool
    531 nmsocket_has_active_handles(isc_nmsocket_t *sock) {
    532 	if (!ISC_LIST_EMPTY(sock->active_handles)) {
    533 		return true;
    534 	}
    535 
    536 	if (sock->children != NULL) {
    537 		for (size_t i = 0; i < sock->nchildren; i++) {
    538 			isc_nmsocket_t *csock = &sock->children[i];
    539 			if (!ISC_LIST_EMPTY(csock->active_handles)) {
    540 				return true;
    541 			}
    542 		}
    543 	}
    544 
    545 	return false;
    546 }
    547 
    548 static void
    549 nmsocket_maybe_destroy(isc_nmsocket_t *sock FLARG) {
    550 	NETMGR_TRACE_LOG("%s():%p->references = %" PRIuFAST32 "\n", __func__,
    551 			 sock, isc_refcount_current(&sock->references));
    552 
    553 	if (sock->parent != NULL) {
    554 		/*
    555 		 * This is a child socket and cannot be destroyed except
    556 		 * as a side effect of destroying the parent, so let's go
    557 		 * see if the parent is ready to be destroyed.
    558 		 */
    559 		nmsocket_maybe_destroy(sock->parent FLARG_PASS);
    560 		return;
    561 	}
    562 
    563 	REQUIRE(!sock->destroying);
    564 	REQUIRE(!sock->active);
    565 
    566 	if (!sock->closed) {
    567 		return;
    568 	}
    569 
    570 	if (isc_refcount_current(&sock->references) != 0) {
    571 		/*
    572 		 * Using such check is valid only if we don't use
    573 		 * isc_refcount_increment0() on the same variable.
    574 		 */
    575 		return;
    576 	}
    577 
    578 	NETMGR_TRACE_LOG("%s:%p->statichandle = %p\n", __func__, sock,
    579 			 sock->statichandle);
    580 
    581 	/*
    582 	 * This is a parent socket (or a standalone). See whether the
    583 	 * children have active handles before deciding whether to
    584 	 * accept destruction.
    585 	 */
    586 	if (sock->statichandle == NULL && nmsocket_has_active_handles(sock)) {
    587 		return;
    588 	}
    589 
    590 	if (sock->tid == isc_tid()) {
    591 		nmsocket_cleanup(sock);
    592 	} else {
    593 		isc_async_run(sock->worker->loop, nmsocket_cleanup, sock);
    594 	}
    595 }
    596 
    597 void
    598 isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG) {
    599 	REQUIRE(sock->parent == NULL);
    600 
    601 	NETMGR_TRACE_LOG("isc___nmsocket_prep_destroy():%p->references = "
    602 			 "%" PRIuFAST32 "\n",
    603 			 sock, isc_refcount_current(&sock->references));
    604 
    605 	/*
    606 	 * The final external reference to the socket is gone. We can try
    607 	 * destroying the socket, but we have to wait for all the inflight
    608 	 * handles to finish first.
    609 	 */
    610 	sock->active = false;
    611 
    612 	/*
    613 	 * If the socket has children, they have been marked inactive by the
    614 	 * shutdown uv_walk
    615 	 */
    616 
    617 	/*
    618 	 * If we're here then we already stopped listening; otherwise
    619 	 * we'd have a hanging reference from the listening process.
    620 	 *
    621 	 * If it's a regular socket we may need to close it.
    622 	 */
    623 	if (!sock->closing && !sock->closed) {
    624 		switch (sock->type) {
    625 		case isc_nm_udpsocket:
    626 			isc__nm_udp_close(sock);
    627 			return;
    628 		case isc_nm_tcpsocket:
    629 			isc__nm_tcp_close(sock);
    630 			return;
    631 		case isc_nm_streamdnssocket:
    632 			isc__nm_streamdns_close(sock);
    633 			return;
    634 		case isc_nm_tlssocket:
    635 			isc__nm_tls_close(sock);
    636 			return;
    637 #if HAVE_LIBNGHTTP2
    638 		case isc_nm_httpsocket:
    639 			isc__nm_http_close(sock);
    640 			return;
    641 #endif
    642 		case isc_nm_proxystreamsocket:
    643 			isc__nm_proxystream_close(sock);
    644 			return;
    645 		case isc_nm_proxyudpsocket:
    646 			isc__nm_proxyudp_close(sock);
    647 			return;
    648 		default:
    649 			break;
    650 		}
    651 	}
    652 
    653 	nmsocket_maybe_destroy(sock FLARG_PASS);
    654 }
    655 
    656 void
    657 isc___nmsocket_detach(isc_nmsocket_t **sockp FLARG) {
    658 	REQUIRE(sockp != NULL && *sockp != NULL);
    659 	REQUIRE(VALID_NMSOCK(*sockp));
    660 
    661 	isc_nmsocket_t *sock = *sockp, *rsock = NULL;
    662 	*sockp = NULL;
    663 
    664 	/*
    665 	 * If the socket is a part of a set (a child socket) we are
    666 	 * counting references for the whole set at the parent.
    667 	 */
    668 	if (sock->parent != NULL) {
    669 		rsock = sock->parent;
    670 		INSIST(rsock->parent == NULL); /* Sanity check */
    671 	} else {
    672 		rsock = sock;
    673 	}
    674 
    675 	NETMGR_TRACE_LOG("isc__nmsocket_detach():%p->references = %" PRIuFAST32
    676 			 "\n",
    677 			 rsock, isc_refcount_current(&rsock->references) - 1);
    678 
    679 	if (isc_refcount_decrement(&rsock->references) == 1) {
    680 		isc___nmsocket_prep_destroy(rsock FLARG_PASS);
    681 	}
    682 }
    683 
    684 void
    685 isc_nmsocket_close(isc_nmsocket_t **sockp) {
    686 	REQUIRE(sockp != NULL);
    687 	REQUIRE(VALID_NMSOCK(*sockp));
    688 	REQUIRE((*sockp)->type == isc_nm_udplistener ||
    689 		(*sockp)->type == isc_nm_tcplistener ||
    690 		(*sockp)->type == isc_nm_streamdnslistener ||
    691 		(*sockp)->type == isc_nm_tlslistener ||
    692 		(*sockp)->type == isc_nm_httplistener ||
    693 		(*sockp)->type == isc_nm_proxystreamlistener ||
    694 		(*sockp)->type == isc_nm_proxyudplistener);
    695 
    696 	isc__nmsocket_detach(sockp);
    697 }
    698 
    699 void
    700 isc___nmsocket_init(isc_nmsocket_t *sock, isc__networker_t *worker,
    701 		    isc_nmsocket_type type, isc_sockaddr_t *iface,
    702 		    isc_nmsocket_t *parent FLARG) {
    703 	uint16_t family;
    704 
    705 	REQUIRE(sock != NULL);
    706 	REQUIRE(worker != NULL);
    707 
    708 	*sock = (isc_nmsocket_t){
    709 		.type = type,
    710 		.tid = worker->loop->tid,
    711 		.fd = -1,
    712 		.inactive_handles = ISC_LIST_INITIALIZER,
    713 		.result = ISC_R_UNSET,
    714 		.active_handles = ISC_LIST_INITIALIZER,
    715 		.active_handles_max = ISC_NETMGR_MAX_STREAM_CLIENTS_PER_CONN,
    716 		.active_link = ISC_LINK_INITIALIZER,
    717 		.active = true,
    718 	};
    719 
    720 	if (iface != NULL) {
    721 		family = iface->type.sa.sa_family;
    722 		sock->iface = *iface;
    723 	} else {
    724 		family = AF_UNSPEC;
    725 	}
    726 
    727 	if (parent) {
    728 		sock->parent = parent;
    729 	} else {
    730 		ISC_LIST_APPEND(worker->active_sockets, sock, active_link);
    731 	}
    732 
    733 #if ISC_NETMGR_TRACE
    734 	sock->backtrace_size = isc_backtrace(sock->backtrace, TRACE_SIZE);
    735 #endif
    736 
    737 	isc__networker_attach(worker, &sock->worker);
    738 	sock->uv_handle.handle.data = sock;
    739 
    740 	switch (type) {
    741 	case isc_nm_udpsocket:
    742 	case isc_nm_udplistener:
    743 		switch (family) {
    744 		case AF_INET:
    745 			sock->statsindex = udp4statsindex;
    746 			break;
    747 		case AF_INET6:
    748 			sock->statsindex = udp6statsindex;
    749 			break;
    750 		case AF_UNSPEC:
    751 			/*
    752 			 * Route sockets are AF_UNSPEC, and don't
    753 			 * have stats counters.
    754 			 */
    755 			break;
    756 		default:
    757 			UNREACHABLE();
    758 		}
    759 		break;
    760 	case isc_nm_tcpsocket:
    761 	case isc_nm_tcplistener:
    762 	case isc_nm_httpsocket:
    763 	case isc_nm_httplistener:
    764 		switch (family) {
    765 		case AF_INET:
    766 			sock->statsindex = tcp4statsindex;
    767 			break;
    768 		case AF_INET6:
    769 			sock->statsindex = tcp6statsindex;
    770 			break;
    771 		default:
    772 			UNREACHABLE();
    773 		}
    774 		break;
    775 	default:
    776 		break;
    777 	}
    778 
    779 	isc_refcount_init(&sock->references, 1);
    780 
    781 	memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
    782 
    783 	NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %" PRIuFAST32
    784 			 "\n",
    785 			 sock, isc_refcount_current(&sock->references));
    786 
    787 	sock->magic = NMSOCK_MAGIC;
    788 
    789 	isc__nm_incstats(sock, STATID_ACTIVE);
    790 }
    791 
    792 void
    793 isc__nmsocket_clearcb(isc_nmsocket_t *sock) {
    794 	REQUIRE(VALID_NMSOCK(sock));
    795 	REQUIRE(sock->tid == isc_tid());
    796 
    797 	sock->recv_cb = NULL;
    798 	sock->recv_cbarg = NULL;
    799 	sock->accept_cb = NULL;
    800 	sock->accept_cbarg = NULL;
    801 	sock->connect_cb = NULL;
    802 	sock->connect_cbarg = NULL;
    803 }
    804 
    805 void
    806 isc__nm_free_uvbuf(isc_nmsocket_t *sock, const uv_buf_t *buf) {
    807 	REQUIRE(VALID_NMSOCK(sock));
    808 
    809 	REQUIRE(buf->base == sock->worker->recvbuf);
    810 
    811 	sock->worker->recvbuf_inuse = false;
    812 }
    813 
    814 static isc_nmhandle_t *
    815 alloc_handle(isc_nmsocket_t *sock) {
    816 	isc_nmhandle_t *handle = isc_mem_get(sock->worker->mctx,
    817 					     sizeof(isc_nmhandle_t));
    818 
    819 	*handle = (isc_nmhandle_t){
    820 		.magic = NMHANDLE_MAGIC,
    821 		.active_link = ISC_LINK_INITIALIZER,
    822 		.inactive_link = ISC_LINK_INITIALIZER,
    823 	};
    824 	isc_refcount_init(&handle->references, 1);
    825 
    826 	return handle;
    827 }
    828 
    829 static isc_nmhandle_t *
    830 dequeue_handle(isc_nmsocket_t *sock) {
    831 #if !__SANITIZE_ADDRESS__ && !__SANITIZE_THREAD__
    832 	isc_nmhandle_t *handle = ISC_LIST_HEAD(sock->inactive_handles);
    833 	if (handle != NULL) {
    834 		ISC_LIST_DEQUEUE(sock->inactive_handles, handle, inactive_link);
    835 
    836 		sock->inactive_handles_cur--;
    837 
    838 		isc_refcount_init(&handle->references, 1);
    839 		INSIST(VALID_NMHANDLE(handle));
    840 		return handle;
    841 	}
    842 #else
    843 	INSIST(ISC_LIST_EMPTY(sock->inactive_handles));
    844 #endif /* !__SANITIZE_ADDRESS__ && !__SANITIZE_THREAD__ */
    845 	return NULL;
    846 }
    847 
    848 isc_nmhandle_t *
    849 isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t const *peer,
    850 		   isc_sockaddr_t const *local FLARG) {
    851 	REQUIRE(VALID_NMSOCK(sock));
    852 
    853 	isc_nmhandle_t *handle = dequeue_handle(sock);
    854 	if (handle == NULL) {
    855 		handle = alloc_handle(sock);
    856 	}
    857 
    858 	NETMGR_TRACE_LOG(
    859 		"isc__nmhandle_get():handle %p->references = %" PRIuFAST32 "\n",
    860 		handle, isc_refcount_current(&handle->references));
    861 
    862 	isc___nmsocket_attach(sock, &handle->sock FLARG_PASS);
    863 
    864 #if ISC_NETMGR_TRACE
    865 	handle->backtrace_size = isc_backtrace(handle->backtrace, TRACE_SIZE);
    866 #endif
    867 
    868 	if (peer != NULL) {
    869 		handle->peer = *peer;
    870 	} else {
    871 		handle->peer = sock->peer;
    872 	}
    873 
    874 	if (local != NULL) {
    875 		handle->local = *local;
    876 	} else {
    877 		handle->local = sock->iface;
    878 	}
    879 
    880 	ISC_LIST_APPEND(sock->active_handles, handle, active_link);
    881 	sock->active_handles_cur++;
    882 
    883 	switch (sock->type) {
    884 	case isc_nm_udpsocket:
    885 	case isc_nm_proxyudpsocket:
    886 		if (!sock->client) {
    887 			break;
    888 		}
    889 		FALLTHROUGH;
    890 	case isc_nm_tcpsocket:
    891 	case isc_nm_tlssocket:
    892 	case isc_nm_proxystreamsocket:
    893 		INSIST(sock->statichandle == NULL);
    894 
    895 		/*
    896 		 * statichandle must be assigned, not attached;
    897 		 * otherwise, if a handle was detached elsewhere
    898 		 * it could never reach 0 references, and the
    899 		 * handle and socket would never be freed.
    900 		 */
    901 		sock->statichandle = handle;
    902 		break;
    903 	default:
    904 		break;
    905 	}
    906 
    907 #if HAVE_LIBNGHTTP2
    908 	if (sock->type == isc_nm_httpsocket && sock->h2 != NULL &&
    909 	    sock->h2->session)
    910 	{
    911 		isc__nm_httpsession_attach(sock->h2->session,
    912 					   &handle->httpsession);
    913 	}
    914 #endif
    915 
    916 	return handle;
    917 }
    918 
    919 bool
    920 isc_nmhandle_is_stream(isc_nmhandle_t *handle) {
    921 	REQUIRE(VALID_NMHANDLE(handle));
    922 
    923 	return handle->sock->type == isc_nm_tcpsocket ||
    924 	       handle->sock->type == isc_nm_tlssocket ||
    925 	       handle->sock->type == isc_nm_httpsocket ||
    926 	       handle->sock->type == isc_nm_streamdnssocket ||
    927 	       handle->sock->type == isc_nm_proxystreamsocket;
    928 }
    929 
    930 static void
    931 nmhandle_free(isc_nmsocket_t *sock, isc_nmhandle_t *handle) {
    932 	handle->magic = 0;
    933 
    934 	if (handle->dofree != NULL) {
    935 		handle->dofree(handle->opaque);
    936 	}
    937 
    938 	isc_mem_put(sock->worker->mctx, handle, sizeof(*handle));
    939 }
    940 
    941 static void
    942 nmhandle__destroy(isc_nmhandle_t *handle) {
    943 	isc_nmsocket_t *sock = handle->sock;
    944 	handle->sock = NULL;
    945 
    946 #if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__)
    947 	nmhandle_free(sock, handle);
    948 #else
    949 	if (sock->active &&
    950 	    sock->inactive_handles_cur < sock->inactive_handles_max)
    951 	{
    952 		sock->inactive_handles_cur++;
    953 		ISC_LIST_APPEND(sock->inactive_handles, handle, inactive_link);
    954 	} else {
    955 		nmhandle_free(sock, handle);
    956 	}
    957 #endif
    958 
    959 	isc__nmsocket_detach(&sock);
    960 }
    961 
    962 static void
    963 isc__nm_closehandle_job(void *arg) {
    964 	isc_nmhandle_t *handle = arg;
    965 	isc_nmsocket_t *sock = handle->sock;
    966 
    967 	sock->closehandle_cb(sock);
    968 
    969 	nmhandle__destroy(handle);
    970 }
    971 
    972 static void
    973 nmhandle_destroy(isc_nmhandle_t *handle) {
    974 	isc_nmsocket_t *sock = handle->sock;
    975 
    976 	if (handle->doreset != NULL) {
    977 		handle->doreset(handle->opaque);
    978 	}
    979 
    980 #if HAVE_LIBNGHTTP2
    981 	if (sock->type == isc_nm_httpsocket && handle->httpsession != NULL) {
    982 		isc__nm_httpsession_detach(&handle->httpsession);
    983 	}
    984 #endif
    985 
    986 	if (handle == sock->statichandle) {
    987 		/* statichandle is assigned, not attached. */
    988 		sock->statichandle = NULL;
    989 	}
    990 
    991 	if (handle->proxy_udphandle != NULL) {
    992 		isc_nmhandle_detach(&handle->proxy_udphandle);
    993 	}
    994 
    995 	ISC_LIST_UNLINK(sock->active_handles, handle, active_link);
    996 	INSIST(sock->active_handles_cur > 0);
    997 	sock->active_handles_cur--;
    998 
    999 	if (sock->closehandle_cb == NULL) {
   1000 		nmhandle__destroy(handle);
   1001 		return;
   1002 	}
   1003 
   1004 	/*
   1005 	 * If the socket has a callback configured for that (e.g.,
   1006 	 * to perform cleanup after request processing), call it
   1007 	 * now asynchronously.
   1008 	 */
   1009 	isc_job_run(sock->worker->loop, &handle->job, isc__nm_closehandle_job,
   1010 		    handle);
   1011 }
   1012 
   1013 #if ISC_NETMGR_TRACE
   1014 ISC_REFCOUNT_TRACE_IMPL(isc_nmhandle, nmhandle_destroy)
   1015 #else
   1016 ISC_REFCOUNT_IMPL(isc_nmhandle, nmhandle_destroy);
   1017 #endif
   1018 
   1019 void *
   1020 isc_nmhandle_getdata(isc_nmhandle_t *handle) {
   1021 	REQUIRE(VALID_NMHANDLE(handle));
   1022 
   1023 	return handle->opaque;
   1024 }
   1025 
   1026 void
   1027 isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
   1028 		     isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree) {
   1029 	REQUIRE(VALID_NMHANDLE(handle));
   1030 
   1031 	handle->opaque = arg;
   1032 	handle->doreset = doreset;
   1033 	handle->dofree = dofree;
   1034 }
   1035 
   1036 void
   1037 isc__nm_failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
   1038 		       isc_result_t eresult, bool async) {
   1039 	REQUIRE(VALID_NMSOCK(sock));
   1040 	REQUIRE(VALID_UVREQ(req));
   1041 
   1042 	if (req->cb.send != NULL) {
   1043 		isc__nm_sendcb(sock, req, eresult, async);
   1044 	} else {
   1045 		isc__nm_uvreq_put(&req);
   1046 	}
   1047 }
   1048 
   1049 void
   1050 isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
   1051 			  isc_result_t eresult, bool async) {
   1052 	REQUIRE(VALID_NMSOCK(sock));
   1053 	REQUIRE(VALID_UVREQ(req));
   1054 	REQUIRE(sock->tid == isc_tid());
   1055 	REQUIRE(req->cb.connect != NULL);
   1056 	REQUIRE(sock->connecting);
   1057 
   1058 	sock->connecting = false;
   1059 
   1060 	isc__nm_incstats(sock, STATID_CONNECTFAIL);
   1061 
   1062 	isc__nmsocket_timer_stop(sock);
   1063 	uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
   1064 
   1065 	isc__nmsocket_clearcb(sock);
   1066 	isc__nm_connectcb(sock, req, eresult, async);
   1067 
   1068 	isc__nmsocket_prep_destroy(sock);
   1069 }
   1070 
   1071 void
   1072 isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async) {
   1073 	REQUIRE(VALID_NMSOCK(sock));
   1074 	UNUSED(async);
   1075 	switch (sock->type) {
   1076 	case isc_nm_udpsocket:
   1077 		isc__nm_udp_failed_read_cb(sock, result, async);
   1078 		return;
   1079 	case isc_nm_tcpsocket:
   1080 		isc__nm_tcp_failed_read_cb(sock, result, async);
   1081 		return;
   1082 	case isc_nm_tlssocket:
   1083 		isc__nm_tls_failed_read_cb(sock, result, async);
   1084 		return;
   1085 	case isc_nm_streamdnssocket:
   1086 		isc__nm_streamdns_failed_read_cb(sock, result, async);
   1087 		return;
   1088 	case isc_nm_proxystreamsocket:
   1089 		isc__nm_proxystream_failed_read_cb(sock, result, async);
   1090 		return;
   1091 	case isc_nm_proxyudpsocket:
   1092 		isc__nm_proxyudp_failed_read_cb(sock, result, async);
   1093 		return;
   1094 	default:
   1095 		UNREACHABLE();
   1096 	}
   1097 }
   1098 
   1099 void
   1100 isc__nmsocket_connecttimeout_cb(uv_timer_t *timer) {
   1101 	uv_connect_t *uvreq = uv_handle_get_data((uv_handle_t *)timer);
   1102 	isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)uvreq->handle);
   1103 	isc__nm_uvreq_t *req = uv_handle_get_data((uv_handle_t *)uvreq);
   1104 
   1105 	REQUIRE(VALID_NMSOCK(sock));
   1106 	REQUIRE(sock->tid == isc_tid());
   1107 	REQUIRE(VALID_UVREQ(req));
   1108 	REQUIRE(VALID_NMHANDLE(req->handle));
   1109 	REQUIRE(sock->connecting);
   1110 
   1111 	isc__nmsocket_timer_stop(sock);
   1112 
   1113 	/*
   1114 	 * Mark the connection as timed out and shutdown the socket.
   1115 	 */
   1116 	REQUIRE(!sock->timedout);
   1117 	sock->timedout = true;
   1118 	isc__nmsocket_shutdown(sock);
   1119 }
   1120 
   1121 void
   1122 isc__nm_accept_connection_log(isc_nmsocket_t *sock, isc_result_t result,
   1123 			      bool can_log_quota) {
   1124 	int level;
   1125 
   1126 	switch (result) {
   1127 	case ISC_R_SUCCESS:
   1128 	case ISC_R_NOCONN:
   1129 		return;
   1130 	case ISC_R_QUOTA:
   1131 	case ISC_R_SOFTQUOTA:
   1132 		if (!can_log_quota) {
   1133 			return;
   1134 		}
   1135 		level = ISC_LOG_INFO;
   1136 		break;
   1137 	case ISC_R_NOTCONNECTED:
   1138 		level = ISC_LOG_INFO;
   1139 		break;
   1140 	default:
   1141 		level = ISC_LOG_ERROR;
   1142 	}
   1143 
   1144 	isc__nmsocket_log(sock, level, "Accepting TCP connection failed: %s",
   1145 			  isc_result_totext(result));
   1146 }
   1147 
   1148 void
   1149 isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult) {
   1150 	isc__nm_uvreq_t *req = data;
   1151 	isc_nmsocket_t *sock = NULL;
   1152 
   1153 	REQUIRE(eresult == ISC_R_TIMEDOUT);
   1154 	REQUIRE(VALID_UVREQ(req));
   1155 	REQUIRE(VALID_NMSOCK(req->sock));
   1156 
   1157 	sock = req->sock;
   1158 
   1159 	isc__nm_start_reading(sock);
   1160 	isc__nmsocket_reset(sock);
   1161 }
   1162 
   1163 void
   1164 isc__nmsocket_readtimeout_cb(uv_timer_t *timer) {
   1165 	isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
   1166 
   1167 	REQUIRE(VALID_NMSOCK(sock));
   1168 	REQUIRE(sock->tid == isc_tid());
   1169 
   1170 	if (sock->client) {
   1171 		uv_timer_stop(timer);
   1172 
   1173 		if (sock->recv_cb != NULL) {
   1174 			isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL);
   1175 			isc__nm_readcb(sock, req, ISC_R_TIMEDOUT, false);
   1176 		}
   1177 
   1178 		if (!isc__nmsocket_timer_running(sock)) {
   1179 			isc__nmsocket_clearcb(sock);
   1180 			isc__nm_failed_read_cb(sock, ISC_R_TIMEDOUT, false);
   1181 		}
   1182 	} else {
   1183 		isc__nm_failed_read_cb(sock, ISC_R_TIMEDOUT, false);
   1184 	}
   1185 }
   1186 
   1187 void
   1188 isc__nmsocket_timer_restart(isc_nmsocket_t *sock) {
   1189 	REQUIRE(VALID_NMSOCK(sock));
   1190 
   1191 	switch (sock->type) {
   1192 	case isc_nm_tlssocket:
   1193 		isc__nmsocket_tls_timer_restart(sock);
   1194 		return;
   1195 	case isc_nm_streamdnssocket:
   1196 		isc__nmsocket_streamdns_timer_restart(sock);
   1197 		return;
   1198 	case isc_nm_proxystreamsocket:
   1199 		isc__nmsocket_proxystream_timer_restart(sock);
   1200 		return;
   1201 	case isc_nm_proxyudpsocket:
   1202 		isc__nmsocket_proxyudp_timer_restart(sock);
   1203 		return;
   1204 	default:
   1205 		break;
   1206 	}
   1207 
   1208 	if (uv_is_closing((uv_handle_t *)&sock->read_timer)) {
   1209 		return;
   1210 	}
   1211 
   1212 	if (sock->connecting) {
   1213 		int r;
   1214 
   1215 		if (sock->connect_timeout == 0) {
   1216 			return;
   1217 		}
   1218 
   1219 		r = uv_timer_start(&sock->read_timer,
   1220 				   isc__nmsocket_connecttimeout_cb,
   1221 				   sock->connect_timeout + 10, 0);
   1222 		UV_RUNTIME_CHECK(uv_timer_start, r);
   1223 
   1224 	} else {
   1225 		int r;
   1226 
   1227 		if (sock->read_timeout == 0) {
   1228 			return;
   1229 		}
   1230 
   1231 		r = uv_timer_start(&sock->read_timer,
   1232 				   isc__nmsocket_readtimeout_cb,
   1233 				   sock->read_timeout, 0);
   1234 		UV_RUNTIME_CHECK(uv_timer_start, r);
   1235 	}
   1236 }
   1237 
   1238 bool
   1239 isc__nmsocket_timer_running(isc_nmsocket_t *sock) {
   1240 	REQUIRE(VALID_NMSOCK(sock));
   1241 
   1242 	switch (sock->type) {
   1243 	case isc_nm_tlssocket:
   1244 		return isc__nmsocket_tls_timer_running(sock);
   1245 	case isc_nm_streamdnssocket:
   1246 		return isc__nmsocket_streamdns_timer_running(sock);
   1247 	case isc_nm_proxystreamsocket:
   1248 		return isc__nmsocket_proxystream_timer_running(sock);
   1249 	case isc_nm_proxyudpsocket:
   1250 		return isc__nmsocket_proxyudp_timer_running(sock);
   1251 	default:
   1252 		break;
   1253 	}
   1254 
   1255 	return uv_is_active((uv_handle_t *)&sock->read_timer);
   1256 }
   1257 
   1258 void
   1259 isc__nmsocket_timer_start(isc_nmsocket_t *sock) {
   1260 	REQUIRE(VALID_NMSOCK(sock));
   1261 
   1262 	if (isc__nmsocket_timer_running(sock)) {
   1263 		return;
   1264 	}
   1265 
   1266 	isc__nmsocket_timer_restart(sock);
   1267 }
   1268 
   1269 void
   1270 isc__nmsocket_timer_stop(isc_nmsocket_t *sock) {
   1271 	int r;
   1272 
   1273 	REQUIRE(VALID_NMSOCK(sock));
   1274 
   1275 	switch (sock->type) {
   1276 	case isc_nm_tlssocket:
   1277 		isc__nmsocket_tls_timer_stop(sock);
   1278 		return;
   1279 	case isc_nm_streamdnssocket:
   1280 		isc__nmsocket_streamdns_timer_stop(sock);
   1281 		return;
   1282 	case isc_nm_proxystreamsocket:
   1283 		isc__nmsocket_proxystream_timer_stop(sock);
   1284 		return;
   1285 	case isc_nm_proxyudpsocket:
   1286 		isc__nmsocket_proxyudp_timer_stop(sock);
   1287 		return;
   1288 	default:
   1289 		break;
   1290 	}
   1291 
   1292 	/* uv_timer_stop() is idempotent, no need to check if running */
   1293 
   1294 	r = uv_timer_stop(&sock->read_timer);
   1295 	UV_RUNTIME_CHECK(uv_timer_stop, r);
   1296 }
   1297 
   1298 isc__nm_uvreq_t *
   1299 isc___nm_get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr FLARG) {
   1300 	isc__nm_uvreq_t *req = NULL;
   1301 
   1302 	req = isc__nm_uvreq_get(sock);
   1303 	req->cb.recv = sock->recv_cb;
   1304 	req->cbarg = sock->recv_cbarg;
   1305 
   1306 	switch (sock->type) {
   1307 	case isc_nm_tcpsocket:
   1308 	case isc_nm_tlssocket:
   1309 	case isc_nm_proxystreamsocket:
   1310 #if ISC_NETMGR_TRACE
   1311 		isc_nmhandle__attach(sock->statichandle,
   1312 				     &req->handle FLARG_PASS);
   1313 #else
   1314 		isc_nmhandle_attach(sock->statichandle, &req->handle);
   1315 #endif
   1316 		break;
   1317 	case isc_nm_streamdnssocket:
   1318 #if ISC_NETMGR_TRACE
   1319 		isc_nmhandle__attach(sock->recv_handle,
   1320 				     &req->handle FLARG_PASS);
   1321 #else
   1322 		isc_nmhandle_attach(sock->recv_handle, &req->handle);
   1323 #endif
   1324 		break;
   1325 	default:
   1326 		if (sock->client && sock->statichandle != NULL) {
   1327 #if ISC_NETMGR_TRACE
   1328 			isc_nmhandle__attach(sock->statichandle,
   1329 					     &req->handle FLARG_PASS);
   1330 #else
   1331 			isc_nmhandle_attach(sock->statichandle, &req->handle);
   1332 #endif
   1333 		} else {
   1334 			req->handle = isc___nmhandle_get(sock, sockaddr,
   1335 							 NULL FLARG_PASS);
   1336 		}
   1337 		break;
   1338 	}
   1339 
   1340 	return req;
   1341 }
   1342 
   1343 /*%<
   1344  * Allocator callback for read operations.
   1345  *
   1346  * Note this doesn't actually allocate anything, it just assigns the
   1347  * worker's receive buffer to a socket, and marks it as "in use".
   1348  */
   1349 void
   1350 isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
   1351 	isc_nmsocket_t *sock = uv_handle_get_data(handle);
   1352 	isc__networker_t *worker = NULL;
   1353 
   1354 	REQUIRE(VALID_NMSOCK(sock));
   1355 	/*
   1356 	 * The size provided by libuv is only suggested size, and it always
   1357 	 * defaults to 64 * 1024 in the current versions of libuv (see
   1358 	 * src/unix/udp.c and src/unix/stream.c).
   1359 	 */
   1360 	UNUSED(size);
   1361 
   1362 	worker = sock->worker;
   1363 	INSIST(!worker->recvbuf_inuse);
   1364 	INSIST(worker->recvbuf != NULL);
   1365 
   1366 	switch (sock->type) {
   1367 	case isc_nm_udpsocket:
   1368 		buf->len = ISC_NETMGR_UDP_RECVBUF_SIZE;
   1369 		break;
   1370 	case isc_nm_tcpsocket:
   1371 		buf->len = ISC_NETMGR_TCP_RECVBUF_SIZE;
   1372 		break;
   1373 	default:
   1374 		UNREACHABLE();
   1375 	}
   1376 
   1377 	REQUIRE(buf->len <= ISC_NETMGR_RECVBUF_SIZE);
   1378 	buf->base = worker->recvbuf;
   1379 
   1380 	worker->recvbuf_inuse = true;
   1381 }
   1382 
   1383 isc_result_t
   1384 isc__nm_start_reading(isc_nmsocket_t *sock) {
   1385 	isc_result_t result = ISC_R_SUCCESS;
   1386 	int r;
   1387 
   1388 	if (uv_is_active(&sock->uv_handle.handle)) {
   1389 		return ISC_R_SUCCESS;
   1390 	}
   1391 
   1392 	switch (sock->type) {
   1393 	case isc_nm_udpsocket:
   1394 		r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb,
   1395 				      isc__nm_udp_read_cb);
   1396 		break;
   1397 	case isc_nm_tcpsocket:
   1398 		r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
   1399 				  isc__nm_tcp_read_cb);
   1400 		break;
   1401 	default:
   1402 		UNREACHABLE();
   1403 	}
   1404 	if (r != 0) {
   1405 		result = isc_uverr2result(r);
   1406 	}
   1407 
   1408 	return result;
   1409 }
   1410 
   1411 void
   1412 isc__nm_stop_reading(isc_nmsocket_t *sock) {
   1413 	int r;
   1414 
   1415 	if (!uv_is_active(&sock->uv_handle.handle)) {
   1416 		return;
   1417 	}
   1418 
   1419 	switch (sock->type) {
   1420 	case isc_nm_udpsocket:
   1421 		r = uv_udp_recv_stop(&sock->uv_handle.udp);
   1422 		UV_RUNTIME_CHECK(uv_udp_recv_stop, r);
   1423 		break;
   1424 	case isc_nm_tcpsocket:
   1425 		r = uv_read_stop(&sock->uv_handle.stream);
   1426 		UV_RUNTIME_CHECK(uv_read_stop, r);
   1427 		break;
   1428 	default:
   1429 		UNREACHABLE();
   1430 	}
   1431 }
   1432 
   1433 bool
   1434 isc__nm_closing(isc__networker_t *worker) {
   1435 	return worker->shuttingdown;
   1436 }
   1437 
   1438 bool
   1439 isc__nmsocket_closing(isc_nmsocket_t *sock) {
   1440 	return !sock->active || sock->closing ||
   1441 	       isc__nm_closing(sock->worker) ||
   1442 	       (sock->server != NULL && !isc__nmsocket_active(sock->server));
   1443 }
   1444 
   1445 void
   1446 isc_nmhandle_cleartimeout(isc_nmhandle_t *handle) {
   1447 	REQUIRE(VALID_NMHANDLE(handle));
   1448 	REQUIRE(VALID_NMSOCK(handle->sock));
   1449 
   1450 	switch (handle->sock->type) {
   1451 #if HAVE_LIBNGHTTP2
   1452 	case isc_nm_httpsocket:
   1453 		isc__nm_http_cleartimeout(handle);
   1454 		return;
   1455 #endif
   1456 	case isc_nm_tlssocket:
   1457 		isc__nm_tls_cleartimeout(handle);
   1458 		return;
   1459 	case isc_nm_streamdnssocket:
   1460 		isc__nmhandle_streamdns_cleartimeout(handle);
   1461 		return;
   1462 	case isc_nm_proxystreamsocket:
   1463 		isc__nmhandle_proxystream_cleartimeout(handle);
   1464 		return;
   1465 	case isc_nm_proxyudpsocket:
   1466 		isc__nmhandle_proxyudp_cleartimeout(handle);
   1467 		return;
   1468 	default:
   1469 		handle->sock->read_timeout = 0;
   1470 
   1471 		if (uv_is_active((uv_handle_t *)&handle->sock->read_timer)) {
   1472 			isc__nmsocket_timer_stop(handle->sock);
   1473 		}
   1474 	}
   1475 }
   1476 
   1477 void
   1478 isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
   1479 	REQUIRE(VALID_NMHANDLE(handle));
   1480 	REQUIRE(VALID_NMSOCK(handle->sock));
   1481 
   1482 	switch (handle->sock->type) {
   1483 #if HAVE_LIBNGHTTP2
   1484 	case isc_nm_httpsocket:
   1485 		isc__nm_http_settimeout(handle, timeout);
   1486 		return;
   1487 #endif
   1488 	case isc_nm_tlssocket:
   1489 		isc__nm_tls_settimeout(handle, timeout);
   1490 		return;
   1491 	case isc_nm_streamdnssocket:
   1492 		isc__nmhandle_streamdns_settimeout(handle, timeout);
   1493 		return;
   1494 	case isc_nm_proxystreamsocket:
   1495 		isc__nmhandle_proxystream_settimeout(handle, timeout);
   1496 		return;
   1497 	case isc_nm_proxyudpsocket:
   1498 		isc__nmhandle_proxyudp_settimeout(handle, timeout);
   1499 		return;
   1500 	default:
   1501 		handle->sock->read_timeout = timeout;
   1502 		isc__nmsocket_timer_restart(handle->sock);
   1503 	}
   1504 }
   1505 
   1506 void
   1507 isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value) {
   1508 	isc_nmsocket_t *sock = NULL;
   1509 	isc_nm_t *netmgr = NULL;
   1510 
   1511 	REQUIRE(VALID_NMHANDLE(handle));
   1512 	REQUIRE(VALID_NMSOCK(handle->sock));
   1513 
   1514 	sock = handle->sock;
   1515 	netmgr = sock->worker->netmgr;
   1516 
   1517 	REQUIRE(sock->tid == isc_tid());
   1518 
   1519 	switch (sock->type) {
   1520 	case isc_nm_tcpsocket:
   1521 		sock->keepalive = value;
   1522 		sock->read_timeout =
   1523 			value ? atomic_load_relaxed(&netmgr->keepalive)
   1524 			      : atomic_load_relaxed(&netmgr->idle);
   1525 		sock->write_timeout =
   1526 			value ? atomic_load_relaxed(&netmgr->keepalive)
   1527 			      : atomic_load_relaxed(&netmgr->idle);
   1528 		break;
   1529 	case isc_nm_streamdnssocket:
   1530 		isc__nmhandle_streamdns_keepalive(handle, value);
   1531 		break;
   1532 	case isc_nm_tlssocket:
   1533 		isc__nmhandle_tls_keepalive(handle, value);
   1534 		break;
   1535 #if HAVE_LIBNGHTTP2
   1536 	case isc_nm_httpsocket:
   1537 		isc__nmhandle_http_keepalive(handle, value);
   1538 		break;
   1539 #endif /* HAVE_LIBNGHTTP2 */
   1540 	case isc_nm_proxystreamsocket:
   1541 		isc__nmhandle_proxystream_keepalive(handle, value);
   1542 		break;
   1543 	default:
   1544 		/*
   1545 		 * For any other protocol, this is a no-op.
   1546 		 */
   1547 		return;
   1548 	}
   1549 }
   1550 
   1551 bool
   1552 isc_nmhandle_timer_running(isc_nmhandle_t *handle) {
   1553 	REQUIRE(VALID_NMHANDLE(handle));
   1554 	REQUIRE(VALID_NMSOCK(handle->sock));
   1555 
   1556 	return isc__nmsocket_timer_running(handle->sock);
   1557 }
   1558 
   1559 isc_sockaddr_t
   1560 isc_nmhandle_peeraddr(isc_nmhandle_t *handle) {
   1561 	REQUIRE(VALID_NMHANDLE(handle));
   1562 
   1563 	return handle->peer;
   1564 }
   1565 
   1566 isc_sockaddr_t
   1567 isc_nmhandle_localaddr(isc_nmhandle_t *handle) {
   1568 	REQUIRE(VALID_NMHANDLE(handle));
   1569 
   1570 	return handle->local;
   1571 }
   1572 
   1573 isc_nm_t *
   1574 isc_nmhandle_netmgr(isc_nmhandle_t *handle) {
   1575 	REQUIRE(VALID_NMHANDLE(handle));
   1576 	REQUIRE(VALID_NMSOCK(handle->sock));
   1577 
   1578 	return handle->sock->worker->netmgr;
   1579 }
   1580 
   1581 isc__nm_uvreq_t *
   1582 isc___nm_uvreq_get(isc_nmsocket_t *sock FLARG) {
   1583 	REQUIRE(VALID_NMSOCK(sock));
   1584 	REQUIRE(sock->tid == isc_tid());
   1585 
   1586 	isc__networker_t *worker = sock->worker;
   1587 
   1588 	isc__nm_uvreq_t *req = isc_mempool_get(worker->uvreq_pool);
   1589 	*req = (isc__nm_uvreq_t){
   1590 		.connect_tries = 3,
   1591 		.link = ISC_LINK_INITIALIZER,
   1592 		.active_link = ISC_LINK_INITIALIZER,
   1593 		.magic = UVREQ_MAGIC,
   1594 	};
   1595 	uv_handle_set_data(&req->uv_req.handle, req);
   1596 
   1597 	isc___nmsocket_attach(sock, &req->sock FLARG_PASS);
   1598 
   1599 	ISC_LIST_APPEND(sock->active_uvreqs, req, active_link);
   1600 
   1601 	return req;
   1602 }
   1603 
   1604 void
   1605 isc___nm_uvreq_put(isc__nm_uvreq_t **reqp FLARG) {
   1606 	REQUIRE(reqp != NULL && VALID_UVREQ(*reqp));
   1607 
   1608 	isc__nm_uvreq_t *req = *reqp;
   1609 	isc_nmhandle_t *handle = req->handle;
   1610 	isc_nmsocket_t *sock = req->sock;
   1611 
   1612 	*reqp = NULL;
   1613 	req->handle = NULL;
   1614 
   1615 	REQUIRE(VALID_UVREQ(req));
   1616 
   1617 	ISC_LIST_UNLINK(sock->active_uvreqs, req, active_link);
   1618 
   1619 	if (handle != NULL) {
   1620 #if ISC_NETMGR_TRACE
   1621 		isc_nmhandle__detach(&handle, func, file, line);
   1622 #else
   1623 		isc_nmhandle_detach(&handle);
   1624 #endif
   1625 	}
   1626 
   1627 	isc_mempool_put(sock->worker->uvreq_pool, req);
   1628 
   1629 	isc___nmsocket_detach(&sock FLARG_PASS);
   1630 }
   1631 
   1632 void
   1633 isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
   1634 	    void *cbarg) {
   1635 	REQUIRE(VALID_NMHANDLE(handle));
   1636 
   1637 	switch (handle->sock->type) {
   1638 	case isc_nm_udpsocket:
   1639 	case isc_nm_udplistener:
   1640 		isc__nm_udp_send(handle, region, cb, cbarg);
   1641 		break;
   1642 	case isc_nm_tcpsocket:
   1643 		isc__nm_tcp_send(handle, region, cb, cbarg);
   1644 		break;
   1645 	case isc_nm_streamdnssocket:
   1646 		isc__nm_streamdns_send(handle, region, cb, cbarg);
   1647 		break;
   1648 	case isc_nm_tlssocket:
   1649 		isc__nm_tls_send(handle, region, cb, cbarg);
   1650 		break;
   1651 #if HAVE_LIBNGHTTP2
   1652 	case isc_nm_httpsocket:
   1653 		isc__nm_http_send(handle, region, cb, cbarg);
   1654 		break;
   1655 #endif
   1656 	case isc_nm_proxystreamsocket:
   1657 		isc__nm_proxystream_send(handle, region, cb, cbarg);
   1658 		break;
   1659 	case isc_nm_proxyudpsocket:
   1660 		isc__nm_proxyudp_send(handle, region, cb, cbarg);
   1661 		break;
   1662 	default:
   1663 		UNREACHABLE();
   1664 	}
   1665 }
   1666 
   1667 void
   1668 isc__nm_senddns(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
   1669 		void *cbarg) {
   1670 	REQUIRE(VALID_NMHANDLE(handle));
   1671 
   1672 	switch (handle->sock->type) {
   1673 	case isc_nm_tcpsocket:
   1674 		isc__nm_tcp_senddns(handle, region, cb, cbarg);
   1675 		break;
   1676 	case isc_nm_tlssocket:
   1677 		isc__nm_tls_senddns(handle, region, cb, cbarg);
   1678 		break;
   1679 	case isc_nm_proxystreamsocket:
   1680 		isc__nm_proxystream_senddns(handle, region, cb, cbarg);
   1681 		break;
   1682 	default:
   1683 		UNREACHABLE();
   1684 	}
   1685 }
   1686 
   1687 void
   1688 isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
   1689 	REQUIRE(VALID_NMHANDLE(handle));
   1690 
   1691 	switch (handle->sock->type) {
   1692 	case isc_nm_udpsocket:
   1693 		isc__nm_udp_read(handle, cb, cbarg);
   1694 		break;
   1695 	case isc_nm_tcpsocket:
   1696 		isc__nm_tcp_read(handle, cb, cbarg);
   1697 		break;
   1698 	case isc_nm_streamdnssocket:
   1699 		isc__nm_streamdns_read(handle, cb, cbarg);
   1700 		break;
   1701 	case isc_nm_tlssocket:
   1702 		isc__nm_tls_read(handle, cb, cbarg);
   1703 		break;
   1704 #if HAVE_LIBNGHTTP2
   1705 	case isc_nm_httpsocket:
   1706 		isc__nm_http_read(handle, cb, cbarg);
   1707 		break;
   1708 #endif
   1709 	case isc_nm_proxystreamsocket:
   1710 		isc__nm_proxystream_read(handle, cb, cbarg);
   1711 		break;
   1712 	case isc_nm_proxyudpsocket:
   1713 		isc__nm_proxyudp_read(handle, cb, cbarg);
   1714 		break;
   1715 	default:
   1716 		UNREACHABLE();
   1717 	}
   1718 }
   1719 
   1720 static void
   1721 cancelread_cb(void *arg) {
   1722 	isc_nmhandle_t *handle = arg;
   1723 
   1724 	REQUIRE(VALID_NMHANDLE(handle));
   1725 	REQUIRE(VALID_NMSOCK(handle->sock));
   1726 	REQUIRE(handle->sock->tid == isc_tid());
   1727 
   1728 	REQUIRE(handle->sock->tid == isc_tid());
   1729 
   1730 	switch (handle->sock->type) {
   1731 	case isc_nm_udpsocket:
   1732 	case isc_nm_proxyudpsocket:
   1733 	case isc_nm_streamdnssocket:
   1734 	case isc_nm_httpsocket:
   1735 		isc__nm_failed_read_cb(handle->sock, ISC_R_CANCELED, false);
   1736 		break;
   1737 	default:
   1738 		UNREACHABLE();
   1739 	}
   1740 
   1741 	isc_nmhandle_detach(&handle);
   1742 }
   1743 
   1744 void
   1745 isc_nm_cancelread(isc_nmhandle_t *handle) {
   1746 	REQUIRE(VALID_NMHANDLE(handle));
   1747 	REQUIRE(VALID_NMSOCK(handle->sock));
   1748 
   1749 	/* Running this directly could cause a dead-lock */
   1750 	isc_nmhandle_ref(handle);
   1751 	isc_async_run(handle->sock->worker->loop, cancelread_cb, handle);
   1752 }
   1753 
   1754 void
   1755 isc_nm_read_stop(isc_nmhandle_t *handle) {
   1756 	REQUIRE(VALID_NMHANDLE(handle));
   1757 
   1758 	isc_nmsocket_t *sock = handle->sock;
   1759 
   1760 	switch (sock->type) {
   1761 	case isc_nm_tcpsocket:
   1762 		isc__nm_tcp_read_stop(handle);
   1763 		break;
   1764 	case isc_nm_tlssocket:
   1765 		isc__nm_tls_read_stop(handle);
   1766 		break;
   1767 	case isc_nm_proxystreamsocket:
   1768 		isc__nm_proxystream_read_stop(handle);
   1769 		break;
   1770 	default:
   1771 		UNREACHABLE();
   1772 	}
   1773 }
   1774 
   1775 void
   1776 isc_nmhandle_close(isc_nmhandle_t *handle) {
   1777 	REQUIRE(VALID_NMHANDLE(handle));
   1778 	REQUIRE(VALID_NMSOCK(handle->sock));
   1779 
   1780 	isc__nmsocket_clearcb(handle->sock);
   1781 	isc__nmsocket_prep_destroy(handle->sock);
   1782 }
   1783 
   1784 void
   1785 isc_nm_stoplistening(isc_nmsocket_t *sock) {
   1786 	REQUIRE(VALID_NMSOCK(sock));
   1787 
   1788 	switch (sock->type) {
   1789 	case isc_nm_udplistener:
   1790 		isc__nm_udp_stoplistening(sock);
   1791 		break;
   1792 	case isc_nm_tcplistener:
   1793 		isc__nm_tcp_stoplistening(sock);
   1794 		break;
   1795 	case isc_nm_streamdnslistener:
   1796 		isc__nm_streamdns_stoplistening(sock);
   1797 		break;
   1798 	case isc_nm_tlslistener:
   1799 		isc__nm_tls_stoplistening(sock);
   1800 		break;
   1801 #if HAVE_LIBNGHTTP2
   1802 	case isc_nm_httplistener:
   1803 		isc__nm_http_stoplistening(sock);
   1804 		break;
   1805 #endif
   1806 	case isc_nm_proxystreamlistener:
   1807 		isc__nm_proxystream_stoplistening(sock);
   1808 		break;
   1809 	case isc_nm_proxyudplistener:
   1810 		isc__nm_proxyudp_stoplistening(sock);
   1811 		break;
   1812 	default:
   1813 		UNREACHABLE();
   1814 	}
   1815 }
   1816 
   1817 void
   1818 isc__nmsocket_stop(isc_nmsocket_t *listener) {
   1819 	REQUIRE(VALID_NMSOCK(listener));
   1820 	REQUIRE(listener->tid == isc_tid());
   1821 	REQUIRE(listener->tid == 0);
   1822 	REQUIRE(listener->type == isc_nm_httplistener ||
   1823 		listener->type == isc_nm_tlslistener ||
   1824 		listener->type == isc_nm_streamdnslistener ||
   1825 		listener->type == isc_nm_proxystreamlistener ||
   1826 		listener->type == isc_nm_proxyudplistener);
   1827 	REQUIRE(!listener->closing);
   1828 
   1829 	listener->closing = true;
   1830 
   1831 	REQUIRE(listener->outer != NULL);
   1832 	isc_nm_stoplistening(listener->outer);
   1833 
   1834 	listener->accept_cb = NULL;
   1835 	listener->accept_cbarg = NULL;
   1836 	listener->recv_cb = NULL;
   1837 	listener->recv_cbarg = NULL;
   1838 
   1839 	isc__nmsocket_detach(&listener->outer);
   1840 
   1841 	listener->closed = true;
   1842 }
   1843 
   1844 void
   1845 isc__nmsocket_barrier_init(isc_nmsocket_t *listener) {
   1846 	REQUIRE(listener->nchildren > 0);
   1847 	isc_barrier_init(&listener->listen_barrier, listener->nchildren);
   1848 	isc_barrier_init(&listener->stop_barrier, listener->nchildren);
   1849 	listener->barriers_initialised = true;
   1850 }
   1851 
   1852 static void
   1853 isc___nm_connectcb(void *arg) {
   1854 	isc__nm_uvreq_t *uvreq = arg;
   1855 
   1856 	uvreq->cb.connect(uvreq->handle, uvreq->result, uvreq->cbarg);
   1857 	isc__nm_uvreq_put(&uvreq);
   1858 }
   1859 
   1860 void
   1861 isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
   1862 		  isc_result_t eresult, bool async) {
   1863 	REQUIRE(VALID_NMSOCK(sock));
   1864 	REQUIRE(VALID_UVREQ(uvreq));
   1865 	REQUIRE(VALID_NMHANDLE(uvreq->handle));
   1866 	REQUIRE(uvreq->cb.connect != NULL);
   1867 
   1868 	uvreq->result = eresult;
   1869 
   1870 	if (!async) {
   1871 		isc___nm_connectcb(uvreq);
   1872 		return;
   1873 	}
   1874 
   1875 	isc_job_run(sock->worker->loop, &uvreq->job, isc___nm_connectcb, uvreq);
   1876 }
   1877 
   1878 static void
   1879 isc___nm_readcb(void *arg) {
   1880 	isc__nm_uvreq_t *uvreq = arg;
   1881 	isc_region_t region;
   1882 
   1883 	region.base = (unsigned char *)uvreq->uvbuf.base;
   1884 	region.length = uvreq->uvbuf.len;
   1885 	uvreq->cb.recv(uvreq->handle, uvreq->result, &region, uvreq->cbarg);
   1886 
   1887 	isc__nm_uvreq_put(&uvreq);
   1888 }
   1889 
   1890 void
   1891 isc__nm_readcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
   1892 	       isc_result_t eresult, bool async) {
   1893 	REQUIRE(VALID_NMSOCK(sock));
   1894 	REQUIRE(VALID_UVREQ(uvreq));
   1895 	REQUIRE(VALID_NMHANDLE(uvreq->handle));
   1896 
   1897 	uvreq->result = eresult;
   1898 
   1899 	if (!async) {
   1900 		isc___nm_readcb(uvreq);
   1901 		return;
   1902 	}
   1903 
   1904 	isc_job_run(sock->worker->loop, &uvreq->job, isc___nm_readcb, uvreq);
   1905 }
   1906 
   1907 static void
   1908 isc___nm_sendcb(void *arg) {
   1909 	isc__nm_uvreq_t *uvreq = arg;
   1910 
   1911 	uvreq->cb.send(uvreq->handle, uvreq->result, uvreq->cbarg);
   1912 	isc__nm_uvreq_put(&uvreq);
   1913 }
   1914 
   1915 void
   1916 isc__nm_sendcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
   1917 	       isc_result_t eresult, bool async) {
   1918 	REQUIRE(VALID_NMSOCK(sock));
   1919 	REQUIRE(VALID_UVREQ(uvreq));
   1920 	REQUIRE(VALID_NMHANDLE(uvreq->handle));
   1921 
   1922 	uvreq->result = eresult;
   1923 
   1924 	if (!async) {
   1925 		isc___nm_sendcb(uvreq);
   1926 		return;
   1927 	}
   1928 
   1929 	isc_job_run(sock->worker->loop, &uvreq->job, isc___nm_sendcb, uvreq);
   1930 }
   1931 
   1932 static void
   1933 reset_shutdown(uv_handle_t *handle) {
   1934 	isc_nmsocket_t *sock = uv_handle_get_data(handle);
   1935 
   1936 	isc__nmsocket_shutdown(sock);
   1937 	isc__nmsocket_detach(&sock);
   1938 }
   1939 
   1940 void
   1941 isc__nmsocket_reset(isc_nmsocket_t *sock) {
   1942 	REQUIRE(VALID_NMSOCK(sock));
   1943 
   1944 	switch (sock->type) {
   1945 	case isc_nm_tcpsocket:
   1946 		/*
   1947 		 * This can be called from the TCP write timeout.
   1948 		 */
   1949 		REQUIRE(sock->parent == NULL);
   1950 		break;
   1951 	case isc_nm_tlssocket:
   1952 		isc__nmsocket_tls_reset(sock);
   1953 		return;
   1954 	case isc_nm_streamdnssocket:
   1955 		isc__nmsocket_streamdns_reset(sock);
   1956 		return;
   1957 	case isc_nm_proxystreamsocket:
   1958 		isc__nmsocket_proxystream_reset(sock);
   1959 		return;
   1960 	default:
   1961 		UNREACHABLE();
   1962 		break;
   1963 	}
   1964 
   1965 	if (!uv_is_closing(&sock->uv_handle.handle) &&
   1966 	    uv_is_active(&sock->uv_handle.handle))
   1967 	{
   1968 		/*
   1969 		 * The real shutdown will be handled in the respective
   1970 		 * close functions.
   1971 		 */
   1972 		isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL });
   1973 		int r = uv_tcp_close_reset(&sock->uv_handle.tcp,
   1974 					   reset_shutdown);
   1975 		if (r != 0) {
   1976 			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
   1977 				      ISC_LOGMODULE_NETMGR, ISC_LOG_DEBUG(1),
   1978 				      "TCP Reset (RST) failed: %s",
   1979 				      uv_strerror(r));
   1980 			reset_shutdown(&sock->uv_handle.handle);
   1981 		}
   1982 	} else {
   1983 		isc__nmsocket_shutdown(sock);
   1984 	}
   1985 }
   1986 
   1987 void
   1988 isc__nmsocket_shutdown(isc_nmsocket_t *sock) {
   1989 	REQUIRE(VALID_NMSOCK(sock));
   1990 	switch (sock->type) {
   1991 	case isc_nm_udpsocket:
   1992 		isc__nm_udp_shutdown(sock);
   1993 		break;
   1994 	case isc_nm_tcpsocket:
   1995 		isc__nm_tcp_shutdown(sock);
   1996 		break;
   1997 	case isc_nm_udplistener:
   1998 	case isc_nm_tcplistener:
   1999 		return;
   2000 	default:
   2001 		UNREACHABLE();
   2002 	}
   2003 }
   2004 
   2005 static void
   2006 shutdown_walk_cb(uv_handle_t *handle, void *arg) {
   2007 	isc_nmsocket_t *sock = NULL;
   2008 	UNUSED(arg);
   2009 
   2010 	if (uv_is_closing(handle)) {
   2011 		return;
   2012 	}
   2013 
   2014 	sock = uv_handle_get_data(handle);
   2015 
   2016 	switch (handle->type) {
   2017 	case UV_UDP:
   2018 		isc__nmsocket_shutdown(sock);
   2019 		return;
   2020 	case UV_TCP:
   2021 		switch (sock->type) {
   2022 		case isc_nm_tcpsocket:
   2023 			if (sock->parent == NULL) {
   2024 				/* Reset the TCP connections on shutdown */
   2025 				isc__nmsocket_reset(sock);
   2026 				return;
   2027 			}
   2028 			FALLTHROUGH;
   2029 		default:
   2030 			isc__nmsocket_shutdown(sock);
   2031 		}
   2032 
   2033 		return;
   2034 	default:
   2035 		return;
   2036 	}
   2037 }
   2038 
   2039 void
   2040 isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats) {
   2041 	REQUIRE(VALID_NM(mgr));
   2042 	REQUIRE(mgr->stats == NULL);
   2043 	REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max);
   2044 
   2045 	isc_stats_attach(stats, &mgr->stats);
   2046 }
   2047 
   2048 void
   2049 isc__nm_incstats(isc_nmsocket_t *sock, isc__nm_statid_t id) {
   2050 	REQUIRE(VALID_NMSOCK(sock));
   2051 	REQUIRE(id < STATID_MAX);
   2052 
   2053 	if (sock->statsindex != NULL && sock->worker->netmgr->stats != NULL) {
   2054 		isc_stats_increment(sock->worker->netmgr->stats,
   2055 				    sock->statsindex[id]);
   2056 	}
   2057 }
   2058 
   2059 void
   2060 isc__nm_decstats(isc_nmsocket_t *sock, isc__nm_statid_t id) {
   2061 	REQUIRE(VALID_NMSOCK(sock));
   2062 	REQUIRE(id < STATID_MAX);
   2063 
   2064 	if (sock->statsindex != NULL && sock->worker->netmgr->stats != NULL) {
   2065 		isc_stats_decrement(sock->worker->netmgr->stats,
   2066 				    sock->statsindex[id]);
   2067 	}
   2068 }
   2069 
   2070 isc_result_t
   2071 isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type) {
   2072 	int proto, pf, addrlen, fd, r;
   2073 
   2074 	REQUIRE(addr != NULL);
   2075 
   2076 	switch (type) {
   2077 	case isc_socktype_tcp:
   2078 		proto = SOCK_STREAM;
   2079 		break;
   2080 	case isc_socktype_udp:
   2081 		proto = SOCK_DGRAM;
   2082 		break;
   2083 	default:
   2084 		return ISC_R_NOTIMPLEMENTED;
   2085 	}
   2086 
   2087 	pf = isc_sockaddr_pf(addr);
   2088 	if (pf == AF_INET) {
   2089 		addrlen = sizeof(struct sockaddr_in);
   2090 	} else {
   2091 		addrlen = sizeof(struct sockaddr_in6);
   2092 	}
   2093 
   2094 	fd = socket(pf, proto, 0);
   2095 	if (fd < 0) {
   2096 		return isc_errno_toresult(errno);
   2097 	}
   2098 
   2099 	r = bind(fd, (const struct sockaddr *)&addr->type.sa, addrlen);
   2100 	if (r < 0) {
   2101 		close(fd);
   2102 		return isc_errno_toresult(errno);
   2103 	}
   2104 
   2105 	close(fd);
   2106 	return ISC_R_SUCCESS;
   2107 }
   2108 
   2109 #if defined(TCP_CONNECTIONTIMEOUT)
   2110 #define TIMEOUT_TYPE	int
   2111 #define TIMEOUT_DIV	1000
   2112 #define TIMEOUT_OPTNAME TCP_CONNECTIONTIMEOUT
   2113 #elif defined(TCP_RXT_CONNDROPTIME)
   2114 #define TIMEOUT_TYPE	int
   2115 #define TIMEOUT_DIV	1000
   2116 #define TIMEOUT_OPTNAME TCP_RXT_CONNDROPTIME
   2117 #elif defined(TCP_USER_TIMEOUT)
   2118 #define TIMEOUT_TYPE	unsigned int
   2119 #define TIMEOUT_DIV	1
   2120 #define TIMEOUT_OPTNAME TCP_USER_TIMEOUT
   2121 #elif defined(TCP_KEEPINIT)
   2122 #define TIMEOUT_TYPE	int
   2123 #define TIMEOUT_DIV	1000
   2124 #define TIMEOUT_OPTNAME TCP_KEEPINIT
   2125 #endif
   2126 
   2127 void
   2128 isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle) {
   2129 	int32_t recv_buffer_size = 0;
   2130 	int32_t send_buffer_size = 0;
   2131 
   2132 	switch (handle->type) {
   2133 	case UV_TCP:
   2134 		recv_buffer_size =
   2135 			atomic_load_relaxed(&nm->recv_tcp_buffer_size);
   2136 		send_buffer_size =
   2137 			atomic_load_relaxed(&nm->send_tcp_buffer_size);
   2138 		break;
   2139 	case UV_UDP:
   2140 		recv_buffer_size =
   2141 			atomic_load_relaxed(&nm->recv_udp_buffer_size);
   2142 		send_buffer_size =
   2143 			atomic_load_relaxed(&nm->send_udp_buffer_size);
   2144 		break;
   2145 	default:
   2146 		UNREACHABLE();
   2147 	}
   2148 
   2149 	if (recv_buffer_size > 0) {
   2150 		int r = uv_recv_buffer_size(handle, &recv_buffer_size);
   2151 		UV_RUNTIME_CHECK(uv_recv_buffer_size, r);
   2152 	}
   2153 
   2154 	if (send_buffer_size > 0) {
   2155 		int r = uv_send_buffer_size(handle, &send_buffer_size);
   2156 		UV_RUNTIME_CHECK(uv_send_buffer_size, r);
   2157 	}
   2158 }
   2159 
   2160 void
   2161 isc_nm_bad_request(isc_nmhandle_t *handle) {
   2162 	isc_nmsocket_t *sock = NULL;
   2163 
   2164 	REQUIRE(VALID_NMHANDLE(handle));
   2165 	REQUIRE(VALID_NMSOCK(handle->sock));
   2166 
   2167 	sock = handle->sock;
   2168 
   2169 	switch (sock->type) {
   2170 	case isc_nm_udpsocket:
   2171 	case isc_nm_proxyudpsocket:
   2172 		return;
   2173 	case isc_nm_tcpsocket:
   2174 	case isc_nm_streamdnssocket:
   2175 	case isc_nm_tlssocket:
   2176 	case isc_nm_proxystreamsocket:
   2177 		REQUIRE(sock->parent == NULL);
   2178 		isc__nmsocket_reset(sock);
   2179 		return;
   2180 #if HAVE_LIBNGHTTP2
   2181 	case isc_nm_httpsocket:
   2182 		isc__nm_http_bad_request(handle);
   2183 		return;
   2184 #endif /* HAVE_LIBNGHTTP2 */
   2185 	default:
   2186 		UNREACHABLE();
   2187 		break;
   2188 	}
   2189 }
   2190 
   2191 isc_result_t
   2192 isc_nm_xfr_checkperm(isc_nmhandle_t *handle) {
   2193 	isc_nmsocket_t *sock = NULL;
   2194 	isc_result_t result = ISC_R_NOPERM;
   2195 
   2196 	REQUIRE(VALID_NMHANDLE(handle));
   2197 	REQUIRE(VALID_NMSOCK(handle->sock));
   2198 
   2199 	sock = handle->sock;
   2200 
   2201 	switch (sock->type) {
   2202 	case isc_nm_streamdnssocket:
   2203 		result = isc__nm_streamdns_xfr_checkperm(sock);
   2204 		break;
   2205 	default:
   2206 		break;
   2207 	}
   2208 
   2209 	return result;
   2210 }
   2211 
   2212 bool
   2213 isc_nm_is_http_handle(isc_nmhandle_t *handle) {
   2214 	REQUIRE(VALID_NMHANDLE(handle));
   2215 	REQUIRE(VALID_NMSOCK(handle->sock));
   2216 
   2217 	return handle->sock->type == isc_nm_httpsocket;
   2218 }
   2219 
   2220 static isc_nmhandle_t *
   2221 get_proxy_handle(isc_nmhandle_t *handle) {
   2222 	isc_nmsocket_t *sock = NULL;
   2223 
   2224 	sock = handle->sock;
   2225 
   2226 	switch (sock->type) {
   2227 	case isc_nm_proxystreamsocket:
   2228 	case isc_nm_proxyudpsocket:
   2229 		return handle;
   2230 #ifdef HAVE_LIBNGHTTP2
   2231 	case isc_nm_httpsocket:
   2232 		if (sock->h2 != NULL) {
   2233 			return get_proxy_handle(
   2234 				isc__nm_httpsession_handle(sock->h2->session));
   2235 		}
   2236 		return NULL;
   2237 #endif /* HAVE_LIBNGHTTP2 */
   2238 	default:
   2239 		break;
   2240 	}
   2241 
   2242 	if (sock->outerhandle != NULL) {
   2243 		return get_proxy_handle(sock->outerhandle);
   2244 	}
   2245 
   2246 	return NULL;
   2247 }
   2248 
   2249 bool
   2250 isc_nm_is_proxy_handle(isc_nmhandle_t *handle) {
   2251 	REQUIRE(VALID_NMHANDLE(handle));
   2252 	REQUIRE(VALID_NMSOCK(handle->sock));
   2253 
   2254 	return get_proxy_handle(handle) != NULL;
   2255 }
   2256 
   2257 bool
   2258 isc_nm_is_proxy_unspec(isc_nmhandle_t *handle) {
   2259 	isc_nmhandle_t *proxyhandle;
   2260 	REQUIRE(VALID_NMHANDLE(handle));
   2261 	REQUIRE(VALID_NMSOCK(handle->sock));
   2262 
   2263 	if (handle->sock->client) {
   2264 		return false;
   2265 	}
   2266 
   2267 	proxyhandle = get_proxy_handle(handle);
   2268 	if (proxyhandle == NULL) {
   2269 		return false;
   2270 	}
   2271 
   2272 	return proxyhandle->proxy_is_unspec;
   2273 }
   2274 
   2275 isc_sockaddr_t
   2276 isc_nmhandle_real_peeraddr(isc_nmhandle_t *handle) {
   2277 	isc_sockaddr_t addr = { 0 };
   2278 	isc_nmhandle_t *proxyhandle;
   2279 	REQUIRE(VALID_NMHANDLE(handle));
   2280 
   2281 	proxyhandle = get_proxy_handle(handle);
   2282 	if (proxyhandle == NULL) {
   2283 		return isc_nmhandle_peeraddr(handle);
   2284 	}
   2285 
   2286 	INSIST(VALID_NMSOCK(proxyhandle->sock));
   2287 
   2288 	if (isc_nmhandle_is_stream(proxyhandle)) {
   2289 		addr = isc_nmhandle_peeraddr(proxyhandle->sock->outerhandle);
   2290 	} else {
   2291 		INSIST(proxyhandle->sock->type == isc_nm_proxyudpsocket);
   2292 		addr = isc_nmhandle_peeraddr(proxyhandle->proxy_udphandle);
   2293 	}
   2294 
   2295 	return addr;
   2296 }
   2297 
   2298 isc_sockaddr_t
   2299 isc_nmhandle_real_localaddr(isc_nmhandle_t *handle) {
   2300 	isc_sockaddr_t addr = { 0 };
   2301 	isc_nmhandle_t *proxyhandle;
   2302 	REQUIRE(VALID_NMHANDLE(handle));
   2303 
   2304 	proxyhandle = get_proxy_handle(handle);
   2305 	if (proxyhandle == NULL) {
   2306 		return isc_nmhandle_localaddr(handle);
   2307 	}
   2308 
   2309 	INSIST(VALID_NMSOCK(proxyhandle->sock));
   2310 
   2311 	if (isc_nmhandle_is_stream(proxyhandle)) {
   2312 		addr = isc_nmhandle_localaddr(proxyhandle->sock->outerhandle);
   2313 	} else {
   2314 		INSIST(proxyhandle->sock->type == isc_nm_proxyudpsocket);
   2315 		addr = isc_nmhandle_localaddr(proxyhandle->proxy_udphandle);
   2316 	}
   2317 
   2318 	return addr;
   2319 }
   2320 
   2321 bool
   2322 isc__nm_valid_proxy_addresses(const isc_sockaddr_t *src,
   2323 			      const isc_sockaddr_t *dst) {
   2324 	struct in_addr inv4 = { 0 };
   2325 	struct in6_addr inv6 = { 0 };
   2326 	isc_netaddr_t zerov4 = { 0 }, zerov6 = { 0 };
   2327 	isc_netaddr_t src_addr = { 0 }, dst_addr = { 0 };
   2328 
   2329 	if (src == NULL || dst == NULL) {
   2330 		return false;
   2331 	}
   2332 
   2333 	/*
   2334 	 * We should not allow using 0 in source addresses as well, but we
   2335 	 * have a precedent of a tool that issues port 0 in the source
   2336 	 * addresses (kdig).
   2337 	 */
   2338 	if (isc_sockaddr_getport(dst) == 0) {
   2339 		return false;
   2340 	}
   2341 
   2342 	/*
   2343 	 * Anybody using zeroes in source or destination addresses is not
   2344 	 * a friend. Considering that most of the upper level code is
   2345 	 * written with consideration that bot source and destination
   2346 	 * addresses are returned by the OS and should be valid, we should
   2347 	 * discard so suspicious addresses. Also, keep in mind that both
   2348 	 * "0.0.0.0" and "::" match all interfaces when using as listener
   2349 	 * addresses.
   2350 	 */
   2351 	isc_netaddr_fromin(&zerov4, &inv4);
   2352 	isc_netaddr_fromin6(&zerov6, &inv6);
   2353 
   2354 	isc_netaddr_fromsockaddr(&src_addr, src);
   2355 	isc_netaddr_fromsockaddr(&dst_addr, dst);
   2356 
   2357 	INSIST(isc_sockaddr_pf(src) == isc_sockaddr_pf(dst));
   2358 
   2359 	switch (isc_sockaddr_pf(src)) {
   2360 	case AF_INET:
   2361 		if (isc_netaddr_equal(&src_addr, &zerov4)) {
   2362 			return false;
   2363 		}
   2364 
   2365 		if (isc_netaddr_equal(&dst_addr, &zerov4)) {
   2366 			return false;
   2367 		}
   2368 		break;
   2369 	case AF_INET6:
   2370 		if (isc_netaddr_equal(&src_addr, &zerov6)) {
   2371 			return false;
   2372 		}
   2373 
   2374 		if (isc_netaddr_equal(&dst_addr, &zerov6)) {
   2375 			return false;
   2376 		}
   2377 		break;
   2378 	default:
   2379 		UNREACHABLE();
   2380 	}
   2381 
   2382 	return true;
   2383 }
   2384 
   2385 void
   2386 isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl) {
   2387 	isc_nmsocket_t *sock = NULL;
   2388 
   2389 	REQUIRE(VALID_NMHANDLE(handle));
   2390 	REQUIRE(VALID_NMSOCK(handle->sock));
   2391 	REQUIRE(!handle->sock->client);
   2392 
   2393 #if !HAVE_LIBNGHTTP2
   2394 	UNUSED(ttl);
   2395 #endif
   2396 
   2397 	sock = handle->sock;
   2398 	switch (sock->type) {
   2399 #if HAVE_LIBNGHTTP2
   2400 	case isc_nm_httpsocket:
   2401 		isc__nm_http_set_maxage(handle, ttl);
   2402 		break;
   2403 #endif /* HAVE_LIBNGHTTP2 */
   2404 	case isc_nm_udpsocket:
   2405 	case isc_nm_proxyudpsocket:
   2406 	case isc_nm_streamdnssocket:
   2407 		return;
   2408 		break;
   2409 	case isc_nm_tcpsocket:
   2410 	case isc_nm_tlssocket:
   2411 	case isc_nm_proxystreamsocket:
   2412 	default:
   2413 		UNREACHABLE();
   2414 		break;
   2415 	}
   2416 }
   2417 
   2418 isc_nmsocket_type
   2419 isc_nm_socket_type(const isc_nmhandle_t *handle) {
   2420 	REQUIRE(VALID_NMHANDLE(handle));
   2421 	REQUIRE(VALID_NMSOCK(handle->sock));
   2422 
   2423 	return handle->sock->type;
   2424 }
   2425 
   2426 bool
   2427 isc_nm_has_encryption(const isc_nmhandle_t *handle) {
   2428 	REQUIRE(VALID_NMHANDLE(handle));
   2429 	REQUIRE(VALID_NMSOCK(handle->sock));
   2430 
   2431 	switch (handle->sock->type) {
   2432 	case isc_nm_tlssocket:
   2433 		return true;
   2434 #if HAVE_LIBNGHTTP2
   2435 	case isc_nm_httpsocket:
   2436 		return isc__nm_http_has_encryption(handle);
   2437 #endif /* HAVE_LIBNGHTTP2 */
   2438 	case isc_nm_streamdnssocket:
   2439 		return isc__nm_streamdns_has_encryption(handle);
   2440 	case isc_nm_proxystreamsocket:
   2441 		return isc__nm_proxystream_has_encryption(handle);
   2442 	default:
   2443 		return false;
   2444 	};
   2445 
   2446 	return false;
   2447 }
   2448 
   2449 const char *
   2450 isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
   2451 	isc_nmsocket_t *sock = NULL;
   2452 
   2453 	REQUIRE(VALID_NMHANDLE(handle));
   2454 	REQUIRE(VALID_NMSOCK(handle->sock));
   2455 
   2456 	sock = handle->sock;
   2457 	switch (sock->type) {
   2458 	case isc_nm_tlssocket:
   2459 		return isc__nm_tls_verify_tls_peer_result_string(handle);
   2460 		break;
   2461 	case isc_nm_proxystreamsocket:
   2462 		return isc__nm_proxystream_verify_tls_peer_result_string(
   2463 			handle);
   2464 		break;
   2465 #if HAVE_LIBNGHTTP2
   2466 	case isc_nm_httpsocket:
   2467 		return isc__nm_http_verify_tls_peer_result_string(handle);
   2468 		break;
   2469 #endif /* HAVE_LIBNGHTTP2 */
   2470 	case isc_nm_streamdnssocket:
   2471 		return isc__nm_streamdns_verify_tls_peer_result_string(handle);
   2472 		break;
   2473 	default:
   2474 		break;
   2475 	}
   2476 
   2477 	return NULL;
   2478 }
   2479 
   2480 typedef struct settlsctx_data {
   2481 	isc_nmsocket_t *listener;
   2482 	isc_tlsctx_t *tlsctx;
   2483 } settlsctx_data_t;
   2484 
   2485 static void
   2486 settlsctx_cb(void *arg) {
   2487 	settlsctx_data_t *data = arg;
   2488 	const uint32_t tid = isc_tid();
   2489 	isc_nmsocket_t *listener = data->listener;
   2490 	isc_tlsctx_t *tlsctx = data->tlsctx;
   2491 	isc__networker_t *worker = &listener->worker->netmgr->workers[tid];
   2492 
   2493 	isc_mem_put(worker->loop->mctx, data, sizeof(*data));
   2494 
   2495 	REQUIRE(listener->type == isc_nm_tlslistener);
   2496 
   2497 	isc__nm_async_tls_set_tlsctx(listener, tlsctx, tid);
   2498 
   2499 	isc__nmsocket_detach(&listener);
   2500 	isc_tlsctx_free(&tlsctx);
   2501 }
   2502 
   2503 static void
   2504 set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
   2505 	const size_t nworkers =
   2506 		(size_t)isc_loopmgr_nloops(listener->worker->netmgr->loopmgr);
   2507 	/* Update the TLS context reference for every worker thread. */
   2508 	for (size_t i = 0; i < nworkers; i++) {
   2509 		isc__networker_t *worker =
   2510 			&listener->worker->netmgr->workers[i];
   2511 		settlsctx_data_t *data = isc_mem_cget(worker->loop->mctx, 1,
   2512 						      sizeof(*data));
   2513 
   2514 		isc__nmsocket_attach(listener, &data->listener);
   2515 		isc_tlsctx_attach(tlsctx, &data->tlsctx);
   2516 
   2517 		isc_async_run(worker->loop, settlsctx_cb, data);
   2518 	}
   2519 }
   2520 
   2521 void
   2522 isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
   2523 	REQUIRE(VALID_NMSOCK(listener));
   2524 	REQUIRE(tlsctx != NULL);
   2525 
   2526 	switch (listener->type) {
   2527 #if HAVE_LIBNGHTTP2
   2528 	case isc_nm_httplistener:
   2529 		/*
   2530 		 * We handle HTTP listener sockets differently, as they rely
   2531 		 * on underlying TLS sockets for networking. The TLS context
   2532 		 * will get passed to these underlying sockets via the call to
   2533 		 * isc__nm_http_set_tlsctx().
   2534 		 */
   2535 		isc__nm_http_set_tlsctx(listener, tlsctx);
   2536 		break;
   2537 #endif /* HAVE_LIBNGHTTP2 */
   2538 	case isc_nm_tlslistener:
   2539 		set_tlsctx_workers(listener, tlsctx);
   2540 		break;
   2541 	case isc_nm_streamdnslistener:
   2542 		isc__nm_streamdns_set_tlsctx(listener, tlsctx);
   2543 		break;
   2544 	case isc_nm_proxystreamlistener:
   2545 		isc__nm_proxystream_set_tlsctx(listener, tlsctx);
   2546 		break;
   2547 	default:
   2548 		UNREACHABLE();
   2549 		break;
   2550 	};
   2551 }
   2552 
   2553 void
   2554 isc_nmsocket_set_max_streams(isc_nmsocket_t *listener,
   2555 			     const uint32_t max_streams) {
   2556 	REQUIRE(VALID_NMSOCK(listener));
   2557 	switch (listener->type) {
   2558 #if HAVE_LIBNGHTTP2
   2559 	case isc_nm_httplistener:
   2560 		isc__nm_http_set_max_streams(listener, max_streams);
   2561 		break;
   2562 #endif /* HAVE_LIBNGHTTP2 */
   2563 	default:
   2564 		UNUSED(max_streams);
   2565 		break;
   2566 	};
   2567 	return;
   2568 }
   2569 
   2570 void
   2571 isc__nmsocket_log_tls_session_reuse(isc_nmsocket_t *sock, isc_tls_t *tls) {
   2572 	const int log_level = ISC_LOG_DEBUG(1);
   2573 	char client_sabuf[ISC_SOCKADDR_FORMATSIZE];
   2574 	char local_sabuf[ISC_SOCKADDR_FORMATSIZE];
   2575 
   2576 	REQUIRE(tls != NULL);
   2577 
   2578 	if (!isc_log_wouldlog(isc_lctx, log_level)) {
   2579 		return;
   2580 	};
   2581 
   2582 	isc_sockaddr_format(&sock->peer, client_sabuf, sizeof(client_sabuf));
   2583 	isc_sockaddr_format(&sock->iface, local_sabuf, sizeof(local_sabuf));
   2584 	isc__nmsocket_log(sock, log_level, "TLS %s session %s for %s on %s",
   2585 			  SSL_is_server(tls) ? "server" : "client",
   2586 			  SSL_session_reused(tls) ? "resumed" : "created",
   2587 			  client_sabuf, local_sabuf);
   2588 }
   2589 
   2590 static void
   2591 isc__networker_destroy(isc__networker_t *worker) {
   2592 	isc_nm_t *netmgr = worker->netmgr;
   2593 	worker->netmgr = NULL;
   2594 
   2595 	isc__netmgr_log(netmgr, ISC_LOG_DEBUG(1),
   2596 			"Destroying network manager worker on loop %p(%d)",
   2597 			worker->loop, isc_tid());
   2598 
   2599 	isc_loop_detach(&worker->loop);
   2600 
   2601 	isc_mempool_destroy(&worker->uvreq_pool);
   2602 	isc_mempool_destroy(&worker->nmsocket_pool);
   2603 
   2604 	isc_mem_putanddetach(&worker->mctx, worker->recvbuf,
   2605 			     ISC_NETMGR_RECVBUF_SIZE);
   2606 	isc_nm_detach(&netmgr);
   2607 }
   2608 
   2609 ISC_REFCOUNT_IMPL(isc__networker, isc__networker_destroy);
   2610 
   2611 void
   2612 isc__netmgr_log(const isc_nm_t *netmgr, int level, const char *fmt, ...) {
   2613 	char msgbuf[2048];
   2614 	va_list ap;
   2615 
   2616 	if (!isc_log_wouldlog(isc_lctx, level)) {
   2617 		return;
   2618 	}
   2619 
   2620 	va_start(ap, fmt);
   2621 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
   2622 	va_end(ap);
   2623 
   2624 	isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_NETMGR,
   2625 		      level, "netmgr %p: %s", netmgr, msgbuf);
   2626 }
   2627 
   2628 void
   2629 isc__nmsocket_log(const isc_nmsocket_t *sock, int level, const char *fmt, ...) {
   2630 	char msgbuf[2048];
   2631 	va_list ap;
   2632 
   2633 	if (!isc_log_wouldlog(isc_lctx, level)) {
   2634 		return;
   2635 	}
   2636 
   2637 	va_start(ap, fmt);
   2638 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
   2639 	va_end(ap);
   2640 
   2641 	isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_NETMGR,
   2642 		      level, "socket %p: %s", sock, msgbuf);
   2643 }
   2644 
   2645 void
   2646 isc__nmhandle_log(const isc_nmhandle_t *handle, int level, const char *fmt,
   2647 		  ...) {
   2648 	char msgbuf[2048];
   2649 	va_list ap;
   2650 
   2651 	if (!isc_log_wouldlog(isc_lctx, level)) {
   2652 		return;
   2653 	}
   2654 
   2655 	va_start(ap, fmt);
   2656 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
   2657 	va_end(ap);
   2658 
   2659 	isc__nmsocket_log(handle->sock, level, "handle %p: %s", handle, msgbuf);
   2660 }
   2661 
   2662 void
   2663 isc__nm_received_proxy_header_log(isc_nmhandle_t *handle,
   2664 				  const isc_proxy2_command_t cmd,
   2665 				  const int socktype,
   2666 				  const isc_sockaddr_t *restrict src_addr,
   2667 				  const isc_sockaddr_t *restrict dst_addr,
   2668 				  const isc_region_t *restrict tlvs) {
   2669 	const int log_level = ISC_LOG_DEBUG(1);
   2670 	isc_sockaddr_t real_local, real_peer;
   2671 	char real_local_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 };
   2672 	char real_peer_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 };
   2673 	char common_msg[512] = { 0 };
   2674 	const char *proto = NULL;
   2675 	const char *real_addresses_msg =
   2676 		"real source and destination addresses are used";
   2677 
   2678 	if (!isc_log_wouldlog(isc_lctx, log_level)) {
   2679 		return;
   2680 	}
   2681 
   2682 	if (isc_nmhandle_is_stream(handle)) {
   2683 		proto = isc_nm_has_encryption(handle) ? "TLS" : "TCP";
   2684 	} else {
   2685 		proto = "UDP";
   2686 	}
   2687 
   2688 	real_local = isc_nmhandle_real_localaddr(handle);
   2689 	real_peer = isc_nmhandle_real_peeraddr(handle);
   2690 
   2691 	isc_sockaddr_format(&real_local, real_local_fmt,
   2692 			    sizeof(real_local_fmt));
   2693 
   2694 	isc_sockaddr_format(&real_peer, real_peer_fmt, sizeof(real_peer_fmt));
   2695 
   2696 	(void)snprintf(common_msg, sizeof(common_msg),
   2697 		       "Received a PROXYv2 header from %s on %s over %s",
   2698 		       real_peer_fmt, real_local_fmt, proto);
   2699 
   2700 	if (cmd == ISC_PROXY2_CMD_LOCAL) {
   2701 		isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT,
   2702 			      ISC_LOGMODULE_NETMGR, log_level,
   2703 			      "%s: command: LOCAL (%s)", common_msg,
   2704 			      real_addresses_msg);
   2705 		return;
   2706 	} else if (cmd == ISC_PROXY2_CMD_PROXY) {
   2707 		const char *tlvs_msg = tlvs == NULL ? "no" : "yes";
   2708 		const char *socktype_name = NULL;
   2709 		const char *src_addr_msg = "(none)", *dst_addr_msg = "(none)";
   2710 		char src_addr_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 };
   2711 		char dst_addr_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 };
   2712 
   2713 		switch (socktype) {
   2714 		case 0:
   2715 			isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT,
   2716 				      ISC_LOGMODULE_NETMGR, log_level,
   2717 				      "%s: command: PROXY (unspecified address "
   2718 				      "and socket type, %s)",
   2719 				      common_msg, real_addresses_msg);
   2720 			return;
   2721 		case SOCK_STREAM:
   2722 			socktype_name = "SOCK_STREAM";
   2723 			break;
   2724 		case SOCK_DGRAM:
   2725 			socktype_name = "SOCK_DGRAM";
   2726 			break;
   2727 		default:
   2728 			UNREACHABLE();
   2729 		}
   2730 
   2731 		if (src_addr) {
   2732 			isc_sockaddr_format(src_addr, src_addr_fmt,
   2733 					    sizeof(src_addr_fmt));
   2734 			src_addr_msg = src_addr_fmt;
   2735 		}
   2736 
   2737 		if (dst_addr) {
   2738 			isc_sockaddr_format(dst_addr, dst_addr_fmt,
   2739 					    sizeof(dst_addr_fmt));
   2740 			dst_addr_msg = dst_addr_fmt;
   2741 		}
   2742 
   2743 		isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT,
   2744 			      ISC_LOGMODULE_NETMGR, log_level,
   2745 			      "%s: command: PROXY, socket type: %s, source: "
   2746 			      "%s, destination: %s, TLVs: %s",
   2747 			      common_msg, socktype_name, src_addr_msg,
   2748 			      dst_addr_msg, tlvs_msg);
   2749 	}
   2750 }
   2751 
   2752 void
   2753 isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual) {
   2754 	REQUIRE(VALID_NMHANDLE(handle));
   2755 	REQUIRE(VALID_NMSOCK(handle->sock));
   2756 
   2757 	isc_nmsocket_t *sock = handle->sock;
   2758 
   2759 	switch (sock->type) {
   2760 	case isc_nm_tcpsocket:
   2761 		isc__nmhandle_tcp_set_manual_timer(handle, manual);
   2762 		return;
   2763 	case isc_nm_tlssocket:
   2764 		isc__nmhandle_tls_set_manual_timer(handle, manual);
   2765 		return;
   2766 	case isc_nm_proxystreamsocket:
   2767 		isc__nmhandle_proxystream_set_manual_timer(handle, manual);
   2768 		return;
   2769 	default:
   2770 		break;
   2771 	};
   2772 
   2773 	UNREACHABLE();
   2774 }
   2775 
   2776 void
   2777 isc__nmhandle_get_selected_alpn(isc_nmhandle_t *handle,
   2778 				const unsigned char **alpn,
   2779 				unsigned int *alpnlen) {
   2780 	REQUIRE(VALID_NMHANDLE(handle));
   2781 	REQUIRE(VALID_NMSOCK(handle->sock));
   2782 
   2783 	isc_nmsocket_t *sock = handle->sock;
   2784 
   2785 	switch (sock->type) {
   2786 	case isc_nm_tlssocket:
   2787 		isc__nmhandle_tls_get_selected_alpn(handle, alpn, alpnlen);
   2788 		return;
   2789 	case isc_nm_proxystreamsocket:
   2790 		isc__nmhandle_proxystream_get_selected_alpn(handle, alpn,
   2791 							    alpnlen);
   2792 		return;
   2793 	default:
   2794 		break;
   2795 	};
   2796 }
   2797 
   2798 isc_result_t
   2799 isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value) {
   2800 	REQUIRE(VALID_NMHANDLE(handle));
   2801 	REQUIRE(VALID_NMSOCK(handle->sock));
   2802 
   2803 	isc_result_t result = ISC_R_FAILURE;
   2804 	isc_nmsocket_t *sock = handle->sock;
   2805 
   2806 	switch (sock->type) {
   2807 	case isc_nm_tcpsocket: {
   2808 		uv_os_fd_t tcp_fd = (uv_os_fd_t)-1;
   2809 		(void)uv_fileno((uv_handle_t *)&sock->uv_handle.tcp, &tcp_fd);
   2810 		RUNTIME_CHECK(tcp_fd != (uv_os_fd_t)-1);
   2811 		result = isc__nm_socket_tcp_nodelay((uv_os_sock_t)tcp_fd,
   2812 						    value);
   2813 	} break;
   2814 	case isc_nm_tlssocket:
   2815 		result = isc__nmhandle_tls_set_tcp_nodelay(handle, value);
   2816 		break;
   2817 	case isc_nm_proxystreamsocket:
   2818 		result = isc__nmhandle_proxystream_set_tcp_nodelay(handle,
   2819 								   value);
   2820 		break;
   2821 	default:
   2822 		UNREACHABLE();
   2823 		break;
   2824 	};
   2825 
   2826 	return result;
   2827 }
   2828 
   2829 isc_sockaddr_t
   2830 isc_nmsocket_getaddr(isc_nmsocket_t *sock) {
   2831 	REQUIRE(VALID_NMSOCK(sock));
   2832 	return sock->iface;
   2833 }
   2834 
   2835 void
   2836 isc_nm_proxyheader_info_init(isc_nm_proxyheader_info_t *restrict info,
   2837 			     isc_sockaddr_t *restrict src_addr,
   2838 			     isc_sockaddr_t *restrict dst_addr,
   2839 			     isc_region_t *restrict tlv_data) {
   2840 	REQUIRE(info != NULL);
   2841 	REQUIRE(src_addr != NULL);
   2842 	REQUIRE(dst_addr != NULL);
   2843 	REQUIRE(tlv_data == NULL ||
   2844 		(tlv_data->length > 0 && tlv_data->base != NULL));
   2845 
   2846 	*info = (isc_nm_proxyheader_info_t){ .proxy_info.src_addr = *src_addr,
   2847 					     .proxy_info.dst_addr = *dst_addr };
   2848 	if (tlv_data != NULL) {
   2849 		info->proxy_info.tlv_data = *tlv_data;
   2850 	}
   2851 }
   2852 
   2853 void
   2854 isc_nm_proxyheader_info_init_complete(isc_nm_proxyheader_info_t *restrict info,
   2855 				      isc_region_t *restrict header_data) {
   2856 	REQUIRE(info != NULL);
   2857 	REQUIRE(header_data != NULL);
   2858 	REQUIRE(header_data->base != NULL &&
   2859 		header_data->length >= ISC_PROXY2_HEADER_SIZE);
   2860 
   2861 	*info = (isc_nm_proxyheader_info_t){ .complete = true,
   2862 					     .complete_header = *header_data };
   2863 }
   2864 
   2865 void
   2866 isc_netmgr_portrange(isc_nm_t *netmgr, sa_family_t af, in_port_t low,
   2867 		     in_port_t high) {
   2868 	REQUIRE(VALID_NM(netmgr));
   2869 	switch (af) {
   2870 	case AF_INET:
   2871 		atomic_store_relaxed(&netmgr->port_low4, low);
   2872 		atomic_store_relaxed(&netmgr->port_high4, high);
   2873 		break;
   2874 	case AF_INET6:
   2875 		atomic_store_relaxed(&netmgr->port_low6, low);
   2876 		atomic_store_relaxed(&netmgr->port_high6, high);
   2877 		break;
   2878 	default:
   2879 		UNREACHABLE();
   2880 	}
   2881 }
   2882 
   2883 #if ISC_NETMGR_TRACE
   2884 /*
   2885  * Dump all active sockets in netmgr. We output to stderr
   2886  * as the logger might be already shut down.
   2887  */
   2888 
   2889 static const char *
   2890 nmsocket_type_totext(isc_nmsocket_type type) {
   2891 	switch (type) {
   2892 	case isc_nm_udpsocket:
   2893 		return "isc_nm_udpsocket";
   2894 	case isc_nm_udplistener:
   2895 		return "isc_nm_udplistener";
   2896 	case isc_nm_tcpsocket:
   2897 		return "isc_nm_tcpsocket";
   2898 	case isc_nm_tcplistener:
   2899 		return "isc_nm_tcplistener";
   2900 	case isc_nm_tlssocket:
   2901 		return "isc_nm_tlssocket";
   2902 	case isc_nm_tlslistener:
   2903 		return "isc_nm_tlslistener";
   2904 	case isc_nm_httplistener:
   2905 		return "isc_nm_httplistener";
   2906 	case isc_nm_httpsocket:
   2907 		return "isc_nm_httpsocket";
   2908 	case isc_nm_streamdnslistener:
   2909 		return "isc_nm_streamdnslistener";
   2910 	case isc_nm_streamdnssocket:
   2911 		return "isc_nm_streamdnssocket";
   2912 	case isc_nm_proxystreamlistener:
   2913 		return "isc_nm_proxystreamlistener";
   2914 	case isc_nm_proxystreamsocket:
   2915 		return "isc_nm_proxystreamsocket";
   2916 	case isc_nm_proxyudplistener:
   2917 		return "isc_nm_proxyudplistener";
   2918 	case isc_nm_proxyudpsocket:
   2919 		return "isc_nm_proxyudpsocket";
   2920 	default:
   2921 		UNREACHABLE();
   2922 	}
   2923 }
   2924 
   2925 static void
   2926 nmhandle_dump(isc_nmhandle_t *handle) {
   2927 	fprintf(stderr, "Active handle %p, refs %" PRIuFAST32 "\n", handle,
   2928 		isc_refcount_current(&handle->references));
   2929 	fprintf(stderr, "Created by:\n");
   2930 	isc_backtrace_symbols_fd(handle->backtrace, handle->backtrace_size,
   2931 				 STDERR_FILENO);
   2932 	fprintf(stderr, "\n\n");
   2933 }
   2934 
   2935 static void
   2936 nmsocket_dump(isc_nmsocket_t *sock) {
   2937 	isc_nmhandle_t *handle = NULL;
   2938 
   2939 	fprintf(stderr, "\n=================\n");
   2940 	fprintf(stderr, "Active %s socket %p, type %s, refs %" PRIuFAST32 "\n",
   2941 		sock->client ? "client" : "server", sock,
   2942 		nmsocket_type_totext(sock->type),
   2943 		isc_refcount_current(&sock->references));
   2944 	fprintf(stderr,
   2945 		"Parent %p, listener %p, server %p, statichandle = "
   2946 		"%p\n",
   2947 		sock->parent, sock->listener, sock->server, sock->statichandle);
   2948 	fprintf(stderr, "Flags:%s%s%s%s%s\n", sock->active ? " active" : "",
   2949 		sock->closing ? " closing" : "",
   2950 		sock->destroying ? " destroying" : "",
   2951 		sock->connecting ? " connecting" : "",
   2952 		sock->accepting ? " accepting" : "");
   2953 	fprintf(stderr, "Created by:\n");
   2954 	isc_backtrace_symbols_fd(sock->backtrace, sock->backtrace_size,
   2955 				 STDERR_FILENO);
   2956 	fprintf(stderr, "\n");
   2957 
   2958 	for (handle = ISC_LIST_HEAD(sock->active_handles); handle != NULL;
   2959 	     handle = ISC_LIST_NEXT(handle, active_link))
   2960 	{
   2961 		static bool first = true;
   2962 		if (first) {
   2963 			fprintf(stderr, "Active handles:\n");
   2964 			first = false;
   2965 		}
   2966 		nmhandle_dump(handle);
   2967 	}
   2968 
   2969 	fprintf(stderr, "\n");
   2970 }
   2971 
   2972 void
   2973 isc__nm_dump_active(isc__networker_t *worker) {
   2974 	isc_nmsocket_t *sock = NULL;
   2975 	bool first = true;
   2976 
   2977 	for (sock = ISC_LIST_HEAD(worker->active_sockets); sock != NULL;
   2978 	     sock = ISC_LIST_NEXT(sock, active_link))
   2979 	{
   2980 		if (first) {
   2981 			fprintf(stderr, "Outstanding sockets\n");
   2982 			first = false;
   2983 		}
   2984 		nmsocket_dump(sock);
   2985 	}
   2986 }
   2987 
   2988 void
   2989 isc__nm_dump_active_manager(isc_nm_t *netmgr) {
   2990 	size_t i = 0;
   2991 
   2992 	for (i = 0; i < netmgr->nloops; i++) {
   2993 		isc__networker_t *worker = &netmgr->workers[i];
   2994 
   2995 		if (!ISC_LIST_EMPTY(worker->active_sockets)) {
   2996 			fprintf(stderr, "Worker #%zu (%p)\n", i, worker);
   2997 			isc__nm_dump_active(worker);
   2998 		}
   2999 	}
   3000 }
   3001 #endif
   3002