xref: /freebsd/contrib/ldns/dnssec_zone.c (revision d6e492fe3de6af8cde3cf4a02f021578e376bad5)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * special zone file structures and functions for better dnssec handling
37b5038d7SDag-Erling Smørgrav  */
47b5038d7SDag-Erling Smørgrav 
57b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
67b5038d7SDag-Erling Smørgrav 
77b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
87b5038d7SDag-Erling Smørgrav 
97b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *
107b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_new(void)
117b5038d7SDag-Erling Smørgrav {
127b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *new_rrs;
137b5038d7SDag-Erling Smørgrav 	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
147b5038d7SDag-Erling Smørgrav         if(!new_rrs) return NULL;
157b5038d7SDag-Erling Smørgrav 	new_rrs->rr = NULL;
167b5038d7SDag-Erling Smørgrav 	new_rrs->next = NULL;
177b5038d7SDag-Erling Smørgrav 	return new_rrs;
187b5038d7SDag-Erling Smørgrav }
197b5038d7SDag-Erling Smørgrav 
207b5038d7SDag-Erling Smørgrav INLINE void
217b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
227b5038d7SDag-Erling Smørgrav {
237b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *next;
247b5038d7SDag-Erling Smørgrav 	while (rrs) {
257b5038d7SDag-Erling Smørgrav 		next = rrs->next;
267b5038d7SDag-Erling Smørgrav 		if (deep) {
277b5038d7SDag-Erling Smørgrav 			ldns_rr_free(rrs->rr);
287b5038d7SDag-Erling Smørgrav 		}
297b5038d7SDag-Erling Smørgrav 		LDNS_FREE(rrs);
307b5038d7SDag-Erling Smørgrav 		rrs = next;
317b5038d7SDag-Erling Smørgrav 	}
327b5038d7SDag-Erling Smørgrav }
337b5038d7SDag-Erling Smørgrav 
347b5038d7SDag-Erling Smørgrav void
357b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
367b5038d7SDag-Erling Smørgrav {
377b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs_free_internal(rrs, 0);
387b5038d7SDag-Erling Smørgrav }
397b5038d7SDag-Erling Smørgrav 
407b5038d7SDag-Erling Smørgrav void
417b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
427b5038d7SDag-Erling Smørgrav {
437b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs_free_internal(rrs, 1);
447b5038d7SDag-Erling Smørgrav }
457b5038d7SDag-Erling Smørgrav 
467b5038d7SDag-Erling Smørgrav ldns_status
477b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
487b5038d7SDag-Erling Smørgrav {
497b5038d7SDag-Erling Smørgrav 	int cmp;
507b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs *new_rrs;
517b5038d7SDag-Erling Smørgrav 	if (!rrs || !rr) {
527b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
537b5038d7SDag-Erling Smørgrav 	}
547b5038d7SDag-Erling Smørgrav 
557b5038d7SDag-Erling Smørgrav 	/* this could be done more efficiently; name and type should already
567b5038d7SDag-Erling Smørgrav 	   be equal */
577b5038d7SDag-Erling Smørgrav 	cmp = ldns_rr_compare(rrs->rr,
587b5038d7SDag-Erling Smørgrav 					  rr);
597b5038d7SDag-Erling Smørgrav 	/* should we error on equal? */
607b5038d7SDag-Erling Smørgrav 	if (cmp <= 0) {
617b5038d7SDag-Erling Smørgrav 		if (rrs->next) {
627b5038d7SDag-Erling Smørgrav 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
637b5038d7SDag-Erling Smørgrav 		} else {
647b5038d7SDag-Erling Smørgrav 			new_rrs = ldns_dnssec_rrs_new();
657b5038d7SDag-Erling Smørgrav 			new_rrs->rr = rr;
667b5038d7SDag-Erling Smørgrav 			rrs->next = new_rrs;
677b5038d7SDag-Erling Smørgrav 		}
687b5038d7SDag-Erling Smørgrav 	} else if (cmp > 0) {
697b5038d7SDag-Erling Smørgrav 		/* put the current old rr in the new next, put the new
707b5038d7SDag-Erling Smørgrav 		   rr in the current container */
717b5038d7SDag-Erling Smørgrav 		new_rrs = ldns_dnssec_rrs_new();
727b5038d7SDag-Erling Smørgrav 		new_rrs->rr = rrs->rr;
737b5038d7SDag-Erling Smørgrav 		new_rrs->next = rrs->next;
747b5038d7SDag-Erling Smørgrav 		rrs->rr = rr;
757b5038d7SDag-Erling Smørgrav 		rrs->next = new_rrs;
767b5038d7SDag-Erling Smørgrav 	}
777b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
787b5038d7SDag-Erling Smørgrav }
797b5038d7SDag-Erling Smørgrav 
807b5038d7SDag-Erling Smørgrav void
817b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
827b5038d7SDag-Erling Smørgrav 	       ldns_dnssec_rrs *rrs)
837b5038d7SDag-Erling Smørgrav {
847b5038d7SDag-Erling Smørgrav 	if (!rrs) {
857b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
867b5038d7SDag-Erling Smørgrav 			fprintf(out, "; <void>");
877b5038d7SDag-Erling Smørgrav 	} else {
887b5038d7SDag-Erling Smørgrav 		if (rrs->rr) {
897b5038d7SDag-Erling Smørgrav 			ldns_rr_print_fmt(out, fmt, rrs->rr);
907b5038d7SDag-Erling Smørgrav 		}
917b5038d7SDag-Erling Smørgrav 		if (rrs->next) {
927b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
937b5038d7SDag-Erling Smørgrav 		}
947b5038d7SDag-Erling Smørgrav 	}
957b5038d7SDag-Erling Smørgrav }
967b5038d7SDag-Erling Smørgrav 
977b5038d7SDag-Erling Smørgrav void
987b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
997b5038d7SDag-Erling Smørgrav {
1007b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
1017b5038d7SDag-Erling Smørgrav }
1027b5038d7SDag-Erling Smørgrav 
1037b5038d7SDag-Erling Smørgrav 
1047b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
1057b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_new(void)
1067b5038d7SDag-Erling Smørgrav {
1077b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1087b5038d7SDag-Erling Smørgrav 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
1097b5038d7SDag-Erling Smørgrav         if(!new_rrsets) return NULL;
1107b5038d7SDag-Erling Smørgrav 	new_rrsets->rrs = NULL;
1117b5038d7SDag-Erling Smørgrav 	new_rrsets->type = 0;
1127b5038d7SDag-Erling Smørgrav 	new_rrsets->signatures = NULL;
1137b5038d7SDag-Erling Smørgrav 	new_rrsets->next = NULL;
1147b5038d7SDag-Erling Smørgrav 	return new_rrsets;
1157b5038d7SDag-Erling Smørgrav }
1167b5038d7SDag-Erling Smørgrav 
1177b5038d7SDag-Erling Smørgrav INLINE void
1187b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
1197b5038d7SDag-Erling Smørgrav {
1207b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1217b5038d7SDag-Erling Smørgrav 		if (rrsets->rrs) {
1227b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
1237b5038d7SDag-Erling Smørgrav 		}
1247b5038d7SDag-Erling Smørgrav 		if (rrsets->next) {
1257b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
1267b5038d7SDag-Erling Smørgrav 		}
1277b5038d7SDag-Erling Smørgrav 		if (rrsets->signatures) {
1287b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
1297b5038d7SDag-Erling Smørgrav 		}
1307b5038d7SDag-Erling Smørgrav 		LDNS_FREE(rrsets);
1317b5038d7SDag-Erling Smørgrav 	}
1327b5038d7SDag-Erling Smørgrav }
1337b5038d7SDag-Erling Smørgrav 
1347b5038d7SDag-Erling Smørgrav void
1357b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
1367b5038d7SDag-Erling Smørgrav {
1377b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
1387b5038d7SDag-Erling Smørgrav }
1397b5038d7SDag-Erling Smørgrav 
1407b5038d7SDag-Erling Smørgrav void
1417b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
1427b5038d7SDag-Erling Smørgrav {
1437b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
1447b5038d7SDag-Erling Smørgrav }
1457b5038d7SDag-Erling Smørgrav 
1467b5038d7SDag-Erling Smørgrav ldns_rr_type
1477b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
1487b5038d7SDag-Erling Smørgrav {
1497b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1507b5038d7SDag-Erling Smørgrav 		return rrsets->type;
1517b5038d7SDag-Erling Smørgrav 	} else {
1527b5038d7SDag-Erling Smørgrav 		return 0;
1537b5038d7SDag-Erling Smørgrav 	}
1547b5038d7SDag-Erling Smørgrav }
1557b5038d7SDag-Erling Smørgrav 
1567b5038d7SDag-Erling Smørgrav ldns_status
1577b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
1587b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type)
1597b5038d7SDag-Erling Smørgrav {
1607b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1617b5038d7SDag-Erling Smørgrav 		rrsets->type = type;
1627b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
1637b5038d7SDag-Erling Smørgrav 	}
1647b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_ERR;
1657b5038d7SDag-Erling Smørgrav }
1667b5038d7SDag-Erling Smørgrav 
1677b5038d7SDag-Erling Smørgrav static ldns_dnssec_rrsets *
1687b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
1697b5038d7SDag-Erling Smørgrav {
1707b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1717b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
1727b5038d7SDag-Erling Smørgrav 	bool rrsig;
1737b5038d7SDag-Erling Smørgrav 
1747b5038d7SDag-Erling Smørgrav 	new_rrsets = ldns_dnssec_rrsets_new();
1757b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
1767b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
1777b5038d7SDag-Erling Smørgrav 		rrsig = true;
1787b5038d7SDag-Erling Smørgrav 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1797b5038d7SDag-Erling Smørgrav 	} else {
1807b5038d7SDag-Erling Smørgrav 		rrsig = false;
1817b5038d7SDag-Erling Smørgrav 	}
1827b5038d7SDag-Erling Smørgrav 	if (!rrsig) {
1837b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs = ldns_dnssec_rrs_new();
1847b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs->rr = rr;
1857b5038d7SDag-Erling Smørgrav 	} else {
1867b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures = ldns_dnssec_rrs_new();
1877b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures->rr = rr;
1887b5038d7SDag-Erling Smørgrav 	}
1897b5038d7SDag-Erling Smørgrav 	new_rrsets->type = rr_type;
1907b5038d7SDag-Erling Smørgrav 	return new_rrsets;
1917b5038d7SDag-Erling Smørgrav }
1927b5038d7SDag-Erling Smørgrav 
1937b5038d7SDag-Erling Smørgrav ldns_status
1947b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
1957b5038d7SDag-Erling Smørgrav {
1967b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1977b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
1987b5038d7SDag-Erling Smørgrav 	bool rrsig = false;
1997b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
2007b5038d7SDag-Erling Smørgrav 
2017b5038d7SDag-Erling Smørgrav 	if (!rrsets || !rr) {
2027b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
2037b5038d7SDag-Erling Smørgrav 	}
2047b5038d7SDag-Erling Smørgrav 
2057b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
2067b5038d7SDag-Erling Smørgrav 
2077b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
2087b5038d7SDag-Erling Smørgrav 		rrsig = true;
2097b5038d7SDag-Erling Smørgrav 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
2107b5038d7SDag-Erling Smørgrav 	}
2117b5038d7SDag-Erling Smørgrav 
2127b5038d7SDag-Erling Smørgrav 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
2137b5038d7SDag-Erling Smørgrav 		if (!rrsig) {
2147b5038d7SDag-Erling Smørgrav 			rrsets->rrs = ldns_dnssec_rrs_new();
2157b5038d7SDag-Erling Smørgrav 			rrsets->rrs->rr = rr;
2167b5038d7SDag-Erling Smørgrav 			rrsets->type = rr_type;
2177b5038d7SDag-Erling Smørgrav 		} else {
2187b5038d7SDag-Erling Smørgrav 			rrsets->signatures = ldns_dnssec_rrs_new();
2197b5038d7SDag-Erling Smørgrav 			rrsets->signatures->rr = rr;
2207b5038d7SDag-Erling Smørgrav 			rrsets->type = rr_type;
2217b5038d7SDag-Erling Smørgrav 		}
2227b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
2237b5038d7SDag-Erling Smørgrav 	}
2247b5038d7SDag-Erling Smørgrav 
2257b5038d7SDag-Erling Smørgrav 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
2267b5038d7SDag-Erling Smørgrav 		if (rrsets->next) {
2277b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
2287b5038d7SDag-Erling Smørgrav 		} else {
2297b5038d7SDag-Erling Smørgrav 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
2307b5038d7SDag-Erling Smørgrav 			rrsets->next = new_rrsets;
2317b5038d7SDag-Erling Smørgrav 		}
2327b5038d7SDag-Erling Smørgrav 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
2337b5038d7SDag-Erling Smørgrav 		/* move the current one into the new next,
2347b5038d7SDag-Erling Smørgrav 		   replace field of current with data from new rr */
2357b5038d7SDag-Erling Smørgrav 		new_rrsets = ldns_dnssec_rrsets_new();
2367b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs = rrsets->rrs;
2377b5038d7SDag-Erling Smørgrav 		new_rrsets->type = rrsets->type;
2387b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures = rrsets->signatures;
2397b5038d7SDag-Erling Smørgrav 		new_rrsets->next = rrsets->next;
2407b5038d7SDag-Erling Smørgrav 		if (!rrsig) {
2417b5038d7SDag-Erling Smørgrav 			rrsets->rrs = ldns_dnssec_rrs_new();
2427b5038d7SDag-Erling Smørgrav 			rrsets->rrs->rr = rr;
2437b5038d7SDag-Erling Smørgrav 			rrsets->signatures = NULL;
2447b5038d7SDag-Erling Smørgrav 		} else {
2457b5038d7SDag-Erling Smørgrav 			rrsets->rrs = NULL;
2467b5038d7SDag-Erling Smørgrav 			rrsets->signatures = ldns_dnssec_rrs_new();
2477b5038d7SDag-Erling Smørgrav 			rrsets->signatures->rr = rr;
2487b5038d7SDag-Erling Smørgrav 		}
2497b5038d7SDag-Erling Smørgrav 		rrsets->type = rr_type;
2507b5038d7SDag-Erling Smørgrav 		rrsets->next = new_rrsets;
2517b5038d7SDag-Erling Smørgrav 	} else {
2527b5038d7SDag-Erling Smørgrav 		/* equal, add to current rrsets */
2537b5038d7SDag-Erling Smørgrav 		if (rrsig) {
2547b5038d7SDag-Erling Smørgrav 			if (rrsets->signatures) {
2557b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
2567b5038d7SDag-Erling Smørgrav 			} else {
2577b5038d7SDag-Erling Smørgrav 				rrsets->signatures = ldns_dnssec_rrs_new();
2587b5038d7SDag-Erling Smørgrav 				rrsets->signatures->rr = rr;
2597b5038d7SDag-Erling Smørgrav 			}
2607b5038d7SDag-Erling Smørgrav 		} else {
2617b5038d7SDag-Erling Smørgrav 			if (rrsets->rrs) {
2627b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
2637b5038d7SDag-Erling Smørgrav 			} else {
2647b5038d7SDag-Erling Smørgrav 				rrsets->rrs = ldns_dnssec_rrs_new();
2657b5038d7SDag-Erling Smørgrav 				rrsets->rrs->rr = rr;
2667b5038d7SDag-Erling Smørgrav 			}
2677b5038d7SDag-Erling Smørgrav 		}
2687b5038d7SDag-Erling Smørgrav 	}
2697b5038d7SDag-Erling Smørgrav 
2707b5038d7SDag-Erling Smørgrav 	return result;
2717b5038d7SDag-Erling Smørgrav }
2727b5038d7SDag-Erling Smørgrav 
2737b5038d7SDag-Erling Smørgrav static void
2747b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
2757b5038d7SDag-Erling Smørgrav 		ldns_dnssec_rrsets *rrsets,
2767b5038d7SDag-Erling Smørgrav 		bool follow,
2777b5038d7SDag-Erling Smørgrav 		bool show_soa)
2787b5038d7SDag-Erling Smørgrav {
2797b5038d7SDag-Erling Smørgrav 	if (!rrsets) {
2807b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
2817b5038d7SDag-Erling Smørgrav 			fprintf(out, "; <void>\n");
2827b5038d7SDag-Erling Smørgrav 	} else {
2837b5038d7SDag-Erling Smørgrav 		if (rrsets->rrs &&
2847b5038d7SDag-Erling Smørgrav 		    (show_soa ||
2857b5038d7SDag-Erling Smørgrav 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
2867b5038d7SDag-Erling Smørgrav 		    )
2877b5038d7SDag-Erling Smørgrav 		   ) {
2887b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
2897b5038d7SDag-Erling Smørgrav 			if (rrsets->signatures) {
2907b5038d7SDag-Erling Smørgrav 				ldns_dnssec_rrs_print_fmt(out, fmt,
2917b5038d7SDag-Erling Smørgrav 						rrsets->signatures);
2927b5038d7SDag-Erling Smørgrav 			}
2937b5038d7SDag-Erling Smørgrav 		}
2947b5038d7SDag-Erling Smørgrav 		if (follow && rrsets->next) {
2957b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
2967b5038d7SDag-Erling Smørgrav 					rrsets->next, follow, show_soa);
2977b5038d7SDag-Erling Smørgrav 		}
2987b5038d7SDag-Erling Smørgrav 	}
2997b5038d7SDag-Erling Smørgrav }
3007b5038d7SDag-Erling Smørgrav 
3017b5038d7SDag-Erling Smørgrav 
3027b5038d7SDag-Erling Smørgrav void
3037b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
3047b5038d7SDag-Erling Smørgrav 		ldns_dnssec_rrsets *rrsets,
3057b5038d7SDag-Erling Smørgrav 		bool follow)
3067b5038d7SDag-Erling Smørgrav {
3077b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
3087b5038d7SDag-Erling Smørgrav }
3097b5038d7SDag-Erling Smørgrav 
3107b5038d7SDag-Erling Smørgrav void
3117b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
3127b5038d7SDag-Erling Smørgrav {
3137b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
3147b5038d7SDag-Erling Smørgrav 			rrsets, follow);
3157b5038d7SDag-Erling Smørgrav }
3167b5038d7SDag-Erling Smørgrav 
3177b5038d7SDag-Erling Smørgrav ldns_dnssec_name *
3187b5038d7SDag-Erling Smørgrav ldns_dnssec_name_new(void)
3197b5038d7SDag-Erling Smørgrav {
3207b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name;
3217b5038d7SDag-Erling Smørgrav 
3227b5038d7SDag-Erling Smørgrav 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
3237b5038d7SDag-Erling Smørgrav 	if (!new_name) {
3247b5038d7SDag-Erling Smørgrav 		return NULL;
3257b5038d7SDag-Erling Smørgrav 	}
3267b5038d7SDag-Erling Smørgrav 	/*
3277b5038d7SDag-Erling Smørgrav 	 * not needed anymore because CALLOC initalizes everything to zero.
3287b5038d7SDag-Erling Smørgrav 
3297b5038d7SDag-Erling Smørgrav 	new_name->name = NULL;
3307b5038d7SDag-Erling Smørgrav 	new_name->rrsets = NULL;
3317b5038d7SDag-Erling Smørgrav 	new_name->name_alloced = false;
3327b5038d7SDag-Erling Smørgrav 	new_name->nsec = NULL;
3337b5038d7SDag-Erling Smørgrav 	new_name->nsec_signatures = NULL;
3347b5038d7SDag-Erling Smørgrav 
3357b5038d7SDag-Erling Smørgrav 	new_name->is_glue = false;
3367b5038d7SDag-Erling Smørgrav 	new_name->hashed_name = NULL;
3377b5038d7SDag-Erling Smørgrav 
3387b5038d7SDag-Erling Smørgrav 	 */
3397b5038d7SDag-Erling Smørgrav 	return new_name;
3407b5038d7SDag-Erling Smørgrav }
3417b5038d7SDag-Erling Smørgrav 
3427b5038d7SDag-Erling Smørgrav ldns_dnssec_name *
3437b5038d7SDag-Erling Smørgrav ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
3447b5038d7SDag-Erling Smørgrav {
3457b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
3467b5038d7SDag-Erling Smørgrav 
3477b5038d7SDag-Erling Smørgrav 	new_name->name = ldns_rr_owner(rr);
3487b5038d7SDag-Erling Smørgrav 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
3497b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name_free(new_name);
3507b5038d7SDag-Erling Smørgrav 		return NULL;
3517b5038d7SDag-Erling Smørgrav 	}
3527b5038d7SDag-Erling Smørgrav 
3537b5038d7SDag-Erling Smørgrav 	return new_name;
3547b5038d7SDag-Erling Smørgrav }
3557b5038d7SDag-Erling Smørgrav 
3567b5038d7SDag-Erling Smørgrav INLINE void
3577b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
3587b5038d7SDag-Erling Smørgrav                                int deep)
3597b5038d7SDag-Erling Smørgrav {
3607b5038d7SDag-Erling Smørgrav 	if (name) {
3617b5038d7SDag-Erling Smørgrav 		if (name->name_alloced) {
3627b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(name->name);
3637b5038d7SDag-Erling Smørgrav 		}
3647b5038d7SDag-Erling Smørgrav 		if (name->rrsets) {
3657b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
3667b5038d7SDag-Erling Smørgrav 		}
3677b5038d7SDag-Erling Smørgrav 		if (name->nsec && deep) {
3687b5038d7SDag-Erling Smørgrav 			ldns_rr_free(name->nsec);
3697b5038d7SDag-Erling Smørgrav 		}
3707b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
3717b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
3727b5038d7SDag-Erling Smørgrav 		}
3737b5038d7SDag-Erling Smørgrav 		if (name->hashed_name) {
3747b5038d7SDag-Erling Smørgrav 			if (deep) {
3757b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(name->hashed_name);
3767b5038d7SDag-Erling Smørgrav 			}
3777b5038d7SDag-Erling Smørgrav 		}
3787b5038d7SDag-Erling Smørgrav 		LDNS_FREE(name);
3797b5038d7SDag-Erling Smørgrav 	}
3807b5038d7SDag-Erling Smørgrav }
3817b5038d7SDag-Erling Smørgrav 
3827b5038d7SDag-Erling Smørgrav void
3837b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free(ldns_dnssec_name *name)
3847b5038d7SDag-Erling Smørgrav {
3857b5038d7SDag-Erling Smørgrav   ldns_dnssec_name_free_internal(name, 0);
3867b5038d7SDag-Erling Smørgrav }
3877b5038d7SDag-Erling Smørgrav 
3887b5038d7SDag-Erling Smørgrav void
3897b5038d7SDag-Erling Smørgrav ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
3907b5038d7SDag-Erling Smørgrav {
3917b5038d7SDag-Erling Smørgrav   ldns_dnssec_name_free_internal(name, 1);
3927b5038d7SDag-Erling Smørgrav }
3937b5038d7SDag-Erling Smørgrav 
3947b5038d7SDag-Erling Smørgrav ldns_rdf *
3957b5038d7SDag-Erling Smørgrav ldns_dnssec_name_name(ldns_dnssec_name *name)
3967b5038d7SDag-Erling Smørgrav {
3977b5038d7SDag-Erling Smørgrav 	if (name) {
3987b5038d7SDag-Erling Smørgrav 		return name->name;
3997b5038d7SDag-Erling Smørgrav 	}
4007b5038d7SDag-Erling Smørgrav 	return NULL;
4017b5038d7SDag-Erling Smørgrav }
4027b5038d7SDag-Erling Smørgrav 
4037b5038d7SDag-Erling Smørgrav bool
4047b5038d7SDag-Erling Smørgrav ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
4057b5038d7SDag-Erling Smørgrav {
4067b5038d7SDag-Erling Smørgrav 	if (name) {
4077b5038d7SDag-Erling Smørgrav 		return name->is_glue;
4087b5038d7SDag-Erling Smørgrav 	}
4097b5038d7SDag-Erling Smørgrav 	return false;
4107b5038d7SDag-Erling Smørgrav }
4117b5038d7SDag-Erling Smørgrav 
4127b5038d7SDag-Erling Smørgrav void
4137b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
4147b5038d7SDag-Erling Smørgrav 					 ldns_rdf *dname)
4157b5038d7SDag-Erling Smørgrav {
4167b5038d7SDag-Erling Smørgrav 	if (rrset && dname) {
4177b5038d7SDag-Erling Smørgrav 		rrset->name = dname;
4187b5038d7SDag-Erling Smørgrav 	}
4197b5038d7SDag-Erling Smørgrav }
4207b5038d7SDag-Erling Smørgrav 
4217b5038d7SDag-Erling Smørgrav 
4227b5038d7SDag-Erling Smørgrav void
4237b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
4247b5038d7SDag-Erling Smørgrav {
4257b5038d7SDag-Erling Smørgrav 	if (rrset && nsec) {
4267b5038d7SDag-Erling Smørgrav 		rrset->nsec = nsec;
4277b5038d7SDag-Erling Smørgrav 	}
4287b5038d7SDag-Erling Smørgrav }
4297b5038d7SDag-Erling Smørgrav 
4307b5038d7SDag-Erling Smørgrav int
4317b5038d7SDag-Erling Smørgrav ldns_dnssec_name_cmp(const void *a, const void *b)
4327b5038d7SDag-Erling Smørgrav {
4337b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
4347b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
4357b5038d7SDag-Erling Smørgrav 
4367b5038d7SDag-Erling Smørgrav 	if (na && nb) {
4377b5038d7SDag-Erling Smørgrav 		return ldns_dname_compare(ldns_dnssec_name_name(na),
4387b5038d7SDag-Erling Smørgrav 							 ldns_dnssec_name_name(nb));
4397b5038d7SDag-Erling Smørgrav 	} else if (na) {
4407b5038d7SDag-Erling Smørgrav 		return 1;
4417b5038d7SDag-Erling Smørgrav 	} else if (nb) {
4427b5038d7SDag-Erling Smørgrav 		return -1;
4437b5038d7SDag-Erling Smørgrav 	} else {
4447b5038d7SDag-Erling Smørgrav 		return 0;
4457b5038d7SDag-Erling Smørgrav 	}
4467b5038d7SDag-Erling Smørgrav }
4477b5038d7SDag-Erling Smørgrav 
4487b5038d7SDag-Erling Smørgrav ldns_status
4497b5038d7SDag-Erling Smørgrav ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
4507b5038d7SDag-Erling Smørgrav 				    ldns_rr *rr)
4517b5038d7SDag-Erling Smørgrav {
4527b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
4537b5038d7SDag-Erling Smørgrav 	ldns_rdf *name_name;
4547b5038d7SDag-Erling Smørgrav 	bool hashed_name = false;
4557b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
4567b5038d7SDag-Erling Smørgrav 	ldns_rr_type typecovered = 0;
4577b5038d7SDag-Erling Smørgrav 
4587b5038d7SDag-Erling Smørgrav 	/* special handling for NSEC3 and NSECX covering RRSIGS */
4597b5038d7SDag-Erling Smørgrav 
4607b5038d7SDag-Erling Smørgrav 	if (!name || !rr) {
4617b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
4627b5038d7SDag-Erling Smørgrav 	}
4637b5038d7SDag-Erling Smørgrav 
4647b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
4657b5038d7SDag-Erling Smørgrav 
4667b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
4677b5038d7SDag-Erling Smørgrav 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
4687b5038d7SDag-Erling Smørgrav 	}
4697b5038d7SDag-Erling Smørgrav 
4707b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
4717b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_NSEC3 ||
4727b5038d7SDag-Erling Smørgrav 	    typecovered == LDNS_RR_TYPE_NSEC3) {
4737b5038d7SDag-Erling Smørgrav 		name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
4747b5038d7SDag-Erling Smørgrav 										   ldns_dnssec_name_name(name));
4757b5038d7SDag-Erling Smørgrav 		hashed_name = true;
4767b5038d7SDag-Erling Smørgrav 	} else {
4777b5038d7SDag-Erling Smørgrav 		name_name = ldns_dnssec_name_name(name);
4787b5038d7SDag-Erling Smørgrav 	}
4797b5038d7SDag-Erling Smørgrav #else
4807b5038d7SDag-Erling Smørgrav 	name_name = ldns_dnssec_name_name(name);
4817b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
4827b5038d7SDag-Erling Smørgrav 
4837b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_NSEC ||
4847b5038d7SDag-Erling Smørgrav 	    rr_type == LDNS_RR_TYPE_NSEC3) {
4857b5038d7SDag-Erling Smørgrav 		/* XX check if is already set (and error?) */
4867b5038d7SDag-Erling Smørgrav 		name->nsec = rr;
4877b5038d7SDag-Erling Smørgrav 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
4887b5038d7SDag-Erling Smørgrav 			 typecovered == LDNS_RR_TYPE_NSEC3) {
4897b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
4907b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
4917b5038d7SDag-Erling Smørgrav 		} else {
4927b5038d7SDag-Erling Smørgrav 			name->nsec_signatures = ldns_dnssec_rrs_new();
4937b5038d7SDag-Erling Smørgrav 			name->nsec_signatures->rr = rr;
4947b5038d7SDag-Erling Smørgrav 		}
4957b5038d7SDag-Erling Smørgrav 	} else {
4967b5038d7SDag-Erling Smørgrav 		/* it's a 'normal' RR, add it to the right rrset */
4977b5038d7SDag-Erling Smørgrav 		if (name->rrsets) {
4987b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
4997b5038d7SDag-Erling Smørgrav 		} else {
5007b5038d7SDag-Erling Smørgrav 			name->rrsets = ldns_dnssec_rrsets_new();
5017b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
5027b5038d7SDag-Erling Smørgrav 		}
5037b5038d7SDag-Erling Smørgrav 	}
5047b5038d7SDag-Erling Smørgrav 
5057b5038d7SDag-Erling Smørgrav 	if (hashed_name) {
5067b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(name_name);
5077b5038d7SDag-Erling Smørgrav 	}
5087b5038d7SDag-Erling Smørgrav 
5097b5038d7SDag-Erling Smørgrav 	return result;
5107b5038d7SDag-Erling Smørgrav }
5117b5038d7SDag-Erling Smørgrav 
5127b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
5137b5038d7SDag-Erling Smørgrav ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
5147b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type) {
5157b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *result;
5167b5038d7SDag-Erling Smørgrav 
5177b5038d7SDag-Erling Smørgrav 	result = name->rrsets;
5187b5038d7SDag-Erling Smørgrav 	while (result) {
5197b5038d7SDag-Erling Smørgrav 		if (result->type == type) {
5207b5038d7SDag-Erling Smørgrav 			return result;
5217b5038d7SDag-Erling Smørgrav 		} else {
5227b5038d7SDag-Erling Smørgrav 			result = result->next;
5237b5038d7SDag-Erling Smørgrav 		}
5247b5038d7SDag-Erling Smørgrav 	}
5257b5038d7SDag-Erling Smørgrav 	return NULL;
5267b5038d7SDag-Erling Smørgrav }
5277b5038d7SDag-Erling Smørgrav 
5287b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
5297b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
5307b5038d7SDag-Erling Smørgrav 					   ldns_rdf *dname,
5317b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type)
5327b5038d7SDag-Erling Smørgrav {
5337b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *node;
5347b5038d7SDag-Erling Smørgrav 
5357b5038d7SDag-Erling Smørgrav 	if (!zone || !dname) {
5367b5038d7SDag-Erling Smørgrav 		return NULL;
5377b5038d7SDag-Erling Smørgrav 	}
5387b5038d7SDag-Erling Smørgrav 
5397b5038d7SDag-Erling Smørgrav 	node = ldns_rbtree_search(zone->names, dname);
5407b5038d7SDag-Erling Smørgrav 	if (node) {
5417b5038d7SDag-Erling Smørgrav 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
5427b5038d7SDag-Erling Smørgrav 									type);
5437b5038d7SDag-Erling Smørgrav 	} else {
5447b5038d7SDag-Erling Smørgrav 		return NULL;
5457b5038d7SDag-Erling Smørgrav 	}
5467b5038d7SDag-Erling Smørgrav }
5477b5038d7SDag-Erling Smørgrav 
5487b5038d7SDag-Erling Smørgrav static void
5497b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
5507b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name *name,
5517b5038d7SDag-Erling Smørgrav 		bool show_soa)
5527b5038d7SDag-Erling Smørgrav {
5537b5038d7SDag-Erling Smørgrav 	if (name) {
5547b5038d7SDag-Erling Smørgrav 		if(name->rrsets) {
5557b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
5567b5038d7SDag-Erling Smørgrav 					name->rrsets, true, show_soa);
5577b5038d7SDag-Erling Smørgrav 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5587b5038d7SDag-Erling Smørgrav 			fprintf(out, ";; Empty nonterminal: ");
5597b5038d7SDag-Erling Smørgrav 			ldns_rdf_print(out, name->name);
5607b5038d7SDag-Erling Smørgrav 			fprintf(out, "\n");
5617b5038d7SDag-Erling Smørgrav 		}
5627b5038d7SDag-Erling Smørgrav 		if(name->nsec) {
5637b5038d7SDag-Erling Smørgrav 			ldns_rr_print_fmt(out, fmt, name->nsec);
5647b5038d7SDag-Erling Smørgrav 		}
5657b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
5667b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt,
5677b5038d7SDag-Erling Smørgrav 					name->nsec_signatures);
5687b5038d7SDag-Erling Smørgrav 		}
5697b5038d7SDag-Erling Smørgrav 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5707b5038d7SDag-Erling Smørgrav 		fprintf(out, "; <void>\n");
5717b5038d7SDag-Erling Smørgrav 	}
5727b5038d7SDag-Erling Smørgrav }
5737b5038d7SDag-Erling Smørgrav 
5747b5038d7SDag-Erling Smørgrav 
5757b5038d7SDag-Erling Smørgrav void
5767b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
5777b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name *name)
5787b5038d7SDag-Erling Smørgrav {
5797b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
5807b5038d7SDag-Erling Smørgrav }
5817b5038d7SDag-Erling Smørgrav 
5827b5038d7SDag-Erling Smørgrav void
5837b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
5847b5038d7SDag-Erling Smørgrav {
5857b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
5867b5038d7SDag-Erling Smørgrav }
5877b5038d7SDag-Erling Smørgrav 
5887b5038d7SDag-Erling Smørgrav 
5897b5038d7SDag-Erling Smørgrav ldns_dnssec_zone *
5907b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new(void)
5917b5038d7SDag-Erling Smørgrav {
5927b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
5937b5038d7SDag-Erling Smørgrav         if(!zone) return NULL;
5947b5038d7SDag-Erling Smørgrav 	zone->soa = NULL;
5957b5038d7SDag-Erling Smørgrav 	zone->names = NULL;
5967b5038d7SDag-Erling Smørgrav 
5977b5038d7SDag-Erling Smørgrav 	return zone;
5987b5038d7SDag-Erling Smørgrav }
5997b5038d7SDag-Erling Smørgrav 
6007b5038d7SDag-Erling Smørgrav static bool
6017b5038d7SDag-Erling Smørgrav rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
6027b5038d7SDag-Erling Smørgrav {
6037b5038d7SDag-Erling Smørgrav 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
6047b5038d7SDag-Erling Smørgrav 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
6057b5038d7SDag-Erling Smørgrav }
6067b5038d7SDag-Erling Smørgrav 
6077b5038d7SDag-Erling Smørgrav /* When the zone is first read into an list and then inserted into an
6087b5038d7SDag-Erling Smørgrav  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
6097b5038d7SDag-Erling Smørgrav  * to each other. Because ldns-verify-zone (the only program that uses this
6107b5038d7SDag-Erling Smørgrav  * function) uses the rbtree mostly for sequentual walking, this results
6117b5038d7SDag-Erling Smørgrav  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
6127b5038d7SDag-Erling Smørgrav  */
6137b5038d7SDag-Erling Smørgrav #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
6147b5038d7SDag-Erling Smørgrav 
6157b5038d7SDag-Erling Smørgrav ldns_status
6167b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
6177b5038d7SDag-Erling Smørgrav 	       	uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
6187b5038d7SDag-Erling Smørgrav {
6197b5038d7SDag-Erling Smørgrav 	ldns_rr* cur_rr;
6207b5038d7SDag-Erling Smørgrav 	size_t i;
6217b5038d7SDag-Erling Smørgrav 
6227b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_origin = NULL;
6237b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_prev = NULL;
6247b5038d7SDag-Erling Smørgrav 
6257b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
6267b5038d7SDag-Erling Smørgrav 	/* when reading NSEC3s, there is a chance that we encounter nsecs
6277b5038d7SDag-Erling Smørgrav 	   for empty nonterminals, whose nonterminals we cannot derive yet
6287b5038d7SDag-Erling Smørgrav 	   because the needed information is to be read later. in that case
6297b5038d7SDag-Erling Smørgrav 	   we keep a list of those nsec3's and retry to add them later */
6307b5038d7SDag-Erling Smørgrav 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
6317b5038d7SDag-Erling Smørgrav 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
6327b5038d7SDag-Erling Smørgrav 
6337b5038d7SDag-Erling Smørgrav 	ldns_status status = LDNS_STATUS_MEM_ERR;
6347b5038d7SDag-Erling Smørgrav 
6357b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6367b5038d7SDag-Erling Smørgrav 	ldns_zone* zone = NULL;
6377b5038d7SDag-Erling Smørgrav 	if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
6387b5038d7SDag-Erling Smørgrav 			!= LDNS_STATUS_OK) goto error;
6397b5038d7SDag-Erling Smørgrav #else
6407b5038d7SDag-Erling Smørgrav 	uint32_t  my_ttl = ttl;
6417b5038d7SDag-Erling Smørgrav #endif
6427b5038d7SDag-Erling Smørgrav 
6437b5038d7SDag-Erling Smørgrav 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
6447b5038d7SDag-Erling Smørgrav 
6457b5038d7SDag-Erling Smørgrav 	if (origin) {
6467b5038d7SDag-Erling Smørgrav 		if (!(my_origin = ldns_rdf_clone(origin))) goto error;
6477b5038d7SDag-Erling Smørgrav 		if (!(my_prev   = ldns_rdf_clone(origin))) goto error;
6487b5038d7SDag-Erling Smørgrav 	}
6497b5038d7SDag-Erling Smørgrav 
6507b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6517b5038d7SDag-Erling Smørgrav 	if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
6527b5038d7SDag-Erling Smørgrav 			!= LDNS_STATUS_OK) goto error;
6537b5038d7SDag-Erling Smørgrav 
6547b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
6557b5038d7SDag-Erling Smørgrav 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
6567b5038d7SDag-Erling Smørgrav 		status = LDNS_STATUS_OK;
6577b5038d7SDag-Erling Smørgrav #else
6587b5038d7SDag-Erling Smørgrav 	while (!feof(fp)) {
6597b5038d7SDag-Erling Smørgrav 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
6607b5038d7SDag-Erling Smørgrav 				&my_prev, line_nr);
6617b5038d7SDag-Erling Smørgrav 
6627b5038d7SDag-Erling Smørgrav #endif
6637b5038d7SDag-Erling Smørgrav 		switch (status) {
6647b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_OK:
6657b5038d7SDag-Erling Smørgrav 
6667b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
6677b5038d7SDag-Erling Smørgrav 			if (status ==
6687b5038d7SDag-Erling Smørgrav 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
6697b5038d7SDag-Erling Smørgrav 
6707b5038d7SDag-Erling Smørgrav 				if (rr_is_rrsig_covering(cur_rr,
6717b5038d7SDag-Erling Smørgrav 							LDNS_RR_TYPE_NSEC3)){
6727b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
6737b5038d7SDag-Erling Smørgrav 							cur_rr);
6747b5038d7SDag-Erling Smørgrav 				} else {
6757b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(todo_nsec3s,
6767b5038d7SDag-Erling Smørgrav 						       	cur_rr);
6777b5038d7SDag-Erling Smørgrav 				}
6787b5038d7SDag-Erling Smørgrav 			} else if (status != LDNS_STATUS_OK)
6797b5038d7SDag-Erling Smørgrav 				goto error;
6807b5038d7SDag-Erling Smørgrav 
6817b5038d7SDag-Erling Smørgrav 			break;
6827b5038d7SDag-Erling Smørgrav 
6837b5038d7SDag-Erling Smørgrav 
6847b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
6857b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
6867b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
6872787e39aSDag-Erling Smørgrav 			status = LDNS_STATUS_OK;
6887b5038d7SDag-Erling Smørgrav 			break;
6897b5038d7SDag-Erling Smørgrav 
6907b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
6917b5038d7SDag-Erling Smørgrav 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
6927b5038d7SDag-Erling Smørgrav 			break;
6937b5038d7SDag-Erling Smørgrav 
6947b5038d7SDag-Erling Smørgrav 		default:
6957b5038d7SDag-Erling Smørgrav 			goto error;
6967b5038d7SDag-Erling Smørgrav 		}
6977b5038d7SDag-Erling Smørgrav 	}
6987b5038d7SDag-Erling Smørgrav 
6997b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
7007b5038d7SDag-Erling Smørgrav 		(void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
7012787e39aSDag-Erling Smørgrav 		for (i = 0; status == LDNS_STATUS_OK &&
7022787e39aSDag-Erling Smørgrav 				i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
7037b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
7047b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
7057b5038d7SDag-Erling Smørgrav 		}
7062787e39aSDag-Erling Smørgrav 		for (i = 0; status == LDNS_STATUS_OK &&
7072787e39aSDag-Erling Smørgrav 				i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
7082787e39aSDag-Erling Smørgrav 			       	i++){
7097b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
7107b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
7117b5038d7SDag-Erling Smørgrav 		}
7127b5038d7SDag-Erling Smørgrav 	} else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
7132787e39aSDag-Erling Smørgrav 		for (i = 0; status == LDNS_STATUS_OK &&
7142787e39aSDag-Erling Smørgrav 				i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
7152787e39aSDag-Erling Smørgrav 				i++){
7167b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
7177b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
7187b5038d7SDag-Erling Smørgrav 		}
7197b5038d7SDag-Erling Smørgrav 	}
7207b5038d7SDag-Erling Smørgrav 
7217b5038d7SDag-Erling Smørgrav 	if (z) {
7227b5038d7SDag-Erling Smørgrav 		*z = newzone;
7232787e39aSDag-Erling Smørgrav 		newzone = NULL;
7247b5038d7SDag-Erling Smørgrav 	} else {
7257b5038d7SDag-Erling Smørgrav 		ldns_dnssec_zone_free(newzone);
7267b5038d7SDag-Erling Smørgrav 	}
7277b5038d7SDag-Erling Smørgrav 
7287b5038d7SDag-Erling Smørgrav error:
7297b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
7307b5038d7SDag-Erling Smørgrav 	if (zone) {
7317b5038d7SDag-Erling Smørgrav 		ldns_zone_free(zone);
7327b5038d7SDag-Erling Smørgrav 	}
7337b5038d7SDag-Erling Smørgrav #endif
7342787e39aSDag-Erling Smørgrav 	ldns_rr_list_free(todo_nsec3_rrsigs);
7352787e39aSDag-Erling Smørgrav 	ldns_rr_list_free(todo_nsec3s);
7362787e39aSDag-Erling Smørgrav 
7377b5038d7SDag-Erling Smørgrav 	if (my_origin) {
7387b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_origin);
7397b5038d7SDag-Erling Smørgrav 	}
7407b5038d7SDag-Erling Smørgrav 	if (my_prev) {
7417b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_prev);
7427b5038d7SDag-Erling Smørgrav 	}
7437b5038d7SDag-Erling Smørgrav 	if (newzone) {
7447b5038d7SDag-Erling Smørgrav 		ldns_dnssec_zone_free(newzone);
7457b5038d7SDag-Erling Smørgrav 	}
7467b5038d7SDag-Erling Smørgrav 	return status;
7477b5038d7SDag-Erling Smørgrav }
7487b5038d7SDag-Erling Smørgrav 
7497b5038d7SDag-Erling Smørgrav ldns_status
7507b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
7517b5038d7SDag-Erling Smørgrav 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
7527b5038d7SDag-Erling Smørgrav {
7537b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
7547b5038d7SDag-Erling Smørgrav }
7557b5038d7SDag-Erling Smørgrav 
7567b5038d7SDag-Erling Smørgrav static void
7577b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
7587b5038d7SDag-Erling Smørgrav 	(void) arg;
7597b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
7607b5038d7SDag-Erling Smørgrav 	LDNS_FREE(node);
7617b5038d7SDag-Erling Smørgrav }
7627b5038d7SDag-Erling Smørgrav 
7637b5038d7SDag-Erling Smørgrav static void
7647b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
7657b5038d7SDag-Erling Smørgrav 	(void) arg;
7667b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
7677b5038d7SDag-Erling Smørgrav 	LDNS_FREE(node);
7687b5038d7SDag-Erling Smørgrav }
7697b5038d7SDag-Erling Smørgrav 
7707b5038d7SDag-Erling Smørgrav void
7717b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
7727b5038d7SDag-Erling Smørgrav {
7737b5038d7SDag-Erling Smørgrav 	if (zone) {
7747b5038d7SDag-Erling Smørgrav 		if (zone->names) {
7757b5038d7SDag-Erling Smørgrav 			/* destroy all name structures within the tree */
7767b5038d7SDag-Erling Smørgrav 			ldns_traverse_postorder(zone->names,
7777b5038d7SDag-Erling Smørgrav 						    ldns_dnssec_name_node_free,
7787b5038d7SDag-Erling Smørgrav 						    NULL);
7797b5038d7SDag-Erling Smørgrav 			LDNS_FREE(zone->names);
7807b5038d7SDag-Erling Smørgrav 		}
7817b5038d7SDag-Erling Smørgrav 		LDNS_FREE(zone);
7827b5038d7SDag-Erling Smørgrav 	}
7837b5038d7SDag-Erling Smørgrav }
7847b5038d7SDag-Erling Smørgrav 
7857b5038d7SDag-Erling Smørgrav void
7867b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
7877b5038d7SDag-Erling Smørgrav {
7887b5038d7SDag-Erling Smørgrav 	if (zone) {
7897b5038d7SDag-Erling Smørgrav 		if (zone->names) {
7907b5038d7SDag-Erling Smørgrav 			/* destroy all name structures within the tree */
7917b5038d7SDag-Erling Smørgrav 			ldns_traverse_postorder(zone->names,
7927b5038d7SDag-Erling Smørgrav 						    ldns_dnssec_name_node_deep_free,
7937b5038d7SDag-Erling Smørgrav 						    NULL);
7947b5038d7SDag-Erling Smørgrav 			LDNS_FREE(zone->names);
7957b5038d7SDag-Erling Smørgrav 		}
7967b5038d7SDag-Erling Smørgrav 		LDNS_FREE(zone);
7977b5038d7SDag-Erling Smørgrav 	}
7987b5038d7SDag-Erling Smørgrav }
7997b5038d7SDag-Erling Smørgrav 
8007b5038d7SDag-Erling Smørgrav /* use for dname comparison in tree */
801*d6e492feSDag-Erling Smørgrav int
8027b5038d7SDag-Erling Smørgrav ldns_dname_compare_v(const void *a, const void *b) {
8037b5038d7SDag-Erling Smørgrav 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
8047b5038d7SDag-Erling Smørgrav }
8057b5038d7SDag-Erling Smørgrav 
8067b5038d7SDag-Erling Smørgrav static ldns_rbnode_t *
8077b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
8087b5038d7SDag-Erling Smørgrav                                      ldns_rr *rr) {
8097b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
8107b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *current_name;
8117b5038d7SDag-Erling Smørgrav 	ldns_rdf *hashed_name;
8127b5038d7SDag-Erling Smørgrav 
8137b5038d7SDag-Erling Smørgrav 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
8147b5038d7SDag-Erling Smørgrav 
8157b5038d7SDag-Erling Smørgrav 	while (current_node != LDNS_RBTREE_NULL) {
8167b5038d7SDag-Erling Smørgrav 		current_name = (ldns_dnssec_name *) current_node->data;
8177b5038d7SDag-Erling Smørgrav 		if (!current_name->hashed_name) {
8187b5038d7SDag-Erling Smørgrav 			current_name->hashed_name =
8197b5038d7SDag-Erling Smørgrav 				ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
8207b5038d7SDag-Erling Smørgrav 		}
8217b5038d7SDag-Erling Smørgrav 		if (ldns_dname_compare(hashed_name,
8227b5038d7SDag-Erling Smørgrav 						   current_name->hashed_name)
8237b5038d7SDag-Erling Smørgrav 		    == 0) {
8247b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(hashed_name);
8257b5038d7SDag-Erling Smørgrav 			return current_node;
8267b5038d7SDag-Erling Smørgrav 		}
8277b5038d7SDag-Erling Smørgrav 		current_node = ldns_rbtree_next(current_node);
8287b5038d7SDag-Erling Smørgrav 	}
8297b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(hashed_name);
8307b5038d7SDag-Erling Smørgrav 	return NULL;
8317b5038d7SDag-Erling Smørgrav }
8327b5038d7SDag-Erling Smørgrav 
8337b5038d7SDag-Erling Smørgrav ldns_status
8347b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
8357b5038d7SDag-Erling Smørgrav {
8367b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
8377b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *cur_name;
8387b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *cur_node;
8397b5038d7SDag-Erling Smørgrav 	ldns_rr_type type_covered = 0;
8407b5038d7SDag-Erling Smørgrav 
8417b5038d7SDag-Erling Smørgrav 	if (!zone || !rr) {
8427b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
8437b5038d7SDag-Erling Smørgrav 	}
8447b5038d7SDag-Erling Smørgrav 
8457b5038d7SDag-Erling Smørgrav 	if (!zone->names) {
8467b5038d7SDag-Erling Smørgrav 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
8477b5038d7SDag-Erling Smørgrav                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
8487b5038d7SDag-Erling Smørgrav 	}
8497b5038d7SDag-Erling Smørgrav 
8507b5038d7SDag-Erling Smørgrav 	/* we need the original of the hashed name if this is
8517b5038d7SDag-Erling Smørgrav 	   an NSEC3, or an RRSIG that covers an NSEC3 */
8527b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
8537b5038d7SDag-Erling Smørgrav 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
8547b5038d7SDag-Erling Smørgrav 	}
8557b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
8567b5038d7SDag-Erling Smørgrav 	    type_covered == LDNS_RR_TYPE_NSEC3) {
8577b5038d7SDag-Erling Smørgrav 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
8587b5038d7SDag-Erling Smørgrav 					 						   rr);
8597b5038d7SDag-Erling Smørgrav 		if (!cur_node) {
8607b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
8617b5038d7SDag-Erling Smørgrav 		}
8627b5038d7SDag-Erling Smørgrav 	} else {
8637b5038d7SDag-Erling Smørgrav 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
8647b5038d7SDag-Erling Smørgrav 	}
8657b5038d7SDag-Erling Smørgrav 
8667b5038d7SDag-Erling Smørgrav 	if (!cur_node) {
8677b5038d7SDag-Erling Smørgrav 		/* add */
8687b5038d7SDag-Erling Smørgrav 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
8697b5038d7SDag-Erling Smørgrav                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
8707b5038d7SDag-Erling Smørgrav 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
8717b5038d7SDag-Erling Smørgrav                 if(!cur_node) {
8727b5038d7SDag-Erling Smørgrav                         ldns_dnssec_name_free(cur_name);
8737b5038d7SDag-Erling Smørgrav                         return LDNS_STATUS_MEM_ERR;
8747b5038d7SDag-Erling Smørgrav                 }
8757b5038d7SDag-Erling Smørgrav 		cur_node->key = ldns_rr_owner(rr);
8767b5038d7SDag-Erling Smørgrav 		cur_node->data = cur_name;
8777b5038d7SDag-Erling Smørgrav 		(void)ldns_rbtree_insert(zone->names, cur_node);
8787b5038d7SDag-Erling Smørgrav 	} else {
8797b5038d7SDag-Erling Smørgrav 		cur_name = (ldns_dnssec_name *) cur_node->data;
8807b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_name_add_rr(cur_name, rr);
8817b5038d7SDag-Erling Smørgrav 	}
8827b5038d7SDag-Erling Smørgrav 
8837b5038d7SDag-Erling Smørgrav 	if (result != LDNS_STATUS_OK) {
8847b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "error adding rr: ");
8857b5038d7SDag-Erling Smørgrav 		ldns_rr_print(stderr, rr);
8867b5038d7SDag-Erling Smørgrav 	}
8877b5038d7SDag-Erling Smørgrav 
8887b5038d7SDag-Erling Smørgrav 	/*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
8897b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
8907b5038d7SDag-Erling Smørgrav 		zone->soa = cur_name;
8917b5038d7SDag-Erling Smørgrav 	}
8927b5038d7SDag-Erling Smørgrav 
8937b5038d7SDag-Erling Smørgrav 	return result;
8947b5038d7SDag-Erling Smørgrav }
8957b5038d7SDag-Erling Smørgrav 
8967b5038d7SDag-Erling Smørgrav void
8977b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
8987b5038d7SDag-Erling Smørgrav 		ldns_rbtree_t *tree,
8997b5038d7SDag-Erling Smørgrav 		bool print_soa)
9007b5038d7SDag-Erling Smørgrav {
9017b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *node;
9027b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *name;
9037b5038d7SDag-Erling Smørgrav 
9047b5038d7SDag-Erling Smørgrav 	node = ldns_rbtree_first(tree);
9057b5038d7SDag-Erling Smørgrav 	while (node != LDNS_RBTREE_NULL) {
9067b5038d7SDag-Erling Smørgrav 		name = (ldns_dnssec_name *) node->data;
9077b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
9087b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
9097b5038d7SDag-Erling Smørgrav 			fprintf(out, ";\n");
9107b5038d7SDag-Erling Smørgrav 		node = ldns_rbtree_next(node);
9117b5038d7SDag-Erling Smørgrav 	}
9127b5038d7SDag-Erling Smørgrav }
9137b5038d7SDag-Erling Smørgrav 
9147b5038d7SDag-Erling Smørgrav void
9157b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
9167b5038d7SDag-Erling Smørgrav {
9177b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
9187b5038d7SDag-Erling Smørgrav 		       tree, print_soa);
9197b5038d7SDag-Erling Smørgrav }
9207b5038d7SDag-Erling Smørgrav 
9217b5038d7SDag-Erling Smørgrav void
9227b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
9237b5038d7SDag-Erling Smørgrav 	       ldns_dnssec_zone *zone)
9247b5038d7SDag-Erling Smørgrav {
9257b5038d7SDag-Erling Smørgrav 	if (zone) {
9267b5038d7SDag-Erling Smørgrav 		if (zone->soa) {
9277b5038d7SDag-Erling Smørgrav 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
9287b5038d7SDag-Erling Smørgrav 				fprintf(out, ";; Zone: ");
9297b5038d7SDag-Erling Smørgrav 				ldns_rdf_print(out, ldns_dnssec_name_name(
9307b5038d7SDag-Erling Smørgrav 							zone->soa));
9317b5038d7SDag-Erling Smørgrav 				fprintf(out, "\n;\n");
9327b5038d7SDag-Erling Smørgrav 			}
9337b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_fmt(out, fmt,
9347b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_find_rrset(
9357b5038d7SDag-Erling Smørgrav 						zone->soa,
9367b5038d7SDag-Erling Smørgrav 						LDNS_RR_TYPE_SOA),
9377b5038d7SDag-Erling Smørgrav 					false);
9387b5038d7SDag-Erling Smørgrav 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
9397b5038d7SDag-Erling Smørgrav 				fprintf(out, ";\n");
9407b5038d7SDag-Erling Smørgrav 		}
9417b5038d7SDag-Erling Smørgrav 
9427b5038d7SDag-Erling Smørgrav 		if (zone->names) {
9437b5038d7SDag-Erling Smørgrav 			ldns_dnssec_zone_names_print_fmt(out, fmt,
9447b5038d7SDag-Erling Smørgrav 					zone->names, false);
9457b5038d7SDag-Erling Smørgrav 		}
9467b5038d7SDag-Erling Smørgrav 	}
9477b5038d7SDag-Erling Smørgrav }
9487b5038d7SDag-Erling Smørgrav 
9497b5038d7SDag-Erling Smørgrav void
9507b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
9517b5038d7SDag-Erling Smørgrav {
9527b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
9537b5038d7SDag-Erling Smørgrav }
9547b5038d7SDag-Erling Smørgrav 
9557b5038d7SDag-Erling Smørgrav ldns_status
9567b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
9577b5038d7SDag-Erling Smørgrav {
9587b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name;
9597b5038d7SDag-Erling Smørgrav 	ldns_rdf *cur_name;
9607b5038d7SDag-Erling Smørgrav 	ldns_rdf *next_name;
9617b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *cur_node, *next_node, *new_node;
9627b5038d7SDag-Erling Smørgrav 
9637b5038d7SDag-Erling Smørgrav 	/* for the detection */
9647b5038d7SDag-Erling Smørgrav 	uint16_t i, cur_label_count, next_label_count;
9657b5038d7SDag-Erling Smørgrav 	uint16_t soa_label_count = 0;
9667b5038d7SDag-Erling Smørgrav 	ldns_rdf *l1, *l2;
9677b5038d7SDag-Erling Smørgrav 	int lpos;
9687b5038d7SDag-Erling Smørgrav 
9697b5038d7SDag-Erling Smørgrav 	if (!zone) {
9707b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
9717b5038d7SDag-Erling Smørgrav 	}
9727b5038d7SDag-Erling Smørgrav 	if (zone->soa && zone->soa->name) {
9737b5038d7SDag-Erling Smørgrav 		soa_label_count = ldns_dname_label_count(zone->soa->name);
9747b5038d7SDag-Erling Smørgrav 	}
9757b5038d7SDag-Erling Smørgrav 
9767b5038d7SDag-Erling Smørgrav 	cur_node = ldns_rbtree_first(zone->names);
9777b5038d7SDag-Erling Smørgrav 	while (cur_node != LDNS_RBTREE_NULL) {
9787b5038d7SDag-Erling Smørgrav 		next_node = ldns_rbtree_next(cur_node);
9797b5038d7SDag-Erling Smørgrav 
9807b5038d7SDag-Erling Smørgrav 		/* skip glue */
9817b5038d7SDag-Erling Smørgrav 		while (next_node != LDNS_RBTREE_NULL &&
9827b5038d7SDag-Erling Smørgrav 		       next_node->data &&
9837b5038d7SDag-Erling Smørgrav 		       ((ldns_dnssec_name *)next_node->data)->is_glue
9847b5038d7SDag-Erling Smørgrav 		) {
9857b5038d7SDag-Erling Smørgrav 			next_node = ldns_rbtree_next(next_node);
9867b5038d7SDag-Erling Smørgrav 		}
9877b5038d7SDag-Erling Smørgrav 
9887b5038d7SDag-Erling Smørgrav 		if (next_node == LDNS_RBTREE_NULL) {
9897b5038d7SDag-Erling Smørgrav 			next_node = ldns_rbtree_first(zone->names);
9907b5038d7SDag-Erling Smørgrav 		}
9912787e39aSDag-Erling Smørgrav 		if (! cur_node->data || ! next_node->data) {
9922787e39aSDag-Erling Smørgrav 			return LDNS_STATUS_ERR;
9932787e39aSDag-Erling Smørgrav 		}
9947b5038d7SDag-Erling Smørgrav 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
9957b5038d7SDag-Erling Smørgrav 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
9967b5038d7SDag-Erling Smørgrav 		cur_label_count = ldns_dname_label_count(cur_name);
9977b5038d7SDag-Erling Smørgrav 		next_label_count = ldns_dname_label_count(next_name);
9987b5038d7SDag-Erling Smørgrav 
9997b5038d7SDag-Erling Smørgrav 		/* Since the names are in canonical order, we can
10007b5038d7SDag-Erling Smørgrav 		 * recognize empty non-terminals by their labels;
10017b5038d7SDag-Erling Smørgrav 		 * every label after the first one on the next owner
10027b5038d7SDag-Erling Smørgrav 		 * name is a non-terminal if it either does not exist
10037b5038d7SDag-Erling Smørgrav 		 * in the current name or is different from the same
10047b5038d7SDag-Erling Smørgrav 		 * label in the current name (counting from the end)
10057b5038d7SDag-Erling Smørgrav 		 */
10067b5038d7SDag-Erling Smørgrav 		for (i = 1; i < next_label_count - soa_label_count; i++) {
10077b5038d7SDag-Erling Smørgrav 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
10087b5038d7SDag-Erling Smørgrav 			if (lpos >= 0) {
10097b5038d7SDag-Erling Smørgrav 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
10107b5038d7SDag-Erling Smørgrav 			} else {
10117b5038d7SDag-Erling Smørgrav 				l1 = NULL;
10127b5038d7SDag-Erling Smørgrav 			}
10137b5038d7SDag-Erling Smørgrav 			l2 = ldns_dname_clone_from(next_name, i);
10147b5038d7SDag-Erling Smørgrav 
10157b5038d7SDag-Erling Smørgrav 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
10167b5038d7SDag-Erling Smørgrav 				/* We have an empty nonterminal, add it to the
10177b5038d7SDag-Erling Smørgrav 				 * tree
10187b5038d7SDag-Erling Smørgrav 				 */
10197b5038d7SDag-Erling Smørgrav 				new_name = ldns_dnssec_name_new();
10207b5038d7SDag-Erling Smørgrav 				if (!new_name) {
10217b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10227b5038d7SDag-Erling Smørgrav 				}
10237b5038d7SDag-Erling Smørgrav 				new_name->name = ldns_dname_clone_from(next_name,
10247b5038d7SDag-Erling Smørgrav 				                                       i);
10257b5038d7SDag-Erling Smørgrav 				if (!new_name->name) {
10267b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_free(new_name);
10277b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10287b5038d7SDag-Erling Smørgrav 				}
10297b5038d7SDag-Erling Smørgrav 				new_name->name_alloced = true;
10307b5038d7SDag-Erling Smørgrav 				new_node = LDNS_MALLOC(ldns_rbnode_t);
10317b5038d7SDag-Erling Smørgrav 				if (!new_node) {
10327b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_free(new_name);
10337b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10347b5038d7SDag-Erling Smørgrav 				}
10357b5038d7SDag-Erling Smørgrav 				new_node->key = new_name->name;
10367b5038d7SDag-Erling Smørgrav 				new_node->data = new_name;
10377b5038d7SDag-Erling Smørgrav 				(void)ldns_rbtree_insert(zone->names, new_node);
10387b5038d7SDag-Erling Smørgrav 			}
10397b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(l1);
10407b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(l2);
10417b5038d7SDag-Erling Smørgrav 		}
10427b5038d7SDag-Erling Smørgrav 
10437b5038d7SDag-Erling Smørgrav 		/* we might have inserted a new node after
10447b5038d7SDag-Erling Smørgrav 		 * the current one so we can't just use next()
10457b5038d7SDag-Erling Smørgrav 		 */
10467b5038d7SDag-Erling Smørgrav 		if (next_node != ldns_rbtree_first(zone->names)) {
10477b5038d7SDag-Erling Smørgrav 			cur_node = next_node;
10487b5038d7SDag-Erling Smørgrav 		} else {
10497b5038d7SDag-Erling Smørgrav 			cur_node = LDNS_RBTREE_NULL;
10507b5038d7SDag-Erling Smørgrav 		}
10517b5038d7SDag-Erling Smørgrav 	}
10527b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
10537b5038d7SDag-Erling Smørgrav }
10547b5038d7SDag-Erling Smørgrav 
10557b5038d7SDag-Erling Smørgrav bool
10567b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
10577b5038d7SDag-Erling Smørgrav {
10587b5038d7SDag-Erling Smørgrav 	ldns_rr* nsec3;
10597b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t* node;
10607b5038d7SDag-Erling Smørgrav 
10617b5038d7SDag-Erling Smørgrav 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
10627b5038d7SDag-Erling Smørgrav 		node = ldns_rbtree_first(zone->names);
10637b5038d7SDag-Erling Smørgrav 		while (node != LDNS_RBTREE_NULL) {
10647b5038d7SDag-Erling Smørgrav 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
10657b5038d7SDag-Erling Smørgrav 			if (nsec3 &&ldns_rr_get_type(nsec3)
10667b5038d7SDag-Erling Smørgrav 					== LDNS_RR_TYPE_NSEC3 &&
10677b5038d7SDag-Erling Smørgrav 					ldns_nsec3_optout(nsec3)) {
10687b5038d7SDag-Erling Smørgrav 				return true;
10697b5038d7SDag-Erling Smørgrav 			}
10707b5038d7SDag-Erling Smørgrav 			node = ldns_rbtree_next(node);
10717b5038d7SDag-Erling Smørgrav 		}
10727b5038d7SDag-Erling Smørgrav 	}
10737b5038d7SDag-Erling Smørgrav 	return false;
10747b5038d7SDag-Erling Smørgrav }
1075