1/* 2 * Copyright (C) 2004-2012 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 if (srcaddr != NULL) 898 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr)); 899 900 mctx = requestmgr->mctx; 901 902 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia"); 903 904 if (isblackholed(requestmgr->dispatchmgr, destaddr)) 905 return (DNS_R_BLACKHOLED); 906 907 request = NULL; 908 result = new_request(mctx, &request); 909 if (result != ISC_R_SUCCESS) 910 return (result); 911 912 if (udptimeout == 0 && udpretries != 0) { 913 udptimeout = timeout / (udpretries + 1); 914 if (udptimeout == 0) 915 udptimeout = 1; 916 } 917 request->udpcount = udpretries; 918 919 /* 920 * Create timer now. We will set it below once. 921 */ 922 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive, 923 NULL, NULL, task, req_timeout, request, 924 &request->timer); 925 if (result != ISC_R_SUCCESS) 926 goto cleanup; 927 928 request->event = (dns_requestevent_t *) 929 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE, 930 action, arg, sizeof(dns_requestevent_t)); 931 if (request->event == NULL) { 932 result = ISC_R_NOMEMORY; 933 goto cleanup; 934 } 935 isc_task_attach(task, &tclone); 936 request->event->ev_sender = task; 937 request->event->request = request; 938 request->event->result = ISC_R_FAILURE; 939 if (key != NULL) 940 dns_tsigkey_attach(key, &request->tsigkey); 941 942 use_tcp: 943 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0); 944 result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, 945 &request->dispatch); 946 if (result != ISC_R_SUCCESS) 947 goto cleanup; 948 949 result = dns_dispatch_addresponse2(request->dispatch, destaddr, task, 950 req_response, request, &id, 951 &request->dispentry, 952 requestmgr->socketmgr); 953 if (result != ISC_R_SUCCESS) 954 goto cleanup; 955 socket = req_getsocket(request); 956 INSIST(socket != NULL); 957 958 message->id = id; 959 if (setkey) { 960 result = dns_message_settsigkey(message, request->tsigkey); 961 if (result != ISC_R_SUCCESS) 962 goto cleanup; 963 } 964 result = req_render(message, &request->query, options, mctx); 965 if (result == DNS_R_USETCP && 966 (options & DNS_REQUESTOPT_TCP) == 0) { 967 /* 968 * Try again using TCP. 969 */ 970 dns_message_renderreset(message); 971 dns_dispatch_removeresponse(&request->dispentry, NULL); 972 dns_dispatch_detach(&request->dispatch); 973 socket = NULL; 974 options |= DNS_REQUESTOPT_TCP; 975 setkey = ISC_FALSE; 976 goto use_tcp; 977 } 978 if (result != ISC_R_SUCCESS) 979 goto cleanup; 980 981 result = dns_message_getquerytsig(message, mctx, &request->tsig); 982 if (result != ISC_R_SUCCESS) 983 goto cleanup; 984 985 LOCK(&requestmgr->lock); 986 if (requestmgr->exiting) { 987 UNLOCK(&requestmgr->lock); 988 result = ISC_R_SHUTTINGDOWN; 989 goto cleanup; 990 } 991 requestmgr_attach(requestmgr, &request->requestmgr); 992 request->hash = mgr_gethash(requestmgr); 993 ISC_LIST_APPEND(requestmgr->requests, request, link); 994 UNLOCK(&requestmgr->lock); 995 996 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout); 997 if (result != ISC_R_SUCCESS) 998 goto unlink; 999 1000 request->destaddr = *destaddr; 1001 if (tcp) { 1002 result = isc_socket_connect(socket, destaddr, task, 1003 req_connected, request); 1004 if (result != ISC_R_SUCCESS) 1005 goto unlink; 1006 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP; 1007 } else { 1008 result = req_send(request, task, destaddr); 1009 if (result != ISC_R_SUCCESS) 1010 goto unlink; 1011 } 1012 1013 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", 1014 request); 1015 *requestp = request; 1016 return (ISC_R_SUCCESS); 1017 1018 unlink: 1019 LOCK(&requestmgr->lock); 1020 ISC_LIST_UNLINK(requestmgr->requests, request, link); 1021 UNLOCK(&requestmgr->lock); 1022 1023 cleanup: 1024 if (tclone != NULL) 1025 isc_task_detach(&tclone); 1026 req_destroy(request); 1027 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s", 1028 dns_result_totext(result)); 1029 return (result); 1030} 1031 1032static isc_result_t 1033req_render(dns_message_t *message, isc_buffer_t **bufferp, 1034 unsigned int options, isc_mem_t *mctx) 1035{ 1036 isc_buffer_t *buf1 = NULL; 1037 isc_buffer_t *buf2 = NULL; 1038 isc_result_t result; 1039 isc_region_t r; 1040 isc_boolean_t tcp = ISC_FALSE; 1041 dns_compress_t cctx; 1042 isc_boolean_t cleanup_cctx = ISC_FALSE; 1043 1044 REQUIRE(bufferp != NULL && *bufferp == NULL); 1045 1046 req_log(ISC_LOG_DEBUG(3), "request_render"); 1047 1048 /* 1049 * Create buffer able to hold largest possible message. 1050 */ 1051 result = isc_buffer_allocate(mctx, &buf1, 65535); 1052 if (result != ISC_R_SUCCESS) 1053 return (result); 1054 1055 result = dns_compress_init(&cctx, -1, mctx); 1056 if (result != ISC_R_SUCCESS) 1057 return (result); 1058 cleanup_cctx = ISC_TRUE; 1059 1060 if ((options & DNS_REQUESTOPT_CASE) != 0) 1061 dns_compress_setsensitive(&cctx, ISC_TRUE); 1062 1063 /* 1064 * Render message. 1065 */ 1066 result = dns_message_renderbegin(message, &cctx, buf1); 1067 if (result != ISC_R_SUCCESS) 1068 goto cleanup; 1069 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); 1070 if (result != ISC_R_SUCCESS) 1071 goto cleanup; 1072 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0); 1073 if (result != ISC_R_SUCCESS) 1074 goto cleanup; 1075 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0); 1076 if (result != ISC_R_SUCCESS) 1077 goto cleanup; 1078 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0); 1079 if (result != ISC_R_SUCCESS) 1080 goto cleanup; 1081 result = dns_message_renderend(message); 1082 if (result != ISC_R_SUCCESS) 1083 goto cleanup; 1084 1085 dns_compress_invalidate(&cctx); 1086 cleanup_cctx = ISC_FALSE; 1087 1088 /* 1089 * Copy rendered message to exact sized buffer. 1090 */ 1091 isc_buffer_usedregion(buf1, &r); 1092 if ((options & DNS_REQUESTOPT_TCP) != 0) { 1093 tcp = ISC_TRUE; 1094 } else if (r.length > 512) { 1095 result = DNS_R_USETCP; 1096 goto cleanup; 1097 } 1098 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0)); 1099 if (result != ISC_R_SUCCESS) 1100 goto cleanup; 1101 if (tcp) 1102 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length); 1103 result = isc_buffer_copyregion(buf2, &r); 1104 if (result != ISC_R_SUCCESS) 1105 goto cleanup; 1106 1107 /* 1108 * Cleanup and return. 1109 */ 1110 isc_buffer_free(&buf1); 1111 *bufferp = buf2; 1112 return (ISC_R_SUCCESS); 1113 1114 cleanup: 1115 dns_message_renderreset(message); 1116 if (buf1 != NULL) 1117 isc_buffer_free(&buf1); 1118 if (buf2 != NULL) 1119 isc_buffer_free(&buf2); 1120 if (cleanup_cctx) 1121 dns_compress_invalidate(&cctx); 1122 return (result); 1123} 1124 1125 1126/* 1127 * If this request is no longer waiting for events, 1128 * send the completion event. This will ultimately 1129 * cause the request to be destroyed. 1130 * 1131 * Requires: 1132 * 'request' is locked by the caller. 1133 */ 1134static void 1135send_if_done(dns_request_t *request, isc_result_t result) { 1136 if (request->event != NULL && !request->canceling) 1137 req_sendevent(request, result); 1138} 1139 1140/* 1141 * Handle the control event. 1142 */ 1143static void 1144do_cancel(isc_task_t *task, isc_event_t *event) { 1145 dns_request_t *request = event->ev_arg; 1146 UNUSED(task); 1147 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL); 1148 LOCK(&request->requestmgr->locks[request->hash]); 1149 request->canceling = ISC_FALSE; 1150 if (!DNS_REQUEST_CANCELED(request)) 1151 req_cancel(request); 1152 send_if_done(request, ISC_R_CANCELED); 1153 UNLOCK(&request->requestmgr->locks[request->hash]); 1154} 1155 1156void 1157dns_request_cancel(dns_request_t *request) { 1158 REQUIRE(VALID_REQUEST(request)); 1159 1160 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request); 1161 1162 REQUIRE(VALID_REQUEST(request)); 1163 1164 LOCK(&request->requestmgr->locks[request->hash]); 1165 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) { 1166 isc_event_t *ev = &request->ctlevent; 1167 isc_task_send(request->event->ev_sender, &ev); 1168 request->canceling = ISC_TRUE; 1169 } 1170 UNLOCK(&request->requestmgr->locks[request->hash]); 1171} 1172 1173isc_result_t 1174dns_request_getresponse(dns_request_t *request, dns_message_t *message, 1175 unsigned int options) 1176{ 1177 isc_result_t result; 1178 1179 REQUIRE(VALID_REQUEST(request)); 1180 REQUIRE(request->answer != NULL); 1181 1182 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p", 1183 request); 1184 1185 result = dns_message_setquerytsig(message, request->tsig); 1186 if (result != ISC_R_SUCCESS) 1187 return (result); 1188 result = dns_message_settsigkey(message, request->tsigkey); 1189 if (result != ISC_R_SUCCESS) 1190 return (result); 1191 result = dns_message_parse(message, request->answer, options); 1192 if (result != ISC_R_SUCCESS) 1193 return (result); 1194 if (request->tsigkey != NULL) 1195 result = dns_tsig_verify(request->answer, message, NULL, NULL); 1196 return (result); 1197} 1198 1199isc_boolean_t 1200dns_request_usedtcp(dns_request_t *request) { 1201 REQUIRE(VALID_REQUEST(request)); 1202 1203 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0)); 1204} 1205 1206void 1207dns_request_destroy(dns_request_t **requestp) { 1208 dns_request_t *request; 1209 1210 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp)); 1211 1212 request = *requestp; 1213 1214 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request); 1215 1216 LOCK(&request->requestmgr->lock); 1217 LOCK(&request->requestmgr->locks[request->hash]); 1218 ISC_LIST_UNLINK(request->requestmgr->requests, request, link); 1219 INSIST(!DNS_REQUEST_CONNECTING(request)); 1220 INSIST(!DNS_REQUEST_SENDING(request)); 1221 UNLOCK(&request->requestmgr->locks[request->hash]); 1222 UNLOCK(&request->requestmgr->lock); 1223 1224 /* 1225 * These should have been cleaned up by req_cancel() before 1226 * the completion event was sent. 1227 */ 1228 INSIST(!ISC_LINK_LINKED(request, link)); 1229 INSIST(request->dispentry == NULL); 1230 INSIST(request->dispatch == NULL); 1231 INSIST(request->timer == NULL); 1232 1233 req_destroy(request); 1234 1235 *requestp = NULL; 1236} 1237 1238/*** 1239 *** Private: request. 1240 ***/ 1241 1242static isc_socket_t * 1243req_getsocket(dns_request_t *request) { 1244 unsigned int dispattr; 1245 isc_socket_t *socket; 1246 1247 dispattr = dns_dispatch_getattributes(request->dispatch); 1248 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { 1249 INSIST(request->dispentry != NULL); 1250 socket = dns_dispatch_getentrysocket(request->dispentry); 1251 } else 1252 socket = dns_dispatch_getsocket(request->dispatch); 1253 1254 return (socket); 1255} 1256 1257static void 1258req_connected(isc_task_t *task, isc_event_t *event) { 1259 isc_socketevent_t *sevent = (isc_socketevent_t *)event; 1260 isc_result_t result; 1261 dns_request_t *request = event->ev_arg; 1262 1263 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); 1264 REQUIRE(VALID_REQUEST(request)); 1265 REQUIRE(DNS_REQUEST_CONNECTING(request)); 1266 1267 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request); 1268 1269 LOCK(&request->requestmgr->locks[request->hash]); 1270 request->flags &= ~DNS_REQUEST_F_CONNECTING; 1271 1272 if (DNS_REQUEST_CANCELED(request)) { 1273 /* 1274 * Send delayed event. 1275 */ 1276 if (DNS_REQUEST_TIMEDOUT(request)) 1277 send_if_done(request, ISC_R_TIMEDOUT); 1278 else 1279 send_if_done(request, ISC_R_CANCELED); 1280 } else { 1281 dns_dispatch_starttcp(request->dispatch); 1282 result = sevent->result; 1283 if (result == ISC_R_SUCCESS) 1284 result = req_send(request, task, NULL); 1285 1286 if (result != ISC_R_SUCCESS) { 1287 req_cancel(request); 1288 send_if_done(request, ISC_R_CANCELED); 1289 } 1290 } 1291 UNLOCK(&request->requestmgr->locks[request->hash]); 1292 isc_event_free(&event); 1293} 1294 1295static void 1296req_senddone(isc_task_t *task, isc_event_t *event) { 1297 isc_socketevent_t *sevent = (isc_socketevent_t *)event; 1298 dns_request_t *request = event->ev_arg; 1299 1300 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); 1301 REQUIRE(VALID_REQUEST(request)); 1302 REQUIRE(DNS_REQUEST_SENDING(request)); 1303 1304 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request); 1305 1306 UNUSED(task); 1307 1308 LOCK(&request->requestmgr->locks[request->hash]); 1309 request->flags &= ~DNS_REQUEST_F_SENDING; 1310 1311 if (DNS_REQUEST_CANCELED(request)) { 1312 /* 1313 * Send delayed event. 1314 */ 1315 if (DNS_REQUEST_TIMEDOUT(request)) 1316 send_if_done(request, ISC_R_TIMEDOUT); 1317 else 1318 send_if_done(request, ISC_R_CANCELED); 1319 } else if (sevent->result != ISC_R_SUCCESS) { 1320 req_cancel(request); 1321 send_if_done(request, ISC_R_CANCELED); 1322 } 1323 UNLOCK(&request->requestmgr->locks[request->hash]); 1324 1325 isc_event_free(&event); 1326} 1327 1328static void 1329req_response(isc_task_t *task, isc_event_t *event) { 1330 isc_result_t result; 1331 dns_request_t *request = event->ev_arg; 1332 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; 1333 isc_region_t r; 1334 1335 REQUIRE(VALID_REQUEST(request)); 1336 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH); 1337 1338 UNUSED(task); 1339 1340 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request, 1341 dns_result_totext(devent->result)); 1342 1343 LOCK(&request->requestmgr->locks[request->hash]); 1344 result = devent->result; 1345 if (result != ISC_R_SUCCESS) 1346 goto done; 1347 1348 /* 1349 * Copy buffer to request. 1350 */ 1351 isc_buffer_usedregion(&devent->buffer, &r); 1352 result = isc_buffer_allocate(request->mctx, &request->answer, 1353 r.length); 1354 if (result != ISC_R_SUCCESS) 1355 goto done; 1356 result = isc_buffer_copyregion(request->answer, &r); 1357 if (result != ISC_R_SUCCESS) 1358 isc_buffer_free(&request->answer); 1359 done: 1360 /* 1361 * Cleanup. 1362 */ 1363 dns_dispatch_removeresponse(&request->dispentry, &devent); 1364 req_cancel(request); 1365 /* 1366 * Send completion event. 1367 */ 1368 send_if_done(request, result); 1369 UNLOCK(&request->requestmgr->locks[request->hash]); 1370} 1371 1372static void 1373req_timeout(isc_task_t *task, isc_event_t *event) { 1374 dns_request_t *request = event->ev_arg; 1375 isc_result_t result; 1376 1377 REQUIRE(VALID_REQUEST(request)); 1378 1379 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request); 1380 1381 UNUSED(task); 1382 LOCK(&request->requestmgr->locks[request->hash]); 1383 if (event->ev_type == ISC_TIMEREVENT_TICK && 1384 request->udpcount-- != 0) { 1385 if (! DNS_REQUEST_SENDING(request)) { 1386 result = req_send(request, task, &request->destaddr); 1387 if (result != ISC_R_SUCCESS) { 1388 req_cancel(request); 1389 send_if_done(request, result); 1390 } 1391 } 1392 } else { 1393 request->flags |= DNS_REQUEST_F_TIMEDOUT; 1394 req_cancel(request); 1395 send_if_done(request, ISC_R_TIMEDOUT); 1396 } 1397 UNLOCK(&request->requestmgr->locks[request->hash]); 1398 isc_event_free(&event); 1399} 1400 1401static void 1402req_sendevent(dns_request_t *request, isc_result_t result) { 1403 isc_task_t *task; 1404 1405 REQUIRE(VALID_REQUEST(request)); 1406 1407 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request); 1408 1409 /* 1410 * Lock held by caller. 1411 */ 1412 task = request->event->ev_sender; 1413 request->event->ev_sender = request; 1414 request->event->result = result; 1415 isc_task_sendanddetach(&task, (isc_event_t **)&request->event); 1416} 1417 1418static void 1419req_destroy(dns_request_t *request) { 1420 isc_mem_t *mctx; 1421 1422 REQUIRE(VALID_REQUEST(request)); 1423 1424 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request); 1425 1426 request->magic = 0; 1427 if (request->query != NULL) 1428 isc_buffer_free(&request->query); 1429 if (request->answer != NULL) 1430 isc_buffer_free(&request->answer); 1431 if (request->event != NULL) 1432 isc_event_free((isc_event_t **)&request->event); 1433 if (request->dispentry != NULL) 1434 dns_dispatch_removeresponse(&request->dispentry, NULL); 1435 if (request->dispatch != NULL) 1436 dns_dispatch_detach(&request->dispatch); 1437 if (request->timer != NULL) 1438 isc_timer_detach(&request->timer); 1439 if (request->tsig != NULL) 1440 isc_buffer_free(&request->tsig); 1441 if (request->tsigkey != NULL) 1442 dns_tsigkey_detach(&request->tsigkey); 1443 if (request->requestmgr != NULL) 1444 requestmgr_detach(&request->requestmgr); 1445 mctx = request->mctx; 1446 isc_mem_put(mctx, request, sizeof(*request)); 1447 isc_mem_detach(&mctx); 1448} 1449 1450/* 1451 * Stop the current request. Must be called from the request's task. 1452 */ 1453static void 1454req_cancel(dns_request_t *request) { 1455 isc_socket_t *socket; 1456 unsigned int dispattr; 1457 1458 REQUIRE(VALID_REQUEST(request)); 1459 1460 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request); 1461 1462 /* 1463 * Lock held by caller. 1464 */ 1465 request->flags |= DNS_REQUEST_F_CANCELED; 1466 1467 if (request->timer != NULL) 1468 isc_timer_detach(&request->timer); 1469 dispattr = dns_dispatch_getattributes(request->dispatch); 1470 socket = NULL; 1471 if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) { 1472 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) { 1473 if (request->dispentry != NULL) { 1474 socket = dns_dispatch_getentrysocket( 1475 request->dispentry); 1476 } 1477 } else 1478 socket = dns_dispatch_getsocket(request->dispatch); 1479 if (DNS_REQUEST_CONNECTING(request) && socket != NULL) 1480 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT); 1481 if (DNS_REQUEST_SENDING(request) && socket != NULL) 1482 isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND); 1483 } 1484 if (request->dispentry != NULL) 1485 dns_dispatch_removeresponse(&request->dispentry, NULL); 1486 dns_dispatch_detach(&request->dispatch); 1487} 1488 1489static void 1490req_log(int level, const char *fmt, ...) { 1491 va_list ap; 1492 1493 va_start(ap, fmt); 1494 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1495 DNS_LOGMODULE_REQUEST, level, fmt, ap); 1496 va_end(ap); 1497} 1498