dnssec_zone.c revision 238104
1238104Sdes/* 2238104Sdes * special zone file structures and functions for better dnssec handling 3238104Sdes */ 4238104Sdes 5238104Sdes#include <ldns/config.h> 6238104Sdes 7238104Sdes#include <ldns/ldns.h> 8238104Sdes 9238104Sdesldns_dnssec_rrs * 10238104Sdesldns_dnssec_rrs_new() 11238104Sdes{ 12238104Sdes ldns_dnssec_rrs *new_rrs; 13238104Sdes new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); 14238104Sdes if(!new_rrs) return NULL; 15238104Sdes new_rrs->rr = NULL; 16238104Sdes new_rrs->next = NULL; 17238104Sdes return new_rrs; 18238104Sdes} 19238104Sdes 20238104SdesINLINE void 21238104Sdesldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep) 22238104Sdes{ 23238104Sdes ldns_dnssec_rrs *next; 24238104Sdes while (rrs) { 25238104Sdes next = rrs->next; 26238104Sdes if (deep) { 27238104Sdes ldns_rr_free(rrs->rr); 28238104Sdes } 29238104Sdes LDNS_FREE(rrs); 30238104Sdes rrs = next; 31238104Sdes } 32238104Sdes} 33238104Sdes 34238104Sdesvoid 35238104Sdesldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs) 36238104Sdes{ 37238104Sdes ldns_dnssec_rrs_free_internal(rrs, 0); 38238104Sdes} 39238104Sdes 40238104Sdesvoid 41238104Sdesldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs) 42238104Sdes{ 43238104Sdes ldns_dnssec_rrs_free_internal(rrs, 1); 44238104Sdes} 45238104Sdes 46238104Sdesldns_status 47238104Sdesldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) 48238104Sdes{ 49238104Sdes int cmp; 50238104Sdes ldns_dnssec_rrs *new_rrs; 51238104Sdes if (!rrs || !rr) { 52238104Sdes return LDNS_STATUS_ERR; 53238104Sdes } 54238104Sdes 55238104Sdes /* this could be done more efficiently; name and type should already 56238104Sdes be equal */ 57238104Sdes cmp = ldns_rr_compare(rrs->rr, 58238104Sdes rr); 59238104Sdes /* should we error on equal? */ 60238104Sdes if (cmp <= 0) { 61238104Sdes if (rrs->next) { 62238104Sdes return ldns_dnssec_rrs_add_rr(rrs->next, rr); 63238104Sdes } else { 64238104Sdes new_rrs = ldns_dnssec_rrs_new(); 65238104Sdes new_rrs->rr = rr; 66238104Sdes rrs->next = new_rrs; 67238104Sdes } 68238104Sdes } else if (cmp > 0) { 69238104Sdes /* put the current old rr in the new next, put the new 70238104Sdes rr in the current container */ 71238104Sdes new_rrs = ldns_dnssec_rrs_new(); 72238104Sdes new_rrs->rr = rrs->rr; 73238104Sdes new_rrs->next = rrs->next; 74238104Sdes rrs->rr = rr; 75238104Sdes rrs->next = new_rrs; 76238104Sdes } 77238104Sdes return LDNS_STATUS_OK; 78238104Sdes} 79238104Sdes 80238104Sdesvoid 81238104Sdesldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, 82238104Sdes ldns_dnssec_rrs *rrs) 83238104Sdes{ 84238104Sdes if (!rrs) { 85238104Sdes if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 86238104Sdes fprintf(out, "; <void>"); 87238104Sdes } else { 88238104Sdes if (rrs->rr) { 89238104Sdes ldns_rr_print_fmt(out, fmt, rrs->rr); 90238104Sdes } 91238104Sdes if (rrs->next) { 92238104Sdes ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next); 93238104Sdes } 94238104Sdes } 95238104Sdes} 96238104Sdes 97238104Sdesvoid 98238104Sdesldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs) 99238104Sdes{ 100238104Sdes ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs); 101238104Sdes} 102238104Sdes 103238104Sdes 104238104Sdesldns_dnssec_rrsets * 105238104Sdesldns_dnssec_rrsets_new() 106238104Sdes{ 107238104Sdes ldns_dnssec_rrsets *new_rrsets; 108238104Sdes new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); 109238104Sdes if(!new_rrsets) return NULL; 110238104Sdes new_rrsets->rrs = NULL; 111238104Sdes new_rrsets->type = 0; 112238104Sdes new_rrsets->signatures = NULL; 113238104Sdes new_rrsets->next = NULL; 114238104Sdes return new_rrsets; 115238104Sdes} 116238104Sdes 117238104SdesINLINE void 118238104Sdesldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep) 119238104Sdes{ 120238104Sdes if (rrsets) { 121238104Sdes if (rrsets->rrs) { 122238104Sdes ldns_dnssec_rrs_free_internal(rrsets->rrs, deep); 123238104Sdes } 124238104Sdes if (rrsets->next) { 125238104Sdes ldns_dnssec_rrsets_free_internal(rrsets->next, deep); 126238104Sdes } 127238104Sdes if (rrsets->signatures) { 128238104Sdes ldns_dnssec_rrs_free_internal(rrsets->signatures, deep); 129238104Sdes } 130238104Sdes LDNS_FREE(rrsets); 131238104Sdes } 132238104Sdes} 133238104Sdes 134238104Sdesvoid 135238104Sdesldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets) 136238104Sdes{ 137238104Sdes ldns_dnssec_rrsets_free_internal(rrsets, 0); 138238104Sdes} 139238104Sdes 140238104Sdesvoid 141238104Sdesldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets) 142238104Sdes{ 143238104Sdes ldns_dnssec_rrsets_free_internal(rrsets, 1); 144238104Sdes} 145238104Sdes 146238104Sdesldns_rr_type 147238104Sdesldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets) 148238104Sdes{ 149238104Sdes if (rrsets) { 150238104Sdes return rrsets->type; 151238104Sdes } else { 152238104Sdes return 0; 153238104Sdes } 154238104Sdes} 155238104Sdes 156238104Sdesldns_status 157238104Sdesldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 158238104Sdes ldns_rr_type type) 159238104Sdes{ 160238104Sdes if (rrsets) { 161238104Sdes rrsets->type = type; 162238104Sdes return LDNS_STATUS_OK; 163238104Sdes } 164238104Sdes return LDNS_STATUS_ERR; 165238104Sdes} 166238104Sdes 167238104Sdesldns_dnssec_rrsets * 168238104Sdesldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) 169238104Sdes{ 170238104Sdes ldns_dnssec_rrsets *new_rrsets; 171238104Sdes ldns_rr_type rr_type; 172238104Sdes bool rrsig; 173238104Sdes 174238104Sdes new_rrsets = ldns_dnssec_rrsets_new(); 175238104Sdes rr_type = ldns_rr_get_type(rr); 176238104Sdes if (rr_type == LDNS_RR_TYPE_RRSIG) { 177238104Sdes rrsig = true; 178238104Sdes rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 179238104Sdes } else { 180238104Sdes rrsig = false; 181238104Sdes } 182238104Sdes if (!rrsig) { 183238104Sdes new_rrsets->rrs = ldns_dnssec_rrs_new(); 184238104Sdes new_rrsets->rrs->rr = rr; 185238104Sdes } else { 186238104Sdes new_rrsets->signatures = ldns_dnssec_rrs_new(); 187238104Sdes new_rrsets->signatures->rr = rr; 188238104Sdes } 189238104Sdes new_rrsets->type = rr_type; 190238104Sdes return new_rrsets; 191238104Sdes} 192238104Sdes 193238104Sdesldns_status 194238104Sdesldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) 195238104Sdes{ 196238104Sdes ldns_dnssec_rrsets *new_rrsets; 197238104Sdes ldns_rr_type rr_type; 198238104Sdes bool rrsig = false; 199238104Sdes ldns_status result = LDNS_STATUS_OK; 200238104Sdes 201238104Sdes if (!rrsets || !rr) { 202238104Sdes return LDNS_STATUS_ERR; 203238104Sdes } 204238104Sdes 205238104Sdes rr_type = ldns_rr_get_type(rr); 206238104Sdes 207238104Sdes if (rr_type == LDNS_RR_TYPE_RRSIG) { 208238104Sdes rrsig = true; 209238104Sdes rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 210238104Sdes } 211238104Sdes 212238104Sdes if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { 213238104Sdes if (!rrsig) { 214238104Sdes rrsets->rrs = ldns_dnssec_rrs_new(); 215238104Sdes rrsets->rrs->rr = rr; 216238104Sdes rrsets->type = rr_type; 217238104Sdes } else { 218238104Sdes rrsets->signatures = ldns_dnssec_rrs_new(); 219238104Sdes rrsets->signatures->rr = rr; 220238104Sdes rrsets->type = rr_type; 221238104Sdes } 222238104Sdes return LDNS_STATUS_OK; 223238104Sdes } 224238104Sdes 225238104Sdes if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { 226238104Sdes if (rrsets->next) { 227238104Sdes result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); 228238104Sdes } else { 229238104Sdes new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); 230238104Sdes rrsets->next = new_rrsets; 231238104Sdes } 232238104Sdes } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { 233238104Sdes /* move the current one into the new next, 234238104Sdes replace field of current with data from new rr */ 235238104Sdes new_rrsets = ldns_dnssec_rrsets_new(); 236238104Sdes new_rrsets->rrs = rrsets->rrs; 237238104Sdes new_rrsets->type = rrsets->type; 238238104Sdes new_rrsets->signatures = rrsets->signatures; 239238104Sdes new_rrsets->next = rrsets->next; 240238104Sdes if (!rrsig) { 241238104Sdes rrsets->rrs = ldns_dnssec_rrs_new(); 242238104Sdes rrsets->rrs->rr = rr; 243238104Sdes rrsets->signatures = NULL; 244238104Sdes } else { 245238104Sdes rrsets->rrs = NULL; 246238104Sdes rrsets->signatures = ldns_dnssec_rrs_new(); 247238104Sdes rrsets->signatures->rr = rr; 248238104Sdes } 249238104Sdes rrsets->type = rr_type; 250238104Sdes rrsets->next = new_rrsets; 251238104Sdes } else { 252238104Sdes /* equal, add to current rrsets */ 253238104Sdes if (rrsig) { 254238104Sdes if (rrsets->signatures) { 255238104Sdes result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); 256238104Sdes } else { 257238104Sdes rrsets->signatures = ldns_dnssec_rrs_new(); 258238104Sdes rrsets->signatures->rr = rr; 259238104Sdes } 260238104Sdes } else { 261238104Sdes if (rrsets->rrs) { 262238104Sdes result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); 263238104Sdes } else { 264238104Sdes rrsets->rrs = ldns_dnssec_rrs_new(); 265238104Sdes rrsets->rrs->rr = rr; 266238104Sdes } 267238104Sdes } 268238104Sdes } 269238104Sdes 270238104Sdes return result; 271238104Sdes} 272238104Sdes 273238104Sdesvoid 274238104Sdesldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 275238104Sdes ldns_dnssec_rrsets *rrsets, 276238104Sdes bool follow, 277238104Sdes bool show_soa) 278238104Sdes{ 279238104Sdes if (!rrsets) { 280238104Sdes if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 281238104Sdes fprintf(out, "; <void>\n"); 282238104Sdes } else { 283238104Sdes if (rrsets->rrs && 284238104Sdes (show_soa || 285238104Sdes ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA 286238104Sdes ) 287238104Sdes ) { 288238104Sdes ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs); 289238104Sdes if (rrsets->signatures) { 290238104Sdes ldns_dnssec_rrs_print_fmt(out, fmt, 291238104Sdes rrsets->signatures); 292238104Sdes } 293238104Sdes } 294238104Sdes if (follow && rrsets->next) { 295238104Sdes ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 296238104Sdes rrsets->next, follow, show_soa); 297238104Sdes } 298238104Sdes } 299238104Sdes} 300238104Sdes 301238104Sdesvoid 302238104Sdesldns_dnssec_rrsets_print_soa(FILE *out, 303238104Sdes ldns_dnssec_rrsets *rrsets, 304238104Sdes bool follow, 305238104Sdes bool show_soa) 306238104Sdes{ 307238104Sdes ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default, 308238104Sdes rrsets, follow, show_soa); 309238104Sdes} 310238104Sdes 311238104Sdes 312238104Sdesvoid 313238104Sdesldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, 314238104Sdes ldns_dnssec_rrsets *rrsets, 315238104Sdes bool follow) 316238104Sdes{ 317238104Sdes ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true); 318238104Sdes} 319238104Sdes 320238104Sdesvoid 321238104Sdesldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow) 322238104Sdes{ 323238104Sdes ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 324238104Sdes rrsets, follow); 325238104Sdes} 326238104Sdes 327238104Sdesldns_dnssec_name * 328238104Sdesldns_dnssec_name_new() 329238104Sdes{ 330238104Sdes ldns_dnssec_name *new_name; 331238104Sdes 332238104Sdes new_name = LDNS_CALLOC(ldns_dnssec_name, 1); 333238104Sdes if (!new_name) { 334238104Sdes return NULL; 335238104Sdes } 336238104Sdes /* 337238104Sdes * not needed anymore because CALLOC initalizes everything to zero. 338238104Sdes 339238104Sdes new_name->name = NULL; 340238104Sdes new_name->rrsets = NULL; 341238104Sdes new_name->name_alloced = false; 342238104Sdes new_name->nsec = NULL; 343238104Sdes new_name->nsec_signatures = NULL; 344238104Sdes 345238104Sdes new_name->is_glue = false; 346238104Sdes new_name->hashed_name = NULL; 347238104Sdes 348238104Sdes */ 349238104Sdes return new_name; 350238104Sdes} 351238104Sdes 352238104Sdesldns_dnssec_name * 353238104Sdesldns_dnssec_name_new_frm_rr(ldns_rr *rr) 354238104Sdes{ 355238104Sdes ldns_dnssec_name *new_name = ldns_dnssec_name_new(); 356238104Sdes 357238104Sdes new_name->name = ldns_rr_owner(rr); 358238104Sdes if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) { 359238104Sdes ldns_dnssec_name_free(new_name); 360238104Sdes return NULL; 361238104Sdes } 362238104Sdes 363238104Sdes return new_name; 364238104Sdes} 365238104Sdes 366238104SdesINLINE void 367238104Sdesldns_dnssec_name_free_internal(ldns_dnssec_name *name, 368238104Sdes int deep) 369238104Sdes{ 370238104Sdes if (name) { 371238104Sdes if (name->name_alloced) { 372238104Sdes ldns_rdf_deep_free(name->name); 373238104Sdes } 374238104Sdes if (name->rrsets) { 375238104Sdes ldns_dnssec_rrsets_free_internal(name->rrsets, deep); 376238104Sdes } 377238104Sdes if (name->nsec && deep) { 378238104Sdes ldns_rr_free(name->nsec); 379238104Sdes } 380238104Sdes if (name->nsec_signatures) { 381238104Sdes ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); 382238104Sdes } 383238104Sdes if (name->hashed_name) { 384238104Sdes if (deep) { 385238104Sdes ldns_rdf_deep_free(name->hashed_name); 386238104Sdes } 387238104Sdes } 388238104Sdes LDNS_FREE(name); 389238104Sdes } 390238104Sdes} 391238104Sdes 392238104Sdesvoid 393238104Sdesldns_dnssec_name_free(ldns_dnssec_name *name) 394238104Sdes{ 395238104Sdes ldns_dnssec_name_free_internal(name, 0); 396238104Sdes} 397238104Sdes 398238104Sdesvoid 399238104Sdesldns_dnssec_name_deep_free(ldns_dnssec_name *name) 400238104Sdes{ 401238104Sdes ldns_dnssec_name_free_internal(name, 1); 402238104Sdes} 403238104Sdes 404238104Sdesldns_rdf * 405238104Sdesldns_dnssec_name_name(ldns_dnssec_name *name) 406238104Sdes{ 407238104Sdes if (name) { 408238104Sdes return name->name; 409238104Sdes } 410238104Sdes return NULL; 411238104Sdes} 412238104Sdes 413238104Sdesbool 414238104Sdesldns_dnssec_name_is_glue(ldns_dnssec_name *name) 415238104Sdes{ 416238104Sdes if (name) { 417238104Sdes return name->is_glue; 418238104Sdes } 419238104Sdes return false; 420238104Sdes} 421238104Sdes 422238104Sdesvoid 423238104Sdesldns_dnssec_name_set_name(ldns_dnssec_name *rrset, 424238104Sdes ldns_rdf *dname) 425238104Sdes{ 426238104Sdes if (rrset && dname) { 427238104Sdes rrset->name = dname; 428238104Sdes } 429238104Sdes} 430238104Sdes 431238104Sdesldns_rr * 432238104Sdesldns_dnssec_name_nsec(ldns_dnssec_name *rrset) 433238104Sdes{ 434238104Sdes if (rrset) { 435238104Sdes return rrset->nsec; 436238104Sdes } 437238104Sdes return NULL; 438238104Sdes} 439238104Sdes 440238104Sdesvoid 441238104Sdesldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) 442238104Sdes{ 443238104Sdes if (rrset && nsec) { 444238104Sdes rrset->nsec = nsec; 445238104Sdes } 446238104Sdes} 447238104Sdes 448238104Sdesint 449238104Sdesldns_dnssec_name_cmp(const void *a, const void *b) 450238104Sdes{ 451238104Sdes ldns_dnssec_name *na = (ldns_dnssec_name *) a; 452238104Sdes ldns_dnssec_name *nb = (ldns_dnssec_name *) b; 453238104Sdes 454238104Sdes if (na && nb) { 455238104Sdes return ldns_dname_compare(ldns_dnssec_name_name(na), 456238104Sdes ldns_dnssec_name_name(nb)); 457238104Sdes } else if (na) { 458238104Sdes return 1; 459238104Sdes } else if (nb) { 460238104Sdes return -1; 461238104Sdes } else { 462238104Sdes return 0; 463238104Sdes } 464238104Sdes} 465238104Sdes 466238104Sdesldns_status 467238104Sdesldns_dnssec_name_add_rr(ldns_dnssec_name *name, 468238104Sdes ldns_rr *rr) 469238104Sdes{ 470238104Sdes ldns_status result = LDNS_STATUS_OK; 471238104Sdes ldns_rdf *name_name; 472238104Sdes bool hashed_name = false; 473238104Sdes ldns_rr_type rr_type; 474238104Sdes ldns_rr_type typecovered = 0; 475238104Sdes 476238104Sdes /* special handling for NSEC3 and NSECX covering RRSIGS */ 477238104Sdes 478238104Sdes if (!name || !rr) { 479238104Sdes return LDNS_STATUS_ERR; 480238104Sdes } 481238104Sdes 482238104Sdes rr_type = ldns_rr_get_type(rr); 483238104Sdes 484238104Sdes if (rr_type == LDNS_RR_TYPE_RRSIG) { 485238104Sdes typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 486238104Sdes } 487238104Sdes 488238104Sdes#ifdef HAVE_SSL 489238104Sdes if (rr_type == LDNS_RR_TYPE_NSEC3 || 490238104Sdes typecovered == LDNS_RR_TYPE_NSEC3) { 491238104Sdes name_name = ldns_nsec3_hash_name_frm_nsec3(rr, 492238104Sdes ldns_dnssec_name_name(name)); 493238104Sdes hashed_name = true; 494238104Sdes } else { 495238104Sdes name_name = ldns_dnssec_name_name(name); 496238104Sdes } 497238104Sdes#else 498238104Sdes name_name = ldns_dnssec_name_name(name); 499238104Sdes#endif /* HAVE_SSL */ 500238104Sdes 501238104Sdes if (rr_type == LDNS_RR_TYPE_NSEC || 502238104Sdes rr_type == LDNS_RR_TYPE_NSEC3) { 503238104Sdes /* XX check if is already set (and error?) */ 504238104Sdes name->nsec = rr; 505238104Sdes } else if (typecovered == LDNS_RR_TYPE_NSEC || 506238104Sdes typecovered == LDNS_RR_TYPE_NSEC3) { 507238104Sdes if (name->nsec_signatures) { 508238104Sdes result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); 509238104Sdes } else { 510238104Sdes name->nsec_signatures = ldns_dnssec_rrs_new(); 511238104Sdes name->nsec_signatures->rr = rr; 512238104Sdes } 513238104Sdes } else { 514238104Sdes /* it's a 'normal' RR, add it to the right rrset */ 515238104Sdes if (name->rrsets) { 516238104Sdes result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 517238104Sdes } else { 518238104Sdes name->rrsets = ldns_dnssec_rrsets_new(); 519238104Sdes result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 520238104Sdes } 521238104Sdes } 522238104Sdes 523238104Sdes if (hashed_name) { 524238104Sdes ldns_rdf_deep_free(name_name); 525238104Sdes } 526238104Sdes 527238104Sdes return result; 528238104Sdes} 529238104Sdes 530238104Sdesldns_dnssec_rrsets * 531238104Sdesldns_dnssec_name_find_rrset(ldns_dnssec_name *name, 532238104Sdes ldns_rr_type type) { 533238104Sdes ldns_dnssec_rrsets *result; 534238104Sdes 535238104Sdes result = name->rrsets; 536238104Sdes while (result) { 537238104Sdes if (result->type == type) { 538238104Sdes return result; 539238104Sdes } else { 540238104Sdes result = result->next; 541238104Sdes } 542238104Sdes } 543238104Sdes return NULL; 544238104Sdes} 545238104Sdes 546238104Sdesldns_dnssec_rrsets * 547238104Sdesldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, 548238104Sdes ldns_rdf *dname, 549238104Sdes ldns_rr_type type) 550238104Sdes{ 551238104Sdes ldns_rbnode_t *node; 552238104Sdes 553238104Sdes if (!zone || !dname) { 554238104Sdes return NULL; 555238104Sdes } 556238104Sdes 557238104Sdes node = ldns_rbtree_search(zone->names, dname); 558238104Sdes if (node) { 559238104Sdes return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data, 560238104Sdes type); 561238104Sdes } else { 562238104Sdes return NULL; 563238104Sdes } 564238104Sdes} 565238104Sdes 566238104Sdesvoid 567238104Sdesldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 568238104Sdes ldns_dnssec_name *name, 569238104Sdes bool show_soa) 570238104Sdes{ 571238104Sdes if (name) { 572238104Sdes if(name->rrsets) { 573238104Sdes ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 574238104Sdes name->rrsets, true, show_soa); 575238104Sdes } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 576238104Sdes fprintf(out, ";; Empty nonterminal: "); 577238104Sdes ldns_rdf_print(out, name->name); 578238104Sdes fprintf(out, "\n"); 579238104Sdes } 580238104Sdes if(name->nsec) { 581238104Sdes ldns_rr_print_fmt(out, fmt, name->nsec); 582238104Sdes } 583238104Sdes if (name->nsec_signatures) { 584238104Sdes ldns_dnssec_rrs_print_fmt(out, fmt, 585238104Sdes name->nsec_signatures); 586238104Sdes } 587238104Sdes } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 588238104Sdes fprintf(out, "; <void>\n"); 589238104Sdes } 590238104Sdes} 591238104Sdes 592238104Sdesvoid 593238104Sdesldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa) 594238104Sdes{ 595238104Sdes ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default, 596238104Sdes name, show_soa); 597238104Sdes} 598238104Sdes 599238104Sdesvoid 600238104Sdesldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, 601238104Sdes ldns_dnssec_name *name) 602238104Sdes{ 603238104Sdes ldns_dnssec_name_print_soa_fmt(out, fmt, name, true); 604238104Sdes} 605238104Sdes 606238104Sdesvoid 607238104Sdesldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name) 608238104Sdes{ 609238104Sdes ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name); 610238104Sdes} 611238104Sdes 612238104Sdes 613238104Sdesldns_dnssec_zone * 614238104Sdesldns_dnssec_zone_new() 615238104Sdes{ 616238104Sdes ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); 617238104Sdes if(!zone) return NULL; 618238104Sdes zone->soa = NULL; 619238104Sdes zone->names = NULL; 620238104Sdes 621238104Sdes return zone; 622238104Sdes} 623238104Sdes 624238104Sdesstatic bool 625238104Sdesrr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) 626238104Sdes{ 627238104Sdes return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG 628238104Sdes && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t; 629238104Sdes} 630238104Sdes 631238104Sdes/* When the zone is first read into an list and then inserted into an 632238104Sdes * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next) 633238104Sdes * to each other. Because ldns-verify-zone (the only program that uses this 634238104Sdes * function) uses the rbtree mostly for sequentual walking, this results 635238104Sdes * in a speed increase (of 15% on linux) because we have less CPU-cache misses. 636238104Sdes */ 637238104Sdes#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */ 638238104Sdes 639238104Sdesldns_status 640238104Sdesldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, 641238104Sdes uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) 642238104Sdes{ 643238104Sdes ldns_rr* cur_rr; 644238104Sdes size_t i; 645238104Sdes 646238104Sdes ldns_rdf *my_origin = NULL; 647238104Sdes ldns_rdf *my_prev = NULL; 648238104Sdes 649238104Sdes ldns_dnssec_zone *newzone = ldns_dnssec_zone_new(); 650238104Sdes /* when reading NSEC3s, there is a chance that we encounter nsecs 651238104Sdes for empty nonterminals, whose nonterminals we cannot derive yet 652238104Sdes because the needed information is to be read later. in that case 653238104Sdes we keep a list of those nsec3's and retry to add them later */ 654238104Sdes ldns_rr_list* todo_nsec3s = ldns_rr_list_new(); 655238104Sdes ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); 656238104Sdes 657238104Sdes ldns_status status = LDNS_STATUS_MEM_ERR; 658238104Sdes 659238104Sdes#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 660238104Sdes ldns_zone* zone = NULL; 661238104Sdes if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr) 662238104Sdes != LDNS_STATUS_OK) goto error; 663238104Sdes#else 664238104Sdes uint32_t my_ttl = ttl; 665238104Sdes#endif 666238104Sdes 667238104Sdes if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error; 668238104Sdes 669238104Sdes if (origin) { 670238104Sdes if (!(my_origin = ldns_rdf_clone(origin))) goto error; 671238104Sdes if (!(my_prev = ldns_rdf_clone(origin))) goto error; 672238104Sdes } 673238104Sdes 674238104Sdes#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 675238104Sdes if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone)) 676238104Sdes != LDNS_STATUS_OK) goto error; 677238104Sdes 678238104Sdes for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 679238104Sdes cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); 680238104Sdes status = LDNS_STATUS_OK; 681238104Sdes#else 682238104Sdes while (!feof(fp)) { 683238104Sdes status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, 684238104Sdes &my_prev, line_nr); 685238104Sdes 686238104Sdes#endif 687238104Sdes switch (status) { 688238104Sdes case LDNS_STATUS_OK: 689238104Sdes 690238104Sdes status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 691238104Sdes if (status == 692238104Sdes LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { 693238104Sdes 694238104Sdes if (rr_is_rrsig_covering(cur_rr, 695238104Sdes LDNS_RR_TYPE_NSEC3)){ 696238104Sdes ldns_rr_list_push_rr(todo_nsec3_rrsigs, 697238104Sdes cur_rr); 698238104Sdes } else { 699238104Sdes ldns_rr_list_push_rr(todo_nsec3s, 700238104Sdes cur_rr); 701238104Sdes } 702238104Sdes } else if (status != LDNS_STATUS_OK) 703238104Sdes goto error; 704238104Sdes 705238104Sdes break; 706238104Sdes 707238104Sdes 708238104Sdes case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ 709238104Sdes case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ 710238104Sdes case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ 711238104Sdes break; 712238104Sdes 713238104Sdes case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ 714238104Sdes status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; 715238104Sdes break; 716238104Sdes 717238104Sdes default: 718238104Sdes goto error; 719238104Sdes } 720238104Sdes } 721238104Sdes 722238104Sdes if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { 723238104Sdes (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); 724238104Sdes for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) { 725238104Sdes cur_rr = ldns_rr_list_rr(todo_nsec3s, i); 726238104Sdes status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 727238104Sdes } 728238104Sdes for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ 729238104Sdes cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); 730238104Sdes status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 731238104Sdes } 732238104Sdes } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { 733238104Sdes for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ 734238104Sdes cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); 735238104Sdes status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 736238104Sdes } 737238104Sdes } 738238104Sdes 739238104Sdes ldns_rr_list_free(todo_nsec3_rrsigs); 740238104Sdes ldns_rr_list_free(todo_nsec3s); 741238104Sdes 742238104Sdes if (z) { 743238104Sdes *z = newzone; 744238104Sdes } else { 745238104Sdes ldns_dnssec_zone_free(newzone); 746238104Sdes } 747238104Sdes 748238104Sdes return LDNS_STATUS_OK; 749238104Sdes 750238104Sdeserror: 751238104Sdes#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 752238104Sdes if (zone) { 753238104Sdes ldns_zone_free(zone); 754238104Sdes } 755238104Sdes#endif 756238104Sdes if (my_origin) { 757238104Sdes ldns_rdf_deep_free(my_origin); 758238104Sdes } 759238104Sdes if (my_prev) { 760238104Sdes ldns_rdf_deep_free(my_prev); 761238104Sdes } 762238104Sdes if (newzone) { 763238104Sdes ldns_dnssec_zone_free(newzone); 764238104Sdes } 765238104Sdes return status; 766238104Sdes} 767238104Sdes 768238104Sdesldns_status 769238104Sdesldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, 770238104Sdes uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) 771238104Sdes{ 772238104Sdes return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); 773238104Sdes} 774238104Sdes 775238104Sdesvoid 776238104Sdesldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { 777238104Sdes (void) arg; 778238104Sdes ldns_dnssec_name_free((ldns_dnssec_name *)node->data); 779238104Sdes LDNS_FREE(node); 780238104Sdes} 781238104Sdes 782238104Sdesvoid 783238104Sdesldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { 784238104Sdes (void) arg; 785238104Sdes ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); 786238104Sdes LDNS_FREE(node); 787238104Sdes} 788238104Sdes 789238104Sdesvoid 790238104Sdesldns_dnssec_zone_free(ldns_dnssec_zone *zone) 791238104Sdes{ 792238104Sdes if (zone) { 793238104Sdes if (zone->names) { 794238104Sdes /* destroy all name structures within the tree */ 795238104Sdes ldns_traverse_postorder(zone->names, 796238104Sdes ldns_dnssec_name_node_free, 797238104Sdes NULL); 798238104Sdes LDNS_FREE(zone->names); 799238104Sdes } 800238104Sdes LDNS_FREE(zone); 801238104Sdes } 802238104Sdes} 803238104Sdes 804238104Sdesvoid 805238104Sdesldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) 806238104Sdes{ 807238104Sdes if (zone) { 808238104Sdes if (zone->names) { 809238104Sdes /* destroy all name structures within the tree */ 810238104Sdes ldns_traverse_postorder(zone->names, 811238104Sdes ldns_dnssec_name_node_deep_free, 812238104Sdes NULL); 813238104Sdes LDNS_FREE(zone->names); 814238104Sdes } 815238104Sdes LDNS_FREE(zone); 816238104Sdes } 817238104Sdes} 818238104Sdes 819238104Sdes/* use for dname comparison in tree */ 820238104Sdesint 821238104Sdesldns_dname_compare_v(const void *a, const void *b) { 822238104Sdes return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); 823238104Sdes} 824238104Sdes 825238104Sdes#ifdef HAVE_SSL 826238104Sdesldns_rbnode_t * 827238104Sdesldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, 828238104Sdes ldns_rr *rr) { 829238104Sdes ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names); 830238104Sdes ldns_dnssec_name *current_name; 831238104Sdes ldns_rdf *hashed_name; 832238104Sdes 833238104Sdes hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); 834238104Sdes 835238104Sdes while (current_node != LDNS_RBTREE_NULL) { 836238104Sdes current_name = (ldns_dnssec_name *) current_node->data; 837238104Sdes if (!current_name->hashed_name) { 838238104Sdes current_name->hashed_name = 839238104Sdes ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name); 840238104Sdes } 841238104Sdes if (ldns_dname_compare(hashed_name, 842238104Sdes current_name->hashed_name) 843238104Sdes == 0) { 844238104Sdes ldns_rdf_deep_free(hashed_name); 845238104Sdes return current_node; 846238104Sdes } 847238104Sdes current_node = ldns_rbtree_next(current_node); 848238104Sdes } 849238104Sdes ldns_rdf_deep_free(hashed_name); 850238104Sdes return NULL; 851238104Sdes} 852238104Sdes 853238104Sdesldns_status 854238104Sdesldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) 855238104Sdes{ 856238104Sdes ldns_status result = LDNS_STATUS_OK; 857238104Sdes ldns_dnssec_name *cur_name; 858238104Sdes ldns_rbnode_t *cur_node; 859238104Sdes ldns_rr_type type_covered = 0; 860238104Sdes 861238104Sdes if (!zone || !rr) { 862238104Sdes return LDNS_STATUS_ERR; 863238104Sdes } 864238104Sdes 865238104Sdes if (!zone->names) { 866238104Sdes zone->names = ldns_rbtree_create(ldns_dname_compare_v); 867238104Sdes if(!zone->names) return LDNS_STATUS_MEM_ERR; 868238104Sdes } 869238104Sdes 870238104Sdes /* we need the original of the hashed name if this is 871238104Sdes an NSEC3, or an RRSIG that covers an NSEC3 */ 872238104Sdes if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { 873238104Sdes type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 874238104Sdes } 875238104Sdes if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || 876238104Sdes type_covered == LDNS_RR_TYPE_NSEC3) { 877238104Sdes cur_node = ldns_dnssec_zone_find_nsec3_original(zone, 878238104Sdes rr); 879238104Sdes if (!cur_node) { 880238104Sdes return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; 881238104Sdes } 882238104Sdes } else { 883238104Sdes cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); 884238104Sdes } 885238104Sdes 886238104Sdes if (!cur_node) { 887238104Sdes /* add */ 888238104Sdes cur_name = ldns_dnssec_name_new_frm_rr(rr); 889238104Sdes if(!cur_name) return LDNS_STATUS_MEM_ERR; 890238104Sdes cur_node = LDNS_MALLOC(ldns_rbnode_t); 891238104Sdes if(!cur_node) { 892238104Sdes ldns_dnssec_name_free(cur_name); 893238104Sdes return LDNS_STATUS_MEM_ERR; 894238104Sdes } 895238104Sdes cur_node->key = ldns_rr_owner(rr); 896238104Sdes cur_node->data = cur_name; 897238104Sdes (void)ldns_rbtree_insert(zone->names, cur_node); 898238104Sdes } else { 899238104Sdes cur_name = (ldns_dnssec_name *) cur_node->data; 900238104Sdes result = ldns_dnssec_name_add_rr(cur_name, rr); 901238104Sdes } 902238104Sdes 903238104Sdes if (result != LDNS_STATUS_OK) { 904238104Sdes fprintf(stderr, "error adding rr: "); 905238104Sdes ldns_rr_print(stderr, rr); 906238104Sdes } 907238104Sdes 908238104Sdes /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/ 909238104Sdes if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { 910238104Sdes zone->soa = cur_name; 911238104Sdes } 912238104Sdes 913238104Sdes return result; 914238104Sdes} 915238104Sdes#endif /* HAVE_SSL */ 916238104Sdes 917238104Sdesvoid 918238104Sdesldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 919238104Sdes ldns_rbtree_t *tree, 920238104Sdes bool print_soa) 921238104Sdes{ 922238104Sdes ldns_rbnode_t *node; 923238104Sdes ldns_dnssec_name *name; 924238104Sdes 925238104Sdes node = ldns_rbtree_first(tree); 926238104Sdes while (node != LDNS_RBTREE_NULL) { 927238104Sdes name = (ldns_dnssec_name *) node->data; 928238104Sdes ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); 929238104Sdes if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 930238104Sdes fprintf(out, ";\n"); 931238104Sdes node = ldns_rbtree_next(node); 932238104Sdes } 933238104Sdes} 934238104Sdes 935238104Sdesvoid 936238104Sdesldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa) 937238104Sdes{ 938238104Sdes ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, 939238104Sdes tree, print_soa); 940238104Sdes} 941238104Sdes 942238104Sdesvoid 943238104Sdesldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, 944238104Sdes ldns_dnssec_zone *zone) 945238104Sdes{ 946238104Sdes if (zone) { 947238104Sdes if (zone->soa) { 948238104Sdes if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 949238104Sdes fprintf(out, ";; Zone: "); 950238104Sdes ldns_rdf_print(out, ldns_dnssec_name_name( 951238104Sdes zone->soa)); 952238104Sdes fprintf(out, "\n;\n"); 953238104Sdes } 954238104Sdes ldns_dnssec_rrsets_print_fmt(out, fmt, 955238104Sdes ldns_dnssec_name_find_rrset( 956238104Sdes zone->soa, 957238104Sdes LDNS_RR_TYPE_SOA), 958238104Sdes false); 959238104Sdes if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 960238104Sdes fprintf(out, ";\n"); 961238104Sdes } 962238104Sdes 963238104Sdes if (zone->names) { 964238104Sdes ldns_dnssec_zone_names_print_fmt(out, fmt, 965238104Sdes zone->names, false); 966238104Sdes } 967238104Sdes } 968238104Sdes} 969238104Sdes 970238104Sdesvoid 971238104Sdesldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone) 972238104Sdes{ 973238104Sdes ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); 974238104Sdes} 975238104Sdes 976238104Sdesldns_status 977238104Sdesldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) 978238104Sdes{ 979238104Sdes ldns_dnssec_name *new_name; 980238104Sdes ldns_rdf *cur_name; 981238104Sdes ldns_rdf *next_name; 982238104Sdes ldns_rbnode_t *cur_node, *next_node, *new_node; 983238104Sdes 984238104Sdes /* for the detection */ 985238104Sdes uint16_t i, cur_label_count, next_label_count; 986238104Sdes uint16_t soa_label_count = 0; 987238104Sdes ldns_rdf *l1, *l2; 988238104Sdes int lpos; 989238104Sdes 990238104Sdes if (!zone) { 991238104Sdes return LDNS_STATUS_ERR; 992238104Sdes } 993238104Sdes if (zone->soa && zone->soa->name) { 994238104Sdes soa_label_count = ldns_dname_label_count(zone->soa->name); 995238104Sdes } 996238104Sdes 997238104Sdes cur_node = ldns_rbtree_first(zone->names); 998238104Sdes while (cur_node != LDNS_RBTREE_NULL) { 999238104Sdes next_node = ldns_rbtree_next(cur_node); 1000238104Sdes 1001238104Sdes /* skip glue */ 1002238104Sdes while (next_node != LDNS_RBTREE_NULL && 1003238104Sdes next_node->data && 1004238104Sdes ((ldns_dnssec_name *)next_node->data)->is_glue 1005238104Sdes ) { 1006238104Sdes next_node = ldns_rbtree_next(next_node); 1007238104Sdes } 1008238104Sdes 1009238104Sdes if (next_node == LDNS_RBTREE_NULL) { 1010238104Sdes next_node = ldns_rbtree_first(zone->names); 1011238104Sdes } 1012238104Sdes 1013238104Sdes cur_name = ((ldns_dnssec_name *)cur_node->data)->name; 1014238104Sdes next_name = ((ldns_dnssec_name *)next_node->data)->name; 1015238104Sdes cur_label_count = ldns_dname_label_count(cur_name); 1016238104Sdes next_label_count = ldns_dname_label_count(next_name); 1017238104Sdes 1018238104Sdes /* Since the names are in canonical order, we can 1019238104Sdes * recognize empty non-terminals by their labels; 1020238104Sdes * every label after the first one on the next owner 1021238104Sdes * name is a non-terminal if it either does not exist 1022238104Sdes * in the current name or is different from the same 1023238104Sdes * label in the current name (counting from the end) 1024238104Sdes */ 1025238104Sdes for (i = 1; i < next_label_count - soa_label_count; i++) { 1026238104Sdes lpos = (int)cur_label_count - (int)next_label_count + (int)i; 1027238104Sdes if (lpos >= 0) { 1028238104Sdes l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); 1029238104Sdes } else { 1030238104Sdes l1 = NULL; 1031238104Sdes } 1032238104Sdes l2 = ldns_dname_clone_from(next_name, i); 1033238104Sdes 1034238104Sdes if (!l1 || ldns_dname_compare(l1, l2) != 0) { 1035238104Sdes /* We have an empty nonterminal, add it to the 1036238104Sdes * tree 1037238104Sdes */ 1038238104Sdes new_name = ldns_dnssec_name_new(); 1039238104Sdes if (!new_name) { 1040238104Sdes return LDNS_STATUS_MEM_ERR; 1041238104Sdes } 1042238104Sdes new_name->name = ldns_dname_clone_from(next_name, 1043238104Sdes i); 1044238104Sdes if (!new_name->name) { 1045238104Sdes ldns_dnssec_name_free(new_name); 1046238104Sdes return LDNS_STATUS_MEM_ERR; 1047238104Sdes } 1048238104Sdes new_name->name_alloced = true; 1049238104Sdes new_node = LDNS_MALLOC(ldns_rbnode_t); 1050238104Sdes if (!new_node) { 1051238104Sdes ldns_dnssec_name_free(new_name); 1052238104Sdes return LDNS_STATUS_MEM_ERR; 1053238104Sdes } 1054238104Sdes new_node->key = new_name->name; 1055238104Sdes new_node->data = new_name; 1056238104Sdes (void)ldns_rbtree_insert(zone->names, new_node); 1057238104Sdes } 1058238104Sdes ldns_rdf_deep_free(l1); 1059238104Sdes ldns_rdf_deep_free(l2); 1060238104Sdes } 1061238104Sdes 1062238104Sdes /* we might have inserted a new node after 1063238104Sdes * the current one so we can't just use next() 1064238104Sdes */ 1065238104Sdes if (next_node != ldns_rbtree_first(zone->names)) { 1066238104Sdes cur_node = next_node; 1067238104Sdes } else { 1068238104Sdes cur_node = LDNS_RBTREE_NULL; 1069238104Sdes } 1070238104Sdes } 1071238104Sdes return LDNS_STATUS_OK; 1072238104Sdes} 1073238104Sdes 1074238104Sdesbool 1075238104Sdesldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone) 1076238104Sdes{ 1077238104Sdes ldns_rr* nsec3; 1078238104Sdes ldns_rbnode_t* node; 1079238104Sdes 1080238104Sdes if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) { 1081238104Sdes node = ldns_rbtree_first(zone->names); 1082238104Sdes while (node != LDNS_RBTREE_NULL) { 1083238104Sdes nsec3 = ((ldns_dnssec_name*)node->data)->nsec; 1084238104Sdes if (nsec3 &&ldns_rr_get_type(nsec3) 1085238104Sdes == LDNS_RR_TYPE_NSEC3 && 1086238104Sdes ldns_nsec3_optout(nsec3)) { 1087238104Sdes return true; 1088238104Sdes } 1089238104Sdes node = ldns_rbtree_next(node); 1090238104Sdes } 1091238104Sdes } 1092238104Sdes return false; 1093238104Sdes} 1094