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