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