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);
302 ldns_dnssec_rrsets_print_soa(FILE *out,
303 ldns_dnssec_rrsets *rrsets,
307 ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default,
308 rrsets, follow, show_soa);
313 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
314 ldns_dnssec_rrsets *rrsets,
317 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
321 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
323 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
328 ldns_dnssec_name_new(void)
330 ldns_dnssec_name *new_name;
332 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
337 * not needed anymore because CALLOC initalizes everything to zero.
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;
345 new_name->is_glue = false;
346 new_name->hashed_name = NULL;
353 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
355 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
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);
367 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
371 if (name->name_alloced) {
372 ldns_rdf_deep_free(name->name);
375 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
377 if (name->nsec && deep) {
378 ldns_rr_free(name->nsec);
380 if (name->nsec_signatures) {
381 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
383 if (name->hashed_name) {
385 ldns_rdf_deep_free(name->hashed_name);
393 ldns_dnssec_name_free(ldns_dnssec_name *name)
395 ldns_dnssec_name_free_internal(name, 0);
399 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
401 ldns_dnssec_name_free_internal(name, 1);
405 ldns_dnssec_name_name(ldns_dnssec_name *name)
414 ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
417 return name->is_glue;
423 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
426 if (rrset && dname) {
432 ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
441 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
449 ldns_dnssec_name_cmp(const void *a, const void *b)
451 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
452 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
455 return ldns_dname_compare(ldns_dnssec_name_name(na),
456 ldns_dnssec_name_name(nb));
467 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
470 ldns_status result = LDNS_STATUS_OK;
472 bool hashed_name = false;
473 ldns_rr_type rr_type;
474 ldns_rr_type typecovered = 0;
476 /* special handling for NSEC3 and NSECX covering RRSIGS */
479 return LDNS_STATUS_ERR;
482 rr_type = ldns_rr_get_type(rr);
484 if (rr_type == LDNS_RR_TYPE_RRSIG) {
485 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
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));
495 name_name = ldns_dnssec_name_name(name);
498 name_name = ldns_dnssec_name_name(name);
499 #endif /* HAVE_SSL */
501 if (rr_type == LDNS_RR_TYPE_NSEC ||
502 rr_type == LDNS_RR_TYPE_NSEC3) {
503 /* XX check if is already set (and error?) */
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);
510 name->nsec_signatures = ldns_dnssec_rrs_new();
511 name->nsec_signatures->rr = rr;
514 /* it's a 'normal' RR, add it to the right rrset */
516 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
518 name->rrsets = ldns_dnssec_rrsets_new();
519 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
524 ldns_rdf_deep_free(name_name);
531 ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
533 ldns_dnssec_rrsets *result;
535 result = name->rrsets;
537 if (result->type == type) {
540 result = result->next;
547 ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
553 if (!zone || !dname) {
557 node = ldns_rbtree_search(zone->names, dname);
559 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
567 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
568 ldns_dnssec_name *name,
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);
581 ldns_rr_print_fmt(out, fmt, name->nsec);
583 if (name->nsec_signatures) {
584 ldns_dnssec_rrs_print_fmt(out, fmt,
585 name->nsec_signatures);
587 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
588 fprintf(out, "; <void>\n");
593 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
595 ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default,
600 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
601 ldns_dnssec_name *name)
603 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
607 ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
609 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
614 ldns_dnssec_zone_new(void)
616 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
617 if(!zone) return NULL;
625 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
627 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
628 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
631 /* When the zone is first read into an list and then inserted into an
632 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
633 * to each other. Because ldns-verify-zone (the only program that uses this
634 * function) uses the rbtree mostly for sequentual walking, this results
635 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
637 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
640 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
641 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
646 ldns_rdf *my_origin = NULL;
647 ldns_rdf *my_prev = NULL;
649 ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
650 /* when reading NSEC3s, there is a chance that we encounter nsecs
651 for empty nonterminals, whose nonterminals we cannot derive yet
652 because the needed information is to be read later. in that case
653 we keep a list of those nsec3's and retry to add them later */
654 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
655 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
657 ldns_status status = LDNS_STATUS_MEM_ERR;
659 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
660 ldns_zone* zone = NULL;
661 if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
662 != LDNS_STATUS_OK) goto error;
664 uint32_t my_ttl = ttl;
667 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
670 if (!(my_origin = ldns_rdf_clone(origin))) goto error;
671 if (!(my_prev = ldns_rdf_clone(origin))) goto error;
674 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
675 if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
676 != LDNS_STATUS_OK) goto error;
678 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680 status = LDNS_STATUS_OK;
683 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
690 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
692 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
694 if (rr_is_rrsig_covering(cur_rr,
695 LDNS_RR_TYPE_NSEC3)){
696 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
699 ldns_rr_list_push_rr(todo_nsec3s,
702 } else if (status != LDNS_STATUS_OK)
708 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
709 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
710 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
713 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
714 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
722 if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
723 (void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
724 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
725 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
726 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
728 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
729 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
730 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
732 } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
733 for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){
734 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
735 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
739 ldns_rr_list_free(todo_nsec3_rrsigs);
740 ldns_rr_list_free(todo_nsec3s);
745 ldns_dnssec_zone_free(newzone);
748 return LDNS_STATUS_OK;
751 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
753 ldns_zone_free(zone);
757 ldns_rdf_deep_free(my_origin);
760 ldns_rdf_deep_free(my_prev);
763 ldns_dnssec_zone_free(newzone);
769 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
770 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
772 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
776 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
778 ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
783 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
785 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
790 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
794 /* destroy all name structures within the tree */
795 ldns_traverse_postorder(zone->names,
796 ldns_dnssec_name_node_free,
798 LDNS_FREE(zone->names);
805 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
809 /* destroy all name structures within the tree */
810 ldns_traverse_postorder(zone->names,
811 ldns_dnssec_name_node_deep_free,
813 LDNS_FREE(zone->names);
819 /* use for dname comparison in tree */
821 ldns_dname_compare_v(const void *a, const void *b) {
822 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
826 static ldns_rbnode_t *
827 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
829 ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
830 ldns_dnssec_name *current_name;
831 ldns_rdf *hashed_name;
833 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
835 while (current_node != LDNS_RBTREE_NULL) {
836 current_name = (ldns_dnssec_name *) current_node->data;
837 if (!current_name->hashed_name) {
838 current_name->hashed_name =
839 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
841 if (ldns_dname_compare(hashed_name,
842 current_name->hashed_name)
844 ldns_rdf_deep_free(hashed_name);
847 current_node = ldns_rbtree_next(current_node);
849 ldns_rdf_deep_free(hashed_name);
854 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
856 ldns_status result = LDNS_STATUS_OK;
857 ldns_dnssec_name *cur_name;
858 ldns_rbnode_t *cur_node;
859 ldns_rr_type type_covered = 0;
862 return LDNS_STATUS_ERR;
866 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
867 if(!zone->names) return LDNS_STATUS_MEM_ERR;
870 /* we need the original of the hashed name if this is
871 an NSEC3, or an RRSIG that covers an NSEC3 */
872 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
873 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
875 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
876 type_covered == LDNS_RR_TYPE_NSEC3) {
877 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
880 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
883 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
888 cur_name = ldns_dnssec_name_new_frm_rr(rr);
889 if(!cur_name) return LDNS_STATUS_MEM_ERR;
890 cur_node = LDNS_MALLOC(ldns_rbnode_t);
892 ldns_dnssec_name_free(cur_name);
893 return LDNS_STATUS_MEM_ERR;
895 cur_node->key = ldns_rr_owner(rr);
896 cur_node->data = cur_name;
897 (void)ldns_rbtree_insert(zone->names, cur_node);
899 cur_name = (ldns_dnssec_name *) cur_node->data;
900 result = ldns_dnssec_name_add_rr(cur_name, rr);
903 if (result != LDNS_STATUS_OK) {
904 fprintf(stderr, "error adding rr: ");
905 ldns_rr_print(stderr, rr);
908 /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
909 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
910 zone->soa = cur_name;
915 #endif /* HAVE_SSL */
918 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
923 ldns_dnssec_name *name;
925 node = ldns_rbtree_first(tree);
926 while (node != LDNS_RBTREE_NULL) {
927 name = (ldns_dnssec_name *) node->data;
928 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
929 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
931 node = ldns_rbtree_next(node);
936 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
938 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
943 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
944 ldns_dnssec_zone *zone)
948 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
949 fprintf(out, ";; Zone: ");
950 ldns_rdf_print(out, ldns_dnssec_name_name(
952 fprintf(out, "\n;\n");
954 ldns_dnssec_rrsets_print_fmt(out, fmt,
955 ldns_dnssec_name_find_rrset(
959 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
964 ldns_dnssec_zone_names_print_fmt(out, fmt,
971 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
973 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
977 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
979 ldns_dnssec_name *new_name;
982 ldns_rbnode_t *cur_node, *next_node, *new_node;
984 /* for the detection */
985 uint16_t i, cur_label_count, next_label_count;
986 uint16_t soa_label_count = 0;
991 return LDNS_STATUS_ERR;
993 if (zone->soa && zone->soa->name) {
994 soa_label_count = ldns_dname_label_count(zone->soa->name);
997 cur_node = ldns_rbtree_first(zone->names);
998 while (cur_node != LDNS_RBTREE_NULL) {
999 next_node = ldns_rbtree_next(cur_node);
1002 while (next_node != LDNS_RBTREE_NULL &&
1004 ((ldns_dnssec_name *)next_node->data)->is_glue
1006 next_node = ldns_rbtree_next(next_node);
1009 if (next_node == LDNS_RBTREE_NULL) {
1010 next_node = ldns_rbtree_first(zone->names);
1013 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1014 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1015 cur_label_count = ldns_dname_label_count(cur_name);
1016 next_label_count = ldns_dname_label_count(next_name);
1018 /* Since the names are in canonical order, we can
1019 * recognize empty non-terminals by their labels;
1020 * every label after the first one on the next owner
1021 * name is a non-terminal if it either does not exist
1022 * in the current name or is different from the same
1023 * label in the current name (counting from the end)
1025 for (i = 1; i < next_label_count - soa_label_count; i++) {
1026 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1028 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1032 l2 = ldns_dname_clone_from(next_name, i);
1034 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1035 /* We have an empty nonterminal, add it to the
1038 new_name = ldns_dnssec_name_new();
1040 return LDNS_STATUS_MEM_ERR;
1042 new_name->name = ldns_dname_clone_from(next_name,
1044 if (!new_name->name) {
1045 ldns_dnssec_name_free(new_name);
1046 return LDNS_STATUS_MEM_ERR;
1048 new_name->name_alloced = true;
1049 new_node = LDNS_MALLOC(ldns_rbnode_t);
1051 ldns_dnssec_name_free(new_name);
1052 return LDNS_STATUS_MEM_ERR;
1054 new_node->key = new_name->name;
1055 new_node->data = new_name;
1056 (void)ldns_rbtree_insert(zone->names, new_node);
1058 ldns_rdf_deep_free(l1);
1059 ldns_rdf_deep_free(l2);
1062 /* we might have inserted a new node after
1063 * the current one so we can't just use next()
1065 if (next_node != ldns_rbtree_first(zone->names)) {
1066 cur_node = next_node;
1068 cur_node = LDNS_RBTREE_NULL;
1071 return LDNS_STATUS_OK;
1075 ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
1078 ldns_rbnode_t* node;
1080 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1081 node = ldns_rbtree_first(zone->names);
1082 while (node != LDNS_RBTREE_NULL) {
1083 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1084 if (nsec3 &&ldns_rr_get_type(nsec3)
1085 == LDNS_RR_TYPE_NSEC3 &&
1086 ldns_nsec3_optout(nsec3)) {
1089 node = ldns_rbtree_next(node);