/src/bind9/lib/dns/request.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /*! \file */ |
15 | | |
16 | | #include <inttypes.h> |
17 | | #include <stdbool.h> |
18 | | |
19 | | #include <isc/async.h> |
20 | | #include <isc/log.h> |
21 | | #include <isc/loop.h> |
22 | | #include <isc/magic.h> |
23 | | #include <isc/mem.h> |
24 | | #include <isc/netmgr.h> |
25 | | #include <isc/result.h> |
26 | | #include <isc/thread.h> |
27 | | #include <isc/tls.h> |
28 | | #include <isc/util.h> |
29 | | |
30 | | #include <dns/acl.h> |
31 | | #include <dns/compress.h> |
32 | | #include <dns/dispatch.h> |
33 | | #include <dns/message.h> |
34 | | #include <dns/rdata.h> |
35 | | #include <dns/rdatastruct.h> |
36 | | #include <dns/request.h> |
37 | | #include <dns/transport.h> |
38 | | #include <dns/tsig.h> |
39 | | |
40 | 0 | #define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M') |
41 | | #define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC) |
42 | | |
43 | 0 | #define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!') |
44 | | #define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC) |
45 | | |
46 | | typedef ISC_LIST(dns_request_t) dns_requestlist_t; |
47 | | |
48 | | struct dns_requestmgr { |
49 | | unsigned int magic; |
50 | | isc_mem_t *mctx; |
51 | | isc_refcount_t references; |
52 | | |
53 | | atomic_bool shuttingdown; |
54 | | |
55 | | dns_dispatchmgr_t *dispatchmgr; |
56 | | dns_dispatchset_t *dispatches4; |
57 | | dns_dispatchset_t *dispatches6; |
58 | | dns_requestlist_t *requests; |
59 | | }; |
60 | | |
61 | | struct dns_request { |
62 | | unsigned int magic; |
63 | | isc_refcount_t references; |
64 | | |
65 | | isc_mem_t *mctx; |
66 | | int32_t flags; |
67 | | |
68 | | isc_loop_t *loop; |
69 | | isc_tid_t tid; |
70 | | |
71 | | isc_result_t result; |
72 | | isc_job_cb cb; |
73 | | void *arg; |
74 | | ISC_LINK(dns_request_t) link; |
75 | | isc_buffer_t *query; |
76 | | isc_buffer_t *answer; |
77 | | dns_dispatch_t *dispatch; |
78 | | dns_dispentry_t *dispentry; |
79 | | dns_requestmgr_t *requestmgr; |
80 | | isc_buffer_t *tsig; |
81 | | dns_tsigkey_t *tsigkey; |
82 | | isc_sockaddr_t destaddr; |
83 | | unsigned int connect_timeout; |
84 | | unsigned int timeout; |
85 | | unsigned int udpcount; |
86 | | }; |
87 | | |
88 | 0 | #define DNS_REQUEST_F_CONNECTING (1 << 0) |
89 | 0 | #define DNS_REQUEST_F_SENDING (1 << 1) |
90 | 0 | #define DNS_REQUEST_F_COMPLETE (1 << 2) |
91 | 0 | #define DNS_REQUEST_F_TCP (1 << 3) |
92 | | |
93 | | #define DNS_REQUEST_CONNECTING(r) (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0) |
94 | 0 | #define DNS_REQUEST_SENDING(r) (((r)->flags & DNS_REQUEST_F_SENDING) != 0) |
95 | 0 | #define DNS_REQUEST_COMPLETE(r) (((r)->flags & DNS_REQUEST_F_COMPLETE) != 0) |
96 | | |
97 | | /*** |
98 | | *** Forward |
99 | | ***/ |
100 | | |
101 | | static isc_result_t |
102 | | req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options, |
103 | | isc_mem_t *mctx); |
104 | | static void |
105 | | req_response(isc_result_t result, isc_region_t *region, void *arg); |
106 | | static void |
107 | | req_senddone(isc_result_t eresult, isc_region_t *region, void *arg); |
108 | | static void |
109 | | req_cleanup(dns_request_t *request); |
110 | | static void |
111 | | req_sendevent(dns_request_t *request, isc_result_t result); |
112 | | static void |
113 | | req_connected(isc_result_t eresult, isc_region_t *region, void *arg); |
114 | | static void |
115 | | req_destroy(dns_request_t *request); |
116 | | static void |
117 | | req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); |
118 | | |
119 | | /*** |
120 | | *** Public |
121 | | ***/ |
122 | | |
123 | | isc_result_t |
124 | | dns_requestmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t *dispatchmgr, |
125 | | dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, |
126 | 0 | dns_requestmgr_t **requestmgrp) { |
127 | 0 | REQUIRE(requestmgrp != NULL && *requestmgrp == NULL); |
128 | 0 | REQUIRE(dispatchmgr != NULL); |
129 | |
|
130 | 0 | req_log(ISC_LOG_DEBUG(3), "%s", __func__); |
131 | |
|
132 | 0 | dns_requestmgr_t *requestmgr = isc_mem_get(mctx, sizeof(*requestmgr)); |
133 | 0 | *requestmgr = (dns_requestmgr_t){ |
134 | 0 | .magic = REQUESTMGR_MAGIC, |
135 | 0 | }; |
136 | 0 | isc_mem_attach(mctx, &requestmgr->mctx); |
137 | |
|
138 | 0 | uint32_t nloops = isc_loopmgr_nloops(); |
139 | 0 | requestmgr->requests = isc_mem_cget(requestmgr->mctx, nloops, |
140 | 0 | sizeof(requestmgr->requests[0])); |
141 | 0 | for (size_t i = 0; i < nloops; i++) { |
142 | 0 | ISC_LIST_INIT(requestmgr->requests[i]); |
143 | | |
144 | | /* unreferenced in requests_cancel() */ |
145 | 0 | isc_loop_ref(isc_loop_get(i)); |
146 | 0 | } |
147 | |
|
148 | 0 | dns_dispatchmgr_attach(dispatchmgr, &requestmgr->dispatchmgr); |
149 | |
|
150 | 0 | if (dispatchv4 != NULL) { |
151 | 0 | dns_dispatchset_create(requestmgr->mctx, dispatchv4, |
152 | 0 | &requestmgr->dispatches4, |
153 | 0 | isc_loopmgr_nloops()); |
154 | 0 | } |
155 | 0 | if (dispatchv6 != NULL) { |
156 | 0 | dns_dispatchset_create(requestmgr->mctx, dispatchv6, |
157 | 0 | &requestmgr->dispatches6, |
158 | 0 | isc_loopmgr_nloops()); |
159 | 0 | } |
160 | |
|
161 | 0 | isc_refcount_init(&requestmgr->references, 1); |
162 | |
|
163 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: %p", __func__, requestmgr); |
164 | |
|
165 | 0 | *requestmgrp = requestmgr; |
166 | 0 | return ISC_R_SUCCESS; |
167 | 0 | } |
168 | | |
169 | | static void |
170 | 0 | requests_cancel(void *arg) { |
171 | 0 | dns_requestmgr_t *requestmgr = arg; |
172 | 0 | isc_tid_t tid = isc_tid(); |
173 | |
|
174 | 0 | ISC_LIST_FOREACH(requestmgr->requests[tid], request, link) { |
175 | 0 | req_log(ISC_LOG_DEBUG(3), "%s(%" PRItid ": request %p", |
176 | 0 | __func__, tid, request); |
177 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
178 | | /* The callback has been already scheduled */ |
179 | 0 | continue; |
180 | 0 | } |
181 | 0 | req_sendevent(request, ISC_R_CANCELED); |
182 | 0 | } |
183 | |
|
184 | 0 | isc_loop_unref(isc_loop_get(tid)); |
185 | 0 | dns_requestmgr_detach(&requestmgr); |
186 | 0 | } |
187 | | |
188 | | void |
189 | 0 | dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) { |
190 | 0 | bool first; |
191 | 0 | REQUIRE(VALID_REQUESTMGR(requestmgr)); |
192 | |
|
193 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: %p", __func__, requestmgr); |
194 | |
|
195 | 0 | rcu_read_lock(); |
196 | 0 | first = atomic_compare_exchange_strong(&requestmgr->shuttingdown, |
197 | 0 | &(bool){ false }, true); |
198 | 0 | rcu_read_unlock(); |
199 | |
|
200 | 0 | if (!first) { |
201 | 0 | return; |
202 | 0 | } |
203 | | |
204 | | /* |
205 | | * Wait until all dns_request_create{raw}() are finished, so |
206 | | * there will be no new requests added to the lists. |
207 | | */ |
208 | 0 | synchronize_rcu(); |
209 | |
|
210 | 0 | isc_tid_t tid = isc_tid(); |
211 | 0 | uint32_t nloops = isc_loopmgr_nloops(); |
212 | 0 | for (size_t i = 0; i < nloops; i++) { |
213 | 0 | dns_requestmgr_ref(requestmgr); |
214 | |
|
215 | 0 | if (i == (uint32_t)tid) { |
216 | | /* Run the current loop synchronously */ |
217 | 0 | requests_cancel(requestmgr); |
218 | 0 | continue; |
219 | 0 | } |
220 | | |
221 | 0 | isc_loop_t *loop = isc_loop_get(i); |
222 | 0 | isc_async_run(loop, requests_cancel, requestmgr); |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | | static void |
227 | 0 | requestmgr_destroy(dns_requestmgr_t *requestmgr) { |
228 | 0 | req_log(ISC_LOG_DEBUG(3), "%s", __func__); |
229 | |
|
230 | 0 | INSIST(atomic_load(&requestmgr->shuttingdown)); |
231 | |
|
232 | 0 | size_t nloops = isc_loopmgr_nloops(); |
233 | 0 | for (size_t i = 0; i < nloops; i++) { |
234 | 0 | INSIST(ISC_LIST_EMPTY(requestmgr->requests[i])); |
235 | 0 | } |
236 | 0 | isc_mem_cput(requestmgr->mctx, requestmgr->requests, nloops, |
237 | 0 | sizeof(requestmgr->requests[0])); |
238 | |
|
239 | 0 | if (requestmgr->dispatches4 != NULL) { |
240 | 0 | dns_dispatchset_destroy(&requestmgr->dispatches4); |
241 | 0 | } |
242 | 0 | if (requestmgr->dispatches6 != NULL) { |
243 | 0 | dns_dispatchset_destroy(&requestmgr->dispatches6); |
244 | 0 | } |
245 | 0 | if (requestmgr->dispatchmgr != NULL) { |
246 | 0 | dns_dispatchmgr_detach(&requestmgr->dispatchmgr); |
247 | 0 | } |
248 | 0 | requestmgr->magic = 0; |
249 | 0 | isc_mem_putanddetach(&requestmgr->mctx, requestmgr, |
250 | 0 | sizeof(*requestmgr)); |
251 | 0 | } |
252 | | |
253 | | #if DNS_REQUEST_TRACE |
254 | | ISC_REFCOUNT_TRACE_IMPL(dns_requestmgr, requestmgr_destroy); |
255 | | #else |
256 | 0 | ISC_REFCOUNT_IMPL(dns_requestmgr, requestmgr_destroy); Unexecuted instantiation: dns_requestmgr_ref Unexecuted instantiation: dns_requestmgr_unref Unexecuted instantiation: dns_requestmgr_detach |
257 | 0 | #endif |
258 | 0 |
|
259 | 0 | static void |
260 | 0 | req_send(dns_request_t *request) { |
261 | 0 | isc_region_t r; |
262 | |
|
263 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
264 | |
|
265 | 0 | REQUIRE(VALID_REQUEST(request)); |
266 | |
|
267 | 0 | isc_buffer_usedregion(request->query, &r); |
268 | |
|
269 | 0 | request->flags |= DNS_REQUEST_F_SENDING; |
270 | | |
271 | | /* detached in req_senddone() */ |
272 | 0 | dns_request_ref(request); |
273 | 0 | dns_dispatch_send(request->dispentry, &r); |
274 | 0 | } |
275 | | |
276 | | static dns_request_t * |
277 | | new_request(isc_mem_t *mctx, isc_loop_t *loop, isc_job_cb cb, void *arg, |
278 | | bool tcp, unsigned int connect_timeout, unsigned int timeout, |
279 | 0 | unsigned int udptimeout, unsigned int udpretries) { |
280 | 0 | dns_request_t *request = isc_mem_get(mctx, sizeof(*request)); |
281 | 0 | *request = (dns_request_t){ |
282 | 0 | .magic = REQUEST_MAGIC, |
283 | 0 | .loop = loop, |
284 | 0 | .tid = isc_tid(), |
285 | 0 | .cb = cb, |
286 | 0 | .arg = arg, |
287 | 0 | .link = ISC_LINK_INITIALIZER, |
288 | 0 | .result = ISC_R_FAILURE, |
289 | 0 | .udpcount = udpretries + 1, |
290 | 0 | }; |
291 | |
|
292 | 0 | isc_refcount_init(&request->references, 1); |
293 | 0 | isc_mem_attach(mctx, &request->mctx); |
294 | |
|
295 | 0 | if (tcp) { |
296 | 0 | request->connect_timeout = connect_timeout * 1000; |
297 | 0 | request->timeout = timeout * 1000; |
298 | 0 | } else { |
299 | 0 | if (udptimeout == 0) { |
300 | 0 | udptimeout = timeout / request->udpcount; |
301 | 0 | } |
302 | 0 | if (udptimeout == 0) { |
303 | 0 | udptimeout = 1; |
304 | 0 | } |
305 | 0 | request->timeout = udptimeout * 1000; |
306 | 0 | } |
307 | |
|
308 | 0 | return request; |
309 | 0 | } |
310 | | |
311 | | static bool |
312 | 0 | isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) { |
313 | 0 | dns_acl_t *blackhole; |
314 | 0 | isc_netaddr_t netaddr; |
315 | 0 | char netaddrstr[ISC_NETADDR_FORMATSIZE]; |
316 | 0 | int match; |
317 | 0 | isc_result_t result; |
318 | |
|
319 | 0 | blackhole = dns_dispatchmgr_getblackhole(dispatchmgr); |
320 | 0 | if (blackhole == NULL) { |
321 | 0 | return false; |
322 | 0 | } |
323 | | |
324 | 0 | isc_netaddr_fromsockaddr(&netaddr, destaddr); |
325 | 0 | result = dns_acl_match(&netaddr, NULL, blackhole, NULL, &match, NULL); |
326 | 0 | if (result != ISC_R_SUCCESS || match <= 0) { |
327 | 0 | return false; |
328 | 0 | } |
329 | | |
330 | 0 | isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr)); |
331 | 0 | req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr); |
332 | |
|
333 | 0 | return true; |
334 | 0 | } |
335 | | |
336 | | static isc_result_t |
337 | | tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, |
338 | | const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, |
339 | 0 | dns_transport_t *transport, dns_dispatch_t **dispatchp) { |
340 | 0 | isc_result_t result; |
341 | |
|
342 | 0 | if (!newtcp) { |
343 | 0 | result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, |
344 | 0 | srcaddr, transport, dispatchp); |
345 | 0 | if (result == ISC_R_SUCCESS) { |
346 | 0 | char peer[ISC_SOCKADDR_FORMATSIZE]; |
347 | |
|
348 | 0 | isc_sockaddr_format(destaddr, peer, sizeof(peer)); |
349 | 0 | req_log(ISC_LOG_DEBUG(1), |
350 | 0 | "attached to TCP connection to %s", peer); |
351 | 0 | return result; |
352 | 0 | } |
353 | 0 | } |
354 | | |
355 | 0 | result = dns_dispatch_createtcp(requestmgr->dispatchmgr, srcaddr, |
356 | 0 | destaddr, transport, 0, dispatchp); |
357 | 0 | return result; |
358 | 0 | } |
359 | | |
360 | | static isc_result_t |
361 | | udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, |
362 | 0 | const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) { |
363 | 0 | dns_dispatch_t *disp = NULL; |
364 | |
|
365 | 0 | if (srcaddr == NULL) { |
366 | 0 | switch (isc_sockaddr_pf(destaddr)) { |
367 | 0 | case PF_INET: |
368 | 0 | disp = dns_dispatchset_get(requestmgr->dispatches4); |
369 | 0 | break; |
370 | | |
371 | 0 | case PF_INET6: |
372 | 0 | disp = dns_dispatchset_get(requestmgr->dispatches6); |
373 | 0 | break; |
374 | | |
375 | 0 | default: |
376 | 0 | return ISC_R_NOTIMPLEMENTED; |
377 | 0 | } |
378 | 0 | if (disp == NULL) { |
379 | 0 | return ISC_R_FAMILYNOSUPPORT; |
380 | 0 | } |
381 | 0 | dns_dispatch_attach(disp, dispatchp); |
382 | 0 | return ISC_R_SUCCESS; |
383 | 0 | } |
384 | | |
385 | 0 | return dns_dispatch_createudp(requestmgr->dispatchmgr, srcaddr, |
386 | 0 | dispatchp); |
387 | 0 | } |
388 | | |
389 | | static isc_result_t |
390 | | get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr, |
391 | | const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, |
392 | 0 | dns_transport_t *transport, dns_dispatch_t **dispatchp) { |
393 | 0 | isc_result_t result; |
394 | |
|
395 | 0 | if (tcp) { |
396 | 0 | result = tcp_dispatch(newtcp, requestmgr, srcaddr, destaddr, |
397 | 0 | transport, dispatchp); |
398 | 0 | } else { |
399 | 0 | result = udp_dispatch(requestmgr, srcaddr, destaddr, dispatchp); |
400 | 0 | } |
401 | 0 | return result; |
402 | 0 | } |
403 | | |
404 | | isc_result_t |
405 | | dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, |
406 | | const isc_sockaddr_t *srcaddr, |
407 | | const isc_sockaddr_t *destaddr, |
408 | | dns_transport_t *transport, |
409 | | isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, |
410 | | unsigned int connect_timeout, unsigned int timeout, |
411 | | unsigned int udptimeout, unsigned int udpretries, |
412 | | isc_loop_t *loop, isc_job_cb cb, void *arg, |
413 | 0 | dns_request_t **requestp) { |
414 | 0 | dns_request_t *request = NULL; |
415 | 0 | isc_result_t result; |
416 | 0 | isc_mem_t *mctx = NULL; |
417 | 0 | dns_messageid_t id; |
418 | 0 | bool tcp = false; |
419 | 0 | bool newtcp = false; |
420 | 0 | isc_region_t r; |
421 | 0 | unsigned int dispopt = 0; |
422 | |
|
423 | 0 | REQUIRE(VALID_REQUESTMGR(requestmgr)); |
424 | 0 | REQUIRE(msgbuf != NULL); |
425 | 0 | REQUIRE(destaddr != NULL); |
426 | 0 | REQUIRE(loop != NULL); |
427 | 0 | REQUIRE(cb != NULL); |
428 | 0 | REQUIRE(requestp != NULL && *requestp == NULL); |
429 | 0 | REQUIRE(connect_timeout > 0 && timeout > 0); |
430 | 0 | REQUIRE(udpretries != UINT_MAX); |
431 | |
|
432 | 0 | if (srcaddr != NULL) { |
433 | 0 | REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr)); |
434 | 0 | } |
435 | |
|
436 | 0 | mctx = requestmgr->mctx; |
437 | |
|
438 | 0 | req_log(ISC_LOG_DEBUG(3), "%s", __func__); |
439 | |
|
440 | 0 | rcu_read_lock(); |
441 | |
|
442 | 0 | if (atomic_load_acquire(&requestmgr->shuttingdown)) { |
443 | 0 | result = ISC_R_SHUTTINGDOWN; |
444 | 0 | goto done; |
445 | 0 | } |
446 | | |
447 | 0 | if (isblackholed(requestmgr->dispatchmgr, destaddr)) { |
448 | 0 | result = DNS_R_BLACKHOLED; |
449 | 0 | goto done; |
450 | 0 | } |
451 | | |
452 | 0 | isc_buffer_usedregion(msgbuf, &r); |
453 | 0 | if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) { |
454 | 0 | result = DNS_R_FORMERR; |
455 | 0 | goto done; |
456 | 0 | } |
457 | | |
458 | 0 | if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) { |
459 | 0 | tcp = true; |
460 | 0 | } |
461 | |
|
462 | 0 | request = new_request(mctx, loop, cb, arg, tcp, connect_timeout, |
463 | 0 | timeout, udptimeout, udpretries); |
464 | |
|
465 | 0 | isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); |
466 | 0 | result = isc_buffer_copyregion(request->query, &r); |
467 | 0 | if (result != ISC_R_SUCCESS) { |
468 | 0 | goto cleanup; |
469 | 0 | } |
470 | | |
471 | 0 | again: |
472 | 0 | result = get_dispatch(tcp, newtcp, requestmgr, srcaddr, destaddr, |
473 | 0 | transport, &request->dispatch); |
474 | 0 | if (result != ISC_R_SUCCESS) { |
475 | 0 | goto cleanup; |
476 | 0 | } |
477 | | |
478 | 0 | if ((options & DNS_REQUESTOPT_FIXEDID) != 0) { |
479 | 0 | id = (r.base[0] << 8) | r.base[1]; |
480 | 0 | dispopt |= DNS_DISPATCHOPT_FIXEDID; |
481 | 0 | } |
482 | |
|
483 | 0 | result = dns_dispatch_add(request->dispatch, loop, dispopt, |
484 | 0 | request->connect_timeout, request->timeout, |
485 | 0 | destaddr, transport, tlsctx_cache, |
486 | 0 | req_connected, req_senddone, req_response, |
487 | 0 | request, &id, &request->dispentry); |
488 | 0 | if (result != ISC_R_SUCCESS) { |
489 | 0 | if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) { |
490 | 0 | dns_dispatch_detach(&request->dispatch); |
491 | 0 | newtcp = true; |
492 | 0 | goto again; |
493 | 0 | } |
494 | | |
495 | 0 | goto cleanup; |
496 | 0 | } |
497 | | |
498 | | /* Add message ID. */ |
499 | 0 | isc_buffer_usedregion(request->query, &r); |
500 | 0 | r.base[0] = (id >> 8) & 0xff; |
501 | 0 | r.base[1] = id & 0xff; |
502 | |
|
503 | 0 | request->destaddr = *destaddr; |
504 | 0 | request->flags |= DNS_REQUEST_F_CONNECTING; |
505 | 0 | if (tcp) { |
506 | 0 | request->flags |= DNS_REQUEST_F_TCP; |
507 | 0 | } |
508 | |
|
509 | 0 | dns_requestmgr_attach(requestmgr, &request->requestmgr); |
510 | 0 | ISC_LIST_APPEND(requestmgr->requests[request->tid], request, link); |
511 | |
|
512 | 0 | dns_request_ref(request); /* detached in req_connected() */ |
513 | 0 | result = dns_dispatch_connect(request->dispentry); |
514 | 0 | if (result != ISC_R_SUCCESS) { |
515 | 0 | dns_request_unref(request); |
516 | 0 | goto cleanup; |
517 | 0 | } |
518 | | |
519 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
520 | 0 | *requestp = request; |
521 | |
|
522 | 0 | cleanup: |
523 | 0 | if (result != ISC_R_SUCCESS) { |
524 | 0 | req_cleanup(request); |
525 | 0 | dns_request_detach(&request); |
526 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: failed %s", __func__, |
527 | 0 | isc_result_totext(result)); |
528 | 0 | } |
529 | |
|
530 | 0 | done: |
531 | 0 | rcu_read_unlock(); |
532 | 0 | return result; |
533 | 0 | } |
534 | | |
535 | | isc_result_t |
536 | | dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, |
537 | | const isc_sockaddr_t *srcaddr, |
538 | | const isc_sockaddr_t *destaddr, dns_transport_t *transport, |
539 | | isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, |
540 | | dns_tsigkey_t *key, unsigned int connect_timeout, |
541 | | unsigned int timeout, unsigned int udptimeout, |
542 | | unsigned int udpretries, isc_loop_t *loop, isc_job_cb cb, |
543 | 0 | void *arg, dns_request_t **requestp) { |
544 | 0 | dns_request_t *request = NULL; |
545 | 0 | isc_result_t result; |
546 | 0 | isc_mem_t *mctx = NULL; |
547 | 0 | dns_messageid_t id; |
548 | 0 | bool tcp = false; |
549 | |
|
550 | 0 | REQUIRE(VALID_REQUESTMGR(requestmgr)); |
551 | 0 | REQUIRE(message != NULL); |
552 | 0 | REQUIRE(destaddr != NULL); |
553 | 0 | REQUIRE(loop != NULL); |
554 | 0 | REQUIRE(cb != NULL); |
555 | 0 | REQUIRE(requestp != NULL && *requestp == NULL); |
556 | 0 | REQUIRE(connect_timeout > 0 && timeout > 0); |
557 | 0 | REQUIRE(udpretries != UINT_MAX); |
558 | |
|
559 | 0 | if (srcaddr != NULL && |
560 | 0 | isc_sockaddr_pf(srcaddr) != isc_sockaddr_pf(destaddr)) |
561 | 0 | { |
562 | 0 | return ISC_R_FAMILYMISMATCH; |
563 | 0 | } |
564 | | |
565 | 0 | mctx = requestmgr->mctx; |
566 | |
|
567 | 0 | req_log(ISC_LOG_DEBUG(3), "%s", __func__); |
568 | |
|
569 | 0 | rcu_read_lock(); |
570 | |
|
571 | 0 | if (atomic_load_acquire(&requestmgr->shuttingdown)) { |
572 | 0 | result = ISC_R_SHUTTINGDOWN; |
573 | 0 | goto done; |
574 | 0 | } |
575 | | |
576 | 0 | if (isblackholed(requestmgr->dispatchmgr, destaddr)) { |
577 | 0 | result = DNS_R_BLACKHOLED; |
578 | 0 | goto done; |
579 | 0 | } |
580 | | |
581 | 0 | if ((options & DNS_REQUESTOPT_TCP) != 0) { |
582 | 0 | tcp = true; |
583 | 0 | } |
584 | |
|
585 | 0 | request = new_request(mctx, loop, cb, arg, tcp, connect_timeout, |
586 | 0 | timeout, udptimeout, udpretries); |
587 | |
|
588 | 0 | if (key != NULL) { |
589 | 0 | dns_tsigkey_attach(key, &request->tsigkey); |
590 | 0 | } |
591 | |
|
592 | 0 | result = dns_message_settsigkey(message, request->tsigkey); |
593 | 0 | if (result != ISC_R_SUCCESS) { |
594 | 0 | goto cleanup; |
595 | 0 | } |
596 | | |
597 | 0 | again: |
598 | 0 | result = get_dispatch(tcp, false, requestmgr, srcaddr, destaddr, |
599 | 0 | transport, &request->dispatch); |
600 | 0 | if (result != ISC_R_SUCCESS) { |
601 | 0 | goto cleanup; |
602 | 0 | } |
603 | | |
604 | 0 | result = dns_dispatch_add(request->dispatch, loop, 0, |
605 | 0 | request->connect_timeout, request->timeout, |
606 | 0 | destaddr, transport, tlsctx_cache, |
607 | 0 | req_connected, req_senddone, req_response, |
608 | 0 | request, &id, &request->dispentry); |
609 | 0 | if (result != ISC_R_SUCCESS) { |
610 | 0 | goto cleanup; |
611 | 0 | } |
612 | | |
613 | 0 | message->id = id; |
614 | 0 | result = req_render(message, &request->query, options, mctx); |
615 | 0 | if (result == DNS_R_USETCP && !tcp) { |
616 | | /* Try again using TCP. */ |
617 | 0 | dns_message_renderreset(message); |
618 | 0 | dns_dispatch_done(&request->dispentry); |
619 | 0 | dns_dispatch_detach(&request->dispatch); |
620 | 0 | options |= DNS_REQUESTOPT_TCP; |
621 | 0 | tcp = true; |
622 | 0 | goto again; |
623 | 0 | } else if (result != ISC_R_SUCCESS) { |
624 | 0 | goto cleanup; |
625 | 0 | } |
626 | | |
627 | 0 | result = dns_message_getquerytsig(message, mctx, &request->tsig); |
628 | 0 | if (result != ISC_R_SUCCESS) { |
629 | 0 | goto cleanup; |
630 | 0 | } |
631 | | |
632 | 0 | request->destaddr = *destaddr; |
633 | 0 | request->flags |= DNS_REQUEST_F_CONNECTING; |
634 | 0 | if (tcp) { |
635 | 0 | request->flags |= DNS_REQUEST_F_TCP; |
636 | 0 | } |
637 | |
|
638 | 0 | dns_requestmgr_attach(requestmgr, &request->requestmgr); |
639 | 0 | ISC_LIST_APPEND(requestmgr->requests[request->tid], request, link); |
640 | |
|
641 | 0 | dns_request_ref(request); /* detached in req_connected() */ |
642 | 0 | result = dns_dispatch_connect(request->dispentry); |
643 | 0 | if (result != ISC_R_SUCCESS) { |
644 | 0 | dns_request_unref(request); |
645 | 0 | goto cleanup; |
646 | 0 | } |
647 | | |
648 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
649 | 0 | *requestp = request; |
650 | |
|
651 | 0 | cleanup: |
652 | 0 | if (result != ISC_R_SUCCESS) { |
653 | 0 | req_cleanup(request); |
654 | 0 | dns_request_detach(&request); |
655 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: failed %s", __func__, |
656 | 0 | isc_result_totext(result)); |
657 | 0 | } |
658 | 0 | done: |
659 | 0 | rcu_read_unlock(); |
660 | |
|
661 | 0 | return result; |
662 | 0 | } |
663 | | |
664 | | static isc_result_t |
665 | | req_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, |
666 | 0 | isc_mem_t *mctx) { |
667 | 0 | isc_buffer_t *buf1 = NULL; |
668 | 0 | isc_buffer_t *buf2 = NULL; |
669 | 0 | isc_result_t result; |
670 | 0 | isc_region_t r; |
671 | 0 | dns_compress_t cctx; |
672 | 0 | unsigned int compflags; |
673 | |
|
674 | 0 | REQUIRE(bufferp != NULL && *bufferp == NULL); |
675 | |
|
676 | 0 | req_log(ISC_LOG_DEBUG(3), "%s", __func__); |
677 | | |
678 | | /* |
679 | | * Create buffer able to hold largest possible message. |
680 | | */ |
681 | 0 | isc_buffer_allocate(mctx, &buf1, 65535); |
682 | |
|
683 | 0 | compflags = 0; |
684 | 0 | if ((options & DNS_REQUESTOPT_LARGE) != 0) { |
685 | 0 | compflags |= DNS_COMPRESS_LARGE; |
686 | 0 | } |
687 | 0 | if ((options & DNS_REQUESTOPT_CASE) != 0) { |
688 | 0 | compflags |= DNS_COMPRESS_CASE; |
689 | 0 | } |
690 | 0 | dns_compress_init(&cctx, mctx, compflags); |
691 | | |
692 | | /* |
693 | | * Render message. |
694 | | */ |
695 | 0 | result = dns_message_renderbegin(message, &cctx, buf1); |
696 | 0 | if (result != ISC_R_SUCCESS) { |
697 | 0 | goto cleanup; |
698 | 0 | } |
699 | 0 | result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); |
700 | 0 | if (result != ISC_R_SUCCESS) { |
701 | 0 | goto cleanup; |
702 | 0 | } |
703 | 0 | result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0); |
704 | 0 | if (result != ISC_R_SUCCESS) { |
705 | 0 | goto cleanup; |
706 | 0 | } |
707 | 0 | result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0); |
708 | 0 | if (result != ISC_R_SUCCESS) { |
709 | 0 | goto cleanup; |
710 | 0 | } |
711 | 0 | result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0); |
712 | 0 | if (result != ISC_R_SUCCESS) { |
713 | 0 | goto cleanup; |
714 | 0 | } |
715 | 0 | result = dns_message_renderend(message); |
716 | 0 | if (result != ISC_R_SUCCESS) { |
717 | 0 | goto cleanup; |
718 | 0 | } |
719 | | |
720 | | /* |
721 | | * Copy rendered message to exact sized buffer. |
722 | | */ |
723 | 0 | isc_buffer_usedregion(buf1, &r); |
724 | 0 | if ((options & DNS_REQUESTOPT_TCP) == 0 && r.length > 512) { |
725 | 0 | result = DNS_R_USETCP; |
726 | 0 | goto cleanup; |
727 | 0 | } |
728 | 0 | isc_buffer_allocate(mctx, &buf2, r.length); |
729 | 0 | result = isc_buffer_copyregion(buf2, &r); |
730 | 0 | if (result != ISC_R_SUCCESS) { |
731 | 0 | goto cleanup; |
732 | 0 | } |
733 | | |
734 | | /* |
735 | | * Cleanup and return. |
736 | | */ |
737 | 0 | dns_compress_invalidate(&cctx); |
738 | 0 | isc_buffer_free(&buf1); |
739 | 0 | *bufferp = buf2; |
740 | 0 | return ISC_R_SUCCESS; |
741 | | |
742 | 0 | cleanup: |
743 | 0 | dns_message_renderreset(message); |
744 | 0 | dns_compress_invalidate(&cctx); |
745 | 0 | if (buf1 != NULL) { |
746 | 0 | isc_buffer_free(&buf1); |
747 | 0 | } |
748 | 0 | if (buf2 != NULL) { |
749 | 0 | isc_buffer_free(&buf2); |
750 | 0 | } |
751 | 0 | return result; |
752 | 0 | } |
753 | | |
754 | | static void |
755 | 0 | request_cancel(dns_request_t *request) { |
756 | 0 | REQUIRE(VALID_REQUEST(request)); |
757 | 0 | REQUIRE(request->tid == isc_tid()); |
758 | |
|
759 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
760 | | /* The request callback was already called */ |
761 | 0 | return; |
762 | 0 | } |
763 | | |
764 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
765 | 0 | req_sendevent(request, ISC_R_CANCELED); /* call asynchronously */ |
766 | 0 | } |
767 | | |
768 | | static void |
769 | 0 | req_cancel_cb(void *arg) { |
770 | 0 | dns_request_t *request = arg; |
771 | |
|
772 | 0 | request_cancel(request); |
773 | 0 | dns_request_unref(request); |
774 | 0 | } |
775 | | |
776 | | void |
777 | 0 | dns_request_cancel(dns_request_t *request) { |
778 | 0 | REQUIRE(VALID_REQUEST(request)); |
779 | |
|
780 | 0 | if (request->tid == isc_tid()) { |
781 | 0 | request_cancel(request); |
782 | 0 | } else { |
783 | 0 | dns_request_ref(request); |
784 | 0 | isc_async_run(request->loop, req_cancel_cb, request); |
785 | 0 | } |
786 | 0 | } |
787 | | |
788 | | isc_result_t |
789 | | dns_request_getresponse(dns_request_t *request, dns_message_t *message, |
790 | 0 | unsigned int options) { |
791 | 0 | isc_result_t result; |
792 | |
|
793 | 0 | REQUIRE(VALID_REQUEST(request)); |
794 | 0 | REQUIRE(request->tid == isc_tid()); |
795 | 0 | REQUIRE(request->answer != NULL); |
796 | |
|
797 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
798 | |
|
799 | 0 | dns_message_setquerytsig(message, request->tsig); |
800 | 0 | result = dns_message_settsigkey(message, request->tsigkey); |
801 | 0 | if (result != ISC_R_SUCCESS) { |
802 | 0 | return result; |
803 | 0 | } |
804 | 0 | result = dns_message_parse(message, request->answer, options); |
805 | 0 | if (result != ISC_R_SUCCESS) { |
806 | 0 | return result; |
807 | 0 | } |
808 | 0 | if (request->tsigkey != NULL) { |
809 | 0 | result = dns_tsig_verify(request->answer, message, NULL, NULL); |
810 | 0 | } |
811 | 0 | return result; |
812 | 0 | } |
813 | | |
814 | | isc_buffer_t * |
815 | 0 | dns_request_getanswer(dns_request_t *request) { |
816 | 0 | REQUIRE(VALID_REQUEST(request)); |
817 | 0 | REQUIRE(request->tid == isc_tid()); |
818 | |
|
819 | 0 | return request->answer; |
820 | 0 | } |
821 | | |
822 | | bool |
823 | 0 | dns_request_usedtcp(dns_request_t *request) { |
824 | 0 | REQUIRE(VALID_REQUEST(request)); |
825 | 0 | REQUIRE(request->tid == isc_tid()); |
826 | |
|
827 | 0 | return (request->flags & DNS_REQUEST_F_TCP) != 0; |
828 | 0 | } |
829 | | |
830 | | void |
831 | 0 | dns_request_destroy(dns_request_t **requestp) { |
832 | 0 | REQUIRE(requestp != NULL && VALID_REQUEST(*requestp)); |
833 | |
|
834 | 0 | dns_request_t *request = *requestp; |
835 | 0 | *requestp = NULL; |
836 | |
|
837 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
838 | |
|
839 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
840 | 0 | dns_request_cancel(request); |
841 | 0 | } |
842 | | |
843 | | /* final detach to shut down request */ |
844 | 0 | dns_request_detach(&request); |
845 | 0 | } |
846 | | |
847 | | static void |
848 | | req_connected(isc_result_t eresult, isc_region_t *region ISC_ATTR_UNUSED, |
849 | 0 | void *arg) { |
850 | 0 | dns_request_t *request = (dns_request_t *)arg; |
851 | |
|
852 | 0 | REQUIRE(VALID_REQUEST(request)); |
853 | 0 | REQUIRE(request->tid == isc_tid()); |
854 | 0 | REQUIRE(DNS_REQUEST_CONNECTING(request)); |
855 | |
|
856 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p: %s", __func__, request, |
857 | 0 | isc_result_totext(eresult)); |
858 | |
|
859 | 0 | request->flags &= ~DNS_REQUEST_F_CONNECTING; |
860 | |
|
861 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
862 | | /* The request callback was already called */ |
863 | 0 | goto detach; |
864 | 0 | } |
865 | | |
866 | 0 | if (eresult == ISC_R_SUCCESS) { |
867 | 0 | req_send(request); |
868 | 0 | } else { |
869 | 0 | req_sendevent(request, eresult); |
870 | 0 | } |
871 | |
|
872 | 0 | detach: |
873 | | /* attached in dns_request_create/_createraw() */ |
874 | 0 | dns_request_unref(request); |
875 | 0 | } |
876 | | |
877 | | static void |
878 | | req_senddone(isc_result_t eresult, isc_region_t *region ISC_ATTR_UNUSED, |
879 | 0 | void *arg) { |
880 | 0 | dns_request_t *request = (dns_request_t *)arg; |
881 | |
|
882 | 0 | REQUIRE(VALID_REQUEST(request)); |
883 | 0 | REQUIRE(request->tid == isc_tid()); |
884 | 0 | REQUIRE(DNS_REQUEST_SENDING(request)); |
885 | |
|
886 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
887 | |
|
888 | 0 | request->flags &= ~DNS_REQUEST_F_SENDING; |
889 | |
|
890 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
891 | | /* The request callback was already called */ |
892 | 0 | goto detach; |
893 | 0 | } |
894 | | |
895 | 0 | if (eresult != ISC_R_SUCCESS) { |
896 | 0 | req_sendevent(request, eresult); |
897 | 0 | } |
898 | |
|
899 | 0 | detach: |
900 | | /* attached in req_send() */ |
901 | 0 | dns_request_unref(request); |
902 | 0 | } |
903 | | |
904 | | static void |
905 | 0 | req_response(isc_result_t eresult, isc_region_t *region, void *arg) { |
906 | 0 | dns_request_t *request = (dns_request_t *)arg; |
907 | |
|
908 | 0 | if (eresult == ISC_R_CANCELED) { |
909 | 0 | return; |
910 | 0 | } |
911 | | |
912 | 0 | REQUIRE(VALID_REQUEST(request)); |
913 | 0 | REQUIRE(request->tid == isc_tid()); |
914 | |
|
915 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p: %s", __func__, request, |
916 | 0 | isc_result_totext(eresult)); |
917 | |
|
918 | 0 | if (DNS_REQUEST_COMPLETE(request)) { |
919 | | /* The request callback was already called */ |
920 | 0 | return; |
921 | 0 | } |
922 | | |
923 | 0 | switch (eresult) { |
924 | 0 | case ISC_R_TIMEDOUT: |
925 | 0 | if (request->udpcount > 1 && !dns_request_usedtcp(request)) { |
926 | 0 | request->udpcount -= 1; |
927 | 0 | dns_dispatch_resume(request->dispentry, |
928 | 0 | request->timeout); |
929 | 0 | if (!DNS_REQUEST_SENDING(request)) { |
930 | 0 | req_send(request); |
931 | 0 | } |
932 | 0 | return; |
933 | 0 | } |
934 | 0 | break; |
935 | 0 | case ISC_R_SUCCESS: |
936 | | /* Copy region to request. */ |
937 | 0 | isc_buffer_allocate(request->mctx, &request->answer, |
938 | 0 | region->length); |
939 | 0 | eresult = isc_buffer_copyregion(request->answer, region); |
940 | 0 | if (eresult != ISC_R_SUCCESS) { |
941 | 0 | isc_buffer_free(&request->answer); |
942 | 0 | } |
943 | 0 | break; |
944 | 0 | default: |
945 | 0 | break; |
946 | 0 | } |
947 | | |
948 | 0 | req_sendevent(request, eresult); |
949 | 0 | } |
950 | | |
951 | | static void |
952 | 0 | req_sendevent_cb(void *arg) { |
953 | 0 | dns_request_t *request = arg; |
954 | |
|
955 | 0 | request->cb(request); |
956 | 0 | dns_request_unref(request); |
957 | 0 | } |
958 | | |
959 | | static void |
960 | 0 | req_cleanup(dns_request_t *request) { |
961 | 0 | if (ISC_LINK_LINKED(request, link)) { |
962 | 0 | ISC_LIST_UNLINK(request->requestmgr->requests[request->tid], |
963 | 0 | request, link); |
964 | 0 | } |
965 | 0 | if (request->dispentry != NULL) { |
966 | 0 | dns_dispatch_done(&request->dispentry); |
967 | 0 | } |
968 | 0 | if (request->dispatch != NULL) { |
969 | 0 | dns_dispatch_detach(&request->dispatch); |
970 | 0 | } |
971 | 0 | } |
972 | | |
973 | | static void |
974 | 0 | req_sendevent(dns_request_t *request, isc_result_t result) { |
975 | 0 | REQUIRE(VALID_REQUEST(request)); |
976 | 0 | REQUIRE(request->tid == isc_tid()); |
977 | 0 | REQUIRE(!DNS_REQUEST_COMPLETE(request)); |
978 | |
|
979 | 0 | request->flags |= DNS_REQUEST_F_COMPLETE; |
980 | |
|
981 | 0 | req_cleanup(request); |
982 | |
|
983 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p: %s", __func__, request, |
984 | 0 | isc_result_totext(result)); |
985 | |
|
986 | 0 | request->result = result; |
987 | | |
988 | | /* |
989 | | * Do not call request->cb directly as it introduces a dead lock |
990 | | * between dns_zonemgr_shutdown and sendtoprimary in lib/dns/zone.c |
991 | | * zone->lock. |
992 | | */ |
993 | 0 | dns_request_ref(request); |
994 | 0 | isc_async_run(request->loop, req_sendevent_cb, request); |
995 | 0 | } |
996 | | |
997 | | static void |
998 | 0 | req_destroy(dns_request_t *request) { |
999 | 0 | REQUIRE(VALID_REQUEST(request)); |
1000 | 0 | REQUIRE(request->tid == isc_tid()); |
1001 | 0 | REQUIRE(!ISC_LINK_LINKED(request, link)); |
1002 | |
|
1003 | 0 | req_log(ISC_LOG_DEBUG(3), "%s: request %p", __func__, request); |
1004 | | |
1005 | | /* |
1006 | | * These should have been cleaned up before the |
1007 | | * completion event was sent. |
1008 | | */ |
1009 | 0 | INSIST(!ISC_LINK_LINKED(request, link)); |
1010 | 0 | INSIST(request->dispentry == NULL); |
1011 | 0 | INSIST(request->dispatch == NULL); |
1012 | |
|
1013 | 0 | request->magic = 0; |
1014 | 0 | if (request->query != NULL) { |
1015 | 0 | isc_buffer_free(&request->query); |
1016 | 0 | } |
1017 | 0 | if (request->answer != NULL) { |
1018 | 0 | isc_buffer_free(&request->answer); |
1019 | 0 | } |
1020 | 0 | if (request->tsig != NULL) { |
1021 | 0 | isc_buffer_free(&request->tsig); |
1022 | 0 | } |
1023 | 0 | if (request->tsigkey != NULL) { |
1024 | 0 | dns_tsigkey_detach(&request->tsigkey); |
1025 | 0 | } |
1026 | 0 | if (request->requestmgr != NULL) { |
1027 | 0 | dns_requestmgr_detach(&request->requestmgr); |
1028 | 0 | } |
1029 | 0 | isc_mem_putanddetach(&request->mctx, request, sizeof(*request)); |
1030 | 0 | } |
1031 | | |
1032 | | void * |
1033 | 0 | dns_request_getarg(dns_request_t *request) { |
1034 | 0 | REQUIRE(VALID_REQUEST(request)); |
1035 | 0 | REQUIRE(request->tid == isc_tid()); |
1036 | |
|
1037 | 0 | return request->arg; |
1038 | 0 | } |
1039 | | |
1040 | | isc_result_t |
1041 | 0 | dns_request_getresult(dns_request_t *request) { |
1042 | 0 | REQUIRE(VALID_REQUEST(request)); |
1043 | 0 | REQUIRE(request->tid == isc_tid()); |
1044 | |
|
1045 | 0 | return request->result; |
1046 | 0 | } |
1047 | | |
1048 | | #if DNS_REQUEST_TRACE |
1049 | | ISC_REFCOUNT_TRACE_IMPL(dns_request, req_destroy); |
1050 | | #else |
1051 | 0 | ISC_REFCOUNT_IMPL(dns_request, req_destroy); Unexecuted instantiation: dns_request_ref Unexecuted instantiation: dns_request_unref Unexecuted instantiation: dns_request_detach |
1052 | 0 | #endif |
1053 | 0 |
|
1054 | 0 | static void |
1055 | 0 | req_log(int level, const char *fmt, ...) { |
1056 | 0 | va_list ap; |
1057 | |
|
1058 | 0 | va_start(ap, fmt); |
1059 | 0 | isc_log_vwrite(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_REQUEST, level, |
1060 | 0 | fmt, ap); |
1061 | | va_end(ap); |
1062 | 0 | } |