2 * special zone file structures and functions for better dnssec handling
5 #include <ldns/config.h>
12 ldns_dnssec_rrs *new_rrs;
13 new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
20 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
22 ldns_dnssec_rrs *next;
26 ldns_rr_free(rrs->rr);
34 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
36 ldns_dnssec_rrs_free_internal(rrs, 0);
40 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
42 ldns_dnssec_rrs_free_internal(rrs, 1);
46 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
49 ldns_dnssec_rrs *new_rrs;
51 return LDNS_STATUS_ERR;
54 /* this could be done more efficiently; name and type should already
56 cmp = ldns_rr_compare(rrs->rr,
58 /* should we error on equal? */
61 return ldns_dnssec_rrs_add_rr(rrs->next, rr);
63 new_rrs = ldns_dnssec_rrs_new();
68 /* put the current old rr in the new next, put the new
69 rr in the current container */
70 new_rrs = ldns_dnssec_rrs_new();
71 new_rrs->rr = rrs->rr;
72 new_rrs->next = rrs->next;
76 return LDNS_STATUS_OK;
80 ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
83 fprintf(out, "<void>");
86 ldns_rr_print(out, rrs->rr);
89 ldns_dnssec_rrs_print(out, rrs->next);
95 ldns_dnssec_rrsets_new()
97 ldns_dnssec_rrsets *new_rrsets;
98 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
99 new_rrsets->rrs = NULL;
100 new_rrsets->type = 0;
101 new_rrsets->signatures = NULL;
102 new_rrsets->next = NULL;
107 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
111 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
114 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
116 if (rrsets->signatures) {
117 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
124 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
126 ldns_dnssec_rrsets_free_internal(rrsets, 0);
130 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
132 ldns_dnssec_rrsets_free_internal(rrsets, 1);
136 ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
146 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
151 return LDNS_STATUS_OK;
153 return LDNS_STATUS_ERR;
157 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
159 ldns_dnssec_rrsets *new_rrsets;
160 ldns_rr_type rr_type;
163 new_rrsets = ldns_dnssec_rrsets_new();
164 rr_type = ldns_rr_get_type(rr);
165 if (rr_type == LDNS_RR_TYPE_RRSIG) {
167 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
172 new_rrsets->rrs = ldns_dnssec_rrs_new();
173 new_rrsets->rrs->rr = rr;
175 new_rrsets->signatures = ldns_dnssec_rrs_new();
176 new_rrsets->signatures->rr = rr;
178 new_rrsets->type = rr_type;
183 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
185 ldns_dnssec_rrsets *new_rrsets;
186 ldns_rr_type rr_type;
188 ldns_status result = LDNS_STATUS_OK;
190 if (!rrsets || !rr) {
191 return LDNS_STATUS_ERR;
194 rr_type = ldns_rr_get_type(rr);
196 if (rr_type == LDNS_RR_TYPE_RRSIG) {
198 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
201 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
203 rrsets->rrs = ldns_dnssec_rrs_new();
204 rrsets->rrs->rr = rr;
205 rrsets->type = rr_type;
207 rrsets->signatures = ldns_dnssec_rrs_new();
208 rrsets->signatures->rr = rr;
209 rrsets->type = rr_type;
211 return LDNS_STATUS_OK;
214 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
216 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
218 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
219 rrsets->next = new_rrsets;
221 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
222 /* move the current one into the new next,
223 replace field of current with data from new rr */
224 new_rrsets = ldns_dnssec_rrsets_new();
225 new_rrsets->rrs = rrsets->rrs;
226 new_rrsets->type = rrsets->type;
227 new_rrsets->signatures = rrsets->signatures;
228 new_rrsets->next = rrsets->next;
230 rrsets->rrs = ldns_dnssec_rrs_new();
231 rrsets->rrs->rr = rr;
232 rrsets->signatures = NULL;
235 rrsets->signatures = ldns_dnssec_rrs_new();
236 rrsets->signatures->rr = rr;
238 rrsets->type = rr_type;
239 rrsets->next = new_rrsets;
241 /* equal, add to current rrsets */
243 if (rrsets->signatures) {
244 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
246 rrsets->signatures = ldns_dnssec_rrs_new();
247 rrsets->signatures->rr = rr;
251 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
253 rrsets->rrs = ldns_dnssec_rrs_new();
254 rrsets->rrs->rr = rr;
263 ldns_dnssec_rrsets_print_soa(FILE *out,
264 ldns_dnssec_rrsets *rrsets,
269 fprintf(out, "<void>\n");
273 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
276 ldns_dnssec_rrs_print(out, rrsets->rrs);
277 if (rrsets->signatures) {
278 ldns_dnssec_rrs_print(out, rrsets->signatures);
281 if (follow && rrsets->next) {
282 ldns_dnssec_rrsets_print_soa(out, rrsets->next, follow, show_soa);
288 ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
290 ldns_dnssec_rrsets_print_soa(out, rrsets, follow, true);
294 ldns_dnssec_name_new()
296 ldns_dnssec_name *new_name;
298 new_name = LDNS_MALLOC(ldns_dnssec_name);
303 new_name->name = NULL;
304 new_name->rrsets = NULL;
305 new_name->name_alloced = false;
306 new_name->nsec = NULL;
307 new_name->nsec_signatures = NULL;
309 new_name->is_glue = false;
310 new_name->hashed_name = NULL;
316 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
318 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
320 new_name->name = ldns_rr_owner(rr);
321 ldns_dnssec_name_add_rr(new_name, rr);
327 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
331 if (name->name_alloced) {
332 ldns_rdf_deep_free(name->name);
335 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
337 if (name->nsec && deep) {
338 ldns_rr_free(name->nsec);
340 if (name->nsec_signatures) {
341 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
343 if (name->hashed_name) {
345 ldns_rdf_deep_free(name->hashed_name);
353 ldns_dnssec_name_free(ldns_dnssec_name *name)
355 ldns_dnssec_name_free_internal(name, 0);
359 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
361 ldns_dnssec_name_free_internal(name, 1);
365 ldns_dnssec_name_name(ldns_dnssec_name *name)
374 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
377 if (rrset && dname) {
383 ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
392 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
400 ldns_dnssec_name_cmp(const void *a, const void *b)
402 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
403 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
406 return ldns_dname_compare(ldns_dnssec_name_name(na),
407 ldns_dnssec_name_name(nb));
418 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
421 ldns_status result = LDNS_STATUS_OK;
423 bool hashed_name = false;
424 ldns_rr_type rr_type;
425 ldns_rr_type typecovered = 0;
427 /* special handling for NSEC3 and NSECX covering RRSIGS */
430 return LDNS_STATUS_ERR;
433 rr_type = ldns_rr_get_type(rr);
435 if (rr_type == LDNS_RR_TYPE_RRSIG) {
436 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
440 if (rr_type == LDNS_RR_TYPE_NSEC3 ||
441 typecovered == LDNS_RR_TYPE_NSEC3) {
442 name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
443 ldns_dnssec_name_name(name));
446 name_name = ldns_dnssec_name_name(name);
449 name_name = ldns_dnssec_name_name(name);
450 #endif /* HAVE_SSL */
452 if (rr_type == LDNS_RR_TYPE_NSEC ||
453 rr_type == LDNS_RR_TYPE_NSEC3) {
454 /* XX check if is already set (and error?) */
456 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
457 typecovered == LDNS_RR_TYPE_NSEC3) {
458 if (name->nsec_signatures) {
459 ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
461 name->nsec_signatures = ldns_dnssec_rrs_new();
462 name->nsec_signatures->rr = rr;
465 /* it's a 'normal' RR, add it to the right rrset */
467 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
469 name->rrsets = ldns_dnssec_rrsets_new();
470 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
475 ldns_rdf_deep_free(name_name);
482 ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
484 ldns_dnssec_rrsets *result;
486 result = name->rrsets;
488 if (result->type == type) {
491 result = result->next;
498 ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
504 if (!zone || !dname) {
508 node = ldns_rbtree_search(zone->names, dname);
510 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
518 print_indent(FILE *out, int c)
521 for (i=0; i<c; i++) {
527 ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
531 ldns_dnssec_rrsets_print_soa(out, name->rrsets, true, show_soa);
533 fprintf(out, ";; Empty nonterminal: ");
534 ldns_rdf_print(out, name->name);
538 ldns_rr_print(out, name->nsec);
540 if (name->nsec_signatures) {
541 ldns_dnssec_rrs_print(out, name->nsec_signatures);
544 fprintf(out, "<void>\n");
549 ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
551 ldns_dnssec_name_print_soa(out, name, true);
555 ldns_dnssec_zone_new()
557 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
565 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
567 ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
572 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
574 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
579 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
583 /* destroy all name structures within the tree */
584 ldns_traverse_postorder(zone->names,
585 ldns_dnssec_name_node_free,
594 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
598 /* destroy all name structures within the tree */
599 ldns_traverse_postorder(zone->names,
600 ldns_dnssec_name_node_deep_free,
608 /* use for dname comparison in tree */
610 ldns_dname_compare_v(const void *a, const void *b) {
611 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
616 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
618 ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
619 ldns_dnssec_name *current_name;
620 ldns_rdf *hashed_name;
622 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
624 while (current_node != LDNS_RBTREE_NULL) {
625 current_name = (ldns_dnssec_name *) current_node->data;
626 if (!current_name->hashed_name) {
627 current_name->hashed_name =
628 ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
630 if (ldns_dname_compare(hashed_name,
631 current_name->hashed_name)
633 ldns_rdf_deep_free(hashed_name);
636 current_node = ldns_rbtree_next(current_node);
638 ldns_rdf_deep_free(hashed_name);
643 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
645 ldns_status result = LDNS_STATUS_OK;
646 ldns_dnssec_name *cur_name;
647 ldns_rbnode_t *cur_node;
648 ldns_rr_type type_covered = 0;
651 return LDNS_STATUS_ERR;
655 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
658 /* we need the original of the hashed name if this is
659 an NSEC3, or an RRSIG that covers an NSEC3 */
660 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
661 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
663 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
664 type_covered == LDNS_RR_TYPE_NSEC3) {
665 cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
668 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
671 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
676 cur_name = ldns_dnssec_name_new_frm_rr(rr);
677 cur_node = LDNS_MALLOC(ldns_rbnode_t);
678 cur_node->key = ldns_rr_owner(rr);
679 cur_node->data = cur_name;
680 ldns_rbtree_insert(zone->names, cur_node);
682 cur_name = (ldns_dnssec_name *) cur_node->data;
683 ldns_dnssec_name_add_rr(cur_name, rr);
686 if (result != LDNS_STATUS_OK) {
687 fprintf(stderr, "error adding rr: ");
688 ldns_rr_print(stderr, rr);
691 /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
692 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
693 zone->soa = cur_name;
698 #endif /* HAVE_SSL */
701 ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
704 ldns_dnssec_name *name;
706 node = ldns_rbtree_first(tree);
707 while (node != LDNS_RBTREE_NULL) {
708 name = (ldns_dnssec_name *) node->data;
709 ldns_dnssec_name_print_soa(out, name, print_soa);
711 node = ldns_rbtree_next(node);
716 ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
720 fprintf(out, ";; Zone: ");
721 ldns_rdf_print(out, ldns_dnssec_name_name(zone->soa));
722 fprintf(out, "\n;\n");
723 ldns_dnssec_rrsets_print(
725 ldns_dnssec_name_find_rrset(zone->soa,
732 ldns_dnssec_zone_names_print(out, zone->names, false);
738 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
740 ldns_dnssec_name *new_name;
743 ldns_rbnode_t *cur_node, *next_node, *new_node;
745 /* for the detection */
746 uint16_t i, cur_label_count, next_label_count;
747 uint16_t soa_label_count = 0;
752 return LDNS_STATUS_ERR;
754 if (zone->soa && zone->soa->name) {
755 soa_label_count = ldns_dname_label_count(zone->soa->name);
758 cur_node = ldns_rbtree_first(zone->names);
759 while (cur_node != LDNS_RBTREE_NULL) {
760 next_node = ldns_rbtree_next(cur_node);
763 while (next_node != LDNS_RBTREE_NULL &&
765 ((ldns_dnssec_name *)next_node->data)->is_glue
767 next_node = ldns_rbtree_next(next_node);
770 if (next_node == LDNS_RBTREE_NULL) {
771 next_node = ldns_rbtree_first(zone->names);
774 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
775 next_name = ((ldns_dnssec_name *)next_node->data)->name;
776 cur_label_count = ldns_dname_label_count(cur_name);
777 next_label_count = ldns_dname_label_count(next_name);
779 /* Since the names are in canonical order, we can
780 * recognize empty non-terminals by their labels;
781 * every label after the first one on the next owner
782 * name is a non-terminal if it either does not exist
783 * in the current name or is different from the same
784 * label in the current name (counting from the end)
786 for (i = 1; i < next_label_count - soa_label_count; i++) {
787 lpos = cur_label_count - next_label_count + i;
789 l1 = ldns_dname_label(cur_name, lpos);
793 l2 = ldns_dname_label(next_name, i);
795 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
796 /* We have an empty nonterminal, add it to the
799 new_name = ldns_dnssec_name_new();
801 return LDNS_STATUS_MEM_ERR;
803 new_name->name = ldns_dname_clone_from(next_name,
806 ldns_dnssec_name_free(new_name);
807 return LDNS_STATUS_MEM_ERR;
809 new_name->name_alloced = true;
810 new_node = LDNS_MALLOC(ldns_rbnode_t);
812 ldns_dnssec_name_free(new_name);
813 return LDNS_STATUS_MEM_ERR;
815 new_node->key = new_name->name;
816 new_node->data = new_name;
817 ldns_rbtree_insert(zone->names, new_node);
819 ldns_rdf_deep_free(l1);
820 ldns_rdf_deep_free(l2);
823 /* we might have inserted a new node after
824 * the current one so we can't just use next()
826 if (next_node != ldns_rbtree_first(zone->names)) {
827 cur_node = next_node;
829 cur_node = LDNS_RBTREE_NULL;
832 return LDNS_STATUS_OK;