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