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