1825eb42bSJan Lentfer /* 2825eb42bSJan Lentfer * special zone file structures and functions for better dnssec handling 3825eb42bSJan Lentfer */ 4825eb42bSJan Lentfer 5825eb42bSJan Lentfer #include <ldns/config.h> 6825eb42bSJan Lentfer 7825eb42bSJan Lentfer #include <ldns/ldns.h> 8825eb42bSJan Lentfer 9825eb42bSJan Lentfer ldns_dnssec_rrs * 10825eb42bSJan Lentfer ldns_dnssec_rrs_new() 11825eb42bSJan Lentfer { 12825eb42bSJan Lentfer ldns_dnssec_rrs *new_rrs; 13825eb42bSJan Lentfer new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); 14fd185f4dSJan Lentfer if(!new_rrs) return NULL; 15825eb42bSJan Lentfer new_rrs->rr = NULL; 16825eb42bSJan Lentfer new_rrs->next = NULL; 17825eb42bSJan Lentfer return new_rrs; 18825eb42bSJan Lentfer } 19825eb42bSJan Lentfer 20825eb42bSJan Lentfer INLINE void 21825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep) 22825eb42bSJan Lentfer { 23825eb42bSJan Lentfer ldns_dnssec_rrs *next; 24825eb42bSJan Lentfer while (rrs) { 25825eb42bSJan Lentfer next = rrs->next; 26825eb42bSJan Lentfer if (deep) { 27825eb42bSJan Lentfer ldns_rr_free(rrs->rr); 28825eb42bSJan Lentfer } 29825eb42bSJan Lentfer LDNS_FREE(rrs); 30825eb42bSJan Lentfer rrs = next; 31825eb42bSJan Lentfer } 32825eb42bSJan Lentfer } 33825eb42bSJan Lentfer 34825eb42bSJan Lentfer void 35825eb42bSJan Lentfer ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs) 36825eb42bSJan Lentfer { 37825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(rrs, 0); 38825eb42bSJan Lentfer } 39825eb42bSJan Lentfer 40825eb42bSJan Lentfer void 41825eb42bSJan Lentfer ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs) 42825eb42bSJan Lentfer { 43825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(rrs, 1); 44825eb42bSJan Lentfer } 45825eb42bSJan Lentfer 46825eb42bSJan Lentfer ldns_status 47825eb42bSJan Lentfer ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) 48825eb42bSJan Lentfer { 49825eb42bSJan Lentfer int cmp; 50825eb42bSJan Lentfer ldns_dnssec_rrs *new_rrs; 51825eb42bSJan Lentfer if (!rrs || !rr) { 52825eb42bSJan Lentfer return LDNS_STATUS_ERR; 53825eb42bSJan Lentfer } 54825eb42bSJan Lentfer 55825eb42bSJan Lentfer /* this could be done more efficiently; name and type should already 56825eb42bSJan Lentfer be equal */ 57825eb42bSJan Lentfer cmp = ldns_rr_compare(rrs->rr, 58825eb42bSJan Lentfer rr); 59825eb42bSJan Lentfer /* should we error on equal? */ 60825eb42bSJan Lentfer if (cmp <= 0) { 61825eb42bSJan Lentfer if (rrs->next) { 62ac996e71SJan Lentfer return ldns_dnssec_rrs_add_rr(rrs->next, rr); 63825eb42bSJan Lentfer } else { 64825eb42bSJan Lentfer new_rrs = ldns_dnssec_rrs_new(); 65825eb42bSJan Lentfer new_rrs->rr = rr; 66825eb42bSJan Lentfer rrs->next = new_rrs; 67825eb42bSJan Lentfer } 68825eb42bSJan Lentfer } else if (cmp > 0) { 69825eb42bSJan Lentfer /* put the current old rr in the new next, put the new 70825eb42bSJan Lentfer rr in the current container */ 71825eb42bSJan Lentfer new_rrs = ldns_dnssec_rrs_new(); 72825eb42bSJan Lentfer new_rrs->rr = rrs->rr; 73825eb42bSJan Lentfer new_rrs->next = rrs->next; 74825eb42bSJan Lentfer rrs->rr = rr; 75825eb42bSJan Lentfer rrs->next = new_rrs; 76825eb42bSJan Lentfer } 77825eb42bSJan Lentfer return LDNS_STATUS_OK; 78825eb42bSJan Lentfer } 79825eb42bSJan Lentfer 80825eb42bSJan Lentfer void 81b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, 82b5dedccaSJan Lentfer ldns_dnssec_rrs *rrs) 83825eb42bSJan Lentfer { 84825eb42bSJan Lentfer if (!rrs) { 85b5dedccaSJan Lentfer if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 86b5dedccaSJan Lentfer fprintf(out, "; <void>"); 87825eb42bSJan Lentfer } else { 88825eb42bSJan Lentfer if (rrs->rr) { 89b5dedccaSJan Lentfer ldns_rr_print_fmt(out, fmt, rrs->rr); 90825eb42bSJan Lentfer } 91825eb42bSJan Lentfer if (rrs->next) { 92b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next); 93825eb42bSJan Lentfer } 94825eb42bSJan Lentfer } 95825eb42bSJan Lentfer } 96825eb42bSJan Lentfer 97b5dedccaSJan Lentfer void 98b5dedccaSJan Lentfer ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs) 99b5dedccaSJan Lentfer { 100b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs); 101b5dedccaSJan Lentfer } 102b5dedccaSJan Lentfer 103b5dedccaSJan Lentfer 104825eb42bSJan Lentfer ldns_dnssec_rrsets * 105825eb42bSJan Lentfer ldns_dnssec_rrsets_new() 106825eb42bSJan Lentfer { 107825eb42bSJan Lentfer ldns_dnssec_rrsets *new_rrsets; 108825eb42bSJan Lentfer new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); 109fd185f4dSJan Lentfer if(!new_rrsets) return NULL; 110825eb42bSJan Lentfer new_rrsets->rrs = NULL; 111825eb42bSJan Lentfer new_rrsets->type = 0; 112825eb42bSJan Lentfer new_rrsets->signatures = NULL; 113825eb42bSJan Lentfer new_rrsets->next = NULL; 114825eb42bSJan Lentfer return new_rrsets; 115825eb42bSJan Lentfer } 116825eb42bSJan Lentfer 117825eb42bSJan Lentfer INLINE void 118825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep) 119825eb42bSJan Lentfer { 120825eb42bSJan Lentfer if (rrsets) { 121825eb42bSJan Lentfer if (rrsets->rrs) { 122825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(rrsets->rrs, deep); 123825eb42bSJan Lentfer } 124825eb42bSJan Lentfer if (rrsets->next) { 125825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(rrsets->next, deep); 126825eb42bSJan Lentfer } 127825eb42bSJan Lentfer if (rrsets->signatures) { 128825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(rrsets->signatures, deep); 129825eb42bSJan Lentfer } 130825eb42bSJan Lentfer LDNS_FREE(rrsets); 131825eb42bSJan Lentfer } 132825eb42bSJan Lentfer } 133825eb42bSJan Lentfer 134825eb42bSJan Lentfer void 135825eb42bSJan Lentfer ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets) 136825eb42bSJan Lentfer { 137825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(rrsets, 0); 138825eb42bSJan Lentfer } 139825eb42bSJan Lentfer 140825eb42bSJan Lentfer void 141825eb42bSJan Lentfer ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets) 142825eb42bSJan Lentfer { 143825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(rrsets, 1); 144825eb42bSJan Lentfer } 145825eb42bSJan Lentfer 146825eb42bSJan Lentfer ldns_rr_type 147825eb42bSJan Lentfer ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets) 148825eb42bSJan Lentfer { 149825eb42bSJan Lentfer if (rrsets) { 150825eb42bSJan Lentfer return rrsets->type; 151825eb42bSJan Lentfer } else { 152825eb42bSJan Lentfer return 0; 153825eb42bSJan Lentfer } 154825eb42bSJan Lentfer } 155825eb42bSJan Lentfer 156825eb42bSJan Lentfer ldns_status 157825eb42bSJan Lentfer ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 158825eb42bSJan Lentfer ldns_rr_type type) 159825eb42bSJan Lentfer { 160825eb42bSJan Lentfer if (rrsets) { 161825eb42bSJan Lentfer rrsets->type = type; 162825eb42bSJan Lentfer return LDNS_STATUS_OK; 163825eb42bSJan Lentfer } 164825eb42bSJan Lentfer return LDNS_STATUS_ERR; 165825eb42bSJan Lentfer } 166825eb42bSJan Lentfer 167825eb42bSJan Lentfer ldns_dnssec_rrsets * 168825eb42bSJan Lentfer ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) 169825eb42bSJan Lentfer { 170825eb42bSJan Lentfer ldns_dnssec_rrsets *new_rrsets; 171825eb42bSJan Lentfer ldns_rr_type rr_type; 172825eb42bSJan Lentfer bool rrsig; 173825eb42bSJan Lentfer 174825eb42bSJan Lentfer new_rrsets = ldns_dnssec_rrsets_new(); 175825eb42bSJan Lentfer rr_type = ldns_rr_get_type(rr); 176825eb42bSJan Lentfer if (rr_type == LDNS_RR_TYPE_RRSIG) { 177825eb42bSJan Lentfer rrsig = true; 178825eb42bSJan Lentfer rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 179825eb42bSJan Lentfer } else { 180825eb42bSJan Lentfer rrsig = false; 181825eb42bSJan Lentfer } 182825eb42bSJan Lentfer if (!rrsig) { 183825eb42bSJan Lentfer new_rrsets->rrs = ldns_dnssec_rrs_new(); 184825eb42bSJan Lentfer new_rrsets->rrs->rr = rr; 185825eb42bSJan Lentfer } else { 186825eb42bSJan Lentfer new_rrsets->signatures = ldns_dnssec_rrs_new(); 187825eb42bSJan Lentfer new_rrsets->signatures->rr = rr; 188825eb42bSJan Lentfer } 189825eb42bSJan Lentfer new_rrsets->type = rr_type; 190825eb42bSJan Lentfer return new_rrsets; 191825eb42bSJan Lentfer } 192825eb42bSJan Lentfer 193825eb42bSJan Lentfer ldns_status 194825eb42bSJan Lentfer ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) 195825eb42bSJan Lentfer { 196825eb42bSJan Lentfer ldns_dnssec_rrsets *new_rrsets; 197825eb42bSJan Lentfer ldns_rr_type rr_type; 198825eb42bSJan Lentfer bool rrsig = false; 199825eb42bSJan Lentfer ldns_status result = LDNS_STATUS_OK; 200825eb42bSJan Lentfer 201825eb42bSJan Lentfer if (!rrsets || !rr) { 202825eb42bSJan Lentfer return LDNS_STATUS_ERR; 203825eb42bSJan Lentfer } 204825eb42bSJan Lentfer 205825eb42bSJan Lentfer rr_type = ldns_rr_get_type(rr); 206825eb42bSJan Lentfer 207825eb42bSJan Lentfer if (rr_type == LDNS_RR_TYPE_RRSIG) { 208825eb42bSJan Lentfer rrsig = true; 209825eb42bSJan Lentfer rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 210825eb42bSJan Lentfer } 211825eb42bSJan Lentfer 212825eb42bSJan Lentfer if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { 213825eb42bSJan Lentfer if (!rrsig) { 214825eb42bSJan Lentfer rrsets->rrs = ldns_dnssec_rrs_new(); 215825eb42bSJan Lentfer rrsets->rrs->rr = rr; 216825eb42bSJan Lentfer rrsets->type = rr_type; 217825eb42bSJan Lentfer } else { 218825eb42bSJan Lentfer rrsets->signatures = ldns_dnssec_rrs_new(); 219825eb42bSJan Lentfer rrsets->signatures->rr = rr; 220825eb42bSJan Lentfer rrsets->type = rr_type; 221825eb42bSJan Lentfer } 222825eb42bSJan Lentfer return LDNS_STATUS_OK; 223825eb42bSJan Lentfer } 224825eb42bSJan Lentfer 225825eb42bSJan Lentfer if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { 226825eb42bSJan Lentfer if (rrsets->next) { 227825eb42bSJan Lentfer result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); 228825eb42bSJan Lentfer } else { 229825eb42bSJan Lentfer new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); 230825eb42bSJan Lentfer rrsets->next = new_rrsets; 231825eb42bSJan Lentfer } 232825eb42bSJan Lentfer } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { 233825eb42bSJan Lentfer /* move the current one into the new next, 234825eb42bSJan Lentfer replace field of current with data from new rr */ 235825eb42bSJan Lentfer new_rrsets = ldns_dnssec_rrsets_new(); 236825eb42bSJan Lentfer new_rrsets->rrs = rrsets->rrs; 237825eb42bSJan Lentfer new_rrsets->type = rrsets->type; 238825eb42bSJan Lentfer new_rrsets->signatures = rrsets->signatures; 239825eb42bSJan Lentfer new_rrsets->next = rrsets->next; 240825eb42bSJan Lentfer if (!rrsig) { 241825eb42bSJan Lentfer rrsets->rrs = ldns_dnssec_rrs_new(); 242825eb42bSJan Lentfer rrsets->rrs->rr = rr; 243825eb42bSJan Lentfer rrsets->signatures = NULL; 244825eb42bSJan Lentfer } else { 245825eb42bSJan Lentfer rrsets->rrs = NULL; 246825eb42bSJan Lentfer rrsets->signatures = ldns_dnssec_rrs_new(); 247825eb42bSJan Lentfer rrsets->signatures->rr = rr; 248825eb42bSJan Lentfer } 249825eb42bSJan Lentfer rrsets->type = rr_type; 250825eb42bSJan Lentfer rrsets->next = new_rrsets; 251825eb42bSJan Lentfer } else { 252825eb42bSJan Lentfer /* equal, add to current rrsets */ 253825eb42bSJan Lentfer if (rrsig) { 254825eb42bSJan Lentfer if (rrsets->signatures) { 255825eb42bSJan Lentfer result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); 256825eb42bSJan Lentfer } else { 257825eb42bSJan Lentfer rrsets->signatures = ldns_dnssec_rrs_new(); 258825eb42bSJan Lentfer rrsets->signatures->rr = rr; 259825eb42bSJan Lentfer } 260825eb42bSJan Lentfer } else { 261825eb42bSJan Lentfer if (rrsets->rrs) { 262825eb42bSJan Lentfer result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); 263825eb42bSJan Lentfer } else { 264825eb42bSJan Lentfer rrsets->rrs = ldns_dnssec_rrs_new(); 265825eb42bSJan Lentfer rrsets->rrs->rr = rr; 266825eb42bSJan Lentfer } 267825eb42bSJan Lentfer } 268825eb42bSJan Lentfer } 269825eb42bSJan Lentfer 270825eb42bSJan Lentfer return result; 271825eb42bSJan Lentfer } 272825eb42bSJan Lentfer 273825eb42bSJan Lentfer void 274b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 275825eb42bSJan Lentfer ldns_dnssec_rrsets *rrsets, 276825eb42bSJan Lentfer bool follow, 277825eb42bSJan Lentfer bool show_soa) 278825eb42bSJan Lentfer { 279825eb42bSJan Lentfer if (!rrsets) { 280b5dedccaSJan Lentfer if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 281b5dedccaSJan Lentfer fprintf(out, "; <void>\n"); 282825eb42bSJan Lentfer } else { 283825eb42bSJan Lentfer if (rrsets->rrs && 284825eb42bSJan Lentfer (show_soa || 285825eb42bSJan Lentfer ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA 286825eb42bSJan Lentfer ) 287825eb42bSJan Lentfer ) { 288b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs); 289825eb42bSJan Lentfer if (rrsets->signatures) { 290b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(out, fmt, 291b5dedccaSJan Lentfer rrsets->signatures); 292825eb42bSJan Lentfer } 293825eb42bSJan Lentfer } 294825eb42bSJan Lentfer if (follow && rrsets->next) { 295b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 296b5dedccaSJan Lentfer rrsets->next, follow, show_soa); 297825eb42bSJan Lentfer } 298825eb42bSJan Lentfer } 299825eb42bSJan Lentfer } 300825eb42bSJan Lentfer 301825eb42bSJan Lentfer void 302b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa(FILE *out, 303b5dedccaSJan Lentfer ldns_dnssec_rrsets *rrsets, 304b5dedccaSJan Lentfer bool follow, 305b5dedccaSJan Lentfer bool show_soa) 306b5dedccaSJan Lentfer { 307b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default, 308b5dedccaSJan Lentfer rrsets, follow, show_soa); 309b5dedccaSJan Lentfer } 310b5dedccaSJan Lentfer 311b5dedccaSJan Lentfer 312b5dedccaSJan Lentfer void 313b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, 314b5dedccaSJan Lentfer ldns_dnssec_rrsets *rrsets, 315b5dedccaSJan Lentfer bool follow) 316b5dedccaSJan Lentfer { 317b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true); 318b5dedccaSJan Lentfer } 319b5dedccaSJan Lentfer 320b5dedccaSJan Lentfer void 321825eb42bSJan Lentfer ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow) 322825eb42bSJan Lentfer { 323b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 324b5dedccaSJan Lentfer rrsets, follow); 325825eb42bSJan Lentfer } 326825eb42bSJan Lentfer 327825eb42bSJan Lentfer ldns_dnssec_name * 328825eb42bSJan Lentfer ldns_dnssec_name_new() 329825eb42bSJan Lentfer { 330825eb42bSJan Lentfer ldns_dnssec_name *new_name; 331825eb42bSJan Lentfer 332b5dedccaSJan Lentfer new_name = LDNS_CALLOC(ldns_dnssec_name, 1); 333825eb42bSJan Lentfer if (!new_name) { 334825eb42bSJan Lentfer return NULL; 335825eb42bSJan Lentfer } 336b5dedccaSJan Lentfer /* 337b5dedccaSJan Lentfer * not needed anymore because CALLOC initalizes everything to zero. 338825eb42bSJan Lentfer 339825eb42bSJan Lentfer new_name->name = NULL; 340825eb42bSJan Lentfer new_name->rrsets = NULL; 341825eb42bSJan Lentfer new_name->name_alloced = false; 342825eb42bSJan Lentfer new_name->nsec = NULL; 343825eb42bSJan Lentfer new_name->nsec_signatures = NULL; 344825eb42bSJan Lentfer 345825eb42bSJan Lentfer new_name->is_glue = false; 346825eb42bSJan Lentfer new_name->hashed_name = NULL; 347825eb42bSJan Lentfer 348b5dedccaSJan Lentfer */ 349825eb42bSJan Lentfer return new_name; 350825eb42bSJan Lentfer } 351825eb42bSJan Lentfer 352825eb42bSJan Lentfer ldns_dnssec_name * 353825eb42bSJan Lentfer ldns_dnssec_name_new_frm_rr(ldns_rr *rr) 354825eb42bSJan Lentfer { 355825eb42bSJan Lentfer ldns_dnssec_name *new_name = ldns_dnssec_name_new(); 356825eb42bSJan Lentfer 357825eb42bSJan Lentfer new_name->name = ldns_rr_owner(rr); 358fd185f4dSJan Lentfer if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) { 359fd185f4dSJan Lentfer ldns_dnssec_name_free(new_name); 360fd185f4dSJan Lentfer return NULL; 361fd185f4dSJan Lentfer } 362825eb42bSJan Lentfer 363825eb42bSJan Lentfer return new_name; 364825eb42bSJan Lentfer } 365825eb42bSJan Lentfer 366825eb42bSJan Lentfer INLINE void 367825eb42bSJan Lentfer ldns_dnssec_name_free_internal(ldns_dnssec_name *name, 368825eb42bSJan Lentfer int deep) 369825eb42bSJan Lentfer { 370825eb42bSJan Lentfer if (name) { 371825eb42bSJan Lentfer if (name->name_alloced) { 372825eb42bSJan Lentfer ldns_rdf_deep_free(name->name); 373825eb42bSJan Lentfer } 374825eb42bSJan Lentfer if (name->rrsets) { 375825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(name->rrsets, deep); 376825eb42bSJan Lentfer } 377825eb42bSJan Lentfer if (name->nsec && deep) { 378825eb42bSJan Lentfer ldns_rr_free(name->nsec); 379825eb42bSJan Lentfer } 380825eb42bSJan Lentfer if (name->nsec_signatures) { 381825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); 382825eb42bSJan Lentfer } 383825eb42bSJan Lentfer if (name->hashed_name) { 384825eb42bSJan Lentfer if (deep) { 385825eb42bSJan Lentfer ldns_rdf_deep_free(name->hashed_name); 386825eb42bSJan Lentfer } 387825eb42bSJan Lentfer } 388825eb42bSJan Lentfer LDNS_FREE(name); 389825eb42bSJan Lentfer } 390825eb42bSJan Lentfer } 391825eb42bSJan Lentfer 392825eb42bSJan Lentfer void 393825eb42bSJan Lentfer ldns_dnssec_name_free(ldns_dnssec_name *name) 394825eb42bSJan Lentfer { 395825eb42bSJan Lentfer ldns_dnssec_name_free_internal(name, 0); 396825eb42bSJan Lentfer } 397825eb42bSJan Lentfer 398825eb42bSJan Lentfer void 399825eb42bSJan Lentfer ldns_dnssec_name_deep_free(ldns_dnssec_name *name) 400825eb42bSJan Lentfer { 401825eb42bSJan Lentfer ldns_dnssec_name_free_internal(name, 1); 402825eb42bSJan Lentfer } 403825eb42bSJan Lentfer 404825eb42bSJan Lentfer ldns_rdf * 405825eb42bSJan Lentfer ldns_dnssec_name_name(ldns_dnssec_name *name) 406825eb42bSJan Lentfer { 407825eb42bSJan Lentfer if (name) { 408825eb42bSJan Lentfer return name->name; 409825eb42bSJan Lentfer } 410825eb42bSJan Lentfer return NULL; 411825eb42bSJan Lentfer } 412825eb42bSJan Lentfer 413b5dedccaSJan Lentfer bool 414b5dedccaSJan Lentfer ldns_dnssec_name_is_glue(ldns_dnssec_name *name) 415b5dedccaSJan Lentfer { 416b5dedccaSJan Lentfer if (name) { 417b5dedccaSJan Lentfer return name->is_glue; 418b5dedccaSJan Lentfer } 419b5dedccaSJan Lentfer return false; 420b5dedccaSJan Lentfer } 421b5dedccaSJan Lentfer 422825eb42bSJan Lentfer void 423825eb42bSJan Lentfer ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, 424825eb42bSJan Lentfer ldns_rdf *dname) 425825eb42bSJan Lentfer { 426825eb42bSJan Lentfer if (rrset && dname) { 427825eb42bSJan Lentfer rrset->name = dname; 428825eb42bSJan Lentfer } 429825eb42bSJan Lentfer } 430825eb42bSJan Lentfer 431825eb42bSJan Lentfer ldns_rr * 432825eb42bSJan Lentfer ldns_dnssec_name_nsec(ldns_dnssec_name *rrset) 433825eb42bSJan Lentfer { 434825eb42bSJan Lentfer if (rrset) { 435825eb42bSJan Lentfer return rrset->nsec; 436825eb42bSJan Lentfer } 437825eb42bSJan Lentfer return NULL; 438825eb42bSJan Lentfer } 439825eb42bSJan Lentfer 440825eb42bSJan Lentfer void 441825eb42bSJan Lentfer ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) 442825eb42bSJan Lentfer { 443825eb42bSJan Lentfer if (rrset && nsec) { 444825eb42bSJan Lentfer rrset->nsec = nsec; 445825eb42bSJan Lentfer } 446825eb42bSJan Lentfer } 447825eb42bSJan Lentfer 448825eb42bSJan Lentfer int 449825eb42bSJan Lentfer ldns_dnssec_name_cmp(const void *a, const void *b) 450825eb42bSJan Lentfer { 451825eb42bSJan Lentfer ldns_dnssec_name *na = (ldns_dnssec_name *) a; 452825eb42bSJan Lentfer ldns_dnssec_name *nb = (ldns_dnssec_name *) b; 453825eb42bSJan Lentfer 454825eb42bSJan Lentfer if (na && nb) { 455825eb42bSJan Lentfer return ldns_dname_compare(ldns_dnssec_name_name(na), 456825eb42bSJan Lentfer ldns_dnssec_name_name(nb)); 457825eb42bSJan Lentfer } else if (na) { 458825eb42bSJan Lentfer return 1; 459825eb42bSJan Lentfer } else if (nb) { 460825eb42bSJan Lentfer return -1; 461825eb42bSJan Lentfer } else { 462825eb42bSJan Lentfer return 0; 463825eb42bSJan Lentfer } 464825eb42bSJan Lentfer } 465825eb42bSJan Lentfer 466825eb42bSJan Lentfer ldns_status 467825eb42bSJan Lentfer ldns_dnssec_name_add_rr(ldns_dnssec_name *name, 468825eb42bSJan Lentfer ldns_rr *rr) 469825eb42bSJan Lentfer { 470825eb42bSJan Lentfer ldns_status result = LDNS_STATUS_OK; 471825eb42bSJan Lentfer ldns_rdf *name_name; 472825eb42bSJan Lentfer bool hashed_name = false; 473ac996e71SJan Lentfer ldns_rr_type rr_type; 474825eb42bSJan Lentfer ldns_rr_type typecovered = 0; 475825eb42bSJan Lentfer 476825eb42bSJan Lentfer /* special handling for NSEC3 and NSECX covering RRSIGS */ 477825eb42bSJan Lentfer 478825eb42bSJan Lentfer if (!name || !rr) { 479825eb42bSJan Lentfer return LDNS_STATUS_ERR; 480825eb42bSJan Lentfer } 481825eb42bSJan Lentfer 482825eb42bSJan Lentfer rr_type = ldns_rr_get_type(rr); 483825eb42bSJan Lentfer 484825eb42bSJan Lentfer if (rr_type == LDNS_RR_TYPE_RRSIG) { 485825eb42bSJan Lentfer typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 486825eb42bSJan Lentfer } 487825eb42bSJan Lentfer 488825eb42bSJan Lentfer #ifdef HAVE_SSL 489825eb42bSJan Lentfer if (rr_type == LDNS_RR_TYPE_NSEC3 || 490825eb42bSJan Lentfer typecovered == LDNS_RR_TYPE_NSEC3) { 491825eb42bSJan Lentfer name_name = ldns_nsec3_hash_name_frm_nsec3(rr, 492825eb42bSJan Lentfer ldns_dnssec_name_name(name)); 493825eb42bSJan Lentfer hashed_name = true; 494825eb42bSJan Lentfer } else { 495825eb42bSJan Lentfer name_name = ldns_dnssec_name_name(name); 496825eb42bSJan Lentfer } 497825eb42bSJan Lentfer #else 498825eb42bSJan Lentfer name_name = ldns_dnssec_name_name(name); 499825eb42bSJan Lentfer #endif /* HAVE_SSL */ 500825eb42bSJan Lentfer 501825eb42bSJan Lentfer if (rr_type == LDNS_RR_TYPE_NSEC || 502825eb42bSJan Lentfer rr_type == LDNS_RR_TYPE_NSEC3) { 503825eb42bSJan Lentfer /* XX check if is already set (and error?) */ 504825eb42bSJan Lentfer name->nsec = rr; 505825eb42bSJan Lentfer } else if (typecovered == LDNS_RR_TYPE_NSEC || 506825eb42bSJan Lentfer typecovered == LDNS_RR_TYPE_NSEC3) { 507825eb42bSJan Lentfer if (name->nsec_signatures) { 508fd185f4dSJan Lentfer result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); 509825eb42bSJan Lentfer } else { 510825eb42bSJan Lentfer name->nsec_signatures = ldns_dnssec_rrs_new(); 511825eb42bSJan Lentfer name->nsec_signatures->rr = rr; 512825eb42bSJan Lentfer } 513825eb42bSJan Lentfer } else { 514825eb42bSJan Lentfer /* it's a 'normal' RR, add it to the right rrset */ 515825eb42bSJan Lentfer if (name->rrsets) { 516825eb42bSJan Lentfer result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 517825eb42bSJan Lentfer } else { 518825eb42bSJan Lentfer name->rrsets = ldns_dnssec_rrsets_new(); 519825eb42bSJan Lentfer result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 520825eb42bSJan Lentfer } 521825eb42bSJan Lentfer } 522825eb42bSJan Lentfer 523825eb42bSJan Lentfer if (hashed_name) { 524825eb42bSJan Lentfer ldns_rdf_deep_free(name_name); 525825eb42bSJan Lentfer } 526825eb42bSJan Lentfer 527825eb42bSJan Lentfer return result; 528825eb42bSJan Lentfer } 529825eb42bSJan Lentfer 530825eb42bSJan Lentfer ldns_dnssec_rrsets * 531825eb42bSJan Lentfer ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, 532825eb42bSJan Lentfer ldns_rr_type type) { 533825eb42bSJan Lentfer ldns_dnssec_rrsets *result; 534825eb42bSJan Lentfer 535825eb42bSJan Lentfer result = name->rrsets; 536825eb42bSJan Lentfer while (result) { 537825eb42bSJan Lentfer if (result->type == type) { 538825eb42bSJan Lentfer return result; 539825eb42bSJan Lentfer } else { 540825eb42bSJan Lentfer result = result->next; 541825eb42bSJan Lentfer } 542825eb42bSJan Lentfer } 543825eb42bSJan Lentfer return NULL; 544825eb42bSJan Lentfer } 545825eb42bSJan Lentfer 546825eb42bSJan Lentfer ldns_dnssec_rrsets * 547825eb42bSJan Lentfer ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, 548825eb42bSJan Lentfer ldns_rdf *dname, 549825eb42bSJan Lentfer ldns_rr_type type) 550825eb42bSJan Lentfer { 551825eb42bSJan Lentfer ldns_rbnode_t *node; 552825eb42bSJan Lentfer 553825eb42bSJan Lentfer if (!zone || !dname) { 554825eb42bSJan Lentfer return NULL; 555825eb42bSJan Lentfer } 556825eb42bSJan Lentfer 557825eb42bSJan Lentfer node = ldns_rbtree_search(zone->names, dname); 558825eb42bSJan Lentfer if (node) { 559825eb42bSJan Lentfer return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data, 560825eb42bSJan Lentfer type); 561825eb42bSJan Lentfer } else { 562825eb42bSJan Lentfer return NULL; 563825eb42bSJan Lentfer } 564825eb42bSJan Lentfer } 565825eb42bSJan Lentfer 566825eb42bSJan Lentfer void 567b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 568b5dedccaSJan Lentfer ldns_dnssec_name *name, 569b5dedccaSJan Lentfer bool show_soa) 570825eb42bSJan Lentfer { 571825eb42bSJan Lentfer if (name) { 572825eb42bSJan Lentfer if(name->rrsets) { 573b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 574b5dedccaSJan Lentfer name->rrsets, true, show_soa); 575b5dedccaSJan Lentfer } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 576825eb42bSJan Lentfer fprintf(out, ";; Empty nonterminal: "); 577825eb42bSJan Lentfer ldns_rdf_print(out, name->name); 578825eb42bSJan Lentfer fprintf(out, "\n"); 579825eb42bSJan Lentfer } 580825eb42bSJan Lentfer if(name->nsec) { 581b5dedccaSJan Lentfer ldns_rr_print_fmt(out, fmt, name->nsec); 582825eb42bSJan Lentfer } 583825eb42bSJan Lentfer if (name->nsec_signatures) { 584b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(out, fmt, 585b5dedccaSJan Lentfer name->nsec_signatures); 586825eb42bSJan Lentfer } 587b5dedccaSJan Lentfer } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 588b5dedccaSJan Lentfer fprintf(out, "; <void>\n"); 589825eb42bSJan Lentfer } 590825eb42bSJan Lentfer } 591825eb42bSJan Lentfer 592825eb42bSJan Lentfer void 593b5dedccaSJan Lentfer ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa) 594b5dedccaSJan Lentfer { 595b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default, 596b5dedccaSJan Lentfer name, show_soa); 597b5dedccaSJan Lentfer } 598b5dedccaSJan Lentfer 599b5dedccaSJan Lentfer void 600b5dedccaSJan Lentfer ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, 601b5dedccaSJan Lentfer ldns_dnssec_name *name) 602b5dedccaSJan Lentfer { 603b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(out, fmt, name, true); 604b5dedccaSJan Lentfer } 605b5dedccaSJan Lentfer 606b5dedccaSJan Lentfer void 607825eb42bSJan Lentfer ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name) 608825eb42bSJan Lentfer { 609b5dedccaSJan Lentfer ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name); 610825eb42bSJan Lentfer } 611825eb42bSJan Lentfer 612b5dedccaSJan Lentfer 613825eb42bSJan Lentfer ldns_dnssec_zone * 614825eb42bSJan Lentfer ldns_dnssec_zone_new() 615825eb42bSJan Lentfer { 616825eb42bSJan Lentfer ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); 617fd185f4dSJan Lentfer if(!zone) return NULL; 618825eb42bSJan Lentfer zone->soa = NULL; 619825eb42bSJan Lentfer zone->names = NULL; 620825eb42bSJan Lentfer 621825eb42bSJan Lentfer return zone; 622825eb42bSJan Lentfer } 623825eb42bSJan Lentfer 624*d1b2b5caSJohn Marino static bool 625*d1b2b5caSJohn Marino rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) 626*d1b2b5caSJohn Marino { 627*d1b2b5caSJohn Marino return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG 628*d1b2b5caSJohn Marino && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t; 629*d1b2b5caSJohn Marino } 630*d1b2b5caSJohn Marino 631*d1b2b5caSJohn Marino /* When the zone is first read into an list and then inserted into an 632*d1b2b5caSJohn Marino * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next) 633*d1b2b5caSJohn Marino * to each other. Because ldns-verify-zone (the only program that uses this 634*d1b2b5caSJohn Marino * function) uses the rbtree mostly for sequentual walking, this results 635*d1b2b5caSJohn Marino * in a speed increase (of 15% on linux) because we have less CPU-cache misses. 636*d1b2b5caSJohn Marino */ 637*d1b2b5caSJohn Marino #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */ 638*d1b2b5caSJohn Marino 639*d1b2b5caSJohn Marino ldns_status 640*d1b2b5caSJohn Marino ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, 641*d1b2b5caSJohn Marino uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) 642*d1b2b5caSJohn Marino { 643*d1b2b5caSJohn Marino ldns_rr* cur_rr; 644*d1b2b5caSJohn Marino size_t i; 645*d1b2b5caSJohn Marino 646*d1b2b5caSJohn Marino ldns_rdf *my_origin = NULL; 647*d1b2b5caSJohn Marino ldns_rdf *my_prev = NULL; 648*d1b2b5caSJohn Marino 649*d1b2b5caSJohn Marino ldns_dnssec_zone *newzone = ldns_dnssec_zone_new(); 650*d1b2b5caSJohn Marino /* when reading NSEC3s, there is a chance that we encounter nsecs 651*d1b2b5caSJohn Marino for empty nonterminals, whose nonterminals we cannot derive yet 652*d1b2b5caSJohn Marino because the needed information is to be read later. in that case 653*d1b2b5caSJohn Marino we keep a list of those nsec3's and retry to add them later */ 654*d1b2b5caSJohn Marino ldns_rr_list* todo_nsec3s = ldns_rr_list_new(); 655*d1b2b5caSJohn Marino ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); 656*d1b2b5caSJohn Marino 657*d1b2b5caSJohn Marino ldns_status status = LDNS_STATUS_MEM_ERR; 658*d1b2b5caSJohn Marino 659*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 660*d1b2b5caSJohn Marino ldns_zone* zone = NULL; 661*d1b2b5caSJohn Marino if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr) 662*d1b2b5caSJohn Marino != LDNS_STATUS_OK) goto error; 663*d1b2b5caSJohn Marino #else 664*d1b2b5caSJohn Marino uint32_t my_ttl = ttl; 665*d1b2b5caSJohn Marino #endif 666*d1b2b5caSJohn Marino 667*d1b2b5caSJohn Marino if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error; 668*d1b2b5caSJohn Marino 669*d1b2b5caSJohn Marino if (origin) { 670*d1b2b5caSJohn Marino if (!(my_origin = ldns_rdf_clone(origin))) goto error; 671*d1b2b5caSJohn Marino if (!(my_prev = ldns_rdf_clone(origin))) goto error; 672*d1b2b5caSJohn Marino } 673*d1b2b5caSJohn Marino 674*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 675*d1b2b5caSJohn Marino if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone)) 676*d1b2b5caSJohn Marino != LDNS_STATUS_OK) goto error; 677*d1b2b5caSJohn Marino 678*d1b2b5caSJohn Marino for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 679*d1b2b5caSJohn Marino cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); 680*d1b2b5caSJohn Marino status = LDNS_STATUS_OK; 681*d1b2b5caSJohn Marino #else 682*d1b2b5caSJohn Marino while (!feof(fp)) { 683*d1b2b5caSJohn Marino status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, 684*d1b2b5caSJohn Marino &my_prev, line_nr); 685*d1b2b5caSJohn Marino 686*d1b2b5caSJohn Marino #endif 687*d1b2b5caSJohn Marino switch (status) { 688*d1b2b5caSJohn Marino case LDNS_STATUS_OK: 689*d1b2b5caSJohn Marino 690*d1b2b5caSJohn Marino status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 691*d1b2b5caSJohn Marino if (status == 692*d1b2b5caSJohn Marino LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { 693*d1b2b5caSJohn Marino 694*d1b2b5caSJohn Marino if (rr_is_rrsig_covering(cur_rr, 695*d1b2b5caSJohn Marino LDNS_RR_TYPE_NSEC3)){ 696*d1b2b5caSJohn Marino ldns_rr_list_push_rr(todo_nsec3_rrsigs, 697*d1b2b5caSJohn Marino cur_rr); 698*d1b2b5caSJohn Marino } else { 699*d1b2b5caSJohn Marino ldns_rr_list_push_rr(todo_nsec3s, 700*d1b2b5caSJohn Marino cur_rr); 701*d1b2b5caSJohn Marino } 702*d1b2b5caSJohn Marino } else if (status != LDNS_STATUS_OK) 703*d1b2b5caSJohn Marino goto error; 704*d1b2b5caSJohn Marino 705*d1b2b5caSJohn Marino break; 706*d1b2b5caSJohn Marino 707*d1b2b5caSJohn Marino 708*d1b2b5caSJohn Marino case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ 709*d1b2b5caSJohn Marino case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ 710*d1b2b5caSJohn Marino case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ 711*d1b2b5caSJohn Marino status = LDNS_STATUS_OK; 712*d1b2b5caSJohn Marino break; 713*d1b2b5caSJohn Marino 714*d1b2b5caSJohn Marino case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ 715*d1b2b5caSJohn Marino status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; 716*d1b2b5caSJohn Marino break; 717*d1b2b5caSJohn Marino 718*d1b2b5caSJohn Marino default: 719*d1b2b5caSJohn Marino goto error; 720*d1b2b5caSJohn Marino } 721*d1b2b5caSJohn Marino } 722*d1b2b5caSJohn Marino 723*d1b2b5caSJohn Marino if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { 724*d1b2b5caSJohn Marino (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); 725*d1b2b5caSJohn Marino for (i = 0; status == LDNS_STATUS_OK && 726*d1b2b5caSJohn Marino i < ldns_rr_list_rr_count(todo_nsec3s); i++) { 727*d1b2b5caSJohn Marino cur_rr = ldns_rr_list_rr(todo_nsec3s, i); 728*d1b2b5caSJohn Marino status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 729*d1b2b5caSJohn Marino } 730*d1b2b5caSJohn Marino for (i = 0; status == LDNS_STATUS_OK && 731*d1b2b5caSJohn Marino i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); 732*d1b2b5caSJohn Marino i++){ 733*d1b2b5caSJohn Marino cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); 734*d1b2b5caSJohn Marino status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 735*d1b2b5caSJohn Marino } 736*d1b2b5caSJohn Marino } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { 737*d1b2b5caSJohn Marino for (i = 0; status == LDNS_STATUS_OK && 738*d1b2b5caSJohn Marino i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); 739*d1b2b5caSJohn Marino i++){ 740*d1b2b5caSJohn Marino cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); 741*d1b2b5caSJohn Marino status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 742*d1b2b5caSJohn Marino } 743*d1b2b5caSJohn Marino } 744*d1b2b5caSJohn Marino 745*d1b2b5caSJohn Marino if (z) { 746*d1b2b5caSJohn Marino *z = newzone; 747*d1b2b5caSJohn Marino newzone = NULL; 748*d1b2b5caSJohn Marino } else { 749*d1b2b5caSJohn Marino ldns_dnssec_zone_free(newzone); 750*d1b2b5caSJohn Marino } 751*d1b2b5caSJohn Marino 752*d1b2b5caSJohn Marino error: 753*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 754*d1b2b5caSJohn Marino if (zone) { 755*d1b2b5caSJohn Marino ldns_zone_free(zone); 756*d1b2b5caSJohn Marino } 757*d1b2b5caSJohn Marino #endif 758*d1b2b5caSJohn Marino ldns_rr_list_free(todo_nsec3_rrsigs); 759*d1b2b5caSJohn Marino ldns_rr_list_free(todo_nsec3s); 760*d1b2b5caSJohn Marino 761*d1b2b5caSJohn Marino if (my_origin) { 762*d1b2b5caSJohn Marino ldns_rdf_deep_free(my_origin); 763*d1b2b5caSJohn Marino } 764*d1b2b5caSJohn Marino if (my_prev) { 765*d1b2b5caSJohn Marino ldns_rdf_deep_free(my_prev); 766*d1b2b5caSJohn Marino } 767*d1b2b5caSJohn Marino if (newzone) { 768*d1b2b5caSJohn Marino ldns_dnssec_zone_free(newzone); 769*d1b2b5caSJohn Marino } 770*d1b2b5caSJohn Marino return status; 771*d1b2b5caSJohn Marino } 772*d1b2b5caSJohn Marino 773*d1b2b5caSJohn Marino ldns_status 774*d1b2b5caSJohn Marino ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, 775*d1b2b5caSJohn Marino uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) 776*d1b2b5caSJohn Marino { 777*d1b2b5caSJohn Marino return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); 778*d1b2b5caSJohn Marino } 779*d1b2b5caSJohn Marino 780825eb42bSJan Lentfer void 781825eb42bSJan Lentfer ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { 782825eb42bSJan Lentfer (void) arg; 783825eb42bSJan Lentfer ldns_dnssec_name_free((ldns_dnssec_name *)node->data); 784*d1b2b5caSJohn Marino LDNS_FREE(node); 785825eb42bSJan Lentfer } 786825eb42bSJan Lentfer 787825eb42bSJan Lentfer void 788825eb42bSJan Lentfer ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { 789825eb42bSJan Lentfer (void) arg; 790825eb42bSJan Lentfer ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); 791*d1b2b5caSJohn Marino LDNS_FREE(node); 792825eb42bSJan Lentfer } 793825eb42bSJan Lentfer 794825eb42bSJan Lentfer void 795825eb42bSJan Lentfer ldns_dnssec_zone_free(ldns_dnssec_zone *zone) 796825eb42bSJan Lentfer { 797825eb42bSJan Lentfer if (zone) { 798825eb42bSJan Lentfer if (zone->names) { 799825eb42bSJan Lentfer /* destroy all name structures within the tree */ 800825eb42bSJan Lentfer ldns_traverse_postorder(zone->names, 801825eb42bSJan Lentfer ldns_dnssec_name_node_free, 802825eb42bSJan Lentfer NULL); 803*d1b2b5caSJohn Marino LDNS_FREE(zone->names); 804825eb42bSJan Lentfer } 805825eb42bSJan Lentfer LDNS_FREE(zone); 806825eb42bSJan Lentfer } 807825eb42bSJan Lentfer } 808825eb42bSJan Lentfer 809825eb42bSJan Lentfer void 810825eb42bSJan Lentfer ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) 811825eb42bSJan Lentfer { 812825eb42bSJan Lentfer if (zone) { 813825eb42bSJan Lentfer if (zone->names) { 814825eb42bSJan Lentfer /* destroy all name structures within the tree */ 815825eb42bSJan Lentfer ldns_traverse_postorder(zone->names, 816825eb42bSJan Lentfer ldns_dnssec_name_node_deep_free, 817825eb42bSJan Lentfer NULL); 818*d1b2b5caSJohn Marino LDNS_FREE(zone->names); 819825eb42bSJan Lentfer } 820825eb42bSJan Lentfer LDNS_FREE(zone); 821825eb42bSJan Lentfer } 822825eb42bSJan Lentfer } 823825eb42bSJan Lentfer 824825eb42bSJan Lentfer /* use for dname comparison in tree */ 825825eb42bSJan Lentfer int 826825eb42bSJan Lentfer ldns_dname_compare_v(const void *a, const void *b) { 827825eb42bSJan Lentfer return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); 828825eb42bSJan Lentfer } 829825eb42bSJan Lentfer 830825eb42bSJan Lentfer ldns_rbnode_t * 831825eb42bSJan Lentfer ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, 832825eb42bSJan Lentfer ldns_rr *rr) { 833825eb42bSJan Lentfer ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names); 834825eb42bSJan Lentfer ldns_dnssec_name *current_name; 835825eb42bSJan Lentfer ldns_rdf *hashed_name; 836825eb42bSJan Lentfer 837825eb42bSJan Lentfer hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); 838825eb42bSJan Lentfer 839825eb42bSJan Lentfer while (current_node != LDNS_RBTREE_NULL) { 840825eb42bSJan Lentfer current_name = (ldns_dnssec_name *) current_node->data; 841825eb42bSJan Lentfer if (!current_name->hashed_name) { 842825eb42bSJan Lentfer current_name->hashed_name = 843825eb42bSJan Lentfer ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name); 844825eb42bSJan Lentfer } 845825eb42bSJan Lentfer if (ldns_dname_compare(hashed_name, 846825eb42bSJan Lentfer current_name->hashed_name) 847825eb42bSJan Lentfer == 0) { 848825eb42bSJan Lentfer ldns_rdf_deep_free(hashed_name); 849825eb42bSJan Lentfer return current_node; 850825eb42bSJan Lentfer } 851825eb42bSJan Lentfer current_node = ldns_rbtree_next(current_node); 852825eb42bSJan Lentfer } 853825eb42bSJan Lentfer ldns_rdf_deep_free(hashed_name); 854825eb42bSJan Lentfer return NULL; 855825eb42bSJan Lentfer } 856825eb42bSJan Lentfer 857825eb42bSJan Lentfer ldns_status 858825eb42bSJan Lentfer ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) 859825eb42bSJan Lentfer { 860825eb42bSJan Lentfer ldns_status result = LDNS_STATUS_OK; 861825eb42bSJan Lentfer ldns_dnssec_name *cur_name; 862825eb42bSJan Lentfer ldns_rbnode_t *cur_node; 863825eb42bSJan Lentfer ldns_rr_type type_covered = 0; 864825eb42bSJan Lentfer 865825eb42bSJan Lentfer if (!zone || !rr) { 866825eb42bSJan Lentfer return LDNS_STATUS_ERR; 867825eb42bSJan Lentfer } 868825eb42bSJan Lentfer 869825eb42bSJan Lentfer if (!zone->names) { 870825eb42bSJan Lentfer zone->names = ldns_rbtree_create(ldns_dname_compare_v); 871fd185f4dSJan Lentfer if(!zone->names) return LDNS_STATUS_MEM_ERR; 872825eb42bSJan Lentfer } 873825eb42bSJan Lentfer 874825eb42bSJan Lentfer /* we need the original of the hashed name if this is 875825eb42bSJan Lentfer an NSEC3, or an RRSIG that covers an NSEC3 */ 876825eb42bSJan Lentfer if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { 877825eb42bSJan Lentfer type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 878825eb42bSJan Lentfer } 879825eb42bSJan Lentfer if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || 880825eb42bSJan Lentfer type_covered == LDNS_RR_TYPE_NSEC3) { 881825eb42bSJan Lentfer cur_node = ldns_dnssec_zone_find_nsec3_original(zone, 882825eb42bSJan Lentfer rr); 883825eb42bSJan Lentfer if (!cur_node) { 884825eb42bSJan Lentfer return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; 885825eb42bSJan Lentfer } 886825eb42bSJan Lentfer } else { 887825eb42bSJan Lentfer cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); 888825eb42bSJan Lentfer } 889825eb42bSJan Lentfer 890825eb42bSJan Lentfer if (!cur_node) { 891825eb42bSJan Lentfer /* add */ 892825eb42bSJan Lentfer cur_name = ldns_dnssec_name_new_frm_rr(rr); 893fd185f4dSJan Lentfer if(!cur_name) return LDNS_STATUS_MEM_ERR; 894825eb42bSJan Lentfer cur_node = LDNS_MALLOC(ldns_rbnode_t); 895fd185f4dSJan Lentfer if(!cur_node) { 896fd185f4dSJan Lentfer ldns_dnssec_name_free(cur_name); 897fd185f4dSJan Lentfer return LDNS_STATUS_MEM_ERR; 898fd185f4dSJan Lentfer } 899825eb42bSJan Lentfer cur_node->key = ldns_rr_owner(rr); 900825eb42bSJan Lentfer cur_node->data = cur_name; 901fd185f4dSJan Lentfer (void)ldns_rbtree_insert(zone->names, cur_node); 902825eb42bSJan Lentfer } else { 903825eb42bSJan Lentfer cur_name = (ldns_dnssec_name *) cur_node->data; 904fd185f4dSJan Lentfer result = ldns_dnssec_name_add_rr(cur_name, rr); 905825eb42bSJan Lentfer } 906825eb42bSJan Lentfer 907825eb42bSJan Lentfer if (result != LDNS_STATUS_OK) { 908825eb42bSJan Lentfer fprintf(stderr, "error adding rr: "); 909825eb42bSJan Lentfer ldns_rr_print(stderr, rr); 910825eb42bSJan Lentfer } 911825eb42bSJan Lentfer 912825eb42bSJan Lentfer /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/ 913825eb42bSJan Lentfer if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { 914825eb42bSJan Lentfer zone->soa = cur_name; 915825eb42bSJan Lentfer } 916825eb42bSJan Lentfer 917825eb42bSJan Lentfer return result; 918825eb42bSJan Lentfer } 919825eb42bSJan Lentfer 920825eb42bSJan Lentfer void 921b5dedccaSJan Lentfer ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 922b5dedccaSJan Lentfer ldns_rbtree_t *tree, 923b5dedccaSJan Lentfer bool print_soa) 924825eb42bSJan Lentfer { 925825eb42bSJan Lentfer ldns_rbnode_t *node; 926825eb42bSJan Lentfer ldns_dnssec_name *name; 927825eb42bSJan Lentfer 928825eb42bSJan Lentfer node = ldns_rbtree_first(tree); 929825eb42bSJan Lentfer while (node != LDNS_RBTREE_NULL) { 930825eb42bSJan Lentfer name = (ldns_dnssec_name *) node->data; 931b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); 932b5dedccaSJan Lentfer if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 933825eb42bSJan Lentfer fprintf(out, ";\n"); 934825eb42bSJan Lentfer node = ldns_rbtree_next(node); 935825eb42bSJan Lentfer } 936825eb42bSJan Lentfer } 937825eb42bSJan Lentfer 938825eb42bSJan Lentfer void 939b5dedccaSJan Lentfer ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa) 940b5dedccaSJan Lentfer { 941b5dedccaSJan Lentfer ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, 942b5dedccaSJan Lentfer tree, print_soa); 943b5dedccaSJan Lentfer } 944b5dedccaSJan Lentfer 945b5dedccaSJan Lentfer void 946b5dedccaSJan Lentfer ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, 947b5dedccaSJan Lentfer ldns_dnssec_zone *zone) 948825eb42bSJan Lentfer { 949825eb42bSJan Lentfer if (zone) { 950825eb42bSJan Lentfer if (zone->soa) { 951b5dedccaSJan Lentfer if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 952825eb42bSJan Lentfer fprintf(out, ";; Zone: "); 953b5dedccaSJan Lentfer ldns_rdf_print(out, ldns_dnssec_name_name( 954b5dedccaSJan Lentfer zone->soa)); 955825eb42bSJan Lentfer fprintf(out, "\n;\n"); 956b5dedccaSJan Lentfer } 957b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_fmt(out, fmt, 958b5dedccaSJan Lentfer ldns_dnssec_name_find_rrset( 959b5dedccaSJan Lentfer zone->soa, 960825eb42bSJan Lentfer LDNS_RR_TYPE_SOA), 961825eb42bSJan Lentfer false); 962b5dedccaSJan Lentfer if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 963825eb42bSJan Lentfer fprintf(out, ";\n"); 964825eb42bSJan Lentfer } 965825eb42bSJan Lentfer 966825eb42bSJan Lentfer if (zone->names) { 967b5dedccaSJan Lentfer ldns_dnssec_zone_names_print_fmt(out, fmt, 968b5dedccaSJan Lentfer zone->names, false); 969825eb42bSJan Lentfer } 970825eb42bSJan Lentfer } 971825eb42bSJan Lentfer } 972825eb42bSJan Lentfer 973b5dedccaSJan Lentfer void 974b5dedccaSJan Lentfer ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone) 975b5dedccaSJan Lentfer { 976b5dedccaSJan Lentfer ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); 977b5dedccaSJan Lentfer } 978b5dedccaSJan Lentfer 979825eb42bSJan Lentfer ldns_status 980825eb42bSJan Lentfer ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) 981825eb42bSJan Lentfer { 982825eb42bSJan Lentfer ldns_dnssec_name *new_name; 983825eb42bSJan Lentfer ldns_rdf *cur_name; 984825eb42bSJan Lentfer ldns_rdf *next_name; 985825eb42bSJan Lentfer ldns_rbnode_t *cur_node, *next_node, *new_node; 986825eb42bSJan Lentfer 987825eb42bSJan Lentfer /* for the detection */ 988825eb42bSJan Lentfer uint16_t i, cur_label_count, next_label_count; 989825eb42bSJan Lentfer uint16_t soa_label_count = 0; 990825eb42bSJan Lentfer ldns_rdf *l1, *l2; 991825eb42bSJan Lentfer int lpos; 992825eb42bSJan Lentfer 993825eb42bSJan Lentfer if (!zone) { 994825eb42bSJan Lentfer return LDNS_STATUS_ERR; 995825eb42bSJan Lentfer } 996825eb42bSJan Lentfer if (zone->soa && zone->soa->name) { 997825eb42bSJan Lentfer soa_label_count = ldns_dname_label_count(zone->soa->name); 998825eb42bSJan Lentfer } 999825eb42bSJan Lentfer 1000825eb42bSJan Lentfer cur_node = ldns_rbtree_first(zone->names); 1001825eb42bSJan Lentfer while (cur_node != LDNS_RBTREE_NULL) { 1002825eb42bSJan Lentfer next_node = ldns_rbtree_next(cur_node); 1003825eb42bSJan Lentfer 1004825eb42bSJan Lentfer /* skip glue */ 1005825eb42bSJan Lentfer while (next_node != LDNS_RBTREE_NULL && 1006825eb42bSJan Lentfer next_node->data && 1007825eb42bSJan Lentfer ((ldns_dnssec_name *)next_node->data)->is_glue 1008825eb42bSJan Lentfer ) { 1009825eb42bSJan Lentfer next_node = ldns_rbtree_next(next_node); 1010825eb42bSJan Lentfer } 1011825eb42bSJan Lentfer 1012825eb42bSJan Lentfer if (next_node == LDNS_RBTREE_NULL) { 1013825eb42bSJan Lentfer next_node = ldns_rbtree_first(zone->names); 1014825eb42bSJan Lentfer } 1015*d1b2b5caSJohn Marino if (! cur_node->data || ! next_node->data) { 1016*d1b2b5caSJohn Marino return LDNS_STATUS_ERR; 1017*d1b2b5caSJohn Marino } 1018825eb42bSJan Lentfer cur_name = ((ldns_dnssec_name *)cur_node->data)->name; 1019825eb42bSJan Lentfer next_name = ((ldns_dnssec_name *)next_node->data)->name; 1020825eb42bSJan Lentfer cur_label_count = ldns_dname_label_count(cur_name); 1021825eb42bSJan Lentfer next_label_count = ldns_dname_label_count(next_name); 1022825eb42bSJan Lentfer 1023825eb42bSJan Lentfer /* Since the names are in canonical order, we can 1024825eb42bSJan Lentfer * recognize empty non-terminals by their labels; 1025825eb42bSJan Lentfer * every label after the first one on the next owner 1026825eb42bSJan Lentfer * name is a non-terminal if it either does not exist 1027825eb42bSJan Lentfer * in the current name or is different from the same 1028825eb42bSJan Lentfer * label in the current name (counting from the end) 1029825eb42bSJan Lentfer */ 1030825eb42bSJan Lentfer for (i = 1; i < next_label_count - soa_label_count; i++) { 1031fd185f4dSJan Lentfer lpos = (int)cur_label_count - (int)next_label_count + (int)i; 1032825eb42bSJan Lentfer if (lpos >= 0) { 1033b5dedccaSJan Lentfer l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); 1034825eb42bSJan Lentfer } else { 1035825eb42bSJan Lentfer l1 = NULL; 1036825eb42bSJan Lentfer } 1037b5dedccaSJan Lentfer l2 = ldns_dname_clone_from(next_name, i); 1038825eb42bSJan Lentfer 1039825eb42bSJan Lentfer if (!l1 || ldns_dname_compare(l1, l2) != 0) { 1040825eb42bSJan Lentfer /* We have an empty nonterminal, add it to the 1041825eb42bSJan Lentfer * tree 1042825eb42bSJan Lentfer */ 1043825eb42bSJan Lentfer new_name = ldns_dnssec_name_new(); 1044825eb42bSJan Lentfer if (!new_name) { 1045825eb42bSJan Lentfer return LDNS_STATUS_MEM_ERR; 1046825eb42bSJan Lentfer } 1047825eb42bSJan Lentfer new_name->name = ldns_dname_clone_from(next_name, 1048825eb42bSJan Lentfer i); 1049b5dedccaSJan Lentfer if (!new_name->name) { 1050825eb42bSJan Lentfer ldns_dnssec_name_free(new_name); 1051825eb42bSJan Lentfer return LDNS_STATUS_MEM_ERR; 1052825eb42bSJan Lentfer } 1053825eb42bSJan Lentfer new_name->name_alloced = true; 1054825eb42bSJan Lentfer new_node = LDNS_MALLOC(ldns_rbnode_t); 1055825eb42bSJan Lentfer if (!new_node) { 1056825eb42bSJan Lentfer ldns_dnssec_name_free(new_name); 1057825eb42bSJan Lentfer return LDNS_STATUS_MEM_ERR; 1058825eb42bSJan Lentfer } 1059825eb42bSJan Lentfer new_node->key = new_name->name; 1060825eb42bSJan Lentfer new_node->data = new_name; 1061fd185f4dSJan Lentfer (void)ldns_rbtree_insert(zone->names, new_node); 1062825eb42bSJan Lentfer } 1063825eb42bSJan Lentfer ldns_rdf_deep_free(l1); 1064825eb42bSJan Lentfer ldns_rdf_deep_free(l2); 1065825eb42bSJan Lentfer } 1066825eb42bSJan Lentfer 1067825eb42bSJan Lentfer /* we might have inserted a new node after 1068825eb42bSJan Lentfer * the current one so we can't just use next() 1069825eb42bSJan Lentfer */ 1070825eb42bSJan Lentfer if (next_node != ldns_rbtree_first(zone->names)) { 1071825eb42bSJan Lentfer cur_node = next_node; 1072825eb42bSJan Lentfer } else { 1073825eb42bSJan Lentfer cur_node = LDNS_RBTREE_NULL; 1074825eb42bSJan Lentfer } 1075825eb42bSJan Lentfer } 1076825eb42bSJan Lentfer return LDNS_STATUS_OK; 1077825eb42bSJan Lentfer } 1078*d1b2b5caSJohn Marino 1079*d1b2b5caSJohn Marino bool 1080*d1b2b5caSJohn Marino ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone) 1081*d1b2b5caSJohn Marino { 1082*d1b2b5caSJohn Marino ldns_rr* nsec3; 1083*d1b2b5caSJohn Marino ldns_rbnode_t* node; 1084*d1b2b5caSJohn Marino 1085*d1b2b5caSJohn Marino if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) { 1086*d1b2b5caSJohn Marino node = ldns_rbtree_first(zone->names); 1087*d1b2b5caSJohn Marino while (node != LDNS_RBTREE_NULL) { 1088*d1b2b5caSJohn Marino nsec3 = ((ldns_dnssec_name*)node->data)->nsec; 1089*d1b2b5caSJohn Marino if (nsec3 &&ldns_rr_get_type(nsec3) 1090*d1b2b5caSJohn Marino == LDNS_RR_TYPE_NSEC3 && 1091*d1b2b5caSJohn Marino ldns_nsec3_optout(nsec3)) { 1092*d1b2b5caSJohn Marino return true; 1093*d1b2b5caSJohn Marino } 1094*d1b2b5caSJohn Marino node = ldns_rbtree_next(node); 1095*d1b2b5caSJohn Marino } 1096*d1b2b5caSJohn Marino } 1097*d1b2b5caSJohn Marino return false; 1098*d1b2b5caSJohn Marino } 1099