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, ®ion, 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