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>
8*5afab0e5SDag-Erling Smørgrav #include <ldns/internal.h>
97b5038d7SDag-Erling Smørgrav
107b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *
ldns_dnssec_rrs_new(void)117b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_new(void)
127b5038d7SDag-Erling Smørgrav {
137b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *new_rrs;
147b5038d7SDag-Erling Smørgrav new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
157b5038d7SDag-Erling Smørgrav if(!new_rrs) return NULL;
167b5038d7SDag-Erling Smørgrav new_rrs->rr = NULL;
177b5038d7SDag-Erling Smørgrav new_rrs->next = NULL;
187b5038d7SDag-Erling Smørgrav return new_rrs;
197b5038d7SDag-Erling Smørgrav }
207b5038d7SDag-Erling Smørgrav
217b5038d7SDag-Erling Smørgrav INLINE void
ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs * rrs,int deep)227b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
237b5038d7SDag-Erling Smørgrav {
247b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *next;
257b5038d7SDag-Erling Smørgrav while (rrs) {
267b5038d7SDag-Erling Smørgrav next = rrs->next;
277b5038d7SDag-Erling Smørgrav if (deep) {
287b5038d7SDag-Erling Smørgrav ldns_rr_free(rrs->rr);
297b5038d7SDag-Erling Smørgrav }
307b5038d7SDag-Erling Smørgrav LDNS_FREE(rrs);
317b5038d7SDag-Erling Smørgrav rrs = next;
327b5038d7SDag-Erling Smørgrav }
337b5038d7SDag-Erling Smørgrav }
347b5038d7SDag-Erling Smørgrav
357b5038d7SDag-Erling Smørgrav void
ldns_dnssec_rrs_free(ldns_dnssec_rrs * rrs)367b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
377b5038d7SDag-Erling Smørgrav {
387b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free_internal(rrs, 0);
397b5038d7SDag-Erling Smørgrav }
407b5038d7SDag-Erling Smørgrav
417b5038d7SDag-Erling Smørgrav void
ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs * rrs)427b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
437b5038d7SDag-Erling Smørgrav {
447b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_free_internal(rrs, 1);
457b5038d7SDag-Erling Smørgrav }
467b5038d7SDag-Erling Smørgrav
477b5038d7SDag-Erling Smørgrav ldns_status
ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs * rrs,ldns_rr * rr)487b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
497b5038d7SDag-Erling Smørgrav {
507b5038d7SDag-Erling Smørgrav int cmp;
517b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs *new_rrs;
527b5038d7SDag-Erling Smørgrav if (!rrs || !rr) {
537b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
547b5038d7SDag-Erling Smørgrav }
557b5038d7SDag-Erling Smørgrav
567b5038d7SDag-Erling Smørgrav /* this could be done more efficiently; name and type should already
577b5038d7SDag-Erling Smørgrav be equal */
5817d15b25SDag-Erling Smørgrav cmp = ldns_rr_compare(rrs->rr, rr);
5917d15b25SDag-Erling Smørgrav if (cmp < 0) {
607b5038d7SDag-Erling Smørgrav if (rrs->next) {
617b5038d7SDag-Erling Smørgrav return ldns_dnssec_rrs_add_rr(rrs->next, rr);
627b5038d7SDag-Erling Smørgrav } else {
637b5038d7SDag-Erling Smørgrav new_rrs = ldns_dnssec_rrs_new();
647b5038d7SDag-Erling Smørgrav new_rrs->rr = rr;
657b5038d7SDag-Erling Smørgrav rrs->next = new_rrs;
667b5038d7SDag-Erling Smørgrav }
677b5038d7SDag-Erling Smørgrav } else if (cmp > 0) {
687b5038d7SDag-Erling Smørgrav /* put the current old rr in the new next, put the new
697b5038d7SDag-Erling Smørgrav rr in the current container */
707b5038d7SDag-Erling Smørgrav new_rrs = ldns_dnssec_rrs_new();
717b5038d7SDag-Erling Smørgrav new_rrs->rr = rrs->rr;
727b5038d7SDag-Erling Smørgrav new_rrs->next = rrs->next;
737b5038d7SDag-Erling Smørgrav rrs->rr = rr;
747b5038d7SDag-Erling Smørgrav rrs->next = new_rrs;
757b5038d7SDag-Erling Smørgrav }
7617d15b25SDag-Erling Smørgrav /* Silently ignore equal rr's */
777b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
787b5038d7SDag-Erling Smørgrav }
797b5038d7SDag-Erling Smørgrav
807b5038d7SDag-Erling Smørgrav void
ldns_dnssec_rrs_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrs * rrs)817b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
82986ba33cSDag-Erling Smørgrav const 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
ldns_dnssec_rrs_print(FILE * out,const ldns_dnssec_rrs * rrs)98986ba33cSDag-Erling Smørgrav ldns_dnssec_rrs_print(FILE *out, const 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 *
ldns_dnssec_rrsets_new(void)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
ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets * rrsets,int deep)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
ldns_dnssec_rrsets_free(ldns_dnssec_rrsets * rrsets)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
ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets * rrsets)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
ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets * rrsets)147986ba33cSDag-Erling Smørgrav ldns_dnssec_rrsets_type(const 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
ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets * rrsets,ldns_rr_type type)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 *
ldns_dnssec_rrsets_new_frm_rr(ldns_rr * rr)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
ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets * rrsets,ldns_rr * rr)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
ldns_dnssec_rrsets_print_soa_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrsets * rrsets,bool follow,bool show_soa)2747b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275986ba33cSDag-Erling Smørgrav const 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
ldns_dnssec_rrsets_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrsets * rrsets,bool follow)3037b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
304986ba33cSDag-Erling Smørgrav const 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
ldns_dnssec_rrsets_print(FILE * out,const ldns_dnssec_rrsets * rrsets,bool follow)311986ba33cSDag-Erling Smørgrav ldns_dnssec_rrsets_print(FILE *out, const 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 *
ldns_dnssec_name_new(void)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 /*
327*5afab0e5SDag-Erling Smørgrav * not needed anymore because CALLOC initializes 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 *
ldns_dnssec_name_new_frm_rr(ldns_rr * rr)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
ldns_dnssec_name_free_internal(ldns_dnssec_name * name,int deep)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) {
374*5afab0e5SDag-Erling Smørgrav /* Hashed name is always allocated when signing,
375*5afab0e5SDag-Erling Smørgrav * so always deep free
376*5afab0e5SDag-Erling Smørgrav */
3777b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(name->hashed_name);
3787b5038d7SDag-Erling Smørgrav }
3797b5038d7SDag-Erling Smørgrav LDNS_FREE(name);
3807b5038d7SDag-Erling Smørgrav }
3817b5038d7SDag-Erling Smørgrav }
3827b5038d7SDag-Erling Smørgrav
3837b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_free(ldns_dnssec_name * name)3847b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free(ldns_dnssec_name *name)
3857b5038d7SDag-Erling Smørgrav {
3867b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free_internal(name, 0);
3877b5038d7SDag-Erling Smørgrav }
3887b5038d7SDag-Erling Smørgrav
3897b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_deep_free(ldns_dnssec_name * name)3907b5038d7SDag-Erling Smørgrav ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
3917b5038d7SDag-Erling Smørgrav {
3927b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free_internal(name, 1);
3937b5038d7SDag-Erling Smørgrav }
3947b5038d7SDag-Erling Smørgrav
3957b5038d7SDag-Erling Smørgrav ldns_rdf *
ldns_dnssec_name_name(const ldns_dnssec_name * name)396986ba33cSDag-Erling Smørgrav ldns_dnssec_name_name(const ldns_dnssec_name *name)
3977b5038d7SDag-Erling Smørgrav {
3987b5038d7SDag-Erling Smørgrav if (name) {
3997b5038d7SDag-Erling Smørgrav return name->name;
4007b5038d7SDag-Erling Smørgrav }
4017b5038d7SDag-Erling Smørgrav return NULL;
4027b5038d7SDag-Erling Smørgrav }
4037b5038d7SDag-Erling Smørgrav
4047b5038d7SDag-Erling Smørgrav bool
ldns_dnssec_name_is_glue(const ldns_dnssec_name * name)405986ba33cSDag-Erling Smørgrav ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
4067b5038d7SDag-Erling Smørgrav {
4077b5038d7SDag-Erling Smørgrav if (name) {
4087b5038d7SDag-Erling Smørgrav return name->is_glue;
4097b5038d7SDag-Erling Smørgrav }
4107b5038d7SDag-Erling Smørgrav return false;
4117b5038d7SDag-Erling Smørgrav }
4127b5038d7SDag-Erling Smørgrav
4137b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_set_name(ldns_dnssec_name * rrset,ldns_rdf * dname)4147b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
4157b5038d7SDag-Erling Smørgrav ldns_rdf *dname)
4167b5038d7SDag-Erling Smørgrav {
4177b5038d7SDag-Erling Smørgrav if (rrset && dname) {
4187b5038d7SDag-Erling Smørgrav rrset->name = dname;
4197b5038d7SDag-Erling Smørgrav }
4207b5038d7SDag-Erling Smørgrav }
4217b5038d7SDag-Erling Smørgrav
4227b5038d7SDag-Erling Smørgrav
4237b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_set_nsec(ldns_dnssec_name * rrset,ldns_rr * nsec)4247b5038d7SDag-Erling Smørgrav ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
4257b5038d7SDag-Erling Smørgrav {
4267b5038d7SDag-Erling Smørgrav if (rrset && nsec) {
4277b5038d7SDag-Erling Smørgrav rrset->nsec = nsec;
4287b5038d7SDag-Erling Smørgrav }
4297b5038d7SDag-Erling Smørgrav }
4307b5038d7SDag-Erling Smørgrav
4317b5038d7SDag-Erling Smørgrav int
ldns_dnssec_name_cmp(const void * a,const void * b)4327b5038d7SDag-Erling Smørgrav ldns_dnssec_name_cmp(const void *a, const void *b)
4337b5038d7SDag-Erling Smørgrav {
4347b5038d7SDag-Erling Smørgrav ldns_dnssec_name *na = (ldns_dnssec_name *) a;
4357b5038d7SDag-Erling Smørgrav ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
4367b5038d7SDag-Erling Smørgrav
4377b5038d7SDag-Erling Smørgrav if (na && nb) {
4387b5038d7SDag-Erling Smørgrav return ldns_dname_compare(ldns_dnssec_name_name(na),
4397b5038d7SDag-Erling Smørgrav ldns_dnssec_name_name(nb));
4407b5038d7SDag-Erling Smørgrav } else if (na) {
4417b5038d7SDag-Erling Smørgrav return 1;
4427b5038d7SDag-Erling Smørgrav } else if (nb) {
4437b5038d7SDag-Erling Smørgrav return -1;
4447b5038d7SDag-Erling Smørgrav } else {
4457b5038d7SDag-Erling Smørgrav return 0;
4467b5038d7SDag-Erling Smørgrav }
4477b5038d7SDag-Erling Smørgrav }
4487b5038d7SDag-Erling Smørgrav
4497b5038d7SDag-Erling Smørgrav ldns_status
ldns_dnssec_name_add_rr(ldns_dnssec_name * name,ldns_rr * rr)4507b5038d7SDag-Erling Smørgrav ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
4517b5038d7SDag-Erling Smørgrav ldns_rr *rr)
4527b5038d7SDag-Erling Smørgrav {
4537b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_OK;
4547b5038d7SDag-Erling Smørgrav ldns_rr_type rr_type;
4557b5038d7SDag-Erling Smørgrav ldns_rr_type typecovered = 0;
4567b5038d7SDag-Erling Smørgrav
4577b5038d7SDag-Erling Smørgrav /* special handling for NSEC3 and NSECX covering RRSIGS */
4587b5038d7SDag-Erling Smørgrav
4597b5038d7SDag-Erling Smørgrav if (!name || !rr) {
4607b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
4617b5038d7SDag-Erling Smørgrav }
4627b5038d7SDag-Erling Smørgrav
4637b5038d7SDag-Erling Smørgrav rr_type = ldns_rr_get_type(rr);
4647b5038d7SDag-Erling Smørgrav
4657b5038d7SDag-Erling Smørgrav if (rr_type == LDNS_RR_TYPE_RRSIG) {
4667b5038d7SDag-Erling Smørgrav typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
4677b5038d7SDag-Erling Smørgrav }
4687b5038d7SDag-Erling Smørgrav
4697b5038d7SDag-Erling Smørgrav if (rr_type == LDNS_RR_TYPE_NSEC ||
4707b5038d7SDag-Erling Smørgrav rr_type == LDNS_RR_TYPE_NSEC3) {
4717b5038d7SDag-Erling Smørgrav /* XX check if is already set (and error?) */
4727b5038d7SDag-Erling Smørgrav name->nsec = rr;
4737b5038d7SDag-Erling Smørgrav } else if (typecovered == LDNS_RR_TYPE_NSEC ||
4747b5038d7SDag-Erling Smørgrav typecovered == LDNS_RR_TYPE_NSEC3) {
4757b5038d7SDag-Erling Smørgrav if (name->nsec_signatures) {
4767b5038d7SDag-Erling Smørgrav result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
4777b5038d7SDag-Erling Smørgrav } else {
4787b5038d7SDag-Erling Smørgrav name->nsec_signatures = ldns_dnssec_rrs_new();
4797b5038d7SDag-Erling Smørgrav name->nsec_signatures->rr = rr;
4807b5038d7SDag-Erling Smørgrav }
4817b5038d7SDag-Erling Smørgrav } else {
4827b5038d7SDag-Erling Smørgrav /* it's a 'normal' RR, add it to the right rrset */
4837b5038d7SDag-Erling Smørgrav if (name->rrsets) {
4847b5038d7SDag-Erling Smørgrav result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
4857b5038d7SDag-Erling Smørgrav } else {
4867b5038d7SDag-Erling Smørgrav name->rrsets = ldns_dnssec_rrsets_new();
4877b5038d7SDag-Erling Smørgrav result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
4887b5038d7SDag-Erling Smørgrav }
4897b5038d7SDag-Erling Smørgrav }
4907b5038d7SDag-Erling Smørgrav return result;
4917b5038d7SDag-Erling Smørgrav }
4927b5038d7SDag-Erling Smørgrav
4937b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
ldns_dnssec_name_find_rrset(const ldns_dnssec_name * name,ldns_rr_type type)494986ba33cSDag-Erling Smørgrav ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
4957b5038d7SDag-Erling Smørgrav ldns_rr_type type) {
4967b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *result;
4977b5038d7SDag-Erling Smørgrav
4987b5038d7SDag-Erling Smørgrav result = name->rrsets;
4997b5038d7SDag-Erling Smørgrav while (result) {
5007b5038d7SDag-Erling Smørgrav if (result->type == type) {
5017b5038d7SDag-Erling Smørgrav return result;
5027b5038d7SDag-Erling Smørgrav } else {
5037b5038d7SDag-Erling Smørgrav result = result->next;
5047b5038d7SDag-Erling Smørgrav }
5057b5038d7SDag-Erling Smørgrav }
5067b5038d7SDag-Erling Smørgrav return NULL;
5077b5038d7SDag-Erling Smørgrav }
5087b5038d7SDag-Erling Smørgrav
5097b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets *
ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone * zone,const ldns_rdf * dname,ldns_rr_type type)510986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
511986ba33cSDag-Erling Smørgrav const ldns_rdf *dname,
5127b5038d7SDag-Erling Smørgrav ldns_rr_type type)
5137b5038d7SDag-Erling Smørgrav {
5147b5038d7SDag-Erling Smørgrav ldns_rbnode_t *node;
5157b5038d7SDag-Erling Smørgrav
516986ba33cSDag-Erling Smørgrav if (!zone || !dname || !zone->names) {
5177b5038d7SDag-Erling Smørgrav return NULL;
5187b5038d7SDag-Erling Smørgrav }
5197b5038d7SDag-Erling Smørgrav
5207b5038d7SDag-Erling Smørgrav node = ldns_rbtree_search(zone->names, dname);
5217b5038d7SDag-Erling Smørgrav if (node) {
5227b5038d7SDag-Erling Smørgrav return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
5237b5038d7SDag-Erling Smørgrav type);
5247b5038d7SDag-Erling Smørgrav } else {
5257b5038d7SDag-Erling Smørgrav return NULL;
5267b5038d7SDag-Erling Smørgrav }
5277b5038d7SDag-Erling Smørgrav }
5287b5038d7SDag-Erling Smørgrav
5297b5038d7SDag-Erling Smørgrav static void
ldns_dnssec_name_print_soa_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name,bool show_soa)5307b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
531986ba33cSDag-Erling Smørgrav const ldns_dnssec_name *name,
5327b5038d7SDag-Erling Smørgrav bool show_soa)
5337b5038d7SDag-Erling Smørgrav {
5347b5038d7SDag-Erling Smørgrav if (name) {
5357b5038d7SDag-Erling Smørgrav if(name->rrsets) {
5367b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
5377b5038d7SDag-Erling Smørgrav name->rrsets, true, show_soa);
5387b5038d7SDag-Erling Smørgrav } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5397b5038d7SDag-Erling Smørgrav fprintf(out, ";; Empty nonterminal: ");
5407b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, name->name);
5417b5038d7SDag-Erling Smørgrav fprintf(out, "\n");
5427b5038d7SDag-Erling Smørgrav }
5437b5038d7SDag-Erling Smørgrav if(name->nsec) {
5447b5038d7SDag-Erling Smørgrav ldns_rr_print_fmt(out, fmt, name->nsec);
5457b5038d7SDag-Erling Smørgrav }
5467b5038d7SDag-Erling Smørgrav if (name->nsec_signatures) {
5477b5038d7SDag-Erling Smørgrav ldns_dnssec_rrs_print_fmt(out, fmt,
5487b5038d7SDag-Erling Smørgrav name->nsec_signatures);
5497b5038d7SDag-Erling Smørgrav }
5507b5038d7SDag-Erling Smørgrav } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
5517b5038d7SDag-Erling Smørgrav fprintf(out, "; <void>\n");
5527b5038d7SDag-Erling Smørgrav }
5537b5038d7SDag-Erling Smørgrav }
5547b5038d7SDag-Erling Smørgrav
5557b5038d7SDag-Erling Smørgrav
5567b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name)5577b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
558986ba33cSDag-Erling Smørgrav const ldns_dnssec_name *name)
5597b5038d7SDag-Erling Smørgrav {
5607b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
5617b5038d7SDag-Erling Smørgrav }
5627b5038d7SDag-Erling Smørgrav
5637b5038d7SDag-Erling Smørgrav void
ldns_dnssec_name_print(FILE * out,const ldns_dnssec_name * name)564986ba33cSDag-Erling Smørgrav ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
5657b5038d7SDag-Erling Smørgrav {
5667b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
5677b5038d7SDag-Erling Smørgrav }
5687b5038d7SDag-Erling Smørgrav
5697b5038d7SDag-Erling Smørgrav
5707b5038d7SDag-Erling Smørgrav ldns_dnssec_zone *
ldns_dnssec_zone_new(void)5717b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_new(void)
5727b5038d7SDag-Erling Smørgrav {
5737b5038d7SDag-Erling Smørgrav ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
5747b5038d7SDag-Erling Smørgrav if(!zone) return NULL;
5757b5038d7SDag-Erling Smørgrav zone->soa = NULL;
5767b5038d7SDag-Erling Smørgrav zone->names = NULL;
57717d15b25SDag-Erling Smørgrav zone->hashed_names = NULL;
57817d15b25SDag-Erling Smørgrav zone->_nsec3params = NULL;
5797b5038d7SDag-Erling Smørgrav
5807b5038d7SDag-Erling Smørgrav return zone;
5817b5038d7SDag-Erling Smørgrav }
5827b5038d7SDag-Erling Smørgrav
5837b5038d7SDag-Erling Smørgrav static bool
rr_is_rrsig_covering(ldns_rr * rr,ldns_rr_type t)5847b5038d7SDag-Erling Smørgrav rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
5857b5038d7SDag-Erling Smørgrav {
5867b5038d7SDag-Erling Smørgrav return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
5877b5038d7SDag-Erling Smørgrav && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
5887b5038d7SDag-Erling Smørgrav }
5897b5038d7SDag-Erling Smørgrav
5907b5038d7SDag-Erling Smørgrav /* When the zone is first read into an list and then inserted into an
5917b5038d7SDag-Erling Smørgrav * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
5927b5038d7SDag-Erling Smørgrav * to each other. Because ldns-verify-zone (the only program that uses this
593*5afab0e5SDag-Erling Smørgrav * function) uses the rbtree mostly for sequential walking, this results
5947b5038d7SDag-Erling Smørgrav * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
5957b5038d7SDag-Erling Smørgrav */
5967b5038d7SDag-Erling Smørgrav #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
5977b5038d7SDag-Erling Smørgrav
598986ba33cSDag-Erling Smørgrav static ldns_status
599986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_add_empty_nonterminals_nsec3(
600986ba33cSDag-Erling Smørgrav ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
601986ba33cSDag-Erling Smørgrav
602986ba33cSDag-Erling Smørgrav static void
ldns_todo_nsec3_ents_node_free(ldns_rbnode_t * node,void * arg)603986ba33cSDag-Erling Smørgrav ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
604986ba33cSDag-Erling Smørgrav (void) arg;
605986ba33cSDag-Erling Smørgrav ldns_rdf_deep_free((ldns_rdf *)node->key);
606986ba33cSDag-Erling Smørgrav LDNS_FREE(node);
607986ba33cSDag-Erling Smørgrav }
608986ba33cSDag-Erling Smørgrav
6097b5038d7SDag-Erling Smørgrav ldns_status
ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone ** z,FILE * fp,const ldns_rdf * origin,uint32_t default_ttl,ldns_rr_class ATTR_UNUSED (c),int * line_nr)610986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
611*5afab0e5SDag-Erling Smørgrav uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
6127b5038d7SDag-Erling Smørgrav {
6137b5038d7SDag-Erling Smørgrav ldns_rr* cur_rr;
6147b5038d7SDag-Erling Smørgrav size_t i;
6157b5038d7SDag-Erling Smørgrav
6167b5038d7SDag-Erling Smørgrav ldns_rdf *my_origin = NULL;
6177b5038d7SDag-Erling Smørgrav ldns_rdf *my_prev = NULL;
6187b5038d7SDag-Erling Smørgrav
6197b5038d7SDag-Erling Smørgrav ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
620986ba33cSDag-Erling Smørgrav /* NSEC3s may occur before the names they refer to. We must remember
621986ba33cSDag-Erling Smørgrav them and add them to the name later on, after the name is read.
622986ba33cSDag-Erling Smørgrav We track not yet matching NSEC3s*n the todo_nsec3s list */
623986ba33cSDag-Erling Smørgrav ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
6247b5038d7SDag-Erling Smørgrav /* when reading NSEC3s, there is a chance that we encounter nsecs
6257b5038d7SDag-Erling Smørgrav for empty nonterminals, whose nonterminals we cannot derive yet
626986ba33cSDag-Erling Smørgrav because the needed information is to be read later.
627986ba33cSDag-Erling Smørgrav
628986ba33cSDag-Erling Smørgrav nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
629986ba33cSDag-Erling Smørgrav hold the NSEC3s that still didn't have a matching name in the
630986ba33cSDag-Erling Smørgrav zone tree, even after all names were read. They can only match
631*5afab0e5SDag-Erling Smørgrav after the zone is equipped with all the empty non terminals. */
632986ba33cSDag-Erling Smørgrav ldns_rbtree_t todo_nsec3_ents;
633986ba33cSDag-Erling Smørgrav ldns_rbnode_t *new_node;
6347b5038d7SDag-Erling Smørgrav ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
6357b5038d7SDag-Erling Smørgrav
636986ba33cSDag-Erling Smørgrav ldns_status status;
6377b5038d7SDag-Erling Smørgrav
6387b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6397b5038d7SDag-Erling Smørgrav ldns_zone* zone = NULL;
6407b5038d7SDag-Erling Smørgrav #else
641*5afab0e5SDag-Erling Smørgrav ldns_rr *prev_rr = NULL;
642*5afab0e5SDag-Erling Smørgrav uint32_t my_ttl = default_ttl;
643*5afab0e5SDag-Erling Smørgrav /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
644*5afab0e5SDag-Erling Smørgrav * to the last explicitly stated values.'
645*5afab0e5SDag-Erling Smørgrav */
646*5afab0e5SDag-Erling Smørgrav bool ttl_from_TTL = false;
647*5afab0e5SDag-Erling Smørgrav bool explicit_ttl = false;
6487b5038d7SDag-Erling Smørgrav #endif
6497b5038d7SDag-Erling Smørgrav
650986ba33cSDag-Erling Smørgrav ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
6517b5038d7SDag-Erling Smørgrav
652986ba33cSDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
653*5afab0e5SDag-Erling Smørgrav status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
654986ba33cSDag-Erling Smørgrav if (status != LDNS_STATUS_OK)
655986ba33cSDag-Erling Smørgrav goto error;
656986ba33cSDag-Erling Smørgrav #endif
657986ba33cSDag-Erling Smørgrav if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
658986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
659986ba33cSDag-Erling Smørgrav goto error;
660986ba33cSDag-Erling Smørgrav }
6617b5038d7SDag-Erling Smørgrav if (origin) {
662986ba33cSDag-Erling Smørgrav if (!(my_origin = ldns_rdf_clone(origin))) {
663986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
664986ba33cSDag-Erling Smørgrav goto error;
665986ba33cSDag-Erling Smørgrav }
666986ba33cSDag-Erling Smørgrav if (!(my_prev = ldns_rdf_clone(origin))) {
667986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
668986ba33cSDag-Erling Smørgrav goto error;
669986ba33cSDag-Erling Smørgrav }
6707b5038d7SDag-Erling Smørgrav }
6717b5038d7SDag-Erling Smørgrav
6727b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
673986ba33cSDag-Erling Smørgrav if (ldns_zone_soa(zone)) {
674986ba33cSDag-Erling Smørgrav status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
675986ba33cSDag-Erling Smørgrav if (status != LDNS_STATUS_OK)
676986ba33cSDag-Erling Smørgrav goto error;
677986ba33cSDag-Erling Smørgrav }
6787b5038d7SDag-Erling Smørgrav for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
6797b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
6807b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_OK;
6817b5038d7SDag-Erling Smørgrav #else
6827b5038d7SDag-Erling Smørgrav while (!feof(fp)) {
683*5afab0e5SDag-Erling Smørgrav /* If ttl came from $TTL line, then it should be the default.
684*5afab0e5SDag-Erling Smørgrav * (RFC 2308 Section 4)
685*5afab0e5SDag-Erling Smørgrav * Otherwise it "defaults to the last explicitly stated value"
686*5afab0e5SDag-Erling Smørgrav * (RFC 1035 Section 5.1)
687*5afab0e5SDag-Erling Smørgrav */
688*5afab0e5SDag-Erling Smørgrav if (ttl_from_TTL)
689*5afab0e5SDag-Erling Smørgrav my_ttl = default_ttl;
6907b5038d7SDag-Erling Smørgrav status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
691*5afab0e5SDag-Erling Smørgrav &my_prev, line_nr, &explicit_ttl);
6927b5038d7SDag-Erling Smørgrav #endif
6937b5038d7SDag-Erling Smørgrav switch (status) {
6947b5038d7SDag-Erling Smørgrav case LDNS_STATUS_OK:
695*5afab0e5SDag-Erling Smørgrav #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
696*5afab0e5SDag-Erling Smørgrav if (explicit_ttl) {
697*5afab0e5SDag-Erling Smørgrav if (!ttl_from_TTL) {
698*5afab0e5SDag-Erling Smørgrav /* No $TTL, so ttl "defaults to the
699*5afab0e5SDag-Erling Smørgrav * last explicitly stated value"
700*5afab0e5SDag-Erling Smørgrav * (RFC 1035 Section 5.1)
701*5afab0e5SDag-Erling Smørgrav */
702*5afab0e5SDag-Erling Smørgrav my_ttl = ldns_rr_ttl(cur_rr);
703*5afab0e5SDag-Erling Smørgrav }
704*5afab0e5SDag-Erling Smørgrav /* When ttl is implicit, try to adhere to the rules as
705*5afab0e5SDag-Erling Smørgrav * much as possible. (also for compatibility with bind)
706*5afab0e5SDag-Erling Smørgrav * This was changed when fixing an issue with ZONEMD
707*5afab0e5SDag-Erling Smørgrav * which hashes the TTL too.
708*5afab0e5SDag-Erling Smørgrav */
709*5afab0e5SDag-Erling Smørgrav } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
710*5afab0e5SDag-Erling Smørgrav || ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
711*5afab0e5SDag-Erling Smørgrav if (ldns_rr_rd_count(cur_rr) >= 4
712*5afab0e5SDag-Erling Smørgrav && ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32)
7137b5038d7SDag-Erling Smørgrav
714*5afab0e5SDag-Erling Smørgrav /* SIG without explicit ttl get ttl
715*5afab0e5SDag-Erling Smørgrav * from the original_ttl field
716*5afab0e5SDag-Erling Smørgrav * (RFC 2535 Section 7.2)
717*5afab0e5SDag-Erling Smørgrav *
718*5afab0e5SDag-Erling Smørgrav * Similarly for RRSIG, but stated less
719*5afab0e5SDag-Erling Smørgrav * specifically in the spec.
720*5afab0e5SDag-Erling Smørgrav * (RFC 4034 Section 3)
721*5afab0e5SDag-Erling Smørgrav */
722*5afab0e5SDag-Erling Smørgrav ldns_rr_set_ttl(cur_rr,
723*5afab0e5SDag-Erling Smørgrav ldns_rdf2native_int32(
724*5afab0e5SDag-Erling Smørgrav ldns_rr_rdf(rr, 3)));
725*5afab0e5SDag-Erling Smørgrav
726*5afab0e5SDag-Erling Smørgrav } else if (prev_rr
727*5afab0e5SDag-Erling Smørgrav && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
728*5afab0e5SDag-Erling Smørgrav && ldns_dname_compare( ldns_rr_owner(prev_rr)
729*5afab0e5SDag-Erling Smørgrav , ldns_rr_owner(cur_rr)) == 0)
730*5afab0e5SDag-Erling Smørgrav
731*5afab0e5SDag-Erling Smørgrav /* "TTLs of all RRs in an RRSet must be the same"
732*5afab0e5SDag-Erling Smørgrav * (RFC 2881 Section 5.2)
733*5afab0e5SDag-Erling Smørgrav */
734*5afab0e5SDag-Erling Smørgrav ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
735*5afab0e5SDag-Erling Smørgrav
736*5afab0e5SDag-Erling Smørgrav prev_rr = cur_rr;
737*5afab0e5SDag-Erling Smørgrav #endif
7387b5038d7SDag-Erling Smørgrav status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
7397b5038d7SDag-Erling Smørgrav if (status ==
7407b5038d7SDag-Erling Smørgrav LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
7417b5038d7SDag-Erling Smørgrav
7427b5038d7SDag-Erling Smørgrav if (rr_is_rrsig_covering(cur_rr,
7437b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_NSEC3)){
7447b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(todo_nsec3_rrsigs,
7457b5038d7SDag-Erling Smørgrav cur_rr);
7467b5038d7SDag-Erling Smørgrav } else {
7477b5038d7SDag-Erling Smørgrav ldns_rr_list_push_rr(todo_nsec3s,
7487b5038d7SDag-Erling Smørgrav cur_rr);
7497b5038d7SDag-Erling Smørgrav }
75017d15b25SDag-Erling Smørgrav status = LDNS_STATUS_OK;
75117d15b25SDag-Erling Smørgrav
7527b5038d7SDag-Erling Smørgrav } else if (status != LDNS_STATUS_OK)
7537b5038d7SDag-Erling Smørgrav goto error;
7547b5038d7SDag-Erling Smørgrav
7557b5038d7SDag-Erling Smørgrav break;
7567b5038d7SDag-Erling Smørgrav
757*5afab0e5SDag-Erling Smørgrav case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
758*5afab0e5SDag-Erling Smørgrav #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
759*5afab0e5SDag-Erling Smørgrav default_ttl = my_ttl;
760*5afab0e5SDag-Erling Smørgrav ttl_from_TTL = true;
761*5afab0e5SDag-Erling Smørgrav #endif
762*5afab0e5SDag-Erling Smørgrav status = LDNS_STATUS_OK;
763*5afab0e5SDag-Erling Smørgrav break;
764*5afab0e5SDag-Erling Smørgrav
7657b5038d7SDag-Erling Smørgrav
7667b5038d7SDag-Erling Smørgrav case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
7677b5038d7SDag-Erling Smørgrav case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
7682787e39aSDag-Erling Smørgrav status = LDNS_STATUS_OK;
7697b5038d7SDag-Erling Smørgrav break;
7707b5038d7SDag-Erling Smørgrav
7717b5038d7SDag-Erling Smørgrav case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
7727b5038d7SDag-Erling Smørgrav status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
7737b5038d7SDag-Erling Smørgrav break;
7747b5038d7SDag-Erling Smørgrav
7757b5038d7SDag-Erling Smørgrav default:
7767b5038d7SDag-Erling Smørgrav goto error;
7777b5038d7SDag-Erling Smørgrav }
7787b5038d7SDag-Erling Smørgrav }
7797b5038d7SDag-Erling Smørgrav
7802787e39aSDag-Erling Smørgrav for (i = 0; status == LDNS_STATUS_OK &&
7812787e39aSDag-Erling Smørgrav i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
7827b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
7837b5038d7SDag-Erling Smørgrav status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
784986ba33cSDag-Erling Smørgrav if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
785986ba33cSDag-Erling Smørgrav if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
786986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
787986ba33cSDag-Erling Smørgrav break;
788986ba33cSDag-Erling Smørgrav }
789986ba33cSDag-Erling Smørgrav new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
790986ba33cSDag-Erling Smørgrav new_node->data = cur_rr;
791986ba33cSDag-Erling Smørgrav if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
792986ba33cSDag-Erling Smørgrav LDNS_FREE(new_node);
793986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_MEM_ERR;
794986ba33cSDag-Erling Smørgrav break;
795986ba33cSDag-Erling Smørgrav }
796986ba33cSDag-Erling Smørgrav status = LDNS_STATUS_OK;
7977b5038d7SDag-Erling Smørgrav }
7987b5038d7SDag-Erling Smørgrav }
799986ba33cSDag-Erling Smørgrav if (todo_nsec3_ents.count > 0)
800986ba33cSDag-Erling Smørgrav (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
801986ba33cSDag-Erling Smørgrav newzone, &todo_nsec3_ents);
8022787e39aSDag-Erling Smørgrav for (i = 0; status == LDNS_STATUS_OK &&
803986ba33cSDag-Erling Smørgrav i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
8047b5038d7SDag-Erling Smørgrav cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
8057b5038d7SDag-Erling Smørgrav status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
8067b5038d7SDag-Erling Smørgrav }
8077b5038d7SDag-Erling Smørgrav if (z) {
8087b5038d7SDag-Erling Smørgrav *z = newzone;
8092787e39aSDag-Erling Smørgrav newzone = NULL;
8107b5038d7SDag-Erling Smørgrav } else {
8117b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_free(newzone);
812*5afab0e5SDag-Erling Smørgrav newzone = NULL;
8137b5038d7SDag-Erling Smørgrav }
8147b5038d7SDag-Erling Smørgrav
8157b5038d7SDag-Erling Smørgrav error:
8167b5038d7SDag-Erling Smørgrav #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
8177b5038d7SDag-Erling Smørgrav if (zone) {
8187b5038d7SDag-Erling Smørgrav ldns_zone_free(zone);
8197b5038d7SDag-Erling Smørgrav }
8207b5038d7SDag-Erling Smørgrav #endif
8212787e39aSDag-Erling Smørgrav ldns_rr_list_free(todo_nsec3_rrsigs);
822986ba33cSDag-Erling Smørgrav ldns_traverse_postorder(&todo_nsec3_ents,
823986ba33cSDag-Erling Smørgrav ldns_todo_nsec3_ents_node_free, NULL);
8242787e39aSDag-Erling Smørgrav ldns_rr_list_free(todo_nsec3s);
8252787e39aSDag-Erling Smørgrav
8267b5038d7SDag-Erling Smørgrav if (my_origin) {
8277b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(my_origin);
8287b5038d7SDag-Erling Smørgrav }
8297b5038d7SDag-Erling Smørgrav if (my_prev) {
8307b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(my_prev);
8317b5038d7SDag-Erling Smørgrav }
8327b5038d7SDag-Erling Smørgrav if (newzone) {
8337b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_free(newzone);
8347b5038d7SDag-Erling Smørgrav }
8357b5038d7SDag-Erling Smørgrav return status;
8367b5038d7SDag-Erling Smørgrav }
8377b5038d7SDag-Erling Smørgrav
8387b5038d7SDag-Erling Smørgrav ldns_status
839986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
8407b5038d7SDag-Erling Smørgrav uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
8417b5038d7SDag-Erling Smørgrav {
8427b5038d7SDag-Erling Smørgrav return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
8437b5038d7SDag-Erling Smørgrav }
8447b5038d7SDag-Erling Smørgrav
8457b5038d7SDag-Erling Smørgrav static void
8467b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
8477b5038d7SDag-Erling Smørgrav (void) arg;
8487b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
8497b5038d7SDag-Erling Smørgrav LDNS_FREE(node);
8507b5038d7SDag-Erling Smørgrav }
8517b5038d7SDag-Erling Smørgrav
8527b5038d7SDag-Erling Smørgrav static void
8537b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
8547b5038d7SDag-Erling Smørgrav (void) arg;
8557b5038d7SDag-Erling Smørgrav ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
8567b5038d7SDag-Erling Smørgrav LDNS_FREE(node);
8577b5038d7SDag-Erling Smørgrav }
8587b5038d7SDag-Erling Smørgrav
859*5afab0e5SDag-Erling Smørgrav static void
860*5afab0e5SDag-Erling Smørgrav ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
861*5afab0e5SDag-Erling Smørgrav (void) arg;
862*5afab0e5SDag-Erling Smørgrav LDNS_FREE(node);
863*5afab0e5SDag-Erling Smørgrav }
864*5afab0e5SDag-Erling Smørgrav
8657b5038d7SDag-Erling Smørgrav void
8667b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
8677b5038d7SDag-Erling Smørgrav {
8687b5038d7SDag-Erling Smørgrav if (zone) {
869*5afab0e5SDag-Erling Smørgrav if (zone->hashed_names) {
870*5afab0e5SDag-Erling Smørgrav ldns_traverse_postorder(zone->hashed_names,
871*5afab0e5SDag-Erling Smørgrav ldns_hashed_names_node_free, NULL);
872*5afab0e5SDag-Erling Smørgrav LDNS_FREE(zone->hashed_names);
873*5afab0e5SDag-Erling Smørgrav }
8747b5038d7SDag-Erling Smørgrav if (zone->names) {
8757b5038d7SDag-Erling Smørgrav /* destroy all name structures within the tree */
8767b5038d7SDag-Erling Smørgrav ldns_traverse_postorder(zone->names,
8777b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_free,
8787b5038d7SDag-Erling Smørgrav NULL);
8797b5038d7SDag-Erling Smørgrav LDNS_FREE(zone->names);
8807b5038d7SDag-Erling Smørgrav }
8817b5038d7SDag-Erling Smørgrav LDNS_FREE(zone);
8827b5038d7SDag-Erling Smørgrav }
8837b5038d7SDag-Erling Smørgrav }
8847b5038d7SDag-Erling Smørgrav
8857b5038d7SDag-Erling Smørgrav void
8867b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
8877b5038d7SDag-Erling Smørgrav {
8887b5038d7SDag-Erling Smørgrav if (zone) {
889*5afab0e5SDag-Erling Smørgrav if (zone->hashed_names) {
890*5afab0e5SDag-Erling Smørgrav ldns_traverse_postorder(zone->hashed_names,
891*5afab0e5SDag-Erling Smørgrav ldns_hashed_names_node_free, NULL);
892*5afab0e5SDag-Erling Smørgrav LDNS_FREE(zone->hashed_names);
893*5afab0e5SDag-Erling Smørgrav }
8947b5038d7SDag-Erling Smørgrav if (zone->names) {
8957b5038d7SDag-Erling Smørgrav /* destroy all name structures within the tree */
8967b5038d7SDag-Erling Smørgrav ldns_traverse_postorder(zone->names,
8977b5038d7SDag-Erling Smørgrav ldns_dnssec_name_node_deep_free,
8987b5038d7SDag-Erling Smørgrav NULL);
8997b5038d7SDag-Erling Smørgrav LDNS_FREE(zone->names);
9007b5038d7SDag-Erling Smørgrav }
9017b5038d7SDag-Erling Smørgrav LDNS_FREE(zone);
9027b5038d7SDag-Erling Smørgrav }
9037b5038d7SDag-Erling Smørgrav }
9047b5038d7SDag-Erling Smørgrav
9057b5038d7SDag-Erling Smørgrav /* use for dname comparison in tree */
906d6e492feSDag-Erling Smørgrav int
9077b5038d7SDag-Erling Smørgrav ldns_dname_compare_v(const void *a, const void *b) {
9087b5038d7SDag-Erling Smørgrav return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
9097b5038d7SDag-Erling Smørgrav }
9107b5038d7SDag-Erling Smørgrav
91117d15b25SDag-Erling Smørgrav static void
91217d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
91317d15b25SDag-Erling Smørgrav ldns_dnssec_name* name, ldns_rr* nsec3rr);
91417d15b25SDag-Erling Smørgrav
91517d15b25SDag-Erling Smørgrav static void
91617d15b25SDag-Erling Smørgrav ldns_dnssec_zone_hashed_names_from_nsec3(
91717d15b25SDag-Erling Smørgrav ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
91817d15b25SDag-Erling Smørgrav {
91917d15b25SDag-Erling Smørgrav ldns_rbnode_t* current_node;
9207b5038d7SDag-Erling Smørgrav ldns_dnssec_name* current_name;
92117d15b25SDag-Erling Smørgrav
92217d15b25SDag-Erling Smørgrav assert(zone != NULL);
92317d15b25SDag-Erling Smørgrav assert(nsec3rr != NULL);
92417d15b25SDag-Erling Smørgrav
92517d15b25SDag-Erling Smørgrav if (zone->hashed_names) {
92617d15b25SDag-Erling Smørgrav ldns_traverse_postorder(zone->hashed_names,
92717d15b25SDag-Erling Smørgrav ldns_hashed_names_node_free, NULL);
92817d15b25SDag-Erling Smørgrav LDNS_FREE(zone->hashed_names);
92917d15b25SDag-Erling Smørgrav }
93017d15b25SDag-Erling Smørgrav zone->_nsec3params = nsec3rr;
93117d15b25SDag-Erling Smørgrav
93217d15b25SDag-Erling Smørgrav /* So this is a NSEC3 zone.
93317d15b25SDag-Erling Smørgrav * Calculate hashes for all names already in the zone
93417d15b25SDag-Erling Smørgrav */
93517d15b25SDag-Erling Smørgrav zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
93617d15b25SDag-Erling Smørgrav if (zone->hashed_names == NULL) {
93717d15b25SDag-Erling Smørgrav return;
93817d15b25SDag-Erling Smørgrav }
93917d15b25SDag-Erling Smørgrav for ( current_node = ldns_rbtree_first(zone->names)
94017d15b25SDag-Erling Smørgrav ; current_node != LDNS_RBTREE_NULL
94117d15b25SDag-Erling Smørgrav ; current_node = ldns_rbtree_next(current_node)
94217d15b25SDag-Erling Smørgrav ) {
94317d15b25SDag-Erling Smørgrav current_name = (ldns_dnssec_name *) current_node->data;
94417d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
94517d15b25SDag-Erling Smørgrav
94617d15b25SDag-Erling Smørgrav }
94717d15b25SDag-Erling Smørgrav }
94817d15b25SDag-Erling Smørgrav
94917d15b25SDag-Erling Smørgrav static void
95017d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
95117d15b25SDag-Erling Smørgrav ldns_dnssec_name* name, ldns_rr* nsec3rr)
95217d15b25SDag-Erling Smørgrav {
95317d15b25SDag-Erling Smørgrav ldns_rbnode_t* new_node;
95417d15b25SDag-Erling Smørgrav
95517d15b25SDag-Erling Smørgrav assert(name != NULL);
95617d15b25SDag-Erling Smørgrav if (! zone->_nsec3params) {
95717d15b25SDag-Erling Smørgrav if (! nsec3rr) {
95817d15b25SDag-Erling Smørgrav return;
95917d15b25SDag-Erling Smørgrav }
96017d15b25SDag-Erling Smørgrav ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
96117d15b25SDag-Erling Smørgrav
96217d15b25SDag-Erling Smørgrav } else if (! nsec3rr) {
96317d15b25SDag-Erling Smørgrav nsec3rr = zone->_nsec3params;
96417d15b25SDag-Erling Smørgrav }
96517d15b25SDag-Erling Smørgrav name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
96617d15b25SDag-Erling Smørgrav
96717d15b25SDag-Erling Smørgrav /* Also store in zone->hashed_names */
96817d15b25SDag-Erling Smørgrav if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
96917d15b25SDag-Erling Smørgrav
97017d15b25SDag-Erling Smørgrav new_node->key = name->hashed_name;
97117d15b25SDag-Erling Smørgrav new_node->data = name;
97217d15b25SDag-Erling Smørgrav
97317d15b25SDag-Erling Smørgrav if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
97417d15b25SDag-Erling Smørgrav
97517d15b25SDag-Erling Smørgrav LDNS_FREE(new_node);
97617d15b25SDag-Erling Smørgrav }
97717d15b25SDag-Erling Smørgrav }
97817d15b25SDag-Erling Smørgrav }
97917d15b25SDag-Erling Smørgrav
98017d15b25SDag-Erling Smørgrav
98117d15b25SDag-Erling Smørgrav static ldns_rbnode_t *
98217d15b25SDag-Erling Smørgrav ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
9837b5038d7SDag-Erling Smørgrav ldns_rdf *hashed_name;
984*5afab0e5SDag-Erling Smørgrav ldns_rbnode_t *to_return;
9857b5038d7SDag-Erling Smørgrav
98617d15b25SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
9877b5038d7SDag-Erling Smørgrav
98817d15b25SDag-Erling Smørgrav ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
9897b5038d7SDag-Erling Smørgrav }
99017d15b25SDag-Erling Smørgrav if (zone->hashed_names == NULL) {
9917b5038d7SDag-Erling Smørgrav return NULL;
9927b5038d7SDag-Erling Smørgrav }
993*5afab0e5SDag-Erling Smørgrav hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
994*5afab0e5SDag-Erling Smørgrav if (hashed_name == NULL) {
995*5afab0e5SDag-Erling Smørgrav return NULL;
996*5afab0e5SDag-Erling Smørgrav }
997*5afab0e5SDag-Erling Smørgrav to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
998*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(hashed_name);
999*5afab0e5SDag-Erling Smørgrav return to_return;
100017d15b25SDag-Erling Smørgrav }
10017b5038d7SDag-Erling Smørgrav
10027b5038d7SDag-Erling Smørgrav ldns_status
10037b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
10047b5038d7SDag-Erling Smørgrav {
10057b5038d7SDag-Erling Smørgrav ldns_status result = LDNS_STATUS_OK;
10067b5038d7SDag-Erling Smørgrav ldns_dnssec_name *cur_name;
10077b5038d7SDag-Erling Smørgrav ldns_rbnode_t *cur_node;
10087b5038d7SDag-Erling Smørgrav ldns_rr_type type_covered = 0;
10097b5038d7SDag-Erling Smørgrav
10107b5038d7SDag-Erling Smørgrav if (!zone || !rr) {
10117b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
10127b5038d7SDag-Erling Smørgrav }
10137b5038d7SDag-Erling Smørgrav
10147b5038d7SDag-Erling Smørgrav if (!zone->names) {
10157b5038d7SDag-Erling Smørgrav zone->names = ldns_rbtree_create(ldns_dname_compare_v);
10167b5038d7SDag-Erling Smørgrav if(!zone->names) return LDNS_STATUS_MEM_ERR;
10177b5038d7SDag-Erling Smørgrav }
10187b5038d7SDag-Erling Smørgrav
10197b5038d7SDag-Erling Smørgrav /* we need the original of the hashed name if this is
10207b5038d7SDag-Erling Smørgrav an NSEC3, or an RRSIG that covers an NSEC3 */
10217b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
10227b5038d7SDag-Erling Smørgrav type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
10237b5038d7SDag-Erling Smørgrav }
10247b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
10257b5038d7SDag-Erling Smørgrav type_covered == LDNS_RR_TYPE_NSEC3) {
102617d15b25SDag-Erling Smørgrav cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
10277b5038d7SDag-Erling Smørgrav if (!cur_node) {
10287b5038d7SDag-Erling Smørgrav return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
10297b5038d7SDag-Erling Smørgrav }
10307b5038d7SDag-Erling Smørgrav } else {
10317b5038d7SDag-Erling Smørgrav cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
10327b5038d7SDag-Erling Smørgrav }
10337b5038d7SDag-Erling Smørgrav if (!cur_node) {
10347b5038d7SDag-Erling Smørgrav /* add */
10357b5038d7SDag-Erling Smørgrav cur_name = ldns_dnssec_name_new_frm_rr(rr);
10367b5038d7SDag-Erling Smørgrav if(!cur_name) return LDNS_STATUS_MEM_ERR;
10377b5038d7SDag-Erling Smørgrav cur_node = LDNS_MALLOC(ldns_rbnode_t);
10387b5038d7SDag-Erling Smørgrav if(!cur_node) {
10397b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free(cur_name);
10407b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
10417b5038d7SDag-Erling Smørgrav }
10427b5038d7SDag-Erling Smørgrav cur_node->key = ldns_rr_owner(rr);
10437b5038d7SDag-Erling Smørgrav cur_node->data = cur_name;
10447b5038d7SDag-Erling Smørgrav (void)ldns_rbtree_insert(zone->names, cur_node);
104517d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
10467b5038d7SDag-Erling Smørgrav } else {
10477b5038d7SDag-Erling Smørgrav cur_name = (ldns_dnssec_name *) cur_node->data;
10487b5038d7SDag-Erling Smørgrav result = ldns_dnssec_name_add_rr(cur_name, rr);
10497b5038d7SDag-Erling Smørgrav }
10507b5038d7SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
10517b5038d7SDag-Erling Smørgrav zone->soa = cur_name;
10527b5038d7SDag-Erling Smørgrav }
10537b5038d7SDag-Erling Smørgrav return result;
10547b5038d7SDag-Erling Smørgrav }
10557b5038d7SDag-Erling Smørgrav
10567b5038d7SDag-Erling Smørgrav void
10577b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
1058986ba33cSDag-Erling Smørgrav const ldns_rbtree_t *tree,
10597b5038d7SDag-Erling Smørgrav bool print_soa)
10607b5038d7SDag-Erling Smørgrav {
10617b5038d7SDag-Erling Smørgrav ldns_rbnode_t *node;
10627b5038d7SDag-Erling Smørgrav ldns_dnssec_name *name;
10637b5038d7SDag-Erling Smørgrav
10647b5038d7SDag-Erling Smørgrav node = ldns_rbtree_first(tree);
10657b5038d7SDag-Erling Smørgrav while (node != LDNS_RBTREE_NULL) {
10667b5038d7SDag-Erling Smørgrav name = (ldns_dnssec_name *) node->data;
10677b5038d7SDag-Erling Smørgrav ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
10687b5038d7SDag-Erling Smørgrav if ((fmt->flags & LDNS_COMMENT_LAYOUT))
10697b5038d7SDag-Erling Smørgrav fprintf(out, ";\n");
10707b5038d7SDag-Erling Smørgrav node = ldns_rbtree_next(node);
10717b5038d7SDag-Erling Smørgrav }
10727b5038d7SDag-Erling Smørgrav }
10737b5038d7SDag-Erling Smørgrav
10747b5038d7SDag-Erling Smørgrav void
1075986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
10767b5038d7SDag-Erling Smørgrav {
10777b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
10787b5038d7SDag-Erling Smørgrav tree, print_soa);
10797b5038d7SDag-Erling Smørgrav }
10807b5038d7SDag-Erling Smørgrav
10817b5038d7SDag-Erling Smørgrav void
10827b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1083986ba33cSDag-Erling Smørgrav const ldns_dnssec_zone *zone)
10847b5038d7SDag-Erling Smørgrav {
10857b5038d7SDag-Erling Smørgrav if (zone) {
10867b5038d7SDag-Erling Smørgrav if (zone->soa) {
10877b5038d7SDag-Erling Smørgrav if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
10887b5038d7SDag-Erling Smørgrav fprintf(out, ";; Zone: ");
10897b5038d7SDag-Erling Smørgrav ldns_rdf_print(out, ldns_dnssec_name_name(
10907b5038d7SDag-Erling Smørgrav zone->soa));
10917b5038d7SDag-Erling Smørgrav fprintf(out, "\n;\n");
10927b5038d7SDag-Erling Smørgrav }
10937b5038d7SDag-Erling Smørgrav ldns_dnssec_rrsets_print_fmt(out, fmt,
10947b5038d7SDag-Erling Smørgrav ldns_dnssec_name_find_rrset(
10957b5038d7SDag-Erling Smørgrav zone->soa,
10967b5038d7SDag-Erling Smørgrav LDNS_RR_TYPE_SOA),
10977b5038d7SDag-Erling Smørgrav false);
10987b5038d7SDag-Erling Smørgrav if ((fmt->flags & LDNS_COMMENT_LAYOUT))
10997b5038d7SDag-Erling Smørgrav fprintf(out, ";\n");
11007b5038d7SDag-Erling Smørgrav }
11017b5038d7SDag-Erling Smørgrav
11027b5038d7SDag-Erling Smørgrav if (zone->names) {
11037b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_names_print_fmt(out, fmt,
11047b5038d7SDag-Erling Smørgrav zone->names, false);
11057b5038d7SDag-Erling Smørgrav }
11067b5038d7SDag-Erling Smørgrav }
11077b5038d7SDag-Erling Smørgrav }
11087b5038d7SDag-Erling Smørgrav
11097b5038d7SDag-Erling Smørgrav void
1110986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
11117b5038d7SDag-Erling Smørgrav {
11127b5038d7SDag-Erling Smørgrav ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
11137b5038d7SDag-Erling Smørgrav }
11147b5038d7SDag-Erling Smørgrav
1115986ba33cSDag-Erling Smørgrav static ldns_status
1116986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1117986ba33cSDag-Erling Smørgrav ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
11187b5038d7SDag-Erling Smørgrav {
11197b5038d7SDag-Erling Smørgrav ldns_dnssec_name *new_name;
11207b5038d7SDag-Erling Smørgrav ldns_rdf *cur_name;
11217b5038d7SDag-Erling Smørgrav ldns_rdf *next_name;
11227b5038d7SDag-Erling Smørgrav ldns_rbnode_t *cur_node, *next_node, *new_node;
11237b5038d7SDag-Erling Smørgrav
11247b5038d7SDag-Erling Smørgrav /* for the detection */
11257b5038d7SDag-Erling Smørgrav uint16_t i, cur_label_count, next_label_count;
11267b5038d7SDag-Erling Smørgrav uint16_t soa_label_count = 0;
11277b5038d7SDag-Erling Smørgrav ldns_rdf *l1, *l2;
11287b5038d7SDag-Erling Smørgrav int lpos;
11297b5038d7SDag-Erling Smørgrav
11307b5038d7SDag-Erling Smørgrav if (!zone) {
11317b5038d7SDag-Erling Smørgrav return LDNS_STATUS_ERR;
11327b5038d7SDag-Erling Smørgrav }
11337b5038d7SDag-Erling Smørgrav if (zone->soa && zone->soa->name) {
11347b5038d7SDag-Erling Smørgrav soa_label_count = ldns_dname_label_count(zone->soa->name);
11357b5038d7SDag-Erling Smørgrav }
11367b5038d7SDag-Erling Smørgrav
11377b5038d7SDag-Erling Smørgrav cur_node = ldns_rbtree_first(zone->names);
11387b5038d7SDag-Erling Smørgrav while (cur_node != LDNS_RBTREE_NULL) {
11397b5038d7SDag-Erling Smørgrav next_node = ldns_rbtree_next(cur_node);
11407b5038d7SDag-Erling Smørgrav
11417b5038d7SDag-Erling Smørgrav /* skip glue */
11427b5038d7SDag-Erling Smørgrav while (next_node != LDNS_RBTREE_NULL &&
11437b5038d7SDag-Erling Smørgrav next_node->data &&
11447b5038d7SDag-Erling Smørgrav ((ldns_dnssec_name *)next_node->data)->is_glue
11457b5038d7SDag-Erling Smørgrav ) {
11467b5038d7SDag-Erling Smørgrav next_node = ldns_rbtree_next(next_node);
11477b5038d7SDag-Erling Smørgrav }
11487b5038d7SDag-Erling Smørgrav
11497b5038d7SDag-Erling Smørgrav if (next_node == LDNS_RBTREE_NULL) {
11507b5038d7SDag-Erling Smørgrav next_node = ldns_rbtree_first(zone->names);
11517b5038d7SDag-Erling Smørgrav }
11522787e39aSDag-Erling Smørgrav if (! cur_node->data || ! next_node->data) {
11532787e39aSDag-Erling Smørgrav return LDNS_STATUS_ERR;
11542787e39aSDag-Erling Smørgrav }
11557b5038d7SDag-Erling Smørgrav cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
11567b5038d7SDag-Erling Smørgrav next_name = ((ldns_dnssec_name *)next_node->data)->name;
11577b5038d7SDag-Erling Smørgrav cur_label_count = ldns_dname_label_count(cur_name);
11587b5038d7SDag-Erling Smørgrav next_label_count = ldns_dname_label_count(next_name);
11597b5038d7SDag-Erling Smørgrav
11607b5038d7SDag-Erling Smørgrav /* Since the names are in canonical order, we can
11617b5038d7SDag-Erling Smørgrav * recognize empty non-terminals by their labels;
11627b5038d7SDag-Erling Smørgrav * every label after the first one on the next owner
11637b5038d7SDag-Erling Smørgrav * name is a non-terminal if it either does not exist
11647b5038d7SDag-Erling Smørgrav * in the current name or is different from the same
11657b5038d7SDag-Erling Smørgrav * label in the current name (counting from the end)
11667b5038d7SDag-Erling Smørgrav */
11677b5038d7SDag-Erling Smørgrav for (i = 1; i < next_label_count - soa_label_count; i++) {
11687b5038d7SDag-Erling Smørgrav lpos = (int)cur_label_count - (int)next_label_count + (int)i;
11697b5038d7SDag-Erling Smørgrav if (lpos >= 0) {
11707b5038d7SDag-Erling Smørgrav l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
11717b5038d7SDag-Erling Smørgrav } else {
11727b5038d7SDag-Erling Smørgrav l1 = NULL;
11737b5038d7SDag-Erling Smørgrav }
11747b5038d7SDag-Erling Smørgrav l2 = ldns_dname_clone_from(next_name, i);
11757b5038d7SDag-Erling Smørgrav
11767b5038d7SDag-Erling Smørgrav if (!l1 || ldns_dname_compare(l1, l2) != 0) {
11777b5038d7SDag-Erling Smørgrav /* We have an empty nonterminal, add it to the
11787b5038d7SDag-Erling Smørgrav * tree
11797b5038d7SDag-Erling Smørgrav */
1180986ba33cSDag-Erling Smørgrav ldns_rbnode_t *node = NULL;
1181986ba33cSDag-Erling Smørgrav ldns_rdf *ent_name;
1182986ba33cSDag-Erling Smørgrav
1183986ba33cSDag-Erling Smørgrav if (!(ent_name = ldns_dname_clone_from(
1184*5afab0e5SDag-Erling Smørgrav next_name, i))) {
1185*5afab0e5SDag-Erling Smørgrav
1186*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l1);
1187*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l2);
1188986ba33cSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1189*5afab0e5SDag-Erling Smørgrav }
1190986ba33cSDag-Erling Smørgrav
1191986ba33cSDag-Erling Smørgrav if (nsec3s && zone->_nsec3params) {
1192986ba33cSDag-Erling Smørgrav ldns_rdf *ent_hashed_name;
1193986ba33cSDag-Erling Smørgrav
1194986ba33cSDag-Erling Smørgrav if (!(ent_hashed_name =
1195986ba33cSDag-Erling Smørgrav ldns_nsec3_hash_name_frm_nsec3(
1196986ba33cSDag-Erling Smørgrav zone->_nsec3params,
1197*5afab0e5SDag-Erling Smørgrav ent_name))) {
1198*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l1);
1199*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l2);
1200*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(ent_name);
1201986ba33cSDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1202*5afab0e5SDag-Erling Smørgrav }
1203986ba33cSDag-Erling Smørgrav node = ldns_rbtree_search(nsec3s,
1204986ba33cSDag-Erling Smørgrav ent_hashed_name);
1205*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(ent_hashed_name);
1206986ba33cSDag-Erling Smørgrav if (!node) {
1207986ba33cSDag-Erling Smørgrav ldns_rdf_deep_free(l1);
1208986ba33cSDag-Erling Smørgrav ldns_rdf_deep_free(l2);
1209*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(ent_name);
1210986ba33cSDag-Erling Smørgrav continue;
1211986ba33cSDag-Erling Smørgrav }
1212986ba33cSDag-Erling Smørgrav }
12137b5038d7SDag-Erling Smørgrav new_name = ldns_dnssec_name_new();
12147b5038d7SDag-Erling Smørgrav if (!new_name) {
1215*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l1);
1216*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l2);
1217*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(ent_name);
12187b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
12197b5038d7SDag-Erling Smørgrav }
1220986ba33cSDag-Erling Smørgrav new_name->name = ent_name;
12217b5038d7SDag-Erling Smørgrav new_name->name_alloced = true;
12227b5038d7SDag-Erling Smørgrav new_node = LDNS_MALLOC(ldns_rbnode_t);
12237b5038d7SDag-Erling Smørgrav if (!new_node) {
1224*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l1);
1225*5afab0e5SDag-Erling Smørgrav ldns_rdf_deep_free(l2);
12267b5038d7SDag-Erling Smørgrav ldns_dnssec_name_free(new_name);
12277b5038d7SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
12287b5038d7SDag-Erling Smørgrav }
12297b5038d7SDag-Erling Smørgrav new_node->key = new_name->name;
12307b5038d7SDag-Erling Smørgrav new_node->data = new_name;
12317b5038d7SDag-Erling Smørgrav (void)ldns_rbtree_insert(zone->names, new_node);
123217d15b25SDag-Erling Smørgrav ldns_dnssec_name_make_hashed_name(
123317d15b25SDag-Erling Smørgrav zone, new_name, NULL);
1234986ba33cSDag-Erling Smørgrav if (node)
1235986ba33cSDag-Erling Smørgrav (void) ldns_dnssec_zone_add_rr(zone,
1236986ba33cSDag-Erling Smørgrav (ldns_rr *)node->data);
12377b5038d7SDag-Erling Smørgrav }
12387b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(l1);
12397b5038d7SDag-Erling Smørgrav ldns_rdf_deep_free(l2);
12407b5038d7SDag-Erling Smørgrav }
12417b5038d7SDag-Erling Smørgrav
12427b5038d7SDag-Erling Smørgrav /* we might have inserted a new node after
12437b5038d7SDag-Erling Smørgrav * the current one so we can't just use next()
12447b5038d7SDag-Erling Smørgrav */
12457b5038d7SDag-Erling Smørgrav if (next_node != ldns_rbtree_first(zone->names)) {
12467b5038d7SDag-Erling Smørgrav cur_node = next_node;
12477b5038d7SDag-Erling Smørgrav } else {
12487b5038d7SDag-Erling Smørgrav cur_node = LDNS_RBTREE_NULL;
12497b5038d7SDag-Erling Smørgrav }
12507b5038d7SDag-Erling Smørgrav }
12517b5038d7SDag-Erling Smørgrav return LDNS_STATUS_OK;
12527b5038d7SDag-Erling Smørgrav }
12537b5038d7SDag-Erling Smørgrav
1254986ba33cSDag-Erling Smørgrav ldns_status
1255986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1256986ba33cSDag-Erling Smørgrav {
1257986ba33cSDag-Erling Smørgrav return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1258986ba33cSDag-Erling Smørgrav }
1259986ba33cSDag-Erling Smørgrav
12607b5038d7SDag-Erling Smørgrav bool
1261986ba33cSDag-Erling Smørgrav ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
12627b5038d7SDag-Erling Smørgrav {
12637b5038d7SDag-Erling Smørgrav ldns_rr* nsec3;
12647b5038d7SDag-Erling Smørgrav ldns_rbnode_t* node;
12657b5038d7SDag-Erling Smørgrav
12667b5038d7SDag-Erling Smørgrav if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
12677b5038d7SDag-Erling Smørgrav node = ldns_rbtree_first(zone->names);
12687b5038d7SDag-Erling Smørgrav while (node != LDNS_RBTREE_NULL) {
12697b5038d7SDag-Erling Smørgrav nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
12707b5038d7SDag-Erling Smørgrav if (nsec3 &&ldns_rr_get_type(nsec3)
12717b5038d7SDag-Erling Smørgrav == LDNS_RR_TYPE_NSEC3 &&
12727b5038d7SDag-Erling Smørgrav ldns_nsec3_optout(nsec3)) {
12737b5038d7SDag-Erling Smørgrav return true;
12747b5038d7SDag-Erling Smørgrav }
12757b5038d7SDag-Erling Smørgrav node = ldns_rbtree_next(node);
12767b5038d7SDag-Erling Smørgrav }
12777b5038d7SDag-Erling Smørgrav }
12787b5038d7SDag-Erling Smørgrav return false;
12797b5038d7SDag-Erling Smørgrav }
1280*5afab0e5SDag-Erling Smørgrav
1281*5afab0e5SDag-Erling Smørgrav /*
1282*5afab0e5SDag-Erling Smørgrav * Stuff for calculating and verifying zone digests
1283*5afab0e5SDag-Erling Smørgrav */
1284*5afab0e5SDag-Erling Smørgrav typedef enum dnssec_zone_rr_iter_state {
1285*5afab0e5SDag-Erling Smørgrav DNSSEC_ZONE_RR_ITER_LT_RRSIG
1286*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1287*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_REST
1288*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
1289*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
1290*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_NSEC3
1291*5afab0e5SDag-Erling Smørgrav , DNSSEC_ZONE_RR_ITER_FINI
1292*5afab0e5SDag-Erling Smørgrav } dnssec_zone_rr_iter_state;
1293*5afab0e5SDag-Erling Smørgrav
1294*5afab0e5SDag-Erling Smørgrav typedef struct dnssec_zone_rr_iter {
1295*5afab0e5SDag-Erling Smørgrav ldns_dnssec_zone *zone;
1296*5afab0e5SDag-Erling Smørgrav ldns_rbnode_t *node;
1297*5afab0e5SDag-Erling Smørgrav ldns_dnssec_name *name;
1298*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets *rrsets;
1299*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrs *rrs;
1300*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets *rrsets4rrsigs;
1301*5afab0e5SDag-Erling Smørgrav ldns_rbnode_t *nsec3_node;
1302*5afab0e5SDag-Erling Smørgrav ldns_dnssec_name *nsec3_name;
1303*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_state state;
1304*5afab0e5SDag-Erling Smørgrav ldns_rdf *apex_name;
1305*5afab0e5SDag-Erling Smørgrav uint8_t apex_labs;
1306*5afab0e5SDag-Erling Smørgrav } dnssec_zone_rr_iter;
1307*5afab0e5SDag-Erling Smørgrav
1308*5afab0e5SDag-Erling Smørgrav INLINE void
1309*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1310*5afab0e5SDag-Erling Smørgrav {
1311*5afab0e5SDag-Erling Smørgrav /* Make sure the i->name is "in zone" (i.e. below the apex) */
1312*5afab0e5SDag-Erling Smørgrav if (i->apex_name) {
1313*5afab0e5SDag-Erling Smørgrav ldns_rdf *name = (ldns_rdf *)i->node->key;
1314*5afab0e5SDag-Erling Smørgrav
1315*5afab0e5SDag-Erling Smørgrav while (i->name && name != i->apex_name /* not apex */
1316*5afab0e5SDag-Erling Smørgrav
1317*5afab0e5SDag-Erling Smørgrav && ( ldns_dname_label_count(name) != i->apex_labs
1318*5afab0e5SDag-Erling Smørgrav || ldns_dname_compare(name, i->apex_name)) /* not apex */
1319*5afab0e5SDag-Erling Smørgrav
1320*5afab0e5SDag-Erling Smørgrav && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1321*5afab0e5SDag-Erling Smørgrav
1322*5afab0e5SDag-Erling Smørgrav /* next name */
1323*5afab0e5SDag-Erling Smørgrav i->node = ldns_rbtree_next(i->node);
1324*5afab0e5SDag-Erling Smørgrav if (i->node == LDNS_RBTREE_NULL)
1325*5afab0e5SDag-Erling Smørgrav i->name = NULL;
1326*5afab0e5SDag-Erling Smørgrav else {
1327*5afab0e5SDag-Erling Smørgrav i->name = (ldns_dnssec_name *)i->node->data;
1328*5afab0e5SDag-Erling Smørgrav name = (ldns_rdf *)i->node->key;
1329*5afab0e5SDag-Erling Smørgrav }
1330*5afab0e5SDag-Erling Smørgrav }
1331*5afab0e5SDag-Erling Smørgrav }
1332*5afab0e5SDag-Erling Smørgrav /* determine state */
1333*5afab0e5SDag-Erling Smørgrav if (!i->name) {
1334*5afab0e5SDag-Erling Smørgrav if (!i->nsec3_name)
1335*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_FINI;
1336*5afab0e5SDag-Erling Smørgrav else {
1337*5afab0e5SDag-Erling Smørgrav i->rrs = i->nsec3_name->nsec_signatures;
1338*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1339*5afab0e5SDag-Erling Smørgrav }
1340*5afab0e5SDag-Erling Smørgrav } else if (!i->nsec3_name) {
1341*5afab0e5SDag-Erling Smørgrav i->rrsets = i->name->rrsets;
1342*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1343*5afab0e5SDag-Erling Smørgrav
1344*5afab0e5SDag-Erling Smørgrav } else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec)
1345*5afab0e5SDag-Erling Smørgrav , (ldns_rdf *)i->node->key) < 0) {
1346*5afab0e5SDag-Erling Smørgrav i->rrs = i->nsec3_name->nsec_signatures;
1347*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1348*5afab0e5SDag-Erling Smørgrav } else {
1349*5afab0e5SDag-Erling Smørgrav i->rrsets = i->name->rrsets;
1350*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1351*5afab0e5SDag-Erling Smørgrav }
1352*5afab0e5SDag-Erling Smørgrav }
1353*5afab0e5SDag-Erling Smørgrav
1354*5afab0e5SDag-Erling Smørgrav /**
1355*5afab0e5SDag-Erling Smørgrav * Iterate over the RR's in the ldns_dnssec_zone in canonical order.
1356*5afab0e5SDag-Erling Smørgrav * There are three possible paths through the RR's in a ldns_dnssec_name.
1357*5afab0e5SDag-Erling Smørgrav *
1358*5afab0e5SDag-Erling Smørgrav * 1. There is no NSEC:
1359*5afab0e5SDag-Erling Smørgrav *
1360*5afab0e5SDag-Erling Smørgrav * 1.1. All the RRs in the name->rrsets with type < RRSIG,
1361*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1362*5afab0e5SDag-Erling Smørgrav *
1363*5afab0e5SDag-Erling Smørgrav * 1.2. Then all the RRSIGs from name->rrsets (likely none)
1364*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1365*5afab0e5SDag-Erling Smørgrav *
1366*5afab0e5SDag-Erling Smørgrav * 1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1367*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_REST
1368*5afab0e5SDag-Erling Smørgrav *
1369*5afab0e5SDag-Erling Smørgrav *
1370*5afab0e5SDag-Erling Smørgrav * 2. There is a NSEC of type NSEC with this name:
1371*5afab0e5SDag-Erling Smørgrav *
1372*5afab0e5SDag-Erling Smørgrav * 2.1. All the RRs in the name->rrsets with type < RRSIG,
1373*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1374*5afab0e5SDag-Erling Smørgrav *
1375*5afab0e5SDag-Erling Smørgrav * 2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1376*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1377*5afab0e5SDag-Erling Smørgrav *
1378*5afab0e5SDag-Erling Smørgrav * 2.3. Then the signatures of the NSEC RR, followed by
1379*5afab0e5SDag-Erling Smørgrav * the signatures of the remaining name->rrsets (type > NSEC),
1380*5afab0e5SDag-Erling Smørgrav * followed by the NSEC rr.
1381*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1382*5afab0e5SDag-Erling Smørgrav *
1383*5afab0e5SDag-Erling Smørgrav * 2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1384*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_REST
1385*5afab0e5SDag-Erling Smørgrav *
1386*5afab0e5SDag-Erling Smørgrav *
1387*5afab0e5SDag-Erling Smørgrav * 3. There is a NSEC of type NSEC3 for this name:
1388*5afab0e5SDag-Erling Smørgrav *
1389*5afab0e5SDag-Erling Smørgrav * 3.1. If the NSEC3 name is before the name for other RRsets in the zone,
1390*5afab0e5SDag-Erling Smørgrav * Then all signatures of the NSEC3 RR, followed by the NSEC3
1391*5afab0e5SDag-Erling Smørgrav * state: DNSSEC_ZONE_RR_ITER_NSEC3
1392*5afab0e5SDag-Erling Smørgrav *
1393*5afab0e5SDag-Erling Smørgrav * otherwise follow path for "no NSEC" for the name for other RRsets
1394*5afab0e5SDag-Erling Smørgrav */
1395*5afab0e5SDag-Erling Smørgrav static ldns_rr *
1396*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1397*5afab0e5SDag-Erling Smørgrav {
1398*5afab0e5SDag-Erling Smørgrav ldns_rr *nsec3;
1399*5afab0e5SDag-Erling Smørgrav
1400*5afab0e5SDag-Erling Smørgrav for (;;) {
1401*5afab0e5SDag-Erling Smørgrav if (i->rrs) {
1402*5afab0e5SDag-Erling Smørgrav ldns_rr *rr = i->rrs->rr;
1403*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrs->next;
1404*5afab0e5SDag-Erling Smørgrav return rr;
1405*5afab0e5SDag-Erling Smørgrav }
1406*5afab0e5SDag-Erling Smørgrav switch (i->state) {
1407*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1408*5afab0e5SDag-Erling Smørgrav if (i->rrsets
1409*5afab0e5SDag-Erling Smørgrav && i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1410*5afab0e5SDag-Erling Smørgrav
1411*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrsets->rrs;
1412*5afab0e5SDag-Erling Smørgrav i->rrsets = i->rrsets->next;
1413*5afab0e5SDag-Erling Smørgrav break;
1414*5afab0e5SDag-Erling Smørgrav }
1415*5afab0e5SDag-Erling Smørgrav i->rrsets4rrsigs = i->name->rrsets;
1416*5afab0e5SDag-Erling Smørgrav if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1417*5afab0e5SDag-Erling Smørgrav == LDNS_RR_TYPE_NSEC) {
1418*5afab0e5SDag-Erling Smørgrav
1419*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1420*5afab0e5SDag-Erling Smørgrav break;
1421*5afab0e5SDag-Erling Smørgrav }
1422*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1423*5afab0e5SDag-Erling Smørgrav /* fallthrough */
1424*5afab0e5SDag-Erling Smørgrav
1425*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC:
1426*5afab0e5SDag-Erling Smørgrav if (i->rrsets4rrsigs) {
1427*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrsets4rrsigs->signatures;
1428*5afab0e5SDag-Erling Smørgrav i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1429*5afab0e5SDag-Erling Smørgrav break;
1430*5afab0e5SDag-Erling Smørgrav }
1431*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_REST;
1432*5afab0e5SDag-Erling Smørgrav /* fallthrough */
1433*5afab0e5SDag-Erling Smørgrav
1434*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_REST:
1435*5afab0e5SDag-Erling Smørgrav if (i->rrsets) {
1436*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrsets->rrs;
1437*5afab0e5SDag-Erling Smørgrav i->rrsets = i->rrsets->next;
1438*5afab0e5SDag-Erling Smørgrav break;
1439*5afab0e5SDag-Erling Smørgrav }
1440*5afab0e5SDag-Erling Smørgrav /* next name */
1441*5afab0e5SDag-Erling Smørgrav i->node = ldns_rbtree_next(i->node);
1442*5afab0e5SDag-Erling Smørgrav i->name = i->node == LDNS_RBTREE_NULL ? NULL
1443*5afab0e5SDag-Erling Smørgrav : (ldns_dnssec_name *)i->node->data;
1444*5afab0e5SDag-Erling Smørgrav
1445*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_set_state_for_next_name(i);
1446*5afab0e5SDag-Erling Smørgrav break;
1447*5afab0e5SDag-Erling Smørgrav
1448*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1449*5afab0e5SDag-Erling Smørgrav if (i->rrsets4rrsigs
1450*5afab0e5SDag-Erling Smørgrav && i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1451*5afab0e5SDag-Erling Smørgrav
1452*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrsets4rrsigs->signatures;
1453*5afab0e5SDag-Erling Smørgrav i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1454*5afab0e5SDag-Erling Smørgrav break;
1455*5afab0e5SDag-Erling Smørgrav }
1456*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1457*5afab0e5SDag-Erling Smørgrav i->rrs = i->name->nsec_signatures;
1458*5afab0e5SDag-Erling Smørgrav break;
1459*5afab0e5SDag-Erling Smørgrav
1460*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST:
1461*5afab0e5SDag-Erling Smørgrav if (i->rrsets4rrsigs) {
1462*5afab0e5SDag-Erling Smørgrav i->rrs = i->rrsets4rrsigs->signatures;
1463*5afab0e5SDag-Erling Smørgrav i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1464*5afab0e5SDag-Erling Smørgrav break;
1465*5afab0e5SDag-Erling Smørgrav }
1466*5afab0e5SDag-Erling Smørgrav i->state = DNSSEC_ZONE_RR_ITER_REST;
1467*5afab0e5SDag-Erling Smørgrav return i->name->nsec;
1468*5afab0e5SDag-Erling Smørgrav
1469*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_NSEC3:
1470*5afab0e5SDag-Erling Smørgrav nsec3 = i->nsec3_name->nsec;
1471*5afab0e5SDag-Erling Smørgrav
1472*5afab0e5SDag-Erling Smørgrav /* next nsec3 */
1473*5afab0e5SDag-Erling Smørgrav do {
1474*5afab0e5SDag-Erling Smørgrav i->nsec3_node
1475*5afab0e5SDag-Erling Smørgrav = ldns_rbtree_next(i->nsec3_node);
1476*5afab0e5SDag-Erling Smørgrav i->nsec3_name
1477*5afab0e5SDag-Erling Smørgrav = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1478*5afab0e5SDag-Erling Smørgrav : (ldns_dnssec_name*)i->nsec3_node->data;
1479*5afab0e5SDag-Erling Smørgrav
1480*5afab0e5SDag-Erling Smørgrav /* names for glue can be in the hashed_names
1481*5afab0e5SDag-Erling Smørgrav * tree, but will not have a NSEC3
1482*5afab0e5SDag-Erling Smørgrav */
1483*5afab0e5SDag-Erling Smørgrav } while (i->nsec3_name && !i->nsec3_name->nsec);
1484*5afab0e5SDag-Erling Smørgrav
1485*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_set_state_for_next_name(i);
1486*5afab0e5SDag-Erling Smørgrav return nsec3;
1487*5afab0e5SDag-Erling Smørgrav
1488*5afab0e5SDag-Erling Smørgrav case DNSSEC_ZONE_RR_ITER_FINI:
1489*5afab0e5SDag-Erling Smørgrav return NULL;
1490*5afab0e5SDag-Erling Smørgrav }
1491*5afab0e5SDag-Erling Smørgrav }
1492*5afab0e5SDag-Erling Smørgrav }
1493*5afab0e5SDag-Erling Smørgrav
1494*5afab0e5SDag-Erling Smørgrav static ldns_rr *
1495*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1496*5afab0e5SDag-Erling Smørgrav {
1497*5afab0e5SDag-Erling Smørgrav if (!i || !zone)
1498*5afab0e5SDag-Erling Smørgrav return NULL;
1499*5afab0e5SDag-Erling Smørgrav
1500*5afab0e5SDag-Erling Smørgrav memset(i, 0, sizeof(*i));
1501*5afab0e5SDag-Erling Smørgrav i->zone = zone;
1502*5afab0e5SDag-Erling Smørgrav if (zone->soa && zone->soa->name) {
1503*5afab0e5SDag-Erling Smørgrav i->apex_name = zone->soa->name;
1504*5afab0e5SDag-Erling Smørgrav i->apex_labs = ldns_dname_label_count(i->apex_name);
1505*5afab0e5SDag-Erling Smørgrav } else
1506*5afab0e5SDag-Erling Smørgrav i->apex_name = NULL;
1507*5afab0e5SDag-Erling Smørgrav
1508*5afab0e5SDag-Erling Smørgrav
1509*5afab0e5SDag-Erling Smørgrav i->node = ldns_rbtree_first(zone->names);
1510*5afab0e5SDag-Erling Smørgrav i->name = i->node == LDNS_RBTREE_NULL ? NULL
1511*5afab0e5SDag-Erling Smørgrav : (ldns_dnssec_name *)i->node->data;
1512*5afab0e5SDag-Erling Smørgrav
1513*5afab0e5SDag-Erling Smørgrav if (zone->hashed_names) {
1514*5afab0e5SDag-Erling Smørgrav do {
1515*5afab0e5SDag-Erling Smørgrav i->nsec3_node = ldns_rbtree_first(zone->hashed_names);
1516*5afab0e5SDag-Erling Smørgrav i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1517*5afab0e5SDag-Erling Smørgrav : (ldns_dnssec_name*)i->nsec3_node->data;
1518*5afab0e5SDag-Erling Smørgrav } while (i->nsec3_name && !i->nsec3_name->nsec);
1519*5afab0e5SDag-Erling Smørgrav }
1520*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter_set_state_for_next_name(i);
1521*5afab0e5SDag-Erling Smørgrav return dnssec_zone_rr_iter_next(i);
1522*5afab0e5SDag-Erling Smørgrav }
1523*5afab0e5SDag-Erling Smørgrav
1524*5afab0e5SDag-Erling Smørgrav enum enum_zonemd_scheme {
1525*5afab0e5SDag-Erling Smørgrav ZONEMD_SCHEME_FIRST = 1,
1526*5afab0e5SDag-Erling Smørgrav ZONEMD_SCHEME_SIMPLE = 1,
1527*5afab0e5SDag-Erling Smørgrav ZONEMD_SCHEME_LAST = 1
1528*5afab0e5SDag-Erling Smørgrav };
1529*5afab0e5SDag-Erling Smørgrav typedef enum enum_zonemd_scheme zonemd_scheme;
1530*5afab0e5SDag-Erling Smørgrav
1531*5afab0e5SDag-Erling Smørgrav enum enum_zonemd_hash {
1532*5afab0e5SDag-Erling Smørgrav ZONEMD_HASH_FIRST = 1,
1533*5afab0e5SDag-Erling Smørgrav ZONEMD_HASH_SHA384 = 1,
1534*5afab0e5SDag-Erling Smørgrav ZONEMD_HASH_SHA512 = 2,
1535*5afab0e5SDag-Erling Smørgrav ZONEMD_HASH_LAST = 2
1536*5afab0e5SDag-Erling Smørgrav };
1537*5afab0e5SDag-Erling Smørgrav typedef enum enum_zonemd_hash zonemd_hash;
1538*5afab0e5SDag-Erling Smørgrav
1539*5afab0e5SDag-Erling Smørgrav struct struct_zone_digester {
1540*5afab0e5SDag-Erling Smørgrav ldns_sha384_CTX sha384_CTX;
1541*5afab0e5SDag-Erling Smørgrav ldns_sha512_CTX sha512_CTX;
1542*5afab0e5SDag-Erling Smørgrav unsigned simple_sha384 : 1;
1543*5afab0e5SDag-Erling Smørgrav unsigned simple_sha512 : 1;
1544*5afab0e5SDag-Erling Smørgrav unsigned double_sha384 : 1;
1545*5afab0e5SDag-Erling Smørgrav unsigned double_sha512 : 1;
1546*5afab0e5SDag-Erling Smørgrav };
1547*5afab0e5SDag-Erling Smørgrav typedef struct struct_zone_digester zone_digester;
1548*5afab0e5SDag-Erling Smørgrav
1549*5afab0e5SDag-Erling Smørgrav INLINE bool zone_digester_set(zone_digester *zd)
1550*5afab0e5SDag-Erling Smørgrav { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1551*5afab0e5SDag-Erling Smørgrav
1552*5afab0e5SDag-Erling Smørgrav INLINE void zone_digester_init(zone_digester *zd)
1553*5afab0e5SDag-Erling Smørgrav { memset(zd, 0, sizeof(*zd)); }
1554*5afab0e5SDag-Erling Smørgrav
1555*5afab0e5SDag-Erling Smørgrav static ldns_status
1556*5afab0e5SDag-Erling Smørgrav zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1557*5afab0e5SDag-Erling Smørgrav {
1558*5afab0e5SDag-Erling Smørgrav if (!zd)
1559*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1560*5afab0e5SDag-Erling Smørgrav
1561*5afab0e5SDag-Erling Smørgrav switch (scheme) {
1562*5afab0e5SDag-Erling Smørgrav case ZONEMD_SCHEME_SIMPLE:
1563*5afab0e5SDag-Erling Smørgrav switch (hash) {
1564*5afab0e5SDag-Erling Smørgrav case ZONEMD_HASH_SHA384:
1565*5afab0e5SDag-Erling Smørgrav if (zd->double_sha384)
1566*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1567*5afab0e5SDag-Erling Smørgrav
1568*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha384) {
1569*5afab0e5SDag-Erling Smørgrav zd->simple_sha384 = 0;
1570*5afab0e5SDag-Erling Smørgrav zd->double_sha384 = 1;
1571*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1572*5afab0e5SDag-Erling Smørgrav }
1573*5afab0e5SDag-Erling Smørgrav ldns_sha384_init(&zd->sha384_CTX);
1574*5afab0e5SDag-Erling Smørgrav zd->simple_sha384 = 1;
1575*5afab0e5SDag-Erling Smørgrav break;
1576*5afab0e5SDag-Erling Smørgrav
1577*5afab0e5SDag-Erling Smørgrav case ZONEMD_HASH_SHA512:
1578*5afab0e5SDag-Erling Smørgrav if (zd->double_sha512)
1579*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1580*5afab0e5SDag-Erling Smørgrav
1581*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha512) {
1582*5afab0e5SDag-Erling Smørgrav zd->simple_sha512 = 0;
1583*5afab0e5SDag-Erling Smørgrav zd->double_sha512 = 1;
1584*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1585*5afab0e5SDag-Erling Smørgrav }
1586*5afab0e5SDag-Erling Smørgrav ldns_sha512_init(&zd->sha512_CTX);
1587*5afab0e5SDag-Erling Smørgrav zd->simple_sha512 = 1;
1588*5afab0e5SDag-Erling Smørgrav break;
1589*5afab0e5SDag-Erling Smørgrav default:
1590*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1591*5afab0e5SDag-Erling Smørgrav }
1592*5afab0e5SDag-Erling Smørgrav break;
1593*5afab0e5SDag-Erling Smørgrav default:
1594*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1595*5afab0e5SDag-Erling Smørgrav }
1596*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1597*5afab0e5SDag-Erling Smørgrav }
1598*5afab0e5SDag-Erling Smørgrav
1599*5afab0e5SDag-Erling Smørgrav static ldns_status
1600*5afab0e5SDag-Erling Smørgrav zone_digester_update(zone_digester *zd, ldns_rr *rr)
1601*5afab0e5SDag-Erling Smørgrav {
1602*5afab0e5SDag-Erling Smørgrav uint8_t data[65536];
1603*5afab0e5SDag-Erling Smørgrav ldns_buffer buf;
1604*5afab0e5SDag-Erling Smørgrav ldns_status st;
1605*5afab0e5SDag-Erling Smørgrav
1606*5afab0e5SDag-Erling Smørgrav buf._data = data;
1607*5afab0e5SDag-Erling Smørgrav buf._position = 0;
1608*5afab0e5SDag-Erling Smørgrav buf._limit = sizeof(data);
1609*5afab0e5SDag-Erling Smørgrav buf._capacity = sizeof(data);
1610*5afab0e5SDag-Erling Smørgrav buf._fixed = 1;
1611*5afab0e5SDag-Erling Smørgrav buf._status = LDNS_STATUS_OK;
1612*5afab0e5SDag-Erling Smørgrav
1613*5afab0e5SDag-Erling Smørgrav if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1614*5afab0e5SDag-Erling Smørgrav return st;
1615*5afab0e5SDag-Erling Smørgrav
1616*5afab0e5SDag-Erling Smørgrav if (zd->simple_sha384)
1617*5afab0e5SDag-Erling Smørgrav ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1618*5afab0e5SDag-Erling Smørgrav
1619*5afab0e5SDag-Erling Smørgrav if (zd->simple_sha512)
1620*5afab0e5SDag-Erling Smørgrav ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1621*5afab0e5SDag-Erling Smørgrav
1622*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1623*5afab0e5SDag-Erling Smørgrav }
1624*5afab0e5SDag-Erling Smørgrav
1625*5afab0e5SDag-Erling Smørgrav INLINE ldns_rr *
1626*5afab0e5SDag-Erling Smørgrav new_zonemd(ldns_rr *soa, zonemd_hash hash)
1627*5afab0e5SDag-Erling Smørgrav {
1628*5afab0e5SDag-Erling Smørgrav ldns_rr *rr = NULL;
1629*5afab0e5SDag-Erling Smørgrav uint8_t *data = NULL;
1630*5afab0e5SDag-Erling Smørgrav ldns_rdf *rdf;
1631*5afab0e5SDag-Erling Smørgrav size_t md_len = hash == ZONEMD_HASH_SHA384
1632*5afab0e5SDag-Erling Smørgrav ? LDNS_SHA384_DIGEST_LENGTH
1633*5afab0e5SDag-Erling Smørgrav : LDNS_SHA512_DIGEST_LENGTH;
1634*5afab0e5SDag-Erling Smørgrav
1635*5afab0e5SDag-Erling Smørgrav if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1636*5afab0e5SDag-Erling Smørgrav return NULL;
1637*5afab0e5SDag-Erling Smørgrav
1638*5afab0e5SDag-Erling Smørgrav if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1639*5afab0e5SDag-Erling Smørgrav goto error;
1640*5afab0e5SDag-Erling Smørgrav
1641*5afab0e5SDag-Erling Smørgrav ldns_rr_set_owner(rr, rdf);
1642*5afab0e5SDag-Erling Smørgrav ldns_rr_set_class(rr, ldns_rr_get_class(soa));
1643*5afab0e5SDag-Erling Smørgrav ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1644*5afab0e5SDag-Erling Smørgrav
1645*5afab0e5SDag-Erling Smørgrav if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1646*5afab0e5SDag-Erling Smørgrav goto error;
1647*5afab0e5SDag-Erling Smørgrav ldns_rr_set_rdf(rr, rdf, 0);
1648*5afab0e5SDag-Erling Smørgrav
1649*5afab0e5SDag-Erling Smørgrav if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1650*5afab0e5SDag-Erling Smørgrav goto error;
1651*5afab0e5SDag-Erling Smørgrav ldns_rr_set_rdf(rr, rdf, 1);
1652*5afab0e5SDag-Erling Smørgrav
1653*5afab0e5SDag-Erling Smørgrav if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1654*5afab0e5SDag-Erling Smørgrav goto error;
1655*5afab0e5SDag-Erling Smørgrav ldns_rr_set_rdf(rr, rdf, 2);
1656*5afab0e5SDag-Erling Smørgrav
1657*5afab0e5SDag-Erling Smørgrav if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1658*5afab0e5SDag-Erling Smørgrav goto error;
1659*5afab0e5SDag-Erling Smørgrav
1660*5afab0e5SDag-Erling Smørgrav if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1661*5afab0e5SDag-Erling Smørgrav goto error;
1662*5afab0e5SDag-Erling Smørgrav ldns_rr_set_rdf(rr, rdf, 3);
1663*5afab0e5SDag-Erling Smørgrav
1664*5afab0e5SDag-Erling Smørgrav return rr;
1665*5afab0e5SDag-Erling Smørgrav error:
1666*5afab0e5SDag-Erling Smørgrav if (data)
1667*5afab0e5SDag-Erling Smørgrav LDNS_FREE(data);
1668*5afab0e5SDag-Erling Smørgrav ldns_rr_free(rr);
1669*5afab0e5SDag-Erling Smørgrav return NULL;
1670*5afab0e5SDag-Erling Smørgrav }
1671*5afab0e5SDag-Erling Smørgrav
1672*5afab0e5SDag-Erling Smørgrav static ldns_rr_list *
1673*5afab0e5SDag-Erling Smørgrav zone_digester_export(
1674*5afab0e5SDag-Erling Smørgrav zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1675*5afab0e5SDag-Erling Smørgrav {
1676*5afab0e5SDag-Erling Smørgrav ldns_status st = LDNS_STATUS_OK;
1677*5afab0e5SDag-Erling Smørgrav ldns_rr_list *rr_list = NULL;
1678*5afab0e5SDag-Erling Smørgrav ldns_rr *sha384 = NULL;
1679*5afab0e5SDag-Erling Smørgrav ldns_rr *sha512 = NULL;
1680*5afab0e5SDag-Erling Smørgrav
1681*5afab0e5SDag-Erling Smørgrav if (!zd || !soa)
1682*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_NULL;
1683*5afab0e5SDag-Erling Smørgrav
1684*5afab0e5SDag-Erling Smørgrav else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1685*5afab0e5SDag-Erling Smørgrav || ldns_rr_rd_count(soa) < 3)
1686*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_ZONEMD_INVALID_SOA;
1687*5afab0e5SDag-Erling Smørgrav
1688*5afab0e5SDag-Erling Smørgrav else if (!(rr_list = ldns_rr_list_new()))
1689*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_MEM_ERR;
1690*5afab0e5SDag-Erling Smørgrav
1691*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha384
1692*5afab0e5SDag-Erling Smørgrav && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1693*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_MEM_ERR;
1694*5afab0e5SDag-Erling Smørgrav
1695*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha512
1696*5afab0e5SDag-Erling Smørgrav && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1697*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_MEM_ERR;
1698*5afab0e5SDag-Erling Smørgrav
1699*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha384
1700*5afab0e5SDag-Erling Smørgrav && !ldns_rr_list_push_rr(rr_list, sha384))
1701*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_MEM_ERR;
1702*5afab0e5SDag-Erling Smørgrav
1703*5afab0e5SDag-Erling Smørgrav else if (zd->simple_sha512
1704*5afab0e5SDag-Erling Smørgrav && !ldns_rr_list_push_rr(rr_list, sha512)) {
1705*5afab0e5SDag-Erling Smørgrav if (zd->simple_sha384)
1706*5afab0e5SDag-Erling Smørgrav sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1707*5afab0e5SDag-Erling Smørgrav st = LDNS_STATUS_MEM_ERR;
1708*5afab0e5SDag-Erling Smørgrav
1709*5afab0e5SDag-Erling Smørgrav } else {
1710*5afab0e5SDag-Erling Smørgrav if (sha384)
1711*5afab0e5SDag-Erling Smørgrav ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1712*5afab0e5SDag-Erling Smørgrav , &zd->sha384_CTX);
1713*5afab0e5SDag-Erling Smørgrav if (sha512)
1714*5afab0e5SDag-Erling Smørgrav ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1715*5afab0e5SDag-Erling Smørgrav , &zd->sha512_CTX);
1716*5afab0e5SDag-Erling Smørgrav return rr_list;
1717*5afab0e5SDag-Erling Smørgrav }
1718*5afab0e5SDag-Erling Smørgrav if (ret_st)
1719*5afab0e5SDag-Erling Smørgrav *ret_st = st;
1720*5afab0e5SDag-Erling Smørgrav if (sha384)
1721*5afab0e5SDag-Erling Smørgrav ldns_rr_free(sha384);
1722*5afab0e5SDag-Erling Smørgrav if (sha512)
1723*5afab0e5SDag-Erling Smørgrav ldns_rr_free(sha512);
1724*5afab0e5SDag-Erling Smørgrav if (rr_list)
1725*5afab0e5SDag-Erling Smørgrav ldns_rr_list_deep_free(rr_list);
1726*5afab0e5SDag-Erling Smørgrav return NULL;
1727*5afab0e5SDag-Erling Smørgrav }
1728*5afab0e5SDag-Erling Smørgrav
1729*5afab0e5SDag-Erling Smørgrav static ldns_status
1730*5afab0e5SDag-Erling Smørgrav ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1731*5afab0e5SDag-Erling Smørgrav {
1732*5afab0e5SDag-Erling Smørgrav ldns_status st = LDNS_STATUS_OK;
1733*5afab0e5SDag-Erling Smørgrav dnssec_zone_rr_iter rr_iter;
1734*5afab0e5SDag-Erling Smørgrav ldns_rr *rr;
1735*5afab0e5SDag-Erling Smørgrav ldns_rdf *apex_name; /* name of zone apex */
1736*5afab0e5SDag-Erling Smørgrav
1737*5afab0e5SDag-Erling Smørgrav if (!zone || !zd || !zone->soa || !zone->soa->name)
1738*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1739*5afab0e5SDag-Erling Smørgrav
1740*5afab0e5SDag-Erling Smørgrav apex_name = zone->soa->name;
1741*5afab0e5SDag-Erling Smørgrav for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1742*5afab0e5SDag-Erling Smørgrav ; rr && !st
1743*5afab0e5SDag-Erling Smørgrav ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1744*5afab0e5SDag-Erling Smørgrav /* Skip apex ZONEMD RRs */
1745*5afab0e5SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD
1746*5afab0e5SDag-Erling Smørgrav && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1747*5afab0e5SDag-Erling Smørgrav continue;
1748*5afab0e5SDag-Erling Smørgrav /* Skip RRSIGs for apex ZONEMD RRs */
1749*5afab0e5SDag-Erling Smørgrav if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
1750*5afab0e5SDag-Erling Smørgrav && LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type(
1751*5afab0e5SDag-Erling Smørgrav ldns_rr_rrsig_typecovered(rr))
1752*5afab0e5SDag-Erling Smørgrav && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1753*5afab0e5SDag-Erling Smørgrav continue;
1754*5afab0e5SDag-Erling Smørgrav st = zone_digester_update(zd, rr);
1755*5afab0e5SDag-Erling Smørgrav }
1756*5afab0e5SDag-Erling Smørgrav return st;
1757*5afab0e5SDag-Erling Smørgrav }
1758*5afab0e5SDag-Erling Smørgrav
1759*5afab0e5SDag-Erling Smørgrav ldns_status
1760*5afab0e5SDag-Erling Smørgrav ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1761*5afab0e5SDag-Erling Smørgrav {
1762*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets *zonemd, *soa;
1763*5afab0e5SDag-Erling Smørgrav zone_digester zd;
1764*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrs *rrs;
1765*5afab0e5SDag-Erling Smørgrav ldns_rr *soa_rr;
1766*5afab0e5SDag-Erling Smørgrav ldns_status st;
1767*5afab0e5SDag-Erling Smørgrav uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1768*5afab0e5SDag-Erling Smørgrav uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1769*5afab0e5SDag-Erling Smørgrav size_t valid_zonemds;
1770*5afab0e5SDag-Erling Smørgrav
1771*5afab0e5SDag-Erling Smørgrav if (!zone)
1772*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1773*5afab0e5SDag-Erling Smørgrav
1774*5afab0e5SDag-Erling Smørgrav zonemd = ldns_dnssec_zone_find_rrset(
1775*5afab0e5SDag-Erling Smørgrav zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1776*5afab0e5SDag-Erling Smørgrav if (!zonemd) {
1777*5afab0e5SDag-Erling Smørgrav ldns_rbnode_t *nsec3_node;
1778*5afab0e5SDag-Erling Smørgrav
1779*5afab0e5SDag-Erling Smørgrav /* we need proof of non-existence for ZONEMD at the apex */
1780*5afab0e5SDag-Erling Smørgrav if (zone->soa->nsec) {
1781*5afab0e5SDag-Erling Smørgrav if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1782*5afab0e5SDag-Erling Smørgrav zone->soa->nsec),
1783*5afab0e5SDag-Erling Smørgrav LDNS_RR_TYPE_ZONEMD))
1784*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_ZONEMD;
1785*5afab0e5SDag-Erling Smørgrav
1786*5afab0e5SDag-Erling Smørgrav } else if (!zone->soa->hashed_name || !zone->hashed_names)
1787*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_ZONEMD;
1788*5afab0e5SDag-Erling Smørgrav
1789*5afab0e5SDag-Erling Smørgrav else if (LDNS_RBTREE_NULL ==
1790*5afab0e5SDag-Erling Smørgrav (nsec3_node = ldns_rbtree_search( zone->hashed_names
1791*5afab0e5SDag-Erling Smørgrav , zone->soa->hashed_name)))
1792*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_ZONEMD;
1793*5afab0e5SDag-Erling Smørgrav else {
1794*5afab0e5SDag-Erling Smørgrav ldns_dnssec_name *nsec3
1795*5afab0e5SDag-Erling Smørgrav = (ldns_dnssec_name *)nsec3_node->data;
1796*5afab0e5SDag-Erling Smørgrav if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1797*5afab0e5SDag-Erling Smørgrav nsec3->nsec),
1798*5afab0e5SDag-Erling Smørgrav LDNS_RR_TYPE_ZONEMD))
1799*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_ZONEMD;
1800*5afab0e5SDag-Erling Smørgrav }
1801*5afab0e5SDag-Erling Smørgrav /* ZONEMD at apex does really not exist */
1802*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1803*5afab0e5SDag-Erling Smørgrav }
1804*5afab0e5SDag-Erling Smørgrav soa = ldns_dnssec_zone_find_rrset(
1805*5afab0e5SDag-Erling Smørgrav zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1806*5afab0e5SDag-Erling Smørgrav if (!soa || !soa->rrs || !soa->rrs->rr)
1807*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_INVALID_SOA;
1808*5afab0e5SDag-Erling Smørgrav
1809*5afab0e5SDag-Erling Smørgrav soa_rr = soa->rrs->rr;
1810*5afab0e5SDag-Erling Smørgrav if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1811*5afab0e5SDag-Erling Smørgrav || ldns_rr_rd_count(soa_rr) < 3)
1812*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_INVALID_SOA;
1813*5afab0e5SDag-Erling Smørgrav
1814*5afab0e5SDag-Erling Smørgrav zone_digester_init(&zd);
1815*5afab0e5SDag-Erling Smørgrav for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1816*5afab0e5SDag-Erling Smørgrav if (!rrs->rr
1817*5afab0e5SDag-Erling Smørgrav || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1818*5afab0e5SDag-Erling Smørgrav || ldns_rr_rd_count(rrs->rr) < 4)
1819*5afab0e5SDag-Erling Smørgrav continue;
1820*5afab0e5SDag-Erling Smørgrav
1821*5afab0e5SDag-Erling Smørgrav /* serial should match SOA's serial */
1822*5afab0e5SDag-Erling Smørgrav if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1823*5afab0e5SDag-Erling Smørgrav != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1824*5afab0e5SDag-Erling Smørgrav continue;
1825*5afab0e5SDag-Erling Smørgrav
1826*5afab0e5SDag-Erling Smørgrav /* Add (scheme, hash) to digester */
1827*5afab0e5SDag-Erling Smørgrav zone_digester_add(&zd,
1828*5afab0e5SDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)),
1829*5afab0e5SDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2)));
1830*5afab0e5SDag-Erling Smørgrav }
1831*5afab0e5SDag-Erling Smørgrav if (!zone_digester_set(&zd))
1832*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NO_VALID_ZONEMD;
1833*5afab0e5SDag-Erling Smørgrav
1834*5afab0e5SDag-Erling Smørgrav if ((st = ldns_digest_zone(zone, &zd)))
1835*5afab0e5SDag-Erling Smørgrav return st;
1836*5afab0e5SDag-Erling Smørgrav
1837*5afab0e5SDag-Erling Smørgrav if (zd.simple_sha384)
1838*5afab0e5SDag-Erling Smørgrav ldns_sha384_final(simple_sha384, &zd.sha384_CTX);
1839*5afab0e5SDag-Erling Smørgrav if (zd.simple_sha512)
1840*5afab0e5SDag-Erling Smørgrav ldns_sha512_final(simple_sha512, &zd.sha512_CTX);
1841*5afab0e5SDag-Erling Smørgrav
1842*5afab0e5SDag-Erling Smørgrav valid_zonemds = 0;
1843*5afab0e5SDag-Erling Smørgrav for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1844*5afab0e5SDag-Erling Smørgrav if (!rrs->rr
1845*5afab0e5SDag-Erling Smørgrav || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1846*5afab0e5SDag-Erling Smørgrav || ldns_rr_rd_count(rrs->rr) < 4)
1847*5afab0e5SDag-Erling Smørgrav continue;
1848*5afab0e5SDag-Erling Smørgrav
1849*5afab0e5SDag-Erling Smørgrav /* serial should match SOA's serial */
1850*5afab0e5SDag-Erling Smørgrav if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1851*5afab0e5SDag-Erling Smørgrav != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1852*5afab0e5SDag-Erling Smørgrav continue;
1853*5afab0e5SDag-Erling Smørgrav
1854*5afab0e5SDag-Erling Smørgrav if (ZONEMD_SCHEME_SIMPLE !=
1855*5afab0e5SDag-Erling Smørgrav ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1856*5afab0e5SDag-Erling Smørgrav continue;
1857*5afab0e5SDag-Erling Smørgrav
1858*5afab0e5SDag-Erling Smørgrav if (ZONEMD_HASH_SHA384
1859*5afab0e5SDag-Erling Smørgrav == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1860*5afab0e5SDag-Erling Smørgrav && LDNS_SHA384_DIGEST_LENGTH
1861*5afab0e5SDag-Erling Smørgrav == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1862*5afab0e5SDag-Erling Smørgrav && memcmp( simple_sha384
1863*5afab0e5SDag-Erling Smørgrav , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1864*5afab0e5SDag-Erling Smørgrav , LDNS_SHA384_DIGEST_LENGTH) == 0)
1865*5afab0e5SDag-Erling Smørgrav
1866*5afab0e5SDag-Erling Smørgrav valid_zonemds += 1;
1867*5afab0e5SDag-Erling Smørgrav
1868*5afab0e5SDag-Erling Smørgrav if (ZONEMD_HASH_SHA512
1869*5afab0e5SDag-Erling Smørgrav == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1870*5afab0e5SDag-Erling Smørgrav && LDNS_SHA512_DIGEST_LENGTH
1871*5afab0e5SDag-Erling Smørgrav == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1872*5afab0e5SDag-Erling Smørgrav && memcmp( simple_sha512
1873*5afab0e5SDag-Erling Smørgrav , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1874*5afab0e5SDag-Erling Smørgrav , LDNS_SHA512_DIGEST_LENGTH) == 0)
1875*5afab0e5SDag-Erling Smørgrav
1876*5afab0e5SDag-Erling Smørgrav valid_zonemds += 1;
1877*5afab0e5SDag-Erling Smørgrav }
1878*5afab0e5SDag-Erling Smørgrav return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1879*5afab0e5SDag-Erling Smørgrav }
1880*5afab0e5SDag-Erling Smørgrav
1881*5afab0e5SDag-Erling Smørgrav #ifdef HAVE_SSL
1882*5afab0e5SDag-Erling Smørgrav static ldns_status
1883*5afab0e5SDag-Erling Smørgrav rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1884*5afab0e5SDag-Erling Smørgrav ldns_rr_list *new_rrs)
1885*5afab0e5SDag-Erling Smørgrav {
1886*5afab0e5SDag-Erling Smørgrav ldns_rr *rr = NULL;
1887*5afab0e5SDag-Erling Smørgrav
1888*5afab0e5SDag-Erling Smørgrav if (!rr_list || !rrs)
1889*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_NULL;
1890*5afab0e5SDag-Erling Smørgrav
1891*5afab0e5SDag-Erling Smørgrav if (ldns_rr_list_rr_count(rr_list) == 0)
1892*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1893*5afab0e5SDag-Erling Smørgrav
1894*5afab0e5SDag-Erling Smørgrav if (!*rrs) {
1895*5afab0e5SDag-Erling Smørgrav if (!(*rrs = ldns_dnssec_rrs_new()))
1896*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1897*5afab0e5SDag-Erling Smørgrav (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1898*5afab0e5SDag-Erling Smørgrav if (new_rrs)
1899*5afab0e5SDag-Erling Smørgrav ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1900*5afab0e5SDag-Erling Smørgrav }
1901*5afab0e5SDag-Erling Smørgrav while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1902*5afab0e5SDag-Erling Smørgrav ldns_status st;
1903*5afab0e5SDag-Erling Smørgrav
1904*5afab0e5SDag-Erling Smørgrav if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1905*5afab0e5SDag-Erling Smørgrav ldns_rr_list_push_rr(rr_list, rr);
1906*5afab0e5SDag-Erling Smørgrav return st;
1907*5afab0e5SDag-Erling Smørgrav } else if (new_rrs)
1908*5afab0e5SDag-Erling Smørgrav ldns_rr_list_push_rr(new_rrs, rr);
1909*5afab0e5SDag-Erling Smørgrav }
1910*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_OK;
1911*5afab0e5SDag-Erling Smørgrav }
1912*5afab0e5SDag-Erling Smørgrav
1913*5afab0e5SDag-Erling Smørgrav
1914*5afab0e5SDag-Erling Smørgrav ldns_status
1915*5afab0e5SDag-Erling Smørgrav dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1916*5afab0e5SDag-Erling Smørgrav ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1917*5afab0e5SDag-Erling Smørgrav {
1918*5afab0e5SDag-Erling Smørgrav ldns_status st = LDNS_STATUS_OK;
1919*5afab0e5SDag-Erling Smørgrav zone_digester zd;
1920*5afab0e5SDag-Erling Smørgrav ldns_rr_list *zonemd_rr_list = NULL;
1921*5afab0e5SDag-Erling Smørgrav ldns_rr_list *zonemd_rrsigs = NULL;
1922*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets *soa_rrset;
1923*5afab0e5SDag-Erling Smørgrav ldns_rr *soa_rr = NULL;
1924*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets **rrset_ref;
1925*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrsets *zonemd_rrset;
1926*5afab0e5SDag-Erling Smørgrav
1927*5afab0e5SDag-Erling Smørgrav zone_digester_init(&zd);
1928*5afab0e5SDag-Erling Smørgrav if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384)
1929*5afab0e5SDag-Erling Smørgrav zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1930*5afab0e5SDag-Erling Smørgrav , ZONEMD_HASH_SHA384);
1931*5afab0e5SDag-Erling Smørgrav
1932*5afab0e5SDag-Erling Smørgrav if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1933*5afab0e5SDag-Erling Smørgrav zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1934*5afab0e5SDag-Erling Smørgrav , ZONEMD_HASH_SHA512);
1935*5afab0e5SDag-Erling Smørgrav
1936*5afab0e5SDag-Erling Smørgrav if ((st = ldns_digest_zone(zone, &zd)))
1937*5afab0e5SDag-Erling Smørgrav return st;
1938*5afab0e5SDag-Erling Smørgrav
1939*5afab0e5SDag-Erling Smørgrav soa_rrset = ldns_dnssec_zone_find_rrset(
1940*5afab0e5SDag-Erling Smørgrav zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1941*5afab0e5SDag-Erling Smørgrav if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1942*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_ZONEMD_INVALID_SOA;
1943*5afab0e5SDag-Erling Smørgrav soa_rr = soa_rrset->rrs->rr;
1944*5afab0e5SDag-Erling Smørgrav
1945*5afab0e5SDag-Erling Smørgrav if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1946*5afab0e5SDag-Erling Smørgrav return st;
1947*5afab0e5SDag-Erling Smørgrav
1948*5afab0e5SDag-Erling Smørgrav /* - replace or add ZONEMD rrset */
1949*5afab0e5SDag-Erling Smørgrav rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1950*5afab0e5SDag-Erling Smørgrav while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1951*5afab0e5SDag-Erling Smørgrav rrset_ref = &(*rrset_ref)->next;
1952*5afab0e5SDag-Erling Smørgrav if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1953*5afab0e5SDag-Erling Smørgrav /* reuse zonemd rrset */
1954*5afab0e5SDag-Erling Smørgrav zonemd_rrset = *rrset_ref;
1955*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1956*5afab0e5SDag-Erling Smørgrav zonemd_rrset->rrs = NULL;
1957*5afab0e5SDag-Erling Smørgrav ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1958*5afab0e5SDag-Erling Smørgrav zonemd_rrset->signatures = NULL;
1959*5afab0e5SDag-Erling Smørgrav } else {
1960*5afab0e5SDag-Erling Smørgrav /* insert zonemd rrset */
1961*5afab0e5SDag-Erling Smørgrav zonemd_rrset = ldns_dnssec_rrsets_new();
1962*5afab0e5SDag-Erling Smørgrav if (!zonemd_rrset) {
1963*5afab0e5SDag-Erling Smørgrav ldns_rr_list_deep_free(zonemd_rr_list);
1964*5afab0e5SDag-Erling Smørgrav return LDNS_STATUS_MEM_ERR;
1965*5afab0e5SDag-Erling Smørgrav }
1966*5afab0e5SDag-Erling Smørgrav zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1967*5afab0e5SDag-Erling Smørgrav zonemd_rrset->next = *rrset_ref;
1968*5afab0e5SDag-Erling Smørgrav *rrset_ref = zonemd_rrset;
1969*5afab0e5SDag-Erling Smørgrav }
1970*5afab0e5SDag-Erling Smørgrav if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1971*5afab0e5SDag-Erling Smørgrav st = rr_list2dnssec_rrs( zonemd_rrsigs
1972*5afab0e5SDag-Erling Smørgrav , &zonemd_rrset->signatures, new_rrs);
1973*5afab0e5SDag-Erling Smørgrav if (!st)
1974*5afab0e5SDag-Erling Smørgrav st = rr_list2dnssec_rrs( zonemd_rr_list
1975*5afab0e5SDag-Erling Smørgrav , &zonemd_rrset->rrs, new_rrs);
1976*5afab0e5SDag-Erling Smørgrav ldns_rr_list_deep_free(zonemd_rr_list);
1977*5afab0e5SDag-Erling Smørgrav ldns_rr_list_deep_free(zonemd_rrsigs);
1978*5afab0e5SDag-Erling Smørgrav return st;
1979*5afab0e5SDag-Erling Smørgrav }
1980*5afab0e5SDag-Erling Smørgrav
1981*5afab0e5SDag-Erling Smørgrav #endif /* HAVE_SSL */
1982*5afab0e5SDag-Erling Smørgrav
1983