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