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