1 /* 2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * See the COPYRIGHT file distributed with this work for additional 9 * information regarding copyright ownership. 10 */ 11 12 #ifndef DNS_RDATASET_H 13 #define DNS_RDATASET_H 1 14 15 /***** 16 ***** Module Info 17 *****/ 18 19 /*! \file dns/rdataset.h 20 * \brief 21 * A DNS rdataset is a handle that can be associated with a collection of 22 * rdata all having a common owner name, class, and type. 23 * 24 * The dns_rdataset_t type is like a "virtual class". To actually use 25 * rdatasets, an implementation of the method suite (e.g. "slabbed rdata") is 26 * required. 27 * 28 * XXX <more> XXX 29 * 30 * MP: 31 *\li Clients of this module must impose any required synchronization. 32 * 33 * Reliability: 34 *\li No anticipated impact. 35 * 36 * Resources: 37 *\li TBS 38 * 39 * Security: 40 *\li No anticipated impact. 41 * 42 * Standards: 43 *\li None. 44 */ 45 46 #include <inttypes.h> 47 #include <stdbool.h> 48 49 #include <isc/lang.h> 50 #include <isc/magic.h> 51 #include <isc/stdtime.h> 52 53 #include <dns/rdatastruct.h> 54 #include <dns/types.h> 55 56 ISC_LANG_BEGINDECLS 57 58 typedef enum { 59 dns_rdatasetadditional_fromauth, 60 dns_rdatasetadditional_fromcache, 61 dns_rdatasetadditional_fromglue 62 } dns_rdatasetadditional_t; 63 64 typedef struct dns_rdatasetmethods { 65 void (*disassociate)(dns_rdataset_t *rdataset); 66 isc_result_t (*first)(dns_rdataset_t *rdataset); 67 isc_result_t (*next)(dns_rdataset_t *rdataset); 68 void (*current)(dns_rdataset_t *rdataset, dns_rdata_t *rdata); 69 void (*clone)(dns_rdataset_t *source, dns_rdataset_t *target); 70 unsigned int (*count)(dns_rdataset_t *rdataset); 71 isc_result_t (*addnoqname)(dns_rdataset_t * rdataset, 72 const dns_name_t *name); 73 isc_result_t (*getnoqname)(dns_rdataset_t *rdataset, dns_name_t *name, 74 dns_rdataset_t *neg, dns_rdataset_t *negsig); 75 isc_result_t (*addclosest)(dns_rdataset_t * rdataset, 76 const dns_name_t *name); 77 isc_result_t (*getclosest)(dns_rdataset_t *rdataset, dns_name_t *name, 78 dns_rdataset_t *neg, dns_rdataset_t *negsig); 79 void (*settrust)(dns_rdataset_t *rdataset, dns_trust_t trust); 80 void (*expire)(dns_rdataset_t *rdataset); 81 void (*clearprefetch)(dns_rdataset_t *rdataset); 82 void (*setownercase)(dns_rdataset_t *rdataset, const dns_name_t *name); 83 void (*getownercase)(const dns_rdataset_t *rdataset, dns_name_t *name); 84 isc_result_t (*addglue)(dns_rdataset_t * rdataset, 85 dns_dbversion_t *version, dns_message_t *msg); 86 } dns_rdatasetmethods_t; 87 88 #define DNS_RDATASET_MAGIC ISC_MAGIC('D', 'N', 'S', 'R') 89 #define DNS_RDATASET_VALID(set) ISC_MAGIC_VALID(set, DNS_RDATASET_MAGIC) 90 91 /*% 92 * Direct use of this structure by clients is strongly discouraged, except 93 * for the 'link' field which may be used however the client wishes. The 94 * 'private', 'current', and 'index' fields MUST NOT be changed by clients. 95 * rdataset implementations may change any of the fields. 96 */ 97 struct dns_rdataset { 98 unsigned int magic; /* XXX ? */ 99 dns_rdatasetmethods_t *methods; 100 ISC_LINK(dns_rdataset_t) link; 101 102 /* 103 * XXX do we need these, or should they be retrieved by methods? 104 * Leaning towards the latter, since they are not frequently required 105 * once you have the rdataset. 106 */ 107 dns_rdataclass_t rdclass; 108 dns_rdatatype_t type; 109 dns_ttl_t ttl; 110 /* 111 * Stale ttl is used to see how long this RRset can still be used 112 * to serve to clients, after the TTL has expired. 113 */ 114 dns_ttl_t stale_ttl; 115 dns_trust_t trust; 116 dns_rdatatype_t covers; 117 118 /* 119 * attributes 120 */ 121 unsigned int attributes; 122 123 /*% 124 * the counter provides the starting point in the "cyclic" order. 125 * The value UINT32_MAX has a special meaning of "picking up a 126 * random value." in order to take care of databases that do not 127 * increment the counter. 128 */ 129 uint32_t count; 130 131 /* 132 * This RRSIG RRset should be re-generated around this time. 133 * Only valid if DNS_RDATASETATTR_RESIGN is set in attributes. 134 */ 135 isc_stdtime_t resign; 136 137 /*@{*/ 138 /*% 139 * These are for use by the rdataset implementation, and MUST NOT 140 * be changed by clients. 141 */ 142 void * private1; 143 void * private2; 144 void * private3; 145 unsigned int privateuint4; 146 void * private5; 147 const void * private6; 148 const void * private7; 149 /*@}*/ 150 }; 151 152 /*! 153 * \def DNS_RDATASETATTR_RENDERED 154 * Used by message.c to indicate that the rdataset was rendered. 155 * 156 * \def DNS_RDATASETATTR_TTLADJUSTED 157 * Used by message.c to indicate that the rdataset's rdata had differing 158 * TTL values, and the rdataset->ttl holds the smallest. 159 * 160 * \def DNS_RDATASETATTR_LOADORDER 161 * Output the RRset in load order. 162 */ 163 164 #define DNS_RDATASETATTR_NONE 0x00000000 /*%< No ordering. */ 165 #define DNS_RDATASETATTR_QUESTION 0x00000001 166 #define DNS_RDATASETATTR_RENDERED 0x00000002 /*%< Used by message.c */ 167 #define DNS_RDATASETATTR_ANSWERED 0x00000004 /*%< Used by server. */ 168 #define DNS_RDATASETATTR_CACHE 0x00000008 /*%< Used by resolver. */ 169 #define DNS_RDATASETATTR_ANSWER 0x00000010 /*%< Used by resolver. */ 170 #define DNS_RDATASETATTR_ANSWERSIG 0x00000020 /*%< Used by resolver. */ 171 #define DNS_RDATASETATTR_EXTERNAL 0x00000040 /*%< Used by resolver. */ 172 #define DNS_RDATASETATTR_NCACHE 0x00000080 /*%< Used by resolver. */ 173 #define DNS_RDATASETATTR_CHAINING 0x00000100 /*%< Used by resolver. */ 174 #define DNS_RDATASETATTR_TTLADJUSTED 0x00000200 /*%< Used by message.c */ 175 #define DNS_RDATASETATTR_FIXEDORDER 0x00000400 /*%< Fixed ordering. */ 176 #define DNS_RDATASETATTR_RANDOMIZE 0x00000800 /*%< Random ordering. */ 177 #define DNS_RDATASETATTR_CHASE 0x00001000 /*%< Used by resolver. */ 178 #define DNS_RDATASETATTR_NXDOMAIN 0x00002000 179 #define DNS_RDATASETATTR_NOQNAME 0x00004000 180 #define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */ 181 #define DNS_RDATASETATTR_REQUIRED 0x00010000 182 #define DNS_RDATASETATTR_REQUIREDGLUE DNS_RDATASETATTR_REQUIRED 183 #define DNS_RDATASETATTR_LOADORDER 0x00020000 184 #define DNS_RDATASETATTR_RESIGN 0x00040000 185 #define DNS_RDATASETATTR_CLOSEST 0x00080000 186 #define DNS_RDATASETATTR_OPTOUT 0x00100000 /*%< OPTOUT proof */ 187 #define DNS_RDATASETATTR_NEGATIVE 0x00200000 188 #define DNS_RDATASETATTR_PREFETCH 0x00400000 189 #define DNS_RDATASETATTR_CYCLIC 0x00800000 /*%< Cyclic ordering. */ 190 #define DNS_RDATASETATTR_STALE 0x01000000 191 192 /*% 193 * _OMITDNSSEC: 194 * Omit DNSSEC records when rendering ncache records. 195 */ 196 #define DNS_RDATASETTOWIRE_OMITDNSSEC 0x0001 197 198 void 199 dns_rdataset_init(dns_rdataset_t *rdataset); 200 /*%< 201 * Make 'rdataset' a valid, disassociated rdataset. 202 * 203 * Requires: 204 *\li 'rdataset' is not NULL. 205 * 206 * Ensures: 207 *\li 'rdataset' is a valid, disassociated rdataset. 208 */ 209 210 void 211 dns_rdataset_invalidate(dns_rdataset_t *rdataset); 212 /*%< 213 * Invalidate 'rdataset'. 214 * 215 * Requires: 216 *\li 'rdataset' is a valid, disassociated rdataset. 217 * 218 * Ensures: 219 *\li If assertion checking is enabled, future attempts to use 'rdataset' 220 * without initializing it will cause an assertion failure. 221 */ 222 223 void 224 dns_rdataset_disassociate(dns_rdataset_t *rdataset); 225 /*%< 226 * Disassociate 'rdataset' from its rdata, allowing it to be reused. 227 * 228 * Notes: 229 *\li The client must ensure it has no references to rdata in the rdataset 230 * before disassociating. 231 * 232 * Requires: 233 *\li 'rdataset' is a valid, associated rdataset. 234 * 235 * Ensures: 236 *\li 'rdataset' is a valid, disassociated rdataset. 237 */ 238 239 bool 240 dns_rdataset_isassociated(dns_rdataset_t *rdataset); 241 /*%< 242 * Is 'rdataset' associated? 243 * 244 * Requires: 245 *\li 'rdataset' is a valid rdataset. 246 * 247 * Returns: 248 *\li #true 'rdataset' is associated. 249 *\li #false 'rdataset' is not associated. 250 */ 251 252 void 253 dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass, 254 dns_rdatatype_t type); 255 /*%< 256 * Make 'rdataset' a valid, associated, question rdataset, with a 257 * question class of 'rdclass' and type 'type'. 258 * 259 * Notes: 260 *\li Question rdatasets have a class and type, but no rdata. 261 * 262 * Requires: 263 *\li 'rdataset' is a valid, disassociated rdataset. 264 * 265 * Ensures: 266 *\li 'rdataset' is a valid, associated, question rdataset. 267 */ 268 269 void 270 dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target); 271 /*%< 272 * Make 'target' refer to the same rdataset as 'source'. 273 * 274 * Requires: 275 *\li 'source' is a valid, associated rdataset. 276 * 277 *\li 'target' is a valid, dissociated rdataset. 278 * 279 * Ensures: 280 *\li 'target' references the same rdataset as 'source'. 281 */ 282 283 unsigned int 284 dns_rdataset_count(dns_rdataset_t *rdataset); 285 /*%< 286 * Return the number of records in 'rdataset'. 287 * 288 * Requires: 289 *\li 'rdataset' is a valid, associated rdataset. 290 * 291 * Returns: 292 *\li The number of records in 'rdataset'. 293 */ 294 295 isc_result_t 296 dns_rdataset_first(dns_rdataset_t *rdataset); 297 /*%< 298 * Move the rdata cursor to the first rdata in the rdataset (if any). 299 * 300 * Requires: 301 *\li 'rdataset' is a valid, associated rdataset. 302 * 303 * Returns: 304 *\li #ISC_R_SUCCESS 305 *\li #ISC_R_NOMORE There are no rdata in the set. 306 */ 307 308 isc_result_t 309 dns_rdataset_next(dns_rdataset_t *rdataset); 310 /*%< 311 * Move the rdata cursor to the next rdata in the rdataset (if any). 312 * 313 * Requires: 314 *\li 'rdataset' is a valid, associated rdataset. 315 * 316 * Returns: 317 *\li #ISC_R_SUCCESS 318 *\li #ISC_R_NOMORE There are no more rdata in the set. 319 */ 320 321 void 322 dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata); 323 /*%< 324 * Make 'rdata' refer to the current rdata. 325 * 326 * Notes: 327 * 328 *\li The data returned in 'rdata' is valid for the life of the 329 * rdataset; in particular, subsequent changes in the cursor position 330 * do not invalidate 'rdata'. 331 * 332 * Requires: 333 *\li 'rdataset' is a valid, associated rdataset. 334 * 335 *\li The rdata cursor of 'rdataset' is at a valid location (i.e. the 336 * result of last call to a cursor movement command was ISC_R_SUCCESS). 337 * 338 * Ensures: 339 *\li 'rdata' refers to the rdata at the rdata cursor location of 340 *\li 'rdataset'. 341 */ 342 343 isc_result_t 344 dns_rdataset_totext(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 345 bool omit_final_dot, bool question, isc_buffer_t *target); 346 /*%< 347 * Convert 'rdataset' to text format, storing the result in 'target'. 348 * 349 * Notes: 350 *\li The rdata cursor position will be changed. 351 * 352 *\li The 'question' flag should normally be #false. If it is 353 * #true, the TTL and rdata fields are not printed. This is 354 * for use when printing an rdata representing a question section. 355 * 356 *\li This interface is deprecated; use dns_master_rdatasettottext() 357 * and/or dns_master_questiontotext() instead. 358 * 359 * Requires: 360 *\li 'rdataset' is a valid rdataset. 361 * 362 *\li 'rdataset' is not empty. 363 */ 364 365 isc_result_t 366 dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name, 367 dns_compress_t *cctx, isc_buffer_t *target, 368 unsigned int options, unsigned int *countp); 369 /*%< 370 * Convert 'rdataset' to wire format, compressing names as specified 371 * in 'cctx', and storing the result in 'target'. 372 * 373 * Notes: 374 *\li The rdata cursor position will be changed. 375 * 376 *\li The number of RRs added to target will be added to *countp. 377 * 378 * Requires: 379 *\li 'rdataset' is a valid rdataset. 380 * 381 *\li 'rdataset' is not empty. 382 * 383 *\li 'countp' is a valid pointer. 384 * 385 * Ensures: 386 *\li On a return of ISC_R_SUCCESS, 'target' contains a wire format 387 * for the data contained in 'rdataset'. Any error return leaves 388 * the buffer unchanged. 389 * 390 *\li *countp has been incremented by the number of RRs added to 391 * target. 392 * 393 * Returns: 394 *\li #ISC_R_SUCCESS - all ok 395 *\li #ISC_R_NOSPACE - 'target' doesn't have enough room 396 * 397 *\li Any error returned by dns_rdata_towire(), dns_rdataset_next(), 398 * dns_name_towire(). 399 */ 400 401 isc_result_t 402 dns_rdataset_towiresorted(dns_rdataset_t * rdataset, 403 const dns_name_t *owner_name, dns_compress_t *cctx, 404 isc_buffer_t *target, dns_rdatasetorderfunc_t order, 405 const void *order_arg, unsigned int options, 406 unsigned int *countp); 407 /*%< 408 * Like dns_rdataset_towire(), but sorting the rdatasets according to 409 * the integer value returned by 'order' when called with the rdataset 410 * and 'order_arg' as arguments. 411 * 412 * Requires: 413 *\li All the requirements of dns_rdataset_towire(), and 414 * that order_arg is NULL if and only if order is NULL. 415 */ 416 417 isc_result_t 418 dns_rdataset_towirepartial(dns_rdataset_t * rdataset, 419 const dns_name_t *owner_name, dns_compress_t *cctx, 420 isc_buffer_t *target, dns_rdatasetorderfunc_t order, 421 const void *order_arg, unsigned int options, 422 unsigned int *countp, void **state); 423 /*%< 424 * Like dns_rdataset_towiresorted() except that a partial rdataset 425 * may be written. 426 * 427 * Requires: 428 *\li All the requirements of dns_rdataset_towiresorted(). 429 * If 'state' is non NULL then the current position in the 430 * rdataset will be remembered if the rdataset in not 431 * completely written and should be passed on on subsequent 432 * calls (NOT CURRENTLY IMPLEMENTED). 433 * 434 * Returns: 435 *\li #ISC_R_SUCCESS if all of the records were written. 436 *\li #ISC_R_NOSPACE if unable to fit in all of the records. *countp 437 * will be updated to reflect the number of records 438 * written. 439 */ 440 441 isc_result_t 442 dns_rdataset_additionaldata(dns_rdataset_t * rdataset, 443 dns_additionaldatafunc_t add, void *arg); 444 /*%< 445 * For each rdata in rdataset, call 'add' for each name and type in the 446 * rdata which is subject to additional section processing. 447 * 448 * Requires: 449 * 450 *\li 'rdataset' is a valid, non-question rdataset. 451 * 452 *\li 'add' is a valid dns_additionaldatafunc_t 453 * 454 * Ensures: 455 * 456 *\li If successful, dns_rdata_additionaldata() will have been called for 457 * each rdata in 'rdataset'. 458 * 459 *\li If a call to dns_rdata_additionaldata() is not successful, the 460 * result returned will be the result of dns_rdataset_additionaldata(). 461 * 462 * Returns: 463 * 464 *\li #ISC_R_SUCCESS 465 * 466 *\li Any error that dns_rdata_additionaldata() can return. 467 */ 468 469 isc_result_t 470 dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name, 471 dns_rdataset_t *neg, dns_rdataset_t *negsig); 472 /*%< 473 * Return the noqname proof for this record. 474 * 475 * Requires: 476 *\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set. 477 *\li 'name' to be valid. 478 *\li 'neg' and 'negsig' to be valid and not associated. 479 */ 480 481 isc_result_t 482 dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name); 483 /*%< 484 * Associate a noqname proof with this record. 485 * Sets #DNS_RDATASETATTR_NOQNAME if successful. 486 * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and 487 * the 'nsec'/'nsec3' and 'rrsig(nsec)'/'rrsig(nsec3)' ttl. 488 * 489 * Requires: 490 *\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set. 491 *\li 'name' to be valid and have NSEC or NSEC3 and associated RRSIG 492 * rdatasets. 493 */ 494 495 isc_result_t 496 dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, 497 dns_rdataset_t *nsec, dns_rdataset_t *nsecsig); 498 /*%< 499 * Return the closest encloser for this record. 500 * 501 * Requires: 502 *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set. 503 *\li 'name' to be valid. 504 *\li 'nsec' and 'nsecsig' to be valid and not associated. 505 */ 506 507 isc_result_t 508 dns_rdataset_addclosest(dns_rdataset_t *rdataset, const dns_name_t *name); 509 /*%< 510 * Associate a closest encloset proof with this record. 511 * Sets #DNS_RDATASETATTR_CLOSEST if successful. 512 * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and 513 * the 'nsec' and 'rrsig(nsec)' ttl. 514 * 515 * Requires: 516 *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set. 517 *\li 'name' to be valid and have NSEC3 and RRSIG(NSEC3) rdatasets. 518 */ 519 520 void 521 dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); 522 /*%< 523 * Set the trust of the 'rdataset' to trust in any in the backing database. 524 * The local trust level of 'rdataset' is also set. 525 */ 526 527 void 528 dns_rdataset_expire(dns_rdataset_t *rdataset); 529 /*%< 530 * Mark the rdataset to be expired in the backing database. 531 */ 532 533 void 534 dns_rdataset_clearprefetch(dns_rdataset_t *rdataset); 535 /*%< 536 * Clear the PREFETCH attribute for the given rdataset in the 537 * underlying database. 538 * 539 * In the cache database, this signals that the rdataset is not 540 * eligible to be prefetched when the TTL is close to expiring. 541 * It has no function in other databases. 542 */ 543 544 void 545 dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name); 546 /*%< 547 * Store the casing of 'name', the owner name of 'rdataset', into 548 * a bitfield so that the name can be capitalized the same when when 549 * the rdataset is used later. This sets the CASESET attribute. 550 */ 551 552 void 553 dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); 554 /*%< 555 * If the CASESET attribute is set, retrieve the case bitfield that was 556 * previously stored by dns_rdataset_getownername(), and capitalize 'name' 557 * according to it. If CASESET is not set, do nothing. 558 */ 559 560 isc_result_t 561 dns_rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version, 562 dns_message_t *msg); 563 /*%< 564 * Add glue records for rdataset to the additional section of message in 565 * 'msg'. 'rdataset' must be of type NS. 566 * 567 * In case a successful result is not returned, the caller should try to 568 * add glue directly to the message by iterating for additional data. 569 * 570 * Requires: 571 * \li 'rdataset' is a valid NS rdataset. 572 * \li 'version' is the DB version. 573 * \li 'msg' is the DNS message to which the glue should be added. 574 * 575 * Returns: 576 *\li #ISC_R_SUCCESS 577 *\li #ISC_R_NOTIMPLEMENTED 578 *\li #ISC_R_FAILURE 579 *\li Any error that dns_rdata_additionaldata() can return. 580 */ 581 582 void 583 dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 584 dns_rdata_rrsig_t *rrsig, isc_stdtime_t now, 585 bool acceptexpired); 586 /*%< 587 * Trim the ttl of 'rdataset' and 'sigrdataset' so that they will expire 588 * at or before 'rrsig->expiretime'. If 'acceptexpired' is true and the 589 * signature has expired or will expire in the next 120 seconds, limit 590 * the ttl to be no more than 120 seconds. 591 * 592 * The ttl is further limited by the original ttl as stored in 'rrsig' 593 * and the original ttl values of 'rdataset' and 'sigrdataset'. 594 * 595 * Requires: 596 * \li 'rdataset' is a valid rdataset. 597 * \li 'sigrdataset' is a valid rdataset. 598 * \li 'rrsig' is non NULL. 599 */ 600 601 const char * 602 dns_trust_totext(dns_trust_t trust); 603 /*%< 604 * Display trust in textual form. 605 */ 606 607 ISC_LANG_ENDDECLS 608 609 #endif /* DNS_RDATASET_H */ 610