1/*
2 * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: client.h,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
18
19#ifndef DNS_CLIENT_H
20#define DNS_CLIENT_H 1
21
22/*****
23 ***** Module Info
24 *****/
25
26/*! \file
27 *
28 * \brief
29 * The DNS client module provides convenient programming interfaces to various
30 * DNS services, such as name resolution with or without DNSSEC validation or
31 * dynamic DNS update.  This module is primarily expected to be used by other
32 * applications than BIND9-related ones that need such advanced DNS features.
33 *
34 * MP:
35 *\li	In the typical usage of this module, application threads will not share
36 *	the same data structures created and manipulated in this module.
37 *	However, the module still ensures appropriate synchronization of such
38 *	data structures.
39 *
40 * Resources:
41 *\li	TBS
42 *
43 * Security:
44 *\li	This module does not handle any low-level data directly, and so no
45 *	security issue specific to this module is anticipated.
46 */
47
48#include <isc/event.h>
49#include <isc/sockaddr.h>
50
51#include <dns/tsig.h>
52#include <dns/types.h>
53
54#include <dst/dst.h>
55
56typedef enum {
57	updateop_none = 0,
58	updateop_add = 1,
59	updateop_delete = 2,
60	updateop_exist = 3,
61	updateop_notexist = 4,
62	updateop_max = 5
63} dns_client_updateop_t;
64
65ISC_LANG_BEGINDECLS
66
67/***
68 *** Types
69 ***/
70
71/*%
72 * Optional flags for dns_client_create(x).
73 */
74/*%< Enable caching resolution results (experimental). */
75#define DNS_CLIENTCREATEOPT_USECACHE	0x8000
76
77/*%
78 * Optional flags for dns_client_(start)resolve.
79 */
80/*%< Disable DNSSEC validation. */
81#define DNS_CLIENTRESOPT_NODNSSEC	0x01
82/*%< Allow running external context. */
83#define DNS_CLIENTRESOPT_ALLOWRUN	0x02
84
85/*%
86 * Optional flags for dns_client_(start)request.
87 */
88/*%< Allow running external context. */
89#define DNS_CLIENTREQOPT_ALLOWRUN	0x01
90
91/*%
92 * A dns_clientresevent_t is sent when name resolution performed by a client
93 * completes.  'result' stores the result code of the entire resolution
94 * procedure.  'vresult' specifically stores the result code of DNSSEC
95 * validation if it is performed.  When name resolution successfully completes,
96 * 'answerlist' is typically non empty, containing answer names along with
97 * RRsets.  It is the receiver's responsibility to free this list by calling
98 * dns_client_freeresanswer() before freeing the event structure.
99 */
100typedef struct dns_clientresevent {
101	ISC_EVENT_COMMON(struct dns_clientresevent);
102	isc_result_t	result;
103	isc_result_t	vresult;
104	dns_namelist_t	answerlist;
105} dns_clientresevent_t;		/* too long? */
106
107/*%
108 * Status of a dynamic update procedure.
109 */
110typedef enum {
111	dns_clientupdatestate_prepare,	/*%< no updates have been sent */
112	dns_clientupdatestate_sent,	/*%< updates were sent, no response */
113	dns_clientupdatestate_done	/*%< update was sent and succeeded */
114} dns_clientupdatestate_t;
115
116/*%
117 * A dns_clientreqevent_t is sent when a DNS request is completed by a client.
118 * 'result' stores the result code of the entire transaction.
119 * If the transaction is successfully completed but the response packet cannot
120 * be parsed, 'result' will store the result code of dns_message_parse().
121 * If the response packet is received, 'rmessage' will contain the response
122 * message, whether it is successfully parsed or not.
123 */
124typedef struct dns_clientreqevent {
125	ISC_EVENT_COMMON(struct dns_clientreqevent);
126	isc_result_t	result;
127	dns_message_t	*rmessage;
128} dns_clientreqevent_t;		/* too long? */
129
130/*%
131 * A dns_clientupdateevent_t is sent when dynamic update performed by a client
132 * completes.  'result' stores the result code of the entire update procedure.
133 * 'state' specifies the status of the update procedure when this event is
134 * sent.  This can be used as a hint by the receiver to determine whether
135 * the update attempt was ever made.  In particular, if the state is
136 * dns_clientupdatestate_prepare, the receiver can be sure that the requested
137 * update was not applied.
138 */
139typedef struct dns_clientupdateevent {
140	ISC_EVENT_COMMON(struct dns_clientupdateevent);
141	isc_result_t		result;
142	dns_clientupdatestate_t	state;
143} dns_clientupdateevent_t;	/* too long? */
144
145isc_result_t
146dns_client_create(dns_client_t **clientp, unsigned int options);
147
148isc_result_t
149dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr,
150		   isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr,
151		   unsigned int options, dns_client_t **clientp);
152/*%<
153 * Create a DNS client.  These functions create a new client object with
154 * minimal internal resources such as the default 'view' for the IN class and
155 * IPv4/IPv6 dispatches for the view.
156 *
157 * dns_client_createx() takes 'manager' arguments so that the caller can
158 * control the behavior of the client through the underlying event framework.
159 * On the other hand, dns_client_create() simplifies the interface and creates
160 * the managers internally.  A DNS client object created via
161 * dns_client_create() is expected to be used by an application that only needs
162 * simple synchronous services or by a thread-based application.
163 *
164 * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
165 * dns_client_create(x) will create a cache database with the view.
166 *
167 * Requires:
168 *
169 *\li	'mctx' is a valid memory context.
170 *
171 *\li	'actx' is a valid application context.
172 *
173 *\li	'taskmgr' is a valid task manager.
174 *
175 *\li	'socketmgr' is a valid socket manager.
176 *
177 *\li	'timermgr' is a valid timer manager.
178 *
179 *\li	clientp != NULL && *clientp == NULL.
180 *
181 * Returns:
182 *
183 *\li	#ISC_R_SUCCESS				On success.
184 *
185 *\li	Anything else				Failure.
186 */
187
188void
189dns_client_destroy(dns_client_t **clientp);
190/*%<
191 * Destroy 'client'.
192 *
193 * Requires:
194 *
195 *\li	'*clientp' is a valid client.
196 *
197 * Ensures:
198 *
199 *\li	*clientp == NULL.
200 */
201
202isc_result_t
203dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
204		      dns_name_t *namespace, isc_sockaddrlist_t *addrs);
205/*%<
206 * Specify a list of addresses of recursive name servers that the client will
207 * use for name resolution.  A view for the 'rdclass' class must be created
208 * beforehand.  If 'namespace' is non NULL, the specified server will be used
209 * if and only if the query name is a subdomain of 'namespace'.  When servers
210 * for multiple 'namespace's are provided, and a query name is covered by
211 * more than one 'namespace', the servers for the best (longest) matching
212 * namespace will be used.  If 'namespace' is NULL, it works as if
213 * dns_rootname (.) were specified.
214 *
215 * Requires:
216 *
217 *\li	'client' is a valid client.
218 *
219 *\li	'namespace' is NULL or a valid name.
220 *
221 *\li	'addrs' != NULL.
222 *
223 * Returns:
224 *
225 *\li	#ISC_R_SUCCESS				On success.
226 *
227 *\li	Anything else				Failure.
228 */
229
230isc_result_t
231dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
232			dns_name_t *namespace);
233/*%<
234 * Remove configured recursive name servers for the 'rdclass' and 'namespace'
235 * from the client.  See the description of dns_client_setservers() for
236 * the requirements about 'rdclass' and 'namespace'.
237 *
238 * Requires:
239 *
240 *\li	'client' is a valid client.
241 *
242 *\li	'namespace' is NULL or a valid name.
243 *
244 * Returns:
245 *
246 *\li	#ISC_R_SUCCESS				On success.
247 *
248 *\li	Anything else				Failure.
249 */
250
251isc_result_t
252dns_client_resolve(dns_client_t *client, dns_name_t *name,
253		   dns_rdataclass_t rdclass, dns_rdatatype_t type,
254		   unsigned int options, dns_namelist_t *namelist);
255
256isc_result_t
257dns_client_startresolve(dns_client_t *client, dns_name_t *name,
258			dns_rdataclass_t rdclass, dns_rdatatype_t type,
259			unsigned int options, isc_task_t *task,
260			isc_taskaction_t action, void *arg,
261			dns_clientrestrans_t **transp);
262/*%<
263 * Perform name resolution for 'name', 'rdclass', and 'type'.
264 *
265 * If any trusted keys are configured and the query name is considered to
266 * belong to a secure zone, these functions also validate the responses
267 * using DNSSEC by default.  If the DNS_CLIENTRESOPT_NODNSSEC flag is set
268 * in 'options', DNSSEC validation is disabled regardless of the configured
269 * trusted keys or the query name.
270 *
271 * dns_client_resolve() provides a synchronous service.  This function starts
272 * name resolution internally and blocks until it completes.  On success,
273 * 'namelist' will contain a list of answer names, each of which has
274 * corresponding RRsets.  The caller must provide a valid empty list, and
275 * is responsible for freeing the list content via dns_client_freeresanswer().
276 * If the name resolution fails due to an error in DNSSEC validation,
277 * dns_client_resolve() returns the result code indicating the validation
278 * error. Otherwise, it returns the result code of the entire resolution
279 * process, either success or failure.
280 *
281 * It is typically expected that the client object passed to
282 * dns_client_resolve() was created via dns_client_create() and has its own
283 * managers and contexts.  However, if the DNS_CLIENTRESOPT_ALLOWRUN flag is
284 * set in 'options', this function performs the synchronous service even if
285 * it does not have its own manager and context structures.
286 *
287 * dns_client_startresolve() is an asynchronous version of dns_client_resolve()
288 * and does not block.  When name resolution is completed, 'action' will be
289 * called with the argument of a 'dns_clientresevent_t' object, which contains
290 * the resulting list of answer names (on success).  On return, '*transp' is
291 * set to an opaque transaction ID so that the caller can cancel this
292 * resolution process.
293 *
294 * Requires:
295 *
296 *\li	'client' is a valid client.
297 *
298 *\li	'addrs' != NULL.
299 *
300 *\li	'name' is a valid name.
301 *
302 *\li	'namelist' != NULL and is not empty.
303 *
304 *\li	'task' is a valid task.
305 *
306 *\li	'transp' != NULL && *transp == NULL;
307 *
308 * Returns:
309 *
310 *\li	#ISC_R_SUCCESS				On success.
311 *
312 *\li	Anything else				Failure.
313 */
314
315void
316dns_client_cancelresolve(dns_clientrestrans_t *trans);
317/*%<
318 * Cancel an ongoing resolution procedure started via
319 * dns_client_startresolve().
320 *
321 * Notes:
322 *
323 *\li	If the resolution procedure has not completed, post its CLIENTRESDONE
324 *	event with a result code of #ISC_R_CANCELED.
325 *
326 * Requires:
327 *
328 *\li	'trans' is a valid transaction ID.
329 */
330
331void
332dns_client_destroyrestrans(dns_clientrestrans_t **transp);
333/*%<
334 * Destroy name resolution transaction state identified by '*transp'.
335 *
336 * Requires:
337 *
338 *\li	'*transp' is a valid transaction ID.
339 *
340 *\li	The caller has received the CLIENTRESDONE event (either because the
341 *	resolution completed or because dns_client_cancelresolve() was called).
342 *
343 * Ensures:
344 *
345 *\li	*transp == NULL.
346 */
347
348void
349dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
350/*%<
351 * Free resources allocated for the content of 'namelist'.
352 *
353 * Requires:
354 *
355 *\li	'client' is a valid client.
356 *
357 *\li	'namelist' != NULL.
358 */
359
360isc_result_t
361dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
362			 dns_name_t *keyname, isc_buffer_t *keydatabuf);
363/*%<
364 * Add a DNSSEC trusted key for the 'rdclass' class.  A view for the 'rdclass'
365 * class must be created beforehand.  'keyname' is the DNS name of the key,
366 * and 'keydatabuf' stores the resource data of the key.
367 *
368 * Requires:
369 *
370 *\li	'client' is a valid client.
371 *
372 *\li	'keyname' is a valid name.
373 *
374 *\li	'keydatabuf' is a valid buffer.
375 *
376 * Returns:
377 *
378 *\li	#ISC_R_SUCCESS				On success.
379 *
380 *\li	Anything else				Failure.
381 */
382
383isc_result_t
384dns_client_request(dns_client_t *client, dns_message_t *qmessage,
385		   dns_message_t *rmessage, isc_sockaddr_t *server,
386		   unsigned int options, unsigned int parseoptions,
387		   dns_tsec_t *tsec, unsigned int timeout,
388		   unsigned int udptimeout, unsigned int udpretries);
389
390isc_result_t
391dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage,
392			dns_message_t *rmessage, isc_sockaddr_t *server,
393			unsigned int options, unsigned int parseoptions,
394			dns_tsec_t *tsec, unsigned int timeout,
395			unsigned int udptimeout, unsigned int udpretries,
396			isc_task_t *task, isc_taskaction_t action, void *arg,
397			dns_clientreqtrans_t **transp);
398
399/*%<
400 * Send a DNS request containig a query message 'query' to 'server'.
401 *
402 * 'parseoptions' will be used when the response packet is parsed, and will be
403 * passed to dns_message_parse() via dns_request_getresponse().  See
404 * dns_message_parse() for more details.
405 *
406 * 'tsec' is a transaction security object containing, e.g. a TSIG key for
407 * authenticating the request/response transaction.  This is optional and can
408 * be NULL, in which case this library performs the transaction  without any
409 * transaction authentication.
410 *
411 * 'timeout', 'udptimeout', and 'udpretries' are passed to
412 * dns_request_createvia3().  See dns_request_createvia3() for more details.
413 *
414 * dns_client_request() provides a synchronous service.  This function sends
415 * the request and blocks until a response is received.  On success,
416 * 'rmessage' will contain the response message.  The caller must provide a
417 * valid initialized message.
418 *
419 * It is usually expected that the client object passed to
420 * dns_client_request() was created via dns_client_create() and has its own
421 * managers and contexts.  However, if the DNS_CLIENTREQOPT_ALLOWRUN flag is
422 * set in 'options', this function performs the synchronous service even if
423 * it does not have its own manager and context structures.
424 *
425 * dns_client_startrequest() is an asynchronous version of dns_client_request()
426 * and does not block.  When the transaction is completed, 'action' will be
427 * called with the argument of a 'dns_clientreqevent_t' object, which contains
428 * the response message (on success).  On return, '*transp' is set to an opaque
429 * transaction ID so that the caller can cancel this request.
430 *
431 * Requires:
432 *
433 *\li	'client' is a valid client.
434 *
435 *\li	'qmessage' and 'rmessage' are valid initialized message.
436 *
437 *\li	'server' is a valid socket address structure.
438 *
439 *\li	'task' is a valid task.
440 *
441 *\li	'transp' != NULL && *transp == NULL;
442 *
443 * Returns:
444 *
445 *\li	#ISC_R_SUCCESS				On success.
446 *
447 *\li	Anything else				Failure.
448 *
449 *\li	Any result that dns_message_parse() can return.
450 */
451
452void
453dns_client_cancelrequest(dns_clientreqtrans_t *transp);
454/*%<
455 * Cancel an ongoing DNS request procedure started via
456 * dns_client_startrequest().
457 *
458 * Notes:
459 *
460 *\li	If the request procedure has not completed, post its CLIENTREQDONE
461 *	event with a result code of #ISC_R_CANCELED.
462 *
463 * Requires:
464 *
465 *\li	'trans' is a valid transaction ID.
466 */
467
468void
469dns_client_destroyreqtrans(dns_clientreqtrans_t **transp);
470/*%
471 * Destroy DNS request transaction state identified by '*transp'.
472 *
473 * Requires:
474 *
475 *\li	'*transp' is a valid transaction ID.
476 *
477 *\li	The caller has received the CLIENTREQDONE event (either because the
478 *	request completed or because dns_client_cancelrequest() was called).
479 *
480 * Ensures:
481 *
482 *\li	*transp == NULL.
483 */
484
485isc_result_t
486dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass,
487		  dns_name_t *zonename, dns_namelist_t *prerequisites,
488		  dns_namelist_t *updates, isc_sockaddrlist_t *servers,
489		  dns_tsec_t *tsec, unsigned int options);
490
491isc_result_t
492dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass,
493		       dns_name_t *zonename, dns_namelist_t *prerequisites,
494		       dns_namelist_t *updates, isc_sockaddrlist_t *servers,
495		       dns_tsec_t *tsec, unsigned int options,
496		       isc_task_t *task, isc_taskaction_t action, void *arg,
497		       dns_clientupdatetrans_t **transp);
498/*%<
499 * Perform DNS dynamic update for 'updates' of the 'rdclass' class with
500 * optional 'prerequisites'.
501 *
502 * 'updates' are a list of names with associated RRsets to be updated.
503 *
504 * 'prerequisites' are a list of names with associated RRsets corresponding to
505 * the prerequisites of the updates.  This is optional and can be NULL, in
506 * which case the prerequisite section of the update message will be empty.
507 *
508 * Both 'updates' and 'prerequisites' must be constructed as specified in
509 * RFC2136.
510 *
511 * 'zonename' is the name of the zone in which the updated names exist.
512 * This is optional and can be NULL.  In this case, these functions internally
513 * identify the appropriate zone through some queries for the SOA RR starting
514 * with the first name in prerequisites or updates.
515 *
516 * 'servers' is a list of authoritative servers to which the update message
517 * should be sent.  This is optional and can be NULL.  In this case, these
518 * functions internally identify the appropriate primary server name and its
519 * addresses through some queries for the SOA RR (like the case of zonename)
520 * and supplemental A/AAAA queries for the server name.
521 * Note: The client module generally assumes the given addresses are of the
522 * primary server of the corresponding zone.  It will work even if a secondary
523 * server address is specified as long as the server allows update forwarding,
524 * it is generally discouraged to include secondary server addresses unless
525 * there's strong reason to do so.
526 *
527 * 'tsec' is a transaction security object containing, e.g. a TSIG key for
528 * authenticating the update transaction (and the supplemental query/response
529 * transactions if the server is specified).  This is optional and can be
530 * NULL, in which case the library tries the update without any transaction
531 * authentication.
532 *
533 * dns_client_update() provides a synchronous service.  This function blocks
534 * until the entire update procedure completes, including the additional
535 * queries when necessary.
536 *
537 * dns_client_startupdate() is an asynchronous version of dns_client_update().
538 * It immediately returns (typically with *transp being set to a non-NULL
539 * pointer), and performs the update procedure through a set of internal
540 * events.  All transactions including the additional query exchanges are
541 * performed as a separate event, so none of these events cause blocking
542 * operation.  When the update procedure completes, the specified function
543 * 'action' will be called with the argument of a 'dns_clientupdateevent_t'
544 * structure.  On return, '*transp' is set to an opaque transaction ID so that
545 * the caller can cancel this update process.
546 *
547 * Notes:
548 *\li	No options are currently defined.
549 *
550 * Requires:
551 *
552 *\li	'client' is a valid client.
553 *
554 *\li	'updates' != NULL.
555 *
556 *\li	'task' is a valid task.
557 *
558 *\li	'transp' != NULL && *transp == NULL;
559 *
560 * Returns:
561 *
562 *\li	#ISC_R_SUCCESS				On success.
563 *
564 *\li	Anything else				Failure.
565 */
566
567void
568dns_client_cancelupdate(dns_clientupdatetrans_t *trans);
569/*%<
570 * Cancel an ongoing dynamic update procedure started via
571 * dns_client_startupdate().
572 *
573 * Notes:
574 *
575 *\li	If the update procedure has not completed, post its UPDATEDONE
576 *	event with a result code of #ISC_R_CANCELED.
577 *
578 * Requires:
579 *
580 *\li	'trans' is a valid transaction ID.
581 */
582
583void
584dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp);
585/*%<
586 * Destroy dynamic update transaction identified by '*transp'.
587 *
588 * Requires:
589 *
590 *\li	'*transp' is a valid transaction ID.
591 *
592 *\li	The caller has received the UPDATEDONE event (either because the
593 *	update completed or because dns_client_cancelupdate() was called).
594 *
595 * Ensures:
596 *
597 *\li	*transp == NULL.
598 */
599
600isc_result_t
601dns_client_updaterec(dns_client_updateop_t op, dns_name_t *owner,
602		     dns_rdatatype_t type, dns_rdata_t *source,
603		     dns_ttl_t ttl, dns_name_t *target,
604		     dns_rdataset_t *rdataset, dns_rdatalist_t *rdatalist,
605		     dns_rdata_t *rdata, isc_mem_t *mctx);
606/*%<
607 * TBD
608 */
609
610void
611dns_client_freeupdate(dns_name_t **namep);
612/*%<
613 * TBD
614 */
615
616isc_mem_t *
617dns_client_mctx(dns_client_t *client);
618
619ISC_LANG_ENDDECLS
620
621#endif /* DNS_CLIENT_H */
622