1238104Sdes/* 2238104Sdes * special zone file structures and functions for better dnssec handling 3238104Sdes * 4238104Sdes * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal' 5238104Sdes * dnssec_zone_rrsets, indexed by name and type 6238104Sdes */ 7238104Sdes 8238104Sdes#ifndef LDNS_DNSSEC_ZONE_H 9238104Sdes#define LDNS_DNSSEC_ZONE_H 10238104Sdes 11238104Sdes#include <ldns/rbtree.h> 12238104Sdes#include <ldns/host2str.h> 13238104Sdes 14238104Sdes#ifdef __cplusplus 15238104Sdesextern "C" { 16238104Sdes#endif 17238104Sdes 18238104Sdes/** 19238104Sdes * Singly linked list of rrs 20238104Sdes */ 21238104Sdestypedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs; 22238104Sdesstruct ldns_struct_dnssec_rrs 23238104Sdes{ 24238104Sdes ldns_rr *rr; 25238104Sdes ldns_dnssec_rrs *next; 26238104Sdes}; 27238104Sdes 28238104Sdes/** 29238104Sdes * Singly linked list of RRsets 30238104Sdes */ 31238104Sdestypedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets; 32238104Sdesstruct ldns_struct_dnssec_rrsets 33238104Sdes{ 34238104Sdes ldns_dnssec_rrs *rrs; 35238104Sdes ldns_rr_type type; 36238104Sdes ldns_dnssec_rrs *signatures; 37238104Sdes ldns_dnssec_rrsets *next; 38238104Sdes}; 39238104Sdes 40238104Sdes/** 41238104Sdes * Structure containing all resource records for a domain name 42238104Sdes * Including the derived NSEC3, if present 43238104Sdes */ 44238104Sdestypedef struct ldns_struct_dnssec_name ldns_dnssec_name; 45238104Sdesstruct ldns_struct_dnssec_name 46238104Sdes{ 47238104Sdes /** 48238104Sdes * pointer to a dname containing the name. 49238104Sdes * Usually points to the owner name of the first RR of the first RRset 50238104Sdes */ 51238104Sdes ldns_rdf *name; 52238104Sdes /** 53238104Sdes * Usually, the name is a pointer to the owner name of the first rr for 54238104Sdes * this name, but sometimes there is no actual data to point to, 55238104Sdes * for instance in 56238104Sdes * names representing empty nonterminals. If so, set alloced to true to 57238104Sdes * indicate that this data must also be freed when the name is freed 58238104Sdes */ 59238104Sdes bool name_alloced; 60238104Sdes /** 61238104Sdes * The rrsets for this name 62238104Sdes */ 63238104Sdes ldns_dnssec_rrsets *rrsets; 64238104Sdes /** 65238104Sdes * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3) 66238104Sdes */ 67238104Sdes ldns_rr *nsec; 68238104Sdes /** 69238104Sdes * signatures for the NSEC record 70238104Sdes */ 71238104Sdes ldns_dnssec_rrs *nsec_signatures; 72238104Sdes /** 73238104Sdes * Unlike what the name is_glue suggests, this field is set to true by 74238104Sdes * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue() 75238104Sdes * when the name, this dnssec_name struct represents, is occluded. 76238104Sdes * Names that contain other occluded rrsets and records with glue on 77238104Sdes * the delegation point will NOT have this bool set to true. 78238104Sdes * This field should NOT be read directly, but only via the 79238104Sdes * ldns_dnssec_name_is_glue() function! 80238104Sdes */ 81238104Sdes bool is_glue; 82238104Sdes /** 83238104Sdes * pointer to store the hashed name (only used when in an NSEC3 zone 84238104Sdes */ 85238104Sdes ldns_rdf *hashed_name; 86238104Sdes}; 87238104Sdes 88238104Sdes/** 89238104Sdes * Structure containing a dnssec zone 90238104Sdes */ 91238104Sdesstruct ldns_struct_dnssec_zone { 92238104Sdes /** points to the name containing the SOA RR */ 93238104Sdes ldns_dnssec_name *soa; 94238104Sdes /** tree of ldns_dnssec_names */ 95238104Sdes ldns_rbtree_t *names; 96238104Sdes}; 97238104Sdestypedef struct ldns_struct_dnssec_zone ldns_dnssec_zone; 98238104Sdes 99238104Sdes/** 100238104Sdes * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs 101238104Sdes * \return the allocated data 102238104Sdes */ 103246827Sdesldns_dnssec_rrs *ldns_dnssec_rrs_new(void); 104238104Sdes 105238104Sdes/** 106238104Sdes * Frees the list of rrs, but *not* the individual ldns_rr records 107238104Sdes * contained in the list 108238104Sdes * 109238104Sdes * \param[in] rrs the data structure to free 110238104Sdes */ 111238104Sdesvoid ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs); 112238104Sdes 113238104Sdes/** 114238104Sdes * Frees the list of rrs, and the individual ldns_rr records 115238104Sdes * contained in the list 116238104Sdes * 117238104Sdes * \param[in] rrs the data structure to free 118238104Sdes */ 119238104Sdesvoid ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs); 120238104Sdes 121238104Sdes/** 122238104Sdes * Adds an RR to the list of RRs. The list will remain ordered 123238104Sdes * 124238104Sdes * \param[in] rrs the list to add to 125238104Sdes * \param[in] rr the RR to add 126238104Sdes * \return LDNS_STATUS_OK on success 127238104Sdes */ 128238104Sdesldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr); 129238104Sdes 130238104Sdes/** 131238104Sdes * Prints the given rrs to the file descriptor 132238104Sdes * 133238104Sdes * \param[in] out the file descriptor to print to 134238104Sdes * \param[in] rrs the list of RRs to print 135238104Sdes */ 136238104Sdesvoid ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs); 137238104Sdes 138238104Sdes/** 139238104Sdes * Prints the given rrs to the file descriptor 140238104Sdes * 141238104Sdes * \param[in] out the file descriptor to print to 142238104Sdes * \param[in] fmt the format of the textual representation 143238104Sdes * \param[in] rrs the list of RRs to print 144238104Sdes */ 145238104Sdesvoid ldns_dnssec_rrs_print_fmt(FILE *out, 146238104Sdes const ldns_output_format *fmt, ldns_dnssec_rrs *rrs); 147238104Sdes 148238104Sdes/** 149238104Sdes * Creates a new list (entry) of RRsets 150238104Sdes * \return the newly allocated structure 151238104Sdes */ 152246827Sdesldns_dnssec_rrsets *ldns_dnssec_rrsets_new(void); 153238104Sdes 154238104Sdes/** 155238104Sdes * Frees the list of rrsets and their rrs, but *not* the ldns_rr 156238104Sdes * records in the sets 157238104Sdes * 158238104Sdes * \param[in] rrsets the data structure to free 159238104Sdes */ 160238104Sdesvoid ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets); 161238104Sdes 162238104Sdes/** 163238104Sdes * Frees the list of rrsets and their rrs, and the ldns_rr 164238104Sdes * records in the sets 165238104Sdes * 166238104Sdes * \param[in] rrsets the data structure to free 167238104Sdes */ 168238104Sdesvoid ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets); 169238104Sdes 170238104Sdes/** 171238104Sdes * Returns the rr type of the rrset (that is head of the given list) 172238104Sdes * 173238104Sdes * \param[in] rrsets the rrset to get the type of 174238104Sdes * \return the rr type 175238104Sdes */ 176238104Sdesldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets); 177238104Sdes 178238104Sdes/** 179238104Sdes * Sets the RR type of the rrset (that is head of the given list) 180238104Sdes * 181238104Sdes * \param[in] rrsets the rrset to set the type of 182238104Sdes * \param[in] type the type to set 183238104Sdes * \return LDNS_STATUS_OK on success 184238104Sdes */ 185238104Sdesldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 186238104Sdes ldns_rr_type type); 187238104Sdes 188238104Sdes/** 189238104Sdes * Add an ldns_rr to the corresponding RRset in the given list of RRsets. 190238104Sdes * If it is not present, add it as a new RRset with 1 record. 191238104Sdes * 192238104Sdes * \param[in] rrsets the list of rrsets to add the RR to 193238104Sdes * \param[in] rr the rr to add to the list of rrsets 194238104Sdes * \return LDNS_STATUS_OK on success 195238104Sdes */ 196238104Sdesldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); 197238104Sdes 198238104Sdes/** 199238104Sdes * Print the given list of rrsets to the fiven file descriptor 200238104Sdes * 201238104Sdes * \param[in] out the file descriptor to print to 202238104Sdes * \param[in] rrsets the list of RRsets to print 203238104Sdes * \param[in] follow if set to false, only print the first RRset 204238104Sdes */ 205238104Sdesvoid ldns_dnssec_rrsets_print(FILE *out, 206238104Sdes ldns_dnssec_rrsets *rrsets, 207238104Sdes bool follow); 208238104Sdes 209238104Sdes/** 210238104Sdes * Print the given list of rrsets to the fiven file descriptor 211238104Sdes * 212238104Sdes * \param[in] out the file descriptor to print to 213238104Sdes * \param[in] fmt the format of the textual representation 214238104Sdes * \param[in] rrsets the list of RRsets to print 215238104Sdes * \param[in] follow if set to false, only print the first RRset 216238104Sdes */ 217238104Sdesvoid ldns_dnssec_rrsets_print_fmt(FILE *out, 218238104Sdes const ldns_output_format *fmt, 219238104Sdes ldns_dnssec_rrsets *rrsets, 220238104Sdes bool follow); 221238104Sdes 222238104Sdes 223238104Sdes/** 224238104Sdes * Create a new data structure for a dnssec name 225238104Sdes * \return the allocated structure 226238104Sdes */ 227246827Sdesldns_dnssec_name *ldns_dnssec_name_new(void); 228238104Sdes 229238104Sdes/** 230238104Sdes * Create a new data structure for a dnssec name for the given RR 231238104Sdes * 232238104Sdes * \param[in] rr the RR to derive properties from, and to add to the name 233238104Sdes */ 234238104Sdesldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr); 235238104Sdes 236238104Sdes/** 237238104Sdes * Frees the name structure and its rrs and rrsets. 238238104Sdes * Individual ldns_rr records therein are not freed 239238104Sdes * 240238104Sdes * \param[in] name the structure to free 241238104Sdes */ 242238104Sdesvoid ldns_dnssec_name_free(ldns_dnssec_name *name); 243238104Sdes 244238104Sdes/** 245238104Sdes * Frees the name structure and its rrs and rrsets. 246238104Sdes * Individual ldns_rr records contained in the name are also freed 247238104Sdes * 248238104Sdes * \param[in] name the structure to free 249238104Sdes */ 250238104Sdesvoid ldns_dnssec_name_deep_free(ldns_dnssec_name *name); 251238104Sdes 252238104Sdes/** 253238104Sdes * Returns the domain name of the given dnssec_name structure 254238104Sdes * 255238104Sdes * \param[in] name the dnssec name to get the domain name from 256238104Sdes * \return the domain name 257238104Sdes */ 258238104Sdesldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name); 259238104Sdes 260238104Sdes 261238104Sdes/** 262238104Sdes * Sets the domain name of the given dnssec_name structure 263238104Sdes * 264238104Sdes * \param[in] name the dnssec name to set the domain name of 265238104Sdes * \param[in] dname the domain name to set it to. This data is *not* copied. 266238104Sdes */ 267238104Sdesvoid ldns_dnssec_name_set_name(ldns_dnssec_name *name, 268238104Sdes ldns_rdf *dname); 269238104Sdes/** 270238104Sdes * Returns if dnssec_name structure is marked as glue. 271238104Sdes * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before 272238104Sdes * using this function. 273238104Sdes * Only names that have only glue rrsets will be marked. 274238104Sdes * Names that have other occluded rrsets and names containing glue on the 275238104Sdes * delegation point will NOT be marked! 276238104Sdes * 277238104Sdes * \param[in] name the dnssec name to get the domain name from 278238104Sdes * \return true if the structure is marked as glue, false otherwise. 279238104Sdes */ 280238104Sdesbool ldns_dnssec_name_is_glue(ldns_dnssec_name *name); 281238104Sdes 282238104Sdes/** 283238104Sdes * Sets the NSEC(3) RR of the given dnssec_name structure 284238104Sdes * 285238104Sdes * \param[in] name the dnssec name to set the domain name of 286238104Sdes * \param[in] nsec the nsec rr to set it to. This data is *not* copied. 287238104Sdes */ 288238104Sdesvoid ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); 289238104Sdes 290238104Sdes/** 291238104Sdes * Compares the domain names of the two arguments in their 292238104Sdes * canonical ordening. 293238104Sdes * 294238104Sdes * \param[in] a The first dnssec_name to compare 295238104Sdes * \param[in] b The second dnssec_name to compare 296238104Sdes * \return -1 if the domain name of a comes before that of b in canonical 297238104Sdes * ordening, 1 if it is the other way around, and 0 if they are 298238104Sdes * equal 299238104Sdes */ 300238104Sdesint ldns_dnssec_name_cmp(const void *a, const void *b); 301238104Sdes 302238104Sdes/** 303238104Sdes * Inserts the given rr at the right place in the current dnssec_name 304238104Sdes * No checking is done whether the name matches 305238104Sdes * 306238104Sdes * \param[in] name The ldns_dnssec_name to add the RR to 307238104Sdes * \param[in] rr The RR to add 308238104Sdes * \return LDNS_STATUS_OK on success, error code otherwise 309238104Sdes */ 310238104Sdesldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, 311238104Sdes ldns_rr *rr); 312238104Sdes 313238104Sdes/** 314238104Sdes * Find the RRset with the given type in within this name structure 315238104Sdes * 316238104Sdes * \param[in] name the name to find the RRset in 317238104Sdes * \param[in] type the type of the RRset to find 318238104Sdes * \return the RRset, or NULL if not present 319238104Sdes */ 320238104Sdesldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, 321238104Sdes ldns_rr_type type); 322238104Sdes 323238104Sdes/** 324238104Sdes * Find the RRset with the given name and type in the zone 325238104Sdes * 326238104Sdes * \param[in] zone the zone structure to find the RRset in 327238104Sdes * \param[in] dname the domain name of the RRset to find 328238104Sdes * \param[in] type the type of the RRset to find 329238104Sdes * \return the RRset, or NULL if not present 330238104Sdes */ 331238104Sdesldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, 332238104Sdes ldns_rdf *dname, 333238104Sdes ldns_rr_type type); 334238104Sdes 335238104Sdes/** 336238104Sdes * Prints the RRs in the dnssec name structure to the given 337238104Sdes * file descriptor 338238104Sdes * 339238104Sdes * \param[in] out the file descriptor to print to 340238104Sdes * \param[in] name the name structure to print the contents of 341238104Sdes */ 342238104Sdesvoid ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name); 343238104Sdes 344238104Sdes/** 345238104Sdes * Prints the RRs in the dnssec name structure to the given 346238104Sdes * file descriptor 347238104Sdes * 348238104Sdes * \param[in] out the file descriptor to print to 349238104Sdes * \param[in] fmt the format of the textual representation 350238104Sdes * \param[in] name the name structure to print the contents of 351238104Sdes */ 352238104Sdesvoid ldns_dnssec_name_print_fmt(FILE *out, 353238104Sdes const ldns_output_format *fmt, ldns_dnssec_name *name); 354238104Sdes 355238104Sdes/** 356238104Sdes * Creates a new dnssec_zone structure 357238104Sdes * \return the allocated structure 358238104Sdes */ 359246827Sdesldns_dnssec_zone *ldns_dnssec_zone_new(void); 360238104Sdes 361238104Sdes/** 362238104Sdes * Create a new dnssec zone from a file. 363238104Sdes * \param[out] z the new zone 364238104Sdes * \param[in] *fp the filepointer to use 365238104Sdes * \param[in] *origin the zones' origin 366238104Sdes * \param[in] c default class to use (IN) 367238104Sdes * \param[in] ttl default ttl to use 368238104Sdes * 369238104Sdes * \return ldns_status mesg with an error or LDNS_STATUS_OK 370238104Sdes */ 371238104Sdesldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, 372238104Sdes ldns_rdf* origin, uint32_t ttl, ldns_rr_class c); 373238104Sdes 374238104Sdes/** 375238104Sdes * Create a new dnssec zone from a file, keep track of the line numbering 376238104Sdes * \param[out] z the new zone 377238104Sdes * \param[in] *fp the filepointer to use 378238104Sdes * \param[in] *origin the zones' origin 379238104Sdes * \param[in] ttl default ttl to use 380238104Sdes * \param[in] c default class to use (IN) 381238104Sdes * \param[out] line_nr used for error msg, to get to the line number 382238104Sdes * 383238104Sdes * \return ldns_status mesg with an error or LDNS_STATUS_OK 384238104Sdes */ 385238104Sdesldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, 386238104Sdes ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr); 387238104Sdes 388238104Sdes/** 389238104Sdes * Frees the given zone structure, and its rbtree of dnssec_names 390238104Sdes * Individual ldns_rr RRs within those names are *not* freed 391238104Sdes * \param[in] *zone the zone to free 392238104Sdes */ 393238104Sdesvoid ldns_dnssec_zone_free(ldns_dnssec_zone *zone); 394238104Sdes 395238104Sdes/** 396238104Sdes * Frees the given zone structure, and its rbtree of dnssec_names 397238104Sdes * Individual ldns_rr RRs within those names are also freed 398238104Sdes * \param[in] *zone the zone to free 399238104Sdes */ 400238104Sdesvoid ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone); 401238104Sdes 402238104Sdes/** 403238104Sdes * Adds the given RR to the zone. 404238104Sdes * It find whether there is a dnssec_name with that name present. 405238104Sdes * If so, add it to that, if not create a new one. 406238104Sdes * Special handling of NSEC and RRSIG provided 407238104Sdes * 408238104Sdes * \param[in] zone the zone to add the RR to 409238104Sdes * \param[in] rr The RR to add 410238104Sdes * \return LDNS_STATUS_OK on success, an error code otherwise 411238104Sdes */ 412238104Sdesldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, 413238104Sdes ldns_rr *rr); 414238104Sdes 415238104Sdes/** 416238104Sdes * Prints the rbtree of ldns_dnssec_name structures to the file descriptor 417238104Sdes * 418238104Sdes * \param[in] out the file descriptor to print the names to 419238104Sdes * \param[in] tree the tree of ldns_dnssec_name structures to print 420238104Sdes * \param[in] print_soa if true, print SOA records, if false, skip them 421238104Sdes */ 422238104Sdesvoid ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa); 423238104Sdes 424238104Sdes/** 425238104Sdes * Prints the rbtree of ldns_dnssec_name structures to the file descriptor 426238104Sdes * 427238104Sdes * \param[in] out the file descriptor to print the names to 428238104Sdes * \param[in] fmt the format of the textual representation 429238104Sdes * \param[in] tree the tree of ldns_dnssec_name structures to print 430238104Sdes * \param[in] print_soa if true, print SOA records, if false, skip them 431238104Sdes */ 432238104Sdesvoid ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 433238104Sdes ldns_rbtree_t *tree, bool print_soa); 434238104Sdes 435238104Sdes/** 436238104Sdes * Prints the complete zone to the given file descriptor 437238104Sdes * 438238104Sdes * \param[in] out the file descriptor to print to 439238104Sdes * \param[in] zone the dnssec_zone to print 440238104Sdes */ 441238104Sdesvoid ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); 442238104Sdes 443238104Sdes/** 444238104Sdes * Prints the complete zone to the given file descriptor 445238104Sdes * 446238104Sdes * \param[in] out the file descriptor to print to 447238104Sdes * \param[in] fmt the format of the textual representation 448238104Sdes * \param[in] zone the dnssec_zone to print 449238104Sdes */ 450238104Sdesvoid ldns_dnssec_zone_print_fmt(FILE *out, 451238104Sdes const ldns_output_format *fmt, ldns_dnssec_zone *zone); 452238104Sdes 453238104Sdes/** 454238104Sdes * Adds explicit dnssec_name structures for the empty nonterminals 455238104Sdes * in this zone. (this is needed for NSEC3 generation) 456238104Sdes * 457238104Sdes * \param[in] zone the zone to check for empty nonterminals 458238104Sdes * return LDNS_STATUS_OK on success. 459238104Sdes */ 460238104Sdesldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); 461238104Sdes 462238104Sdes/** 463238104Sdes * If a NSEC3PARAM is available in the apex, walks the zone and returns true 464238104Sdes * on the first optout nsec3. 465238104Sdes * 466238104Sdes * \param[in] zone the zone to check for nsec3 optout records 467238104Sdes * return true when the zone has at least one nsec3 optout record. 468238104Sdes */ 469238104Sdesbool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone); 470238104Sdes 471238104Sdes#ifdef __cplusplus 472238104Sdes} 473238104Sdes#endif 474238104Sdes 475238104Sdes#endif 476