1 /* 2 * special zone file structures and functions for better dnssec handling 3 * 4 * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal' 5 * dnssec_zone_rrsets, indexed by name and type 6 */ 7 8 #ifndef LDNS_DNSSEC_ZONE_H 9 #define LDNS_DNSSEC_ZONE_H 10 11 #include <ldns/ldns.h> 12 #include <ldns/rbtree.h> 13 #include <ldns/host2str.h> 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /** 20 * Singly linked list of rrs 21 */ 22 typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs; 23 struct ldns_struct_dnssec_rrs 24 { 25 ldns_rr *rr; 26 ldns_dnssec_rrs *next; 27 }; 28 29 /** 30 * Singly linked list of RRsets 31 */ 32 typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets; 33 struct ldns_struct_dnssec_rrsets 34 { 35 ldns_dnssec_rrs *rrs; 36 ldns_rr_type type; 37 ldns_dnssec_rrs *signatures; 38 ldns_dnssec_rrsets *next; 39 }; 40 41 /** 42 * Structure containing all resource records for a domain name 43 * Including the derived NSEC3, if present 44 */ 45 typedef struct ldns_struct_dnssec_name ldns_dnssec_name; 46 struct ldns_struct_dnssec_name 47 { 48 /** 49 * pointer to a dname containing the name. 50 * Usually points to the owner name of the first RR of the first RRset 51 */ 52 ldns_rdf *name; 53 /** 54 * Usually, the name is a pointer to the owner name of the first rr for 55 * this name, but sometimes there is no actual data to point to, 56 * for instance in 57 * names representing empty nonterminals. If so, set alloced to true to 58 * indicate that this data must also be freed when the name is freed 59 */ 60 bool name_alloced; 61 /** 62 * The rrsets for this name 63 */ 64 ldns_dnssec_rrsets *rrsets; 65 /** 66 * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3) 67 */ 68 ldns_rr *nsec; 69 /** 70 * signatures for the NSEC record 71 */ 72 ldns_dnssec_rrs *nsec_signatures; 73 /** 74 * Unlike what the name is_glue suggests, this field is set to true by 75 * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue() 76 * when the name, this dnssec_name struct represents, is occluded. 77 * Names that contain other occluded rrsets and records with glue on 78 * the delegation point will NOT have this bool set to true. 79 * This field should NOT be read directly, but only via the 80 * ldns_dnssec_name_is_glue() function! 81 */ 82 bool is_glue; 83 /** 84 * pointer to store the hashed name (only used when in an NSEC3 zone 85 */ 86 ldns_rdf *hashed_name; 87 }; 88 89 /** 90 * Structure containing a dnssec zone 91 */ 92 struct ldns_struct_dnssec_zone { 93 /** points to the name containing the SOA RR */ 94 ldns_dnssec_name *soa; 95 /** tree of ldns_dnssec_names */ 96 ldns_rbtree_t *names; 97 }; 98 typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone; 99 100 /** 101 * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs 102 * \return the allocated data 103 */ 104 ldns_dnssec_rrs *ldns_dnssec_rrs_new(); 105 106 /** 107 * Frees the list of rrs, but *not* the individual ldns_rr records 108 * contained in the list 109 * 110 * \param[in] rrs the data structure to free 111 */ 112 void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs); 113 114 /** 115 * Frees the list of rrs, and the individual ldns_rr records 116 * contained in the list 117 * 118 * \param[in] rrs the data structure to free 119 */ 120 void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs); 121 122 /** 123 * Adds an RR to the list of RRs. The list will remain ordered 124 * 125 * \param[in] rrs the list to add to 126 * \param[in] rr the RR to add 127 * \return LDNS_STATUS_OK on success 128 */ 129 ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr); 130 131 /** 132 * Prints the given rrs to the file descriptor 133 * 134 * \param[in] out the file descriptor to print to 135 * \param[in] rrs the list of RRs to print 136 */ 137 void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs); 138 139 /** 140 * Prints the given rrs to the file descriptor 141 * 142 * \param[in] out the file descriptor to print to 143 * \param[in] fmt the format of the textual representation 144 * \param[in] rrs the list of RRs to print 145 */ 146 void ldns_dnssec_rrs_print_fmt(FILE *out, 147 const ldns_output_format *fmt, ldns_dnssec_rrs *rrs); 148 149 /** 150 * Creates a new list (entry) of RRsets 151 * \return the newly allocated structure 152 */ 153 ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(); 154 155 /** 156 * Frees the list of rrsets and their rrs, but *not* the ldns_rr 157 * records in the sets 158 * 159 * \param[in] rrsets the data structure to free 160 */ 161 void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets); 162 163 /** 164 * Frees the list of rrsets and their rrs, and the ldns_rr 165 * records in the sets 166 * 167 * \param[in] rrsets the data structure to free 168 */ 169 void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets); 170 171 /** 172 * Returns the rr type of the rrset (that is head of the given list) 173 * 174 * \param[in] rrsets the rrset to get the type of 175 * \return the rr type 176 */ 177 ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets); 178 179 /** 180 * Sets the RR type of the rrset (that is head of the given list) 181 * 182 * \param[in] rrsets the rrset to set the type of 183 * \param[in] type the type to set 184 * \return LDNS_STATUS_OK on success 185 */ 186 ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 187 ldns_rr_type type); 188 189 /** 190 * Add an ldns_rr to the corresponding RRset in the given list of RRsets. 191 * If it is not present, add it as a new RRset with 1 record. 192 * 193 * \param[in] rrsets the list of rrsets to add the RR to 194 * \param[in] rr the rr to add to the list of rrsets 195 * \return LDNS_STATUS_OK on success 196 */ 197 ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); 198 199 /** 200 * Print the given list of rrsets to the fiven file descriptor 201 * 202 * \param[in] out the file descriptor to print to 203 * \param[in] rrsets the list of RRsets to print 204 * \param[in] follow if set to false, only print the first RRset 205 */ 206 void ldns_dnssec_rrsets_print(FILE *out, 207 ldns_dnssec_rrsets *rrsets, 208 bool follow); 209 210 /** 211 * Print the given list of rrsets to the fiven file descriptor 212 * 213 * \param[in] out the file descriptor to print to 214 * \param[in] fmt the format of the textual representation 215 * \param[in] rrsets the list of RRsets to print 216 * \param[in] follow if set to false, only print the first RRset 217 */ 218 void ldns_dnssec_rrsets_print_fmt(FILE *out, 219 const ldns_output_format *fmt, 220 ldns_dnssec_rrsets *rrsets, 221 bool follow); 222 223 224 /** 225 * Create a new data structure for a dnssec name 226 * \return the allocated structure 227 */ 228 ldns_dnssec_name *ldns_dnssec_name_new(); 229 230 /** 231 * Create a new data structure for a dnssec name for the given RR 232 * 233 * \param[in] rr the RR to derive properties from, and to add to the name 234 */ 235 ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr); 236 237 /** 238 * Frees the name structure and its rrs and rrsets. 239 * Individual ldns_rr records therein are not freed 240 * 241 * \param[in] name the structure to free 242 */ 243 void ldns_dnssec_name_free(ldns_dnssec_name *name); 244 245 /** 246 * Frees the name structure and its rrs and rrsets. 247 * Individual ldns_rr records contained in the name are also freed 248 * 249 * \param[in] name the structure to free 250 */ 251 void ldns_dnssec_name_deep_free(ldns_dnssec_name *name); 252 253 /** 254 * Returns the domain name of the given dnssec_name structure 255 * 256 * \param[in] name the dnssec name to get the domain name from 257 * \return the domain name 258 */ 259 ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name); 260 261 262 /** 263 * Sets the domain name of the given dnssec_name structure 264 * 265 * \param[in] name the dnssec name to set the domain name of 266 * \param[in] dname the domain name to set it to. This data is *not* copied. 267 */ 268 void ldns_dnssec_name_set_name(ldns_dnssec_name *name, 269 ldns_rdf *dname); 270 /** 271 * Returns if dnssec_name structure is marked as glue. 272 * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before 273 * using this function. 274 * Only names that have only glue rrsets will be marked. 275 * Names that have other occluded rrsets and names containing glue on the 276 * delegation point will NOT be marked! 277 * 278 * \param[in] name the dnssec name to get the domain name from 279 * \return true if the structure is marked as glue, false otherwise. 280 */ 281 bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name); 282 283 /** 284 * Sets the NSEC(3) RR of the given dnssec_name structure 285 * 286 * \param[in] name the dnssec name to set the domain name of 287 * \param[in] nsec the nsec rr to set it to. This data is *not* copied. 288 */ 289 void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); 290 291 /** 292 * Compares the domain names of the two arguments in their 293 * canonical ordening. 294 * 295 * \param[in] a The first dnssec_name to compare 296 * \param[in] b The second dnssec_name to compare 297 * \return -1 if the domain name of a comes before that of b in canonical 298 * ordening, 1 if it is the other way around, and 0 if they are 299 * equal 300 */ 301 int ldns_dnssec_name_cmp(const void *a, const void *b); 302 303 /** 304 * Inserts the given rr at the right place in the current dnssec_name 305 * No checking is done whether the name matches 306 * 307 * \param[in] name The ldns_dnssec_name to add the RR to 308 * \param[in] rr The RR to add 309 * \return LDNS_STATUS_OK on success, error code otherwise 310 */ 311 ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, 312 ldns_rr *rr); 313 314 /** 315 * Find the RRset with the given type in within this name structure 316 * 317 * \param[in] name the name to find the RRset in 318 * \param[in] type the type of the RRset to find 319 * \return the RRset, or NULL if not present 320 */ 321 ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, 322 ldns_rr_type type); 323 324 /** 325 * Find the RRset with the given name and type in the zone 326 * 327 * \param[in] zone the zone structure to find the RRset in 328 * \param[in] dname the domain name of the RRset to find 329 * \param[in] type the type of the RRset to find 330 * \return the RRset, or NULL if not present 331 */ 332 ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, 333 ldns_rdf *dname, 334 ldns_rr_type type); 335 336 /** 337 * Prints the RRs in the dnssec name structure to the given 338 * file descriptor 339 * 340 * \param[in] out the file descriptor to print to 341 * \param[in] name the name structure to print the contents of 342 */ 343 void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name); 344 345 /** 346 * Prints the RRs in the dnssec name structure to the given 347 * file descriptor 348 * 349 * \param[in] out the file descriptor to print to 350 * \param[in] fmt the format of the textual representation 351 * \param[in] name the name structure to print the contents of 352 */ 353 void ldns_dnssec_name_print_fmt(FILE *out, 354 const ldns_output_format *fmt, ldns_dnssec_name *name); 355 356 /** 357 * Creates a new dnssec_zone structure 358 * \return the allocated structure 359 */ 360 ldns_dnssec_zone *ldns_dnssec_zone_new(); 361 362 /** 363 * Frees the given zone structure, and its rbtree of dnssec_names 364 * Individual ldns_rr RRs within those names are *not* freed 365 * \param[in] *zone the zone to free 366 */ 367 void ldns_dnssec_zone_free(ldns_dnssec_zone *zone); 368 369 /** 370 * Frees the given zone structure, and its rbtree of dnssec_names 371 * Individual ldns_rr RRs within those names are also freed 372 * \param[in] *zone the zone to free 373 */ 374 void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone); 375 376 /** 377 * Adds the given RR to the zone. 378 * It find whether there is a dnssec_name with that name present. 379 * If so, add it to that, if not create a new one. 380 * Special handling of NSEC and RRSIG provided 381 * 382 * \param[in] zone the zone to add the RR to 383 * \param[in] rr The RR to add 384 * \return LDNS_STATUS_OK on success, an error code otherwise 385 */ 386 ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, 387 ldns_rr *rr); 388 389 /** 390 * Prints the rbtree of ldns_dnssec_name structures to the file descriptor 391 * 392 * \param[in] out the file descriptor to print the names to 393 * \param[in] tree the tree of ldns_dnssec_name structures to print 394 * \param[in] print_soa if true, print SOA records, if false, skip them 395 */ 396 void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa); 397 398 /** 399 * Prints the rbtree of ldns_dnssec_name structures to the file descriptor 400 * 401 * \param[in] out the file descriptor to print the names to 402 * \param[in] fmt the format of the textual representation 403 * \param[in] tree the tree of ldns_dnssec_name structures to print 404 * \param[in] print_soa if true, print SOA records, if false, skip them 405 */ 406 void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 407 ldns_rbtree_t *tree, bool print_soa); 408 409 /** 410 * Prints the complete zone to the given file descriptor 411 * 412 * \param[in] out the file descriptor to print to 413 * \param[in] zone the dnssec_zone to print 414 */ 415 void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); 416 417 /** 418 * Prints the complete zone to the given file descriptor 419 * 420 * \param[in] out the file descriptor to print to 421 * \param[in] fmt the format of the textual representation 422 * \param[in] zone the dnssec_zone to print 423 */ 424 void ldns_dnssec_zone_print_fmt(FILE *out, 425 const ldns_output_format *fmt, ldns_dnssec_zone *zone); 426 427 /** 428 * Adds explicit dnssec_name structures for the empty nonterminals 429 * in this zone. (this is needed for NSEC3 generation) 430 * 431 * \param[in] zone the zone to check for empty nonterminals 432 * return LDNS_STATUS_OK on success. 433 */ 434 ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); 435 436 #ifdef __cplusplus 437 } 438 #endif 439 440 #endif 441