1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * SPDX-License-Identifier: MPL-2.0 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 #ifndef DNS_CLIENT_H 15 #define DNS_CLIENT_H 1 16 17 /***** 18 ***** Module Info 19 *****/ 20 21 /*! \file 22 * 23 * \brief 24 * The DNS client module provides convenient programming interfaces to various 25 * DNS services, such as name resolution with or without DNSSEC validation or 26 * dynamic DNS update. This module is primarily expected to be used by other 27 * applications than BIND9-related ones that need such advanced DNS features. 28 * 29 * MP: 30 *\li In the typical usage of this module, application threads will not share 31 * the same data structures created and manipulated in this module. 32 * However, the module still ensures appropriate synchronization of such 33 * data structures. 34 * 35 * Resources: 36 *\li TBS 37 * 38 * Security: 39 *\li This module does not handle any low-level data directly, and so no 40 * security issue specific to this module is anticipated. 41 */ 42 43 #include <isc/event.h> 44 #include <isc/sockaddr.h> 45 46 #include <dns/tsig.h> 47 #include <dns/types.h> 48 49 #include <dst/dst.h> 50 51 typedef enum { 52 updateop_none = 0, 53 updateop_add = 1, 54 updateop_delete = 2, 55 updateop_exist = 3, 56 updateop_notexist = 4, 57 updateop_max = 5 58 } dns_client_updateop_t; 59 60 ISC_LANG_BEGINDECLS 61 62 /*** 63 *** Types 64 ***/ 65 66 /*% 67 * Optional flags for dns_client_create(x). 68 */ 69 /*%< Enable caching resolution results (experimental). */ 70 #define DNS_CLIENTCREATEOPT_USECACHE 0x8000 71 72 /*% 73 * Optional flags for dns_client_(start)resolve. 74 */ 75 /*%< Do not return DNSSEC data (e.g. RRSIGS) with response. */ 76 #define DNS_CLIENTRESOPT_NODNSSEC 0x01 77 /*%< Allow running external context. */ 78 #define DNS_CLIENTRESOPT_RESERVED 0x02 79 /*%< Don't validate responses. */ 80 #define DNS_CLIENTRESOPT_NOVALIDATE 0x04 81 /*%< Don't set the CD flag on upstream queries. */ 82 #define DNS_CLIENTRESOPT_NOCDFLAG 0x08 83 /*%< Use TCP transport. */ 84 #define DNS_CLIENTRESOPT_TCP 0x10 85 86 /*% 87 * Optional flags for dns_client_(start)request. 88 */ 89 /*%< Allow running external context. */ 90 #define DNS_CLIENTREQOPT_RESERVED 0x01 91 /*%< Use TCP transport. */ 92 #define DNS_CLIENTREQOPT_TCP 0x02 93 94 /*% 95 * Optional flags for dns_client_(start)update. 96 */ 97 /*%< Allow running external context. */ 98 #define DNS_CLIENTUPDOPT_RESERVED 0x01 99 /*%< Use TCP transport. */ 100 #define DNS_CLIENTUPDOPT_TCP 0x02 101 102 /*% 103 * View name used in dns_client. 104 */ 105 #define DNS_CLIENTVIEW_NAME "_dnsclient" 106 107 /*% 108 * A dns_clientresevent_t is sent when name resolution performed by a client 109 * completes. 'result' stores the result code of the entire resolution 110 * procedure. 'vresult' specifically stores the result code of DNSSEC 111 * validation if it is performed. When name resolution successfully completes, 112 * 'answerlist' is typically non empty, containing answer names along with 113 * RRsets. It is the receiver's responsibility to free this list by calling 114 * dns_client_freeresanswer() before freeing the event structure. 115 */ 116 typedef struct dns_clientresevent { 117 ISC_EVENT_COMMON(struct dns_clientresevent); 118 isc_result_t result; 119 isc_result_t vresult; 120 dns_namelist_t answerlist; 121 } dns_clientresevent_t; /* too long? */ 122 123 /*% 124 * A dns_clientreqevent_t is sent when a DNS request is completed by a client. 125 * 'result' stores the result code of the entire transaction. 126 * If the transaction is successfully completed but the response packet cannot 127 * be parsed, 'result' will store the result code of dns_message_parse(). 128 * If the response packet is received, 'rmessage' will contain the response 129 * message, whether it is successfully parsed or not. 130 */ 131 typedef struct dns_clientreqevent { 132 ISC_EVENT_COMMON(struct dns_clientreqevent); 133 isc_result_t result; 134 dns_message_t *rmessage; 135 } dns_clientreqevent_t; /* too long? */ 136 137 isc_result_t 138 dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, 139 isc_socketmgr_t *socketmgr, isc_timermgr_t *timermgr, 140 unsigned int options, dns_client_t **clientp, 141 const isc_sockaddr_t *localaddr4, 142 const isc_sockaddr_t *localaddr6); 143 /*%< 144 * Create a DNS client object with minimal internal resources, such as 145 * a default view for the IN class and IPv4/IPv6 dispatches for the view. 146 * 147 * dns_client_create() takes 'manager' arguments so that the caller can 148 * control the behavior of the client through the underlying event framework. 149 * 'localaddr4' and 'localaddr6' specify the local addresses to use for 150 * each address family; if both are set to NULL, then wildcard addresses 151 * will be used for both families. If only one is NULL, then the other 152 * address will be used as the local address, and the NULL protocol family 153 * will not be used. 154 * 155 * Requires: 156 * 157 *\li 'mctx' is a valid memory context. 158 * 159 *\li 'actx' is a valid application context. 160 * 161 *\li 'taskmgr' is a valid task manager. 162 * 163 *\li 'socketmgr' is a valid socket manager. 164 * 165 *\li 'timermgr' is a valid timer manager. 166 * 167 *\li clientp != NULL && *clientp == NULL. 168 * 169 * Returns: 170 * 171 *\li #ISC_R_SUCCESS On success. 172 * 173 *\li Anything else Failure. 174 */ 175 176 void 177 dns_client_destroy(dns_client_t **clientp); 178 /*%< 179 * Destroy 'client'. 180 * 181 * Requires: 182 * 183 *\li '*clientp' is a valid client. 184 * 185 * Ensures: 186 * 187 *\li *clientp == NULL. 188 */ 189 190 isc_result_t 191 dns_client_setservers(dns_client_t *client, dns_rdataclass_t rdclass, 192 const dns_name_t *name_space, isc_sockaddrlist_t *addrs); 193 /*%< 194 * Specify a list of addresses of recursive name servers that the client will 195 * use for name resolution. A view for the 'rdclass' class must be created 196 * beforehand. If 'name_space' is non NULL, the specified server will be used 197 * if and only if the query name is a subdomain of 'name_space'. When servers 198 * for multiple 'name_space's are provided, and a query name is covered by 199 * more than one 'name_space', the servers for the best (longest) matching 200 * name_space will be used. If 'name_space' is NULL, it works as if 201 * dns_rootname (.) were specified. 202 * 203 * Requires: 204 * 205 *\li 'client' is a valid client. 206 * 207 *\li 'name_space' is NULL or a valid name. 208 * 209 *\li 'addrs' != NULL. 210 * 211 * Returns: 212 * 213 *\li #ISC_R_SUCCESS On success. 214 * 215 *\li Anything else Failure. 216 */ 217 218 isc_result_t 219 dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, 220 const dns_name_t *name_space); 221 /*%< 222 * Remove configured recursive name servers for the 'rdclass' and 'name_space' 223 * from the client. See the description of dns_client_setservers() for 224 * the requirements about 'rdclass' and 'name_space'. 225 * 226 * Requires: 227 * 228 *\li 'client' is a valid client. 229 * 230 *\li 'name_space' is NULL or a valid name. 231 * 232 * Returns: 233 * 234 *\li #ISC_R_SUCCESS On success. 235 * 236 *\li Anything else Failure. 237 */ 238 239 isc_result_t 240 dns_client_resolve(dns_client_t *client, const dns_name_t *name, 241 dns_rdataclass_t rdclass, dns_rdatatype_t type, 242 unsigned int options, dns_namelist_t *namelist); 243 244 isc_result_t 245 dns_client_startresolve(dns_client_t *client, const dns_name_t *name, 246 dns_rdataclass_t rdclass, dns_rdatatype_t type, 247 unsigned int options, isc_task_t *task, 248 isc_taskaction_t action, void *arg, 249 dns_clientrestrans_t **transp); 250 /*%< 251 * Perform name resolution for 'name', 'rdclass', and 'type'. 252 * 253 * If any trusted keys are configured and the query name is considered to 254 * belong to a secure zone, these functions also validate the responses 255 * using DNSSEC by default. If the DNS_CLIENTRESOPT_NOVALIDATE flag is set 256 * in 'options', DNSSEC validation is disabled regardless of the configured 257 * trusted keys or the query name. With DNS_CLIENTRESOPT_NODNSSEC 258 * DNSSEC data is not returned with response. DNS_CLIENTRESOPT_NOCDFLAG 259 * disables the CD flag on queries, DNS_CLIENTRESOPT_TCP switches to 260 * the TCP (vs. UDP) transport. 261 * 262 * dns_client_resolve() provides a synchronous service. This function starts 263 * name resolution internally and blocks until it completes. On success, 264 * 'namelist' will contain a list of answer names, each of which has 265 * corresponding RRsets. The caller must provide a valid empty list, and 266 * is responsible for freeing the list content via dns_client_freeresanswer(). 267 * If the name resolution fails due to an error in DNSSEC validation, 268 * dns_client_resolve() returns the result code indicating the validation 269 * error. Otherwise, it returns the result code of the entire resolution 270 * process, either success or failure. 271 * 272 * It is expected that the client object passed to dns_client_resolve() was 273 * created via dns_client_create() and has external managers and contexts. 274 * 275 * dns_client_startresolve() is an asynchronous version of dns_client_resolve() 276 * and does not block. When name resolution is completed, 'action' will be 277 * called with the argument of a 'dns_clientresevent_t' object, which contains 278 * the resulting list of answer names (on success). On return, '*transp' is 279 * set to an opaque transaction ID so that the caller can cancel this 280 * resolution process. 281 * 282 * Requires: 283 * 284 *\li 'client' is a valid client. 285 * 286 *\li 'addrs' != NULL. 287 * 288 *\li 'name' is a valid name. 289 * 290 *\li 'namelist' != NULL and is not empty. 291 * 292 *\li 'task' is a valid task. 293 * 294 *\li 'transp' != NULL && *transp == NULL; 295 * 296 * Returns: 297 * 298 *\li #ISC_R_SUCCESS On success. 299 * 300 *\li Anything else Failure. 301 */ 302 303 void 304 dns_client_cancelresolve(dns_clientrestrans_t *trans); 305 /*%< 306 * Cancel an ongoing resolution procedure started via 307 * dns_client_startresolve(). 308 * 309 * Notes: 310 * 311 *\li If the resolution procedure has not completed, post its CLIENTRESDONE 312 * event with a result code of #ISC_R_CANCELED. 313 * 314 * Requires: 315 * 316 *\li 'trans' is a valid transaction ID. 317 */ 318 319 void 320 dns_client_destroyrestrans(dns_clientrestrans_t **transp); 321 /*%< 322 * Destroy name resolution transaction state identified by '*transp'. 323 * 324 * Requires: 325 * 326 *\li '*transp' is a valid transaction ID. 327 * 328 *\li The caller has received the CLIENTRESDONE event (either because the 329 * resolution completed or because dns_client_cancelresolve() was called). 330 * 331 * Ensures: 332 * 333 *\li *transp == NULL. 334 */ 335 336 void 337 dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist); 338 /*%< 339 * Free resources allocated for the content of 'namelist'. 340 * 341 * Requires: 342 * 343 *\li 'client' is a valid client. 344 * 345 *\li 'namelist' != NULL. 346 */ 347 348 isc_result_t 349 dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, 350 dns_rdatatype_t rdtype, const dns_name_t *keyname, 351 isc_buffer_t *keydatabuf); 352 /*%< 353 * Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass' 354 * class must be created beforehand. 'rdtype' is the type of the RR data 355 * for the key, either DNSKEY or DS. 'keyname' is the DNS name of the key, 356 * and 'keydatabuf' stores the RR data. 357 * 358 * Requires: 359 * 360 *\li 'client' is a valid client. 361 * 362 *\li 'keyname' is a valid name. 363 * 364 *\li 'keydatabuf' is a valid buffer. 365 * 366 * Returns: 367 * 368 *\li #ISC_R_SUCCESS On success. 369 * 370 *\li Anything else Failure. 371 */ 372 373 isc_result_t 374 dns_client_request(dns_client_t *client, dns_message_t *qmessage, 375 dns_message_t *rmessage, const isc_sockaddr_t *server, 376 unsigned int options, unsigned int parseoptions, 377 dns_tsec_t *tsec, unsigned int timeout, 378 unsigned int udptimeout, unsigned int udpretries); 379 380 isc_result_t 381 dns_client_startrequest(dns_client_t *client, dns_message_t *qmessage, 382 dns_message_t *rmessage, const isc_sockaddr_t *server, 383 unsigned int options, unsigned int parseoptions, 384 dns_tsec_t *tsec, unsigned int timeout, 385 unsigned int udptimeout, unsigned int udpretries, 386 isc_task_t *task, isc_taskaction_t action, void *arg, 387 dns_clientreqtrans_t **transp); 388 389 /*%< 390 * Send a DNS request containing a query message 'query' to 'server'. 391 * 392 * 'parseoptions' will be used when the response packet is parsed, and will be 393 * passed to dns_message_parse() via dns_request_getresponse(). See 394 * dns_message_parse() for more details. 395 * 396 * 'tsec' is a transaction security object containing, e.g. a TSIG key for 397 * authenticating the request/response transaction. This is optional and can 398 * be NULL, in which case this library performs the transaction without any 399 * transaction authentication. 400 * 401 * 'timeout', 'udptimeout', and 'udpretries' are passed to 402 * dns_request_createvia3(). See dns_request_createvia3() for more details. 403 * 404 * dns_client_request() provides a synchronous service. This function sends 405 * the request and blocks until a response is received. On success, 406 * 'rmessage' will contain the response message. The caller must provide a 407 * valid initialized message. 408 * 409 * It is expected that the client object passed to dns_client_request() was 410 * created via dns_client_create() and has external managers and contexts. 411 * 412 * dns_client_startrequest() is an asynchronous version of dns_client_request() 413 * and does not block. When the transaction is completed, 'action' will be 414 * called with the argument of a 'dns_clientreqevent_t' object, which contains 415 * the response message (on success). On return, '*transp' is set to an opaque 416 * transaction ID so that the caller can cancel this request. 417 * 418 * DNS_CLIENTREQOPT_TCP switches to the TCP (vs. UDP) transport. 419 * 420 * Requires: 421 * 422 *\li 'client' is a valid client. 423 * 424 *\li 'qmessage' and 'rmessage' are valid initialized message. 425 * 426 *\li 'server' is a valid socket address structure. 427 * 428 *\li 'task' is a valid task. 429 * 430 *\li 'transp' != NULL && *transp == NULL; 431 * 432 * Returns: 433 * 434 *\li #ISC_R_SUCCESS On success. 435 * 436 *\li Anything else Failure. 437 * 438 *\li Any result that dns_message_parse() can return. 439 */ 440 441 void 442 dns_client_cancelrequest(dns_clientreqtrans_t *transp); 443 /*%< 444 * Cancel an ongoing DNS request procedure started via 445 * dns_client_startrequest(). 446 * 447 * Notes: 448 * 449 *\li If the request procedure has not completed, post its CLIENTREQDONE 450 * event with a result code of #ISC_R_CANCELED. 451 * 452 * Requires: 453 * 454 *\li 'trans' is a valid transaction ID. 455 */ 456 457 void 458 dns_client_destroyreqtrans(dns_clientreqtrans_t **transp); 459 /*% 460 * Destroy DNS request transaction state identified by '*transp'. 461 * 462 * Requires: 463 * 464 *\li '*transp' is a valid transaction ID. 465 * 466 *\li The caller has received the CLIENTREQDONE event (either because the 467 * request completed or because dns_client_cancelrequest() was called). 468 * 469 * Ensures: 470 * 471 *\li *transp == NULL. 472 */ 473 474 ISC_LANG_ENDDECLS 475 476 #endif /* DNS_CLIENT_H */ 477