2 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
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.
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.
17 /* $Id: client.h,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
20 #define DNS_CLIENT_H 1
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.
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
44 *\li This module does not handle any low-level data directly, and so no
45 * security issue specific to this module is anticipated.
48 #include <isc/event.h>
49 #include <isc/sockaddr.h>
52 #include <dns/types.h>
61 updateop_notexist = 4,
63 } dns_client_updateop_t;
72 * Optional flags for dns_client_create(x).
74 /*%< Enable caching resolution results (experimental). */
75 #define DNS_CLIENTCREATEOPT_USECACHE 0x8000
78 * Optional flags for dns_client_(start)resolve.
80 /*%< Disable DNSSEC validation. */
81 #define DNS_CLIENTRESOPT_NODNSSEC 0x01
82 /*%< Allow running external context. */
83 #define DNS_CLIENTRESOPT_ALLOWRUN 0x02
86 * Optional flags for dns_client_(start)request.
88 /*%< Allow running external context. */
89 #define DNS_CLIENTREQOPT_ALLOWRUN 0x01
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.
100 typedef struct dns_clientresevent {
101 ISC_EVENT_COMMON(struct dns_clientresevent);
103 isc_result_t vresult;
104 dns_namelist_t answerlist;
105 } dns_clientresevent_t; /* too long? */
108 * Status of a dynamic update procedure.
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;
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.
124 typedef struct dns_clientreqevent {
125 ISC_EVENT_COMMON(struct dns_clientreqevent);
127 dns_message_t *rmessage;
128 } dns_clientreqevent_t; /* too long? */
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.
139 typedef struct dns_clientupdateevent {
140 ISC_EVENT_COMMON(struct dns_clientupdateevent);
142 dns_clientupdatestate_t state;
143 } dns_clientupdateevent_t; /* too long? */
146 dns_client_create(dns_client_t **clientp, unsigned int options);
149 dns_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);
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.
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.
164 * If the DNS_CLIENTCREATEOPT_USECACHE flag is set in 'options',
165 * dns_client_create(x) will create a cache database with the view.
169 *\li 'mctx' is a valid memory context.
171 *\li 'actx' is a valid application context.
173 *\li 'taskmgr' is a valid task manager.
175 *\li 'socketmgr' is a valid socket manager.
177 *\li 'timermgr' is a valid timer manager.
179 *\li clientp != NULL && *clientp == NULL.
183 *\li #ISC_R_SUCCESS On success.
185 *\li Anything else Failure.
189 dns_client_destroy(dns_client_t **clientp);
195 *\li '*clientp' is a valid client.
199 *\li *clientp == NULL.
203 dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass,
204 dns_name_t *namespace, isc_sockaddrlist_t *addrs);
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.
217 *\li 'client' is a valid client.
219 *\li 'namespace' is NULL or a valid name.
221 *\li 'addrs' != NULL.
225 *\li #ISC_R_SUCCESS On success.
227 *\li Anything else Failure.
231 dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass,
232 dns_name_t *namespace);
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'.
240 *\li 'client' is a valid client.
242 *\li 'namespace' is NULL or a valid name.
246 *\li #ISC_R_SUCCESS On success.
248 *\li Anything else Failure.
252 dns_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);
257 dns_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);
263 * Perform name resolution for 'name', 'rdclass', and 'type'.
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.
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.
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.
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.
296 *\li 'client' is a valid client.
298 *\li 'addrs' != NULL.
300 *\li 'name' is a valid name.
302 *\li 'namelist' != NULL and is not empty.
304 *\li 'task' is a valid task.
306 *\li 'transp' != NULL && *transp == NULL;
310 *\li #ISC_R_SUCCESS On success.
312 *\li Anything else Failure.
316 dns_client_cancelresolve(dns_clientrestrans_t *trans);
318 * Cancel an ongoing resolution procedure started via
319 * dns_client_startresolve().
323 *\li If the resolution procedure has not completed, post its CLIENTRESDONE
324 * event with a result code of #ISC_R_CANCELED.
328 *\li 'trans' is a valid transaction ID.
332 dns_client_destroyrestrans(dns_clientrestrans_t **transp);
334 * Destroy name resolution transaction state identified by '*transp'.
338 *\li '*transp' is a valid transaction ID.
340 *\li The caller has received the CLIENTRESDONE event (either because the
341 * resolution completed or because dns_client_cancelresolve() was called).
345 *\li *transp == NULL.
349 dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
351 * Free resources allocated for the content of 'namelist'.
355 *\li 'client' is a valid client.
357 *\li 'namelist' != NULL.
361 dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
362 dns_name_t *keyname, isc_buffer_t *keydatabuf);
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.
370 *\li 'client' is a valid client.
372 *\li 'keyname' is a valid name.
374 *\li 'keydatabuf' is a valid buffer.
378 *\li #ISC_R_SUCCESS On success.
380 *\li Anything else Failure.
384 dns_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);
391 dns_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);
400 * Send a DNS request containig a query message 'query' to 'server'.
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.
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.
411 * 'timeout', 'udptimeout', and 'udpretries' are passed to
412 * dns_request_createvia3(). See dns_request_createvia3() for more details.
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.
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.
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.
433 *\li 'client' is a valid client.
435 *\li 'qmessage' and 'rmessage' are valid initialized message.
437 *\li 'server' is a valid socket address structure.
439 *\li 'task' is a valid task.
441 *\li 'transp' != NULL && *transp == NULL;
445 *\li #ISC_R_SUCCESS On success.
447 *\li Anything else Failure.
449 *\li Any result that dns_message_parse() can return.
453 dns_client_cancelrequest(dns_clientreqtrans_t *transp);
455 * Cancel an ongoing DNS request procedure started via
456 * dns_client_startrequest().
460 *\li If the request procedure has not completed, post its CLIENTREQDONE
461 * event with a result code of #ISC_R_CANCELED.
465 *\li 'trans' is a valid transaction ID.
469 dns_client_destroyreqtrans(dns_clientreqtrans_t **transp);
471 * Destroy DNS request transaction state identified by '*transp'.
475 *\li '*transp' is a valid transaction ID.
477 *\li The caller has received the CLIENTREQDONE event (either because the
478 * request completed or because dns_client_cancelrequest() was called).
482 *\li *transp == NULL.
486 dns_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);
492 dns_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);
499 * Perform DNS dynamic update for 'updates' of the 'rdclass' class with
500 * optional 'prerequisites'.
502 * 'updates' are a list of names with associated RRsets to be updated.
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.
508 * Both 'updates' and 'prerequisites' must be constructed as specified in
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.
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.
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
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.
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.
548 *\li No options are currently defined.
552 *\li 'client' is a valid client.
554 *\li 'updates' != NULL.
556 *\li 'task' is a valid task.
558 *\li 'transp' != NULL && *transp == NULL;
562 *\li #ISC_R_SUCCESS On success.
564 *\li Anything else Failure.
568 dns_client_cancelupdate(dns_clientupdatetrans_t *trans);
570 * Cancel an ongoing dynamic update procedure started via
571 * dns_client_startupdate().
575 *\li If the update procedure has not completed, post its UPDATEDONE
576 * event with a result code of #ISC_R_CANCELED.
580 *\li 'trans' is a valid transaction ID.
584 dns_client_destroyupdatetrans(dns_clientupdatetrans_t **transp);
586 * Destroy dynamic update transaction identified by '*transp'.
590 *\li '*transp' is a valid transaction ID.
592 *\li The caller has received the UPDATEDONE event (either because the
593 * update completed or because dns_client_cancelupdate() was called).
597 *\li *transp == NULL.
601 dns_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);
611 dns_client_freeupdate(dns_name_t **namep);
617 dns_client_mctx(dns_client_t *client);
621 #endif /* DNS_CLIENT_H */