xref: /freebsd/contrib/ldns/dnssec_zone.c (revision 17d15b251108ff09e632ed4812f7c66999a6b69b)
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 */
57*17d15b25SDag-Erling Smørgrav 	cmp = ldns_rr_compare(rrs->rr, rr);
58*17d15b25SDag-Erling Smørgrav 	if (cmp < 0) {
597b5038d7SDag-Erling Smørgrav 		if (rrs->next) {
607b5038d7SDag-Erling Smørgrav 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
617b5038d7SDag-Erling Smørgrav 		} else {
627b5038d7SDag-Erling Smørgrav 			new_rrs = ldns_dnssec_rrs_new();
637b5038d7SDag-Erling Smørgrav 			new_rrs->rr = rr;
647b5038d7SDag-Erling Smørgrav 			rrs->next = new_rrs;
657b5038d7SDag-Erling Smørgrav 		}
667b5038d7SDag-Erling Smørgrav 	} else if (cmp > 0) {
677b5038d7SDag-Erling Smørgrav 		/* put the current old rr in the new next, put the new
687b5038d7SDag-Erling Smørgrav 		   rr in the current container */
697b5038d7SDag-Erling Smørgrav 		new_rrs = ldns_dnssec_rrs_new();
707b5038d7SDag-Erling Smørgrav 		new_rrs->rr = rrs->rr;
717b5038d7SDag-Erling Smørgrav 		new_rrs->next = rrs->next;
727b5038d7SDag-Erling Smørgrav 		rrs->rr = rr;
737b5038d7SDag-Erling Smørgrav 		rrs->next = new_rrs;
747b5038d7SDag-Erling Smørgrav 	}
75*17d15b25SDag-Erling Smørgrav 	/* Silently ignore equal rr's */
767b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
777b5038d7SDag-Erling Smørgrav }
787b5038d7SDag-Erling Smørgrav 
797b5038d7SDag-Erling Smørgrav void
807b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
817b5038d7SDag-Erling Smørgrav 	       ldns_dnssec_rrs *rrs)
827b5038d7SDag-Erling Smørgrav {
837b5038d7SDag-Erling Smørgrav 	if (!rrs) {
847b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
857b5038d7SDag-Erling Smørgrav 			fprintf(out, "; <void>");
867b5038d7SDag-Erling Smørgrav 	} else {
877b5038d7SDag-Erling Smørgrav 		if (rrs->rr) {
887b5038d7SDag-Erling Smørgrav 			ldns_rr_print_fmt(out, fmt, rrs->rr);
897b5038d7SDag-Erling Smørgrav 		}
907b5038d7SDag-Erling Smørgrav 		if (rrs->next) {
917b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
927b5038d7SDag-Erling Smørgrav 		}
937b5038d7SDag-Erling Smørgrav 	}
947b5038d7SDag-Erling Smørgrav }
957b5038d7SDag-Erling Smørgrav 
967b5038d7SDag-Erling Smørgrav void
977b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
987b5038d7SDag-Erling Smørgrav {
997b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
1007b5038d7SDag-Erling Smørgrav }
1017b5038d7SDag-Erling Smørgrav 
1027b5038d7SDag-Erling Smørgrav 
1037b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
1047b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_new(void)
1057b5038d7SDag-Erling Smørgrav {
1067b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1077b5038d7SDag-Erling Smørgrav 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
1087b5038d7SDag-Erling Smørgrav         if(!new_rrsets) return NULL;
1097b5038d7SDag-Erling Smørgrav 	new_rrsets->rrs = NULL;
1107b5038d7SDag-Erling Smørgrav 	new_rrsets->type = 0;
1117b5038d7SDag-Erling Smørgrav 	new_rrsets->signatures = NULL;
1127b5038d7SDag-Erling Smørgrav 	new_rrsets->next = NULL;
1137b5038d7SDag-Erling Smørgrav 	return new_rrsets;
1147b5038d7SDag-Erling Smørgrav }
1157b5038d7SDag-Erling Smørgrav 
1167b5038d7SDag-Erling Smørgrav INLINE void
1177b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
1187b5038d7SDag-Erling Smørgrav {
1197b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1207b5038d7SDag-Erling Smørgrav 		if (rrsets->rrs) {
1217b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
1227b5038d7SDag-Erling Smørgrav 		}
1237b5038d7SDag-Erling Smørgrav 		if (rrsets->next) {
1247b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
1257b5038d7SDag-Erling Smørgrav 		}
1267b5038d7SDag-Erling Smørgrav 		if (rrsets->signatures) {
1277b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
1287b5038d7SDag-Erling Smørgrav 		}
1297b5038d7SDag-Erling Smørgrav 		LDNS_FREE(rrsets);
1307b5038d7SDag-Erling Smørgrav 	}
1317b5038d7SDag-Erling Smørgrav }
1327b5038d7SDag-Erling Smørgrav 
1337b5038d7SDag-Erling Smørgrav void
1347b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
1357b5038d7SDag-Erling Smørgrav {
1367b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
1377b5038d7SDag-Erling Smørgrav }
1387b5038d7SDag-Erling Smørgrav 
1397b5038d7SDag-Erling Smørgrav void
1407b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
1417b5038d7SDag-Erling Smørgrav {
1427b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
1437b5038d7SDag-Erling Smørgrav }
1447b5038d7SDag-Erling Smørgrav 
1457b5038d7SDag-Erling Smørgrav ldns_rr_type
1467b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
1477b5038d7SDag-Erling Smørgrav {
1487b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1497b5038d7SDag-Erling Smørgrav 		return rrsets->type;
1507b5038d7SDag-Erling Smørgrav 	} else {
1517b5038d7SDag-Erling Smørgrav 		return 0;
1527b5038d7SDag-Erling Smørgrav 	}
1537b5038d7SDag-Erling Smørgrav }
1547b5038d7SDag-Erling Smørgrav 
1557b5038d7SDag-Erling Smørgrav ldns_status
1567b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
1577b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type)
1587b5038d7SDag-Erling Smørgrav {
1597b5038d7SDag-Erling Smørgrav 	if (rrsets) {
1607b5038d7SDag-Erling Smørgrav 		rrsets->type = type;
1617b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
1627b5038d7SDag-Erling Smørgrav 	}
1637b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_ERR;
1647b5038d7SDag-Erling Smørgrav }
1657b5038d7SDag-Erling Smørgrav 
1667b5038d7SDag-Erling Smørgrav static ldns_dnssec_rrsets *
1677b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
1687b5038d7SDag-Erling Smørgrav {
1697b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1707b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
1717b5038d7SDag-Erling Smørgrav 	bool rrsig;
1727b5038d7SDag-Erling Smørgrav 
1737b5038d7SDag-Erling Smørgrav 	new_rrsets = ldns_dnssec_rrsets_new();
1747b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
1757b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
1767b5038d7SDag-Erling Smørgrav 		rrsig = true;
1777b5038d7SDag-Erling Smørgrav 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1787b5038d7SDag-Erling Smørgrav 	} else {
1797b5038d7SDag-Erling Smørgrav 		rrsig = false;
1807b5038d7SDag-Erling Smørgrav 	}
1817b5038d7SDag-Erling Smørgrav 	if (!rrsig) {
1827b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs = ldns_dnssec_rrs_new();
1837b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs->rr = rr;
1847b5038d7SDag-Erling Smørgrav 	} else {
1857b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures = ldns_dnssec_rrs_new();
1867b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures->rr = rr;
1877b5038d7SDag-Erling Smørgrav 	}
1887b5038d7SDag-Erling Smørgrav 	new_rrsets->type = rr_type;
1897b5038d7SDag-Erling Smørgrav 	return new_rrsets;
1907b5038d7SDag-Erling Smørgrav }
1917b5038d7SDag-Erling Smørgrav 
1927b5038d7SDag-Erling Smørgrav ldns_status
1937b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
1947b5038d7SDag-Erling Smørgrav {
1957b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *new_rrsets;
1967b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
1977b5038d7SDag-Erling Smørgrav 	bool rrsig = false;
1987b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
1997b5038d7SDag-Erling Smørgrav 
2007b5038d7SDag-Erling Smørgrav 	if (!rrsets || !rr) {
2017b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
2027b5038d7SDag-Erling Smørgrav 	}
2037b5038d7SDag-Erling Smørgrav 
2047b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
2057b5038d7SDag-Erling Smørgrav 
2067b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
2077b5038d7SDag-Erling Smørgrav 		rrsig = true;
2087b5038d7SDag-Erling Smørgrav 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
2097b5038d7SDag-Erling Smørgrav 	}
2107b5038d7SDag-Erling Smørgrav 
2117b5038d7SDag-Erling Smørgrav 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
2127b5038d7SDag-Erling Smørgrav 		if (!rrsig) {
2137b5038d7SDag-Erling Smørgrav 			rrsets->rrs = ldns_dnssec_rrs_new();
2147b5038d7SDag-Erling Smørgrav 			rrsets->rrs->rr = rr;
2157b5038d7SDag-Erling Smørgrav 			rrsets->type = rr_type;
2167b5038d7SDag-Erling Smørgrav 		} else {
2177b5038d7SDag-Erling Smørgrav 			rrsets->signatures = ldns_dnssec_rrs_new();
2187b5038d7SDag-Erling Smørgrav 			rrsets->signatures->rr = rr;
2197b5038d7SDag-Erling Smørgrav 			rrsets->type = rr_type;
2207b5038d7SDag-Erling Smørgrav 		}
2217b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
2227b5038d7SDag-Erling Smørgrav 	}
2237b5038d7SDag-Erling Smørgrav 
2247b5038d7SDag-Erling Smørgrav 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
2257b5038d7SDag-Erling Smørgrav 		if (rrsets->next) {
2267b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
2277b5038d7SDag-Erling Smørgrav 		} else {
2287b5038d7SDag-Erling Smørgrav 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
2297b5038d7SDag-Erling Smørgrav 			rrsets->next = new_rrsets;
2307b5038d7SDag-Erling Smørgrav 		}
2317b5038d7SDag-Erling Smørgrav 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
2327b5038d7SDag-Erling Smørgrav 		/* move the current one into the new next,
2337b5038d7SDag-Erling Smørgrav 		   replace field of current with data from new rr */
2347b5038d7SDag-Erling Smørgrav 		new_rrsets = ldns_dnssec_rrsets_new();
2357b5038d7SDag-Erling Smørgrav 		new_rrsets->rrs = rrsets->rrs;
2367b5038d7SDag-Erling Smørgrav 		new_rrsets->type = rrsets->type;
2377b5038d7SDag-Erling Smørgrav 		new_rrsets->signatures = rrsets->signatures;
2387b5038d7SDag-Erling Smørgrav 		new_rrsets->next = rrsets->next;
2397b5038d7SDag-Erling Smørgrav 		if (!rrsig) {
2407b5038d7SDag-Erling Smørgrav 			rrsets->rrs = ldns_dnssec_rrs_new();
2417b5038d7SDag-Erling Smørgrav 			rrsets->rrs->rr = rr;
2427b5038d7SDag-Erling Smørgrav 			rrsets->signatures = NULL;
2437b5038d7SDag-Erling Smørgrav 		} else {
2447b5038d7SDag-Erling Smørgrav 			rrsets->rrs = NULL;
2457b5038d7SDag-Erling Smørgrav 			rrsets->signatures = ldns_dnssec_rrs_new();
2467b5038d7SDag-Erling Smørgrav 			rrsets->signatures->rr = rr;
2477b5038d7SDag-Erling Smørgrav 		}
2487b5038d7SDag-Erling Smørgrav 		rrsets->type = rr_type;
2497b5038d7SDag-Erling Smørgrav 		rrsets->next = new_rrsets;
2507b5038d7SDag-Erling Smørgrav 	} else {
2517b5038d7SDag-Erling Smørgrav 		/* equal, add to current rrsets */
2527b5038d7SDag-Erling Smørgrav 		if (rrsig) {
2537b5038d7SDag-Erling Smørgrav 			if (rrsets->signatures) {
2547b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
2557b5038d7SDag-Erling Smørgrav 			} else {
2567b5038d7SDag-Erling Smørgrav 				rrsets->signatures = ldns_dnssec_rrs_new();
2577b5038d7SDag-Erling Smørgrav 				rrsets->signatures->rr = rr;
2587b5038d7SDag-Erling Smørgrav 			}
2597b5038d7SDag-Erling Smørgrav 		} else {
2607b5038d7SDag-Erling Smørgrav 			if (rrsets->rrs) {
2617b5038d7SDag-Erling Smørgrav 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
2627b5038d7SDag-Erling Smørgrav 			} else {
2637b5038d7SDag-Erling Smørgrav 				rrsets->rrs = ldns_dnssec_rrs_new();
2647b5038d7SDag-Erling Smørgrav 				rrsets->rrs->rr = rr;
2657b5038d7SDag-Erling Smørgrav 			}
2667b5038d7SDag-Erling Smørgrav 		}
2677b5038d7SDag-Erling Smørgrav 	}
2687b5038d7SDag-Erling Smørgrav 
2697b5038d7SDag-Erling Smørgrav 	return result;
2707b5038d7SDag-Erling Smørgrav }
2717b5038d7SDag-Erling Smørgrav 
2727b5038d7SDag-Erling Smørgrav static void
2737b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
2747b5038d7SDag-Erling Smørgrav 		ldns_dnssec_rrsets *rrsets,
2757b5038d7SDag-Erling Smørgrav 		bool follow,
2767b5038d7SDag-Erling Smørgrav 		bool show_soa)
2777b5038d7SDag-Erling Smørgrav {
2787b5038d7SDag-Erling Smørgrav 	if (!rrsets) {
2797b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
2807b5038d7SDag-Erling Smørgrav 			fprintf(out, "; <void>\n");
2817b5038d7SDag-Erling Smørgrav 	} else {
2827b5038d7SDag-Erling Smørgrav 		if (rrsets->rrs &&
2837b5038d7SDag-Erling Smørgrav 		    (show_soa ||
2847b5038d7SDag-Erling Smørgrav 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
2857b5038d7SDag-Erling Smørgrav 		    )
2867b5038d7SDag-Erling Smørgrav 		   ) {
2877b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
2887b5038d7SDag-Erling Smørgrav 			if (rrsets->signatures) {
2897b5038d7SDag-Erling Smørgrav 				ldns_dnssec_rrs_print_fmt(out, fmt,
2907b5038d7SDag-Erling Smørgrav 						rrsets->signatures);
2917b5038d7SDag-Erling Smørgrav 			}
2927b5038d7SDag-Erling Smørgrav 		}
2937b5038d7SDag-Erling Smørgrav 		if (follow && rrsets->next) {
2947b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
2957b5038d7SDag-Erling Smørgrav 					rrsets->next, follow, show_soa);
2967b5038d7SDag-Erling Smørgrav 		}
2977b5038d7SDag-Erling Smørgrav 	}
2987b5038d7SDag-Erling Smørgrav }
2997b5038d7SDag-Erling Smørgrav 
3007b5038d7SDag-Erling Smørgrav 
3017b5038d7SDag-Erling Smørgrav void
3027b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
3037b5038d7SDag-Erling Smørgrav 		ldns_dnssec_rrsets *rrsets,
3047b5038d7SDag-Erling Smørgrav 		bool follow)
3057b5038d7SDag-Erling Smørgrav {
3067b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
3077b5038d7SDag-Erling Smørgrav }
3087b5038d7SDag-Erling Smørgrav 
3097b5038d7SDag-Erling Smørgrav void
3107b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
3117b5038d7SDag-Erling Smørgrav {
3127b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
3137b5038d7SDag-Erling Smørgrav 			rrsets, follow);
3147b5038d7SDag-Erling Smørgrav }
3157b5038d7SDag-Erling Smørgrav 
3167b5038d7SDag-Erling Smørgrav ldns_dnssec_name *
3177b5038d7SDag-Erling Smørgrav ldns_dnssec_name_new(void)
3187b5038d7SDag-Erling Smørgrav {
3197b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name;
3207b5038d7SDag-Erling Smørgrav 
3217b5038d7SDag-Erling Smørgrav 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
3227b5038d7SDag-Erling Smørgrav 	if (!new_name) {
3237b5038d7SDag-Erling Smørgrav 		return NULL;
3247b5038d7SDag-Erling Smørgrav 	}
3257b5038d7SDag-Erling Smørgrav 	/*
3267b5038d7SDag-Erling Smørgrav 	 * not needed anymore because CALLOC initalizes everything to zero.
3277b5038d7SDag-Erling Smørgrav 
3287b5038d7SDag-Erling Smørgrav 	new_name->name = NULL;
3297b5038d7SDag-Erling Smørgrav 	new_name->rrsets = NULL;
3307b5038d7SDag-Erling Smørgrav 	new_name->name_alloced = false;
3317b5038d7SDag-Erling Smørgrav 	new_name->nsec = NULL;
3327b5038d7SDag-Erling Smørgrav 	new_name->nsec_signatures = NULL;
3337b5038d7SDag-Erling Smørgrav 
3347b5038d7SDag-Erling Smørgrav 	new_name->is_glue = false;
3357b5038d7SDag-Erling Smørgrav 	new_name->hashed_name = NULL;
3367b5038d7SDag-Erling Smørgrav 
3377b5038d7SDag-Erling Smørgrav 	 */
3387b5038d7SDag-Erling Smørgrav 	return new_name;
3397b5038d7SDag-Erling Smørgrav }
3407b5038d7SDag-Erling Smørgrav 
3417b5038d7SDag-Erling Smørgrav ldns_dnssec_name *
3427b5038d7SDag-Erling Smørgrav ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
3437b5038d7SDag-Erling Smørgrav {
3447b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
3457b5038d7SDag-Erling Smørgrav 
3467b5038d7SDag-Erling Smørgrav 	new_name->name = ldns_rr_owner(rr);
3477b5038d7SDag-Erling Smørgrav 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
3487b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name_free(new_name);
3497b5038d7SDag-Erling Smørgrav 		return NULL;
3507b5038d7SDag-Erling Smørgrav 	}
3517b5038d7SDag-Erling Smørgrav 
3527b5038d7SDag-Erling Smørgrav 	return new_name;
3537b5038d7SDag-Erling Smørgrav }
3547b5038d7SDag-Erling Smørgrav 
3557b5038d7SDag-Erling Smørgrav INLINE void
3567b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
3577b5038d7SDag-Erling Smørgrav                                int deep)
3587b5038d7SDag-Erling Smørgrav {
3597b5038d7SDag-Erling Smørgrav 	if (name) {
3607b5038d7SDag-Erling Smørgrav 		if (name->name_alloced) {
3617b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(name->name);
3627b5038d7SDag-Erling Smørgrav 		}
3637b5038d7SDag-Erling Smørgrav 		if (name->rrsets) {
3647b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
3657b5038d7SDag-Erling Smørgrav 		}
3667b5038d7SDag-Erling Smørgrav 		if (name->nsec && deep) {
3677b5038d7SDag-Erling Smørgrav 			ldns_rr_free(name->nsec);
3687b5038d7SDag-Erling Smørgrav 		}
3697b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
3707b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
3717b5038d7SDag-Erling Smørgrav 		}
3727b5038d7SDag-Erling Smørgrav 		if (name->hashed_name) {
3737b5038d7SDag-Erling Smørgrav 			if (deep) {
3747b5038d7SDag-Erling Smørgrav 				ldns_rdf_deep_free(name->hashed_name);
3757b5038d7SDag-Erling Smørgrav 			}
3767b5038d7SDag-Erling Smørgrav 		}
3777b5038d7SDag-Erling Smørgrav 		LDNS_FREE(name);
3787b5038d7SDag-Erling Smørgrav 	}
3797b5038d7SDag-Erling Smørgrav }
3807b5038d7SDag-Erling Smørgrav 
3817b5038d7SDag-Erling Smørgrav void
3827b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free(ldns_dnssec_name *name)
3837b5038d7SDag-Erling Smørgrav {
3847b5038d7SDag-Erling Smørgrav   ldns_dnssec_name_free_internal(name, 0);
3857b5038d7SDag-Erling Smørgrav }
3867b5038d7SDag-Erling Smørgrav 
3877b5038d7SDag-Erling Smørgrav void
3887b5038d7SDag-Erling Smørgrav ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
3897b5038d7SDag-Erling Smørgrav {
3907b5038d7SDag-Erling Smørgrav   ldns_dnssec_name_free_internal(name, 1);
3917b5038d7SDag-Erling Smørgrav }
3927b5038d7SDag-Erling Smørgrav 
3937b5038d7SDag-Erling Smørgrav ldns_rdf *
3947b5038d7SDag-Erling Smørgrav ldns_dnssec_name_name(ldns_dnssec_name *name)
3957b5038d7SDag-Erling Smørgrav {
3967b5038d7SDag-Erling Smørgrav 	if (name) {
3977b5038d7SDag-Erling Smørgrav 		return name->name;
3987b5038d7SDag-Erling Smørgrav 	}
3997b5038d7SDag-Erling Smørgrav 	return NULL;
4007b5038d7SDag-Erling Smørgrav }
4017b5038d7SDag-Erling Smørgrav 
4027b5038d7SDag-Erling Smørgrav bool
4037b5038d7SDag-Erling Smørgrav ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
4047b5038d7SDag-Erling Smørgrav {
4057b5038d7SDag-Erling Smørgrav 	if (name) {
4067b5038d7SDag-Erling Smørgrav 		return name->is_glue;
4077b5038d7SDag-Erling Smørgrav 	}
4087b5038d7SDag-Erling Smørgrav 	return false;
4097b5038d7SDag-Erling Smørgrav }
4107b5038d7SDag-Erling Smørgrav 
4117b5038d7SDag-Erling Smørgrav void
4127b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
4137b5038d7SDag-Erling Smørgrav 					 ldns_rdf *dname)
4147b5038d7SDag-Erling Smørgrav {
4157b5038d7SDag-Erling Smørgrav 	if (rrset && dname) {
4167b5038d7SDag-Erling Smørgrav 		rrset->name = dname;
4177b5038d7SDag-Erling Smørgrav 	}
4187b5038d7SDag-Erling Smørgrav }
4197b5038d7SDag-Erling Smørgrav 
4207b5038d7SDag-Erling Smørgrav 
4217b5038d7SDag-Erling Smørgrav void
4227b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
4237b5038d7SDag-Erling Smørgrav {
4247b5038d7SDag-Erling Smørgrav 	if (rrset && nsec) {
4257b5038d7SDag-Erling Smørgrav 		rrset->nsec = nsec;
4267b5038d7SDag-Erling Smørgrav 	}
4277b5038d7SDag-Erling Smørgrav }
4287b5038d7SDag-Erling Smørgrav 
4297b5038d7SDag-Erling Smørgrav int
4307b5038d7SDag-Erling Smørgrav ldns_dnssec_name_cmp(const void *a, const void *b)
4317b5038d7SDag-Erling Smørgrav {
4327b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
4337b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
4347b5038d7SDag-Erling Smørgrav 
4357b5038d7SDag-Erling Smørgrav 	if (na && nb) {
4367b5038d7SDag-Erling Smørgrav 		return ldns_dname_compare(ldns_dnssec_name_name(na),
4377b5038d7SDag-Erling Smørgrav 							 ldns_dnssec_name_name(nb));
4387b5038d7SDag-Erling Smørgrav 	} else if (na) {
4397b5038d7SDag-Erling Smørgrav 		return 1;
4407b5038d7SDag-Erling Smørgrav 	} else if (nb) {
4417b5038d7SDag-Erling Smørgrav 		return -1;
4427b5038d7SDag-Erling Smørgrav 	} else {
4437b5038d7SDag-Erling Smørgrav 		return 0;
4447b5038d7SDag-Erling Smørgrav 	}
4457b5038d7SDag-Erling Smørgrav }
4467b5038d7SDag-Erling Smørgrav 
4477b5038d7SDag-Erling Smørgrav ldns_status
4487b5038d7SDag-Erling Smørgrav ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
4497b5038d7SDag-Erling Smørgrav 				    ldns_rr *rr)
4507b5038d7SDag-Erling Smørgrav {
4517b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
4527b5038d7SDag-Erling Smørgrav 	ldns_rr_type rr_type;
4537b5038d7SDag-Erling Smørgrav 	ldns_rr_type typecovered = 0;
4547b5038d7SDag-Erling Smørgrav 
4557b5038d7SDag-Erling Smørgrav 	/* special handling for NSEC3 and NSECX covering RRSIGS */
4567b5038d7SDag-Erling Smørgrav 
4577b5038d7SDag-Erling Smørgrav 	if (!name || !rr) {
4587b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
4597b5038d7SDag-Erling Smørgrav 	}
4607b5038d7SDag-Erling Smørgrav 
4617b5038d7SDag-Erling Smørgrav 	rr_type = ldns_rr_get_type(rr);
4627b5038d7SDag-Erling Smørgrav 
4637b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
4647b5038d7SDag-Erling Smørgrav 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
4657b5038d7SDag-Erling Smørgrav 	}
4667b5038d7SDag-Erling Smørgrav 
4677b5038d7SDag-Erling Smørgrav 	if (rr_type == LDNS_RR_TYPE_NSEC ||
4687b5038d7SDag-Erling Smørgrav 	    rr_type == LDNS_RR_TYPE_NSEC3) {
4697b5038d7SDag-Erling Smørgrav 		/* XX check if is already set (and error?) */
4707b5038d7SDag-Erling Smørgrav 		name->nsec = rr;
4717b5038d7SDag-Erling Smørgrav 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
4727b5038d7SDag-Erling Smørgrav 			 typecovered == LDNS_RR_TYPE_NSEC3) {
4737b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
4747b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
4757b5038d7SDag-Erling Smørgrav 		} else {
4767b5038d7SDag-Erling Smørgrav 			name->nsec_signatures = ldns_dnssec_rrs_new();
4777b5038d7SDag-Erling Smørgrav 			name->nsec_signatures->rr = rr;
4787b5038d7SDag-Erling Smørgrav 		}
4797b5038d7SDag-Erling Smørgrav 	} else {
4807b5038d7SDag-Erling Smørgrav 		/* it's a 'normal' RR, add it to the right rrset */
4817b5038d7SDag-Erling Smørgrav 		if (name->rrsets) {
4827b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
4837b5038d7SDag-Erling Smørgrav 		} else {
4847b5038d7SDag-Erling Smørgrav 			name->rrsets = ldns_dnssec_rrsets_new();
4857b5038d7SDag-Erling Smørgrav 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
4867b5038d7SDag-Erling Smørgrav 		}
4877b5038d7SDag-Erling Smørgrav 	}
4887b5038d7SDag-Erling Smørgrav 	return result;
4897b5038d7SDag-Erling Smørgrav }
4907b5038d7SDag-Erling Smørgrav 
4917b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
4927b5038d7SDag-Erling Smørgrav ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
4937b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type) {
4947b5038d7SDag-Erling Smørgrav 	ldns_dnssec_rrsets *result;
4957b5038d7SDag-Erling Smørgrav 
4967b5038d7SDag-Erling Smørgrav 	result = name->rrsets;
4977b5038d7SDag-Erling Smørgrav 	while (result) {
4987b5038d7SDag-Erling Smørgrav 		if (result->type == type) {
4997b5038d7SDag-Erling Smørgrav 			return result;
5007b5038d7SDag-Erling Smørgrav 		} else {
5017b5038d7SDag-Erling Smørgrav 			result = result->next;
5027b5038d7SDag-Erling Smørgrav 		}
5037b5038d7SDag-Erling Smørgrav 	}
5047b5038d7SDag-Erling Smørgrav 	return NULL;
5057b5038d7SDag-Erling Smørgrav }
5067b5038d7SDag-Erling Smørgrav 
5077b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
5087b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
5097b5038d7SDag-Erling Smørgrav 					   ldns_rdf *dname,
5107b5038d7SDag-Erling Smørgrav 					   ldns_rr_type type)
5117b5038d7SDag-Erling Smørgrav {
5127b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *node;
5137b5038d7SDag-Erling Smørgrav 
5147b5038d7SDag-Erling Smørgrav 	if (!zone || !dname) {
5157b5038d7SDag-Erling Smørgrav 		return NULL;
5167b5038d7SDag-Erling Smørgrav 	}
5177b5038d7SDag-Erling Smørgrav 
5187b5038d7SDag-Erling Smørgrav 	node = ldns_rbtree_search(zone->names, dname);
5197b5038d7SDag-Erling Smørgrav 	if (node) {
5207b5038d7SDag-Erling Smørgrav 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
5217b5038d7SDag-Erling Smørgrav 									type);
5227b5038d7SDag-Erling Smørgrav 	} else {
5237b5038d7SDag-Erling Smørgrav 		return NULL;
5247b5038d7SDag-Erling Smørgrav 	}
5257b5038d7SDag-Erling Smørgrav }
5267b5038d7SDag-Erling Smørgrav 
5277b5038d7SDag-Erling Smørgrav static void
5287b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
5297b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name *name,
5307b5038d7SDag-Erling Smørgrav 		bool show_soa)
5317b5038d7SDag-Erling Smørgrav {
5327b5038d7SDag-Erling Smørgrav 	if (name) {
5337b5038d7SDag-Erling Smørgrav 		if(name->rrsets) {
5347b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
5357b5038d7SDag-Erling Smørgrav 					name->rrsets, true, show_soa);
5367b5038d7SDag-Erling Smørgrav 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5377b5038d7SDag-Erling Smørgrav 			fprintf(out, ";; Empty nonterminal: ");
5387b5038d7SDag-Erling Smørgrav 			ldns_rdf_print(out, name->name);
5397b5038d7SDag-Erling Smørgrav 			fprintf(out, "\n");
5407b5038d7SDag-Erling Smørgrav 		}
5417b5038d7SDag-Erling Smørgrav 		if(name->nsec) {
5427b5038d7SDag-Erling Smørgrav 			ldns_rr_print_fmt(out, fmt, name->nsec);
5437b5038d7SDag-Erling Smørgrav 		}
5447b5038d7SDag-Erling Smørgrav 		if (name->nsec_signatures) {
5457b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrs_print_fmt(out, fmt,
5467b5038d7SDag-Erling Smørgrav 					name->nsec_signatures);
5477b5038d7SDag-Erling Smørgrav 		}
5487b5038d7SDag-Erling Smørgrav 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5497b5038d7SDag-Erling Smørgrav 		fprintf(out, "; <void>\n");
5507b5038d7SDag-Erling Smørgrav 	}
5517b5038d7SDag-Erling Smørgrav }
5527b5038d7SDag-Erling Smørgrav 
5537b5038d7SDag-Erling Smørgrav 
5547b5038d7SDag-Erling Smørgrav void
5557b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
5567b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name *name)
5577b5038d7SDag-Erling Smørgrav {
5587b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
5597b5038d7SDag-Erling Smørgrav }
5607b5038d7SDag-Erling Smørgrav 
5617b5038d7SDag-Erling Smørgrav void
5627b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
5637b5038d7SDag-Erling Smørgrav {
5647b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
5657b5038d7SDag-Erling Smørgrav }
5667b5038d7SDag-Erling Smørgrav 
5677b5038d7SDag-Erling Smørgrav 
5687b5038d7SDag-Erling Smørgrav ldns_dnssec_zone *
5697b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new(void)
5707b5038d7SDag-Erling Smørgrav {
5717b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
5727b5038d7SDag-Erling Smørgrav         if(!zone) return NULL;
5737b5038d7SDag-Erling Smørgrav 	zone->soa = NULL;
5747b5038d7SDag-Erling Smørgrav 	zone->names = NULL;
575*17d15b25SDag-Erling Smørgrav 	zone->hashed_names = NULL;
576*17d15b25SDag-Erling Smørgrav 	zone->_nsec3params = NULL;
5777b5038d7SDag-Erling Smørgrav 
5787b5038d7SDag-Erling Smørgrav 	return zone;
5797b5038d7SDag-Erling Smørgrav }
5807b5038d7SDag-Erling Smørgrav 
5817b5038d7SDag-Erling Smørgrav static bool
5827b5038d7SDag-Erling Smørgrav rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
5837b5038d7SDag-Erling Smørgrav {
5847b5038d7SDag-Erling Smørgrav 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
5857b5038d7SDag-Erling Smørgrav 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
5867b5038d7SDag-Erling Smørgrav }
5877b5038d7SDag-Erling Smørgrav 
5887b5038d7SDag-Erling Smørgrav /* When the zone is first read into an list and then inserted into an
5897b5038d7SDag-Erling Smørgrav  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
5907b5038d7SDag-Erling Smørgrav  * to each other. Because ldns-verify-zone (the only program that uses this
5917b5038d7SDag-Erling Smørgrav  * function) uses the rbtree mostly for sequentual walking, this results
5927b5038d7SDag-Erling Smørgrav  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
5937b5038d7SDag-Erling Smørgrav  */
5947b5038d7SDag-Erling Smørgrav #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
5957b5038d7SDag-Erling Smørgrav 
5967b5038d7SDag-Erling Smørgrav ldns_status
5977b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
5987b5038d7SDag-Erling Smørgrav 	       	uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
5997b5038d7SDag-Erling Smørgrav {
6007b5038d7SDag-Erling Smørgrav 	ldns_rr* cur_rr;
6017b5038d7SDag-Erling Smørgrav 	size_t i;
6027b5038d7SDag-Erling Smørgrav 
6037b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_origin = NULL;
6047b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_prev = NULL;
6057b5038d7SDag-Erling Smørgrav 
6067b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
6077b5038d7SDag-Erling Smørgrav 	/* when reading NSEC3s, there is a chance that we encounter nsecs
6087b5038d7SDag-Erling Smørgrav 	   for empty nonterminals, whose nonterminals we cannot derive yet
6097b5038d7SDag-Erling Smørgrav 	   because the needed information is to be read later. in that case
6107b5038d7SDag-Erling Smørgrav 	   we keep a list of those nsec3's and retry to add them later */
6117b5038d7SDag-Erling Smørgrav 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
6127b5038d7SDag-Erling Smørgrav 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
6137b5038d7SDag-Erling Smørgrav 
6147b5038d7SDag-Erling Smørgrav 	ldns_status status = LDNS_STATUS_MEM_ERR;
6157b5038d7SDag-Erling Smørgrav 
6167b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6177b5038d7SDag-Erling Smørgrav 	ldns_zone* zone = NULL;
6187b5038d7SDag-Erling Smørgrav 	if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
6197b5038d7SDag-Erling Smørgrav 			!= LDNS_STATUS_OK) goto error;
6207b5038d7SDag-Erling Smørgrav #else
6217b5038d7SDag-Erling Smørgrav 	uint32_t  my_ttl = ttl;
6227b5038d7SDag-Erling Smørgrav #endif
6237b5038d7SDag-Erling Smørgrav 
6247b5038d7SDag-Erling Smørgrav 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
6257b5038d7SDag-Erling Smørgrav 
6267b5038d7SDag-Erling Smørgrav 	if (origin) {
6277b5038d7SDag-Erling Smørgrav 		if (!(my_origin = ldns_rdf_clone(origin))) goto error;
6287b5038d7SDag-Erling Smørgrav 		if (!(my_prev   = ldns_rdf_clone(origin))) goto error;
6297b5038d7SDag-Erling Smørgrav 	}
6307b5038d7SDag-Erling Smørgrav 
6317b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6327b5038d7SDag-Erling Smørgrav 	if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
6337b5038d7SDag-Erling Smørgrav 			!= LDNS_STATUS_OK) goto error;
6347b5038d7SDag-Erling Smørgrav 
6357b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
6367b5038d7SDag-Erling Smørgrav 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
6377b5038d7SDag-Erling Smørgrav 		status = LDNS_STATUS_OK;
6387b5038d7SDag-Erling Smørgrav #else
6397b5038d7SDag-Erling Smørgrav 	while (!feof(fp)) {
6407b5038d7SDag-Erling Smørgrav 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
6417b5038d7SDag-Erling Smørgrav 				&my_prev, line_nr);
6427b5038d7SDag-Erling Smørgrav 
6437b5038d7SDag-Erling Smørgrav #endif
6447b5038d7SDag-Erling Smørgrav 		switch (status) {
6457b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_OK:
6467b5038d7SDag-Erling Smørgrav 
6477b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
6487b5038d7SDag-Erling Smørgrav 			if (status ==
6497b5038d7SDag-Erling Smørgrav 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
6507b5038d7SDag-Erling Smørgrav 
6517b5038d7SDag-Erling Smørgrav 				if (rr_is_rrsig_covering(cur_rr,
6527b5038d7SDag-Erling Smørgrav 							LDNS_RR_TYPE_NSEC3)){
6537b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
6547b5038d7SDag-Erling Smørgrav 							cur_rr);
6557b5038d7SDag-Erling Smørgrav 				} else {
6567b5038d7SDag-Erling Smørgrav 					ldns_rr_list_push_rr(todo_nsec3s,
6577b5038d7SDag-Erling Smørgrav 						       	cur_rr);
6587b5038d7SDag-Erling Smørgrav 				}
659*17d15b25SDag-Erling Smørgrav 				status = LDNS_STATUS_OK;
660*17d15b25SDag-Erling Smørgrav 
6617b5038d7SDag-Erling Smørgrav 			} else if (status != LDNS_STATUS_OK)
6627b5038d7SDag-Erling Smørgrav 				goto error;
6637b5038d7SDag-Erling Smørgrav 
6647b5038d7SDag-Erling Smørgrav 			break;
6657b5038d7SDag-Erling Smørgrav 
6667b5038d7SDag-Erling Smørgrav 
6677b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
6687b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
6697b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
6702787e39aSDag-Erling Smørgrav 			status = LDNS_STATUS_OK;
6717b5038d7SDag-Erling Smørgrav 			break;
6727b5038d7SDag-Erling Smørgrav 
6737b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
6747b5038d7SDag-Erling Smørgrav 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
6757b5038d7SDag-Erling Smørgrav 			break;
6767b5038d7SDag-Erling Smørgrav 
6777b5038d7SDag-Erling Smørgrav 		default:
6787b5038d7SDag-Erling Smørgrav 			goto error;
6797b5038d7SDag-Erling Smørgrav 		}
6807b5038d7SDag-Erling Smørgrav 	}
6817b5038d7SDag-Erling Smørgrav 
6827b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
6837b5038d7SDag-Erling Smørgrav 		(void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
6842787e39aSDag-Erling Smørgrav 		for (i = 0; status == LDNS_STATUS_OK &&
6852787e39aSDag-Erling Smørgrav 				i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
6867b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
6877b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
6887b5038d7SDag-Erling Smørgrav 		}
6897b5038d7SDag-Erling Smørgrav 	}
690*17d15b25SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
6912787e39aSDag-Erling Smørgrav 		for (i = 0; status == LDNS_STATUS_OK &&
6922787e39aSDag-Erling Smørgrav 				i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
6932787e39aSDag-Erling Smørgrav 				i++){
6947b5038d7SDag-Erling Smørgrav 			cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
6957b5038d7SDag-Erling Smørgrav 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
6967b5038d7SDag-Erling Smørgrav 		}
6977b5038d7SDag-Erling Smørgrav 	}
6987b5038d7SDag-Erling Smørgrav 
6997b5038d7SDag-Erling Smørgrav 	if (z) {
7007b5038d7SDag-Erling Smørgrav 		*z = newzone;
7012787e39aSDag-Erling Smørgrav 		newzone = NULL;
7027b5038d7SDag-Erling Smørgrav 	} else {
7037b5038d7SDag-Erling Smørgrav 		ldns_dnssec_zone_free(newzone);
7047b5038d7SDag-Erling Smørgrav 	}
7057b5038d7SDag-Erling Smørgrav 
7067b5038d7SDag-Erling Smørgrav error:
7077b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
7087b5038d7SDag-Erling Smørgrav 	if (zone) {
7097b5038d7SDag-Erling Smørgrav 		ldns_zone_free(zone);
7107b5038d7SDag-Erling Smørgrav 	}
7117b5038d7SDag-Erling Smørgrav #endif
7122787e39aSDag-Erling Smørgrav 	ldns_rr_list_free(todo_nsec3_rrsigs);
7132787e39aSDag-Erling Smørgrav 	ldns_rr_list_free(todo_nsec3s);
7142787e39aSDag-Erling Smørgrav 
7157b5038d7SDag-Erling Smørgrav 	if (my_origin) {
7167b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_origin);
7177b5038d7SDag-Erling Smørgrav 	}
7187b5038d7SDag-Erling Smørgrav 	if (my_prev) {
7197b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_prev);
7207b5038d7SDag-Erling Smørgrav 	}
7217b5038d7SDag-Erling Smørgrav 	if (newzone) {
7227b5038d7SDag-Erling Smørgrav 		ldns_dnssec_zone_free(newzone);
7237b5038d7SDag-Erling Smørgrav 	}
7247b5038d7SDag-Erling Smørgrav 	return status;
7257b5038d7SDag-Erling Smørgrav }
7267b5038d7SDag-Erling Smørgrav 
7277b5038d7SDag-Erling Smørgrav ldns_status
7287b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
7297b5038d7SDag-Erling Smørgrav 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
7307b5038d7SDag-Erling Smørgrav {
7317b5038d7SDag-Erling Smørgrav 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
7327b5038d7SDag-Erling Smørgrav }
7337b5038d7SDag-Erling Smørgrav 
7347b5038d7SDag-Erling Smørgrav static void
7357b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
7367b5038d7SDag-Erling Smørgrav 	(void) arg;
7377b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
7387b5038d7SDag-Erling Smørgrav 	LDNS_FREE(node);
7397b5038d7SDag-Erling Smørgrav }
7407b5038d7SDag-Erling Smørgrav 
7417b5038d7SDag-Erling Smørgrav static void
7427b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
7437b5038d7SDag-Erling Smørgrav 	(void) arg;
7447b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
7457b5038d7SDag-Erling Smørgrav 	LDNS_FREE(node);
7467b5038d7SDag-Erling Smørgrav }
7477b5038d7SDag-Erling Smørgrav 
7487b5038d7SDag-Erling Smørgrav void
7497b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
7507b5038d7SDag-Erling Smørgrav {
7517b5038d7SDag-Erling Smørgrav 	if (zone) {
7527b5038d7SDag-Erling Smørgrav 		if (zone->names) {
7537b5038d7SDag-Erling Smørgrav 			/* destroy all name structures within the tree */
7547b5038d7SDag-Erling Smørgrav 			ldns_traverse_postorder(zone->names,
7557b5038d7SDag-Erling Smørgrav 						    ldns_dnssec_name_node_free,
7567b5038d7SDag-Erling Smørgrav 						    NULL);
7577b5038d7SDag-Erling Smørgrav 			LDNS_FREE(zone->names);
7587b5038d7SDag-Erling Smørgrav 		}
7597b5038d7SDag-Erling Smørgrav 		LDNS_FREE(zone);
7607b5038d7SDag-Erling Smørgrav 	}
7617b5038d7SDag-Erling Smørgrav }
7627b5038d7SDag-Erling Smørgrav 
7637b5038d7SDag-Erling Smørgrav void
7647b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
7657b5038d7SDag-Erling Smørgrav {
7667b5038d7SDag-Erling Smørgrav 	if (zone) {
7677b5038d7SDag-Erling Smørgrav 		if (zone->names) {
7687b5038d7SDag-Erling Smørgrav 			/* destroy all name structures within the tree */
7697b5038d7SDag-Erling Smørgrav 			ldns_traverse_postorder(zone->names,
7707b5038d7SDag-Erling Smørgrav 						    ldns_dnssec_name_node_deep_free,
7717b5038d7SDag-Erling Smørgrav 						    NULL);
7727b5038d7SDag-Erling Smørgrav 			LDNS_FREE(zone->names);
7737b5038d7SDag-Erling Smørgrav 		}
7747b5038d7SDag-Erling Smørgrav 		LDNS_FREE(zone);
7757b5038d7SDag-Erling Smørgrav 	}
7767b5038d7SDag-Erling Smørgrav }
7777b5038d7SDag-Erling Smørgrav 
7787b5038d7SDag-Erling Smørgrav /* use for dname comparison in tree */
779d6e492feSDag-Erling Smørgrav int
7807b5038d7SDag-Erling Smørgrav ldns_dname_compare_v(const void *a, const void *b) {
7817b5038d7SDag-Erling Smørgrav 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
7827b5038d7SDag-Erling Smørgrav }
7837b5038d7SDag-Erling Smørgrav 
784*17d15b25SDag-Erling Smørgrav static void
785*17d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
786*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_name* name, ldns_rr* nsec3rr);
787*17d15b25SDag-Erling Smørgrav 
788*17d15b25SDag-Erling Smørgrav static void
789*17d15b25SDag-Erling Smørgrav ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
790*17d15b25SDag-Erling Smørgrav 	(void) arg;
791*17d15b25SDag-Erling Smørgrav 	LDNS_FREE(node);
792*17d15b25SDag-Erling Smørgrav }
793*17d15b25SDag-Erling Smørgrav 
794*17d15b25SDag-Erling Smørgrav static void
795*17d15b25SDag-Erling Smørgrav ldns_dnssec_zone_hashed_names_from_nsec3(
796*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
797*17d15b25SDag-Erling Smørgrav {
798*17d15b25SDag-Erling Smørgrav 	ldns_rbnode_t* current_node;
7997b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name* current_name;
800*17d15b25SDag-Erling Smørgrav 
801*17d15b25SDag-Erling Smørgrav 	assert(zone != NULL);
802*17d15b25SDag-Erling Smørgrav 	assert(nsec3rr != NULL);
803*17d15b25SDag-Erling Smørgrav 
804*17d15b25SDag-Erling Smørgrav 	if (zone->hashed_names) {
805*17d15b25SDag-Erling Smørgrav 		ldns_traverse_postorder(zone->hashed_names,
806*17d15b25SDag-Erling Smørgrav 				ldns_hashed_names_node_free, NULL);
807*17d15b25SDag-Erling Smørgrav 		LDNS_FREE(zone->hashed_names);
808*17d15b25SDag-Erling Smørgrav 	}
809*17d15b25SDag-Erling Smørgrav 	zone->_nsec3params = nsec3rr;
810*17d15b25SDag-Erling Smørgrav 
811*17d15b25SDag-Erling Smørgrav 	/* So this is a NSEC3 zone.
812*17d15b25SDag-Erling Smørgrav 	* Calculate hashes for all names already in the zone
813*17d15b25SDag-Erling Smørgrav 	*/
814*17d15b25SDag-Erling Smørgrav 	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
815*17d15b25SDag-Erling Smørgrav 	if (zone->hashed_names == NULL) {
816*17d15b25SDag-Erling Smørgrav 		return;
817*17d15b25SDag-Erling Smørgrav 	}
818*17d15b25SDag-Erling Smørgrav 	for ( current_node  = ldns_rbtree_first(zone->names)
819*17d15b25SDag-Erling Smørgrav 	    ; current_node != LDNS_RBTREE_NULL
820*17d15b25SDag-Erling Smørgrav 	    ; current_node  = ldns_rbtree_next(current_node)
821*17d15b25SDag-Erling Smørgrav 	    ) {
822*17d15b25SDag-Erling Smørgrav 		current_name = (ldns_dnssec_name *) current_node->data;
823*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
824*17d15b25SDag-Erling Smørgrav 
825*17d15b25SDag-Erling Smørgrav 	}
826*17d15b25SDag-Erling Smørgrav }
827*17d15b25SDag-Erling Smørgrav 
828*17d15b25SDag-Erling Smørgrav static void
829*17d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
830*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_name* name, ldns_rr* nsec3rr)
831*17d15b25SDag-Erling Smørgrav {
832*17d15b25SDag-Erling Smørgrav 	ldns_rbnode_t* new_node;
833*17d15b25SDag-Erling Smørgrav 
834*17d15b25SDag-Erling Smørgrav 	assert(name != NULL);
835*17d15b25SDag-Erling Smørgrav 	if (! zone->_nsec3params) {
836*17d15b25SDag-Erling Smørgrav 		if (! nsec3rr) {
837*17d15b25SDag-Erling Smørgrav 			return;
838*17d15b25SDag-Erling Smørgrav 		}
839*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
840*17d15b25SDag-Erling Smørgrav 
841*17d15b25SDag-Erling Smørgrav 	} else if (! nsec3rr) {
842*17d15b25SDag-Erling Smørgrav 		nsec3rr = zone->_nsec3params;
843*17d15b25SDag-Erling Smørgrav 	}
844*17d15b25SDag-Erling Smørgrav 	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
845*17d15b25SDag-Erling Smørgrav 
846*17d15b25SDag-Erling Smørgrav 	/* Also store in zone->hashed_names */
847*17d15b25SDag-Erling Smørgrav 	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
848*17d15b25SDag-Erling Smørgrav 
849*17d15b25SDag-Erling Smørgrav 		new_node->key  = name->hashed_name;
850*17d15b25SDag-Erling Smørgrav 		new_node->data = name;
851*17d15b25SDag-Erling Smørgrav 
852*17d15b25SDag-Erling Smørgrav 		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
853*17d15b25SDag-Erling Smørgrav 
854*17d15b25SDag-Erling Smørgrav 				LDNS_FREE(new_node);
855*17d15b25SDag-Erling Smørgrav 		}
856*17d15b25SDag-Erling Smørgrav 	}
857*17d15b25SDag-Erling Smørgrav }
858*17d15b25SDag-Erling Smørgrav 
859*17d15b25SDag-Erling Smørgrav 
860*17d15b25SDag-Erling Smørgrav static ldns_rbnode_t *
861*17d15b25SDag-Erling Smørgrav ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
8627b5038d7SDag-Erling Smørgrav 	ldns_rdf *hashed_name;
8637b5038d7SDag-Erling Smørgrav 
8647b5038d7SDag-Erling Smørgrav 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
865*17d15b25SDag-Erling Smørgrav 	if (hashed_name == NULL) {
866*17d15b25SDag-Erling Smørgrav 		return NULL;
867*17d15b25SDag-Erling Smørgrav 	}
868*17d15b25SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
8697b5038d7SDag-Erling Smørgrav 
870*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
8717b5038d7SDag-Erling Smørgrav 	}
872*17d15b25SDag-Erling Smørgrav 	if (zone->hashed_names == NULL) {
8737b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(hashed_name);
8747b5038d7SDag-Erling Smørgrav 		return NULL;
8757b5038d7SDag-Erling Smørgrav 	}
876*17d15b25SDag-Erling Smørgrav 	return  ldns_rbtree_search(zone->hashed_names, hashed_name);
877*17d15b25SDag-Erling Smørgrav }
8787b5038d7SDag-Erling Smørgrav 
8797b5038d7SDag-Erling Smørgrav ldns_status
8807b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
8817b5038d7SDag-Erling Smørgrav {
8827b5038d7SDag-Erling Smørgrav 	ldns_status result = LDNS_STATUS_OK;
8837b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *cur_name;
8847b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *cur_node;
8857b5038d7SDag-Erling Smørgrav 	ldns_rr_type type_covered = 0;
8867b5038d7SDag-Erling Smørgrav 
8877b5038d7SDag-Erling Smørgrav 	if (!zone || !rr) {
8887b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
8897b5038d7SDag-Erling Smørgrav 	}
8907b5038d7SDag-Erling Smørgrav 
8917b5038d7SDag-Erling Smørgrav 	if (!zone->names) {
8927b5038d7SDag-Erling Smørgrav 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
8937b5038d7SDag-Erling Smørgrav                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
8947b5038d7SDag-Erling Smørgrav 	}
8957b5038d7SDag-Erling Smørgrav 
8967b5038d7SDag-Erling Smørgrav 	/* we need the original of the hashed name if this is
8977b5038d7SDag-Erling Smørgrav 	   an NSEC3, or an RRSIG that covers an NSEC3 */
8987b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
8997b5038d7SDag-Erling Smørgrav 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
9007b5038d7SDag-Erling Smørgrav 	}
9017b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
9027b5038d7SDag-Erling Smørgrav 	    type_covered == LDNS_RR_TYPE_NSEC3) {
903*17d15b25SDag-Erling Smørgrav 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
9047b5038d7SDag-Erling Smørgrav 		if (!cur_node) {
9057b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
9067b5038d7SDag-Erling Smørgrav 		}
9077b5038d7SDag-Erling Smørgrav 	} else {
9087b5038d7SDag-Erling Smørgrav 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
9097b5038d7SDag-Erling Smørgrav 	}
9107b5038d7SDag-Erling Smørgrav 	if (!cur_node) {
9117b5038d7SDag-Erling Smørgrav 		/* add */
9127b5038d7SDag-Erling Smørgrav 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
9137b5038d7SDag-Erling Smørgrav                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
9147b5038d7SDag-Erling Smørgrav 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
9157b5038d7SDag-Erling Smørgrav                 if(!cur_node) {
9167b5038d7SDag-Erling Smørgrav                         ldns_dnssec_name_free(cur_name);
9177b5038d7SDag-Erling Smørgrav                         return LDNS_STATUS_MEM_ERR;
9187b5038d7SDag-Erling Smørgrav                 }
9197b5038d7SDag-Erling Smørgrav 		cur_node->key = ldns_rr_owner(rr);
9207b5038d7SDag-Erling Smørgrav 		cur_node->data = cur_name;
9217b5038d7SDag-Erling Smørgrav 		(void)ldns_rbtree_insert(zone->names, cur_node);
922*17d15b25SDag-Erling Smørgrav 		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
9237b5038d7SDag-Erling Smørgrav 	} else {
9247b5038d7SDag-Erling Smørgrav 		cur_name = (ldns_dnssec_name *) cur_node->data;
9257b5038d7SDag-Erling Smørgrav 		result = ldns_dnssec_name_add_rr(cur_name, rr);
9267b5038d7SDag-Erling Smørgrav 	}
9277b5038d7SDag-Erling Smørgrav 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
9287b5038d7SDag-Erling Smørgrav 		zone->soa = cur_name;
9297b5038d7SDag-Erling Smørgrav 	}
9307b5038d7SDag-Erling Smørgrav 	return result;
9317b5038d7SDag-Erling Smørgrav }
9327b5038d7SDag-Erling Smørgrav 
9337b5038d7SDag-Erling Smørgrav void
9347b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
9357b5038d7SDag-Erling Smørgrav 		ldns_rbtree_t *tree,
9367b5038d7SDag-Erling Smørgrav 		bool print_soa)
9377b5038d7SDag-Erling Smørgrav {
9387b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *node;
9397b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *name;
9407b5038d7SDag-Erling Smørgrav 
9417b5038d7SDag-Erling Smørgrav 	node = ldns_rbtree_first(tree);
9427b5038d7SDag-Erling Smørgrav 	while (node != LDNS_RBTREE_NULL) {
9437b5038d7SDag-Erling Smørgrav 		name = (ldns_dnssec_name *) node->data;
9447b5038d7SDag-Erling Smørgrav 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
9457b5038d7SDag-Erling Smørgrav 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
9467b5038d7SDag-Erling Smørgrav 			fprintf(out, ";\n");
9477b5038d7SDag-Erling Smørgrav 		node = ldns_rbtree_next(node);
9487b5038d7SDag-Erling Smørgrav 	}
9497b5038d7SDag-Erling Smørgrav }
9507b5038d7SDag-Erling Smørgrav 
9517b5038d7SDag-Erling Smørgrav void
9527b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
9537b5038d7SDag-Erling Smørgrav {
9547b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
9557b5038d7SDag-Erling Smørgrav 		       tree, print_soa);
9567b5038d7SDag-Erling Smørgrav }
9577b5038d7SDag-Erling Smørgrav 
9587b5038d7SDag-Erling Smørgrav void
9597b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
9607b5038d7SDag-Erling Smørgrav 	       ldns_dnssec_zone *zone)
9617b5038d7SDag-Erling Smørgrav {
9627b5038d7SDag-Erling Smørgrav 	if (zone) {
9637b5038d7SDag-Erling Smørgrav 		if (zone->soa) {
9647b5038d7SDag-Erling Smørgrav 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
9657b5038d7SDag-Erling Smørgrav 				fprintf(out, ";; Zone: ");
9667b5038d7SDag-Erling Smørgrav 				ldns_rdf_print(out, ldns_dnssec_name_name(
9677b5038d7SDag-Erling Smørgrav 							zone->soa));
9687b5038d7SDag-Erling Smørgrav 				fprintf(out, "\n;\n");
9697b5038d7SDag-Erling Smørgrav 			}
9707b5038d7SDag-Erling Smørgrav 			ldns_dnssec_rrsets_print_fmt(out, fmt,
9717b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_find_rrset(
9727b5038d7SDag-Erling Smørgrav 						zone->soa,
9737b5038d7SDag-Erling Smørgrav 						LDNS_RR_TYPE_SOA),
9747b5038d7SDag-Erling Smørgrav 					false);
9757b5038d7SDag-Erling Smørgrav 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
9767b5038d7SDag-Erling Smørgrav 				fprintf(out, ";\n");
9777b5038d7SDag-Erling Smørgrav 		}
9787b5038d7SDag-Erling Smørgrav 
9797b5038d7SDag-Erling Smørgrav 		if (zone->names) {
9807b5038d7SDag-Erling Smørgrav 			ldns_dnssec_zone_names_print_fmt(out, fmt,
9817b5038d7SDag-Erling Smørgrav 					zone->names, false);
9827b5038d7SDag-Erling Smørgrav 		}
9837b5038d7SDag-Erling Smørgrav 	}
9847b5038d7SDag-Erling Smørgrav }
9857b5038d7SDag-Erling Smørgrav 
9867b5038d7SDag-Erling Smørgrav void
9877b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
9887b5038d7SDag-Erling Smørgrav {
9897b5038d7SDag-Erling Smørgrav 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
9907b5038d7SDag-Erling Smørgrav }
9917b5038d7SDag-Erling Smørgrav 
9927b5038d7SDag-Erling Smørgrav ldns_status
9937b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
9947b5038d7SDag-Erling Smørgrav {
9957b5038d7SDag-Erling Smørgrav 	ldns_dnssec_name *new_name;
9967b5038d7SDag-Erling Smørgrav 	ldns_rdf *cur_name;
9977b5038d7SDag-Erling Smørgrav 	ldns_rdf *next_name;
9987b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t *cur_node, *next_node, *new_node;
9997b5038d7SDag-Erling Smørgrav 
10007b5038d7SDag-Erling Smørgrav 	/* for the detection */
10017b5038d7SDag-Erling Smørgrav 	uint16_t i, cur_label_count, next_label_count;
10027b5038d7SDag-Erling Smørgrav 	uint16_t soa_label_count = 0;
10037b5038d7SDag-Erling Smørgrav 	ldns_rdf *l1, *l2;
10047b5038d7SDag-Erling Smørgrav 	int lpos;
10057b5038d7SDag-Erling Smørgrav 
10067b5038d7SDag-Erling Smørgrav 	if (!zone) {
10077b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ERR;
10087b5038d7SDag-Erling Smørgrav 	}
10097b5038d7SDag-Erling Smørgrav 	if (zone->soa && zone->soa->name) {
10107b5038d7SDag-Erling Smørgrav 		soa_label_count = ldns_dname_label_count(zone->soa->name);
10117b5038d7SDag-Erling Smørgrav 	}
10127b5038d7SDag-Erling Smørgrav 
10137b5038d7SDag-Erling Smørgrav 	cur_node = ldns_rbtree_first(zone->names);
10147b5038d7SDag-Erling Smørgrav 	while (cur_node != LDNS_RBTREE_NULL) {
10157b5038d7SDag-Erling Smørgrav 		next_node = ldns_rbtree_next(cur_node);
10167b5038d7SDag-Erling Smørgrav 
10177b5038d7SDag-Erling Smørgrav 		/* skip glue */
10187b5038d7SDag-Erling Smørgrav 		while (next_node != LDNS_RBTREE_NULL &&
10197b5038d7SDag-Erling Smørgrav 		       next_node->data &&
10207b5038d7SDag-Erling Smørgrav 		       ((ldns_dnssec_name *)next_node->data)->is_glue
10217b5038d7SDag-Erling Smørgrav 		) {
10227b5038d7SDag-Erling Smørgrav 			next_node = ldns_rbtree_next(next_node);
10237b5038d7SDag-Erling Smørgrav 		}
10247b5038d7SDag-Erling Smørgrav 
10257b5038d7SDag-Erling Smørgrav 		if (next_node == LDNS_RBTREE_NULL) {
10267b5038d7SDag-Erling Smørgrav 			next_node = ldns_rbtree_first(zone->names);
10277b5038d7SDag-Erling Smørgrav 		}
10282787e39aSDag-Erling Smørgrav 		if (! cur_node->data || ! next_node->data) {
10292787e39aSDag-Erling Smørgrav 			return LDNS_STATUS_ERR;
10302787e39aSDag-Erling Smørgrav 		}
10317b5038d7SDag-Erling Smørgrav 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
10327b5038d7SDag-Erling Smørgrav 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
10337b5038d7SDag-Erling Smørgrav 		cur_label_count = ldns_dname_label_count(cur_name);
10347b5038d7SDag-Erling Smørgrav 		next_label_count = ldns_dname_label_count(next_name);
10357b5038d7SDag-Erling Smørgrav 
10367b5038d7SDag-Erling Smørgrav 		/* Since the names are in canonical order, we can
10377b5038d7SDag-Erling Smørgrav 		 * recognize empty non-terminals by their labels;
10387b5038d7SDag-Erling Smørgrav 		 * every label after the first one on the next owner
10397b5038d7SDag-Erling Smørgrav 		 * name is a non-terminal if it either does not exist
10407b5038d7SDag-Erling Smørgrav 		 * in the current name or is different from the same
10417b5038d7SDag-Erling Smørgrav 		 * label in the current name (counting from the end)
10427b5038d7SDag-Erling Smørgrav 		 */
10437b5038d7SDag-Erling Smørgrav 		for (i = 1; i < next_label_count - soa_label_count; i++) {
10447b5038d7SDag-Erling Smørgrav 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
10457b5038d7SDag-Erling Smørgrav 			if (lpos >= 0) {
10467b5038d7SDag-Erling Smørgrav 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
10477b5038d7SDag-Erling Smørgrav 			} else {
10487b5038d7SDag-Erling Smørgrav 				l1 = NULL;
10497b5038d7SDag-Erling Smørgrav 			}
10507b5038d7SDag-Erling Smørgrav 			l2 = ldns_dname_clone_from(next_name, i);
10517b5038d7SDag-Erling Smørgrav 
10527b5038d7SDag-Erling Smørgrav 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
10537b5038d7SDag-Erling Smørgrav 				/* We have an empty nonterminal, add it to the
10547b5038d7SDag-Erling Smørgrav 				 * tree
10557b5038d7SDag-Erling Smørgrav 				 */
10567b5038d7SDag-Erling Smørgrav 				new_name = ldns_dnssec_name_new();
10577b5038d7SDag-Erling Smørgrav 				if (!new_name) {
10587b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10597b5038d7SDag-Erling Smørgrav 				}
10607b5038d7SDag-Erling Smørgrav 				new_name->name = ldns_dname_clone_from(next_name,
10617b5038d7SDag-Erling Smørgrav 				                                       i);
10627b5038d7SDag-Erling Smørgrav 				if (!new_name->name) {
10637b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_free(new_name);
10647b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10657b5038d7SDag-Erling Smørgrav 				}
10667b5038d7SDag-Erling Smørgrav 				new_name->name_alloced = true;
10677b5038d7SDag-Erling Smørgrav 				new_node = LDNS_MALLOC(ldns_rbnode_t);
10687b5038d7SDag-Erling Smørgrav 				if (!new_node) {
10697b5038d7SDag-Erling Smørgrav 					ldns_dnssec_name_free(new_name);
10707b5038d7SDag-Erling Smørgrav 					return LDNS_STATUS_MEM_ERR;
10717b5038d7SDag-Erling Smørgrav 				}
10727b5038d7SDag-Erling Smørgrav 				new_node->key = new_name->name;
10737b5038d7SDag-Erling Smørgrav 				new_node->data = new_name;
10747b5038d7SDag-Erling Smørgrav 				(void)ldns_rbtree_insert(zone->names, new_node);
1075*17d15b25SDag-Erling Smørgrav 				ldns_dnssec_name_make_hashed_name(
1076*17d15b25SDag-Erling Smørgrav 						zone, new_name, NULL);
10777b5038d7SDag-Erling Smørgrav 			}
10787b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(l1);
10797b5038d7SDag-Erling Smørgrav 			ldns_rdf_deep_free(l2);
10807b5038d7SDag-Erling Smørgrav 		}
10817b5038d7SDag-Erling Smørgrav 
10827b5038d7SDag-Erling Smørgrav 		/* we might have inserted a new node after
10837b5038d7SDag-Erling Smørgrav 		 * the current one so we can't just use next()
10847b5038d7SDag-Erling Smørgrav 		 */
10857b5038d7SDag-Erling Smørgrav 		if (next_node != ldns_rbtree_first(zone->names)) {
10867b5038d7SDag-Erling Smørgrav 			cur_node = next_node;
10877b5038d7SDag-Erling Smørgrav 		} else {
10887b5038d7SDag-Erling Smørgrav 			cur_node = LDNS_RBTREE_NULL;
10897b5038d7SDag-Erling Smørgrav 		}
10907b5038d7SDag-Erling Smørgrav 	}
10917b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
10927b5038d7SDag-Erling Smørgrav }
10937b5038d7SDag-Erling Smørgrav 
10947b5038d7SDag-Erling Smørgrav bool
10957b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
10967b5038d7SDag-Erling Smørgrav {
10977b5038d7SDag-Erling Smørgrav 	ldns_rr* nsec3;
10987b5038d7SDag-Erling Smørgrav 	ldns_rbnode_t* node;
10997b5038d7SDag-Erling Smørgrav 
11007b5038d7SDag-Erling Smørgrav 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
11017b5038d7SDag-Erling Smørgrav 		node = ldns_rbtree_first(zone->names);
11027b5038d7SDag-Erling Smørgrav 		while (node != LDNS_RBTREE_NULL) {
11037b5038d7SDag-Erling Smørgrav 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
11047b5038d7SDag-Erling Smørgrav 			if (nsec3 &&ldns_rr_get_type(nsec3)
11057b5038d7SDag-Erling Smørgrav 					== LDNS_RR_TYPE_NSEC3 &&
11067b5038d7SDag-Erling Smørgrav 					ldns_nsec3_optout(nsec3)) {
11077b5038d7SDag-Erling Smørgrav 				return true;
11087b5038d7SDag-Erling Smørgrav 			}
11097b5038d7SDag-Erling Smørgrav 			node = ldns_rbtree_next(node);
11107b5038d7SDag-Erling Smørgrav 		}
11117b5038d7SDag-Erling Smørgrav 	}
11127b5038d7SDag-Erling Smørgrav 	return false;
11137b5038d7SDag-Erling Smørgrav }
1114