1/* 2 * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2002 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <isc/magic.h> 25#include <isc/mem.h> 26#include <isc/task.h> 27#include <isc/timer.h> 28#include <isc/util.h> 29 30#include <dns/acl.h> 31#include <dns/compress.h> 32#include <dns/dispatch.h> 33#include <dns/events.h> 34#include <dns/log.h> 35#include <dns/message.h> 36#include <dns/rdata.h> 37#include <dns/rdatastruct.h> 38#include <dns/request.h> 39#include <dns/result.h> 40#include <dns/tsig.h> 41 42#define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M') 43#define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC) 44 45#define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!') 46#define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC) 47 48typedef ISC_LIST(dns_request_t) dns_requestlist_t; 49 50#define DNS_REQUEST_NLOCKS 7 51 52struct dns_requestmgr { 53 unsigned int magic; 54 isc_mutex_t lock; 55 isc_mem_t *mctx; 56 57 /* locked */ 58 isc_int32_t eref; 59 isc_int32_t iref; 60 isc_timermgr_t *timermgr; 61 isc_socketmgr_t *socketmgr; 62 isc_taskmgr_t *taskmgr; 63 dns_dispatchmgr_t *dispatchmgr; 64 dns_dispatch_t *dispatchv4; 65 dns_dispatch_t *dispatchv6; 66 isc_boolean_t exiting; 67 isc_eventlist_t whenshutdown; 68 unsigned int hash; 69 isc_mutex_t locks[DNS_REQUEST_NLOCKS]; 70 dns_requestlist_t requests; 71}; 72 73struct dns_request { 74 unsigned int magic; 75 unsigned int hash; 76 isc_mem_t *mctx; 77 isc_int32_t flags; 78 ISC_LINK(dns_request_t) link; 79 isc_buffer_t *query; 80 isc_buffer_t *answer; 81 dns_requestevent_t *event; 82 dns_dispatch_t *dispatch; 83 dns_dispentry_t *dispentry; 84 isc_timer_t *timer; 85 dns_requestmgr_t *requestmgr; 86 isc_buffer_t *tsig; 87 dns_tsigkey_t *tsigkey; 88 isc_event_t ctlevent; 89 isc_boolean_t canceling; /* ctlevent outstanding */ 90 isc_sockaddr_t destaddr; 91 unsigned int udpcount; 92}; 93 94#define DNS_REQUEST_F_CONNECTING 0x0001 95#define DNS_REQUEST_F_SENDING 0x0002 96#define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise 97 synchronously canceled */ 98#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */ 99#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */ 100#define DNS_REQUEST_CANCELED(r) \ 101 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0) 102#define DNS_REQUEST_CONNECTING(r) \ 103 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0) 104#define DNS_REQUEST_SENDING(r) \ 105 (((r)->flags & DNS_REQUEST_F_SENDING) != 0) 106#define DNS_REQUEST_TIMEDOUT(r) \ 107 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0) 108 109 110/*** 111 *** Forward 112 ***/ 113 114static void mgr_destroy(dns_requestmgr_t *requestmgr); 115static void mgr_shutdown(dns_requestmgr_t *requestmgr); 116static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr); 117static void send_shutdown_events(dns_requestmgr_t *requestmgr); 118 119static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer, 120 unsigned int options, isc_mem_t *mctx); 121static void req_senddone(isc_task_t *task, isc_event_t *event); 122static void req_response(isc_task_t *task, isc_event_t *event); 123static void req_timeout(isc_task_t *task, isc_event_t *event); 124static isc_socket_t * req_getsocket(dns_request_t *request); 125static void req_connected(isc_task_t *task, isc_event_t *event); 126static void req_sendevent(dns_request_t *request, isc_result_t result); 127static void req_cancel(dns_request_t *request); 128static void req_destroy(dns_request_t *request); 129static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 130static void do_cancel(isc_task_t *task, isc_event_t *event); 131 132/*** 133 *** Public 134 ***/ 135 136isc_result_t 137dns_requestmgr_create(isc_mem_t *mctx, 138 isc_timermgr_t *timermgr, 139 isc_socketmgr_t *socketmgr, 140 isc_taskmgr_t *taskmgr, 141 dns_dispatchmgr_t *dispatchmgr, 142 dns_dispatch_t *dispatchv4, 143 dns_dispatch_t *dispatchv6, 144 dns_requestmgr_t **requestmgrp) 145{ 146 dns_requestmgr_t *requestmgr; 147 isc_socket_t *socket; 148 isc_result_t result; 149 int i; 150 unsigned int dispattr; 151 152 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create"); 153 154 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL); 155 REQUIRE(timermgr != NULL); 156 REQUIRE(socketmgr != NULL); 157 REQUIRE(taskmgr != NULL); 158 REQUIRE(dispatchmgr != NULL); 159 UNUSED(socket); 160 if (dispatchv4 != NULL) { 161 dispattr = dns_dispatch_getattributes(dispatchv4); 162 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); 163 } 164 if (dispatchv6 != NULL) { 165 dispattr = dns_dispatch_getattributes(dispatchv6); 166 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0); 167 } 168 169 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr)); 170 if (requestmgr == NULL) 171 return (ISC_R_NOMEMORY); 172 173 result = isc_mutex_init(&requestmgr->lock); 174 if (result != ISC_R_SUCCESS) { 175 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr)); 176 return (result); 177 } 178 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { 179 result = isc_mutex_init(&requestmgr->locks[i]); 180 if (result != ISC_R_SUCCESS) { 181 while (--i >= 0) 182 DESTROYLOCK(&requestmgr->locks[i]); 183 DESTROYLOCK(&requestmgr->lock); 184 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr)); 185 return (result); 186 } 187 } 188 requestmgr->timermgr = timermgr; 189 requestmgr->socketmgr = socketmgr; 190 requestmgr->taskmgr = taskmgr; 191 requestmgr->dispatchmgr = dispatchmgr; 192 requestmgr->dispatchv4 = NULL; 193 if (dispatchv4 != NULL) 194 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4); 195 requestmgr->dispatchv6 = NULL; 196 if (dispatchv6 != NULL) 197 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6); 198 requestmgr->mctx = NULL; 199 isc_mem_attach(mctx, &requestmgr->mctx); 200 requestmgr->eref = 1; /* implicit attach */ 201 requestmgr->iref = 0; 202 ISC_LIST_INIT(requestmgr->whenshutdown); 203 ISC_LIST_INIT(requestmgr->requests); 204 requestmgr->exiting = ISC_FALSE; 205 requestmgr->hash = 0; 206 requestmgr->magic = REQUESTMGR_MAGIC; 207 208 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr); 209 210 *requestmgrp = requestmgr; 211 return (ISC_R_SUCCESS); 212} 213 214void 215dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task, 216 isc_event_t **eventp) 217{ 218 isc_task_t *clone; 219 isc_event_t *event; 220 221 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown"); 222 223 REQUIRE(VALID_REQUESTMGR(requestmgr)); 224 REQUIRE(eventp != NULL); 225 226 event = *eventp; 227 *eventp = NULL; 228 229 LOCK(&requestmgr->lock); 230 231 if (requestmgr->exiting) { 232 /* 233 * We're already shutdown. Send the event. 234 */ 235 event->ev_sender = requestmgr; 236 isc_task_send(task, &event); 237 } else { 238 clone = NULL; 239 isc_task_attach(task, &clone); 240 event->ev_sender = clone; 241 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link); 242 } 243 UNLOCK(&requestmgr->lock); 244} 245 246void 247dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) { 248 249 REQUIRE(VALID_REQUESTMGR(requestmgr)); 250 251 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr); 252 253 LOCK(&requestmgr->lock); 254 mgr_shutdown(requestmgr); 255 UNLOCK(&requestmgr->lock); 256} 257 258static void 259mgr_shutdown(dns_requestmgr_t *requestmgr) { 260 dns_request_t *request; 261 262 /* 263 * Caller holds lock. 264 */ 265 if (!requestmgr->exiting) { 266 requestmgr->exiting = ISC_TRUE; 267 for (request = ISC_LIST_HEAD(requestmgr->requests); 268 request != NULL; 269 request = ISC_LIST_NEXT(request, link)) { 270 dns_request_cancel(request); 271 } 272 if (requestmgr->iref == 0) { 273 INSIST(ISC_LIST_EMPTY(requestmgr->requests)); 274 send_shutdown_events(requestmgr); 275 } 276 } 277} 278 279static void 280requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { 281 282 /* 283 * Locked by caller. 284 */ 285 286 REQUIRE(VALID_REQUESTMGR(source)); 287 REQUIRE(targetp != NULL && *targetp == NULL); 288 289 REQUIRE(!source->exiting); 290 291 source->iref++; 292 *targetp = source; 293 294 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d", 295 source, source->eref, source->iref); 296} 297 298static void 299requestmgr_detach(dns_requestmgr_t **requestmgrp) { 300 dns_requestmgr_t *requestmgr; 301 isc_boolean_t need_destroy = ISC_FALSE; 302 303 REQUIRE(requestmgrp != NULL); 304 requestmgr = *requestmgrp; 305 REQUIRE(VALID_REQUESTMGR(requestmgr)); 306 307 *requestmgrp = NULL; 308 LOCK(&requestmgr->lock); 309 INSIST(requestmgr->iref > 0); 310 requestmgr->iref--; 311 312 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d", 313 requestmgr, requestmgr->eref, requestmgr->iref); 314 315 if (requestmgr->iref == 0 && requestmgr->exiting) { 316 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL); 317 send_shutdown_events(requestmgr); 318 if (requestmgr->eref == 0) 319 need_destroy = ISC_TRUE; 320 } 321 UNLOCK(&requestmgr->lock); 322 323 if (need_destroy) 324 mgr_destroy(requestmgr); 325} 326 327void 328dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { 329 330 REQUIRE(VALID_REQUESTMGR(source)); 331 REQUIRE(targetp != NULL && *targetp == NULL); 332 REQUIRE(!source->exiting); 333 334 LOCK(&source->lock); 335 source->eref++; 336 *targetp = source; 337 UNLOCK(&source->lock); 338 339 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d", 340 source, source->eref, source->iref); 341} 342 343void 344dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) { 345 dns_requestmgr_t *requestmgr; 346 isc_boolean_t need_destroy = ISC_FALSE; 347 348 REQUIRE(requestmgrp != NULL); 349 requestmgr = *requestmgrp; 350 REQUIRE(VALID_REQUESTMGR(requestmgr)); 351 352 LOCK(&requestmgr->lock); 353 INSIST(requestmgr->eref > 0); 354 requestmgr->eref--; 355 356 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d", 357 requestmgr, requestmgr->eref, requestmgr->iref); 358 359 if (requestmgr->eref == 0 && requestmgr->iref == 0) { 360 INSIST(requestmgr->exiting && 361 ISC_LIST_HEAD(requestmgr->requests) == NULL); 362 need_destroy = ISC_TRUE; 363 } 364 UNLOCK(&requestmgr->lock); 365 366 if (need_destroy) 367 mgr_destroy(requestmgr); 368 369 *requestmgrp = NULL; 370} 371 372static void 373send_shutdown_events(dns_requestmgr_t *requestmgr) { 374 isc_event_t *event, *next_event; 375 isc_task_t *etask; 376 377 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr); 378 379 /* 380 * Caller must be holding the manager lock. 381 */ 382 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown); 383 event != NULL; 384 event = next_event) { 385 next_event = ISC_LIST_NEXT(event, ev_link); 386 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link); 387 etask = event->ev_sender; 388 event->ev_sender = requestmgr; 389 isc_task_sendanddetach(&etask, &event); 390 } 391} 392 393static void 394mgr_destroy(dns_requestmgr_t *requestmgr) { 395 int i; 396 isc_mem_t *mctx; 397 398 req_log(ISC_LOG_DEBUG(3), "mgr_destroy"); 399 400 REQUIRE(requestmgr->eref == 0); 401 REQUIRE(requestmgr->iref == 0); 402 403 DESTROYLOCK(&requestmgr->lock); 404 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) 405 DESTROYLOCK(&requestmgr->locks[i]); 406 if (requestmgr->dispatchv4 != NULL) 407 dns_dispatch_detach(&requestmgr->dispatchv4); 408 if (requestmgr->dispatchv6 != NULL) 409 dns_dispatch_detach(&requestmgr->dispatchv6); 410 requestmgr->magic = 0; 411 mctx = requestmgr->mctx; 412 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr)); 413 isc_mem_detach(&mctx); 414} 415 416static unsigned int 417mgr_gethash(dns_requestmgr_t *requestmgr) { 418 req_log(ISC_LOG_DEBUG(3), "mgr_gethash"); 419 /* 420 * Locked by caller. 421 */ 422 requestmgr->hash++; 423 return (requestmgr->hash % DNS_REQUEST_NLOCKS); 424} 425 426static inline isc_result_t 427req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) { 428 isc_region_t r; 429 isc_socket_t *socket; 430 isc_result_t result; 431 432 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request); 433 434 REQUIRE(VALID_REQUEST(request)); 435 socket = req_getsocket(request); 436 isc_buffer_usedregion(request->query, &r); 437 /* 438 * We could connect the socket when we are using an exclusive dispatch 439 * as we do in resolver.c, but we prefer implementation simplicity 440 * at this moment. 441 */ 442 result = isc_socket_sendto(socket, &r, task, req_senddone, 443 request, address, NULL); 444 if (result == ISC_R_SUCCESS) 445 request->flags |= DNS_REQUEST_F_SENDING; 446 return (result); 447} 448 449static isc_result_t 450new_request(isc_mem_t *mctx, dns_request_t **requestp) 451{ 452 dns_request_t *request; 453 454 request = isc_mem_get(mctx, sizeof(*request)); 455 if (request == NULL) 456 return (ISC_R_NOMEMORY); 457 458 /* 459 * Zero structure. 460 */ 461 request->magic = 0; 462 request->mctx = NULL; 463 request->flags = 0; 464 ISC_LINK_INIT(request, link); 465 request->query = NULL; 466 request->answer = NULL; 467 request->event = NULL; 468 request->dispatch = NULL; 469 request->dispentry = NULL; 470 request->timer = NULL; 471 request->requestmgr = NULL; 472 request->tsig = NULL; 473 request->tsigkey = NULL; 474 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL, 475 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, 476 NULL, NULL); 477 request->canceling = ISC_FALSE; 478 request->udpcount = 0; 479 480 isc_mem_attach(mctx, &request->mctx); 481 482 request->magic = REQUEST_MAGIC; 483 *requestp = request; 484 return (ISC_R_SUCCESS); 485} 486 487 488static isc_boolean_t 489isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) { 490 dns_acl_t *blackhole; 491 isc_netaddr_t netaddr; 492 int match; 493 isc_boolean_t drop = ISC_FALSE; 494 char netaddrstr[ISC_NETADDR_FORMATSIZE]; 495 496 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr); 497 if (blackhole != NULL) { 498 isc_netaddr_fromsockaddr(&netaddr, destaddr); 499 if (dns_acl_match(&netaddr, NULL, blackhole, 500 NULL, &match, NULL) == ISC_R_SUCCESS && 501 match > 0) 502 drop = ISC_TRUE; 503 } 504 if (drop) { 505 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr)); 506 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr); 507 } 508 return (drop); 509} 510 511static isc_result_t 512create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, 513 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) 514{ 515 isc_result_t result; 516 isc_socket_t *socket = NULL; 517 isc_sockaddr_t src; 518 unsigned int attrs; 519 isc_sockaddr_t bind_any; 520 521 result = isc_socket_create(requestmgr->socketmgr, 522 isc_sockaddr_pf(destaddr), 523 isc_sockettype_tcp, &socket); 524 if (result != ISC_R_SUCCESS) 525 return (result); 526#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT 527 if (srcaddr == NULL) { 528 isc_sockaddr_anyofpf(&bind_any, 529 isc_sockaddr_pf(destaddr)); 530 result = isc_socket_bind(socket, &bind_any, 0); 531 } else { 532 src = *srcaddr; 533 isc_sockaddr_setport(&src, 0); 534 result = isc_socket_bind(socket, &src, 0); 535 } 536 if (result != ISC_R_SUCCESS) 537 goto cleanup; 538#endif 539 attrs = 0; 540 attrs |= DNS_DISPATCHATTR_TCP; 541 attrs |= DNS_DISPATCHATTR_PRIVATE; 542 if (isc_sockaddr_pf(destaddr) == AF_INET) 543 attrs |= DNS_DISPATCHATTR_IPV4; 544 else 545 attrs |= DNS_DISPATCHATTR_IPV6; 546 attrs |= DNS_DISPATCHATTR_MAKEQUERY; 547 result = dns_dispatch_createtcp(requestmgr->dispatchmgr, 548 socket, requestmgr->taskmgr, 549 4096, 2, 1, 1, 3, attrs, 550 dispatchp); 551cleanup: 552 isc_socket_detach(&socket); 553 return (result); 554} 555 556static isc_result_t 557find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr, 558 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) 559{ 560 dns_dispatch_t *disp = NULL; 561 unsigned int attrs, attrmask; 562 563 if (srcaddr == NULL) { 564 switch (isc_sockaddr_pf(destaddr)) { 565 case PF_INET: 566 disp = requestmgr->dispatchv4; 567 break; 568 569 case PF_INET6: 570 disp = requestmgr->dispatchv6; 571 break; 572 573 default: 574 return (ISC_R_NOTIMPLEMENTED); 575 } 576 if (disp == NULL) 577 return (ISC_R_FAMILYNOSUPPORT); 578 dns_dispatch_attach(disp, dispatchp); 579 return (ISC_R_SUCCESS); 580 } 581 attrs = 0; 582 attrs |= DNS_DISPATCHATTR_UDP; 583 switch (isc_sockaddr_pf(srcaddr)) { 584 case PF_INET: 585 attrs |= DNS_DISPATCHATTR_IPV4; 586 break; 587 588 case PF_INET6: 589 attrs |= DNS_DISPATCHATTR_IPV6; 590 break; 591 592 default: 593 return (ISC_R_NOTIMPLEMENTED); 594 } 595 attrmask = 0; 596 attrmask |= DNS_DISPATCHATTR_UDP; 597 attrmask |= DNS_DISPATCHATTR_TCP; 598 attrmask |= DNS_DISPATCHATTR_IPV4; 599 attrmask |= DNS_DISPATCHATTR_IPV6; 600 return (dns_dispatch_getudp(requestmgr->dispatchmgr, 601 requestmgr->socketmgr, 602 requestmgr->taskmgr, 603 srcaddr, 4096, 604 1000, 32768, 16411, 16433, 605 attrs, attrmask, 606 dispatchp)); 607} 608 609static isc_result_t 610get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr, 611 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 612 dns_dispatch_t **dispatchp) 613{ 614 isc_result_t result; 615 if (tcp) 616 result = create_tcp_dispatch(requestmgr, srcaddr, 617 destaddr, dispatchp); 618 else 619 result = find_udp_dispatch(requestmgr, srcaddr, 620 destaddr, dispatchp); 621 return (result); 622} 623 624static isc_result_t 625set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) { 626 isc_time_t expires; 627 isc_interval_t interval; 628 isc_result_t result; 629 isc_timertype_t timertype; 630 631 isc_interval_set(&interval, timeout, 0); 632 result = isc_time_nowplusinterval(&expires, &interval); 633 isc_interval_set(&interval, udpresend, 0); 634 635 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once; 636 if (result == ISC_R_SUCCESS) 637 result = isc_timer_reset(timer, timertype, &expires, 638 &interval, ISC_FALSE); 639 return (result); 640} 641 642isc_result_t 643dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, 644 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 645 unsigned int options, unsigned int timeout, 646 isc_task_t *task, isc_taskaction_t action, void *arg, 647 dns_request_t **requestp) 648{ 649 return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr, 650 options, timeout, 0, 0, task, action, 651 arg, requestp)); 652} 653 654isc_result_t 655dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, 656 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 657 unsigned int options, unsigned int timeout, 658 unsigned int udptimeout, isc_task_t *task, 659 isc_taskaction_t action, void *arg, 660 dns_request_t **requestp) 661{ 662 unsigned int udpretries = 0; 663 664 if (udptimeout != 0) 665 udpretries = timeout / udptimeout; 666 667 return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr, 668 options, timeout, udptimeout, 669 udpretries, task, action, arg, 670 requestp)); 671} 672 673isc_result_t 674dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, 675 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 676 unsigned int options, unsigned int timeout, 677 unsigned int udptimeout, unsigned int udpretries, 678 isc_task_t *task, isc_taskaction_t action, void *arg, 679 dns_request_t **requestp) 680{ 681 dns_request_t *request = NULL; 682 isc_task_t *tclone = NULL; 683 isc_socket_t *socket = NULL; 684 isc_result_t result; 685 isc_mem_t *mctx; 686 dns_messageid_t id; 687 isc_boolean_t tcp = ISC_FALSE; 688 isc_region_t r; 689 690 REQUIRE(VALID_REQUESTMGR(requestmgr)); 691 REQUIRE(msgbuf != NULL); 692 REQUIRE(destaddr != NULL); 693 REQUIRE(task != NULL); 694 REQUIRE(action != NULL); 695 REQUIRE(requestp != NULL && *requestp == NULL); 696 REQUIRE(timeout > 0); 697 if (srcaddr != NULL) 698 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr)); 699 700 mctx = requestmgr->mctx; 701 702 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw"); 703 704 if (isblackholed(requestmgr->dispatchmgr, destaddr)) 705 return (DNS_R_BLACKHOLED); 706 707 request = NULL; 708 result = new_request(mctx, &request); 709 if (result != ISC_R_SUCCESS) 710 return (result); 711 712 if (udptimeout == 0 && udpretries != 0) { 713 udptimeout = timeout / (udpretries + 1); 714 if (udptimeout == 0) 715 udptimeout = 1; 716 } 717 request->udpcount = udpretries; 718 719 /* 720 * Create timer now. We will set it below once. 721 */ 722 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, 723 NULL, NULL, task, req_timeout, request, 724 &request->timer); 725 if (result != ISC_R_SUCCESS) 726 goto cleanup; 727 728 request->event = (dns_requestevent_t *) 729 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE, 730 action, arg, sizeof(dns_requestevent_t)); 731 if (request->event == NULL) { 732 result = ISC_R_NOMEMORY; 733 goto cleanup; 734 } 735 isc_task_attach(task, &tclone); 736 request->event->ev_sender = task; 737 request->event->request = request; 738 request->event->result = ISC_R_FAILURE; 739 740 isc_buffer_usedregion(msgbuf, &r); 741 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) { 742 result = DNS_R_FORMERR; 743 goto cleanup; 744 } 745 746 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) 747 tcp = ISC_TRUE; 748 749 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, 750 &request->dispatch); 751 if (result != ISC_R_SUCCESS) 752 goto cleanup; 753 754 result = dns_dispatch_addresponse2(request->dispatch, destaddr, task, 755 req_response, request, &id, 756 &request->dispentry, 757 requestmgr->socketmgr); 758 if (result != ISC_R_SUCCESS) 759 goto cleanup; 760 761 socket = req_getsocket(request); 762 INSIST(socket != NULL); 763 764 result = isc_buffer_allocate(mctx, &request->query, 765 r.length + (tcp ? 2 : 0)); 766 if (result != ISC_R_SUCCESS) 767 goto cleanup; 768 if (tcp) 769 isc_buffer_putuint16(request->query, (isc_uint16_t)r.length); 770 result = isc_buffer_copyregion(request->query, &r); 771 if (result != ISC_R_SUCCESS) 772 goto cleanup; 773 774 /* Add message ID. */ 775 isc_buffer_usedregion(request->query, &r); 776 if (tcp) 777 isc_region_consume(&r, 2); 778 r.base[0] = (id>>8) & 0xff; 779 r.base[1] = id & 0xff; 780 781 LOCK(&requestmgr->lock); 782 if (requestmgr->exiting) { 783 UNLOCK(&requestmgr->lock); 784 result = ISC_R_SHUTTINGDOWN; 785 goto cleanup; 786 } 787 requestmgr_attach(requestmgr, &request->requestmgr); 788 request->hash = mgr_gethash(requestmgr); 789 ISC_LIST_APPEND(requestmgr->requests, request, link); 790 UNLOCK(&requestmgr->lock); 791 792 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); 793 if (result != ISC_R_SUCCESS) 794 goto unlink; 795 796 request->destaddr = *destaddr; 797 if (tcp) { 798 result = isc_socket_connect(socket, destaddr, task, 799 req_connected, request); 800 if (result != ISC_R_SUCCESS) 801 goto unlink; 802 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP; 803 } else { 804 result = req_send(request, task, destaddr); 805 if (result != ISC_R_SUCCESS) 806 goto unlink; 807 } 808 809 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", 810 request); 811 *requestp = request; 812 return (ISC_R_SUCCESS); 813 814 unlink: 815 LOCK(&requestmgr->lock); 816 ISC_LIST_UNLINK(requestmgr->requests, request, link); 817 UNLOCK(&requestmgr->lock); 818 819 cleanup: 820 if (tclone != NULL) 821 isc_task_detach(&tclone); 822 req_destroy(request); 823 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s", 824 dns_result_totext(result)); 825 return (result); 826} 827 828isc_result_t 829dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, 830 isc_sockaddr_t *address, unsigned int options, 831 dns_tsigkey_t *key, 832 unsigned int timeout, isc_task_t *task, 833 isc_taskaction_t action, void *arg, 834 dns_request_t **requestp) 835{ 836 return (dns_request_createvia3(requestmgr, message, NULL, address, 837 options, key, timeout, 0, 0, task, 838 action, arg, requestp)); 839} 840 841isc_result_t 842dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message, 843 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 844 unsigned int options, dns_tsigkey_t *key, 845 unsigned int timeout, isc_task_t *task, 846 isc_taskaction_t action, void *arg, 847 dns_request_t **requestp) 848{ 849 return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr, 850 options, key, timeout, 0, 0, task, 851 action, arg, requestp)); 852} 853 854isc_result_t 855dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message, 856 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 857 unsigned int options, dns_tsigkey_t *key, 858 unsigned int timeout, unsigned int udptimeout, 859 isc_task_t *task, isc_taskaction_t action, void *arg, 860 dns_request_t **requestp) 861{ 862 unsigned int udpretries = 0; 863 864 if (udptimeout != 0) 865 udpretries = timeout / udptimeout; 866 return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr, 867 options, key, timeout, udptimeout, 868 udpretries, task, action, arg, 869 requestp)); 870} 871 872isc_result_t 873dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message, 874 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, 875 unsigned int options, dns_tsigkey_t *key, 876 unsigned int timeout, unsigned int udptimeout, 877 unsigned int udpretries, isc_task_t *task, 878 isc_taskaction_t action, void *arg, 879 dns_request_t **requestp) 880{ 881 dns_request_t *request = NULL; 882 isc_task_t *tclone = NULL; 883 isc_socket_t *socket = NULL; 884 isc_result_t result; 885 isc_mem_t *mctx; 886 dns_messageid_t id; 887 isc_boolean_t tcp; 888 isc_boolean_t setkey = ISC_TRUE; 889 890 REQUIRE(VALID_REQUESTMGR(requestmgr)); 891 REQUIRE(message != NULL); 892 REQUIRE(destaddr != NULL); 893 REQUIRE(task != NULL); 894 REQUIRE(action != NULL); 895 REQUIRE(requestp != NULL && *requestp == NULL); 896 REQUIRE(timeout > 0); 897 898 mctx = requestmgr->mctx; 899 900 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia"); 901 902 if (srcaddr != NULL && 903 isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr)) 904 return (ISC_R_FAMILYMISMATCH); 905 906 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 **)&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 **)&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