2 * special zone file structures and functions for better dnssec handling
5 #include <ldns/config.h>
10 ldns_dnssec_rrs_new(void)
12 ldns_dnssec_rrs *new_rrs;
13 new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
14 if(!new_rrs) return NULL;
21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
23 ldns_dnssec_rrs *next;
27 ldns_rr_free(rrs->rr);
35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
37 ldns_dnssec_rrs_free_internal(rrs, 0);
41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
43 ldns_dnssec_rrs_free_internal(rrs, 1);
47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
50 ldns_dnssec_rrs *new_rrs;
52 return LDNS_STATUS_ERR;
55 /* this could be done more efficiently; name and type should already
57 cmp = ldns_rr_compare(rrs->rr, rr);
60 return ldns_dnssec_rrs_add_rr(rrs->next, rr);
62 new_rrs = ldns_dnssec_rrs_new();
67 /* put the current old rr in the new next, put the new
68 rr in the current container */
69 new_rrs = ldns_dnssec_rrs_new();
70 new_rrs->rr = rrs->rr;
71 new_rrs->next = rrs->next;
75 /* Silently ignore equal rr's */
76 return LDNS_STATUS_OK;
80 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
81 const ldns_dnssec_rrs *rrs)
84 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
85 fprintf(out, "; <void>");
88 ldns_rr_print_fmt(out, fmt, rrs->rr);
91 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
97 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
99 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
104 ldns_dnssec_rrsets_new(void)
106 ldns_dnssec_rrsets *new_rrsets;
107 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
108 if(!new_rrsets) return NULL;
109 new_rrsets->rrs = NULL;
110 new_rrsets->type = 0;
111 new_rrsets->signatures = NULL;
112 new_rrsets->next = NULL;
117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
121 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
124 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126 if (rrsets->signatures) {
127 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
134 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
136 ldns_dnssec_rrsets_free_internal(rrsets, 0);
140 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
142 ldns_dnssec_rrsets_free_internal(rrsets, 1);
146 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
156 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
161 return LDNS_STATUS_OK;
163 return LDNS_STATUS_ERR;
166 static ldns_dnssec_rrsets *
167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169 ldns_dnssec_rrsets *new_rrsets;
170 ldns_rr_type rr_type;
173 new_rrsets = ldns_dnssec_rrsets_new();
174 rr_type = ldns_rr_get_type(rr);
175 if (rr_type == LDNS_RR_TYPE_RRSIG) {
177 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
182 new_rrsets->rrs = ldns_dnssec_rrs_new();
183 new_rrsets->rrs->rr = rr;
185 new_rrsets->signatures = ldns_dnssec_rrs_new();
186 new_rrsets->signatures->rr = rr;
188 new_rrsets->type = rr_type;
193 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
195 ldns_dnssec_rrsets *new_rrsets;
196 ldns_rr_type rr_type;
198 ldns_status result = LDNS_STATUS_OK;
200 if (!rrsets || !rr) {
201 return LDNS_STATUS_ERR;
204 rr_type = ldns_rr_get_type(rr);
206 if (rr_type == LDNS_RR_TYPE_RRSIG) {
208 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
211 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213 rrsets->rrs = ldns_dnssec_rrs_new();
214 rrsets->rrs->rr = rr;
215 rrsets->type = rr_type;
217 rrsets->signatures = ldns_dnssec_rrs_new();
218 rrsets->signatures->rr = rr;
219 rrsets->type = rr_type;
221 return LDNS_STATUS_OK;
224 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
229 rrsets->next = new_rrsets;
231 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
232 /* move the current one into the new next,
233 replace field of current with data from new rr */
234 new_rrsets = ldns_dnssec_rrsets_new();
235 new_rrsets->rrs = rrsets->rrs;
236 new_rrsets->type = rrsets->type;
237 new_rrsets->signatures = rrsets->signatures;
238 new_rrsets->next = rrsets->next;
240 rrsets->rrs = ldns_dnssec_rrs_new();
241 rrsets->rrs->rr = rr;
242 rrsets->signatures = NULL;
245 rrsets->signatures = ldns_dnssec_rrs_new();
246 rrsets->signatures->rr = rr;
248 rrsets->type = rr_type;
249 rrsets->next = new_rrsets;
251 /* equal, add to current rrsets */
253 if (rrsets->signatures) {
254 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256 rrsets->signatures = ldns_dnssec_rrs_new();
257 rrsets->signatures->rr = rr;
261 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263 rrsets->rrs = ldns_dnssec_rrs_new();
264 rrsets->rrs->rr = rr;
273 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
274 const ldns_dnssec_rrsets *rrsets,
279 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
280 fprintf(out, "; <void>\n");
284 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
287 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
288 if (rrsets->signatures) {
289 ldns_dnssec_rrs_print_fmt(out, fmt,
293 if (follow && rrsets->next) {
294 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295 rrsets->next, follow, show_soa);
302 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
303 const ldns_dnssec_rrsets *rrsets,
306 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
310 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
312 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
317 ldns_dnssec_name_new(void)
319 ldns_dnssec_name *new_name;
321 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
326 * not needed anymore because CALLOC initalizes everything to zero.
328 new_name->name = NULL;
329 new_name->rrsets = NULL;
330 new_name->name_alloced = false;
331 new_name->nsec = NULL;
332 new_name->nsec_signatures = NULL;
334 new_name->is_glue = false;
335 new_name->hashed_name = NULL;
342 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
344 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
346 new_name->name = ldns_rr_owner(rr);
347 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
348 ldns_dnssec_name_free(new_name);
356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
360 if (name->name_alloced) {
361 ldns_rdf_deep_free(name->name);
364 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
366 if (name->nsec && deep) {
367 ldns_rr_free(name->nsec);
369 if (name->nsec_signatures) {
370 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
372 if (name->hashed_name) {
374 ldns_rdf_deep_free(name->hashed_name);
382 ldns_dnssec_name_free(ldns_dnssec_name *name)
384 ldns_dnssec_name_free_internal(name, 0);
388 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
390 ldns_dnssec_name_free_internal(name, 1);
394 ldns_dnssec_name_name(const ldns_dnssec_name *name)
403 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
406 return name->is_glue;
412 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
415 if (rrset && dname) {
422 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
430 ldns_dnssec_name_cmp(const void *a, const void *b)
432 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
433 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
436 return ldns_dname_compare(ldns_dnssec_name_name(na),
437 ldns_dnssec_name_name(nb));
448 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
451 ldns_status result = LDNS_STATUS_OK;
452 ldns_rr_type rr_type;
453 ldns_rr_type typecovered = 0;
455 /* special handling for NSEC3 and NSECX covering RRSIGS */
458 return LDNS_STATUS_ERR;
461 rr_type = ldns_rr_get_type(rr);
463 if (rr_type == LDNS_RR_TYPE_RRSIG) {
464 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
467 if (rr_type == LDNS_RR_TYPE_NSEC ||
468 rr_type == LDNS_RR_TYPE_NSEC3) {
469 /* XX check if is already set (and error?) */
471 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
472 typecovered == LDNS_RR_TYPE_NSEC3) {
473 if (name->nsec_signatures) {
474 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
476 name->nsec_signatures = ldns_dnssec_rrs_new();
477 name->nsec_signatures->rr = rr;
480 /* it's a 'normal' RR, add it to the right rrset */
482 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
484 name->rrsets = ldns_dnssec_rrsets_new();
485 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
492 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
494 ldns_dnssec_rrsets *result;
496 result = name->rrsets;
498 if (result->type == type) {
501 result = result->next;
508 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
509 const ldns_rdf *dname,
514 if (!zone || !dname || !zone->names) {
518 node = ldns_rbtree_search(zone->names, dname);
520 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
528 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
529 const ldns_dnssec_name *name,
534 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
535 name->rrsets, true, show_soa);
536 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
537 fprintf(out, ";; Empty nonterminal: ");
538 ldns_rdf_print(out, name->name);
542 ldns_rr_print_fmt(out, fmt, name->nsec);
544 if (name->nsec_signatures) {
545 ldns_dnssec_rrs_print_fmt(out, fmt,
546 name->nsec_signatures);
548 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
549 fprintf(out, "; <void>\n");
555 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
556 const ldns_dnssec_name *name)
558 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
562 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
564 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
569 ldns_dnssec_zone_new(void)
571 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
572 if(!zone) return NULL;
575 zone->hashed_names = NULL;
576 zone->_nsec3params = NULL;
582 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
584 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
585 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
588 /* When the zone is first read into an list and then inserted into an
589 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
590 * to each other. Because ldns-verify-zone (the only program that uses this
591 * function) uses the rbtree mostly for sequentual walking, this results
592 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
594 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
597 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
598 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
601 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
603 ldns_rdf_deep_free((ldns_rdf *)node->key);
608 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
609 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
614 ldns_rdf *my_origin = NULL;
615 ldns_rdf *my_prev = NULL;
617 ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
618 /* NSEC3s may occur before the names they refer to. We must remember
619 them and add them to the name later on, after the name is read.
620 We track not yet matching NSEC3s*n the todo_nsec3s list */
621 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
622 /* when reading NSEC3s, there is a chance that we encounter nsecs
623 for empty nonterminals, whose nonterminals we cannot derive yet
624 because the needed information is to be read later.
626 nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
627 hold the NSEC3s that still didn't have a matching name in the
628 zone tree, even after all names were read. They can only match
629 after the zone is equiped with all the empty non terminals. */
630 ldns_rbtree_t todo_nsec3_ents;
631 ldns_rbnode_t *new_node;
632 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
636 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
637 ldns_zone* zone = NULL;
639 uint32_t my_ttl = ttl;
642 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
644 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
645 status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr);
646 if (status != LDNS_STATUS_OK)
649 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
650 status = LDNS_STATUS_MEM_ERR;
654 if (!(my_origin = ldns_rdf_clone(origin))) {
655 status = LDNS_STATUS_MEM_ERR;
658 if (!(my_prev = ldns_rdf_clone(origin))) {
659 status = LDNS_STATUS_MEM_ERR;
664 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
665 if (ldns_zone_soa(zone)) {
666 status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
667 if (status != LDNS_STATUS_OK)
670 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
671 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
672 status = LDNS_STATUS_OK;
675 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
682 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
684 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
686 if (rr_is_rrsig_covering(cur_rr,
687 LDNS_RR_TYPE_NSEC3)){
688 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
691 ldns_rr_list_push_rr(todo_nsec3s,
694 status = LDNS_STATUS_OK;
696 } else if (status != LDNS_STATUS_OK)
702 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
703 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
704 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
705 status = LDNS_STATUS_OK;
708 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
709 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
717 for (i = 0; status == LDNS_STATUS_OK &&
718 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
719 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
720 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
721 if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
722 if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
723 status = LDNS_STATUS_MEM_ERR;
726 new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
727 new_node->data = cur_rr;
728 if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
730 status = LDNS_STATUS_MEM_ERR;
733 status = LDNS_STATUS_OK;
736 if (todo_nsec3_ents.count > 0)
737 (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
738 newzone, &todo_nsec3_ents);
739 for (i = 0; status == LDNS_STATUS_OK &&
740 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
741 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
742 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
748 ldns_dnssec_zone_free(newzone);
752 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
754 ldns_zone_free(zone);
757 ldns_rr_list_free(todo_nsec3_rrsigs);
758 ldns_traverse_postorder(&todo_nsec3_ents,
759 ldns_todo_nsec3_ents_node_free, NULL);
760 ldns_rr_list_free(todo_nsec3s);
763 ldns_rdf_deep_free(my_origin);
766 ldns_rdf_deep_free(my_prev);
769 ldns_dnssec_zone_free(newzone);
775 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
776 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
778 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
782 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
784 ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
789 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
791 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
796 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
800 /* destroy all name structures within the tree */
801 ldns_traverse_postorder(zone->names,
802 ldns_dnssec_name_node_free,
804 LDNS_FREE(zone->names);
811 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
815 /* destroy all name structures within the tree */
816 ldns_traverse_postorder(zone->names,
817 ldns_dnssec_name_node_deep_free,
819 LDNS_FREE(zone->names);
825 /* use for dname comparison in tree */
827 ldns_dname_compare_v(const void *a, const void *b) {
828 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
832 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
833 ldns_dnssec_name* name, ldns_rr* nsec3rr);
836 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
842 ldns_dnssec_zone_hashed_names_from_nsec3(
843 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
845 ldns_rbnode_t* current_node;
846 ldns_dnssec_name* current_name;
848 assert(zone != NULL);
849 assert(nsec3rr != NULL);
851 if (zone->hashed_names) {
852 ldns_traverse_postorder(zone->hashed_names,
853 ldns_hashed_names_node_free, NULL);
854 LDNS_FREE(zone->hashed_names);
856 zone->_nsec3params = nsec3rr;
858 /* So this is a NSEC3 zone.
859 * Calculate hashes for all names already in the zone
861 zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
862 if (zone->hashed_names == NULL) {
865 for ( current_node = ldns_rbtree_first(zone->names)
866 ; current_node != LDNS_RBTREE_NULL
867 ; current_node = ldns_rbtree_next(current_node)
869 current_name = (ldns_dnssec_name *) current_node->data;
870 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
876 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
877 ldns_dnssec_name* name, ldns_rr* nsec3rr)
879 ldns_rbnode_t* new_node;
881 assert(name != NULL);
882 if (! zone->_nsec3params) {
886 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
888 } else if (! nsec3rr) {
889 nsec3rr = zone->_nsec3params;
891 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
893 /* Also store in zone->hashed_names */
894 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
896 new_node->key = name->hashed_name;
897 new_node->data = name;
899 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
907 static ldns_rbnode_t *
908 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
909 ldns_rdf *hashed_name;
911 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
912 if (hashed_name == NULL) {
915 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
917 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
919 if (zone->hashed_names == NULL) {
920 ldns_rdf_deep_free(hashed_name);
923 return ldns_rbtree_search(zone->hashed_names, hashed_name);
927 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
929 ldns_status result = LDNS_STATUS_OK;
930 ldns_dnssec_name *cur_name;
931 ldns_rbnode_t *cur_node;
932 ldns_rr_type type_covered = 0;
935 return LDNS_STATUS_ERR;
939 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
940 if(!zone->names) return LDNS_STATUS_MEM_ERR;
943 /* we need the original of the hashed name if this is
944 an NSEC3, or an RRSIG that covers an NSEC3 */
945 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
946 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
948 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
949 type_covered == LDNS_RR_TYPE_NSEC3) {
950 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
952 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
955 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
959 cur_name = ldns_dnssec_name_new_frm_rr(rr);
960 if(!cur_name) return LDNS_STATUS_MEM_ERR;
961 cur_node = LDNS_MALLOC(ldns_rbnode_t);
963 ldns_dnssec_name_free(cur_name);
964 return LDNS_STATUS_MEM_ERR;
966 cur_node->key = ldns_rr_owner(rr);
967 cur_node->data = cur_name;
968 (void)ldns_rbtree_insert(zone->names, cur_node);
969 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
971 cur_name = (ldns_dnssec_name *) cur_node->data;
972 result = ldns_dnssec_name_add_rr(cur_name, rr);
974 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
975 zone->soa = cur_name;
981 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
982 const ldns_rbtree_t *tree,
986 ldns_dnssec_name *name;
988 node = ldns_rbtree_first(tree);
989 while (node != LDNS_RBTREE_NULL) {
990 name = (ldns_dnssec_name *) node->data;
991 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
992 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
994 node = ldns_rbtree_next(node);
999 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1001 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1006 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1007 const ldns_dnssec_zone *zone)
1011 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1012 fprintf(out, ";; Zone: ");
1013 ldns_rdf_print(out, ldns_dnssec_name_name(
1015 fprintf(out, "\n;\n");
1017 ldns_dnssec_rrsets_print_fmt(out, fmt,
1018 ldns_dnssec_name_find_rrset(
1022 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1023 fprintf(out, ";\n");
1027 ldns_dnssec_zone_names_print_fmt(out, fmt,
1028 zone->names, false);
1034 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1036 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1040 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1041 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1043 ldns_dnssec_name *new_name;
1045 ldns_rdf *next_name;
1046 ldns_rbnode_t *cur_node, *next_node, *new_node;
1048 /* for the detection */
1049 uint16_t i, cur_label_count, next_label_count;
1050 uint16_t soa_label_count = 0;
1055 return LDNS_STATUS_ERR;
1057 if (zone->soa && zone->soa->name) {
1058 soa_label_count = ldns_dname_label_count(zone->soa->name);
1061 cur_node = ldns_rbtree_first(zone->names);
1062 while (cur_node != LDNS_RBTREE_NULL) {
1063 next_node = ldns_rbtree_next(cur_node);
1066 while (next_node != LDNS_RBTREE_NULL &&
1068 ((ldns_dnssec_name *)next_node->data)->is_glue
1070 next_node = ldns_rbtree_next(next_node);
1073 if (next_node == LDNS_RBTREE_NULL) {
1074 next_node = ldns_rbtree_first(zone->names);
1076 if (! cur_node->data || ! next_node->data) {
1077 return LDNS_STATUS_ERR;
1079 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1080 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1081 cur_label_count = ldns_dname_label_count(cur_name);
1082 next_label_count = ldns_dname_label_count(next_name);
1084 /* Since the names are in canonical order, we can
1085 * recognize empty non-terminals by their labels;
1086 * every label after the first one on the next owner
1087 * name is a non-terminal if it either does not exist
1088 * in the current name or is different from the same
1089 * label in the current name (counting from the end)
1091 for (i = 1; i < next_label_count - soa_label_count; i++) {
1092 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1094 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1098 l2 = ldns_dname_clone_from(next_name, i);
1100 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1101 /* We have an empty nonterminal, add it to the
1104 ldns_rbnode_t *node = NULL;
1107 if (!(ent_name = ldns_dname_clone_from(
1109 return LDNS_STATUS_MEM_ERR;
1111 if (nsec3s && zone->_nsec3params) {
1112 ldns_rdf *ent_hashed_name;
1114 if (!(ent_hashed_name =
1115 ldns_nsec3_hash_name_frm_nsec3(
1118 return LDNS_STATUS_MEM_ERR;
1119 node = ldns_rbtree_search(nsec3s,
1122 ldns_rdf_deep_free(l1);
1123 ldns_rdf_deep_free(l2);
1127 new_name = ldns_dnssec_name_new();
1129 return LDNS_STATUS_MEM_ERR;
1131 new_name->name = ent_name;
1132 if (!new_name->name) {
1133 ldns_dnssec_name_free(new_name);
1134 return LDNS_STATUS_MEM_ERR;
1136 new_name->name_alloced = true;
1137 new_node = LDNS_MALLOC(ldns_rbnode_t);
1139 ldns_dnssec_name_free(new_name);
1140 return LDNS_STATUS_MEM_ERR;
1142 new_node->key = new_name->name;
1143 new_node->data = new_name;
1144 (void)ldns_rbtree_insert(zone->names, new_node);
1145 ldns_dnssec_name_make_hashed_name(
1146 zone, new_name, NULL);
1148 (void) ldns_dnssec_zone_add_rr(zone,
1149 (ldns_rr *)node->data);
1151 ldns_rdf_deep_free(l1);
1152 ldns_rdf_deep_free(l2);
1155 /* we might have inserted a new node after
1156 * the current one so we can't just use next()
1158 if (next_node != ldns_rbtree_first(zone->names)) {
1159 cur_node = next_node;
1161 cur_node = LDNS_RBTREE_NULL;
1164 return LDNS_STATUS_OK;
1168 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1170 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1174 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1177 ldns_rbnode_t* node;
1179 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1180 node = ldns_rbtree_first(zone->names);
1181 while (node != LDNS_RBTREE_NULL) {
1182 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1183 if (nsec3 &&ldns_rr_get_type(nsec3)
1184 == LDNS_RR_TYPE_NSEC3 &&
1185 ldns_nsec3_optout(nsec3)) {
1188 node = ldns_rbtree_next(node);