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 #ifndef DNS_REQUEST_H
15 #define DNS_REQUEST_H 1
16 
17 /*****
18 ***** Module Info
19 *****/
20 
21 /*! \file dns/request.h
22  *
23  * \brief
24  * The request module provides simple request/response services useful for
25  * sending SOA queries, DNS Notify messages, and dynamic update requests.
26  *
27  * MP:
28  *\li	The module ensures appropriate synchronization of data structures it
29  *	creates and manipulates.
30  *
31  * Resources:
32  *\li	TBS
33  *
34  * Security:
35  *\li	No anticipated impact.
36  */
37 
38 #include <stdbool.h>
39 
40 #include <isc/event.h>
41 #include <isc/lang.h>
42 
43 #include <dns/types.h>
44 
45 #define DNS_REQUESTOPT_TCP     0x00000001U
46 #define DNS_REQUESTOPT_CASE    0x00000002U
47 #define DNS_REQUESTOPT_FIXEDID 0x00000004U
48 #define DNS_REQUESTOPT_SHARE   0x00000008U
49 
50 typedef struct dns_requestevent {
51 	ISC_EVENT_COMMON(struct dns_requestevent);
52 	isc_result_t   result;
53 	dns_request_t *request;
54 } dns_requestevent_t;
55 
56 ISC_LANG_BEGINDECLS
57 
58 isc_result_t
59 dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
60 		      isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
61 		      dns_dispatchmgr_t *dispatchmgr,
62 		      dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
63 		      dns_requestmgr_t **requestmgrp);
64 /*%<
65  * Create a request manager.
66  *
67  * Requires:
68  *
69  *\li	'mctx' is a valid memory context.
70  *
71  *\li	'timermgr' is a valid timer manager.
72  *
73  *\li	'socketmgr' is a valid socket manager.
74  *
75  *\li	'taskmgr' is a valid task manager.
76  *
77  *\li	'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL.
78  *
79  *\li	'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
80  *
81  *\li	requestmgrp != NULL && *requestmgrp == NULL
82  *
83  * Ensures:
84  *
85  *\li	On success, *requestmgrp is a valid request manager.
86  *
87  * Returns:
88  *
89  *\li	ISC_R_SUCCESS
90  *
91  *\li	Any other result indicates failure.
92  */
93 
94 void
95 dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
96 			    isc_event_t **eventp);
97 /*%<
98  * Send '*eventp' to 'task' when 'requestmgr' has completed shutdown.
99  *
100  * Notes:
101  *
102  *\li	It is not safe to detach the last reference to 'requestmgr' until
103  *	shutdown is complete.
104  *
105  * Requires:
106  *
107  *\li	'requestmgr' is a valid request manager.
108  *
109  *\li	'task' is a valid task.
110  *
111  *\li	*eventp is a valid event.
112  *
113  * Ensures:
114  *
115  *\li	*eventp == NULL.
116  */
117 
118 void
119 dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr);
120 /*%<
121  * Start the shutdown process for 'requestmgr'.
122  *
123  * Notes:
124  *
125  *\li	This call has no effect if the request manager is already shutting
126  *	down.
127  *
128  * Requires:
129  *
130  *\li	'requestmgr' is a valid requestmgr.
131  */
132 
133 void
134 dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp);
135 /*%<
136  *	Attach to the request manager.  dns_requestmgr_shutdown() must not
137  *	have been called on 'source' prior to calling dns_requestmgr_attach().
138  *
139  * Requires:
140  *
141  *\li	'source' is a valid requestmgr.
142  *
143  *\li	'targetp' to be non NULL and '*targetp' to be NULL.
144  */
145 
146 void
147 dns_requestmgr_detach(dns_requestmgr_t **requestmgrp);
148 /*%<
149  *	Detach from the given requestmgr.  If this is the final detach
150  *	requestmgr will be destroyed.  dns_requestmgr_shutdown() must
151  *	be called before the final detach.
152  *
153  * Requires:
154  *
155  *\li	'*requestmgrp' is a valid requestmgr.
156  *
157  * Ensures:
158  *\li	'*requestmgrp' is NULL.
159  */
160 
161 isc_result_t
162 dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
163 		   const isc_sockaddr_t *address, unsigned int options,
164 		   dns_tsigkey_t *key, unsigned int timeout, isc_task_t *task,
165 		   isc_taskaction_t action, void *arg,
166 		   dns_request_t **requestp);
167 /*%<
168  * Create and send a request.
169  *
170  * Notes:
171  *
172  *\li	'message' will be rendered and sent to 'address'.  If the
173  *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
174  *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
175  *	(vs. connected) will be shared too.  The request
176  *	will timeout after 'timeout' seconds.
177  *
178  *\li	If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
179  *	compression.
180  *
181  *\li	When the request completes, successfully, due to a timeout, or
182  *	because it was canceled, a completion event will be sent to 'task'.
183  *
184  * Requires:
185  *
186  *\li	'message' is a valid DNS message.
187  *
188  *\li	'address' is a valid sockaddr.
189  *
190  *\li	'timeout' > 0
191  *
192  *\li	'task' is a valid task.
193  *
194  *\li	requestp != NULL && *requestp == NULL
195  */
196 
197 isc_result_t
198 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
199 		      const isc_sockaddr_t *srcaddr,
200 		      const isc_sockaddr_t *destaddr, isc_dscp_t dscp,
201 		      unsigned int options, dns_tsigkey_t *key,
202 		      unsigned int timeout, unsigned int udptimeout,
203 		      unsigned int udpretries, isc_task_t *task,
204 		      isc_taskaction_t action, void *arg,
205 		      dns_request_t **requestp);
206 /*%<
207  * Create and send a request.
208  *
209  * Notes:
210  *
211  *\li	'message' will be rendered and sent to 'address'.  If the
212  *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
213  *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
214  *	(vs. connected) will be shared too.  The request
215  *	will timeout after 'timeout' seconds.  UDP requests will be resent
216  *	at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
217  *
218  *\li	If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
219  *	compression.
220  *
221  *\li	When the request completes, successfully, due to a timeout, or
222  *	because it was canceled, a completion event will be sent to 'task'.
223  *
224  * Requires:
225  *
226  *\li	'message' is a valid DNS message.
227  *
228  *\li	'dstaddr' is a valid sockaddr.
229  *
230  *\li	'srcaddr' is a valid sockaddr or NULL.
231  *
232  *\li	'srcaddr' and 'dstaddr' are the same protocol family.
233  *
234  *\li	'timeout' > 0
235  *
236  *\li	'task' is a valid task.
237  *
238  *\li	requestp != NULL && *requestp == NULL
239  */
240 
241 isc_result_t
242 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
243 		      const isc_sockaddr_t *srcaddr,
244 		      const isc_sockaddr_t *destaddr, isc_dscp_t dscp,
245 		      unsigned int options, unsigned int timeout,
246 		      unsigned int udptimeout, unsigned int udpretries,
247 		      isc_task_t *task, isc_taskaction_t action, void *arg,
248 		      dns_request_t **requestp);
249 /*!<
250  * \brief Create and send a request.
251  *
252  * Notes:
253  *
254  *\li	'msgbuf' will be sent to 'destaddr' after setting the id.  If the
255  *	#DNS_REQUESTOPT_TCP option is set, TCP will be used,
256  *	#DNS_REQUESTOPT_SHARE option is set too, connecting TCP
257  *	(vs. connected) will be shared too.  The request
258  *	will timeout after 'timeout' seconds.   UDP requests will be resent
259  *	at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
260  *
261  *\li	When the request completes, successfully, due to a timeout, or
262  *	because it was canceled, a completion event will be sent to 'task'.
263  *
264  * Requires:
265  *
266  *\li	'msgbuf' is a valid DNS message in compressed wire format.
267  *
268  *\li	'destaddr' is a valid sockaddr.
269  *
270  *\li	'srcaddr' is a valid sockaddr or NULL.
271  *
272  *\li	'srcaddr' and 'dstaddr' are the same protocol family.
273  *
274  *\li	'timeout' > 0
275  *
276  *\li	'task' is a valid task.
277  *
278  *\li	requestp != NULL && *requestp == NULL
279  */
280 
281 void
282 dns_request_cancel(dns_request_t *request);
283 /*%<
284  * Cancel 'request'.
285  *
286  * Requires:
287  *
288  *\li	'request' is a valid request.
289  *
290  * Ensures:
291  *
292  *\li	If the completion event for 'request' has not yet been sent, it
293  *	will be sent, and the result code will be ISC_R_CANCELED.
294  */
295 
296 isc_result_t
297 dns_request_getresponse(dns_request_t *request, dns_message_t *message,
298 			unsigned int options);
299 /*%<
300  * Get the response to 'request' by filling in 'message'.
301  *
302  * 'options' is passed to dns_message_parse().  See dns_message_parse()
303  * for more details.
304  *
305  * Requires:
306  *
307  *\li	'request' is a valid request for which the caller has received the
308  *	completion event.
309  *
310  *\li	The result code of the completion event was #ISC_R_SUCCESS.
311  *
312  * Returns:
313  *
314  *\li	ISC_R_SUCCESS
315  *
316  *\li	Any result that dns_message_parse() can return.
317  */
318 isc_buffer_t *
319 dns_request_getanswer(dns_request_t *request);
320 /*
321  * Get the response to 'request' as a buffer.
322  *
323  * Requires:
324  *
325  *\li	'request' is a valid request for which the caller has received the
326  *	completion event.
327  *
328  * Returns:
329  *
330  *\li	a pointer to the answer buffer.
331  */
332 
333 bool
334 dns_request_usedtcp(dns_request_t *request);
335 /*%<
336  * Return whether this query used TCP or not.  Setting #DNS_REQUESTOPT_TCP
337  * in the call to dns_request_create() will cause the function to return
338  * #true, otherwise the result is based on the query message size.
339  *
340  * Requires:
341  *\li	'request' is a valid request.
342  *
343  * Returns:
344  *\li	true	if TCP was used.
345  *\li	false	if UDP was used.
346  */
347 
348 void
349 dns_request_destroy(dns_request_t **requestp);
350 /*%<
351  * Destroy 'request'.
352  *
353  * Requires:
354  *
355  *\li	'request' is a valid request for which the caller has received the
356  *	completion event.
357  *
358  * Ensures:
359  *
360  *\li	*requestp == NULL
361  */
362 
363 ISC_LANG_ENDDECLS
364 
365 #endif /* DNS_REQUEST_H */
366