00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/magic.h>
00025 #include <isc/mem.h>
00026 #include <isc/task.h>
00027 #include <isc/timer.h>
00028 #include <isc/util.h>
00029
00030 #include <dns/acl.h>
00031 #include <dns/compress.h>
00032 #include <dns/dispatch.h>
00033 #include <dns/events.h>
00034 #include <dns/log.h>
00035 #include <dns/message.h>
00036 #include <dns/rdata.h>
00037 #include <dns/rdatastruct.h>
00038 #include <dns/request.h>
00039 #include <dns/result.h>
00040 #include <dns/tsig.h>
00041
00042 #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
00043 #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
00044
00045 #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
00046 #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
00047
00048 typedef ISC_LIST(dns_request_t) dns_requestlist_t;
00049
00050 #define DNS_REQUEST_NLOCKS 7
00051
00052 struct dns_requestmgr {
00053 unsigned int magic;
00054 isc_mutex_t lock;
00055 isc_mem_t *mctx;
00056
00057
00058 isc_int32_t eref;
00059 isc_int32_t iref;
00060 isc_timermgr_t *timermgr;
00061 isc_socketmgr_t *socketmgr;
00062 isc_taskmgr_t *taskmgr;
00063 dns_dispatchmgr_t *dispatchmgr;
00064 dns_dispatch_t *dispatchv4;
00065 dns_dispatch_t *dispatchv6;
00066 isc_boolean_t exiting;
00067 isc_eventlist_t whenshutdown;
00068 unsigned int hash;
00069 isc_mutex_t locks[DNS_REQUEST_NLOCKS];
00070 dns_requestlist_t requests;
00071 };
00072
00073 struct dns_request {
00074 unsigned int magic;
00075 unsigned int hash;
00076 isc_mem_t *mctx;
00077 isc_int32_t flags;
00078 ISC_LINK(dns_request_t) link;
00079 isc_buffer_t *query;
00080 isc_buffer_t *answer;
00081 dns_requestevent_t *event;
00082 dns_dispatch_t *dispatch;
00083 dns_dispentry_t *dispentry;
00084 isc_timer_t *timer;
00085 dns_requestmgr_t *requestmgr;
00086 isc_buffer_t *tsig;
00087 dns_tsigkey_t *tsigkey;
00088 isc_event_t ctlevent;
00089 isc_boolean_t canceling;
00090 isc_sockaddr_t destaddr;
00091 unsigned int udpcount;
00092 isc_dscp_t dscp;
00093 };
00094
00095 #define DNS_REQUEST_F_CONNECTING 0x0001
00096 #define DNS_REQUEST_F_SENDING 0x0002
00097 #define DNS_REQUEST_F_CANCELED 0x0004
00098
00099 #define DNS_REQUEST_F_TIMEDOUT 0x0008
00100 #define DNS_REQUEST_F_TCP 0x0010
00101 #define DNS_REQUEST_CANCELED(r) \
00102 (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
00103 #define DNS_REQUEST_CONNECTING(r) \
00104 (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
00105 #define DNS_REQUEST_SENDING(r) \
00106 (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
00107 #define DNS_REQUEST_TIMEDOUT(r) \
00108 (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
00109
00110
00111
00112
00113
00114
00115 static void mgr_destroy(dns_requestmgr_t *requestmgr);
00116 static void mgr_shutdown(dns_requestmgr_t *requestmgr);
00117 static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
00118 static void send_shutdown_events(dns_requestmgr_t *requestmgr);
00119
00120 static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
00121 unsigned int options, isc_mem_t *mctx);
00122 static void req_senddone(isc_task_t *task, isc_event_t *event);
00123 static void req_response(isc_task_t *task, isc_event_t *event);
00124 static void req_timeout(isc_task_t *task, isc_event_t *event);
00125 static isc_socket_t * req_getsocket(dns_request_t *request);
00126 static void req_connected(isc_task_t *task, isc_event_t *event);
00127 static void req_sendevent(dns_request_t *request, isc_result_t result);
00128 static void req_cancel(dns_request_t *request);
00129 static void req_destroy(dns_request_t *request);
00130 static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
00131 static void do_cancel(isc_task_t *task, isc_event_t *event);
00132
00133
00134
00135
00136
00137 isc_result_t
00138 dns_requestmgr_create(isc_mem_t *mctx,
00139 isc_timermgr_t *timermgr,
00140 isc_socketmgr_t *socketmgr,
00141 isc_taskmgr_t *taskmgr,
00142 dns_dispatchmgr_t *dispatchmgr,
00143 dns_dispatch_t *dispatchv4,
00144 dns_dispatch_t *dispatchv6,
00145 dns_requestmgr_t **requestmgrp)
00146 {
00147 dns_requestmgr_t *requestmgr;
00148 isc_socket_t *sock;
00149 isc_result_t result;
00150 int i;
00151 unsigned int dispattr;
00152
00153 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
00154
00155 REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
00156 REQUIRE(timermgr != NULL);
00157 REQUIRE(socketmgr != NULL);
00158 REQUIRE(taskmgr != NULL);
00159 REQUIRE(dispatchmgr != NULL);
00160 UNUSED(sock);
00161 if (dispatchv4 != NULL) {
00162 dispattr = dns_dispatch_getattributes(dispatchv4);
00163 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
00164 }
00165 if (dispatchv6 != NULL) {
00166 dispattr = dns_dispatch_getattributes(dispatchv6);
00167 REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
00168 }
00169
00170 requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
00171 if (requestmgr == NULL)
00172 return (ISC_R_NOMEMORY);
00173
00174 result = isc_mutex_init(&requestmgr->lock);
00175 if (result != ISC_R_SUCCESS) {
00176 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
00177 return (result);
00178 }
00179 for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
00180 result = isc_mutex_init(&requestmgr->locks[i]);
00181 if (result != ISC_R_SUCCESS) {
00182 while (--i >= 0)
00183 DESTROYLOCK(&requestmgr->locks[i]);
00184 DESTROYLOCK(&requestmgr->lock);
00185 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
00186 return (result);
00187 }
00188 }
00189 requestmgr->timermgr = timermgr;
00190 requestmgr->socketmgr = socketmgr;
00191 requestmgr->taskmgr = taskmgr;
00192 requestmgr->dispatchmgr = dispatchmgr;
00193 requestmgr->dispatchv4 = NULL;
00194 if (dispatchv4 != NULL)
00195 dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
00196 requestmgr->dispatchv6 = NULL;
00197 if (dispatchv6 != NULL)
00198 dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
00199 requestmgr->mctx = NULL;
00200 isc_mem_attach(mctx, &requestmgr->mctx);
00201 requestmgr->eref = 1;
00202 requestmgr->iref = 0;
00203 ISC_LIST_INIT(requestmgr->whenshutdown);
00204 ISC_LIST_INIT(requestmgr->requests);
00205 requestmgr->exiting = ISC_FALSE;
00206 requestmgr->hash = 0;
00207 requestmgr->magic = REQUESTMGR_MAGIC;
00208
00209 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
00210
00211 *requestmgrp = requestmgr;
00212 return (ISC_R_SUCCESS);
00213 }
00214
00215 void
00216 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
00217 isc_event_t **eventp)
00218 {
00219 isc_task_t *clone;
00220 isc_event_t *event;
00221
00222 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
00223
00224 REQUIRE(VALID_REQUESTMGR(requestmgr));
00225 REQUIRE(eventp != NULL);
00226
00227 event = *eventp;
00228 *eventp = NULL;
00229
00230 LOCK(&requestmgr->lock);
00231
00232 if (requestmgr->exiting) {
00233
00234
00235
00236 event->ev_sender = requestmgr;
00237 isc_task_send(task, &event);
00238 } else {
00239 clone = NULL;
00240 isc_task_attach(task, &clone);
00241 event->ev_sender = clone;
00242 ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
00243 }
00244 UNLOCK(&requestmgr->lock);
00245 }
00246
00247 void
00248 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
00249
00250 REQUIRE(VALID_REQUESTMGR(requestmgr));
00251
00252 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
00253
00254 LOCK(&requestmgr->lock);
00255 mgr_shutdown(requestmgr);
00256 UNLOCK(&requestmgr->lock);
00257 }
00258
00259 static void
00260 mgr_shutdown(dns_requestmgr_t *requestmgr) {
00261 dns_request_t *request;
00262
00263
00264
00265
00266 if (!requestmgr->exiting) {
00267 requestmgr->exiting = ISC_TRUE;
00268 for (request = ISC_LIST_HEAD(requestmgr->requests);
00269 request != NULL;
00270 request = ISC_LIST_NEXT(request, link)) {
00271 dns_request_cancel(request);
00272 }
00273 if (requestmgr->iref == 0) {
00274 INSIST(ISC_LIST_EMPTY(requestmgr->requests));
00275 send_shutdown_events(requestmgr);
00276 }
00277 }
00278 }
00279
00280 static void
00281 requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
00282
00283
00284
00285
00286
00287 REQUIRE(VALID_REQUESTMGR(source));
00288 REQUIRE(targetp != NULL && *targetp == NULL);
00289
00290 REQUIRE(!source->exiting);
00291
00292 source->iref++;
00293 *targetp = source;
00294
00295 req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
00296 source, source->eref, source->iref);
00297 }
00298
00299 static void
00300 requestmgr_detach(dns_requestmgr_t **requestmgrp) {
00301 dns_requestmgr_t *requestmgr;
00302 isc_boolean_t need_destroy = ISC_FALSE;
00303
00304 REQUIRE(requestmgrp != NULL);
00305 requestmgr = *requestmgrp;
00306 REQUIRE(VALID_REQUESTMGR(requestmgr));
00307
00308 *requestmgrp = NULL;
00309 LOCK(&requestmgr->lock);
00310 INSIST(requestmgr->iref > 0);
00311 requestmgr->iref--;
00312
00313 req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
00314 requestmgr, requestmgr->eref, requestmgr->iref);
00315
00316 if (requestmgr->iref == 0 && requestmgr->exiting) {
00317 INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
00318 send_shutdown_events(requestmgr);
00319 if (requestmgr->eref == 0)
00320 need_destroy = ISC_TRUE;
00321 }
00322 UNLOCK(&requestmgr->lock);
00323
00324 if (need_destroy)
00325 mgr_destroy(requestmgr);
00326 }
00327
00328 void
00329 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
00330
00331 REQUIRE(VALID_REQUESTMGR(source));
00332 REQUIRE(targetp != NULL && *targetp == NULL);
00333 REQUIRE(!source->exiting);
00334
00335 LOCK(&source->lock);
00336 source->eref++;
00337 *targetp = source;
00338 UNLOCK(&source->lock);
00339
00340 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
00341 source, source->eref, source->iref);
00342 }
00343
00344 void
00345 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
00346 dns_requestmgr_t *requestmgr;
00347 isc_boolean_t need_destroy = ISC_FALSE;
00348
00349 REQUIRE(requestmgrp != NULL);
00350 requestmgr = *requestmgrp;
00351 REQUIRE(VALID_REQUESTMGR(requestmgr));
00352
00353 LOCK(&requestmgr->lock);
00354 INSIST(requestmgr->eref > 0);
00355 requestmgr->eref--;
00356
00357 req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
00358 requestmgr, requestmgr->eref, requestmgr->iref);
00359
00360 if (requestmgr->eref == 0 && requestmgr->iref == 0) {
00361 INSIST(requestmgr->exiting &&
00362 ISC_LIST_HEAD(requestmgr->requests) == NULL);
00363 need_destroy = ISC_TRUE;
00364 }
00365 UNLOCK(&requestmgr->lock);
00366
00367 if (need_destroy)
00368 mgr_destroy(requestmgr);
00369
00370 *requestmgrp = NULL;
00371 }
00372
00373 static void
00374 send_shutdown_events(dns_requestmgr_t *requestmgr) {
00375 isc_event_t *event, *next_event;
00376 isc_task_t *etask;
00377
00378 req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
00379
00380
00381
00382
00383 for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
00384 event != NULL;
00385 event = next_event) {
00386 next_event = ISC_LIST_NEXT(event, ev_link);
00387 ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
00388 etask = event->ev_sender;
00389 event->ev_sender = requestmgr;
00390 isc_task_sendanddetach(&etask, &event);
00391 }
00392 }
00393
00394 static void
00395 mgr_destroy(dns_requestmgr_t *requestmgr) {
00396 int i;
00397 isc_mem_t *mctx;
00398
00399 req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
00400
00401 REQUIRE(requestmgr->eref == 0);
00402 REQUIRE(requestmgr->iref == 0);
00403
00404 DESTROYLOCK(&requestmgr->lock);
00405 for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
00406 DESTROYLOCK(&requestmgr->locks[i]);
00407 if (requestmgr->dispatchv4 != NULL)
00408 dns_dispatch_detach(&requestmgr->dispatchv4);
00409 if (requestmgr->dispatchv6 != NULL)
00410 dns_dispatch_detach(&requestmgr->dispatchv6);
00411 requestmgr->magic = 0;
00412 mctx = requestmgr->mctx;
00413 isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
00414 isc_mem_detach(&mctx);
00415 }
00416
00417 static unsigned int
00418 mgr_gethash(dns_requestmgr_t *requestmgr) {
00419 req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
00420
00421
00422
00423 requestmgr->hash++;
00424 return (requestmgr->hash % DNS_REQUEST_NLOCKS);
00425 }
00426
00427 static inline isc_result_t
00428 req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
00429 isc_region_t r;
00430 isc_socket_t *sock;
00431 isc_socketevent_t *sendevent;
00432 isc_result_t result;
00433
00434 req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
00435
00436 REQUIRE(VALID_REQUEST(request));
00437 sock = req_getsocket(request);
00438 isc_buffer_usedregion(request->query, &r);
00439
00440
00441
00442
00443
00444 sendevent = isc_socket_socketevent(request->mctx, sock,
00445 ISC_SOCKEVENT_SENDDONE,
00446 req_senddone, request);
00447 if (sendevent == NULL)
00448 return (ISC_R_NOMEMORY);
00449 if (request->dscp == -1) {
00450 sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
00451 sendevent->dscp = 0;
00452 } else {
00453 sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
00454 sendevent->dscp = request->dscp;
00455 }
00456
00457 result = isc_socket_sendto2(sock, &r, task, address, NULL,
00458 sendevent, 0);
00459 if (result == ISC_R_SUCCESS)
00460 request->flags |= DNS_REQUEST_F_SENDING;
00461 return (result);
00462 }
00463
00464 static isc_result_t
00465 new_request(isc_mem_t *mctx, dns_request_t **requestp)
00466 {
00467 dns_request_t *request;
00468
00469 request = isc_mem_get(mctx, sizeof(*request));
00470 if (request == NULL)
00471 return (ISC_R_NOMEMORY);
00472
00473
00474
00475
00476 request->magic = 0;
00477 request->mctx = NULL;
00478 request->flags = 0;
00479 ISC_LINK_INIT(request, link);
00480 request->query = NULL;
00481 request->answer = NULL;
00482 request->event = NULL;
00483 request->dispatch = NULL;
00484 request->dispentry = NULL;
00485 request->timer = NULL;
00486 request->requestmgr = NULL;
00487 request->tsig = NULL;
00488 request->tsigkey = NULL;
00489 request->dscp = -1;
00490 ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
00491 DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
00492 NULL, NULL);
00493 request->canceling = ISC_FALSE;
00494 request->udpcount = 0;
00495
00496 isc_mem_attach(mctx, &request->mctx);
00497
00498 request->magic = REQUEST_MAGIC;
00499 *requestp = request;
00500 return (ISC_R_SUCCESS);
00501 }
00502
00503
00504 static isc_boolean_t
00505 isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
00506 dns_acl_t *blackhole;
00507 isc_netaddr_t netaddr;
00508 int match;
00509 isc_boolean_t drop = ISC_FALSE;
00510 char netaddrstr[ISC_NETADDR_FORMATSIZE];
00511
00512 blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
00513 if (blackhole != NULL) {
00514 isc_netaddr_fromsockaddr(&netaddr, destaddr);
00515 if (dns_acl_match(&netaddr, NULL, blackhole,
00516 NULL, &match, NULL) == ISC_R_SUCCESS &&
00517 match > 0)
00518 drop = ISC_TRUE;
00519 }
00520 if (drop) {
00521 isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
00522 req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
00523 }
00524 return (drop);
00525 }
00526
00527 static isc_result_t
00528 create_tcp_dispatch(isc_boolean_t newtcp, isc_boolean_t share,
00529 dns_requestmgr_t *requestmgr,
00530 isc_sockaddr_t *srcaddr,
00531 isc_sockaddr_t *destaddr, isc_dscp_t dscp,
00532 isc_boolean_t *connected, dns_dispatch_t **dispatchp)
00533 {
00534 isc_result_t result;
00535 isc_socket_t *sock = NULL;
00536 isc_sockaddr_t src;
00537 unsigned int attrs;
00538 isc_sockaddr_t bind_any;
00539
00540 if (!newtcp && share) {
00541 result = dns_dispatch_gettcp2(requestmgr->dispatchmgr,
00542 destaddr, srcaddr,
00543 connected, dispatchp);
00544 if (result == ISC_R_SUCCESS) {
00545 char peer[ISC_SOCKADDR_FORMATSIZE];
00546
00547 isc_sockaddr_format(destaddr, peer, sizeof(peer));
00548 req_log(ISC_LOG_DEBUG(1), "attached to %s TCP "
00549 "connection to %s",
00550 *connected ? "existing" : "pending", peer);
00551 return (result);
00552 }
00553 } else if (!newtcp) {
00554 result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr,
00555 srcaddr, dispatchp);
00556 if (result == ISC_R_SUCCESS) {
00557 char peer[ISC_SOCKADDR_FORMATSIZE];
00558
00559 *connected = ISC_TRUE;
00560 isc_sockaddr_format(destaddr, peer, sizeof(peer));
00561 req_log(ISC_LOG_DEBUG(1), "attached to existing TCP "
00562 "connection to %s", peer);
00563 return (result);
00564 }
00565 }
00566
00567 result = isc_socket_create(requestmgr->socketmgr,
00568 isc_sockaddr_pf(destaddr),
00569 isc_sockettype_tcp, &sock);
00570 if (result != ISC_R_SUCCESS)
00571 return (result);
00572 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
00573 if (srcaddr == NULL) {
00574 isc_sockaddr_anyofpf(&bind_any,
00575 isc_sockaddr_pf(destaddr));
00576 result = isc_socket_bind(sock, &bind_any, 0);
00577 } else {
00578 src = *srcaddr;
00579 isc_sockaddr_setport(&src, 0);
00580 result = isc_socket_bind(sock, &src, 0);
00581 }
00582 if (result != ISC_R_SUCCESS)
00583 goto cleanup;
00584 #endif
00585
00586 attrs = 0;
00587 attrs |= DNS_DISPATCHATTR_TCP;
00588 if (isc_sockaddr_pf(destaddr) == AF_INET)
00589 attrs |= DNS_DISPATCHATTR_IPV4;
00590 else
00591 attrs |= DNS_DISPATCHATTR_IPV6;
00592 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
00593
00594 isc_socket_dscp(sock, dscp);
00595 result = dns_dispatch_createtcp2(requestmgr->dispatchmgr,
00596 sock, requestmgr->taskmgr,
00597 srcaddr, destaddr,
00598 4096, 32768, 32768, 16411, 16433,
00599 attrs, dispatchp);
00600 cleanup:
00601 isc_socket_detach(&sock);
00602 return (result);
00603 }
00604
00605 static isc_result_t
00606 find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
00607 isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
00608 {
00609 dns_dispatch_t *disp = NULL;
00610 unsigned int attrs, attrmask;
00611
00612 if (srcaddr == NULL) {
00613 switch (isc_sockaddr_pf(destaddr)) {
00614 case PF_INET:
00615 disp = requestmgr->dispatchv4;
00616 break;
00617
00618 case PF_INET6:
00619 disp = requestmgr->dispatchv6;
00620 break;
00621
00622 default:
00623 return (ISC_R_NOTIMPLEMENTED);
00624 }
00625 if (disp == NULL)
00626 return (ISC_R_FAMILYNOSUPPORT);
00627 dns_dispatch_attach(disp, dispatchp);
00628 return (ISC_R_SUCCESS);
00629 }
00630 attrs = 0;
00631 attrs |= DNS_DISPATCHATTR_UDP;
00632 switch (isc_sockaddr_pf(srcaddr)) {
00633 case PF_INET:
00634 attrs |= DNS_DISPATCHATTR_IPV4;
00635 break;
00636
00637 case PF_INET6:
00638 attrs |= DNS_DISPATCHATTR_IPV6;
00639 break;
00640
00641 default:
00642 return (ISC_R_NOTIMPLEMENTED);
00643 }
00644 attrmask = 0;
00645 attrmask |= DNS_DISPATCHATTR_UDP;
00646 attrmask |= DNS_DISPATCHATTR_TCP;
00647 attrmask |= DNS_DISPATCHATTR_IPV4;
00648 attrmask |= DNS_DISPATCHATTR_IPV6;
00649 return (dns_dispatch_getudp(requestmgr->dispatchmgr,
00650 requestmgr->socketmgr,
00651 requestmgr->taskmgr,
00652 srcaddr, 4096,
00653 32768, 32768, 16411, 16433,
00654 attrs, attrmask,
00655 dispatchp));
00656 }
00657
00658 static isc_result_t
00659 get_dispatch(isc_boolean_t tcp, isc_boolean_t newtcp, isc_boolean_t share,
00660 dns_requestmgr_t *requestmgr,
00661 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00662 isc_dscp_t dscp, isc_boolean_t *connected,
00663 dns_dispatch_t **dispatchp)
00664 {
00665 isc_result_t result;
00666
00667 if (tcp)
00668 result = create_tcp_dispatch(newtcp, share, requestmgr,
00669 srcaddr, destaddr, dscp,
00670 connected, dispatchp);
00671 else
00672 result = find_udp_dispatch(requestmgr, srcaddr,
00673 destaddr, dispatchp);
00674 return (result);
00675 }
00676
00677 static isc_result_t
00678 set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
00679 isc_time_t expires;
00680 isc_interval_t interval;
00681 isc_result_t result;
00682 isc_timertype_t timertype;
00683
00684 isc_interval_set(&interval, timeout, 0);
00685 result = isc_time_nowplusinterval(&expires, &interval);
00686 isc_interval_set(&interval, udpresend, 0);
00687
00688 timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
00689 if (result == ISC_R_SUCCESS)
00690 result = isc_timer_reset(timer, timertype, &expires,
00691 &interval, ISC_FALSE);
00692 return (result);
00693 }
00694
00695 isc_result_t
00696 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
00697 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00698 unsigned int options, unsigned int timeout,
00699 isc_task_t *task, isc_taskaction_t action, void *arg,
00700 dns_request_t **requestp)
00701 {
00702 return(dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
00703 -1, options, timeout, 0, 0, task, action,
00704 arg, requestp));
00705 }
00706
00707 isc_result_t
00708 dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
00709 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00710 unsigned int options, unsigned int timeout,
00711 unsigned int udptimeout, isc_task_t *task,
00712 isc_taskaction_t action, void *arg,
00713 dns_request_t **requestp)
00714 {
00715 unsigned int udpretries = 0;
00716
00717 if (udptimeout != 0)
00718 udpretries = timeout / udptimeout;
00719
00720 return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
00721 -1, options, timeout, udptimeout,
00722 udpretries, task, action, arg,
00723 requestp));
00724 }
00725
00726 isc_result_t
00727 dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
00728 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00729 unsigned int options, unsigned int timeout,
00730 unsigned int udptimeout, unsigned int udpretries,
00731 isc_task_t *task, isc_taskaction_t action, void *arg,
00732 dns_request_t **requestp)
00733 {
00734 return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
00735 -1, options, timeout, udptimeout,
00736 udpretries, task, action, arg,
00737 requestp));
00738 }
00739
00740 isc_result_t
00741 dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
00742 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00743 isc_dscp_t dscp, unsigned int options,
00744 unsigned int timeout, unsigned int udptimeout,
00745 unsigned int udpretries, isc_task_t *task,
00746 isc_taskaction_t action, void *arg,
00747 dns_request_t **requestp)
00748 {
00749 dns_request_t *request = NULL;
00750 isc_task_t *tclone = NULL;
00751 isc_socket_t *sock = NULL;
00752 isc_result_t result;
00753 isc_mem_t *mctx;
00754 dns_messageid_t id;
00755 isc_boolean_t tcp = ISC_FALSE;
00756 isc_boolean_t newtcp = ISC_FALSE;
00757 isc_boolean_t share = ISC_FALSE;
00758 isc_region_t r;
00759 isc_boolean_t connected = ISC_FALSE;
00760 unsigned int dispopt = 0;
00761
00762 REQUIRE(VALID_REQUESTMGR(requestmgr));
00763 REQUIRE(msgbuf != NULL);
00764 REQUIRE(destaddr != NULL);
00765 REQUIRE(task != NULL);
00766 REQUIRE(action != NULL);
00767 REQUIRE(requestp != NULL && *requestp == NULL);
00768 REQUIRE(timeout > 0);
00769 if (srcaddr != NULL)
00770 REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
00771
00772 mctx = requestmgr->mctx;
00773
00774 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
00775
00776 if (isblackholed(requestmgr->dispatchmgr, destaddr))
00777 return (DNS_R_BLACKHOLED);
00778
00779 request = NULL;
00780 result = new_request(mctx, &request);
00781 if (result != ISC_R_SUCCESS)
00782 return (result);
00783
00784 if (udptimeout == 0 && udpretries != 0) {
00785 udptimeout = timeout / (udpretries + 1);
00786 if (udptimeout == 0)
00787 udptimeout = 1;
00788 }
00789 request->udpcount = udpretries;
00790 request->dscp = dscp;
00791
00792
00793
00794
00795 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
00796 NULL, NULL, task, req_timeout, request,
00797 &request->timer);
00798 if (result != ISC_R_SUCCESS)
00799 goto cleanup;
00800
00801 request->event = (dns_requestevent_t *)
00802 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
00803 action, arg, sizeof(dns_requestevent_t));
00804 if (request->event == NULL) {
00805 result = ISC_R_NOMEMORY;
00806 goto cleanup;
00807 }
00808 isc_task_attach(task, &tclone);
00809 request->event->ev_sender = task;
00810 request->event->request = request;
00811 request->event->result = ISC_R_FAILURE;
00812
00813 isc_buffer_usedregion(msgbuf, &r);
00814 if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
00815 result = DNS_R_FORMERR;
00816 goto cleanup;
00817 }
00818
00819 if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
00820 tcp = ISC_TRUE;
00821 share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
00822
00823 again:
00824 result = get_dispatch(tcp, newtcp, share, requestmgr,
00825 srcaddr, destaddr, dscp,
00826 &connected, &request->dispatch);
00827 if (result != ISC_R_SUCCESS)
00828 goto cleanup;
00829
00830 if ((options & DNS_REQUESTOPT_FIXEDID) != 0) {
00831 id = (r.base[0] << 8) | r.base[1];
00832 dispopt |= DNS_DISPATCHOPT_FIXEDID;
00833 }
00834
00835 result = dns_dispatch_addresponse3(request->dispatch, dispopt,
00836 destaddr, task, req_response,
00837 request, &id, &request->dispentry,
00838 requestmgr->socketmgr);
00839 if (result != ISC_R_SUCCESS) {
00840 if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) {
00841 newtcp = ISC_TRUE;
00842 connected = ISC_FALSE;
00843 dns_dispatch_detach(&request->dispatch);
00844 goto again;
00845 }
00846 goto cleanup;
00847 }
00848
00849 sock = req_getsocket(request);
00850 INSIST(sock != NULL);
00851
00852 result = isc_buffer_allocate(mctx, &request->query,
00853 r.length + (tcp ? 2 : 0));
00854 if (result != ISC_R_SUCCESS)
00855 goto cleanup;
00856 if (tcp)
00857 isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
00858 result = isc_buffer_copyregion(request->query, &r);
00859 if (result != ISC_R_SUCCESS)
00860 goto cleanup;
00861
00862
00863 isc_buffer_usedregion(request->query, &r);
00864 if (tcp)
00865 isc_region_consume(&r, 2);
00866 r.base[0] = (id>>8) & 0xff;
00867 r.base[1] = id & 0xff;
00868
00869 LOCK(&requestmgr->lock);
00870 if (requestmgr->exiting) {
00871 UNLOCK(&requestmgr->lock);
00872 result = ISC_R_SHUTTINGDOWN;
00873 goto cleanup;
00874 }
00875 requestmgr_attach(requestmgr, &request->requestmgr);
00876 request->hash = mgr_gethash(requestmgr);
00877 ISC_LIST_APPEND(requestmgr->requests, request, link);
00878 UNLOCK(&requestmgr->lock);
00879
00880 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
00881 if (result != ISC_R_SUCCESS)
00882 goto unlink;
00883
00884 request->destaddr = *destaddr;
00885 if (tcp && !connected) {
00886 result = isc_socket_connect(sock, destaddr, task,
00887 req_connected, request);
00888 if (result != ISC_R_SUCCESS)
00889 goto unlink;
00890 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
00891 } else {
00892 result = req_send(request, task, connected ? NULL : destaddr);
00893 if (result != ISC_R_SUCCESS)
00894 goto unlink;
00895 }
00896
00897 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
00898 request);
00899 *requestp = request;
00900 return (ISC_R_SUCCESS);
00901
00902 unlink:
00903 LOCK(&requestmgr->lock);
00904 ISC_LIST_UNLINK(requestmgr->requests, request, link);
00905 UNLOCK(&requestmgr->lock);
00906
00907 cleanup:
00908 if (tclone != NULL)
00909 isc_task_detach(&tclone);
00910 req_destroy(request);
00911 req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
00912 dns_result_totext(result));
00913 return (result);
00914 }
00915
00916 isc_result_t
00917 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
00918 isc_sockaddr_t *address, unsigned int options,
00919 dns_tsigkey_t *key,
00920 unsigned int timeout, isc_task_t *task,
00921 isc_taskaction_t action, void *arg,
00922 dns_request_t **requestp)
00923 {
00924 return (dns_request_createvia4(requestmgr, message, NULL, address,
00925 -1, options, key, timeout, 0, 0, task,
00926 action, arg, requestp));
00927 }
00928
00929 isc_result_t
00930 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
00931 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00932 unsigned int options, dns_tsigkey_t *key,
00933 unsigned int timeout, isc_task_t *task,
00934 isc_taskaction_t action, void *arg,
00935 dns_request_t **requestp)
00936 {
00937 return(dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
00938 -1, options, key, timeout, 0, 0, task,
00939 action, arg, requestp));
00940 }
00941
00942 isc_result_t
00943 dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
00944 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00945 unsigned int options, dns_tsigkey_t *key,
00946 unsigned int timeout, unsigned int udptimeout,
00947 isc_task_t *task, isc_taskaction_t action, void *arg,
00948 dns_request_t **requestp)
00949 {
00950 unsigned int udpretries = 0;
00951
00952 if (udptimeout != 0)
00953 udpretries = timeout / udptimeout;
00954 return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
00955 -1, options, key, timeout, udptimeout,
00956 udpretries, task, action, arg,
00957 requestp));
00958 }
00959
00960 isc_result_t
00961 dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
00962 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00963 unsigned int options, dns_tsigkey_t *key,
00964 unsigned int timeout, unsigned int udptimeout,
00965 unsigned int udpretries, isc_task_t *task,
00966 isc_taskaction_t action, void *arg,
00967 dns_request_t **requestp)
00968 {
00969 return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
00970 -1, options, key, timeout, udptimeout,
00971 udpretries, task, action, arg,
00972 requestp));
00973 }
00974
00975 isc_result_t
00976 dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
00977 isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
00978 isc_dscp_t dscp, unsigned int options,
00979 dns_tsigkey_t *key, unsigned int timeout,
00980 unsigned int udptimeout, unsigned int udpretries,
00981 isc_task_t *task, isc_taskaction_t action, void *arg,
00982 dns_request_t **requestp)
00983 {
00984 dns_request_t *request = NULL;
00985 isc_task_t *tclone = NULL;
00986 isc_socket_t *sock = NULL;
00987 isc_result_t result;
00988 isc_mem_t *mctx;
00989 dns_messageid_t id;
00990 isc_boolean_t tcp;
00991 isc_boolean_t share;
00992 isc_boolean_t settsigkey = ISC_TRUE;
00993 isc_boolean_t connected = ISC_FALSE;
00994
00995 REQUIRE(VALID_REQUESTMGR(requestmgr));
00996 REQUIRE(message != NULL);
00997 REQUIRE(destaddr != NULL);
00998 REQUIRE(task != NULL);
00999 REQUIRE(action != NULL);
01000 REQUIRE(requestp != NULL && *requestp == NULL);
01001 REQUIRE(timeout > 0);
01002
01003 mctx = requestmgr->mctx;
01004
01005 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
01006
01007 if (srcaddr != NULL &&
01008 isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr))
01009 return (ISC_R_FAMILYMISMATCH);
01010
01011 if (isblackholed(requestmgr->dispatchmgr, destaddr))
01012 return (DNS_R_BLACKHOLED);
01013
01014 request = NULL;
01015 result = new_request(mctx, &request);
01016 if (result != ISC_R_SUCCESS)
01017 return (result);
01018
01019 if (udptimeout == 0 && udpretries != 0) {
01020 udptimeout = timeout / (udpretries + 1);
01021 if (udptimeout == 0)
01022 udptimeout = 1;
01023 }
01024 request->udpcount = udpretries;
01025 request->dscp = dscp;
01026
01027
01028
01029
01030 result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
01031 NULL, NULL, task, req_timeout, request,
01032 &request->timer);
01033 if (result != ISC_R_SUCCESS)
01034 goto cleanup;
01035
01036 request->event = (dns_requestevent_t *)
01037 isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
01038 action, arg, sizeof(dns_requestevent_t));
01039 if (request->event == NULL) {
01040 result = ISC_R_NOMEMORY;
01041 goto cleanup;
01042 }
01043 isc_task_attach(task, &tclone);
01044 request->event->ev_sender = task;
01045 request->event->request = request;
01046 request->event->result = ISC_R_FAILURE;
01047 if (key != NULL)
01048 dns_tsigkey_attach(key, &request->tsigkey);
01049
01050 use_tcp:
01051 tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
01052 share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
01053 result = get_dispatch(tcp, ISC_FALSE, share,
01054 requestmgr, srcaddr, destaddr,
01055 dscp, &connected, &request->dispatch);
01056 if (result != ISC_R_SUCCESS)
01057 goto cleanup;
01058
01059 result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
01060 req_response, request, &id,
01061 &request->dispentry,
01062 requestmgr->socketmgr);
01063 if (result != ISC_R_SUCCESS)
01064 goto cleanup;
01065 sock = req_getsocket(request);
01066 INSIST(sock != NULL);
01067
01068 message->id = id;
01069 if (settsigkey) {
01070 result = dns_message_settsigkey(message, request->tsigkey);
01071 if (result != ISC_R_SUCCESS)
01072 goto cleanup;
01073 }
01074 result = req_render(message, &request->query, options, mctx);
01075 if (result == DNS_R_USETCP &&
01076 (options & DNS_REQUESTOPT_TCP) == 0) {
01077
01078
01079
01080 dns_message_renderreset(message);
01081 dns_dispatch_removeresponse(&request->dispentry, NULL);
01082 dns_dispatch_detach(&request->dispatch);
01083 sock = NULL;
01084 options |= DNS_REQUESTOPT_TCP;
01085 settsigkey = ISC_FALSE;
01086 goto use_tcp;
01087 }
01088 if (result != ISC_R_SUCCESS)
01089 goto cleanup;
01090
01091 result = dns_message_getquerytsig(message, mctx, &request->tsig);
01092 if (result != ISC_R_SUCCESS)
01093 goto cleanup;
01094
01095 LOCK(&requestmgr->lock);
01096 if (requestmgr->exiting) {
01097 UNLOCK(&requestmgr->lock);
01098 result = ISC_R_SHUTTINGDOWN;
01099 goto cleanup;
01100 }
01101 requestmgr_attach(requestmgr, &request->requestmgr);
01102 request->hash = mgr_gethash(requestmgr);
01103 ISC_LIST_APPEND(requestmgr->requests, request, link);
01104 UNLOCK(&requestmgr->lock);
01105
01106 result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
01107 if (result != ISC_R_SUCCESS)
01108 goto unlink;
01109
01110 request->destaddr = *destaddr;
01111 if (tcp && !connected) {
01112 result = isc_socket_connect(sock, destaddr, task,
01113 req_connected, request);
01114 if (result != ISC_R_SUCCESS)
01115 goto unlink;
01116 request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
01117 } else {
01118 result = req_send(request, task, connected ? NULL : destaddr);
01119 if (result != ISC_R_SUCCESS)
01120 goto unlink;
01121 }
01122
01123 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
01124 request);
01125 *requestp = request;
01126 return (ISC_R_SUCCESS);
01127
01128 unlink:
01129 LOCK(&requestmgr->lock);
01130 ISC_LIST_UNLINK(requestmgr->requests, request, link);
01131 UNLOCK(&requestmgr->lock);
01132
01133 cleanup:
01134 if (tclone != NULL)
01135 isc_task_detach(&tclone);
01136 req_destroy(request);
01137 req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
01138 dns_result_totext(result));
01139 return (result);
01140 }
01141
01142 static isc_result_t
01143 req_render(dns_message_t *message, isc_buffer_t **bufferp,
01144 unsigned int options, isc_mem_t *mctx)
01145 {
01146 isc_buffer_t *buf1 = NULL;
01147 isc_buffer_t *buf2 = NULL;
01148 isc_result_t result;
01149 isc_region_t r;
01150 isc_boolean_t tcp = ISC_FALSE;
01151 dns_compress_t cctx;
01152 isc_boolean_t cleanup_cctx = ISC_FALSE;
01153
01154 REQUIRE(bufferp != NULL && *bufferp == NULL);
01155
01156 req_log(ISC_LOG_DEBUG(3), "request_render");
01157
01158
01159
01160
01161 result = isc_buffer_allocate(mctx, &buf1, 65535);
01162 if (result != ISC_R_SUCCESS)
01163 return (result);
01164
01165 result = dns_compress_init(&cctx, -1, mctx);
01166 if (result != ISC_R_SUCCESS)
01167 return (result);
01168 cleanup_cctx = ISC_TRUE;
01169
01170 if ((options & DNS_REQUESTOPT_CASE) != 0)
01171 dns_compress_setsensitive(&cctx, ISC_TRUE);
01172
01173
01174
01175
01176 result = dns_message_renderbegin(message, &cctx, buf1);
01177 if (result != ISC_R_SUCCESS)
01178 goto cleanup;
01179 result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
01180 if (result != ISC_R_SUCCESS)
01181 goto cleanup;
01182 result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
01183 if (result != ISC_R_SUCCESS)
01184 goto cleanup;
01185 result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
01186 if (result != ISC_R_SUCCESS)
01187 goto cleanup;
01188 result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
01189 if (result != ISC_R_SUCCESS)
01190 goto cleanup;
01191 result = dns_message_renderend(message);
01192 if (result != ISC_R_SUCCESS)
01193 goto cleanup;
01194
01195 dns_compress_invalidate(&cctx);
01196 cleanup_cctx = ISC_FALSE;
01197
01198
01199
01200
01201 isc_buffer_usedregion(buf1, &r);
01202 if ((options & DNS_REQUESTOPT_TCP) != 0) {
01203 tcp = ISC_TRUE;
01204 } else if (r.length > 512) {
01205 result = DNS_R_USETCP;
01206 goto cleanup;
01207 }
01208 result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
01209 if (result != ISC_R_SUCCESS)
01210 goto cleanup;
01211 if (tcp)
01212 isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
01213 result = isc_buffer_copyregion(buf2, &r);
01214 if (result != ISC_R_SUCCESS)
01215 goto cleanup;
01216
01217
01218
01219
01220 isc_buffer_free(&buf1);
01221 *bufferp = buf2;
01222 return (ISC_R_SUCCESS);
01223
01224 cleanup:
01225 dns_message_renderreset(message);
01226 if (buf1 != NULL)
01227 isc_buffer_free(&buf1);
01228 if (buf2 != NULL)
01229 isc_buffer_free(&buf2);
01230 if (cleanup_cctx)
01231 dns_compress_invalidate(&cctx);
01232 return (result);
01233 }
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 static void
01245 send_if_done(dns_request_t *request, isc_result_t result) {
01246 if (request->event != NULL && !request->canceling)
01247 req_sendevent(request, result);
01248 }
01249
01250
01251
01252
01253 static void
01254 do_cancel(isc_task_t *task, isc_event_t *event) {
01255 dns_request_t *request = event->ev_arg;
01256 UNUSED(task);
01257 INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
01258 LOCK(&request->requestmgr->locks[request->hash]);
01259 request->canceling = ISC_FALSE;
01260 if (!DNS_REQUEST_CANCELED(request))
01261 req_cancel(request);
01262 send_if_done(request, ISC_R_CANCELED);
01263 UNLOCK(&request->requestmgr->locks[request->hash]);
01264 }
01265
01266 void
01267 dns_request_cancel(dns_request_t *request) {
01268 REQUIRE(VALID_REQUEST(request));
01269
01270 req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
01271
01272 REQUIRE(VALID_REQUEST(request));
01273
01274 LOCK(&request->requestmgr->locks[request->hash]);
01275 if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
01276 isc_event_t *ev = &request->ctlevent;
01277 isc_task_send(request->event->ev_sender, &ev);
01278 request->canceling = ISC_TRUE;
01279 }
01280 UNLOCK(&request->requestmgr->locks[request->hash]);
01281 }
01282
01283 isc_result_t
01284 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
01285 unsigned int options)
01286 {
01287 isc_result_t result;
01288
01289 REQUIRE(VALID_REQUEST(request));
01290 REQUIRE(request->answer != NULL);
01291
01292 req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
01293 request);
01294
01295 result = dns_message_setquerytsig(message, request->tsig);
01296 if (result != ISC_R_SUCCESS)
01297 return (result);
01298 result = dns_message_settsigkey(message, request->tsigkey);
01299 if (result != ISC_R_SUCCESS)
01300 return (result);
01301 result = dns_message_parse(message, request->answer, options);
01302 if (result != ISC_R_SUCCESS)
01303 return (result);
01304 if (request->tsigkey != NULL)
01305 result = dns_tsig_verify(request->answer, message, NULL, NULL);
01306 return (result);
01307 }
01308
01309 isc_boolean_t
01310 dns_request_usedtcp(dns_request_t *request) {
01311 REQUIRE(VALID_REQUEST(request));
01312
01313 return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
01314 }
01315
01316 void
01317 dns_request_destroy(dns_request_t **requestp) {
01318 dns_request_t *request;
01319
01320 REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
01321
01322 request = *requestp;
01323
01324 req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
01325
01326 LOCK(&request->requestmgr->lock);
01327 LOCK(&request->requestmgr->locks[request->hash]);
01328 ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
01329 INSIST(!DNS_REQUEST_CONNECTING(request));
01330 INSIST(!DNS_REQUEST_SENDING(request));
01331 UNLOCK(&request->requestmgr->locks[request->hash]);
01332 UNLOCK(&request->requestmgr->lock);
01333
01334
01335
01336
01337
01338 INSIST(!ISC_LINK_LINKED(request, link));
01339 INSIST(request->dispentry == NULL);
01340 INSIST(request->dispatch == NULL);
01341 INSIST(request->timer == NULL);
01342
01343 req_destroy(request);
01344
01345 *requestp = NULL;
01346 }
01347
01348
01349
01350
01351
01352 static isc_socket_t *
01353 req_getsocket(dns_request_t *request) {
01354 unsigned int dispattr;
01355 isc_socket_t *sock;
01356
01357 dispattr = dns_dispatch_getattributes(request->dispatch);
01358 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
01359 INSIST(request->dispentry != NULL);
01360 sock = dns_dispatch_getentrysocket(request->dispentry);
01361 } else
01362 sock = dns_dispatch_getsocket(request->dispatch);
01363
01364 return (sock);
01365 }
01366
01367 static void
01368 req_connected(isc_task_t *task, isc_event_t *event) {
01369 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
01370 isc_result_t result;
01371 dns_request_t *request = event->ev_arg;
01372
01373 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
01374 REQUIRE(VALID_REQUEST(request));
01375 REQUIRE(DNS_REQUEST_CONNECTING(request));
01376
01377 req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
01378
01379 LOCK(&request->requestmgr->locks[request->hash]);
01380 request->flags &= ~DNS_REQUEST_F_CONNECTING;
01381
01382 if (DNS_REQUEST_CANCELED(request)) {
01383
01384
01385
01386 if (DNS_REQUEST_TIMEDOUT(request))
01387 send_if_done(request, ISC_R_TIMEDOUT);
01388 else
01389 send_if_done(request, ISC_R_CANCELED);
01390 } else {
01391 dns_dispatch_starttcp(request->dispatch);
01392 result = sevent->result;
01393 if (result == ISC_R_SUCCESS)
01394 result = req_send(request, task, NULL);
01395
01396 if (result != ISC_R_SUCCESS) {
01397 req_cancel(request);
01398 send_if_done(request, ISC_R_CANCELED);
01399 }
01400 }
01401 UNLOCK(&request->requestmgr->locks[request->hash]);
01402 isc_event_free(&event);
01403 }
01404
01405 static void
01406 req_senddone(isc_task_t *task, isc_event_t *event) {
01407 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
01408 dns_request_t *request = event->ev_arg;
01409
01410 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
01411 REQUIRE(VALID_REQUEST(request));
01412 REQUIRE(DNS_REQUEST_SENDING(request));
01413
01414 req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
01415
01416 UNUSED(task);
01417
01418 LOCK(&request->requestmgr->locks[request->hash]);
01419 request->flags &= ~DNS_REQUEST_F_SENDING;
01420
01421 if (DNS_REQUEST_CANCELED(request)) {
01422
01423
01424
01425 if (DNS_REQUEST_TIMEDOUT(request))
01426 send_if_done(request, ISC_R_TIMEDOUT);
01427 else
01428 send_if_done(request, ISC_R_CANCELED);
01429 } else if (sevent->result != ISC_R_SUCCESS) {
01430 req_cancel(request);
01431 send_if_done(request, ISC_R_CANCELED);
01432 }
01433 UNLOCK(&request->requestmgr->locks[request->hash]);
01434
01435 isc_event_free(&event);
01436 }
01437
01438 static void
01439 req_response(isc_task_t *task, isc_event_t *event) {
01440 isc_result_t result;
01441 dns_request_t *request = event->ev_arg;
01442 dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
01443 isc_region_t r;
01444
01445 REQUIRE(VALID_REQUEST(request));
01446 REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
01447
01448 UNUSED(task);
01449
01450 req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
01451 dns_result_totext(devent->result));
01452
01453 LOCK(&request->requestmgr->locks[request->hash]);
01454 result = devent->result;
01455 if (result != ISC_R_SUCCESS)
01456 goto done;
01457
01458
01459
01460
01461 isc_buffer_usedregion(&devent->buffer, &r);
01462 result = isc_buffer_allocate(request->mctx, &request->answer,
01463 r.length);
01464 if (result != ISC_R_SUCCESS)
01465 goto done;
01466 result = isc_buffer_copyregion(request->answer, &r);
01467 if (result != ISC_R_SUCCESS)
01468 isc_buffer_free(&request->answer);
01469 done:
01470
01471
01472
01473 dns_dispatch_removeresponse(&request->dispentry, &devent);
01474 req_cancel(request);
01475
01476
01477
01478 send_if_done(request, result);
01479 UNLOCK(&request->requestmgr->locks[request->hash]);
01480 }
01481
01482 static void
01483 req_timeout(isc_task_t *task, isc_event_t *event) {
01484 dns_request_t *request = event->ev_arg;
01485 isc_result_t result;
01486
01487 REQUIRE(VALID_REQUEST(request));
01488
01489 req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
01490
01491 UNUSED(task);
01492 LOCK(&request->requestmgr->locks[request->hash]);
01493 if (event->ev_type == ISC_TIMEREVENT_TICK &&
01494 request->udpcount-- != 0) {
01495 if (! DNS_REQUEST_SENDING(request)) {
01496 result = req_send(request, task, &request->destaddr);
01497 if (result != ISC_R_SUCCESS) {
01498 req_cancel(request);
01499 send_if_done(request, result);
01500 }
01501 }
01502 } else {
01503 request->flags |= DNS_REQUEST_F_TIMEDOUT;
01504 req_cancel(request);
01505 send_if_done(request, ISC_R_TIMEDOUT);
01506 }
01507 UNLOCK(&request->requestmgr->locks[request->hash]);
01508 isc_event_free(&event);
01509 }
01510
01511 static void
01512 req_sendevent(dns_request_t *request, isc_result_t result) {
01513 isc_task_t *task;
01514
01515 REQUIRE(VALID_REQUEST(request));
01516
01517 req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
01518
01519
01520
01521
01522 task = request->event->ev_sender;
01523 request->event->ev_sender = request;
01524 request->event->result = result;
01525 isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
01526 }
01527
01528 static void
01529 req_destroy(dns_request_t *request) {
01530 isc_mem_t *mctx;
01531
01532 REQUIRE(VALID_REQUEST(request));
01533
01534 req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
01535
01536 request->magic = 0;
01537 if (request->query != NULL)
01538 isc_buffer_free(&request->query);
01539 if (request->answer != NULL)
01540 isc_buffer_free(&request->answer);
01541 if (request->event != NULL)
01542 isc_event_free((isc_event_t **)&request->event);
01543 if (request->dispentry != NULL)
01544 dns_dispatch_removeresponse(&request->dispentry, NULL);
01545 if (request->dispatch != NULL)
01546 dns_dispatch_detach(&request->dispatch);
01547 if (request->timer != NULL)
01548 isc_timer_detach(&request->timer);
01549 if (request->tsig != NULL)
01550 isc_buffer_free(&request->tsig);
01551 if (request->tsigkey != NULL)
01552 dns_tsigkey_detach(&request->tsigkey);
01553 if (request->requestmgr != NULL)
01554 requestmgr_detach(&request->requestmgr);
01555 mctx = request->mctx;
01556 isc_mem_put(mctx, request, sizeof(*request));
01557 isc_mem_detach(&mctx);
01558 }
01559
01560
01561
01562
01563 static void
01564 req_cancel(dns_request_t *request) {
01565 isc_socket_t *sock;
01566 unsigned int dispattr;
01567
01568 REQUIRE(VALID_REQUEST(request));
01569
01570 req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
01571
01572
01573
01574
01575 request->flags |= DNS_REQUEST_F_CANCELED;
01576
01577 if (request->timer != NULL)
01578 isc_timer_detach(&request->timer);
01579 dispattr = dns_dispatch_getattributes(request->dispatch);
01580 sock = NULL;
01581 if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
01582 if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
01583 if (request->dispentry != NULL) {
01584 sock = dns_dispatch_getentrysocket(
01585 request->dispentry);
01586 }
01587 } else
01588 sock = dns_dispatch_getsocket(request->dispatch);
01589 if (DNS_REQUEST_CONNECTING(request) && sock != NULL)
01590 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_CONNECT);
01591 if (DNS_REQUEST_SENDING(request) && sock != NULL)
01592 isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_SEND);
01593 }
01594 if (request->dispentry != NULL)
01595 dns_dispatch_removeresponse(&request->dispentry, NULL);
01596 dns_dispatch_detach(&request->dispatch);
01597 }
01598
01599 static void
01600 req_log(int level, const char *fmt, ...) {
01601 va_list ap;
01602
01603 va_start(ap, fmt);
01604 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
01605 DNS_LOGMODULE_REQUEST, level, fmt, ap);
01606 va_end(ap);
01607 }