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,
59 /* should we error on equal? */
62 return ldns_dnssec_rrs_add_rr(rrs->next, rr);
64 new_rrs = ldns_dnssec_rrs_new();
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;
77 return LDNS_STATUS_OK;
81 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
85 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86 fprintf(out, "; <void>");
89 ldns_rr_print_fmt(out, fmt, rrs->rr);
92 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
98 ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
100 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
105 ldns_dnssec_rrsets_new(void)
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;
118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
122 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
125 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
127 if (rrsets->signatures) {
128 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
137 ldns_dnssec_rrsets_free_internal(rrsets, 0);
141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
143 ldns_dnssec_rrsets_free_internal(rrsets, 1);
147 ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
162 return LDNS_STATUS_OK;
164 return LDNS_STATUS_ERR;
167 static ldns_dnssec_rrsets *
168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
170 ldns_dnssec_rrsets *new_rrsets;
171 ldns_rr_type rr_type;
174 new_rrsets = ldns_dnssec_rrsets_new();
175 rr_type = ldns_rr_get_type(rr);
176 if (rr_type == LDNS_RR_TYPE_RRSIG) {
178 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
183 new_rrsets->rrs = ldns_dnssec_rrs_new();
184 new_rrsets->rrs->rr = rr;
186 new_rrsets->signatures = ldns_dnssec_rrs_new();
187 new_rrsets->signatures->rr = rr;
189 new_rrsets->type = rr_type;
194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
196 ldns_dnssec_rrsets *new_rrsets;
197 ldns_rr_type rr_type;
199 ldns_status result = LDNS_STATUS_OK;
201 if (!rrsets || !rr) {
202 return LDNS_STATUS_ERR;
205 rr_type = ldns_rr_get_type(rr);
207 if (rr_type == LDNS_RR_TYPE_RRSIG) {
209 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
212 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
214 rrsets->rrs = ldns_dnssec_rrs_new();
215 rrsets->rrs->rr = rr;
216 rrsets->type = rr_type;
218 rrsets->signatures = ldns_dnssec_rrs_new();
219 rrsets->signatures->rr = rr;
220 rrsets->type = rr_type;
222 return LDNS_STATUS_OK;
225 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
227 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
229 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230 rrsets->next = new_rrsets;
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;
241 rrsets->rrs = ldns_dnssec_rrs_new();
242 rrsets->rrs->rr = rr;
243 rrsets->signatures = NULL;
246 rrsets->signatures = ldns_dnssec_rrs_new();
247 rrsets->signatures->rr = rr;
249 rrsets->type = rr_type;
250 rrsets->next = new_rrsets;
252 /* equal, add to current rrsets */
254 if (rrsets->signatures) {
255 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
257 rrsets->signatures = ldns_dnssec_rrs_new();
258 rrsets->signatures->rr = rr;
262 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
264 rrsets->rrs = ldns_dnssec_rrs_new();
265 rrsets->rrs->rr = rr;
274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275 ldns_dnssec_rrsets *rrsets,
280 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281 fprintf(out, "; <void>\n");
285 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
288 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289 if (rrsets->signatures) {
290 ldns_dnssec_rrs_print_fmt(out, fmt,
294 if (follow && rrsets->next) {
295 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
296 rrsets->next, follow, show_soa);
303 ldns_dnssec_rrsets_print_soa(FILE *out,
304 ldns_dnssec_rrsets *rrsets,
308 ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default,
309 rrsets, follow, show_soa);
314 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
315 ldns_dnssec_rrsets *rrsets,
318 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
322 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
324 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
329 ldns_dnssec_name_new(void)
331 ldns_dnssec_name *new_name;
333 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
338 * not needed anymore because CALLOC initalizes everything to zero.
340 new_name->name = NULL;
341 new_name->rrsets = NULL;
342 new_name->name_alloced = false;
343 new_name->nsec = NULL;
344 new_name->nsec_signatures = NULL;
346 new_name->is_glue = false;
347 new_name->hashed_name = NULL;
354 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
356 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
358 new_name->name = ldns_rr_owner(rr);
359 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
360 ldns_dnssec_name_free(new_name);
368 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
372 if (name->name_alloced) {
373 ldns_rdf_deep_free(name->name);
376 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
378 if (name->nsec && deep) {
379 ldns_rr_free(name->nsec);
381 if (name->nsec_signatures) {
382 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
384 if (name->hashed_name) {
386 ldns_rdf_deep_free(name->hashed_name);
394 ldns_dnssec_name_free(ldns_dnssec_name *name)
396 ldns_dnssec_name_free_internal(name, 0);
400 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
402 ldns_dnssec_name_free_internal(name, 1);
406 ldns_dnssec_name_name(ldns_dnssec_name *name)
415 ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
418 return name->is_glue;
424 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
427 if (rrset && dname) {
434 ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
444 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
452 ldns_dnssec_name_cmp(const void *a, const void *b)
454 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
455 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
458 return ldns_dname_compare(ldns_dnssec_name_name(na),
459 ldns_dnssec_name_name(nb));
470 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
473 ldns_status result = LDNS_STATUS_OK;
475 bool hashed_name = false;
476 ldns_rr_type rr_type;
477 ldns_rr_type typecovered = 0;
479 /* special handling for NSEC3 and NSECX covering RRSIGS */
482 return LDNS_STATUS_ERR;
485 rr_type = ldns_rr_get_type(rr);
487 if (rr_type == LDNS_RR_TYPE_RRSIG) {
488 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
492 if (rr_type == LDNS_RR_TYPE_NSEC3 ||
493 typecovered == LDNS_RR_TYPE_NSEC3) {
494 name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
495 ldns_dnssec_name_name(name));
498 name_name = ldns_dnssec_name_name(name);
501 name_name = ldns_dnssec_name_name(name);
502 #endif /* HAVE_SSL */
504 if (rr_type == LDNS_RR_TYPE_NSEC ||
505 rr_type == LDNS_RR_TYPE_NSEC3) {
506 /* XX check if is already set (and error?) */
508 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
509 typecovered == LDNS_RR_TYPE_NSEC3) {
510 if (name->nsec_signatures) {
511 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
513 name->nsec_signatures = ldns_dnssec_rrs_new();
514 name->nsec_signatures->rr = rr;
517 /* it's a 'normal' RR, add it to the right rrset */
519 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
521 name->rrsets = ldns_dnssec_rrsets_new();
522 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
527 ldns_rdf_deep_free(name_name);
534 ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
536 ldns_dnssec_rrsets *result;
538 result = name->rrsets;
540 if (result->type == type) {
543 result = result->next;
550 ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
556 if (!zone || !dname) {
560 node = ldns_rbtree_search(zone->names, dname);
562 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
570 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
571 ldns_dnssec_name *name,
576 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
577 name->rrsets, true, show_soa);
578 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
579 fprintf(out, ";; Empty nonterminal: ");
580 ldns_rdf_print(out, name->name);
584 ldns_rr_print_fmt(out, fmt, name->nsec);
586 if (name->nsec_signatures) {
587 ldns_dnssec_rrs_print_fmt(out, fmt,
588 name->nsec_signatures);
590 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
591 fprintf(out, "; <void>\n");
597 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
599 ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default,
605 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
606 ldns_dnssec_name *name)
608 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
612 ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
614 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
619 ldns_dnssec_zone_new(void)
621 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
622 if(!zone) return NULL;
630 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
632 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
633 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
636 /* When the zone is first read into an list and then inserted into an
637 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
638 * to each other. Because ldns-verify-zone (the only program that uses this
639 * function) uses the rbtree mostly for sequentual walking, this results
640 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
642 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
645 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
646 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
651 ldns_rdf *my_origin = NULL;
652 ldns_rdf *my_prev = NULL;
654 ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
655 /* when reading NSEC3s, there is a chance that we encounter nsecs
656 for empty nonterminals, whose nonterminals we cannot derive yet
657 because the needed information is to be read later. in that case
658 we keep a list of those nsec3's and retry to add them later */
659 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
660 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
662 ldns_status status = LDNS_STATUS_MEM_ERR;
664 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
665 ldns_zone* zone = NULL;
666 if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
667 != LDNS_STATUS_OK) goto error;
669 uint32_t my_ttl = ttl;
672 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
675 if (!(my_origin = ldns_rdf_clone(origin))) goto error;
676 if (!(my_prev = ldns_rdf_clone(origin))) goto error;
679 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
680 if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
681 != LDNS_STATUS_OK) goto error;
683 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
684 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
685 status = LDNS_STATUS_OK;
688 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
695 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
697 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
699 if (rr_is_rrsig_covering(cur_rr,
700 LDNS_RR_TYPE_NSEC3)){
701 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
704 ldns_rr_list_push_rr(todo_nsec3s,
707 } else if (status != LDNS_STATUS_OK)
713 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
714 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
715 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
716 status = LDNS_STATUS_OK;
719 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
720 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
728 if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
729 (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
730 for (i = 0; status == LDNS_STATUS_OK &&
731 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
732 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
733 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
735 for (i = 0; status == LDNS_STATUS_OK &&
736 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
738 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
739 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
741 } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
742 for (i = 0; status == LDNS_STATUS_OK &&
743 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
745 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
746 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
754 ldns_dnssec_zone_free(newzone);
758 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
760 ldns_zone_free(zone);
763 ldns_rr_list_free(todo_nsec3_rrsigs);
764 ldns_rr_list_free(todo_nsec3s);
767 ldns_rdf_deep_free(my_origin);
770 ldns_rdf_deep_free(my_prev);
773 ldns_dnssec_zone_free(newzone);
779 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
780 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
782 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
786 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
788 ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
793 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
795 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
800 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
804 /* destroy all name structures within the tree */
805 ldns_traverse_postorder(zone->names,
806 ldns_dnssec_name_node_free,
808 LDNS_FREE(zone->names);
815 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
819 /* destroy all name structures within the tree */
820 ldns_traverse_postorder(zone->names,
821 ldns_dnssec_name_node_deep_free,
823 LDNS_FREE(zone->names);
829 /* use for dname comparison in tree */
831 ldns_dname_compare_v(const void *a, const void *b) {
832 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
835 static ldns_rbnode_t *
836 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
838 ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
839 ldns_dnssec_name *current_name;
840 ldns_rdf *hashed_name;
842 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
844 while (current_node != LDNS_RBTREE_NULL) {
845 current_name = (ldns_dnssec_name *) current_node->data;
846 if (!current_name->hashed_name) {
847 current_name->hashed_name =
848 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
850 if (ldns_dname_compare(hashed_name,
851 current_name->hashed_name)
853 ldns_rdf_deep_free(hashed_name);
856 current_node = ldns_rbtree_next(current_node);
858 ldns_rdf_deep_free(hashed_name);
863 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
865 ldns_status result = LDNS_STATUS_OK;
866 ldns_dnssec_name *cur_name;
867 ldns_rbnode_t *cur_node;
868 ldns_rr_type type_covered = 0;
871 return LDNS_STATUS_ERR;
875 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
876 if(!zone->names) return LDNS_STATUS_MEM_ERR;
879 /* we need the original of the hashed name if this is
880 an NSEC3, or an RRSIG that covers an NSEC3 */
881 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
882 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
884 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
885 type_covered == LDNS_RR_TYPE_NSEC3) {
886 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
889 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
892 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
897 cur_name = ldns_dnssec_name_new_frm_rr(rr);
898 if(!cur_name) return LDNS_STATUS_MEM_ERR;
899 cur_node = LDNS_MALLOC(ldns_rbnode_t);
901 ldns_dnssec_name_free(cur_name);
902 return LDNS_STATUS_MEM_ERR;
904 cur_node->key = ldns_rr_owner(rr);
905 cur_node->data = cur_name;
906 (void)ldns_rbtree_insert(zone->names, cur_node);
908 cur_name = (ldns_dnssec_name *) cur_node->data;
909 result = ldns_dnssec_name_add_rr(cur_name, rr);
912 if (result != LDNS_STATUS_OK) {
913 fprintf(stderr, "error adding rr: ");
914 ldns_rr_print(stderr, rr);
917 /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
918 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
919 zone->soa = cur_name;
926 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
931 ldns_dnssec_name *name;
933 node = ldns_rbtree_first(tree);
934 while (node != LDNS_RBTREE_NULL) {
935 name = (ldns_dnssec_name *) node->data;
936 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
937 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
939 node = ldns_rbtree_next(node);
944 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
946 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
951 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
952 ldns_dnssec_zone *zone)
956 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
957 fprintf(out, ";; Zone: ");
958 ldns_rdf_print(out, ldns_dnssec_name_name(
960 fprintf(out, "\n;\n");
962 ldns_dnssec_rrsets_print_fmt(out, fmt,
963 ldns_dnssec_name_find_rrset(
967 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
972 ldns_dnssec_zone_names_print_fmt(out, fmt,
979 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
981 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
985 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
987 ldns_dnssec_name *new_name;
990 ldns_rbnode_t *cur_node, *next_node, *new_node;
992 /* for the detection */
993 uint16_t i, cur_label_count, next_label_count;
994 uint16_t soa_label_count = 0;
999 return LDNS_STATUS_ERR;
1001 if (zone->soa && zone->soa->name) {
1002 soa_label_count = ldns_dname_label_count(zone->soa->name);
1005 cur_node = ldns_rbtree_first(zone->names);
1006 while (cur_node != LDNS_RBTREE_NULL) {
1007 next_node = ldns_rbtree_next(cur_node);
1010 while (next_node != LDNS_RBTREE_NULL &&
1012 ((ldns_dnssec_name *)next_node->data)->is_glue
1014 next_node = ldns_rbtree_next(next_node);
1017 if (next_node == LDNS_RBTREE_NULL) {
1018 next_node = ldns_rbtree_first(zone->names);
1020 if (! cur_node->data || ! next_node->data) {
1021 return LDNS_STATUS_ERR;
1023 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1024 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1025 cur_label_count = ldns_dname_label_count(cur_name);
1026 next_label_count = ldns_dname_label_count(next_name);
1028 /* Since the names are in canonical order, we can
1029 * recognize empty non-terminals by their labels;
1030 * every label after the first one on the next owner
1031 * name is a non-terminal if it either does not exist
1032 * in the current name or is different from the same
1033 * label in the current name (counting from the end)
1035 for (i = 1; i < next_label_count - soa_label_count; i++) {
1036 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1038 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1042 l2 = ldns_dname_clone_from(next_name, i);
1044 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1045 /* We have an empty nonterminal, add it to the
1048 new_name = ldns_dnssec_name_new();
1050 return LDNS_STATUS_MEM_ERR;
1052 new_name->name = ldns_dname_clone_from(next_name,
1054 if (!new_name->name) {
1055 ldns_dnssec_name_free(new_name);
1056 return LDNS_STATUS_MEM_ERR;
1058 new_name->name_alloced = true;
1059 new_node = LDNS_MALLOC(ldns_rbnode_t);
1061 ldns_dnssec_name_free(new_name);
1062 return LDNS_STATUS_MEM_ERR;
1064 new_node->key = new_name->name;
1065 new_node->data = new_name;
1066 (void)ldns_rbtree_insert(zone->names, new_node);
1068 ldns_rdf_deep_free(l1);
1069 ldns_rdf_deep_free(l2);
1072 /* we might have inserted a new node after
1073 * the current one so we can't just use next()
1075 if (next_node != ldns_rbtree_first(zone->names)) {
1076 cur_node = next_node;
1078 cur_node = LDNS_RBTREE_NULL;
1081 return LDNS_STATUS_OK;
1085 ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
1088 ldns_rbnode_t* node;
1090 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1091 node = ldns_rbtree_first(zone->names);
1092 while (node != LDNS_RBTREE_NULL) {
1093 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1094 if (nsec3 &&ldns_rr_get_type(nsec3)
1095 == LDNS_RR_TYPE_NSEC3 &&
1096 ldns_nsec3_optout(nsec3)) {
1099 node = ldns_rbtree_next(node);