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