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