/contrib/bind9/lib/dns/request.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1497 lines · 1170 code · 214 blank · 113 comment · 323 complexity · fd33bdb912225c7c7f16ecd2731003ef MD5 · raw file

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