1 /* $NetBSD: request.c,v 1.6 2022/09/23 12:15:30 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 21 #include <isc/magic.h> 22 #include <isc/mem.h> 23 #include <isc/task.h> 24 #include <isc/timer.h> 25 #include <isc/util.h> 26 27 #include <dns/acl.h> 28 #include <dns/compress.h> 29 #include <dns/dispatch.h> 30 #include <dns/events.h> 31 #include <dns/log.h> 32 #include <dns/message.h> 33 #include <dns/rdata.h> 34 #include <dns/rdatastruct.h> 35 #include <dns/request.h> 36 #include <dns/result.h> 37 #include <dns/tsig.h> 38 39 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M') 40 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC) 41 42 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!') 43 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC) 44 45 typedef ISC_LIST(dns_request_t) dns_requestlist_t; 46 47 #define DNS_REQUEST_NLOCKS 7 48 49 struct dns_requestmgr { 50 unsigned int magic; 51 isc_mutex_t lock; 52 isc_mem_t *mctx; 53 54 /* locked */ 55 int32_t eref; 56 int32_t iref; 57 isc_timermgr_t *timermgr; 58 isc_socketmgr_t *socketmgr; 59 isc_taskmgr_t *taskmgr; 60 dns_dispatchmgr_t *dispatchmgr; 61 dns_dispatch_t *dispatchv4; 62 dns_dispatch_t *dispatchv6; 63 bool exiting; 64 isc_eventlist_t whenshutdown; 65 unsigned int hash; 66 isc_mutex_t locks[DNS_REQUEST_NLOCKS]; 67 dns_requestlist_t requests; 68 }; 69 70 struct dns_request { 71 unsigned int magic; 72 unsigned int hash; 73 isc_mem_t *mctx; 74 int32_t flags; 75 ISC_LINK(dns_request_t) link; 76 isc_buffer_t *query; 77 isc_buffer_t *answer; 78 dns_requestevent_t *event; 79 dns_dispatch_t *dispatch; 80 dns_dispentry_t *dispentry; 81 isc_timer_t *timer; 82 dns_requestmgr_t *requestmgr; 83 isc_buffer_t *tsig; 84 dns_tsigkey_t *tsigkey; 85 isc_event_t ctlevent; 86 bool canceling; /* ctlevent outstanding */ 87 isc_sockaddr_t destaddr; 88 unsigned int udpcount; 89 isc_dscp_t dscp; 90 }; 91 92 #define DNS_REQUEST_F_CONNECTING 0x0001 93 #define DNS_REQUEST_F_SENDING 0x0002 94 #define DNS_REQUEST_F_CANCELED \ 95 0x0004 /*%< ctlevent received, or otherwise \ 96 * synchronously canceled */ 97 #define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */ 98 #define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */ 99 #define DNS_REQUEST_CANCELED(r) (((r)->flags & DNS_REQUEST_F_CANCELED) != 0) 100 #define DNS_REQUEST_CONNECTING(r) (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0) 101 #define DNS_REQUEST_SENDING(r) (((r)->flags & DNS_REQUEST_F_SENDING) != 0) 102 #define DNS_REQUEST_TIMEDOUT(r) (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0) 103 104 /*** 105 *** Forward 106 ***/ 107 108 static void 109 mgr_destroy(dns_requestmgr_t *requestmgr); 110 static void 111 mgr_shutdown(dns_requestmgr_t *requestmgr); 112 static unsigned int 113 mgr_gethash(dns_requestmgr_t *requestmgr); 114 static void 115 send_shutdown_events(dns_requestmgr_t *requestmgr); 116 117 static isc_result_t 118 req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options, 119 isc_mem_t *mctx); 120 static void 121 req_senddone(isc_task_t *task, isc_event_t *event); 122 static void 123 req_response(isc_task_t *task, isc_event_t *event); 124 static void 125 req_timeout(isc_task_t *task, isc_event_t *event); 126 static isc_socket_t * 127 req_getsocket(dns_request_t *request); 128 static void 129 req_connected(isc_task_t *task, isc_event_t *event); 130 static void 131 req_sendevent(dns_request_t *request, isc_result_t result); 132 static void 133 req_cancel(dns_request_t *request); 134 static void 135 req_destroy(dns_request_t *request); 136 static void 137 req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 138 static void 139 do_cancel(isc_task_t *task, isc_event_t *event); 140 141 /*** 142 *** Public 143 ***/ 144 145 isc_result_t 146 dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, 147 isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, 148 dns_dispatchmgr_t *dispatchmgr, 149 dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, 150 dns_requestmgr_t **requestmgrp) { 151 dns_requestmgr_t *requestmgr; 152 int i; 153 unsigned int dispattr; 154 155 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create"); 156 157 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL); 158 REQUIRE(timermgr != NULL); 159 REQUIRE(socketmgr != NULL); 160 REQUIRE(taskmgr != NULL); 161 REQUIRE(dispatchmgr != NULL); 162 163 if (dispatchv4 != NULL) { 164 dispattr = dns_dispatch_getattributes(dispatchv4); 165 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); 166 } 167 if (dispatchv6 != NULL) { 168 dispattr = dns_dispatch_getattributes(dispatchv6); 169 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); 170 } 171 172 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr)); 173 174 isc_mutex_init(&requestmgr->lock); 175 176 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { 177 isc_mutex_init(&requestmgr->locks[i]); 178 } 179 requestmgr->timermgr = timermgr; 180 requestmgr->socketmgr = socketmgr; 181 requestmgr->taskmgr = taskmgr; 182 requestmgr->dispatchmgr = dispatchmgr; 183 requestmgr->dispatchv4 = NULL; 184 if (dispatchv4 != NULL) { 185 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4); 186 } 187 requestmgr->dispatchv6 = NULL; 188 if (dispatchv6 != NULL) { 189 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6); 190 } 191 requestmgr->mctx = NULL; 192 isc_mem_attach(mctx, &requestmgr->mctx); 193 requestmgr->eref = 1; /* implicit attach */ 194 requestmgr->iref = 0; 195 ISC_LIST_INIT(requestmgr->whenshutdown); 196 ISC_LIST_INIT(requestmgr->requests); 197 requestmgr->exiting = false; 198 requestmgr->hash = 0; 199 requestmgr->magic = REQUESTMGR_MAGIC; 200 201 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr); 202 203 *requestmgrp = requestmgr; 204 return (ISC_R_SUCCESS); 205 } 206 207 void 208 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task, 209 isc_event_t **eventp) { 210 isc_task_t *tclone; 211 isc_event_t *event; 212 213 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown"); 214 215 REQUIRE(VALID_REQUESTMGR(requestmgr)); 216 REQUIRE(eventp != NULL); 217 218 event = *eventp; 219 *eventp = NULL; 220 221 LOCK(&requestmgr->lock); 222 223 if (requestmgr->exiting) { 224 /* 225 * We're already shutdown. Send the event. 226 */ 227 event->ev_sender = requestmgr; 228 isc_task_send(task, &event); 229 } else { 230 tclone = NULL; 231 isc_task_attach(task, &tclone); 232 event->ev_sender = tclone; 233 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link); 234 } 235 UNLOCK(&requestmgr->lock); 236 } 237 238 void 239 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) { 240 REQUIRE(VALID_REQUESTMGR(requestmgr)); 241 242 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr); 243 244 LOCK(&requestmgr->lock); 245 mgr_shutdown(requestmgr); 246 UNLOCK(&requestmgr->lock); 247 } 248 249 static void 250 mgr_shutdown(dns_requestmgr_t *requestmgr) { 251 dns_request_t *request; 252 253 /* 254 * Caller holds lock. 255 */ 256 if (!requestmgr->exiting) { 257 requestmgr->exiting = true; 258 for (request = ISC_LIST_HEAD(requestmgr->requests); 259 request != NULL; request = ISC_LIST_NEXT(request, link)) 260 { 261 dns_request_cancel(request); 262 } 263 if (requestmgr->iref == 0) { 264 INSIST(ISC_LIST_EMPTY(requestmgr->requests)); 265 send_shutdown_events(requestmgr); 266 } 267 } 268 } 269 270 static void 271 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { 272 /* 273 * Locked by caller. 274 */ 275 276 REQUIRE(VALID_REQUESTMGR(source)); 277 REQUIRE(targetp != NULL && *targetp == NULL); 278 279 REQUIRE(!source->exiting); 280 281 source->iref++; 282 *targetp = source; 283 284 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d", 285 source, source->eref, source->iref); 286 } 287 288 static void 289 requestmgr_detach(dns_requestmgr_t **requestmgrp) { 290 dns_requestmgr_t *requestmgr; 291 bool need_destroy = false; 292 293 REQUIRE(requestmgrp != NULL); 294 requestmgr = *requestmgrp; 295 *requestmgrp = NULL; 296 REQUIRE(VALID_REQUESTMGR(requestmgr)); 297 298 LOCK(&requestmgr->lock); 299 INSIST(requestmgr->iref > 0); 300 requestmgr->iref--; 301 302 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d", 303 requestmgr, requestmgr->eref, requestmgr->iref); 304 305 if (requestmgr->iref == 0 && requestmgr->exiting) { 306 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL); 307 send_shutdown_events(requestmgr); 308 if (requestmgr->eref == 0) { 309 need_destroy = true; 310 } 311 } 312 UNLOCK(&requestmgr->lock); 313 314 if (need_destroy) { 315 mgr_destroy(requestmgr); 316 } 317 } 318 319 void 320 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { 321 REQUIRE(VALID_REQUESTMGR(source)); 322 REQUIRE(targetp != NULL && *targetp == NULL); 323 REQUIRE(!source->exiting); 324 325 LOCK(&source->lock); 326 source->eref++; 327 *targetp = source; 328 UNLOCK(&source->lock); 329 330 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d", 331 source, source->eref, source->iref); 332 } 333 334 void 335 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) { 336 dns_requestmgr_t *requestmgr; 337 bool need_destroy = false; 338 339 REQUIRE(requestmgrp != NULL); 340 requestmgr = *requestmgrp; 341 *requestmgrp = NULL; 342 REQUIRE(VALID_REQUESTMGR(requestmgr)); 343 344 LOCK(&requestmgr->lock); 345 INSIST(requestmgr->eref > 0); 346 requestmgr->eref--; 347 348 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d", 349 requestmgr, requestmgr->eref, requestmgr->iref); 350 351 if (requestmgr->eref == 0 && requestmgr->iref == 0) { 352 INSIST(requestmgr->exiting && 353 ISC_LIST_HEAD(requestmgr->requests) == NULL); 354 need_destroy = true; 355 } 356 UNLOCK(&requestmgr->lock); 357 358 if (need_destroy) { 359 mgr_destroy(requestmgr); 360 } 361 } 362 363 static void 364 send_shutdown_events(dns_requestmgr_t *requestmgr) { 365 isc_event_t *event, *next_event; 366 isc_task_t *etask; 367 368 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr); 369 370 /* 371 * Caller must be holding the manager lock. 372 */ 373 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown); event != NULL; 374 event = next_event) 375 { 376 next_event = ISC_LIST_NEXT(event, ev_link); 377 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link); 378 etask = event->ev_sender; 379 event->ev_sender = requestmgr; 380 isc_task_sendanddetach(&etask, &event); 381 } 382 } 383 384 static void 385 mgr_destroy(dns_requestmgr_t *requestmgr) { 386 int i; 387 388 req_log(ISC_LOG_DEBUG(3), "mgr_destroy"); 389 390 REQUIRE(requestmgr->eref == 0); 391 REQUIRE(requestmgr->iref == 0); 392 393 isc_mutex_destroy(&requestmgr->lock); 394 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { 395 isc_mutex_destroy(&requestmgr->locks[i]); 396 } 397 if (requestmgr->dispatchv4 != NULL) { 398 dns_dispatch_detach(&requestmgr->dispatchv4); 399 } 400 if (requestmgr->dispatchv6 != NULL) { 401 dns_dispatch_detach(&requestmgr->dispatchv6); 402 } 403 requestmgr->magic = 0; 404 isc_mem_putanddetach(&requestmgr->mctx, requestmgr, 405 sizeof(*requestmgr)); 406 } 407 408 static unsigned int 409 mgr_gethash(dns_requestmgr_t *requestmgr) { 410 req_log(ISC_LOG_DEBUG(3), "mgr_gethash"); 411 /* 412 * Locked by caller. 413 */ 414 requestmgr->hash++; 415 return (requestmgr->hash % DNS_REQUEST_NLOCKS); 416 } 417 418 static isc_result_t 419 req_send(dns_request_t *request, isc_task_t *task, 420 const isc_sockaddr_t *address) { 421 isc_region_t r; 422 isc_socket_t *sock; 423 isc_socketevent_t *sendevent; 424 isc_result_t result; 425 426 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request); 427 428 REQUIRE(VALID_REQUEST(request)); 429 sock = req_getsocket(request); 430 isc_buffer_usedregion(request->query, &r); 431 /* 432 * We could connect the socket when we are using an exclusive dispatch 433 * as we do in resolver.c, but we prefer implementation simplicity 434 * at this moment. 435 */ 436 sendevent = isc_socket_socketevent(request->mctx, sock, 437 ISC_SOCKEVENT_SENDDONE, req_senddone, 438 request); 439 if (sendevent == NULL) { 440 return (ISC_R_NOMEMORY); 441 } 442 if (request->dscp == -1) { 443 sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP; 444 sendevent->dscp = 0; 445 } else { 446 sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP; 447 sendevent->dscp = request->dscp; 448 } 449 450 request->flags |= DNS_REQUEST_F_SENDING; 451 result = isc_socket_sendto2(sock, &r, task, address, NULL, sendevent, 452 0); 453 INSIST(result == ISC_R_SUCCESS); 454 return (result); 455 } 456 457 static isc_result_t 458 new_request(isc_mem_t *mctx, dns_request_t **requestp) { 459 dns_request_t *request; 460 461 request = isc_mem_get(mctx, sizeof(*request)); 462 463 /* 464 * Zero structure. 465 */ 466 request->magic = 0; 467 request->mctx = NULL; 468 request->flags = 0; 469 ISC_LINK_INIT(request, link); 470 request->query = NULL; 471 request->answer = NULL; 472 request->event = NULL; 473 request->dispatch = NULL; 474 request->dispentry = NULL; 475 request->timer = NULL; 476 request->requestmgr = NULL; 477 request->tsig = NULL; 478 request->tsigkey = NULL; 479 request->dscp = -1; 480 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL, 481 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL, 482 NULL); 483 request->canceling = false; 484 request->udpcount = 0; 485 486 isc_mem_attach(mctx, &request->mctx); 487 488 request->magic = REQUEST_MAGIC; 489 *requestp = request; 490 return (ISC_R_SUCCESS); 491 } 492 493 static bool 494 isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) { 495 dns_acl_t *blackhole; 496 isc_netaddr_t netaddr; 497 int match; 498 bool drop = false; 499 char netaddrstr[ISC_NETADDR_FORMATSIZE]; 500 501 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr); 502 if (blackhole != NULL) { 503 isc_netaddr_fromsockaddr(&netaddr, destaddr); 504 if (dns_acl_match(&netaddr, NULL, blackhole, NULL, &match, 505 NULL) == ISC_R_SUCCESS && 506 match > 0) 507 { 508 drop = true; 509 } 510 } 511 if (drop) { 512 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr)); 513 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr); 514 } 515 return (drop); 516 } 517 518 static isc_result_t 519 create_tcp_dispatch(bool newtcp, bool share, dns_requestmgr_t *requestmgr, 520 const isc_sockaddr_t *srcaddr, 521 const isc_sockaddr_t *destaddr, isc_dscp_t dscp, 522 bool *connected, dns_dispatch_t **dispatchp) { 523 isc_result_t result; 524 isc_socket_t *sock = NULL; 525 isc_sockaddr_t src; 526 unsigned int attrs; 527 isc_sockaddr_t bind_any; 528 529 if (!newtcp && share) { 530 result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, 531 srcaddr, connected, dispatchp); 532 if (result == ISC_R_SUCCESS) { 533 char peer[ISC_SOCKADDR_FORMATSIZE]; 534 535 isc_sockaddr_format(destaddr, peer, sizeof(peer)); 536 req_log(ISC_LOG_DEBUG(1), 537 "attached to %s TCP " 538 "connection to %s", 539 *connected ? "existing" : "pending", peer); 540 return (result); 541 } 542 } else if (!newtcp) { 543 result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, 544 srcaddr, NULL, dispatchp); 545 if (result == ISC_R_SUCCESS) { 546 char peer[ISC_SOCKADDR_FORMATSIZE]; 547 548 *connected = true; 549 isc_sockaddr_format(destaddr, peer, sizeof(peer)); 550 req_log(ISC_LOG_DEBUG(1), 551 "attached to existing TCP " 552 "connection to %s", 553 peer); 554 return (result); 555 } 556 } 557 558 result = isc_socket_create(requestmgr->socketmgr, 559 isc_sockaddr_pf(destaddr), 560 isc_sockettype_tcp, &sock); 561 if (result != ISC_R_SUCCESS) { 562 return (result); 563 } 564 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT 565 if (srcaddr == NULL) { 566 isc_sockaddr_anyofpf(&bind_any, isc_sockaddr_pf(destaddr)); 567 result = isc_socket_bind(sock, &bind_any, 0); 568 } else { 569 src = *srcaddr; 570 isc_sockaddr_setport(&src, 0); 571 result = isc_socket_bind(sock, &src, 0); 572 } 573 if (result != ISC_R_SUCCESS) { 574 goto cleanup; 575 } 576 #endif /* ifndef BROKEN_TCP_BIND_BEFORE_CONNECT */ 577 578 attrs = 0; 579 attrs |= DNS_DISPATCHATTR_TCP; 580 if (isc_sockaddr_pf(destaddr) == AF_INET) { 581 attrs |= DNS_DISPATCHATTR_IPV4; 582 } else { 583 attrs |= DNS_DISPATCHATTR_IPV6; 584 } 585 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 586 587 isc_socket_dscp(sock, dscp); 588 result = dns_dispatch_createtcp( 589 requestmgr->dispatchmgr, sock, requestmgr->taskmgr, srcaddr, 590 destaddr, 4096, 32768, 32768, 16411, 16433, attrs, dispatchp); 591 cleanup: 592 isc_socket_detach(&sock); 593 return (result); 594 } 595 596 static isc_result_t 597 find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, 598 const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) { 599 dns_dispatch_t *disp = NULL; 600 unsigned int attrs, attrmask; 601 602 if (srcaddr == NULL) { 603 switch (isc_sockaddr_pf(destaddr)) { 604 case PF_INET: 605 disp = requestmgr->dispatchv4; 606 break; 607 608 case PF_INET6: 609 disp = requestmgr->dispatchv6; 610 break; 611 612 default: 613 return (ISC_R_NOTIMPLEMENTED); 614 } 615 if (disp == NULL) { 616 return (ISC_R_FAMILYNOSUPPORT); 617 } 618 dns_dispatch_attach(disp, dispatchp); 619 return (ISC_R_SUCCESS); 620 } 621 attrs = 0; 622 attrs |= DNS_DISPATCHATTR_UDP; 623 switch (isc_sockaddr_pf(srcaddr)) { 624 case PF_INET: 625 attrs |= DNS_DISPATCHATTR_IPV4; 626 break; 627 628 case PF_INET6: 629 attrs |= DNS_DISPATCHATTR_IPV6; 630 break; 631 632 default: 633 return (ISC_R_NOTIMPLEMENTED); 634 } 635 attrmask = 0; 636 attrmask |= DNS_DISPATCHATTR_UDP; 637 attrmask |= DNS_DISPATCHATTR_TCP; 638 attrmask |= DNS_DISPATCHATTR_IPV4; 639 attrmask |= DNS_DISPATCHATTR_IPV6; 640 return (dns_dispatch_getudp(requestmgr->dispatchmgr, 641 requestmgr->socketmgr, requestmgr->taskmgr, 642 srcaddr, 4096, 32768, 32768, 16411, 16433, 643 attrs, attrmask, dispatchp)); 644 } 645 646 static isc_result_t 647 get_dispatch(bool tcp, bool newtcp, bool share, dns_requestmgr_t *requestmgr, 648 const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, 649 isc_dscp_t dscp, bool *connected, dns_dispatch_t **dispatchp) { 650 isc_result_t result; 651 652 if (tcp) { 653 result = create_tcp_dispatch(newtcp, share, requestmgr, srcaddr, 654 destaddr, dscp, connected, 655 dispatchp); 656 } else { 657 result = find_udp_dispatch(requestmgr, srcaddr, destaddr, 658 dispatchp); 659 } 660 return (result); 661 } 662 663 static isc_result_t 664 set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) { 665 isc_time_t expires; 666 isc_interval_t interval; 667 isc_result_t result; 668 isc_timertype_t timertype; 669 670 isc_interval_set(&interval, timeout, 0); 671 result = isc_time_nowplusinterval(&expires, &interval); 672 isc_interval_set(&interval, udpresend, 0); 673 674 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once; 675 if (result == ISC_R_SUCCESS) { 676 result = isc_timer_reset(timer, timertype, &expires, &interval, 677 false); 678 } 679 return (result); 680 } 681 682 isc_result_t 683 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, 684 const isc_sockaddr_t *srcaddr, 685 const isc_sockaddr_t *destaddr, isc_dscp_t dscp, 686 unsigned int options, unsigned int timeout, 687 unsigned int udptimeout, unsigned int udpretries, 688 isc_task_t *task, isc_taskaction_t action, void *arg, 689 dns_request_t **requestp) { 690 dns_request_t *request = NULL; 691 isc_task_t *tclone = NULL; 692 isc_socket_t *sock = NULL; 693 isc_result_t result; 694 isc_mem_t *mctx; 695 dns_messageid_t id; 696 bool tcp = false; 697 bool newtcp = false; 698 bool share = false; 699 isc_region_t r; 700 bool connected = false; 701 unsigned int dispopt = 0; 702 703 REQUIRE(VALID_REQUESTMGR(requestmgr)); 704 REQUIRE(msgbuf != NULL); 705 REQUIRE(destaddr != NULL); 706 REQUIRE(task != NULL); 707 REQUIRE(action != NULL); 708 REQUIRE(requestp != NULL && *requestp == NULL); 709 REQUIRE(timeout > 0); 710 if (srcaddr != NULL) { 711 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr)); 712 } 713 714 mctx = requestmgr->mctx; 715 716 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw"); 717 718 if (isblackholed(requestmgr->dispatchmgr, destaddr)) { 719 return (DNS_R_BLACKHOLED); 720 } 721 722 request = NULL; 723 result = new_request(mctx, &request); 724 if (result != ISC_R_SUCCESS) { 725 return (result); 726 } 727 728 if (udptimeout == 0 && udpretries != 0) { 729 udptimeout = timeout / (udpretries + 1); 730 if (udptimeout == 0) { 731 udptimeout = 1; 732 } 733 } 734 request->udpcount = udpretries; 735 request->dscp = dscp; 736 737 /* 738 * Create timer now. We will set it below once. 739 */ 740 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, 741 NULL, NULL, task, req_timeout, request, 742 &request->timer); 743 if (result != ISC_R_SUCCESS) { 744 goto cleanup; 745 } 746 747 request->event = (dns_requestevent_t *)isc_event_allocate( 748 mctx, task, DNS_EVENT_REQUESTDONE, action, arg, 749 sizeof(dns_requestevent_t)); 750 isc_task_attach(task, &tclone); 751 request->event->ev_sender = task; 752 request->event->request = request; 753 request->event->result = ISC_R_FAILURE; 754 755 isc_buffer_usedregion(msgbuf, &r); 756 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) { 757 result = DNS_R_FORMERR; 758 goto cleanup; 759 } 760 761 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) { 762 tcp = true; 763 } 764 share = (options & DNS_REQUESTOPT_SHARE); 765 766 again: 767 result = get_dispatch(tcp, newtcp, share, requestmgr, srcaddr, destaddr, 768 dscp, &connected, &request->dispatch); 769 if (result != ISC_R_SUCCESS) { 770 goto cleanup; 771 } 772 773 if ((options & DNS_REQUESTOPT_FIXEDID) != 0) { 774 id = (r.base[0] << 8) | r.base[1]; 775 dispopt |= DNS_DISPATCHOPT_FIXEDID; 776 } 777 778 result = dns_dispatch_addresponse( 779 request->dispatch, dispopt, destaddr, task, req_response, 780 request, &id, &request->dispentry, requestmgr->socketmgr); 781 if (result != ISC_R_SUCCESS) { 782 if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) { 783 newtcp = true; 784 connected = false; 785 dns_dispatch_detach(&request->dispatch); 786 goto again; 787 } 788 goto cleanup; 789 } 790 791 sock = req_getsocket(request); 792 INSIST(sock != NULL); 793 794 isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); 795 if (tcp) { 796 isc_buffer_putuint16(request->query, (uint16_t)r.length); 797 } 798 result = isc_buffer_copyregion(request->query, &r); 799 if (result != ISC_R_SUCCESS) { 800 goto cleanup; 801 } 802 803 /* Add message ID. */ 804 isc_buffer_usedregion(request->query, &r); 805 if (tcp) { 806 isc_region_consume(&r, 2); 807 } 808 r.base[0] = (id >> 8) & 0xff; 809 r.base[1] = id & 0xff; 810 811 LOCK(&requestmgr->lock); 812 if (requestmgr->exiting) { 813 UNLOCK(&requestmgr->lock); 814 result = ISC_R_SHUTTINGDOWN; 815 goto cleanup; 816 } 817 requestmgr_attach(requestmgr, &request->requestmgr); 818 request->hash = mgr_gethash(requestmgr); 819 ISC_LIST_APPEND(requestmgr->requests, request, link); 820 UNLOCK(&requestmgr->lock); 821 822 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); 823 if (result != ISC_R_SUCCESS) { 824 goto unlink; 825 } 826 827 request->destaddr = *destaddr; 828 if (tcp && !connected) { 829 result = isc_socket_connect(sock, destaddr, task, req_connected, 830 request); 831 if (result != ISC_R_SUCCESS) { 832 goto unlink; 833 } 834 request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; 835 } else { 836 result = req_send(request, task, connected ? NULL : destaddr); 837 if (result != ISC_R_SUCCESS) { 838 goto unlink; 839 } 840 } 841 842 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", request); 843 *requestp = request; 844 return (ISC_R_SUCCESS); 845 846 unlink: 847 LOCK(&requestmgr->lock); 848 ISC_LIST_UNLINK(requestmgr->requests, request, link); 849 UNLOCK(&requestmgr->lock); 850 851 cleanup: 852 if (tclone != NULL) { 853 isc_task_detach(&tclone); 854 } 855 req_destroy(request); 856 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s", 857 dns_result_totext(result)); 858 return (result); 859 } 860 861 isc_result_t 862 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, 863 const isc_sockaddr_t *address, unsigned int options, 864 dns_tsigkey_t *key, unsigned int timeout, isc_task_t *task, 865 isc_taskaction_t action, void *arg, 866 dns_request_t **requestp) { 867 return (dns_request_createvia(requestmgr, message, NULL, address, -1, 868 options, key, timeout, 0, 0, task, action, 869 arg, requestp)); 870 } 871 872 isc_result_t 873 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, 874 const isc_sockaddr_t *srcaddr, 875 const isc_sockaddr_t *destaddr, isc_dscp_t dscp, 876 unsigned int options, dns_tsigkey_t *key, 877 unsigned int timeout, unsigned int udptimeout, 878 unsigned int udpretries, isc_task_t *task, 879 isc_taskaction_t action, void *arg, 880 dns_request_t **requestp) { 881 dns_request_t *request = NULL; 882 isc_task_t *tclone = NULL; 883 isc_socket_t *sock = NULL; 884 isc_result_t result; 885 isc_mem_t *mctx; 886 dns_messageid_t id; 887 bool tcp; 888 bool share; 889 bool settsigkey = true; 890 bool connected = false; 891 892 REQUIRE(VALID_REQUESTMGR(requestmgr)); 893 REQUIRE(message != NULL); 894 REQUIRE(destaddr != NULL); 895 REQUIRE(task != NULL); 896 REQUIRE(action != NULL); 897 REQUIRE(requestp != NULL && *requestp == NULL); 898 REQUIRE(timeout > 0); 899 900 mctx = requestmgr->mctx; 901 902 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia"); 903 904 if (srcaddr != NULL && 905 isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr)) { 906 return (ISC_R_FAMILYMISMATCH); 907 } 908 909 if (isblackholed(requestmgr->dispatchmgr, destaddr)) { 910 return (DNS_R_BLACKHOLED); 911 } 912 913 request = NULL; 914 result = new_request(mctx, &request); 915 if (result != ISC_R_SUCCESS) { 916 return (result); 917 } 918 919 if (udptimeout == 0 && udpretries != 0) { 920 udptimeout = timeout / (udpretries + 1); 921 if (udptimeout == 0) { 922 udptimeout = 1; 923 } 924 } 925 request->udpcount = udpretries; 926 request->dscp = dscp; 927 928 /* 929 * Create timer now. We will set it below once. 930 */ 931 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, 932 NULL, NULL, task, req_timeout, request, 933 &request->timer); 934 if (result != ISC_R_SUCCESS) { 935 goto cleanup; 936 } 937 938 request->event = (dns_requestevent_t *)isc_event_allocate( 939 mctx, task, DNS_EVENT_REQUESTDONE, action, arg, 940 sizeof(dns_requestevent_t)); 941 isc_task_attach(task, &tclone); 942 request->event->ev_sender = task; 943 request->event->request = request; 944 request->event->result = ISC_R_FAILURE; 945 if (key != NULL) { 946 dns_tsigkey_attach(key, &request->tsigkey); 947 } 948 949 use_tcp: 950 tcp = ((options & DNS_REQUESTOPT_TCP) != 0); 951 share = ((options & DNS_REQUESTOPT_SHARE) != 0); 952 result = get_dispatch(tcp, false, share, requestmgr, srcaddr, destaddr, 953 dscp, &connected, &request->dispatch); 954 if (result != ISC_R_SUCCESS) { 955 goto cleanup; 956 } 957 958 result = dns_dispatch_addresponse( 959 request->dispatch, 0, destaddr, task, req_response, request, 960 &id, &request->dispentry, requestmgr->socketmgr); 961 if (result != ISC_R_SUCCESS) { 962 goto cleanup; 963 } 964 sock = req_getsocket(request); 965 INSIST(sock != NULL); 966 967 message->id = id; 968 if (settsigkey) { 969 result = dns_message_settsigkey(message, request->tsigkey); 970 if (result != ISC_R_SUCCESS) { 971 goto cleanup; 972 } 973 } 974 result = req_render(message, &request->query, options, mctx); 975 if (result == DNS_R_USETCP && (options & DNS_REQUESTOPT_TCP) == 0) { 976 /* 977 * Try again using TCP. 978 */ 979 dns_message_renderreset(message); 980 dns_dispatch_removeresponse(&request->dispentry, NULL); 981 dns_dispatch_detach(&request->dispatch); 982 sock = NULL; 983 options |= DNS_REQUESTOPT_TCP; 984 settsigkey = false; 985 goto use_tcp; 986 } 987 if (result != ISC_R_SUCCESS) { 988 goto cleanup; 989 } 990 991 result = dns_message_getquerytsig(message, mctx, &request->tsig); 992 if (result != ISC_R_SUCCESS) { 993 goto cleanup; 994 } 995 996 LOCK(&requestmgr->lock); 997 if (requestmgr->exiting) { 998 UNLOCK(&requestmgr->lock); 999 result = ISC_R_SHUTTINGDOWN; 1000 goto cleanup; 1001 } 1002 requestmgr_attach(requestmgr, &request->requestmgr); 1003 request->hash = mgr_gethash(requestmgr); 1004 ISC_LIST_APPEND(requestmgr->requests, request, link); 1005 UNLOCK(&requestmgr->lock); 1006 1007 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); 1008 if (result != ISC_R_SUCCESS) { 1009 goto unlink; 1010 } 1011 1012 request->destaddr = *destaddr; 1013 if (tcp && !connected) { 1014 result = isc_socket_connect(sock, destaddr, task, req_connected, 1015 request); 1016 if (result != ISC_R_SUCCESS) { 1017 goto unlink; 1018 } 1019 request->flags |= DNS_REQUEST_F_CONNECTING | DNS_REQUEST_F_TCP; 1020 } else { 1021 result = req_send(request, task, connected ? NULL : destaddr); 1022 if (result != ISC_R_SUCCESS) { 1023 goto unlink; 1024 } 1025 } 1026 1027 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request); 1028 *requestp = request; 1029 return (ISC_R_SUCCESS); 1030 1031 unlink: 1032 LOCK(&requestmgr->lock); 1033 ISC_LIST_UNLINK(requestmgr->requests, request, link); 1034 UNLOCK(&requestmgr->lock); 1035 1036 cleanup: 1037 if (tclone != NULL) { 1038 isc_task_detach(&tclone); 1039 } 1040 req_destroy(request); 1041 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s", 1042 dns_result_totext(result)); 1043 return (result); 1044 } 1045 1046 static isc_result_t 1047 req_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, 1048 isc_mem_t *mctx) { 1049 isc_buffer_t *buf1 = NULL; 1050 isc_buffer_t *buf2 = NULL; 1051 isc_result_t result; 1052 isc_region_t r; 1053 bool tcp = false; 1054 dns_compress_t cctx; 1055 bool cleanup_cctx = false; 1056 1057 REQUIRE(bufferp != NULL && *bufferp == NULL); 1058 1059 req_log(ISC_LOG_DEBUG(3), "request_render"); 1060 1061 /* 1062 * Create buffer able to hold largest possible message. 1063 */ 1064 isc_buffer_allocate(mctx, &buf1, 65535); 1065 1066 result = dns_compress_init(&cctx, -1, mctx); 1067 if (result != ISC_R_SUCCESS) { 1068 return (result); 1069 } 1070 cleanup_cctx = true; 1071 1072 if ((options & DNS_REQUESTOPT_CASE) != 0) { 1073 dns_compress_setsensitive(&cctx, true); 1074 } 1075 1076 /* 1077 * Render message. 1078 */ 1079 result = dns_message_renderbegin(message, &cctx, buf1); 1080 if (result != ISC_R_SUCCESS) { 1081 goto cleanup; 1082 } 1083 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); 1084 if (result != ISC_R_SUCCESS) { 1085 goto cleanup; 1086 } 1087 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0); 1088 if (result != ISC_R_SUCCESS) { 1089 goto cleanup; 1090 } 1091 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0); 1092 if (result != ISC_R_SUCCESS) { 1093 goto cleanup; 1094 } 1095 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0); 1096 if (result != ISC_R_SUCCESS) { 1097 goto cleanup; 1098 } 1099 result = dns_message_renderend(message); 1100 if (result != ISC_R_SUCCESS) { 1101 goto cleanup; 1102 } 1103 1104 dns_compress_invalidate(&cctx); 1105 cleanup_cctx = false; 1106 1107 /* 1108 * Copy rendered message to exact sized buffer. 1109 */ 1110 isc_buffer_usedregion(buf1, &r); 1111 if ((options & DNS_REQUESTOPT_TCP) != 0) { 1112 tcp = true; 1113 } else if (r.length > 512) { 1114 result = DNS_R_USETCP; 1115 goto cleanup; 1116 } 1117 isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0)); 1118 if (tcp) { 1119 isc_buffer_putuint16(buf2, (uint16_t)r.length); 1120 } 1121 result = isc_buffer_copyregion(buf2, &r); 1122 if (result != ISC_R_SUCCESS) { 1123 goto cleanup; 1124 } 1125 1126 /* 1127 * Cleanup and return. 1128 */ 1129 isc_buffer_free(&buf1); 1130 *bufferp = buf2; 1131 return (ISC_R_SUCCESS); 1132 1133 cleanup: 1134 dns_message_renderreset(message); 1135 if (buf1 != NULL) { 1136 isc_buffer_free(&buf1); 1137 } 1138 if (buf2 != NULL) { 1139 isc_buffer_free(&buf2); 1140 } 1141 if (cleanup_cctx) { 1142 dns_compress_invalidate(&cctx); 1143 } 1144 return (result); 1145 } 1146 1147 /* 1148 * If this request is no longer waiting for events, 1149 * send the completion event. This will ultimately 1150 * cause the request to be destroyed. 1151 * 1152 * Requires: 1153 * 'request' is locked by the caller. 1154 */ 1155 static void 1156 send_if_done(dns_request_t *request, isc_result_t result) { 1157 if (request->event != NULL && !request->canceling) { 1158 req_sendevent(request, result); 1159 } 1160 } 1161 1162 /* 1163 * Handle the control event. 1164 */ 1165 static void 1166 do_cancel(isc_task_t *task, isc_event_t *event) { 1167 dns_request_t *request = event->ev_arg; 1168 UNUSED(task); 1169 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL); 1170 LOCK(&request->requestmgr->locks[request->hash]); 1171 request->canceling = false; 1172 if (!DNS_REQUEST_CANCELED(request)) { 1173 req_cancel(request); 1174 } 1175 send_if_done(request, ISC_R_CANCELED); 1176 UNLOCK(&request->requestmgr->locks[request->hash]); 1177 } 1178 1179 void 1180 dns_request_cancel(dns_request_t *request) { 1181 REQUIRE(VALID_REQUEST(request)); 1182 1183 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request); 1184 1185 REQUIRE(VALID_REQUEST(request)); 1186 1187 LOCK(&request->requestmgr->locks[request->hash]); 1188 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) { 1189 isc_event_t *ev = &request->ctlevent; 1190 isc_task_send(request->event->ev_sender, &ev); 1191 request->canceling = true; 1192 } 1193 UNLOCK(&request->requestmgr->locks[request->hash]); 1194 } 1195 1196 isc_result_t 1197 dns_request_getresponse(dns_request_t *request, dns_message_t *message, 1198 unsigned int options) { 1199 isc_result_t result; 1200 1201 REQUIRE(VALID_REQUEST(request)); 1202 REQUIRE(request->answer != NULL); 1203 1204 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p", 1205 request); 1206 1207 result = dns_message_setquerytsig(message, request->tsig); 1208 if (result != ISC_R_SUCCESS) { 1209 return (result); 1210 } 1211 result = dns_message_settsigkey(message, request->tsigkey); 1212 if (result != ISC_R_SUCCESS) { 1213 return (result); 1214 } 1215 result = dns_message_parse(message, request->answer, options); 1216 if (result != ISC_R_SUCCESS) { 1217 return (result); 1218 } 1219 if (request->tsigkey != NULL) { 1220 result = dns_tsig_verify(request->answer, message, NULL, NULL); 1221 } 1222 return (result); 1223 } 1224 1225 isc_buffer_t * 1226 dns_request_getanswer(dns_request_t *request) { 1227 REQUIRE(VALID_REQUEST(request)); 1228 1229 return (request->answer); 1230 } 1231 1232 bool 1233 dns_request_usedtcp(dns_request_t *request) { 1234 REQUIRE(VALID_REQUEST(request)); 1235 1236 return ((request->flags & DNS_REQUEST_F_TCP) != 0); 1237 } 1238 1239 void 1240 dns_request_destroy(dns_request_t **requestp) { 1241 dns_request_t *request; 1242 1243 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp)); 1244 1245 request = *requestp; 1246 *requestp = NULL; 1247 1248 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request); 1249 1250 LOCK(&request->requestmgr->lock); 1251 LOCK(&request->requestmgr->locks[request->hash]); 1252 ISC_LIST_UNLINK(request->requestmgr->requests, request, link); 1253 INSIST(!DNS_REQUEST_CONNECTING(request)); 1254 INSIST(!DNS_REQUEST_SENDING(request)); 1255 UNLOCK(&request->requestmgr->locks[request->hash]); 1256 UNLOCK(&request->requestmgr->lock); 1257 1258 /* 1259 * These should have been cleaned up by req_cancel() before 1260 * the completion event was sent. 1261 */ 1262 INSIST(!ISC_LINK_LINKED(request, link)); 1263 INSIST(request->dispentry == NULL); 1264 INSIST(request->dispatch == NULL); 1265 INSIST(request->timer == NULL); 1266 1267 req_destroy(request); 1268 } 1269 1270 /*** 1271 *** Private: request. 1272 ***/ 1273 1274 static isc_socket_t * 1275 req_getsocket(dns_request_t *request) { 1276 unsigned int dispattr; 1277 isc_socket_t *sock; 1278 1279 dispattr = dns_dispatch_getattributes(request->dispatch); 1280 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { 1281 INSIST(request->dispentry != NULL); 1282 sock = dns_dispatch_getentrysocket(request->dispentry); 1283 } else { 1284 sock = dns_dispatch_getsocket(request->dispatch); 1285 } 1286 1287 return (sock); 1288 } 1289 1290 static void 1291 req_connected(isc_task_t *task, isc_event_t *event) { 1292 isc_socketevent_t *sevent = (isc_socketevent_t *)event; 1293 isc_result_t result; 1294 dns_request_t *request = event->ev_arg; 1295 1296 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); 1297 REQUIRE(VALID_REQUEST(request)); 1298 REQUIRE(DNS_REQUEST_CONNECTING(request)); 1299 1300 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request); 1301 1302 LOCK(&request->requestmgr->locks[request->hash]); 1303 request->flags &= ~DNS_REQUEST_F_CONNECTING; 1304 1305 if (DNS_REQUEST_CANCELED(request)) { 1306 /* 1307 * Send delayed event. 1308 */ 1309 if (DNS_REQUEST_TIMEDOUT(request)) { 1310 send_if_done(request, ISC_R_TIMEDOUT); 1311 } else { 1312 send_if_done(request, ISC_R_CANCELED); 1313 } 1314 } else { 1315 dns_dispatch_starttcp(request->dispatch); 1316 result = sevent->result; 1317 if (result == ISC_R_SUCCESS) { 1318 result = req_send(request, task, NULL); 1319 } 1320 1321 if (result != ISC_R_SUCCESS) { 1322 req_cancel(request); 1323 send_if_done(request, ISC_R_CANCELED); 1324 } 1325 } 1326 UNLOCK(&request->requestmgr->locks[request->hash]); 1327 isc_event_free(&event); 1328 } 1329 1330 static void 1331 req_senddone(isc_task_t *task, isc_event_t *event) { 1332 isc_socketevent_t *sevent = (isc_socketevent_t *)event; 1333 dns_request_t *request = event->ev_arg; 1334 1335 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); 1336 REQUIRE(VALID_REQUEST(request)); 1337 REQUIRE(DNS_REQUEST_SENDING(request)); 1338 1339 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request); 1340 1341 UNUSED(task); 1342 1343 LOCK(&request->requestmgr->locks[request->hash]); 1344 request->flags &= ~DNS_REQUEST_F_SENDING; 1345 1346 if (DNS_REQUEST_CANCELED(request)) { 1347 /* 1348 * Send delayed event. 1349 */ 1350 if (DNS_REQUEST_TIMEDOUT(request)) { 1351 send_if_done(request, ISC_R_TIMEDOUT); 1352 } else { 1353 send_if_done(request, ISC_R_CANCELED); 1354 } 1355 } else if (sevent->result != ISC_R_SUCCESS) { 1356 req_cancel(request); 1357 send_if_done(request, ISC_R_CANCELED); 1358 } 1359 UNLOCK(&request->requestmgr->locks[request->hash]); 1360 1361 isc_event_free(&event); 1362 } 1363 1364 static void 1365 req_response(isc_task_t *task, isc_event_t *event) { 1366 isc_result_t result; 1367 dns_request_t *request = event->ev_arg; 1368 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; 1369 isc_region_t r; 1370 1371 REQUIRE(VALID_REQUEST(request)); 1372 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH); 1373 1374 UNUSED(task); 1375 1376 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request, 1377 dns_result_totext(devent->result)); 1378 1379 LOCK(&request->requestmgr->locks[request->hash]); 1380 result = devent->result; 1381 if (result != ISC_R_SUCCESS) { 1382 goto done; 1383 } 1384 1385 /* 1386 * Copy buffer to request. 1387 */ 1388 isc_buffer_usedregion(&devent->buffer, &r); 1389 isc_buffer_allocate(request->mctx, &request->answer, r.length); 1390 result = isc_buffer_copyregion(request->answer, &r); 1391 if (result != ISC_R_SUCCESS) { 1392 isc_buffer_free(&request->answer); 1393 } 1394 done: 1395 /* 1396 * Cleanup. 1397 */ 1398 dns_dispatch_removeresponse(&request->dispentry, &devent); 1399 req_cancel(request); 1400 /* 1401 * Send completion event. 1402 */ 1403 send_if_done(request, result); 1404 UNLOCK(&request->requestmgr->locks[request->hash]); 1405 } 1406 1407 static void 1408 req_timeout(isc_task_t *task, isc_event_t *event) { 1409 dns_request_t *request = event->ev_arg; 1410 isc_result_t result; 1411 1412 REQUIRE(VALID_REQUEST(request)); 1413 1414 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request); 1415 1416 UNUSED(task); 1417 LOCK(&request->requestmgr->locks[request->hash]); 1418 if (event->ev_type == ISC_TIMEREVENT_TICK && request->udpcount-- != 0) { 1419 if (!DNS_REQUEST_SENDING(request)) { 1420 result = req_send(request, task, &request->destaddr); 1421 if (result != ISC_R_SUCCESS) { 1422 req_cancel(request); 1423 send_if_done(request, result); 1424 } 1425 } 1426 } else { 1427 request->flags |= DNS_REQUEST_F_TIMEDOUT; 1428 req_cancel(request); 1429 send_if_done(request, ISC_R_TIMEDOUT); 1430 } 1431 UNLOCK(&request->requestmgr->locks[request->hash]); 1432 isc_event_free(&event); 1433 } 1434 1435 static void 1436 req_sendevent(dns_request_t *request, isc_result_t result) { 1437 isc_task_t *task; 1438 1439 REQUIRE(VALID_REQUEST(request)); 1440 1441 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request); 1442 1443 /* 1444 * Lock held by caller. 1445 */ 1446 task = request->event->ev_sender; 1447 request->event->ev_sender = request; 1448 request->event->result = result; 1449 isc_task_sendanddetach(&task, (isc_event_t **)(void *)&request->event); 1450 } 1451 1452 static void 1453 req_destroy(dns_request_t *request) { 1454 REQUIRE(VALID_REQUEST(request)); 1455 1456 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request); 1457 1458 request->magic = 0; 1459 if (request->query != NULL) { 1460 isc_buffer_free(&request->query); 1461 } 1462 if (request->answer != NULL) { 1463 isc_buffer_free(&request->answer); 1464 } 1465 if (request->event != NULL) { 1466 isc_event_free((isc_event_t **)(void *)&request->event); 1467 } 1468 if (request->dispentry != NULL) { 1469 dns_dispatch_removeresponse(&request->dispentry, NULL); 1470 } 1471 if (request->dispatch != NULL) { 1472 dns_dispatch_detach(&request->dispatch); 1473 } 1474 if (request->timer != NULL) { 1475 isc_timer_detach(&request->timer); 1476 } 1477 if (request->tsig != NULL) { 1478 isc_buffer_free(&request->tsig); 1479 } 1480 if (request->tsigkey != NULL) { 1481 dns_tsigkey_detach(&request->tsigkey); 1482 } 1483 if (request->requestmgr != NULL) { 1484 requestmgr_detach(&request->requestmgr); 1485 } 1486 isc_mem_putanddetach(&request->mctx, request, sizeof(*request)); 1487 } 1488 1489 /* 1490 * Stop the current request. Must be called from the request's task. 1491 */ 1492 static void 1493 req_cancel(dns_request_t *request) { 1494 isc_socket_t *sock; 1495 unsigned int dispattr; 1496 1497 REQUIRE(VALID_REQUEST(request)); 1498 1499 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request); 1500 1501 /* 1502 * Lock held by caller. 1503 */ 1504 request->flags |= DNS_REQUEST_F_CANCELED; 1505 1506 if (request->timer != NULL) { 1507 isc_timer_detach(&request->timer); 1508 } 1509 dispattr = dns_dispatch_getattributes(request->dispatch); 1510 sock = NULL; 1511 if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) { 1512 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { 1513 if (request->dispentry != NULL) { 1514 sock = dns_dispatch_getentrysocket( 1515 request->dispentry); 1516 } 1517 } else { 1518 sock = dns_dispatch_getsocket(request->dispatch); 1519 } 1520 if (DNS_REQUEST_CONNECTING(request) && sock != NULL) { 1521 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT); 1522 } 1523 if (DNS_REQUEST_SENDING(request) && sock != NULL) { 1524 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND); 1525 } 1526 } 1527 if (request->dispentry != NULL) { 1528 dns_dispatch_removeresponse(&request->dispentry, NULL); 1529 } 1530 dns_dispatch_detach(&request->dispatch); 1531 } 1532 1533 static void 1534 req_log(int level, const char *fmt, ...) { 1535 va_list ap; 1536 1537 va_start(ap, fmt); 1538 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_REQUEST, 1539 level, fmt, ap); 1540 va_end(ap); 1541 } 1542