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