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 53typedef 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 62ISC_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 */ 118typedef 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 */ 128typedef 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 */ 142typedef 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 */ 157typedef 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 163isc_result_t 164dns_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 211void 212dns_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 225isc_result_t 226dns_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 253isc_result_t 254dns_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 274isc_result_t 275dns_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 279isc_result_t 280dns_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 341void 342dns_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 357void 358dns_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 374void 375dns_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 386isc_result_t 387dns_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 411isc_result_t 412dns_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 418isc_result_t 419dns_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 482void 483dns_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 498void 499dns_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 515isc_result_t 516dns_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 521isc_result_t 522dns_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 603void 604dns_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 619void 620dns_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 636isc_result_t 637dns_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 646void 647dns_client_freeupdate(dns_name_t **namep); 648/*%< 649 * TBD 650 */ 651 652isc_mem_t * 653dns_client_mctx(dns_client_t *client); 654 655ISC_LANG_ENDDECLS 656 657#endif /* DNS_CLIENT_H */ 658