1 /* 2 * special zone file structures and functions for better dnssec handling 3 */ 4 5 #include <ldns/config.h> 6 7 #include <ldns/ldns.h> 8 9 ldns_dnssec_rrs * 10 ldns_dnssec_rrs_new() 11 { 12 ldns_dnssec_rrs *new_rrs; 13 new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); 14 if(!new_rrs) return NULL; 15 new_rrs->rr = NULL; 16 new_rrs->next = NULL; 17 return new_rrs; 18 } 19 20 INLINE void 21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep) 22 { 23 ldns_dnssec_rrs *next; 24 while (rrs) { 25 next = rrs->next; 26 if (deep) { 27 ldns_rr_free(rrs->rr); 28 } 29 LDNS_FREE(rrs); 30 rrs = next; 31 } 32 } 33 34 void 35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs) 36 { 37 ldns_dnssec_rrs_free_internal(rrs, 0); 38 } 39 40 void 41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs) 42 { 43 ldns_dnssec_rrs_free_internal(rrs, 1); 44 } 45 46 ldns_status 47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) 48 { 49 int cmp; 50 ldns_dnssec_rrs *new_rrs; 51 if (!rrs || !rr) { 52 return LDNS_STATUS_ERR; 53 } 54 55 /* this could be done more efficiently; name and type should already 56 be equal */ 57 cmp = ldns_rr_compare(rrs->rr, 58 rr); 59 /* should we error on equal? */ 60 if (cmp <= 0) { 61 if (rrs->next) { 62 return ldns_dnssec_rrs_add_rr(rrs->next, rr); 63 } else { 64 new_rrs = ldns_dnssec_rrs_new(); 65 new_rrs->rr = rr; 66 rrs->next = new_rrs; 67 } 68 } else if (cmp > 0) { 69 /* put the current old rr in the new next, put the new 70 rr in the current container */ 71 new_rrs = ldns_dnssec_rrs_new(); 72 new_rrs->rr = rrs->rr; 73 new_rrs->next = rrs->next; 74 rrs->rr = rr; 75 rrs->next = new_rrs; 76 } 77 return LDNS_STATUS_OK; 78 } 79 80 void 81 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, 82 ldns_dnssec_rrs *rrs) 83 { 84 if (!rrs) { 85 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 86 fprintf(out, "; <void>"); 87 } else { 88 if (rrs->rr) { 89 ldns_rr_print_fmt(out, fmt, rrs->rr); 90 } 91 if (rrs->next) { 92 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next); 93 } 94 } 95 } 96 97 void 98 ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs) 99 { 100 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs); 101 } 102 103 104 ldns_dnssec_rrsets * 105 ldns_dnssec_rrsets_new() 106 { 107 ldns_dnssec_rrsets *new_rrsets; 108 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); 109 if(!new_rrsets) return NULL; 110 new_rrsets->rrs = NULL; 111 new_rrsets->type = 0; 112 new_rrsets->signatures = NULL; 113 new_rrsets->next = NULL; 114 return new_rrsets; 115 } 116 117 INLINE void 118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep) 119 { 120 if (rrsets) { 121 if (rrsets->rrs) { 122 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep); 123 } 124 if (rrsets->next) { 125 ldns_dnssec_rrsets_free_internal(rrsets->next, deep); 126 } 127 if (rrsets->signatures) { 128 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep); 129 } 130 LDNS_FREE(rrsets); 131 } 132 } 133 134 void 135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets) 136 { 137 ldns_dnssec_rrsets_free_internal(rrsets, 0); 138 } 139 140 void 141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets) 142 { 143 ldns_dnssec_rrsets_free_internal(rrsets, 1); 144 } 145 146 ldns_rr_type 147 ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets) 148 { 149 if (rrsets) { 150 return rrsets->type; 151 } else { 152 return 0; 153 } 154 } 155 156 ldns_status 157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 158 ldns_rr_type type) 159 { 160 if (rrsets) { 161 rrsets->type = type; 162 return LDNS_STATUS_OK; 163 } 164 return LDNS_STATUS_ERR; 165 } 166 167 ldns_dnssec_rrsets * 168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) 169 { 170 ldns_dnssec_rrsets *new_rrsets; 171 ldns_rr_type rr_type; 172 bool rrsig; 173 174 new_rrsets = ldns_dnssec_rrsets_new(); 175 rr_type = ldns_rr_get_type(rr); 176 if (rr_type == LDNS_RR_TYPE_RRSIG) { 177 rrsig = true; 178 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 179 } else { 180 rrsig = false; 181 } 182 if (!rrsig) { 183 new_rrsets->rrs = ldns_dnssec_rrs_new(); 184 new_rrsets->rrs->rr = rr; 185 } else { 186 new_rrsets->signatures = ldns_dnssec_rrs_new(); 187 new_rrsets->signatures->rr = rr; 188 } 189 new_rrsets->type = rr_type; 190 return new_rrsets; 191 } 192 193 ldns_status 194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) 195 { 196 ldns_dnssec_rrsets *new_rrsets; 197 ldns_rr_type rr_type; 198 bool rrsig = false; 199 ldns_status result = LDNS_STATUS_OK; 200 201 if (!rrsets || !rr) { 202 return LDNS_STATUS_ERR; 203 } 204 205 rr_type = ldns_rr_get_type(rr); 206 207 if (rr_type == LDNS_RR_TYPE_RRSIG) { 208 rrsig = true; 209 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 210 } 211 212 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { 213 if (!rrsig) { 214 rrsets->rrs = ldns_dnssec_rrs_new(); 215 rrsets->rrs->rr = rr; 216 rrsets->type = rr_type; 217 } else { 218 rrsets->signatures = ldns_dnssec_rrs_new(); 219 rrsets->signatures->rr = rr; 220 rrsets->type = rr_type; 221 } 222 return LDNS_STATUS_OK; 223 } 224 225 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { 226 if (rrsets->next) { 227 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); 228 } else { 229 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); 230 rrsets->next = new_rrsets; 231 } 232 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { 233 /* move the current one into the new next, 234 replace field of current with data from new rr */ 235 new_rrsets = ldns_dnssec_rrsets_new(); 236 new_rrsets->rrs = rrsets->rrs; 237 new_rrsets->type = rrsets->type; 238 new_rrsets->signatures = rrsets->signatures; 239 new_rrsets->next = rrsets->next; 240 if (!rrsig) { 241 rrsets->rrs = ldns_dnssec_rrs_new(); 242 rrsets->rrs->rr = rr; 243 rrsets->signatures = NULL; 244 } else { 245 rrsets->rrs = NULL; 246 rrsets->signatures = ldns_dnssec_rrs_new(); 247 rrsets->signatures->rr = rr; 248 } 249 rrsets->type = rr_type; 250 rrsets->next = new_rrsets; 251 } else { 252 /* equal, add to current rrsets */ 253 if (rrsig) { 254 if (rrsets->signatures) { 255 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); 256 } else { 257 rrsets->signatures = ldns_dnssec_rrs_new(); 258 rrsets->signatures->rr = rr; 259 } 260 } else { 261 if (rrsets->rrs) { 262 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); 263 } else { 264 rrsets->rrs = ldns_dnssec_rrs_new(); 265 rrsets->rrs->rr = rr; 266 } 267 } 268 } 269 270 return result; 271 } 272 273 void 274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 275 ldns_dnssec_rrsets *rrsets, 276 bool follow, 277 bool show_soa) 278 { 279 if (!rrsets) { 280 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 281 fprintf(out, "; <void>\n"); 282 } else { 283 if (rrsets->rrs && 284 (show_soa || 285 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA 286 ) 287 ) { 288 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs); 289 if (rrsets->signatures) { 290 ldns_dnssec_rrs_print_fmt(out, fmt, 291 rrsets->signatures); 292 } 293 } 294 if (follow && rrsets->next) { 295 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 296 rrsets->next, follow, show_soa); 297 } 298 } 299 } 300 301 void 302 ldns_dnssec_rrsets_print_soa(FILE *out, 303 ldns_dnssec_rrsets *rrsets, 304 bool follow, 305 bool show_soa) 306 { 307 ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default, 308 rrsets, follow, show_soa); 309 } 310 311 312 void 313 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, 314 ldns_dnssec_rrsets *rrsets, 315 bool follow) 316 { 317 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true); 318 } 319 320 void 321 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow) 322 { 323 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 324 rrsets, follow); 325 } 326 327 ldns_dnssec_name * 328 ldns_dnssec_name_new() 329 { 330 ldns_dnssec_name *new_name; 331 332 new_name = LDNS_CALLOC(ldns_dnssec_name, 1); 333 if (!new_name) { 334 return NULL; 335 } 336 /* 337 * not needed anymore because CALLOC initalizes everything to zero. 338 339 new_name->name = NULL; 340 new_name->rrsets = NULL; 341 new_name->name_alloced = false; 342 new_name->nsec = NULL; 343 new_name->nsec_signatures = NULL; 344 345 new_name->is_glue = false; 346 new_name->hashed_name = NULL; 347 348 */ 349 return new_name; 350 } 351 352 ldns_dnssec_name * 353 ldns_dnssec_name_new_frm_rr(ldns_rr *rr) 354 { 355 ldns_dnssec_name *new_name = ldns_dnssec_name_new(); 356 357 new_name->name = ldns_rr_owner(rr); 358 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) { 359 ldns_dnssec_name_free(new_name); 360 return NULL; 361 } 362 363 return new_name; 364 } 365 366 INLINE void 367 ldns_dnssec_name_free_internal(ldns_dnssec_name *name, 368 int deep) 369 { 370 if (name) { 371 if (name->name_alloced) { 372 ldns_rdf_deep_free(name->name); 373 } 374 if (name->rrsets) { 375 ldns_dnssec_rrsets_free_internal(name->rrsets, deep); 376 } 377 if (name->nsec && deep) { 378 ldns_rr_free(name->nsec); 379 } 380 if (name->nsec_signatures) { 381 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); 382 } 383 if (name->hashed_name) { 384 if (deep) { 385 ldns_rdf_deep_free(name->hashed_name); 386 } 387 } 388 LDNS_FREE(name); 389 } 390 } 391 392 void 393 ldns_dnssec_name_free(ldns_dnssec_name *name) 394 { 395 ldns_dnssec_name_free_internal(name, 0); 396 } 397 398 void 399 ldns_dnssec_name_deep_free(ldns_dnssec_name *name) 400 { 401 ldns_dnssec_name_free_internal(name, 1); 402 } 403 404 ldns_rdf * 405 ldns_dnssec_name_name(ldns_dnssec_name *name) 406 { 407 if (name) { 408 return name->name; 409 } 410 return NULL; 411 } 412 413 bool 414 ldns_dnssec_name_is_glue(ldns_dnssec_name *name) 415 { 416 if (name) { 417 return name->is_glue; 418 } 419 return false; 420 } 421 422 void 423 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, 424 ldns_rdf *dname) 425 { 426 if (rrset && dname) { 427 rrset->name = dname; 428 } 429 } 430 431 ldns_rr * 432 ldns_dnssec_name_nsec(ldns_dnssec_name *rrset) 433 { 434 if (rrset) { 435 return rrset->nsec; 436 } 437 return NULL; 438 } 439 440 void 441 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) 442 { 443 if (rrset && nsec) { 444 rrset->nsec = nsec; 445 } 446 } 447 448 int 449 ldns_dnssec_name_cmp(const void *a, const void *b) 450 { 451 ldns_dnssec_name *na = (ldns_dnssec_name *) a; 452 ldns_dnssec_name *nb = (ldns_dnssec_name *) b; 453 454 if (na && nb) { 455 return ldns_dname_compare(ldns_dnssec_name_name(na), 456 ldns_dnssec_name_name(nb)); 457 } else if (na) { 458 return 1; 459 } else if (nb) { 460 return -1; 461 } else { 462 return 0; 463 } 464 } 465 466 ldns_status 467 ldns_dnssec_name_add_rr(ldns_dnssec_name *name, 468 ldns_rr *rr) 469 { 470 ldns_status result = LDNS_STATUS_OK; 471 ldns_rdf *name_name; 472 bool hashed_name = false; 473 ldns_rr_type rr_type; 474 ldns_rr_type typecovered = 0; 475 476 /* special handling for NSEC3 and NSECX covering RRSIGS */ 477 478 if (!name || !rr) { 479 return LDNS_STATUS_ERR; 480 } 481 482 rr_type = ldns_rr_get_type(rr); 483 484 if (rr_type == LDNS_RR_TYPE_RRSIG) { 485 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 486 } 487 488 #ifdef HAVE_SSL 489 if (rr_type == LDNS_RR_TYPE_NSEC3 || 490 typecovered == LDNS_RR_TYPE_NSEC3) { 491 name_name = ldns_nsec3_hash_name_frm_nsec3(rr, 492 ldns_dnssec_name_name(name)); 493 hashed_name = true; 494 } else { 495 name_name = ldns_dnssec_name_name(name); 496 } 497 #else 498 name_name = ldns_dnssec_name_name(name); 499 #endif /* HAVE_SSL */ 500 501 if (rr_type == LDNS_RR_TYPE_NSEC || 502 rr_type == LDNS_RR_TYPE_NSEC3) { 503 /* XX check if is already set (and error?) */ 504 name->nsec = rr; 505 } else if (typecovered == LDNS_RR_TYPE_NSEC || 506 typecovered == LDNS_RR_TYPE_NSEC3) { 507 if (name->nsec_signatures) { 508 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); 509 } else { 510 name->nsec_signatures = ldns_dnssec_rrs_new(); 511 name->nsec_signatures->rr = rr; 512 } 513 } else { 514 /* it's a 'normal' RR, add it to the right rrset */ 515 if (name->rrsets) { 516 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 517 } else { 518 name->rrsets = ldns_dnssec_rrsets_new(); 519 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 520 } 521 } 522 523 if (hashed_name) { 524 ldns_rdf_deep_free(name_name); 525 } 526 527 return result; 528 } 529 530 ldns_dnssec_rrsets * 531 ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, 532 ldns_rr_type type) { 533 ldns_dnssec_rrsets *result; 534 535 result = name->rrsets; 536 while (result) { 537 if (result->type == type) { 538 return result; 539 } else { 540 result = result->next; 541 } 542 } 543 return NULL; 544 } 545 546 ldns_dnssec_rrsets * 547 ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, 548 ldns_rdf *dname, 549 ldns_rr_type type) 550 { 551 ldns_rbnode_t *node; 552 553 if (!zone || !dname) { 554 return NULL; 555 } 556 557 node = ldns_rbtree_search(zone->names, dname); 558 if (node) { 559 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data, 560 type); 561 } else { 562 return NULL; 563 } 564 } 565 566 void 567 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 568 ldns_dnssec_name *name, 569 bool show_soa) 570 { 571 if (name) { 572 if(name->rrsets) { 573 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 574 name->rrsets, true, show_soa); 575 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 576 fprintf(out, ";; Empty nonterminal: "); 577 ldns_rdf_print(out, name->name); 578 fprintf(out, "\n"); 579 } 580 if(name->nsec) { 581 ldns_rr_print_fmt(out, fmt, name->nsec); 582 } 583 if (name->nsec_signatures) { 584 ldns_dnssec_rrs_print_fmt(out, fmt, 585 name->nsec_signatures); 586 } 587 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 588 fprintf(out, "; <void>\n"); 589 } 590 } 591 592 void 593 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa) 594 { 595 ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default, 596 name, show_soa); 597 } 598 599 void 600 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, 601 ldns_dnssec_name *name) 602 { 603 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true); 604 } 605 606 void 607 ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name) 608 { 609 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name); 610 } 611 612 613 ldns_dnssec_zone * 614 ldns_dnssec_zone_new() 615 { 616 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); 617 if(!zone) return NULL; 618 zone->soa = NULL; 619 zone->names = NULL; 620 621 return zone; 622 } 623 624 void 625 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { 626 (void) arg; 627 ldns_dnssec_name_free((ldns_dnssec_name *)node->data); 628 free(node); 629 } 630 631 void 632 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { 633 (void) arg; 634 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); 635 free(node); 636 } 637 638 void 639 ldns_dnssec_zone_free(ldns_dnssec_zone *zone) 640 { 641 if (zone) { 642 if (zone->names) { 643 /* destroy all name structures within the tree */ 644 ldns_traverse_postorder(zone->names, 645 ldns_dnssec_name_node_free, 646 NULL); 647 free(zone->names); 648 } 649 LDNS_FREE(zone); 650 } 651 } 652 653 void 654 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) 655 { 656 if (zone) { 657 if (zone->names) { 658 /* destroy all name structures within the tree */ 659 ldns_traverse_postorder(zone->names, 660 ldns_dnssec_name_node_deep_free, 661 NULL); 662 free(zone->names); 663 } 664 LDNS_FREE(zone); 665 } 666 } 667 668 /* use for dname comparison in tree */ 669 int 670 ldns_dname_compare_v(const void *a, const void *b) { 671 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); 672 } 673 674 #ifdef HAVE_SSL 675 ldns_rbnode_t * 676 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, 677 ldns_rr *rr) { 678 ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names); 679 ldns_dnssec_name *current_name; 680 ldns_rdf *hashed_name; 681 682 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); 683 684 while (current_node != LDNS_RBTREE_NULL) { 685 current_name = (ldns_dnssec_name *) current_node->data; 686 if (!current_name->hashed_name) { 687 current_name->hashed_name = 688 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name); 689 } 690 if (ldns_dname_compare(hashed_name, 691 current_name->hashed_name) 692 == 0) { 693 ldns_rdf_deep_free(hashed_name); 694 return current_node; 695 } 696 current_node = ldns_rbtree_next(current_node); 697 } 698 ldns_rdf_deep_free(hashed_name); 699 return NULL; 700 } 701 702 ldns_status 703 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) 704 { 705 ldns_status result = LDNS_STATUS_OK; 706 ldns_dnssec_name *cur_name; 707 ldns_rbnode_t *cur_node; 708 ldns_rr_type type_covered = 0; 709 710 if (!zone || !rr) { 711 return LDNS_STATUS_ERR; 712 } 713 714 if (!zone->names) { 715 zone->names = ldns_rbtree_create(ldns_dname_compare_v); 716 if(!zone->names) return LDNS_STATUS_MEM_ERR; 717 } 718 719 /* we need the original of the hashed name if this is 720 an NSEC3, or an RRSIG that covers an NSEC3 */ 721 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { 722 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 723 } 724 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || 725 type_covered == LDNS_RR_TYPE_NSEC3) { 726 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, 727 rr); 728 if (!cur_node) { 729 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; 730 } 731 } else { 732 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); 733 } 734 735 if (!cur_node) { 736 /* add */ 737 cur_name = ldns_dnssec_name_new_frm_rr(rr); 738 if(!cur_name) return LDNS_STATUS_MEM_ERR; 739 cur_node = LDNS_MALLOC(ldns_rbnode_t); 740 if(!cur_node) { 741 ldns_dnssec_name_free(cur_name); 742 return LDNS_STATUS_MEM_ERR; 743 } 744 cur_node->key = ldns_rr_owner(rr); 745 cur_node->data = cur_name; 746 (void)ldns_rbtree_insert(zone->names, cur_node); 747 } else { 748 cur_name = (ldns_dnssec_name *) cur_node->data; 749 result = ldns_dnssec_name_add_rr(cur_name, rr); 750 } 751 752 if (result != LDNS_STATUS_OK) { 753 fprintf(stderr, "error adding rr: "); 754 ldns_rr_print(stderr, rr); 755 } 756 757 /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/ 758 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { 759 zone->soa = cur_name; 760 } 761 762 return result; 763 } 764 #endif /* HAVE_SSL */ 765 766 void 767 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 768 ldns_rbtree_t *tree, 769 bool print_soa) 770 { 771 ldns_rbnode_t *node; 772 ldns_dnssec_name *name; 773 774 node = ldns_rbtree_first(tree); 775 while (node != LDNS_RBTREE_NULL) { 776 name = (ldns_dnssec_name *) node->data; 777 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); 778 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 779 fprintf(out, ";\n"); 780 node = ldns_rbtree_next(node); 781 } 782 } 783 784 void 785 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa) 786 { 787 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, 788 tree, print_soa); 789 } 790 791 void 792 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, 793 ldns_dnssec_zone *zone) 794 { 795 if (zone) { 796 if (zone->soa) { 797 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 798 fprintf(out, ";; Zone: "); 799 ldns_rdf_print(out, ldns_dnssec_name_name( 800 zone->soa)); 801 fprintf(out, "\n;\n"); 802 } 803 ldns_dnssec_rrsets_print_fmt(out, fmt, 804 ldns_dnssec_name_find_rrset( 805 zone->soa, 806 LDNS_RR_TYPE_SOA), 807 false); 808 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 809 fprintf(out, ";\n"); 810 } 811 812 if (zone->names) { 813 ldns_dnssec_zone_names_print_fmt(out, fmt, 814 zone->names, false); 815 } 816 } 817 } 818 819 void 820 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone) 821 { 822 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); 823 } 824 825 ldns_status 826 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) 827 { 828 ldns_dnssec_name *new_name; 829 ldns_rdf *cur_name; 830 ldns_rdf *next_name; 831 ldns_rbnode_t *cur_node, *next_node, *new_node; 832 833 /* for the detection */ 834 uint16_t i, cur_label_count, next_label_count; 835 uint16_t soa_label_count = 0; 836 ldns_rdf *l1, *l2; 837 int lpos; 838 839 if (!zone) { 840 return LDNS_STATUS_ERR; 841 } 842 if (zone->soa && zone->soa->name) { 843 soa_label_count = ldns_dname_label_count(zone->soa->name); 844 } 845 846 cur_node = ldns_rbtree_first(zone->names); 847 while (cur_node != LDNS_RBTREE_NULL) { 848 next_node = ldns_rbtree_next(cur_node); 849 850 /* skip glue */ 851 while (next_node != LDNS_RBTREE_NULL && 852 next_node->data && 853 ((ldns_dnssec_name *)next_node->data)->is_glue 854 ) { 855 next_node = ldns_rbtree_next(next_node); 856 } 857 858 if (next_node == LDNS_RBTREE_NULL) { 859 next_node = ldns_rbtree_first(zone->names); 860 } 861 862 cur_name = ((ldns_dnssec_name *)cur_node->data)->name; 863 next_name = ((ldns_dnssec_name *)next_node->data)->name; 864 cur_label_count = ldns_dname_label_count(cur_name); 865 next_label_count = ldns_dname_label_count(next_name); 866 867 /* Since the names are in canonical order, we can 868 * recognize empty non-terminals by their labels; 869 * every label after the first one on the next owner 870 * name is a non-terminal if it either does not exist 871 * in the current name or is different from the same 872 * label in the current name (counting from the end) 873 */ 874 for (i = 1; i < next_label_count - soa_label_count; i++) { 875 lpos = (int)cur_label_count - (int)next_label_count + (int)i; 876 if (lpos >= 0) { 877 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); 878 } else { 879 l1 = NULL; 880 } 881 l2 = ldns_dname_clone_from(next_name, i); 882 883 if (!l1 || ldns_dname_compare(l1, l2) != 0) { 884 /* We have an empty nonterminal, add it to the 885 * tree 886 */ 887 new_name = ldns_dnssec_name_new(); 888 if (!new_name) { 889 return LDNS_STATUS_MEM_ERR; 890 } 891 new_name->name = ldns_dname_clone_from(next_name, 892 i); 893 if (!new_name->name) { 894 ldns_dnssec_name_free(new_name); 895 return LDNS_STATUS_MEM_ERR; 896 } 897 new_name->name_alloced = true; 898 new_node = LDNS_MALLOC(ldns_rbnode_t); 899 if (!new_node) { 900 ldns_dnssec_name_free(new_name); 901 return LDNS_STATUS_MEM_ERR; 902 } 903 new_node->key = new_name->name; 904 new_node->data = new_name; 905 (void)ldns_rbtree_insert(zone->names, new_node); 906 } 907 ldns_rdf_deep_free(l1); 908 ldns_rdf_deep_free(l2); 909 } 910 911 /* we might have inserted a new node after 912 * the current one so we can't just use next() 913 */ 914 if (next_node != ldns_rbtree_first(zone->names)) { 915 cur_node = next_node; 916 } else { 917 cur_node = LDNS_RBTREE_NULL; 918 } 919 } 920 return LDNS_STATUS_OK; 921 } 922