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