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