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