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