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