1 /* $NetBSD: netmgr.c,v 1.17 2026/09/17 18:01:17 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 isc__nm_httpsession_active(sock->h2->session)) 2234 { 2235 return get_proxy_handle( 2236 isc__nm_httpsession_handle(sock->h2->session)); 2237 } 2238 return NULL; 2239 #endif /* HAVE_LIBNGHTTP2 */ 2240 default: 2241 break; 2242 } 2243 2244 if (sock->outerhandle != NULL) { 2245 return get_proxy_handle(sock->outerhandle); 2246 } 2247 2248 return NULL; 2249 } 2250 2251 bool 2252 isc_nm_is_proxy_handle(isc_nmhandle_t *handle) { 2253 REQUIRE(VALID_NMHANDLE(handle)); 2254 REQUIRE(VALID_NMSOCK(handle->sock)); 2255 2256 return get_proxy_handle(handle) != NULL; 2257 } 2258 2259 bool 2260 isc_nm_is_proxy_unspec(isc_nmhandle_t *handle) { 2261 isc_nmhandle_t *proxyhandle; 2262 REQUIRE(VALID_NMHANDLE(handle)); 2263 REQUIRE(VALID_NMSOCK(handle->sock)); 2264 2265 if (handle->sock->client) { 2266 return false; 2267 } 2268 2269 proxyhandle = get_proxy_handle(handle); 2270 if (proxyhandle == NULL) { 2271 return false; 2272 } 2273 2274 return proxyhandle->proxy_is_unspec; 2275 } 2276 2277 isc_sockaddr_t 2278 isc_nmhandle_real_peeraddr(isc_nmhandle_t *handle) { 2279 isc_sockaddr_t addr = { 0 }; 2280 isc_nmhandle_t *proxyhandle; 2281 REQUIRE(VALID_NMHANDLE(handle)); 2282 2283 proxyhandle = get_proxy_handle(handle); 2284 if (proxyhandle == NULL) { 2285 return isc_nmhandle_peeraddr(handle); 2286 } 2287 2288 INSIST(VALID_NMSOCK(proxyhandle->sock)); 2289 2290 if (isc_nmhandle_is_stream(proxyhandle)) { 2291 addr = isc_nmhandle_peeraddr(proxyhandle->sock->outerhandle); 2292 } else { 2293 INSIST(proxyhandle->sock->type == isc_nm_proxyudpsocket); 2294 addr = isc_nmhandle_peeraddr(proxyhandle->proxy_udphandle); 2295 } 2296 2297 return addr; 2298 } 2299 2300 isc_sockaddr_t 2301 isc_nmhandle_real_localaddr(isc_nmhandle_t *handle) { 2302 isc_sockaddr_t addr = { 0 }; 2303 isc_nmhandle_t *proxyhandle; 2304 REQUIRE(VALID_NMHANDLE(handle)); 2305 2306 proxyhandle = get_proxy_handle(handle); 2307 if (proxyhandle == NULL) { 2308 return isc_nmhandle_localaddr(handle); 2309 } 2310 2311 INSIST(VALID_NMSOCK(proxyhandle->sock)); 2312 2313 if (isc_nmhandle_is_stream(proxyhandle)) { 2314 addr = isc_nmhandle_localaddr(proxyhandle->sock->outerhandle); 2315 } else { 2316 INSIST(proxyhandle->sock->type == isc_nm_proxyudpsocket); 2317 addr = isc_nmhandle_localaddr(proxyhandle->proxy_udphandle); 2318 } 2319 2320 return addr; 2321 } 2322 2323 bool 2324 isc__nm_valid_proxy_addresses(const isc_sockaddr_t *src, 2325 const isc_sockaddr_t *dst) { 2326 struct in_addr inv4 = { 0 }; 2327 struct in6_addr inv6 = { 0 }; 2328 isc_netaddr_t zerov4 = { 0 }, zerov6 = { 0 }; 2329 isc_netaddr_t src_addr = { 0 }, dst_addr = { 0 }; 2330 2331 if (src == NULL || dst == NULL) { 2332 return false; 2333 } 2334 2335 /* 2336 * We should not allow using 0 in source addresses as well, but we 2337 * have a precedent of a tool that issues port 0 in the source 2338 * addresses (kdig). 2339 */ 2340 if (isc_sockaddr_getport(dst) == 0) { 2341 return false; 2342 } 2343 2344 /* 2345 * Anybody using zeroes in source or destination addresses is not 2346 * a friend. Considering that most of the upper level code is 2347 * written with consideration that bot source and destination 2348 * addresses are returned by the OS and should be valid, we should 2349 * discard so suspicious addresses. Also, keep in mind that both 2350 * "0.0.0.0" and "::" match all interfaces when using as listener 2351 * addresses. 2352 */ 2353 isc_netaddr_fromin(&zerov4, &inv4); 2354 isc_netaddr_fromin6(&zerov6, &inv6); 2355 2356 isc_netaddr_fromsockaddr(&src_addr, src); 2357 isc_netaddr_fromsockaddr(&dst_addr, dst); 2358 2359 INSIST(isc_sockaddr_pf(src) == isc_sockaddr_pf(dst)); 2360 2361 switch (isc_sockaddr_pf(src)) { 2362 case AF_INET: 2363 if (isc_netaddr_equal(&src_addr, &zerov4)) { 2364 return false; 2365 } 2366 2367 if (isc_netaddr_equal(&dst_addr, &zerov4)) { 2368 return false; 2369 } 2370 break; 2371 case AF_INET6: 2372 if (isc_netaddr_equal(&src_addr, &zerov6)) { 2373 return false; 2374 } 2375 2376 if (isc_netaddr_equal(&dst_addr, &zerov6)) { 2377 return false; 2378 } 2379 break; 2380 default: 2381 UNREACHABLE(); 2382 } 2383 2384 return true; 2385 } 2386 2387 void 2388 isc_nm_set_maxage(isc_nmhandle_t *handle, const uint32_t ttl) { 2389 isc_nmsocket_t *sock = NULL; 2390 2391 REQUIRE(VALID_NMHANDLE(handle)); 2392 REQUIRE(VALID_NMSOCK(handle->sock)); 2393 REQUIRE(!handle->sock->client); 2394 2395 #if !HAVE_LIBNGHTTP2 2396 UNUSED(ttl); 2397 #endif 2398 2399 sock = handle->sock; 2400 switch (sock->type) { 2401 #if HAVE_LIBNGHTTP2 2402 case isc_nm_httpsocket: 2403 isc__nm_http_set_maxage(handle, ttl); 2404 break; 2405 #endif /* HAVE_LIBNGHTTP2 */ 2406 case isc_nm_udpsocket: 2407 case isc_nm_proxyudpsocket: 2408 case isc_nm_streamdnssocket: 2409 return; 2410 break; 2411 case isc_nm_tcpsocket: 2412 case isc_nm_tlssocket: 2413 case isc_nm_proxystreamsocket: 2414 default: 2415 UNREACHABLE(); 2416 break; 2417 } 2418 } 2419 2420 isc_nmsocket_type 2421 isc_nm_socket_type(const isc_nmhandle_t *handle) { 2422 REQUIRE(VALID_NMHANDLE(handle)); 2423 REQUIRE(VALID_NMSOCK(handle->sock)); 2424 2425 return handle->sock->type; 2426 } 2427 2428 bool 2429 isc_nm_has_encryption(const isc_nmhandle_t *handle) { 2430 REQUIRE(VALID_NMHANDLE(handle)); 2431 REQUIRE(VALID_NMSOCK(handle->sock)); 2432 2433 switch (handle->sock->type) { 2434 case isc_nm_tlssocket: 2435 return true; 2436 #if HAVE_LIBNGHTTP2 2437 case isc_nm_httpsocket: 2438 return isc__nm_http_has_encryption(handle); 2439 #endif /* HAVE_LIBNGHTTP2 */ 2440 case isc_nm_streamdnssocket: 2441 return isc__nm_streamdns_has_encryption(handle); 2442 case isc_nm_proxystreamsocket: 2443 return isc__nm_proxystream_has_encryption(handle); 2444 default: 2445 return false; 2446 }; 2447 2448 return false; 2449 } 2450 2451 const char * 2452 isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle) { 2453 isc_nmsocket_t *sock = NULL; 2454 2455 REQUIRE(VALID_NMHANDLE(handle)); 2456 REQUIRE(VALID_NMSOCK(handle->sock)); 2457 2458 sock = handle->sock; 2459 switch (sock->type) { 2460 case isc_nm_tlssocket: 2461 return isc__nm_tls_verify_tls_peer_result_string(handle); 2462 break; 2463 case isc_nm_proxystreamsocket: 2464 return isc__nm_proxystream_verify_tls_peer_result_string( 2465 handle); 2466 break; 2467 #if HAVE_LIBNGHTTP2 2468 case isc_nm_httpsocket: 2469 return isc__nm_http_verify_tls_peer_result_string(handle); 2470 break; 2471 #endif /* HAVE_LIBNGHTTP2 */ 2472 case isc_nm_streamdnssocket: 2473 return isc__nm_streamdns_verify_tls_peer_result_string(handle); 2474 break; 2475 default: 2476 break; 2477 } 2478 2479 return NULL; 2480 } 2481 2482 typedef struct settlsctx_data { 2483 isc_nmsocket_t *listener; 2484 isc_tlsctx_t *tlsctx; 2485 } settlsctx_data_t; 2486 2487 static void 2488 settlsctx_cb(void *arg) { 2489 settlsctx_data_t *data = arg; 2490 const uint32_t tid = isc_tid(); 2491 isc_nmsocket_t *listener = data->listener; 2492 isc_tlsctx_t *tlsctx = data->tlsctx; 2493 isc__networker_t *worker = &listener->worker->netmgr->workers[tid]; 2494 2495 isc_mem_put(worker->loop->mctx, data, sizeof(*data)); 2496 2497 REQUIRE(listener->type == isc_nm_tlslistener); 2498 2499 isc__nm_async_tls_set_tlsctx(listener, tlsctx, tid); 2500 2501 isc__nmsocket_detach(&listener); 2502 isc_tlsctx_free(&tlsctx); 2503 } 2504 2505 static void 2506 set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) { 2507 const size_t nworkers = 2508 (size_t)isc_loopmgr_nloops(listener->worker->netmgr->loopmgr); 2509 /* Update the TLS context reference for every worker thread. */ 2510 for (size_t i = 0; i < nworkers; i++) { 2511 isc__networker_t *worker = 2512 &listener->worker->netmgr->workers[i]; 2513 settlsctx_data_t *data = isc_mem_cget(worker->loop->mctx, 1, 2514 sizeof(*data)); 2515 2516 isc__nmsocket_attach(listener, &data->listener); 2517 isc_tlsctx_attach(tlsctx, &data->tlsctx); 2518 2519 isc_async_run(worker->loop, settlsctx_cb, data); 2520 } 2521 } 2522 2523 void 2524 isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) { 2525 REQUIRE(VALID_NMSOCK(listener)); 2526 REQUIRE(tlsctx != NULL); 2527 2528 switch (listener->type) { 2529 #if HAVE_LIBNGHTTP2 2530 case isc_nm_httplistener: 2531 /* 2532 * We handle HTTP listener sockets differently, as they rely 2533 * on underlying TLS sockets for networking. The TLS context 2534 * will get passed to these underlying sockets via the call to 2535 * isc__nm_http_set_tlsctx(). 2536 */ 2537 isc__nm_http_set_tlsctx(listener, tlsctx); 2538 break; 2539 #endif /* HAVE_LIBNGHTTP2 */ 2540 case isc_nm_tlslistener: 2541 set_tlsctx_workers(listener, tlsctx); 2542 break; 2543 case isc_nm_streamdnslistener: 2544 isc__nm_streamdns_set_tlsctx(listener, tlsctx); 2545 break; 2546 case isc_nm_proxystreamlistener: 2547 isc__nm_proxystream_set_tlsctx(listener, tlsctx); 2548 break; 2549 default: 2550 UNREACHABLE(); 2551 break; 2552 }; 2553 } 2554 2555 void 2556 isc_nmsocket_set_max_streams(isc_nmsocket_t *listener, 2557 const uint32_t max_streams) { 2558 REQUIRE(VALID_NMSOCK(listener)); 2559 switch (listener->type) { 2560 #if HAVE_LIBNGHTTP2 2561 case isc_nm_httplistener: 2562 isc__nm_http_set_max_streams(listener, max_streams); 2563 break; 2564 #endif /* HAVE_LIBNGHTTP2 */ 2565 default: 2566 UNUSED(max_streams); 2567 break; 2568 }; 2569 return; 2570 } 2571 2572 void 2573 isc__nmsocket_log_tls_session_reuse(isc_nmsocket_t *sock, isc_tls_t *tls) { 2574 const int log_level = ISC_LOG_DEBUG(1); 2575 char client_sabuf[ISC_SOCKADDR_FORMATSIZE]; 2576 char local_sabuf[ISC_SOCKADDR_FORMATSIZE]; 2577 2578 REQUIRE(tls != NULL); 2579 2580 if (!isc_log_wouldlog(isc_lctx, log_level)) { 2581 return; 2582 }; 2583 2584 isc_sockaddr_format(&sock->peer, client_sabuf, sizeof(client_sabuf)); 2585 isc_sockaddr_format(&sock->iface, local_sabuf, sizeof(local_sabuf)); 2586 isc__nmsocket_log(sock, log_level, "TLS %s session %s for %s on %s", 2587 SSL_is_server(tls) ? "server" : "client", 2588 SSL_session_reused(tls) ? "resumed" : "created", 2589 client_sabuf, local_sabuf); 2590 } 2591 2592 static void 2593 isc__networker_destroy(isc__networker_t *worker) { 2594 isc_nm_t *netmgr = worker->netmgr; 2595 worker->netmgr = NULL; 2596 2597 isc__netmgr_log(netmgr, ISC_LOG_DEBUG(1), 2598 "Destroying network manager worker on loop %p(%d)", 2599 worker->loop, isc_tid()); 2600 2601 isc_loop_detach(&worker->loop); 2602 2603 isc_mempool_destroy(&worker->uvreq_pool); 2604 isc_mempool_destroy(&worker->nmsocket_pool); 2605 2606 isc_mem_putanddetach(&worker->mctx, worker->recvbuf, 2607 ISC_NETMGR_RECVBUF_SIZE); 2608 isc_nm_detach(&netmgr); 2609 } 2610 2611 ISC_REFCOUNT_IMPL(isc__networker, isc__networker_destroy); 2612 2613 void 2614 isc__netmgr_log(const isc_nm_t *netmgr, int level, const char *fmt, ...) { 2615 char msgbuf[2048]; 2616 va_list ap; 2617 2618 if (!isc_log_wouldlog(isc_lctx, level)) { 2619 return; 2620 } 2621 2622 va_start(ap, fmt); 2623 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 2624 va_end(ap); 2625 2626 isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_NETMGR, 2627 level, "netmgr %p: %s", netmgr, msgbuf); 2628 } 2629 2630 void 2631 isc__nmsocket_log(const isc_nmsocket_t *sock, int level, const char *fmt, ...) { 2632 char msgbuf[2048]; 2633 va_list ap; 2634 2635 if (!isc_log_wouldlog(isc_lctx, level)) { 2636 return; 2637 } 2638 2639 va_start(ap, fmt); 2640 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 2641 va_end(ap); 2642 2643 isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_NETMGR, 2644 level, "socket %p: %s", sock, msgbuf); 2645 } 2646 2647 void 2648 isc__nmhandle_log(const isc_nmhandle_t *handle, int level, const char *fmt, 2649 ...) { 2650 char msgbuf[2048]; 2651 va_list ap; 2652 2653 if (!isc_log_wouldlog(isc_lctx, level)) { 2654 return; 2655 } 2656 2657 va_start(ap, fmt); 2658 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 2659 va_end(ap); 2660 2661 isc__nmsocket_log(handle->sock, level, "handle %p: %s", handle, msgbuf); 2662 } 2663 2664 void 2665 isc__nm_received_proxy_header_log(isc_nmhandle_t *handle, 2666 const isc_proxy2_command_t cmd, 2667 const int socktype, 2668 const isc_sockaddr_t *restrict src_addr, 2669 const isc_sockaddr_t *restrict dst_addr, 2670 const isc_region_t *restrict tlvs) { 2671 const int log_level = ISC_LOG_DEBUG(1); 2672 isc_sockaddr_t real_local, real_peer; 2673 char real_local_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 }; 2674 char real_peer_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 }; 2675 char common_msg[512] = { 0 }; 2676 const char *proto = NULL; 2677 const char *real_addresses_msg = 2678 "real source and destination addresses are used"; 2679 2680 if (!isc_log_wouldlog(isc_lctx, log_level)) { 2681 return; 2682 } 2683 2684 if (isc_nmhandle_is_stream(handle)) { 2685 proto = isc_nm_has_encryption(handle) ? "TLS" : "TCP"; 2686 } else { 2687 proto = "UDP"; 2688 } 2689 2690 real_local = isc_nmhandle_real_localaddr(handle); 2691 real_peer = isc_nmhandle_real_peeraddr(handle); 2692 2693 isc_sockaddr_format(&real_local, real_local_fmt, 2694 sizeof(real_local_fmt)); 2695 2696 isc_sockaddr_format(&real_peer, real_peer_fmt, sizeof(real_peer_fmt)); 2697 2698 (void)snprintf(common_msg, sizeof(common_msg), 2699 "Received a PROXYv2 header from %s on %s over %s", 2700 real_peer_fmt, real_local_fmt, proto); 2701 2702 if (cmd == ISC_PROXY2_CMD_LOCAL) { 2703 isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, 2704 ISC_LOGMODULE_NETMGR, log_level, 2705 "%s: command: LOCAL (%s)", common_msg, 2706 real_addresses_msg); 2707 return; 2708 } else if (cmd == ISC_PROXY2_CMD_PROXY) { 2709 const char *tlvs_msg = tlvs == NULL ? "no" : "yes"; 2710 const char *socktype_name = NULL; 2711 const char *src_addr_msg = "(none)", *dst_addr_msg = "(none)"; 2712 char src_addr_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 }; 2713 char dst_addr_fmt[ISC_SOCKADDR_FORMATSIZE] = { 0 }; 2714 2715 switch (socktype) { 2716 case 0: 2717 isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, 2718 ISC_LOGMODULE_NETMGR, log_level, 2719 "%s: command: PROXY (unspecified address " 2720 "and socket type, %s)", 2721 common_msg, real_addresses_msg); 2722 return; 2723 case SOCK_STREAM: 2724 socktype_name = "SOCK_STREAM"; 2725 break; 2726 case SOCK_DGRAM: 2727 socktype_name = "SOCK_DGRAM"; 2728 break; 2729 default: 2730 UNREACHABLE(); 2731 } 2732 2733 if (src_addr) { 2734 isc_sockaddr_format(src_addr, src_addr_fmt, 2735 sizeof(src_addr_fmt)); 2736 src_addr_msg = src_addr_fmt; 2737 } 2738 2739 if (dst_addr) { 2740 isc_sockaddr_format(dst_addr, dst_addr_fmt, 2741 sizeof(dst_addr_fmt)); 2742 dst_addr_msg = dst_addr_fmt; 2743 } 2744 2745 isc_log_write(isc_lctx, ISC_LOGCATEGORY_DEFAULT, 2746 ISC_LOGMODULE_NETMGR, log_level, 2747 "%s: command: PROXY, socket type: %s, source: " 2748 "%s, destination: %s, TLVs: %s", 2749 common_msg, socktype_name, src_addr_msg, 2750 dst_addr_msg, tlvs_msg); 2751 } 2752 } 2753 2754 void 2755 isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual) { 2756 REQUIRE(VALID_NMHANDLE(handle)); 2757 REQUIRE(VALID_NMSOCK(handle->sock)); 2758 2759 isc_nmsocket_t *sock = handle->sock; 2760 2761 switch (sock->type) { 2762 case isc_nm_tcpsocket: 2763 isc__nmhandle_tcp_set_manual_timer(handle, manual); 2764 return; 2765 case isc_nm_tlssocket: 2766 isc__nmhandle_tls_set_manual_timer(handle, manual); 2767 return; 2768 case isc_nm_proxystreamsocket: 2769 isc__nmhandle_proxystream_set_manual_timer(handle, manual); 2770 return; 2771 default: 2772 break; 2773 }; 2774 2775 UNREACHABLE(); 2776 } 2777 2778 void 2779 isc__nmhandle_get_selected_alpn(isc_nmhandle_t *handle, 2780 const unsigned char **alpn, 2781 unsigned int *alpnlen) { 2782 REQUIRE(VALID_NMHANDLE(handle)); 2783 REQUIRE(VALID_NMSOCK(handle->sock)); 2784 2785 isc_nmsocket_t *sock = handle->sock; 2786 2787 switch (sock->type) { 2788 case isc_nm_tlssocket: 2789 isc__nmhandle_tls_get_selected_alpn(handle, alpn, alpnlen); 2790 return; 2791 case isc_nm_proxystreamsocket: 2792 isc__nmhandle_proxystream_get_selected_alpn(handle, alpn, 2793 alpnlen); 2794 return; 2795 default: 2796 break; 2797 }; 2798 } 2799 2800 isc_result_t 2801 isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value) { 2802 REQUIRE(VALID_NMHANDLE(handle)); 2803 REQUIRE(VALID_NMSOCK(handle->sock)); 2804 2805 isc_result_t result = ISC_R_FAILURE; 2806 isc_nmsocket_t *sock = handle->sock; 2807 2808 switch (sock->type) { 2809 case isc_nm_tcpsocket: { 2810 uv_os_fd_t tcp_fd = (uv_os_fd_t)-1; 2811 (void)uv_fileno((uv_handle_t *)&sock->uv_handle.tcp, &tcp_fd); 2812 RUNTIME_CHECK(tcp_fd != (uv_os_fd_t)-1); 2813 result = isc__nm_socket_tcp_nodelay((uv_os_sock_t)tcp_fd, 2814 value); 2815 } break; 2816 case isc_nm_tlssocket: 2817 result = isc__nmhandle_tls_set_tcp_nodelay(handle, value); 2818 break; 2819 case isc_nm_proxystreamsocket: 2820 result = isc__nmhandle_proxystream_set_tcp_nodelay(handle, 2821 value); 2822 break; 2823 default: 2824 UNREACHABLE(); 2825 break; 2826 }; 2827 2828 return result; 2829 } 2830 2831 isc_sockaddr_t 2832 isc_nmsocket_getaddr(isc_nmsocket_t *sock) { 2833 REQUIRE(VALID_NMSOCK(sock)); 2834 return sock->iface; 2835 } 2836 2837 void 2838 isc_nm_proxyheader_info_init(isc_nm_proxyheader_info_t *restrict info, 2839 isc_sockaddr_t *restrict src_addr, 2840 isc_sockaddr_t *restrict dst_addr, 2841 isc_region_t *restrict tlv_data) { 2842 REQUIRE(info != NULL); 2843 REQUIRE(src_addr != NULL); 2844 REQUIRE(dst_addr != NULL); 2845 REQUIRE(tlv_data == NULL || 2846 (tlv_data->length > 0 && tlv_data->base != NULL)); 2847 2848 *info = (isc_nm_proxyheader_info_t){ .proxy_info.src_addr = *src_addr, 2849 .proxy_info.dst_addr = *dst_addr }; 2850 if (tlv_data != NULL) { 2851 info->proxy_info.tlv_data = *tlv_data; 2852 } 2853 } 2854 2855 void 2856 isc_nm_proxyheader_info_init_complete(isc_nm_proxyheader_info_t *restrict info, 2857 isc_region_t *restrict header_data) { 2858 REQUIRE(info != NULL); 2859 REQUIRE(header_data != NULL); 2860 REQUIRE(header_data->base != NULL && 2861 header_data->length >= ISC_PROXY2_HEADER_SIZE); 2862 2863 *info = (isc_nm_proxyheader_info_t){ .complete = true, 2864 .complete_header = *header_data }; 2865 } 2866 2867 void 2868 isc_netmgr_portrange(isc_nm_t *netmgr, sa_family_t af, in_port_t low, 2869 in_port_t high) { 2870 REQUIRE(VALID_NM(netmgr)); 2871 switch (af) { 2872 case AF_INET: 2873 atomic_store_relaxed(&netmgr->port_low4, low); 2874 atomic_store_relaxed(&netmgr->port_high4, high); 2875 break; 2876 case AF_INET6: 2877 atomic_store_relaxed(&netmgr->port_low6, low); 2878 atomic_store_relaxed(&netmgr->port_high6, high); 2879 break; 2880 default: 2881 UNREACHABLE(); 2882 } 2883 } 2884 2885 #if ISC_NETMGR_TRACE 2886 /* 2887 * Dump all active sockets in netmgr. We output to stderr 2888 * as the logger might be already shut down. 2889 */ 2890 2891 static const char * 2892 nmsocket_type_totext(isc_nmsocket_type type) { 2893 switch (type) { 2894 case isc_nm_udpsocket: 2895 return "isc_nm_udpsocket"; 2896 case isc_nm_udplistener: 2897 return "isc_nm_udplistener"; 2898 case isc_nm_tcpsocket: 2899 return "isc_nm_tcpsocket"; 2900 case isc_nm_tcplistener: 2901 return "isc_nm_tcplistener"; 2902 case isc_nm_tlssocket: 2903 return "isc_nm_tlssocket"; 2904 case isc_nm_tlslistener: 2905 return "isc_nm_tlslistener"; 2906 case isc_nm_httplistener: 2907 return "isc_nm_httplistener"; 2908 case isc_nm_httpsocket: 2909 return "isc_nm_httpsocket"; 2910 case isc_nm_streamdnslistener: 2911 return "isc_nm_streamdnslistener"; 2912 case isc_nm_streamdnssocket: 2913 return "isc_nm_streamdnssocket"; 2914 case isc_nm_proxystreamlistener: 2915 return "isc_nm_proxystreamlistener"; 2916 case isc_nm_proxystreamsocket: 2917 return "isc_nm_proxystreamsocket"; 2918 case isc_nm_proxyudplistener: 2919 return "isc_nm_proxyudplistener"; 2920 case isc_nm_proxyudpsocket: 2921 return "isc_nm_proxyudpsocket"; 2922 default: 2923 UNREACHABLE(); 2924 } 2925 } 2926 2927 static void 2928 nmhandle_dump(isc_nmhandle_t *handle) { 2929 fprintf(stderr, "Active handle %p, refs %" PRIuFAST32 "\n", handle, 2930 isc_refcount_current(&handle->references)); 2931 fprintf(stderr, "Created by:\n"); 2932 isc_backtrace_symbols_fd(handle->backtrace, handle->backtrace_size, 2933 STDERR_FILENO); 2934 fprintf(stderr, "\n\n"); 2935 } 2936 2937 static void 2938 nmsocket_dump(isc_nmsocket_t *sock) { 2939 isc_nmhandle_t *handle = NULL; 2940 2941 fprintf(stderr, "\n=================\n"); 2942 fprintf(stderr, "Active %s socket %p, type %s, refs %" PRIuFAST32 "\n", 2943 sock->client ? "client" : "server", sock, 2944 nmsocket_type_totext(sock->type), 2945 isc_refcount_current(&sock->references)); 2946 fprintf(stderr, 2947 "Parent %p, listener %p, server %p, statichandle = " 2948 "%p\n", 2949 sock->parent, sock->listener, sock->server, sock->statichandle); 2950 fprintf(stderr, "Flags:%s%s%s%s%s\n", sock->active ? " active" : "", 2951 sock->closing ? " closing" : "", 2952 sock->destroying ? " destroying" : "", 2953 sock->connecting ? " connecting" : "", 2954 sock->accepting ? " accepting" : ""); 2955 fprintf(stderr, "Created by:\n"); 2956 isc_backtrace_symbols_fd(sock->backtrace, sock->backtrace_size, 2957 STDERR_FILENO); 2958 fprintf(stderr, "\n"); 2959 2960 for (handle = ISC_LIST_HEAD(sock->active_handles); handle != NULL; 2961 handle = ISC_LIST_NEXT(handle, active_link)) 2962 { 2963 static bool first = true; 2964 if (first) { 2965 fprintf(stderr, "Active handles:\n"); 2966 first = false; 2967 } 2968 nmhandle_dump(handle); 2969 } 2970 2971 fprintf(stderr, "\n"); 2972 } 2973 2974 void 2975 isc__nm_dump_active(isc__networker_t *worker) { 2976 isc_nmsocket_t *sock = NULL; 2977 bool first = true; 2978 2979 for (sock = ISC_LIST_HEAD(worker->active_sockets); sock != NULL; 2980 sock = ISC_LIST_NEXT(sock, active_link)) 2981 { 2982 if (first) { 2983 fprintf(stderr, "Outstanding sockets\n"); 2984 first = false; 2985 } 2986 nmsocket_dump(sock); 2987 } 2988 } 2989 2990 void 2991 isc__nm_dump_active_manager(isc_nm_t *netmgr) { 2992 size_t i = 0; 2993 2994 for (i = 0; i < netmgr->nloops; i++) { 2995 isc__networker_t *worker = &netmgr->workers[i]; 2996 2997 if (!ISC_LIST_EMPTY(worker->active_sockets)) { 2998 fprintf(stderr, "Worker #%zu (%p)\n", i, worker); 2999 isc__nm_dump_active(worker); 3000 } 3001 } 3002 } 3003 #endif 3004