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