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