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