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