1 /* $NetBSD: dispatch.c,v 1.16 2026/06/19 20:09:59 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 /*! \file */ 17 18 #include <inttypes.h> 19 #include <stdbool.h> 20 #include <stdlib.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include <isc/async.h> 25 #include <isc/hash.h> 26 #include <isc/hashmap.h> 27 #include <isc/loop.h> 28 #include <isc/mem.h> 29 #include <isc/mutex.h> 30 #include <isc/net.h> 31 #include <isc/netmgr.h> 32 #include <isc/portset.h> 33 #include <isc/random.h> 34 #include <isc/stats.h> 35 #include <isc/string.h> 36 #include <isc/tid.h> 37 #include <isc/time.h> 38 #include <isc/tls.h> 39 #include <isc/urcu.h> 40 #include <isc/util.h> 41 42 #include <dns/acl.h> 43 #include <dns/dispatch.h> 44 #include <dns/log.h> 45 #include <dns/message.h> 46 #include <dns/stats.h> 47 #include <dns/transport.h> 48 #include <dns/types.h> 49 50 /* 51 * Maximum number of queries to pipeline on a single shared TCP dispatch. 52 * Once reached, the dispatch is removed from the hash table so new queries 53 * get a fresh connection. Can be overridden via 'named -T tcppipelining=N'. 54 */ 55 size_t dns_dispatch_tcppipelining = 256; 56 57 typedef ISC_LIST(dns_dispentry_t) dns_displist_t; 58 59 struct dns_dispatchmgr { 60 /* Unlocked. */ 61 unsigned int magic; 62 isc_refcount_t references; 63 isc_mem_t *mctx; 64 dns_acl_t *blackhole; 65 isc_stats_t *stats; 66 isc_nm_t *nm; 67 68 uint32_t nloops; 69 70 struct cds_lfht **tcps; 71 72 struct cds_lfht *qids; 73 74 in_port_t *v4ports; /*%< available ports for IPv4 */ 75 unsigned int nv4ports; /*%< # of available ports for IPv4 */ 76 in_port_t *v6ports; /*%< available ports for IPv6 */ 77 unsigned int nv6ports; /*%< # of available ports for IPv6 */ 78 }; 79 80 typedef enum { 81 DNS_DISPATCHSTATE_NONE = 0UL, 82 DNS_DISPATCHSTATE_CONNECTING, 83 DNS_DISPATCHSTATE_CONNECTED, 84 DNS_DISPATCHSTATE_CANCELED, 85 } dns_dispatchstate_t; 86 87 struct dns_dispentry { 88 unsigned int magic; 89 isc_refcount_t references; 90 isc_mem_t *mctx; 91 dns_dispatch_t *disp; 92 isc_loop_t *loop; 93 isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */ 94 dns_dispatchstate_t state; 95 dns_transport_t *transport; 96 isc_tlsctx_cache_t *tlsctx_cache; 97 unsigned int retries; 98 unsigned int timeout; 99 isc_time_t start; 100 isc_sockaddr_t local; 101 isc_sockaddr_t peer; 102 in_port_t port; 103 dns_messageid_t id; 104 dispatch_cb_t connected; 105 dispatch_cb_t sent; 106 dispatch_cb_t response; 107 void *arg; 108 bool reading; 109 isc_result_t result; 110 ISC_LINK(dns_dispentry_t) alink; 111 ISC_LINK(dns_dispentry_t) plink; 112 ISC_LINK(dns_dispentry_t) rlink; 113 114 struct cds_lfht_node ht_node; 115 struct rcu_head rcu_head; 116 }; 117 118 struct dns_dispatch { 119 /* Unlocked. */ 120 unsigned int magic; /*%< magic */ 121 uint32_t tid; 122 isc_socktype_t socktype; 123 isc_refcount_t references; 124 isc_mem_t *mctx; 125 dns_dispatchmgr_t *mgr; /*%< dispatch manager */ 126 isc_nmhandle_t *handle; /*%< netmgr handle for TCP connection */ 127 isc_sockaddr_t local; /*%< local address */ 128 isc_sockaddr_t peer; /*%< peer address (TCP) */ 129 dns_transport_t *transport; /*%< TCP transport parameters */ 130 131 dns_dispatchopt_t options; 132 dns_dispatchstate_t state; 133 dns_dispatchtype_t disptype; 134 135 dns_messageid_t nextid; /*%< next sequential QID for TCP */ 136 137 bool reading; 138 139 dns_displist_t pending; 140 dns_displist_t active; 141 142 uint_fast32_t requests; /*%< how many requests we have */ 143 144 unsigned int timedout; 145 146 struct cds_lfht_node ht_node; 147 struct rcu_head rcu_head; 148 }; 149 150 #define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p') 151 #define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC) 152 153 #define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p') 154 #define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC) 155 156 #define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r') 157 #define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC) 158 159 #if DNS_DISPATCH_TRACE 160 #define dns_dispentry_ref(ptr) \ 161 dns_dispentry__ref(ptr, __func__, __FILE__, __LINE__) 162 #define dns_dispentry_unref(ptr) \ 163 dns_dispentry__unref(ptr, __func__, __FILE__, __LINE__) 164 #define dns_dispentry_attach(ptr, ptrp) \ 165 dns_dispentry__attach(ptr, ptrp, __func__, __FILE__, __LINE__) 166 #define dns_dispentry_detach(ptrp) \ 167 dns_dispentry__detach(ptrp, __func__, __FILE__, __LINE__) 168 ISC_REFCOUNT_TRACE_DECL(dns_dispentry); 169 #else 170 ISC_REFCOUNT_DECL(dns_dispentry); 171 #endif 172 173 /* 174 * The number of attempts to find unique <addr, port, query_id> combination 175 */ 176 #define QID_MAX_TRIES 64 177 178 /* 179 * Initial and minimum QID table sizes. 180 */ 181 #define QIDS_INIT_SIZE (1 << 4) /* Must be power of 2 */ 182 #define QIDS_MIN_SIZE (1 << 4) /* Must be power of 2 */ 183 184 /* 185 * Statics. 186 */ 187 static void 188 dispatchmgr_destroy(dns_dispatchmgr_t *mgr); 189 190 static void 191 udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 192 void *arg); 193 static void 194 tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 195 void *arg); 196 static void 197 dispentry_cancel(dns_dispentry_t *resp, isc_result_t result); 198 static isc_result_t 199 dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 200 uint32_t tid, dns_dispatch_t **dispp); 201 static void 202 udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp); 203 static void 204 udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp); 205 static void 206 tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp); 207 static void 208 tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, 209 int32_t timeout); 210 static void 211 udp_dispatch_getnext(dns_dispentry_t *resp, int32_t timeout); 212 213 static const char * 214 socktype2str(dns_dispentry_t *resp) { 215 dns_transport_type_t transport_type = DNS_TRANSPORT_UDP; 216 dns_dispatch_t *disp = resp->disp; 217 218 if (disp->socktype == isc_socktype_tcp) { 219 if (resp->transport != NULL) { 220 transport_type = 221 dns_transport_get_type(resp->transport); 222 } else { 223 transport_type = DNS_TRANSPORT_TCP; 224 } 225 } 226 227 switch (transport_type) { 228 case DNS_TRANSPORT_UDP: 229 return "UDP"; 230 case DNS_TRANSPORT_TCP: 231 return "TCP"; 232 case DNS_TRANSPORT_TLS: 233 return "TLS"; 234 case DNS_TRANSPORT_HTTP: 235 return "HTTP"; 236 default: 237 return "<unexpected>"; 238 } 239 } 240 241 static const char * 242 state2str(dns_dispatchstate_t state) { 243 switch (state) { 244 case DNS_DISPATCHSTATE_NONE: 245 return "none"; 246 case DNS_DISPATCHSTATE_CONNECTING: 247 return "connecting"; 248 case DNS_DISPATCHSTATE_CONNECTED: 249 return "connected"; 250 case DNS_DISPATCHSTATE_CANCELED: 251 return "canceled"; 252 default: 253 return "<unexpected>"; 254 } 255 } 256 257 static void 258 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) 259 ISC_FORMAT_PRINTF(3, 4); 260 261 static void 262 mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) { 263 char msgbuf[2048]; 264 va_list ap; 265 266 if (!isc_log_wouldlog(dns_lctx, level)) { 267 return; 268 } 269 270 va_start(ap, fmt); 271 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 272 va_end(ap); 273 274 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH, 275 DNS_LOGMODULE_DISPATCH, level, "dispatchmgr %p: %s", mgr, 276 msgbuf); 277 } 278 279 static void 280 inc_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) { 281 if (mgr->stats != NULL) { 282 isc_stats_increment(mgr->stats, counter); 283 } 284 } 285 286 static void 287 dec_stats(dns_dispatchmgr_t *mgr, isc_statscounter_t counter) { 288 if (mgr->stats != NULL) { 289 isc_stats_decrement(mgr->stats, counter); 290 } 291 } 292 293 static void 294 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) 295 ISC_FORMAT_PRINTF(3, 4); 296 297 static void 298 dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) { 299 char msgbuf[2048]; 300 va_list ap; 301 int r; 302 303 if (!isc_log_wouldlog(dns_lctx, level)) { 304 return; 305 } 306 307 va_start(ap, fmt); 308 r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 309 if (r < 0) { 310 msgbuf[0] = '\0'; 311 } else if ((unsigned int)r >= sizeof(msgbuf)) { 312 /* Truncated */ 313 msgbuf[sizeof(msgbuf) - 1] = '\0'; 314 } 315 va_end(ap); 316 317 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH, 318 DNS_LOGMODULE_DISPATCH, level, "dispatch %p: %s", disp, 319 msgbuf); 320 } 321 322 static void 323 dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...) 324 ISC_FORMAT_PRINTF(3, 4); 325 326 static void 327 dispentry_log(dns_dispentry_t *resp, int level, const char *fmt, ...) { 328 char msgbuf[2048]; 329 va_list ap; 330 int r; 331 332 if (!isc_log_wouldlog(dns_lctx, level)) { 333 return; 334 } 335 336 va_start(ap, fmt); 337 r = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 338 if (r < 0) { 339 msgbuf[0] = '\0'; 340 } else if ((unsigned int)r >= sizeof(msgbuf)) { 341 /* Truncated */ 342 msgbuf[sizeof(msgbuf) - 1] = '\0'; 343 } 344 va_end(ap); 345 346 dispatch_log(resp->disp, level, "%s response %p: %s", 347 socktype2str(resp), resp, msgbuf); 348 } 349 350 /*% 351 * Choose a random port number for a dispatch entry. 352 */ 353 static isc_result_t 354 setup_socket(dns_dispatch_t *disp, dns_dispentry_t *resp, 355 const isc_sockaddr_t *dest, in_port_t *portp) { 356 dns_dispatchmgr_t *mgr = disp->mgr; 357 unsigned int nports; 358 in_port_t *ports = NULL; 359 in_port_t port = *portp; 360 361 if (resp->retries++ > 5) { 362 return ISC_R_FAILURE; 363 } 364 365 if (isc_sockaddr_pf(&disp->local) == AF_INET) { 366 nports = mgr->nv4ports; 367 ports = mgr->v4ports; 368 } else { 369 nports = mgr->nv6ports; 370 ports = mgr->v6ports; 371 } 372 if (nports == 0) { 373 return ISC_R_ADDRNOTAVAIL; 374 } 375 376 resp->local = disp->local; 377 resp->peer = *dest; 378 379 if (port == 0) { 380 port = ports[isc_random_uniform(nports)]; 381 isc_sockaddr_setport(&resp->local, port); 382 *portp = port; 383 } 384 resp->port = port; 385 386 return ISC_R_SUCCESS; 387 } 388 389 static uint32_t 390 qid_hash(const dns_dispentry_t *dispentry) { 391 isc_hash32_t hash; 392 393 isc_hash32_init(&hash); 394 395 isc_sockaddr_hash_ex(&hash, &dispentry->peer, true); 396 isc_hash32_hash(&hash, &dispentry->id, sizeof(dispentry->id), true); 397 isc_hash32_hash(&hash, &dispentry->port, sizeof(dispentry->port), true); 398 399 return isc_hash32_finalize(&hash); 400 } 401 402 static int 403 qid_match(struct cds_lfht_node *node, const void *key0) { 404 const dns_dispentry_t *dispentry = 405 caa_container_of(node, dns_dispentry_t, ht_node); 406 const dns_dispentry_t *key = key0; 407 408 return dispentry->id == key->id && dispentry->port == key->port && 409 isc_sockaddr_equal(&dispentry->peer, &key->peer); 410 } 411 412 static void 413 dispentry_destroy_rcu(struct rcu_head *rcu_head) { 414 dns_dispentry_t *resp = caa_container_of(rcu_head, dns_dispentry_t, 415 rcu_head); 416 isc_mem_putanddetach(&resp->mctx, resp, sizeof(*resp)); 417 } 418 419 static void 420 dispentry_destroy(dns_dispentry_t *resp) { 421 dns_dispatch_t *disp = resp->disp; 422 423 /* 424 * We need to call this from here in case there's an external event that 425 * shuts down our dispatch (like ISC_R_SHUTTINGDOWN). 426 */ 427 dispentry_cancel(resp, ISC_R_CANCELED); 428 429 INSIST(disp->requests > 0); 430 disp->requests--; 431 432 resp->magic = 0; 433 434 INSIST(!ISC_LINK_LINKED(resp, plink)); 435 INSIST(!ISC_LINK_LINKED(resp, alink)); 436 INSIST(!ISC_LINK_LINKED(resp, rlink)); 437 438 dispentry_log(resp, ISC_LOG_DEBUG(90), "destroying"); 439 440 if (resp->handle != NULL) { 441 dispentry_log(resp, ISC_LOG_DEBUG(90), 442 "detaching handle %p from %p", resp->handle, 443 &resp->handle); 444 isc_nmhandle_detach(&resp->handle); 445 } 446 447 if (resp->tlsctx_cache != NULL) { 448 isc_tlsctx_cache_detach(&resp->tlsctx_cache); 449 } 450 451 if (resp->transport != NULL) { 452 dns_transport_detach(&resp->transport); 453 } 454 455 dns_dispatch_detach(&disp); /* DISPATCH001 */ 456 457 call_rcu(&resp->rcu_head, dispentry_destroy_rcu); 458 } 459 460 #if DNS_DISPATCH_TRACE 461 ISC_REFCOUNT_TRACE_IMPL(dns_dispentry, dispentry_destroy); 462 #else 463 ISC_REFCOUNT_IMPL(dns_dispentry, dispentry_destroy); 464 #endif 465 466 /* 467 * How long in milliseconds has it been since this dispentry 468 * started reading? 469 */ 470 static unsigned int 471 dispentry_runtime(dns_dispentry_t *resp, const isc_time_t *now) { 472 if (isc_time_isepoch(&resp->start)) { 473 return 0; 474 } 475 476 return isc_time_microdiff(now, &resp->start) / 1000; 477 } 478 479 /* 480 * General flow: 481 * 482 * If I/O result == CANCELED or error, free the buffer. 483 * 484 * If query, free the buffer, restart. 485 * 486 * If response: 487 * Allocate event, fill in details. 488 * If cannot allocate, free buffer, restart. 489 * find target. If not found, free buffer, restart. 490 * if event queue is not empty, queue. else, send. 491 * restart. 492 */ 493 static void 494 udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 495 void *arg) { 496 dns_dispentry_t *resp = (dns_dispentry_t *)arg; 497 dns_dispatch_t *disp = NULL; 498 dns_messageid_t id; 499 isc_result_t dres; 500 isc_buffer_t source; 501 unsigned int flags; 502 isc_sockaddr_t peer; 503 isc_netaddr_t netaddr; 504 int match, timeout = 0; 505 bool respond = true; 506 isc_time_t now; 507 508 REQUIRE(VALID_RESPONSE(resp)); 509 REQUIRE(VALID_DISPATCH(resp->disp)); 510 511 disp = resp->disp; 512 513 REQUIRE(disp->tid == isc_tid()); 514 INSIST(resp->reading); 515 resp->reading = false; 516 517 if (resp->state == DNS_DISPATCHSTATE_CANCELED) { 518 /* 519 * Nobody is interested in the callback if the response 520 * has been canceled already. Detach from the response 521 * and the handle. 522 */ 523 respond = false; 524 eresult = ISC_R_CANCELED; 525 } 526 527 dispentry_log(resp, ISC_LOG_DEBUG(90), 528 "read callback:%s, requests %" PRIuFAST32, 529 isc_result_totext(eresult), disp->requests); 530 531 if (eresult != ISC_R_SUCCESS) { 532 /* 533 * This is most likely a network error on a connected 534 * socket, a timeout, or the query has been canceled. 535 * It makes no sense to check the address or parse the 536 * packet, but we can return the error to the caller. 537 */ 538 goto done; 539 } 540 541 peer = isc_nmhandle_peeraddr(handle); 542 isc_netaddr_fromsockaddr(&netaddr, &peer); 543 544 /* 545 * If this is from a blackholed address, drop it. 546 */ 547 if (disp->mgr->blackhole != NULL && 548 dns_acl_match(&netaddr, NULL, disp->mgr->blackhole, NULL, &match, 549 NULL) == ISC_R_SUCCESS && 550 match > 0) 551 { 552 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(10))) { 553 char netaddrstr[ISC_NETADDR_FORMATSIZE]; 554 isc_netaddr_format(&netaddr, netaddrstr, 555 sizeof(netaddrstr)); 556 dispentry_log(resp, ISC_LOG_DEBUG(10), 557 "blackholed packet from %s", netaddrstr); 558 } 559 goto next; 560 } 561 562 /* 563 * Peek into the buffer to see what we can see. 564 */ 565 id = resp->id; 566 isc_buffer_init(&source, region->base, region->length); 567 isc_buffer_add(&source, region->length); 568 dres = dns_message_peekheader(&source, &id, &flags); 569 if (dres != ISC_R_SUCCESS) { 570 char netaddrstr[ISC_NETADDR_FORMATSIZE]; 571 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr)); 572 dispentry_log(resp, ISC_LOG_DEBUG(10), 573 "got garbage packet from %s", netaddrstr); 574 goto next; 575 } 576 577 dispentry_log(resp, ISC_LOG_DEBUG(92), 578 "got valid DNS message header, /QR %c, id %u", 579 ((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id); 580 581 /* 582 * Look at the message flags. If it's a query, ignore it. 583 */ 584 if ((flags & DNS_MESSAGEFLAG_QR) == 0) { 585 goto next; 586 } 587 588 /* 589 * The QID and the address must match the expected ones. A 590 * mismatch can happen during normal operation only when a stale 591 * response from a previous query arrives late, which is rare in 592 * practice; treat any mismatch as a possible spoofing attempt and 593 * let the caller retry over TCP to prevent off-path spoofing. 594 */ 595 if (resp->id != id || !isc_sockaddr_equal(&peer, &resp->peer)) { 596 dispentry_log(resp, ISC_LOG_DEBUG(90), 597 "response doesn't match"); 598 inc_stats(disp->mgr, dns_resstatscounter_mismatch); 599 eresult = DNS_R_MISMATCH; 600 goto done; 601 } 602 603 /* 604 * We have the right resp, so call the caller back. 605 */ 606 goto done; 607 608 next: 609 /* 610 * This is the wrong response. Check whether there is still enough 611 * time to wait for the correct one to arrive before the timeout fires. 612 */ 613 now = isc_loop_now(resp->loop); 614 if (resp->timeout > 0) { 615 timeout = resp->timeout - dispentry_runtime(resp, &now); 616 if (timeout <= 0) { 617 /* 618 * The time window for receiving the correct response is 619 * already closed, libuv has just not processed the 620 * socket timer yet. Invoke the read callback, 621 * indicating a timeout. 622 */ 623 eresult = ISC_R_TIMEDOUT; 624 goto done; 625 } 626 } 627 628 /* 629 * Do not invoke the read callback just yet and instead wait for the 630 * proper response to arrive until the original timeout fires. 631 */ 632 respond = false; 633 udp_dispatch_getnext(resp, timeout); 634 635 done: 636 if (respond) { 637 dispentry_log(resp, ISC_LOG_DEBUG(90), 638 "UDP read callback on %p: %s", handle, 639 isc_result_totext(eresult)); 640 resp->response(eresult, region, resp->arg); 641 } 642 643 dns_dispentry_detach(&resp); /* DISPENTRY003 */ 644 } 645 646 static isc_result_t 647 tcp_recv_oldest(dns_dispatch_t *disp, dns_dispentry_t **respp) { 648 dns_dispentry_t *resp = NULL; 649 resp = ISC_LIST_HEAD(disp->active); 650 if (resp != NULL) { 651 disp->timedout++; 652 653 *respp = resp; 654 return ISC_R_TIMEDOUT; 655 } 656 657 return ISC_R_NOTFOUND; 658 } 659 660 static isc_result_t 661 tcp_recv_success(dns_dispatch_t *disp, isc_region_t *region, 662 dns_dispentry_t **respp) { 663 isc_buffer_t source; 664 dns_messageid_t id; 665 unsigned int flags; 666 isc_result_t result = ISC_R_SUCCESS; 667 668 dispatch_log(disp, ISC_LOG_DEBUG(90), 669 "TCP read success, length == %d, addr = %p", 670 region->length, region->base); 671 672 /* 673 * Peek into the buffer to see what we can see. 674 */ 675 isc_buffer_init(&source, region->base, region->length); 676 isc_buffer_add(&source, region->length); 677 result = dns_message_peekheader(&source, &id, &flags); 678 if (result != ISC_R_SUCCESS) { 679 dispatch_log(disp, ISC_LOG_DEBUG(10), "got garbage packet"); 680 return ISC_R_UNEXPECTED; 681 } 682 683 dispatch_log(disp, ISC_LOG_DEBUG(92), 684 "got valid DNS message header, /QR %c, id %u", 685 ((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0', id); 686 687 /* 688 * Look at the message flags. If it's a query, ignore it and keep 689 * reading. 690 */ 691 if ((flags & DNS_MESSAGEFLAG_QR) == 0) { 692 dispatch_log(disp, ISC_LOG_DEBUG(10), 693 "got DNS query instead of answer"); 694 return ISC_R_UNEXPECTED; 695 } 696 697 /* 698 * We have a valid response; find the associated dispentry by 699 * scanning disp->active. With sequential IDs and a bounded 700 * pipelining limit this is a short linear scan. 701 */ 702 dns_dispentry_t *resp = NULL, *r = NULL; 703 ISC_LIST_FOREACH(disp->active, r, alink) { 704 if (r->id == id) { 705 resp = r; 706 break; 707 } 708 } 709 710 if (resp != NULL) { 711 *respp = resp; 712 } else { 713 result = ISC_R_NOTFOUND; 714 } 715 dispatch_log(disp, ISC_LOG_DEBUG(90), "search for response: %s", 716 isc_result_totext(result)); 717 718 return result; 719 } 720 721 static void 722 tcp_recv_add(dns_displist_t *resps, dns_dispentry_t *resp, 723 isc_result_t result) { 724 dns_dispentry_ref(resp); /* DISPENTRY009 */ 725 ISC_LIST_UNLINK(resp->disp->active, resp, alink); 726 ISC_LIST_APPEND(*resps, resp, rlink); 727 INSIST(resp->reading); 728 resp->reading = false; 729 resp->result = result; 730 } 731 732 static void 733 tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps, 734 isc_result_t result) { 735 dns_dispentry_t *resp = NULL, *next = NULL; 736 737 /* 738 * If there are any active responses, shut them all down. 739 */ 740 for (resp = ISC_LIST_HEAD(disp->active); resp != NULL; resp = next) { 741 next = ISC_LIST_NEXT(resp, alink); 742 tcp_recv_add(resps, resp, result); 743 } 744 disp->state = DNS_DISPATCHSTATE_CANCELED; 745 } 746 747 static void 748 tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) { 749 dns_dispentry_t *resp = NULL, *next = NULL; 750 751 for (resp = ISC_LIST_HEAD(*resps); resp != NULL; resp = next) { 752 next = ISC_LIST_NEXT(resp, rlink); 753 ISC_LIST_UNLINK(*resps, resp, rlink); 754 755 dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s", 756 isc_result_totext(resp->result)); 757 resp->response(resp->result, region, resp->arg); 758 dns_dispentry_detach(&resp); /* DISPENTRY009 */ 759 } 760 } 761 762 /* 763 * General flow: 764 * 765 * If I/O result == CANCELED, EOF, or error, notify everyone as the 766 * various queues drain. 767 * 768 * If response: 769 * Allocate event, fill in details. 770 * If cannot allocate, restart. 771 * find target. If not found, restart. 772 * if event queue is not empty, queue. else, send. 773 * restart. 774 */ 775 static void 776 tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, 777 void *arg) { 778 dns_dispatch_t *disp = (dns_dispatch_t *)arg; 779 dns_dispentry_t *resp = NULL; 780 char buf[ISC_SOCKADDR_FORMATSIZE]; 781 isc_sockaddr_t peer; 782 dns_displist_t resps = ISC_LIST_INITIALIZER; 783 isc_time_t now; 784 int timeout = 0; 785 786 REQUIRE(VALID_DISPATCH(disp)); 787 788 REQUIRE(disp->tid == isc_tid()); 789 INSIST(disp->reading); 790 disp->reading = false; 791 792 dispatch_log(disp, ISC_LOG_DEBUG(90), 793 "TCP read:%s:requests %" PRIuFAST32, 794 isc_result_totext(result), disp->requests); 795 796 peer = isc_nmhandle_peeraddr(handle); 797 798 rcu_read_lock(); 799 /* 800 * Phase 1: Process timeout and success. 801 */ 802 switch (result) { 803 case ISC_R_TIMEDOUT: 804 /* 805 * Time out the oldest response in the active queue. 806 */ 807 result = tcp_recv_oldest(disp, &resp); 808 break; 809 case ISC_R_SUCCESS: 810 /* We got an answer */ 811 result = tcp_recv_success(disp, region, &resp); 812 break; 813 814 default: 815 break; 816 } 817 818 if (resp != NULL) { 819 tcp_recv_add(&resps, resp, result); 820 } 821 822 /* 823 * Phase 2: Look if we timed out before. 824 */ 825 826 if (result == ISC_R_NOTFOUND) { 827 if (disp->timedout > 0) { 828 /* There was active query that timed-out before */ 829 disp->timedout--; 830 } else { 831 result = ISC_R_UNEXPECTED; 832 } 833 } 834 835 /* 836 * Phase 3: Trigger timeouts. It's possible that the responses would 837 * have been timed out out already, but non-matching TCP reads have 838 * prevented this. 839 */ 840 resp = ISC_LIST_HEAD(disp->active); 841 if (resp != NULL) { 842 now = isc_loop_now(resp->loop); 843 } 844 while (resp != NULL) { 845 dns_dispentry_t *next = ISC_LIST_NEXT(resp, alink); 846 847 if (resp->timeout > 0) { 848 timeout = resp->timeout - dispentry_runtime(resp, &now); 849 if (timeout <= 0) { 850 tcp_recv_add(&resps, resp, ISC_R_TIMEDOUT); 851 } 852 } 853 854 resp = next; 855 } 856 857 /* 858 * Phase 4: log if we errored out. 859 */ 860 switch (result) { 861 case ISC_R_SUCCESS: 862 case ISC_R_TIMEDOUT: 863 case ISC_R_NOTFOUND: 864 break; 865 866 case ISC_R_SHUTTINGDOWN: 867 case ISC_R_CANCELED: 868 case ISC_R_EOF: 869 case ISC_R_CONNECTIONRESET: 870 isc_sockaddr_format(&peer, buf, sizeof(buf)); 871 dispatch_log(disp, ISC_LOG_DEBUG(90), 872 "shutting down TCP: %s: %s", buf, 873 isc_result_totext(result)); 874 tcp_recv_shutdown(disp, &resps, result); 875 break; 876 default: 877 isc_sockaddr_format(&peer, buf, sizeof(buf)); 878 dispatch_log(disp, ISC_LOG_ERROR, 879 "shutting down due to TCP " 880 "receive error: %s: %s", 881 buf, isc_result_totext(result)); 882 tcp_recv_shutdown(disp, &resps, result); 883 break; 884 } 885 886 /* 887 * Phase 5: Resume reading if there are still active responses 888 */ 889 resp = ISC_LIST_HEAD(disp->active); 890 if (resp != NULL) { 891 if (resp->timeout > 0) { 892 timeout = resp->timeout - dispentry_runtime(resp, &now); 893 INSIST(timeout > 0); 894 } 895 tcp_startrecv(disp, resp); 896 if (timeout > 0) { 897 isc_nmhandle_settimeout(handle, timeout); 898 } 899 } 900 901 rcu_read_unlock(); 902 903 /* 904 * Phase 6: Process all scheduled callbacks. 905 */ 906 tcp_recv_processall(&resps, region); 907 908 dns_dispatch_detach(&disp); /* DISPATCH002 */ 909 } 910 911 /*% 912 * Create a temporary port list to set the initial default set of dispatch 913 * ephemeral ports. This is almost meaningless as the application will 914 * normally set the ports explicitly, but is provided to fill some minor corner 915 * cases. 916 */ 917 static void 918 create_default_portset(isc_mem_t *mctx, int family, isc_portset_t **portsetp) { 919 in_port_t low, high; 920 921 isc_net_getportrange(family, &low, &high); 922 923 isc_portset_create(mctx, portsetp); 924 isc_portset_addrange(*portsetp, low, high); 925 } 926 927 static isc_result_t 928 setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, 929 isc_portset_t *v6portset) { 930 in_port_t *v4ports, *v6ports, p = 0; 931 unsigned int nv4ports, nv6ports, i4 = 0, i6 = 0; 932 933 nv4ports = isc_portset_nports(v4portset); 934 nv6ports = isc_portset_nports(v6portset); 935 936 v4ports = NULL; 937 if (nv4ports != 0) { 938 v4ports = isc_mem_cget(mgr->mctx, nv4ports, sizeof(in_port_t)); 939 } 940 v6ports = NULL; 941 if (nv6ports != 0) { 942 v6ports = isc_mem_cget(mgr->mctx, nv6ports, sizeof(in_port_t)); 943 } 944 945 do { 946 if (isc_portset_isset(v4portset, p)) { 947 INSIST(i4 < nv4ports); 948 v4ports[i4++] = p; 949 } 950 if (isc_portset_isset(v6portset, p)) { 951 INSIST(i6 < nv6ports); 952 v6ports[i6++] = p; 953 } 954 } while (p++ < 65535); 955 INSIST(i4 == nv4ports && i6 == nv6ports); 956 957 if (mgr->v4ports != NULL) { 958 isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports, 959 sizeof(in_port_t)); 960 } 961 mgr->v4ports = v4ports; 962 mgr->nv4ports = nv4ports; 963 964 if (mgr->v6ports != NULL) { 965 isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports, 966 sizeof(in_port_t)); 967 } 968 mgr->v6ports = v6ports; 969 mgr->nv6ports = nv6ports; 970 971 return ISC_R_SUCCESS; 972 } 973 974 /* 975 * Publics. 976 */ 977 978 isc_result_t 979 dns_dispatchmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t *nm, 980 dns_dispatchmgr_t **mgrp) { 981 dns_dispatchmgr_t *mgr = NULL; 982 isc_portset_t *v4portset = NULL; 983 isc_portset_t *v6portset = NULL; 984 985 REQUIRE(mctx != NULL); 986 REQUIRE(mgrp != NULL && *mgrp == NULL); 987 988 mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t)); 989 *mgr = (dns_dispatchmgr_t){ 990 .magic = 0, 991 .nloops = isc_loopmgr_nloops(loopmgr), 992 }; 993 994 #if DNS_DISPATCH_TRACE 995 fprintf(stderr, "dns_dispatchmgr__init:%s:%s:%d:%p->references = 1\n", 996 __func__, __FILE__, __LINE__, mgr); 997 #endif 998 isc_refcount_init(&mgr->references, 1); 999 1000 isc_mem_attach(mctx, &mgr->mctx); 1001 isc_nm_attach(nm, &mgr->nm); 1002 1003 mgr->tcps = isc_mem_cget(mgr->mctx, mgr->nloops, sizeof(mgr->tcps[0])); 1004 for (size_t i = 0; i < mgr->nloops; i++) { 1005 mgr->tcps[i] = cds_lfht_new( 1006 2, 2, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, 1007 NULL); 1008 } 1009 1010 create_default_portset(mgr->mctx, AF_INET, &v4portset); 1011 create_default_portset(mgr->mctx, AF_INET6, &v6portset); 1012 1013 setavailports(mgr, v4portset, v6portset); 1014 1015 isc_portset_destroy(mgr->mctx, &v4portset); 1016 isc_portset_destroy(mgr->mctx, &v6portset); 1017 1018 mgr->qids = cds_lfht_new(QIDS_INIT_SIZE, QIDS_MIN_SIZE, 0, 1019 CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, 1020 NULL); 1021 1022 mgr->magic = DNS_DISPATCHMGR_MAGIC; 1023 1024 *mgrp = mgr; 1025 return ISC_R_SUCCESS; 1026 } 1027 1028 #if DNS_DISPATCH_TRACE 1029 ISC_REFCOUNT_TRACE_IMPL(dns_dispatchmgr, dispatchmgr_destroy); 1030 #else 1031 ISC_REFCOUNT_IMPL(dns_dispatchmgr, dispatchmgr_destroy); 1032 #endif 1033 1034 void 1035 dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) { 1036 REQUIRE(VALID_DISPATCHMGR(mgr)); 1037 if (mgr->blackhole != NULL) { 1038 dns_acl_detach(&mgr->blackhole); 1039 } 1040 dns_acl_attach(blackhole, &mgr->blackhole); 1041 } 1042 1043 dns_acl_t * 1044 dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) { 1045 REQUIRE(VALID_DISPATCHMGR(mgr)); 1046 return mgr->blackhole; 1047 } 1048 1049 isc_result_t 1050 dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, 1051 isc_portset_t *v6portset) { 1052 REQUIRE(VALID_DISPATCHMGR(mgr)); 1053 return setavailports(mgr, v4portset, v6portset); 1054 } 1055 1056 static void 1057 dispatchmgr_destroy(dns_dispatchmgr_t *mgr) { 1058 REQUIRE(VALID_DISPATCHMGR(mgr)); 1059 1060 isc_refcount_destroy(&mgr->references); 1061 1062 mgr->magic = 0; 1063 1064 RUNTIME_CHECK(!cds_lfht_destroy(mgr->qids, NULL)); 1065 1066 for (size_t i = 0; i < mgr->nloops; i++) { 1067 RUNTIME_CHECK(!cds_lfht_destroy(mgr->tcps[i], NULL)); 1068 } 1069 isc_mem_cput(mgr->mctx, mgr->tcps, mgr->nloops, sizeof(mgr->tcps[0])); 1070 1071 if (mgr->blackhole != NULL) { 1072 dns_acl_detach(&mgr->blackhole); 1073 } 1074 1075 if (mgr->stats != NULL) { 1076 isc_stats_detach(&mgr->stats); 1077 } 1078 1079 if (mgr->v4ports != NULL) { 1080 isc_mem_cput(mgr->mctx, mgr->v4ports, mgr->nv4ports, 1081 sizeof(in_port_t)); 1082 } 1083 if (mgr->v6ports != NULL) { 1084 isc_mem_cput(mgr->mctx, mgr->v6ports, mgr->nv6ports, 1085 sizeof(in_port_t)); 1086 } 1087 1088 isc_nm_detach(&mgr->nm); 1089 1090 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(dns_dispatchmgr_t)); 1091 } 1092 1093 void 1094 dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) { 1095 REQUIRE(VALID_DISPATCHMGR(mgr)); 1096 REQUIRE(mgr->stats == NULL); 1097 1098 isc_stats_attach(stats, &mgr->stats); 1099 } 1100 1101 /* 1102 * Allocate and set important limits. 1103 */ 1104 static void 1105 dispatch_allocate(dns_dispatchmgr_t *mgr, isc_socktype_t type, uint32_t tid, 1106 dns_dispatch_t **dispp) { 1107 dns_dispatch_t *disp = NULL; 1108 1109 REQUIRE(VALID_DISPATCHMGR(mgr)); 1110 REQUIRE(dispp != NULL && *dispp == NULL); 1111 1112 /* 1113 * Set up the dispatcher, mostly. Don't bother setting some of 1114 * the options that are controlled by tcp vs. udp, etc. 1115 */ 1116 1117 disp = isc_mem_get(mgr->mctx, sizeof(*disp)); 1118 *disp = (dns_dispatch_t){ 1119 .socktype = type, 1120 .active = ISC_LIST_INITIALIZER, 1121 .pending = ISC_LIST_INITIALIZER, 1122 .tid = tid, 1123 .magic = DISPATCH_MAGIC, 1124 }; 1125 1126 isc_mem_attach(mgr->mctx, &disp->mctx); 1127 1128 dns_dispatchmgr_attach(mgr, &disp->mgr); 1129 #if DNS_DISPATCH_TRACE 1130 fprintf(stderr, "dns_dispatch__init:%s:%s:%d:%p->references = 1\n", 1131 __func__, __FILE__, __LINE__, disp); 1132 #endif 1133 isc_refcount_init(&disp->references, 1); /* DISPATCH000 */ 1134 1135 *dispp = disp; 1136 } 1137 1138 struct dispatch_key { 1139 const isc_sockaddr_t *local; 1140 const isc_sockaddr_t *peer; 1141 const dns_transport_t *transport; 1142 const dns_dispatchtype_t disptype; 1143 }; 1144 1145 static uint32_t 1146 dispatch_hash(struct dispatch_key *key) { 1147 isc_hash32_t hash; 1148 1149 isc_hash32_init(&hash); 1150 1151 isc_sockaddr_hash_ex(&hash, key->peer, false); 1152 if (key->local != NULL) { 1153 isc_sockaddr_hash_ex(&hash, key->local, true); 1154 } 1155 if (key->transport != NULL) { 1156 uintptr_t transport = (uintptr_t)key->transport; 1157 isc_hash32_hash(&hash, &transport, sizeof(transport), true); 1158 } 1159 isc_hash32_hash(&hash, &key->disptype, sizeof(key->disptype), true); 1160 1161 return isc_hash32_finalize(&hash); 1162 } 1163 1164 static int 1165 dispatch_match(struct cds_lfht_node *node, const void *key0) { 1166 dns_dispatch_t *disp = caa_container_of(node, dns_dispatch_t, ht_node); 1167 const struct dispatch_key *key = key0; 1168 isc_sockaddr_t local; 1169 isc_sockaddr_t peer; 1170 1171 if (disp->handle != NULL) { 1172 local = isc_nmhandle_localaddr(disp->handle); 1173 peer = isc_nmhandle_peeraddr(disp->handle); 1174 } else { 1175 local = disp->local; 1176 peer = disp->peer; 1177 } 1178 1179 return disp->disptype == key->disptype && 1180 isc_sockaddr_equal(&peer, key->peer) && 1181 disp->transport == key->transport && 1182 (key->local == NULL || isc_sockaddr_equal(&local, key->local)); 1183 } 1184 1185 static isc_result_t 1186 dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 1187 const isc_sockaddr_t *destaddr, dns_transport_t *transport, 1188 dns_dispatchtype_t disptype, dns_dispatch_t **dispp) { 1189 dns_dispatch_t *disp_connected = NULL; 1190 dns_dispatch_t *disp_fallback = NULL; 1191 isc_result_t result = ISC_R_NOTFOUND; 1192 uint32_t tid = isc_tid(); 1193 1194 REQUIRE(VALID_DISPATCHMGR(mgr)); 1195 REQUIRE(destaddr != NULL); 1196 REQUIRE(dispp != NULL && *dispp == NULL); 1197 1198 struct dispatch_key key = { 1199 .local = localaddr, 1200 .peer = destaddr, 1201 .transport = transport, 1202 .disptype = disptype, 1203 }; 1204 1205 rcu_read_lock(); 1206 struct cds_lfht_iter iter; 1207 dns_dispatch_t *disp = NULL; 1208 cds_lfht_for_each_entry_duplicate(mgr->tcps[tid], dispatch_hash(&key), 1209 dispatch_match, &key, &iter, disp, 1210 ht_node) { 1211 INSIST(disp->tid == isc_tid()); 1212 INSIST(disp->socktype == isc_socktype_tcp); 1213 1214 switch (disp->state) { 1215 case DNS_DISPATCHSTATE_NONE: 1216 /* A dispatch in indeterminate state, skip it */ 1217 break; 1218 case DNS_DISPATCHSTATE_CONNECTED: 1219 /* We found a connected dispatch */ 1220 dns_dispatch_attach(disp, &disp_connected); 1221 break; 1222 case DNS_DISPATCHSTATE_CONNECTING: 1223 /* We found "a" dispatch, store it for later */ 1224 if (disp_fallback == NULL) { 1225 dns_dispatch_attach(disp, &disp_fallback); 1226 } 1227 break; 1228 case DNS_DISPATCHSTATE_CANCELED: 1229 /* A canceled dispatch, skip it. */ 1230 break; 1231 default: 1232 UNREACHABLE(); 1233 } 1234 1235 if (disp_connected != NULL) { 1236 break; 1237 } 1238 } 1239 rcu_read_unlock(); 1240 1241 if (disp_connected != NULL) { 1242 /* We found connected dispatch */ 1243 INSIST(disp_connected->handle != NULL); 1244 1245 *dispp = disp_connected; 1246 disp_connected = NULL; 1247 1248 result = ISC_R_SUCCESS; 1249 1250 if (disp_fallback != NULL) { 1251 dns_dispatch_detach(&disp_fallback); 1252 } 1253 } else if (disp_fallback != NULL) { 1254 *dispp = disp_fallback; 1255 1256 result = ISC_R_SUCCESS; 1257 } 1258 1259 return result; 1260 } 1261 1262 static void 1263 dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 1264 const isc_sockaddr_t *destaddr, dns_transport_t *transport, 1265 dns_dispatchtype_t disptype, dns_dispatchopt_t options, 1266 dns_dispatch_t **dispp) { 1267 dns_dispatch_t *disp = NULL; 1268 uint32_t tid = isc_tid(); 1269 1270 dispatch_allocate(mgr, isc_socktype_tcp, tid, &disp); 1271 1272 disp->disptype = disptype; 1273 disp->nextid = isc_random16(); 1274 disp->options = options; 1275 disp->peer = *destaddr; 1276 if (transport != NULL) { 1277 dns_transport_attach(transport, &disp->transport); 1278 } 1279 1280 if (localaddr != NULL) { 1281 disp->local = *localaddr; 1282 } else { 1283 int pf; 1284 pf = isc_sockaddr_pf(destaddr); 1285 isc_sockaddr_anyofpf(&disp->local, pf); 1286 isc_sockaddr_setport(&disp->local, 0); 1287 } 1288 1289 /* 1290 * Append it to the dispatcher list. 1291 */ 1292 if ((options & DNS_DISPATCHOPT_FIXEDID) == 0) { 1293 struct dispatch_key key = { 1294 .local = &disp->local, 1295 .peer = &disp->peer, 1296 .transport = transport, 1297 .disptype = disptype, 1298 }; 1299 rcu_read_lock(); 1300 cds_lfht_add(mgr->tcps[tid], dispatch_hash(&key), 1301 &disp->ht_node); 1302 rcu_read_unlock(); 1303 } 1304 1305 *dispp = disp; 1306 } 1307 1308 isc_result_t 1309 dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 1310 const isc_sockaddr_t *destaddr, 1311 dns_transport_t *transport, dns_dispatchtype_t disptype, 1312 dns_dispatchopt_t options, dns_dispatch_t **dispp) { 1313 REQUIRE(VALID_DISPATCHMGR(mgr)); 1314 REQUIRE(destaddr != NULL); 1315 1316 isc_result_t result; 1317 1318 if ((options & DNS_DISPATCHOPT_FIXEDID) == 0 && 1319 disptype != DNS_DISPATCHTYPE_XFRIN) 1320 { 1321 result = dispatch_gettcp(mgr, localaddr, destaddr, transport, 1322 disptype, dispp); 1323 if (result == ISC_R_SUCCESS) { 1324 if (isc_log_wouldlog(dns_lctx, 90)) { 1325 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1326 1327 isc_sockaddr_format(&(*dispp)->local, addrbuf, 1328 ISC_SOCKADDR_FORMATSIZE); 1329 1330 mgr_log(mgr, ISC_LOG_DEBUG(90), 1331 "dns_dispatch_createtcp: reused TCP " 1332 "dispatch %p for " 1333 "%s", 1334 *dispp, addrbuf); 1335 } 1336 return result; 1337 } 1338 } 1339 1340 /* 1341 * Otherwise allocate new TCP dispatch. 1342 */ 1343 1344 dispatch_createtcp(mgr, localaddr, destaddr, transport, disptype, 1345 options, dispp); 1346 1347 if (isc_log_wouldlog(dns_lctx, 90)) { 1348 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1349 1350 isc_sockaddr_format(&(*dispp)->local, addrbuf, 1351 ISC_SOCKADDR_FORMATSIZE); 1352 1353 mgr_log(mgr, ISC_LOG_DEBUG(90), 1354 "dns_dispatch_createtcp: created TCP dispatch %p for " 1355 "%s", 1356 *dispp, addrbuf); 1357 } 1358 1359 return ISC_R_SUCCESS; 1360 } 1361 1362 isc_result_t 1363 dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 1364 dns_dispatch_t **dispp) { 1365 isc_result_t result; 1366 dns_dispatch_t *disp = NULL; 1367 1368 REQUIRE(VALID_DISPATCHMGR(mgr)); 1369 REQUIRE(localaddr != NULL); 1370 REQUIRE(dispp != NULL && *dispp == NULL); 1371 1372 result = dispatch_createudp(mgr, localaddr, isc_tid(), &disp); 1373 if (result == ISC_R_SUCCESS) { 1374 *dispp = disp; 1375 } 1376 1377 return result; 1378 } 1379 1380 static isc_result_t 1381 dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, 1382 uint32_t tid, dns_dispatch_t **dispp) { 1383 isc_result_t result = ISC_R_SUCCESS; 1384 dns_dispatch_t *disp = NULL; 1385 isc_sockaddr_t sa_any; 1386 1387 /* 1388 * Check whether this address/port is available locally. 1389 */ 1390 isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); 1391 if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { 1392 result = isc_nm_checkaddr(localaddr, isc_socktype_udp); 1393 if (result != ISC_R_SUCCESS) { 1394 return result; 1395 } 1396 } 1397 1398 dispatch_allocate(mgr, isc_socktype_udp, tid, &disp); 1399 1400 if (isc_log_wouldlog(dns_lctx, 90)) { 1401 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 1402 1403 isc_sockaddr_format(localaddr, addrbuf, 1404 ISC_SOCKADDR_FORMATSIZE); 1405 mgr_log(mgr, ISC_LOG_DEBUG(90), 1406 "dispatch_createudp: created UDP dispatch %p for %s", 1407 disp, addrbuf); 1408 } 1409 1410 disp->local = *localaddr; 1411 1412 /* 1413 * Don't append it to the dispatcher list, we don't care about UDP, only 1414 * TCP should be searched 1415 * 1416 * ISC_LIST_APPEND(mgr->list, disp, link); 1417 */ 1418 1419 *dispp = disp; 1420 1421 return result; 1422 } 1423 1424 static void 1425 dispatch_destroy_rcu(struct rcu_head *rcu_head) { 1426 dns_dispatch_t *disp = caa_container_of(rcu_head, dns_dispatch_t, 1427 rcu_head); 1428 1429 isc_mem_putanddetach(&disp->mctx, disp, sizeof(*disp)); 1430 } 1431 1432 static void 1433 dispatch_destroy(dns_dispatch_t *disp) { 1434 dns_dispatchmgr_t *mgr = disp->mgr; 1435 uint32_t tid = isc_tid(); 1436 1437 disp->magic = 0; 1438 1439 if ((disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 && 1440 disp->socktype == isc_socktype_tcp) 1441 { 1442 (void)cds_lfht_del(mgr->tcps[tid], &disp->ht_node); 1443 } 1444 1445 INSIST(disp->requests == 0); 1446 INSIST(ISC_LIST_EMPTY(disp->pending)); 1447 INSIST(ISC_LIST_EMPTY(disp->active)); 1448 1449 dispatch_log(disp, ISC_LOG_DEBUG(90), "destroying dispatch %p", disp); 1450 1451 if (disp->handle) { 1452 dispatch_log(disp, ISC_LOG_DEBUG(90), 1453 "detaching TCP handle %p from %p", disp->handle, 1454 &disp->handle); 1455 isc_nmhandle_detach(&disp->handle); 1456 } 1457 if (disp->transport != NULL) { 1458 dns_transport_detach(&disp->transport); 1459 } 1460 dns_dispatchmgr_detach(&disp->mgr); 1461 1462 call_rcu(&disp->rcu_head, dispatch_destroy_rcu); 1463 } 1464 1465 #if DNS_DISPATCH_TRACE 1466 ISC_REFCOUNT_TRACE_IMPL(dns_dispatch, dispatch_destroy); 1467 #else 1468 ISC_REFCOUNT_IMPL(dns_dispatch, dispatch_destroy); 1469 #endif 1470 1471 isc_result_t 1472 dns_dispatch_add(dns_dispatch_t *disp, isc_loop_t *loop, 1473 dns_dispatchopt_t options, unsigned int timeout, 1474 const isc_sockaddr_t *dest, dns_transport_t *transport, 1475 isc_tlsctx_cache_t *tlsctx_cache, dispatch_cb_t connected, 1476 dispatch_cb_t sent, dispatch_cb_t response, void *arg, 1477 dns_messageid_t *idp, dns_dispentry_t **respp) { 1478 REQUIRE(VALID_DISPATCH(disp)); 1479 REQUIRE(dest != NULL); 1480 REQUIRE(respp != NULL && *respp == NULL); 1481 REQUIRE(idp != NULL); 1482 REQUIRE(disp->socktype == isc_socktype_tcp || 1483 disp->socktype == isc_socktype_udp); 1484 REQUIRE(connected != NULL); 1485 REQUIRE(response != NULL); 1486 REQUIRE(sent != NULL); 1487 REQUIRE(loop != NULL); 1488 REQUIRE(disp->tid == isc_tid()); 1489 REQUIRE(disp->transport == transport); 1490 1491 if (disp->state == DNS_DISPATCHSTATE_CANCELED) { 1492 return ISC_R_CANCELED; 1493 } 1494 1495 in_port_t localport = isc_sockaddr_getport(&disp->local); 1496 dns_dispentry_t *resp = isc_mem_get(disp->mctx, sizeof(*resp)); 1497 *resp = (dns_dispentry_t){ 1498 .timeout = timeout, 1499 .port = localport, 1500 .peer = *dest, 1501 .loop = loop, 1502 .connected = connected, 1503 .sent = sent, 1504 .response = response, 1505 .arg = arg, 1506 .alink = ISC_LINK_INITIALIZER, 1507 .plink = ISC_LINK_INITIALIZER, 1508 .rlink = ISC_LINK_INITIALIZER, 1509 .magic = RESPONSE_MAGIC, 1510 }; 1511 1512 #if DNS_DISPATCH_TRACE 1513 fprintf(stderr, "dns_dispentry__init:%s:%s:%d:%p->references = 1\n", 1514 __func__, __FILE__, __LINE__, resp); 1515 #endif 1516 isc_refcount_init(&resp->references, 1); /* DISPENTRY000 */ 1517 1518 if (disp->socktype == isc_socktype_udp) { 1519 isc_result_t result = setup_socket(disp, resp, dest, 1520 &localport); 1521 if (result != ISC_R_SUCCESS) { 1522 isc_mem_put(disp->mctx, resp, sizeof(*resp)); 1523 inc_stats(disp->mgr, dns_resstatscounter_dispsockfail); 1524 return result; 1525 } 1526 } 1527 1528 isc_result_t result = ISC_R_NOMORE; 1529 rcu_read_lock(); 1530 1531 if (disp->socktype == isc_socktype_tcp) { 1532 /* 1533 * TCP dispentries don't use the global QID hash table. 1534 * Responses are matched by scanning disp->active, and 1535 * sequential per-dispatch IDs (bounded by the pipelining 1536 * limit) are guaranteed to be unique within the dispatch. 1537 * FIXEDID TCP dispatches are always fresh and isolated 1538 * (see dns_dispatch_createtcp), so the caller-supplied ID 1539 * can't collide either. 1540 */ 1541 resp->id = ((options & DNS_DISPATCHOPT_FIXEDID) != 0) 1542 ? *idp 1543 : disp->nextid++; 1544 result = ISC_R_SUCCESS; 1545 } else { 1546 size_t i = 0; 1547 do { 1548 /* 1549 * Try somewhat hard to find a unique random ID 1550 * (or use the fixed ID if DNS_DISPATCHOPT_FIXEDID 1551 * is set). 1552 */ 1553 resp->id = ((options & DNS_DISPATCHOPT_FIXEDID) != 0) 1554 ? *idp 1555 : (dns_messageid_t)isc_random16(); 1556 1557 struct cds_lfht_node *node = cds_lfht_add_unique( 1558 disp->mgr->qids, qid_hash(resp), qid_match, 1559 resp, &resp->ht_node); 1560 1561 if (node != &resp->ht_node) { 1562 if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) { 1563 /* 1564 * When using fixed ID, we either 1565 * must use it or fail. 1566 */ 1567 goto fail; 1568 } 1569 } else { 1570 result = ISC_R_SUCCESS; 1571 break; 1572 } 1573 } while (i++ < QID_MAX_TRIES); 1574 } 1575 fail: 1576 if (result != ISC_R_SUCCESS) { 1577 isc_mem_put(disp->mctx, resp, sizeof(*resp)); 1578 rcu_read_unlock(); 1579 return result; 1580 } 1581 1582 isc_mem_attach(disp->mctx, &resp->mctx); 1583 1584 if (transport != NULL) { 1585 dns_transport_attach(transport, &resp->transport); 1586 } 1587 1588 if (tlsctx_cache != NULL) { 1589 isc_tlsctx_cache_attach(tlsctx_cache, &resp->tlsctx_cache); 1590 } 1591 1592 dns_dispatch_attach(disp, &resp->disp); /* DISPATCH001 */ 1593 1594 disp->requests++; 1595 1596 /* 1597 * If this shared TCP dispatch has reached the pipelining limit, 1598 * remove it from the hash table so new queries get a fresh 1599 * connection. The dispatch continues to serve its existing 1600 * queries until they complete. 1601 */ 1602 if (disp->socktype == isc_socktype_tcp && 1603 (disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 && 1604 disp->requests >= dns_dispatch_tcppipelining) 1605 { 1606 (void)cds_lfht_del(disp->mgr->tcps[isc_tid()], &disp->ht_node); 1607 } 1608 1609 inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp) 1610 ? dns_resstatscounter_disprequdp 1611 : dns_resstatscounter_dispreqtcp); 1612 1613 rcu_read_unlock(); 1614 1615 *idp = resp->id; 1616 *respp = resp; 1617 1618 return ISC_R_SUCCESS; 1619 } 1620 1621 isc_result_t 1622 dns_dispatch_getnext(dns_dispentry_t *resp) { 1623 REQUIRE(VALID_RESPONSE(resp)); 1624 REQUIRE(VALID_DISPATCH(resp->disp)); 1625 1626 dns_dispatch_t *disp = resp->disp; 1627 isc_result_t result = ISC_R_SUCCESS; 1628 int32_t timeout = 0; 1629 1630 dispentry_log(resp, ISC_LOG_DEBUG(90), "getnext for QID %d", resp->id); 1631 1632 if (resp->timeout > 0) { 1633 isc_time_t now = isc_loop_now(resp->loop); 1634 timeout = resp->timeout - dispentry_runtime(resp, &now); 1635 if (timeout <= 0) { 1636 return ISC_R_TIMEDOUT; 1637 } 1638 } 1639 1640 REQUIRE(disp->tid == isc_tid()); 1641 switch (disp->socktype) { 1642 case isc_socktype_udp: 1643 udp_dispatch_getnext(resp, timeout); 1644 break; 1645 case isc_socktype_tcp: 1646 tcp_dispatch_getnext(disp, resp, timeout); 1647 break; 1648 default: 1649 UNREACHABLE(); 1650 } 1651 1652 return result; 1653 } 1654 1655 /* 1656 * NOTE: Must be RCU read locked! 1657 */ 1658 static void 1659 udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { 1660 REQUIRE(VALID_RESPONSE(resp)); 1661 REQUIRE(VALID_DISPATCH(resp->disp)); 1662 REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr)); 1663 1664 dns_dispatch_t *disp = resp->disp; 1665 bool respond = false; 1666 1667 REQUIRE(disp->tid == isc_tid()); 1668 dispentry_log(resp, ISC_LOG_DEBUG(90), 1669 "canceling response: %s, %s/%s (%s/%s), " 1670 "requests %" PRIuFAST32, 1671 isc_result_totext(result), state2str(resp->state), 1672 resp->reading ? "reading" : "not reading", 1673 state2str(disp->state), 1674 disp->reading ? "reading" : "not reading", 1675 disp->requests); 1676 1677 if (ISC_LINK_LINKED(resp, alink)) { 1678 ISC_LIST_UNLINK(disp->active, resp, alink); 1679 } 1680 1681 switch (resp->state) { 1682 case DNS_DISPATCHSTATE_NONE: 1683 break; 1684 1685 case DNS_DISPATCHSTATE_CONNECTING: 1686 break; 1687 1688 case DNS_DISPATCHSTATE_CONNECTED: 1689 if (resp->reading) { 1690 respond = true; 1691 dispentry_log(resp, ISC_LOG_DEBUG(90), 1692 "canceling read on %p", resp->handle); 1693 isc_nm_cancelread(resp->handle); 1694 } 1695 break; 1696 1697 case DNS_DISPATCHSTATE_CANCELED: 1698 goto unlock; 1699 1700 default: 1701 UNREACHABLE(); 1702 } 1703 1704 dec_stats(disp->mgr, dns_resstatscounter_disprequdp); 1705 1706 (void)cds_lfht_del(disp->mgr->qids, &resp->ht_node); 1707 1708 resp->state = DNS_DISPATCHSTATE_CANCELED; 1709 1710 unlock: 1711 if (respond) { 1712 dispentry_log(resp, ISC_LOG_DEBUG(90), "read callback: %s", 1713 isc_result_totext(result)); 1714 resp->response(result, NULL, resp->arg); 1715 } 1716 } 1717 1718 /* 1719 * NOTE: Must be RCU read locked! 1720 */ 1721 static void 1722 tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { 1723 REQUIRE(VALID_RESPONSE(resp)); 1724 REQUIRE(VALID_DISPATCH(resp->disp)); 1725 REQUIRE(VALID_DISPATCHMGR(resp->disp->mgr)); 1726 1727 dns_dispatch_t *disp = resp->disp; 1728 dns_displist_t resps = ISC_LIST_INITIALIZER; 1729 1730 REQUIRE(disp->tid == isc_tid()); 1731 dispentry_log(resp, ISC_LOG_DEBUG(90), 1732 "canceling response: %s, %s/%s (%s/%s), " 1733 "requests %" PRIuFAST32, 1734 isc_result_totext(result), state2str(resp->state), 1735 resp->reading ? "reading" : "not reading", 1736 state2str(disp->state), 1737 disp->reading ? "reading" : "not reading", 1738 disp->requests); 1739 1740 switch (resp->state) { 1741 case DNS_DISPATCHSTATE_NONE: 1742 break; 1743 1744 case DNS_DISPATCHSTATE_CONNECTING: 1745 break; 1746 1747 case DNS_DISPATCHSTATE_CONNECTED: 1748 if (resp->reading) { 1749 tcp_recv_add(&resps, resp, ISC_R_CANCELED); 1750 } 1751 1752 INSIST(!ISC_LINK_LINKED(resp, alink)); 1753 1754 if (ISC_LIST_EMPTY(disp->active)) { 1755 INSIST(disp->handle != NULL); 1756 1757 #if DISPATCH_TCP_KEEPALIVE 1758 /* 1759 * This is an experimental code that keeps the TCP 1760 * connection open for 1 second before it is finally 1761 * closed. By keeping the TCP connection open, it can 1762 * be reused by dns_request that uses 1763 * dns_dispatch_gettcp() to join existing TCP 1764 * connections. 1765 * 1766 * It is disabled for now, because it changes the 1767 * behaviour, but I am keeping the code here for future 1768 * reference when we improve the dns_dispatch to reuse 1769 * the TCP connections also in the resolver. 1770 * 1771 * The TCP connection reuse should be seamless and not 1772 * require any extra handling on the client side though. 1773 */ 1774 isc_nmhandle_cleartimeout(disp->handle); 1775 isc_nmhandle_settimeout(disp->handle, 1000); 1776 1777 if (!disp->reading) { 1778 dispentry_log(resp, ISC_LOG_DEBUG(90), 1779 "final 1 second timeout on %p", 1780 disp->handle); 1781 tcp_startrecv(disp, NULL); 1782 } 1783 #else 1784 if (disp->reading) { 1785 dispentry_log(resp, ISC_LOG_DEBUG(90), 1786 "canceling read on %p", 1787 disp->handle); 1788 isc_nm_cancelread(disp->handle); 1789 } 1790 #endif 1791 } 1792 break; 1793 1794 case DNS_DISPATCHSTATE_CANCELED: 1795 goto unlock; 1796 1797 default: 1798 UNREACHABLE(); 1799 } 1800 1801 dec_stats(disp->mgr, dns_resstatscounter_dispreqtcp); 1802 1803 resp->state = DNS_DISPATCHSTATE_CANCELED; 1804 1805 unlock: 1806 1807 /* 1808 * NOTE: Calling the response callback directly from here should be done 1809 * asynchronously, as the dns_dispatch_done() is usually called directly 1810 * from the response callback, so there's a slight chance that the call 1811 * stack will get higher here, but it's mitigated by the ".reading" 1812 * flag, so we don't ever go into a loop. 1813 */ 1814 1815 tcp_recv_processall(&resps, NULL); 1816 } 1817 1818 static void 1819 dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { 1820 REQUIRE(VALID_RESPONSE(resp)); 1821 REQUIRE(VALID_DISPATCH(resp->disp)); 1822 1823 dns_dispatch_t *disp = resp->disp; 1824 1825 rcu_read_lock(); 1826 switch (disp->socktype) { 1827 case isc_socktype_udp: 1828 udp_dispentry_cancel(resp, result); 1829 break; 1830 case isc_socktype_tcp: 1831 tcp_dispentry_cancel(resp, result); 1832 break; 1833 default: 1834 UNREACHABLE(); 1835 } 1836 rcu_read_unlock(); 1837 } 1838 1839 void 1840 dns_dispatch_done(dns_dispentry_t **respp) { 1841 REQUIRE(VALID_RESPONSE(*respp)); 1842 1843 dns_dispentry_t *resp = *respp; 1844 *respp = NULL; 1845 1846 dispentry_cancel(resp, ISC_R_CANCELED); 1847 dns_dispentry_detach(&resp); /* DISPENTRY000 */ 1848 } 1849 1850 static void 1851 udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp) { 1852 REQUIRE(VALID_RESPONSE(resp)); 1853 1854 dispentry_log(resp, ISC_LOG_DEBUG(90), "attaching handle %p to %p", 1855 handle, &resp->handle); 1856 isc_nmhandle_attach(handle, &resp->handle); 1857 dns_dispentry_ref(resp); /* DISPENTRY003 */ 1858 dispentry_log(resp, ISC_LOG_DEBUG(90), "reading"); 1859 isc_nm_read(resp->handle, udp_recv, resp); 1860 resp->reading = true; 1861 } 1862 1863 static void 1864 tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) { 1865 REQUIRE(VALID_DISPATCH(disp)); 1866 REQUIRE(disp->socktype == isc_socktype_tcp); 1867 1868 dns_dispatch_ref(disp); /* DISPATCH002 */ 1869 if (resp != NULL) { 1870 dispentry_log(resp, ISC_LOG_DEBUG(90), "reading from %p", 1871 disp->handle); 1872 INSIST(!isc_time_isepoch(&resp->start)); 1873 } else { 1874 dispatch_log(disp, ISC_LOG_DEBUG(90), 1875 "TCP reading without response from %p", 1876 disp->handle); 1877 } 1878 isc_nm_read(disp->handle, tcp_recv, disp); 1879 disp->reading = true; 1880 } 1881 1882 static void 1883 resp_connected(void *arg) { 1884 dns_dispentry_t *resp = arg; 1885 dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s", 1886 isc_result_totext(resp->result)); 1887 1888 resp->connected(resp->result, NULL, resp->arg); 1889 dns_dispentry_detach(&resp); /* DISPENTRY005 */ 1890 } 1891 1892 static void 1893 tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 1894 dns_dispatch_t *disp = (dns_dispatch_t *)arg; 1895 dns_dispentry_t *resp = NULL; 1896 dns_dispentry_t *next = NULL; 1897 dns_displist_t resps = ISC_LIST_INITIALIZER; 1898 1899 if (isc_log_wouldlog(dns_lctx, 90)) { 1900 char localbuf[ISC_SOCKADDR_FORMATSIZE]; 1901 char peerbuf[ISC_SOCKADDR_FORMATSIZE]; 1902 if (handle != NULL) { 1903 isc_sockaddr_t local = isc_nmhandle_localaddr(handle); 1904 isc_sockaddr_t peer = isc_nmhandle_peeraddr(handle); 1905 1906 isc_sockaddr_format(&local, localbuf, 1907 ISC_SOCKADDR_FORMATSIZE); 1908 isc_sockaddr_format(&peer, peerbuf, 1909 ISC_SOCKADDR_FORMATSIZE); 1910 } else { 1911 isc_sockaddr_format(&disp->local, localbuf, 1912 ISC_SOCKADDR_FORMATSIZE); 1913 isc_sockaddr_format(&disp->peer, peerbuf, 1914 ISC_SOCKADDR_FORMATSIZE); 1915 } 1916 1917 dispatch_log(disp, ISC_LOG_DEBUG(90), 1918 "connected from %s to %s: %s", localbuf, peerbuf, 1919 isc_result_totext(eresult)); 1920 } 1921 1922 REQUIRE(disp->tid == isc_tid()); 1923 INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING); 1924 1925 /* 1926 * If there are pending responses, call the connect 1927 * callbacks for all of them. 1928 */ 1929 for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) { 1930 next = ISC_LIST_NEXT(resp, plink); 1931 ISC_LIST_UNLINK(disp->pending, resp, plink); 1932 ISC_LIST_APPEND(resps, resp, rlink); 1933 resp->result = eresult; 1934 1935 if (resp->state == DNS_DISPATCHSTATE_CANCELED) { 1936 resp->result = ISC_R_CANCELED; 1937 } else if (eresult == ISC_R_SUCCESS) { 1938 resp->state = DNS_DISPATCHSTATE_CONNECTED; 1939 ISC_LIST_APPEND(disp->active, resp, alink); 1940 resp->reading = true; 1941 dispentry_log(resp, ISC_LOG_DEBUG(90), "start reading"); 1942 } else { 1943 resp->state = DNS_DISPATCHSTATE_NONE; 1944 } 1945 } 1946 1947 if (ISC_LIST_EMPTY(disp->active)) { 1948 /* All responses have been canceled */ 1949 disp->state = DNS_DISPATCHSTATE_CANCELED; 1950 } else if (eresult == ISC_R_SUCCESS) { 1951 disp->state = DNS_DISPATCHSTATE_CONNECTED; 1952 isc_nmhandle_attach(handle, &disp->handle); 1953 tcp_startrecv(disp, resp); 1954 } else { 1955 disp->state = DNS_DISPATCHSTATE_NONE; 1956 } 1957 1958 for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) { 1959 next = ISC_LIST_NEXT(resp, rlink); 1960 ISC_LIST_UNLINK(resps, resp, rlink); 1961 1962 resp_connected(resp); 1963 } 1964 1965 dns_dispatch_detach(&disp); /* DISPATCH003 */ 1966 } 1967 1968 static void 1969 udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 1970 dns_dispentry_t *resp = (dns_dispentry_t *)arg; 1971 dns_dispatch_t *disp = resp->disp; 1972 1973 dispentry_log(resp, ISC_LOG_DEBUG(90), "connected: %s", 1974 isc_result_totext(eresult)); 1975 1976 REQUIRE(disp->tid == isc_tid()); 1977 switch (resp->state) { 1978 case DNS_DISPATCHSTATE_CANCELED: 1979 eresult = ISC_R_CANCELED; 1980 ISC_LIST_UNLINK(disp->pending, resp, plink); 1981 goto unlock; 1982 case DNS_DISPATCHSTATE_CONNECTING: 1983 ISC_LIST_UNLINK(disp->pending, resp, plink); 1984 break; 1985 default: 1986 UNREACHABLE(); 1987 } 1988 1989 switch (eresult) { 1990 case ISC_R_CANCELED: 1991 break; 1992 case ISC_R_SUCCESS: 1993 resp->state = DNS_DISPATCHSTATE_CONNECTED; 1994 udp_startrecv(handle, resp); 1995 break; 1996 case ISC_R_NOPERM: 1997 case ISC_R_ADDRINUSE: { 1998 in_port_t localport = isc_sockaddr_getport(&disp->local); 1999 isc_result_t result; 2000 2001 /* probably a port collision; try a different one */ 2002 result = setup_socket(disp, resp, &resp->peer, &localport); 2003 if (result == ISC_R_SUCCESS) { 2004 udp_dispatch_connect(disp, resp); 2005 goto detach; 2006 } 2007 resp->state = DNS_DISPATCHSTATE_NONE; 2008 break; 2009 } 2010 default: 2011 resp->state = DNS_DISPATCHSTATE_NONE; 2012 break; 2013 } 2014 unlock: 2015 2016 dispentry_log(resp, ISC_LOG_DEBUG(90), "connect callback: %s", 2017 isc_result_totext(eresult)); 2018 resp->connected(eresult, NULL, resp->arg); 2019 2020 detach: 2021 dns_dispentry_detach(&resp); /* DISPENTRY004 */ 2022 } 2023 2024 static void 2025 udp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { 2026 REQUIRE(disp->tid == isc_tid()); 2027 resp->state = DNS_DISPATCHSTATE_CONNECTING; 2028 resp->start = isc_loop_now(resp->loop); 2029 dns_dispentry_ref(resp); /* DISPENTRY004 */ 2030 ISC_LIST_APPEND(disp->pending, resp, plink); 2031 2032 isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer, 2033 udp_connected, resp, resp->timeout); 2034 } 2035 2036 static inline const char * 2037 get_tls_sni_hostname(dns_dispentry_t *resp) { 2038 char *hostname = NULL; 2039 2040 if (resp->transport != NULL) { 2041 hostname = dns_transport_get_remote_hostname(resp->transport); 2042 } 2043 2044 if (hostname == NULL) { 2045 return NULL; 2046 } 2047 2048 if (isc_tls_valid_sni_hostname(hostname)) { 2049 return hostname; 2050 } 2051 2052 return NULL; 2053 } 2054 2055 static isc_result_t 2056 tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) { 2057 dns_transport_type_t transport_type = DNS_TRANSPORT_TCP; 2058 isc_tlsctx_t *tlsctx = NULL; 2059 isc_tlsctx_client_session_cache_t *sess_cache = NULL; 2060 2061 if (resp->transport != NULL) { 2062 transport_type = dns_transport_get_type(resp->transport); 2063 } 2064 2065 if (transport_type == DNS_TRANSPORT_TLS) { 2066 isc_result_t result; 2067 2068 result = dns_transport_get_tlsctx( 2069 resp->transport, &resp->peer, resp->tlsctx_cache, 2070 resp->mctx, &tlsctx, &sess_cache); 2071 2072 if (result != ISC_R_SUCCESS) { 2073 return result; 2074 } 2075 INSIST(tlsctx != NULL); 2076 } 2077 2078 /* Check whether the dispatch is already connecting or connected. */ 2079 REQUIRE(disp->tid == isc_tid()); 2080 switch (disp->state) { 2081 case DNS_DISPATCHSTATE_NONE: 2082 /* First connection, continue with connecting */ 2083 disp->state = DNS_DISPATCHSTATE_CONNECTING; 2084 resp->state = DNS_DISPATCHSTATE_CONNECTING; 2085 resp->start = isc_loop_now(resp->loop); 2086 dns_dispentry_ref(resp); /* DISPENTRY005 */ 2087 ISC_LIST_APPEND(disp->pending, resp, plink); 2088 2089 char localbuf[ISC_SOCKADDR_FORMATSIZE]; 2090 char peerbuf[ISC_SOCKADDR_FORMATSIZE]; 2091 2092 isc_sockaddr_format(&disp->local, localbuf, 2093 ISC_SOCKADDR_FORMATSIZE); 2094 isc_sockaddr_format(&disp->peer, peerbuf, 2095 ISC_SOCKADDR_FORMATSIZE); 2096 2097 dns_dispatch_ref(disp); /* DISPATCH003 */ 2098 dispentry_log(resp, ISC_LOG_DEBUG(90), 2099 "connecting from %s to %s, timeout %u", localbuf, 2100 peerbuf, resp->timeout); 2101 2102 const char *hostname = get_tls_sni_hostname(resp); 2103 2104 isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local, 2105 &disp->peer, tcp_connected, disp, 2106 resp->timeout, tlsctx, hostname, 2107 sess_cache, ISC_NM_PROXY_NONE, NULL); 2108 break; 2109 2110 case DNS_DISPATCHSTATE_CONNECTING: 2111 /* Connection pending; add resp to the list */ 2112 resp->state = DNS_DISPATCHSTATE_CONNECTING; 2113 resp->start = isc_loop_now(resp->loop); 2114 dns_dispentry_ref(resp); /* DISPENTRY005 */ 2115 ISC_LIST_APPEND(disp->pending, resp, plink); 2116 break; 2117 2118 case DNS_DISPATCHSTATE_CONNECTED: 2119 resp->state = DNS_DISPATCHSTATE_CONNECTED; 2120 resp->start = isc_loop_now(resp->loop); 2121 2122 /* Add the resp to the reading list */ 2123 ISC_LIST_APPEND(disp->active, resp, alink); 2124 dispentry_log(resp, ISC_LOG_DEBUG(90), 2125 "already connected; attaching"); 2126 resp->reading = true; 2127 2128 if (!disp->reading) { 2129 /* Restart the reading */ 2130 tcp_startrecv(disp, resp); 2131 } 2132 2133 /* Already connected; call the connected cb asynchronously */ 2134 dns_dispentry_ref(resp); /* DISPENTRY005 */ 2135 isc_async_run(resp->loop, resp_connected, resp); 2136 break; 2137 2138 default: 2139 UNREACHABLE(); 2140 } 2141 2142 return ISC_R_SUCCESS; 2143 } 2144 2145 isc_result_t 2146 dns_dispatch_connect(dns_dispentry_t *resp) { 2147 REQUIRE(VALID_RESPONSE(resp)); 2148 REQUIRE(VALID_DISPATCH(resp->disp)); 2149 2150 dns_dispatch_t *disp = resp->disp; 2151 2152 switch (disp->socktype) { 2153 case isc_socktype_tcp: 2154 return tcp_dispatch_connect(disp, resp); 2155 2156 case isc_socktype_udp: 2157 udp_dispatch_connect(disp, resp); 2158 return ISC_R_SUCCESS; 2159 2160 default: 2161 UNREACHABLE(); 2162 } 2163 } 2164 2165 static void 2166 send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { 2167 dns_dispentry_t *resp = (dns_dispentry_t *)cbarg; 2168 2169 REQUIRE(VALID_RESPONSE(resp)); 2170 2171 dns_dispatch_t *disp = resp->disp; 2172 2173 REQUIRE(VALID_DISPATCH(disp)); 2174 2175 dispentry_log(resp, ISC_LOG_DEBUG(90), "sent: %s", 2176 isc_result_totext(result)); 2177 2178 resp->sent(result, NULL, resp->arg); 2179 2180 if (result != ISC_R_SUCCESS) { 2181 dispentry_cancel(resp, result); 2182 } 2183 2184 dns_dispentry_detach(&resp); /* DISPENTRY007 */ 2185 isc_nmhandle_detach(&handle); 2186 } 2187 2188 static void 2189 tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, 2190 int32_t timeout) { 2191 REQUIRE(timeout <= INT16_MAX); 2192 2193 dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading"); 2194 2195 if (!resp->reading) { 2196 ISC_LIST_APPEND(disp->active, resp, alink); 2197 resp->reading = true; 2198 } 2199 2200 if (disp->reading) { 2201 return; 2202 } 2203 2204 if (timeout > 0) { 2205 isc_nmhandle_settimeout(disp->handle, timeout); 2206 } 2207 2208 dns_dispatch_ref(disp); /* DISPATCH002 */ 2209 isc_nm_read(disp->handle, tcp_recv, disp); 2210 disp->reading = true; 2211 } 2212 2213 static void 2214 udp_dispatch_getnext(dns_dispentry_t *resp, int32_t timeout) { 2215 REQUIRE(timeout <= INT16_MAX); 2216 2217 if (resp->reading) { 2218 return; 2219 } 2220 2221 if (timeout > 0) { 2222 isc_nmhandle_settimeout(resp->handle, timeout); 2223 } 2224 2225 dispentry_log(resp, ISC_LOG_DEBUG(90), "continue reading"); 2226 2227 dns_dispentry_ref(resp); /* DISPENTRY003 */ 2228 isc_nm_read(resp->handle, udp_recv, resp); 2229 resp->reading = true; 2230 } 2231 2232 void 2233 dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) { 2234 REQUIRE(VALID_RESPONSE(resp)); 2235 REQUIRE(VALID_DISPATCH(resp->disp)); 2236 2237 dns_dispatch_t *disp = resp->disp; 2238 2239 dispentry_log(resp, ISC_LOG_DEBUG(90), "resume"); 2240 2241 REQUIRE(disp->tid == isc_tid()); 2242 switch (disp->socktype) { 2243 case isc_socktype_udp: { 2244 udp_dispatch_getnext(resp, timeout); 2245 break; 2246 } 2247 case isc_socktype_tcp: 2248 INSIST(disp->timedout > 0); 2249 disp->timedout--; 2250 tcp_dispatch_getnext(disp, resp, timeout); 2251 break; 2252 default: 2253 UNREACHABLE(); 2254 } 2255 } 2256 2257 void 2258 dns_dispatch_send(dns_dispentry_t *resp, isc_region_t *r) { 2259 REQUIRE(VALID_RESPONSE(resp)); 2260 REQUIRE(VALID_DISPATCH(resp->disp)); 2261 2262 dns_dispatch_t *disp = resp->disp; 2263 isc_nmhandle_t *sendhandle = NULL; 2264 2265 dispentry_log(resp, ISC_LOG_DEBUG(90), "sending"); 2266 switch (disp->socktype) { 2267 case isc_socktype_udp: 2268 isc_nmhandle_attach(resp->handle, &sendhandle); 2269 break; 2270 case isc_socktype_tcp: 2271 isc_nmhandle_attach(disp->handle, &sendhandle); 2272 break; 2273 default: 2274 UNREACHABLE(); 2275 } 2276 dns_dispentry_ref(resp); /* DISPENTRY007 */ 2277 isc_nm_send(sendhandle, r, send_done, resp); 2278 } 2279 2280 isc_result_t 2281 dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) { 2282 REQUIRE(VALID_DISPATCH(disp)); 2283 REQUIRE(addrp != NULL); 2284 2285 if (disp->socktype == isc_socktype_udp) { 2286 *addrp = disp->local; 2287 return ISC_R_SUCCESS; 2288 } 2289 return ISC_R_NOTIMPLEMENTED; 2290 } 2291 2292 isc_result_t 2293 dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) { 2294 REQUIRE(VALID_RESPONSE(resp)); 2295 REQUIRE(VALID_DISPATCH(resp->disp)); 2296 REQUIRE(addrp != NULL); 2297 2298 dns_dispatch_t *disp = resp->disp; 2299 2300 switch (disp->socktype) { 2301 case isc_socktype_tcp: 2302 *addrp = disp->local; 2303 return ISC_R_SUCCESS; 2304 case isc_socktype_udp: 2305 *addrp = isc_nmhandle_localaddr(resp->handle); 2306 return ISC_R_SUCCESS; 2307 default: 2308 UNREACHABLE(); 2309 } 2310 } 2311 2312 dns_dispatch_t * 2313 dns_dispatchset_get(dns_dispatchset_t *dset) { 2314 uint32_t tid = isc_tid(); 2315 2316 /* check that dispatch set is configured */ 2317 if (dset == NULL || dset->ndisp == 0) { 2318 return NULL; 2319 } 2320 2321 INSIST(tid < dset->ndisp); 2322 2323 return dset->dispatches[tid]; 2324 } 2325 2326 isc_result_t 2327 dns_dispatchset_create(isc_mem_t *mctx, dns_dispatch_t *source, 2328 dns_dispatchset_t **dsetp, uint32_t ndisp) { 2329 isc_result_t result; 2330 dns_dispatchset_t *dset = NULL; 2331 dns_dispatchmgr_t *mgr = NULL; 2332 size_t i; 2333 2334 REQUIRE(VALID_DISPATCH(source)); 2335 REQUIRE(source->socktype == isc_socktype_udp); 2336 REQUIRE(dsetp != NULL && *dsetp == NULL); 2337 2338 mgr = source->mgr; 2339 2340 dset = isc_mem_get(mctx, sizeof(dns_dispatchset_t)); 2341 *dset = (dns_dispatchset_t){ .ndisp = ndisp }; 2342 2343 isc_mem_attach(mctx, &dset->mctx); 2344 2345 dset->dispatches = isc_mem_cget(dset->mctx, ndisp, 2346 sizeof(dns_dispatch_t *)); 2347 2348 dset->dispatches[0] = NULL; 2349 dns_dispatch_attach(source, &dset->dispatches[0]); /* DISPATCH004 */ 2350 2351 for (i = 1; i < dset->ndisp; i++) { 2352 result = dispatch_createudp(mgr, &source->local, i, 2353 &dset->dispatches[i]); 2354 if (result != ISC_R_SUCCESS) { 2355 goto fail; 2356 } 2357 } 2358 2359 *dsetp = dset; 2360 2361 return ISC_R_SUCCESS; 2362 2363 fail: 2364 for (size_t j = 0; j < i; j++) { 2365 dns_dispatch_detach(&(dset->dispatches[j])); /* DISPATCH004 */ 2366 } 2367 isc_mem_cput(dset->mctx, dset->dispatches, ndisp, 2368 sizeof(dns_dispatch_t *)); 2369 2370 isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t)); 2371 return result; 2372 } 2373 2374 void 2375 dns_dispatchset_destroy(dns_dispatchset_t **dsetp) { 2376 REQUIRE(dsetp != NULL && *dsetp != NULL); 2377 2378 dns_dispatchset_t *dset = *dsetp; 2379 *dsetp = NULL; 2380 2381 for (size_t i = 0; i < dset->ndisp; i++) { 2382 dns_dispatch_detach(&(dset->dispatches[i])); /* DISPATCH004 */ 2383 } 2384 isc_mem_cput(dset->mctx, dset->dispatches, dset->ndisp, 2385 sizeof(dns_dispatch_t *)); 2386 isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t)); 2387 } 2388 2389 isc_result_t 2390 dns_dispatch_checkperm(dns_dispatch_t *disp) { 2391 REQUIRE(VALID_DISPATCH(disp)); 2392 2393 if (disp->handle == NULL || disp->socktype == isc_socktype_udp) { 2394 return ISC_R_NOPERM; 2395 } 2396 2397 return isc_nm_xfr_checkperm(disp->handle); 2398 } 2399