xref: /dflybsd-src/contrib/ldns/dnssec_zone.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * special zone file structures and functions for better dnssec handling
3825eb42bSJan Lentfer  */
4825eb42bSJan Lentfer 
5825eb42bSJan Lentfer #include <ldns/config.h>
6825eb42bSJan Lentfer 
7825eb42bSJan Lentfer #include <ldns/ldns.h>
8825eb42bSJan Lentfer 
9825eb42bSJan Lentfer ldns_dnssec_rrs *
ldns_dnssec_rrs_new(void)105340022aSzrj ldns_dnssec_rrs_new(void)
11825eb42bSJan Lentfer {
12825eb42bSJan Lentfer 	ldns_dnssec_rrs *new_rrs;
13825eb42bSJan Lentfer 	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
14fd185f4dSJan Lentfer         if(!new_rrs) return NULL;
15825eb42bSJan Lentfer 	new_rrs->rr = NULL;
16825eb42bSJan Lentfer 	new_rrs->next = NULL;
17825eb42bSJan Lentfer 	return new_rrs;
18825eb42bSJan Lentfer }
19825eb42bSJan Lentfer 
20825eb42bSJan Lentfer INLINE void
ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs * rrs,int deep)21825eb42bSJan Lentfer ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
22825eb42bSJan Lentfer {
23825eb42bSJan Lentfer 	ldns_dnssec_rrs *next;
24825eb42bSJan Lentfer 	while (rrs) {
25825eb42bSJan Lentfer 		next = rrs->next;
26825eb42bSJan Lentfer 		if (deep) {
27825eb42bSJan Lentfer 			ldns_rr_free(rrs->rr);
28825eb42bSJan Lentfer 		}
29825eb42bSJan Lentfer 		LDNS_FREE(rrs);
30825eb42bSJan Lentfer 		rrs = next;
31825eb42bSJan Lentfer 	}
32825eb42bSJan Lentfer }
33825eb42bSJan Lentfer 
34825eb42bSJan Lentfer void
ldns_dnssec_rrs_free(ldns_dnssec_rrs * rrs)35825eb42bSJan Lentfer ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
36825eb42bSJan Lentfer {
37825eb42bSJan Lentfer 	ldns_dnssec_rrs_free_internal(rrs, 0);
38825eb42bSJan Lentfer }
39825eb42bSJan Lentfer 
40825eb42bSJan Lentfer void
ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs * rrs)41825eb42bSJan Lentfer ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
42825eb42bSJan Lentfer {
43825eb42bSJan Lentfer 	ldns_dnssec_rrs_free_internal(rrs, 1);
44825eb42bSJan Lentfer }
45825eb42bSJan Lentfer 
46825eb42bSJan Lentfer ldns_status
ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs * rrs,ldns_rr * rr)47825eb42bSJan Lentfer ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
48825eb42bSJan Lentfer {
49825eb42bSJan Lentfer 	int cmp;
50825eb42bSJan Lentfer 	ldns_dnssec_rrs *new_rrs;
51825eb42bSJan Lentfer 	if (!rrs || !rr) {
52825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
53825eb42bSJan Lentfer 	}
54825eb42bSJan Lentfer 
55825eb42bSJan Lentfer 	/* this could be done more efficiently; name and type should already
56825eb42bSJan Lentfer 	   be equal */
575340022aSzrj 	cmp = ldns_rr_compare(rrs->rr, rr);
585340022aSzrj 	if (cmp < 0) {
59825eb42bSJan Lentfer 		if (rrs->next) {
60ac996e71SJan Lentfer 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
61825eb42bSJan Lentfer 		} else {
62825eb42bSJan Lentfer 			new_rrs = ldns_dnssec_rrs_new();
63825eb42bSJan Lentfer 			new_rrs->rr = rr;
64825eb42bSJan Lentfer 			rrs->next = new_rrs;
65825eb42bSJan Lentfer 		}
66825eb42bSJan Lentfer 	} else if (cmp > 0) {
67825eb42bSJan Lentfer 		/* put the current old rr in the new next, put the new
68825eb42bSJan Lentfer 		   rr in the current container */
69825eb42bSJan Lentfer 		new_rrs = ldns_dnssec_rrs_new();
70825eb42bSJan Lentfer 		new_rrs->rr = rrs->rr;
71825eb42bSJan Lentfer 		new_rrs->next = rrs->next;
72825eb42bSJan Lentfer 		rrs->rr = rr;
73825eb42bSJan Lentfer 		rrs->next = new_rrs;
74825eb42bSJan Lentfer 	}
755340022aSzrj 	/* Silently ignore equal rr's */
76825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
77825eb42bSJan Lentfer }
78825eb42bSJan Lentfer 
79825eb42bSJan Lentfer void
ldns_dnssec_rrs_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrs * rrs)80b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
815340022aSzrj 	       const ldns_dnssec_rrs *rrs)
82825eb42bSJan Lentfer {
83825eb42bSJan Lentfer 	if (!rrs) {
84b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
85b5dedccaSJan Lentfer 			fprintf(out, "; <void>");
86825eb42bSJan Lentfer 	} else {
87825eb42bSJan Lentfer 		if (rrs->rr) {
88b5dedccaSJan Lentfer 			ldns_rr_print_fmt(out, fmt, rrs->rr);
89825eb42bSJan Lentfer 		}
90825eb42bSJan Lentfer 		if (rrs->next) {
91b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
92825eb42bSJan Lentfer 		}
93825eb42bSJan Lentfer 	}
94825eb42bSJan Lentfer }
95825eb42bSJan Lentfer 
96b5dedccaSJan Lentfer void
ldns_dnssec_rrs_print(FILE * out,const ldns_dnssec_rrs * rrs)975340022aSzrj ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
98b5dedccaSJan Lentfer {
99b5dedccaSJan Lentfer 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
100b5dedccaSJan Lentfer }
101b5dedccaSJan Lentfer 
102b5dedccaSJan Lentfer 
103825eb42bSJan Lentfer ldns_dnssec_rrsets *
ldns_dnssec_rrsets_new(void)1045340022aSzrj ldns_dnssec_rrsets_new(void)
105825eb42bSJan Lentfer {
106825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
107825eb42bSJan Lentfer 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
108fd185f4dSJan Lentfer         if(!new_rrsets) return NULL;
109825eb42bSJan Lentfer 	new_rrsets->rrs = NULL;
110825eb42bSJan Lentfer 	new_rrsets->type = 0;
111825eb42bSJan Lentfer 	new_rrsets->signatures = NULL;
112825eb42bSJan Lentfer 	new_rrsets->next = NULL;
113825eb42bSJan Lentfer 	return new_rrsets;
114825eb42bSJan Lentfer }
115825eb42bSJan Lentfer 
116825eb42bSJan Lentfer INLINE void
ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets * rrsets,int deep)117825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
118825eb42bSJan Lentfer {
119825eb42bSJan Lentfer 	if (rrsets) {
120825eb42bSJan Lentfer 		if (rrsets->rrs) {
121825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
122825eb42bSJan Lentfer 		}
123825eb42bSJan Lentfer 		if (rrsets->next) {
124825eb42bSJan Lentfer 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
125825eb42bSJan Lentfer 		}
126825eb42bSJan Lentfer 		if (rrsets->signatures) {
127825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
128825eb42bSJan Lentfer 		}
129825eb42bSJan Lentfer 		LDNS_FREE(rrsets);
130825eb42bSJan Lentfer 	}
131825eb42bSJan Lentfer }
132825eb42bSJan Lentfer 
133825eb42bSJan Lentfer void
ldns_dnssec_rrsets_free(ldns_dnssec_rrsets * rrsets)134825eb42bSJan Lentfer ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
135825eb42bSJan Lentfer {
136825eb42bSJan Lentfer 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
137825eb42bSJan Lentfer }
138825eb42bSJan Lentfer 
139825eb42bSJan Lentfer void
ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets * rrsets)140825eb42bSJan Lentfer ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
141825eb42bSJan Lentfer {
142825eb42bSJan Lentfer 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
143825eb42bSJan Lentfer }
144825eb42bSJan Lentfer 
145825eb42bSJan Lentfer ldns_rr_type
ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets * rrsets)1465340022aSzrj ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
147825eb42bSJan Lentfer {
148825eb42bSJan Lentfer 	if (rrsets) {
149825eb42bSJan Lentfer 		return rrsets->type;
150825eb42bSJan Lentfer 	} else {
151825eb42bSJan Lentfer 		return 0;
152825eb42bSJan Lentfer 	}
153825eb42bSJan Lentfer }
154825eb42bSJan Lentfer 
155825eb42bSJan Lentfer ldns_status
ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets * rrsets,ldns_rr_type type)156825eb42bSJan Lentfer ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
157825eb42bSJan Lentfer 					   ldns_rr_type type)
158825eb42bSJan Lentfer {
159825eb42bSJan Lentfer 	if (rrsets) {
160825eb42bSJan Lentfer 		rrsets->type = type;
161825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
162825eb42bSJan Lentfer 	}
163825eb42bSJan Lentfer 	return LDNS_STATUS_ERR;
164825eb42bSJan Lentfer }
165825eb42bSJan Lentfer 
1665340022aSzrj static ldns_dnssec_rrsets *
ldns_dnssec_rrsets_new_frm_rr(ldns_rr * rr)167825eb42bSJan Lentfer ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
168825eb42bSJan Lentfer {
169825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
170825eb42bSJan Lentfer 	ldns_rr_type rr_type;
171825eb42bSJan Lentfer 	bool rrsig;
172825eb42bSJan Lentfer 
173825eb42bSJan Lentfer 	new_rrsets = ldns_dnssec_rrsets_new();
174825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
175825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
176825eb42bSJan Lentfer 		rrsig = true;
177825eb42bSJan Lentfer 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
178825eb42bSJan Lentfer 	} else {
179825eb42bSJan Lentfer 		rrsig = false;
180825eb42bSJan Lentfer 	}
181825eb42bSJan Lentfer 	if (!rrsig) {
182825eb42bSJan Lentfer 		new_rrsets->rrs = ldns_dnssec_rrs_new();
183825eb42bSJan Lentfer 		new_rrsets->rrs->rr = rr;
184825eb42bSJan Lentfer 	} else {
185825eb42bSJan Lentfer 		new_rrsets->signatures = ldns_dnssec_rrs_new();
186825eb42bSJan Lentfer 		new_rrsets->signatures->rr = rr;
187825eb42bSJan Lentfer 	}
188825eb42bSJan Lentfer 	new_rrsets->type = rr_type;
189825eb42bSJan Lentfer 	return new_rrsets;
190825eb42bSJan Lentfer }
191825eb42bSJan Lentfer 
192825eb42bSJan Lentfer ldns_status
ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets * rrsets,ldns_rr * rr)193825eb42bSJan Lentfer ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
194825eb42bSJan Lentfer {
195825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
196825eb42bSJan Lentfer 	ldns_rr_type rr_type;
197825eb42bSJan Lentfer 	bool rrsig = false;
198825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
199825eb42bSJan Lentfer 
200825eb42bSJan Lentfer 	if (!rrsets || !rr) {
201825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
202825eb42bSJan Lentfer 	}
203825eb42bSJan Lentfer 
204825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
205825eb42bSJan Lentfer 
206825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
207825eb42bSJan Lentfer 		rrsig = true;
208825eb42bSJan Lentfer 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
209825eb42bSJan Lentfer 	}
210825eb42bSJan Lentfer 
211825eb42bSJan Lentfer 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
212825eb42bSJan Lentfer 		if (!rrsig) {
213825eb42bSJan Lentfer 			rrsets->rrs = ldns_dnssec_rrs_new();
214825eb42bSJan Lentfer 			rrsets->rrs->rr = rr;
215825eb42bSJan Lentfer 			rrsets->type = rr_type;
216825eb42bSJan Lentfer 		} else {
217825eb42bSJan Lentfer 			rrsets->signatures = ldns_dnssec_rrs_new();
218825eb42bSJan Lentfer 			rrsets->signatures->rr = rr;
219825eb42bSJan Lentfer 			rrsets->type = rr_type;
220825eb42bSJan Lentfer 		}
221825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
222825eb42bSJan Lentfer 	}
223825eb42bSJan Lentfer 
224825eb42bSJan Lentfer 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
225825eb42bSJan Lentfer 		if (rrsets->next) {
226825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
227825eb42bSJan Lentfer 		} else {
228825eb42bSJan Lentfer 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
229825eb42bSJan Lentfer 			rrsets->next = new_rrsets;
230825eb42bSJan Lentfer 		}
231825eb42bSJan Lentfer 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
232825eb42bSJan Lentfer 		/* move the current one into the new next,
233825eb42bSJan Lentfer 		   replace field of current with data from new rr */
234825eb42bSJan Lentfer 		new_rrsets = ldns_dnssec_rrsets_new();
235825eb42bSJan Lentfer 		new_rrsets->rrs = rrsets->rrs;
236825eb42bSJan Lentfer 		new_rrsets->type = rrsets->type;
237825eb42bSJan Lentfer 		new_rrsets->signatures = rrsets->signatures;
238825eb42bSJan Lentfer 		new_rrsets->next = rrsets->next;
239825eb42bSJan Lentfer 		if (!rrsig) {
240825eb42bSJan Lentfer 			rrsets->rrs = ldns_dnssec_rrs_new();
241825eb42bSJan Lentfer 			rrsets->rrs->rr = rr;
242825eb42bSJan Lentfer 			rrsets->signatures = NULL;
243825eb42bSJan Lentfer 		} else {
244825eb42bSJan Lentfer 			rrsets->rrs = NULL;
245825eb42bSJan Lentfer 			rrsets->signatures = ldns_dnssec_rrs_new();
246825eb42bSJan Lentfer 			rrsets->signatures->rr = rr;
247825eb42bSJan Lentfer 		}
248825eb42bSJan Lentfer 		rrsets->type = rr_type;
249825eb42bSJan Lentfer 		rrsets->next = new_rrsets;
250825eb42bSJan Lentfer 	} else {
251825eb42bSJan Lentfer 		/* equal, add to current rrsets */
252825eb42bSJan Lentfer 		if (rrsig) {
253825eb42bSJan Lentfer 			if (rrsets->signatures) {
254825eb42bSJan Lentfer 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
255825eb42bSJan Lentfer 			} else {
256825eb42bSJan Lentfer 				rrsets->signatures = ldns_dnssec_rrs_new();
257825eb42bSJan Lentfer 				rrsets->signatures->rr = rr;
258825eb42bSJan Lentfer 			}
259825eb42bSJan Lentfer 		} else {
260825eb42bSJan Lentfer 			if (rrsets->rrs) {
261825eb42bSJan Lentfer 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
262825eb42bSJan Lentfer 			} else {
263825eb42bSJan Lentfer 				rrsets->rrs = ldns_dnssec_rrs_new();
264825eb42bSJan Lentfer 				rrsets->rrs->rr = rr;
265825eb42bSJan Lentfer 			}
266825eb42bSJan Lentfer 		}
267825eb42bSJan Lentfer 	}
268825eb42bSJan Lentfer 
269825eb42bSJan Lentfer 	return result;
270825eb42bSJan Lentfer }
271825eb42bSJan Lentfer 
2725340022aSzrj 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)273b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
2745340022aSzrj 		const ldns_dnssec_rrsets *rrsets,
275825eb42bSJan Lentfer 		bool follow,
276825eb42bSJan Lentfer 		bool show_soa)
277825eb42bSJan Lentfer {
278825eb42bSJan Lentfer 	if (!rrsets) {
279b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
280b5dedccaSJan Lentfer 			fprintf(out, "; <void>\n");
281825eb42bSJan Lentfer 	} else {
282825eb42bSJan Lentfer 		if (rrsets->rrs &&
283825eb42bSJan Lentfer 		    (show_soa ||
284825eb42bSJan Lentfer 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
285825eb42bSJan Lentfer 		    )
286825eb42bSJan Lentfer 		   ) {
287b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
288825eb42bSJan Lentfer 			if (rrsets->signatures) {
289b5dedccaSJan Lentfer 				ldns_dnssec_rrs_print_fmt(out, fmt,
290b5dedccaSJan Lentfer 						rrsets->signatures);
291825eb42bSJan Lentfer 			}
292825eb42bSJan Lentfer 		}
293825eb42bSJan Lentfer 		if (follow && rrsets->next) {
294b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295b5dedccaSJan Lentfer 					rrsets->next, follow, show_soa);
296825eb42bSJan Lentfer 		}
297825eb42bSJan Lentfer 	}
298825eb42bSJan Lentfer }
299825eb42bSJan Lentfer 
300b5dedccaSJan Lentfer 
301b5dedccaSJan Lentfer void
ldns_dnssec_rrsets_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrsets * rrsets,bool follow)302b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
3035340022aSzrj 		const ldns_dnssec_rrsets *rrsets,
304b5dedccaSJan Lentfer 		bool follow)
305b5dedccaSJan Lentfer {
306b5dedccaSJan Lentfer 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
307b5dedccaSJan Lentfer }
308b5dedccaSJan Lentfer 
309b5dedccaSJan Lentfer void
ldns_dnssec_rrsets_print(FILE * out,const ldns_dnssec_rrsets * rrsets,bool follow)3105340022aSzrj ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
311825eb42bSJan Lentfer {
312b5dedccaSJan Lentfer 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
313b5dedccaSJan Lentfer 			rrsets, follow);
314825eb42bSJan Lentfer }
315825eb42bSJan Lentfer 
316825eb42bSJan Lentfer ldns_dnssec_name *
ldns_dnssec_name_new(void)3175340022aSzrj ldns_dnssec_name_new(void)
318825eb42bSJan Lentfer {
319825eb42bSJan Lentfer 	ldns_dnssec_name *new_name;
320825eb42bSJan Lentfer 
321b5dedccaSJan Lentfer 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
322825eb42bSJan Lentfer 	if (!new_name) {
323825eb42bSJan Lentfer 		return NULL;
324825eb42bSJan Lentfer 	}
325b5dedccaSJan Lentfer 	/*
326*ee791febSAntonio Huete Jimenez 	 * not needed anymore because CALLOC initializes everything to zero.
327825eb42bSJan Lentfer 
328825eb42bSJan Lentfer 	new_name->name = NULL;
329825eb42bSJan Lentfer 	new_name->rrsets = NULL;
330825eb42bSJan Lentfer 	new_name->name_alloced = false;
331825eb42bSJan Lentfer 	new_name->nsec = NULL;
332825eb42bSJan Lentfer 	new_name->nsec_signatures = NULL;
333825eb42bSJan Lentfer 
334825eb42bSJan Lentfer 	new_name->is_glue = false;
335825eb42bSJan Lentfer 	new_name->hashed_name = NULL;
336825eb42bSJan Lentfer 
337b5dedccaSJan Lentfer 	 */
338825eb42bSJan Lentfer 	return new_name;
339825eb42bSJan Lentfer }
340825eb42bSJan Lentfer 
341825eb42bSJan Lentfer ldns_dnssec_name *
ldns_dnssec_name_new_frm_rr(ldns_rr * rr)342825eb42bSJan Lentfer ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
343825eb42bSJan Lentfer {
344825eb42bSJan Lentfer 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
345825eb42bSJan Lentfer 
346825eb42bSJan Lentfer 	new_name->name = ldns_rr_owner(rr);
347fd185f4dSJan Lentfer 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
348fd185f4dSJan Lentfer 		ldns_dnssec_name_free(new_name);
349fd185f4dSJan Lentfer 		return NULL;
350fd185f4dSJan Lentfer 	}
351825eb42bSJan Lentfer 
352825eb42bSJan Lentfer 	return new_name;
353825eb42bSJan Lentfer }
354825eb42bSJan Lentfer 
355825eb42bSJan Lentfer INLINE void
ldns_dnssec_name_free_internal(ldns_dnssec_name * name,int deep)356825eb42bSJan Lentfer ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357825eb42bSJan Lentfer                                int deep)
358825eb42bSJan Lentfer {
359825eb42bSJan Lentfer 	if (name) {
360825eb42bSJan Lentfer 		if (name->name_alloced) {
361825eb42bSJan Lentfer 			ldns_rdf_deep_free(name->name);
362825eb42bSJan Lentfer 		}
363825eb42bSJan Lentfer 		if (name->rrsets) {
364825eb42bSJan Lentfer 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
365825eb42bSJan Lentfer 		}
366825eb42bSJan Lentfer 		if (name->nsec && deep) {
367825eb42bSJan Lentfer 			ldns_rr_free(name->nsec);
368825eb42bSJan Lentfer 		}
369825eb42bSJan Lentfer 		if (name->nsec_signatures) {
370825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
371825eb42bSJan Lentfer 		}
372825eb42bSJan Lentfer 		if (name->hashed_name) {
373*ee791febSAntonio Huete Jimenez 			/* Hashed name is always allocated when signing,
374*ee791febSAntonio Huete Jimenez 			 * so always deep free
375*ee791febSAntonio Huete Jimenez 			 */
376825eb42bSJan Lentfer 			ldns_rdf_deep_free(name->hashed_name);
377825eb42bSJan Lentfer 		}
378825eb42bSJan Lentfer 		LDNS_FREE(name);
379825eb42bSJan Lentfer 	}
380825eb42bSJan Lentfer }
381825eb42bSJan Lentfer 
382825eb42bSJan Lentfer void
ldns_dnssec_name_free(ldns_dnssec_name * name)383825eb42bSJan Lentfer ldns_dnssec_name_free(ldns_dnssec_name *name)
384825eb42bSJan Lentfer {
385825eb42bSJan Lentfer   ldns_dnssec_name_free_internal(name, 0);
386825eb42bSJan Lentfer }
387825eb42bSJan Lentfer 
388825eb42bSJan Lentfer void
ldns_dnssec_name_deep_free(ldns_dnssec_name * name)389825eb42bSJan Lentfer ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
390825eb42bSJan Lentfer {
391825eb42bSJan Lentfer   ldns_dnssec_name_free_internal(name, 1);
392825eb42bSJan Lentfer }
393825eb42bSJan Lentfer 
394825eb42bSJan Lentfer ldns_rdf *
ldns_dnssec_name_name(const ldns_dnssec_name * name)3955340022aSzrj ldns_dnssec_name_name(const ldns_dnssec_name *name)
396825eb42bSJan Lentfer {
397825eb42bSJan Lentfer 	if (name) {
398825eb42bSJan Lentfer 		return name->name;
399825eb42bSJan Lentfer 	}
400825eb42bSJan Lentfer 	return NULL;
401825eb42bSJan Lentfer }
402825eb42bSJan Lentfer 
403b5dedccaSJan Lentfer bool
ldns_dnssec_name_is_glue(const ldns_dnssec_name * name)4045340022aSzrj ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
405b5dedccaSJan Lentfer {
406b5dedccaSJan Lentfer 	if (name) {
407b5dedccaSJan Lentfer 		return name->is_glue;
408b5dedccaSJan Lentfer 	}
409b5dedccaSJan Lentfer 	return false;
410b5dedccaSJan Lentfer }
411b5dedccaSJan Lentfer 
412825eb42bSJan Lentfer void
ldns_dnssec_name_set_name(ldns_dnssec_name * rrset,ldns_rdf * dname)413825eb42bSJan Lentfer ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
414825eb42bSJan Lentfer 					 ldns_rdf *dname)
415825eb42bSJan Lentfer {
416825eb42bSJan Lentfer 	if (rrset && dname) {
417825eb42bSJan Lentfer 		rrset->name = dname;
418825eb42bSJan Lentfer 	}
419825eb42bSJan Lentfer }
420825eb42bSJan Lentfer 
421825eb42bSJan Lentfer 
422825eb42bSJan Lentfer void
ldns_dnssec_name_set_nsec(ldns_dnssec_name * rrset,ldns_rr * nsec)423825eb42bSJan Lentfer ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
424825eb42bSJan Lentfer {
425825eb42bSJan Lentfer 	if (rrset && nsec) {
426825eb42bSJan Lentfer 		rrset->nsec = nsec;
427825eb42bSJan Lentfer 	}
428825eb42bSJan Lentfer }
429825eb42bSJan Lentfer 
430825eb42bSJan Lentfer int
ldns_dnssec_name_cmp(const void * a,const void * b)431825eb42bSJan Lentfer ldns_dnssec_name_cmp(const void *a, const void *b)
432825eb42bSJan Lentfer {
433825eb42bSJan Lentfer 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
434825eb42bSJan Lentfer 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
435825eb42bSJan Lentfer 
436825eb42bSJan Lentfer 	if (na && nb) {
437825eb42bSJan Lentfer 		return ldns_dname_compare(ldns_dnssec_name_name(na),
438825eb42bSJan Lentfer 							 ldns_dnssec_name_name(nb));
439825eb42bSJan Lentfer 	} else if (na) {
440825eb42bSJan Lentfer 		return 1;
441825eb42bSJan Lentfer 	} else if (nb) {
442825eb42bSJan Lentfer 		return -1;
443825eb42bSJan Lentfer 	} else {
444825eb42bSJan Lentfer 		return 0;
445825eb42bSJan Lentfer 	}
446825eb42bSJan Lentfer }
447825eb42bSJan Lentfer 
448825eb42bSJan Lentfer ldns_status
ldns_dnssec_name_add_rr(ldns_dnssec_name * name,ldns_rr * rr)449825eb42bSJan Lentfer ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
450825eb42bSJan Lentfer 				    ldns_rr *rr)
451825eb42bSJan Lentfer {
452825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
453ac996e71SJan Lentfer 	ldns_rr_type rr_type;
454825eb42bSJan Lentfer 	ldns_rr_type typecovered = 0;
455825eb42bSJan Lentfer 
456825eb42bSJan Lentfer 	/* special handling for NSEC3 and NSECX covering RRSIGS */
457825eb42bSJan Lentfer 
458825eb42bSJan Lentfer 	if (!name || !rr) {
459825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
460825eb42bSJan Lentfer 	}
461825eb42bSJan Lentfer 
462825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
463825eb42bSJan Lentfer 
464825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
465825eb42bSJan Lentfer 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
466825eb42bSJan Lentfer 	}
467825eb42bSJan Lentfer 
468825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_NSEC ||
469825eb42bSJan Lentfer 	    rr_type == LDNS_RR_TYPE_NSEC3) {
470825eb42bSJan Lentfer 		/* XX check if is already set (and error?) */
471825eb42bSJan Lentfer 		name->nsec = rr;
472825eb42bSJan Lentfer 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
473825eb42bSJan Lentfer 			 typecovered == LDNS_RR_TYPE_NSEC3) {
474825eb42bSJan Lentfer 		if (name->nsec_signatures) {
475fd185f4dSJan Lentfer 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
476825eb42bSJan Lentfer 		} else {
477825eb42bSJan Lentfer 			name->nsec_signatures = ldns_dnssec_rrs_new();
478825eb42bSJan Lentfer 			name->nsec_signatures->rr = rr;
479825eb42bSJan Lentfer 		}
480825eb42bSJan Lentfer 	} else {
481825eb42bSJan Lentfer 		/* it's a 'normal' RR, add it to the right rrset */
482825eb42bSJan Lentfer 		if (name->rrsets) {
483825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
484825eb42bSJan Lentfer 		} else {
485825eb42bSJan Lentfer 			name->rrsets = ldns_dnssec_rrsets_new();
486825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
487825eb42bSJan Lentfer 		}
488825eb42bSJan Lentfer 	}
489825eb42bSJan Lentfer 	return result;
490825eb42bSJan Lentfer }
491825eb42bSJan Lentfer 
492825eb42bSJan Lentfer ldns_dnssec_rrsets *
ldns_dnssec_name_find_rrset(const ldns_dnssec_name * name,ldns_rr_type type)4935340022aSzrj ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
494825eb42bSJan Lentfer 					   ldns_rr_type type) {
495825eb42bSJan Lentfer 	ldns_dnssec_rrsets *result;
496825eb42bSJan Lentfer 
497825eb42bSJan Lentfer 	result = name->rrsets;
498825eb42bSJan Lentfer 	while (result) {
499825eb42bSJan Lentfer 		if (result->type == type) {
500825eb42bSJan Lentfer 			return result;
501825eb42bSJan Lentfer 		} else {
502825eb42bSJan Lentfer 			result = result->next;
503825eb42bSJan Lentfer 		}
504825eb42bSJan Lentfer 	}
505825eb42bSJan Lentfer 	return NULL;
506825eb42bSJan Lentfer }
507825eb42bSJan Lentfer 
508825eb42bSJan Lentfer ldns_dnssec_rrsets *
ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone * zone,const ldns_rdf * dname,ldns_rr_type type)5095340022aSzrj ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
5105340022aSzrj 					   const ldns_rdf *dname,
511825eb42bSJan Lentfer 					   ldns_rr_type type)
512825eb42bSJan Lentfer {
513825eb42bSJan Lentfer 	ldns_rbnode_t *node;
514825eb42bSJan Lentfer 
5155340022aSzrj 	if (!zone || !dname || !zone->names) {
516825eb42bSJan Lentfer 		return NULL;
517825eb42bSJan Lentfer 	}
518825eb42bSJan Lentfer 
519825eb42bSJan Lentfer 	node = ldns_rbtree_search(zone->names, dname);
520825eb42bSJan Lentfer 	if (node) {
521825eb42bSJan Lentfer 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
522825eb42bSJan Lentfer 									type);
523825eb42bSJan Lentfer 	} else {
524825eb42bSJan Lentfer 		return NULL;
525825eb42bSJan Lentfer 	}
526825eb42bSJan Lentfer }
527825eb42bSJan Lentfer 
5285340022aSzrj static void
ldns_dnssec_name_print_soa_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name,bool show_soa)529b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
5305340022aSzrj 		const ldns_dnssec_name *name,
531b5dedccaSJan Lentfer 		bool show_soa)
532825eb42bSJan Lentfer {
533825eb42bSJan Lentfer 	if (name) {
534825eb42bSJan Lentfer 		if(name->rrsets) {
535b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
536b5dedccaSJan Lentfer 					name->rrsets, true, show_soa);
537b5dedccaSJan Lentfer 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
538825eb42bSJan Lentfer 			fprintf(out, ";; Empty nonterminal: ");
539825eb42bSJan Lentfer 			ldns_rdf_print(out, name->name);
540825eb42bSJan Lentfer 			fprintf(out, "\n");
541825eb42bSJan Lentfer 		}
542825eb42bSJan Lentfer 		if(name->nsec) {
543b5dedccaSJan Lentfer 			ldns_rr_print_fmt(out, fmt, name->nsec);
544825eb42bSJan Lentfer 		}
545825eb42bSJan Lentfer 		if (name->nsec_signatures) {
546b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt,
547b5dedccaSJan Lentfer 					name->nsec_signatures);
548825eb42bSJan Lentfer 		}
549b5dedccaSJan Lentfer 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
550b5dedccaSJan Lentfer 		fprintf(out, "; <void>\n");
551825eb42bSJan Lentfer 	}
552825eb42bSJan Lentfer }
553825eb42bSJan Lentfer 
554b5dedccaSJan Lentfer 
555b5dedccaSJan Lentfer void
ldns_dnssec_name_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name)556b5dedccaSJan Lentfer ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
5575340022aSzrj 		const ldns_dnssec_name *name)
558b5dedccaSJan Lentfer {
559b5dedccaSJan Lentfer 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
560b5dedccaSJan Lentfer }
561b5dedccaSJan Lentfer 
562b5dedccaSJan Lentfer void
ldns_dnssec_name_print(FILE * out,const ldns_dnssec_name * name)5635340022aSzrj ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
564825eb42bSJan Lentfer {
565b5dedccaSJan Lentfer 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
566825eb42bSJan Lentfer }
567825eb42bSJan Lentfer 
568b5dedccaSJan Lentfer 
569825eb42bSJan Lentfer ldns_dnssec_zone *
ldns_dnssec_zone_new(void)5705340022aSzrj ldns_dnssec_zone_new(void)
571825eb42bSJan Lentfer {
572825eb42bSJan Lentfer 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
573fd185f4dSJan Lentfer         if(!zone) return NULL;
574825eb42bSJan Lentfer 	zone->soa = NULL;
575825eb42bSJan Lentfer 	zone->names = NULL;
5765340022aSzrj 	zone->hashed_names = NULL;
5775340022aSzrj 	zone->_nsec3params = NULL;
578825eb42bSJan Lentfer 
579825eb42bSJan Lentfer 	return zone;
580825eb42bSJan Lentfer }
581825eb42bSJan Lentfer 
582d1b2b5caSJohn Marino static bool
rr_is_rrsig_covering(ldns_rr * rr,ldns_rr_type t)583d1b2b5caSJohn Marino rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
584d1b2b5caSJohn Marino {
585d1b2b5caSJohn Marino 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
586d1b2b5caSJohn Marino 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
587d1b2b5caSJohn Marino }
588d1b2b5caSJohn Marino 
589d1b2b5caSJohn Marino /* When the zone is first read into an list and then inserted into an
590d1b2b5caSJohn Marino  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
591d1b2b5caSJohn Marino  * to each other. Because ldns-verify-zone (the only program that uses this
592*ee791febSAntonio Huete Jimenez  * function) uses the rbtree mostly for sequential walking, this results
593d1b2b5caSJohn Marino  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
594d1b2b5caSJohn Marino  */
595d1b2b5caSJohn Marino #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
596d1b2b5caSJohn Marino 
5975340022aSzrj static ldns_status
5985340022aSzrj ldns_dnssec_zone_add_empty_nonterminals_nsec3(
5995340022aSzrj 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
6005340022aSzrj 
6015340022aSzrj static void
ldns_todo_nsec3_ents_node_free(ldns_rbnode_t * node,void * arg)6025340022aSzrj ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
6035340022aSzrj 	(void) arg;
6045340022aSzrj 	ldns_rdf_deep_free((ldns_rdf *)node->key);
6055340022aSzrj 	LDNS_FREE(node);
6065340022aSzrj }
6075340022aSzrj 
608*ee791febSAntonio Huete Jimenez ldns_status _ldns_rr_new_frm_fp_l_internal(ldns_rr **newrr, FILE *fp,
609*ee791febSAntonio Huete Jimenez 		uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev,
610*ee791febSAntonio Huete Jimenez 		int *line_nr, bool *explicit_ttl);
611*ee791febSAntonio Huete Jimenez 
612d1b2b5caSJohn Marino 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)6135340022aSzrj ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
614*ee791febSAntonio Huete Jimenez 		uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
615d1b2b5caSJohn Marino {
616d1b2b5caSJohn Marino 	ldns_rr* cur_rr;
617d1b2b5caSJohn Marino 	size_t i;
618d1b2b5caSJohn Marino 
619d1b2b5caSJohn Marino 	ldns_rdf *my_origin = NULL;
620d1b2b5caSJohn Marino 	ldns_rdf *my_prev = NULL;
621d1b2b5caSJohn Marino 
622d1b2b5caSJohn Marino 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
6235340022aSzrj 	/* NSEC3s may occur before the names they refer to. We must remember
6245340022aSzrj 	   them and add them to the name later on, after the name is read.
6255340022aSzrj 	   We track not yet  matching NSEC3s*n the todo_nsec3s list */
6265340022aSzrj 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
627d1b2b5caSJohn Marino 	/* when reading NSEC3s, there is a chance that we encounter nsecs
628d1b2b5caSJohn Marino 	   for empty nonterminals, whose nonterminals we cannot derive yet
6295340022aSzrj 	   because the needed information is to be read later.
6305340022aSzrj 
6315340022aSzrj 	   nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
6325340022aSzrj 	   hold the NSEC3s that still didn't have a matching name in the
6335340022aSzrj 	   zone tree, even after all names were read.  They can only match
634*ee791febSAntonio Huete Jimenez 	   after the zone is equipped with all the empty non terminals. */
6355340022aSzrj 	ldns_rbtree_t todo_nsec3_ents;
6365340022aSzrj 	ldns_rbnode_t *new_node;
637d1b2b5caSJohn Marino 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
638d1b2b5caSJohn Marino 
6395340022aSzrj 	ldns_status status;
640d1b2b5caSJohn Marino 
641d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
642d1b2b5caSJohn Marino 	ldns_zone* zone = NULL;
643d1b2b5caSJohn Marino #else
644*ee791febSAntonio Huete Jimenez 	ldns_rr  *prev_rr = NULL;
645*ee791febSAntonio Huete Jimenez 	uint32_t   my_ttl = default_ttl;
646*ee791febSAntonio Huete Jimenez 	/* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
647*ee791febSAntonio Huete Jimenez 	 * to the last explicitly stated values.'
648*ee791febSAntonio Huete Jimenez 	 */
649*ee791febSAntonio Huete Jimenez 	bool ttl_from_TTL = false;
650*ee791febSAntonio Huete Jimenez 	bool explicit_ttl = false;
651d1b2b5caSJohn Marino #endif
652d1b2b5caSJohn Marino 
6535340022aSzrj 	ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
654d1b2b5caSJohn Marino 
6555340022aSzrj #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
656*ee791febSAntonio Huete Jimenez 	status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
6575340022aSzrj 	if (status != LDNS_STATUS_OK)
6585340022aSzrj 		goto error;
6595340022aSzrj #endif
6605340022aSzrj 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
6615340022aSzrj 		status = LDNS_STATUS_MEM_ERR;
6625340022aSzrj 		goto error;
6635340022aSzrj 	}
664d1b2b5caSJohn Marino 	if (origin) {
6655340022aSzrj 		if (!(my_origin = ldns_rdf_clone(origin))) {
6665340022aSzrj 			status = LDNS_STATUS_MEM_ERR;
6675340022aSzrj 			goto error;
6685340022aSzrj 		}
6695340022aSzrj 		if (!(my_prev   = ldns_rdf_clone(origin))) {
6705340022aSzrj 			status = LDNS_STATUS_MEM_ERR;
6715340022aSzrj 			goto error;
6725340022aSzrj 		}
673d1b2b5caSJohn Marino 	}
674d1b2b5caSJohn Marino 
675d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
6765340022aSzrj 	if (ldns_zone_soa(zone)) {
6775340022aSzrj 		status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
6785340022aSzrj 		if (status != LDNS_STATUS_OK)
6795340022aSzrj 			goto error;
6805340022aSzrj 	}
681d1b2b5caSJohn Marino 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
682d1b2b5caSJohn Marino 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
683d1b2b5caSJohn Marino 		status = LDNS_STATUS_OK;
684d1b2b5caSJohn Marino #else
685d1b2b5caSJohn Marino 	while (!feof(fp)) {
686*ee791febSAntonio Huete Jimenez 		/* If ttl came from $TTL line, then it should be the default.
687*ee791febSAntonio Huete Jimenez 		 * (RFC 2308 Section 4)
688*ee791febSAntonio Huete Jimenez 		 * Otherwise it "defaults to the last explicitly stated value"
689*ee791febSAntonio Huete Jimenez 		 * (RFC 1035 Section 5.1)
690*ee791febSAntonio Huete Jimenez 		 */
691*ee791febSAntonio Huete Jimenez 		if (ttl_from_TTL)
692*ee791febSAntonio Huete Jimenez 			my_ttl = default_ttl;
693d1b2b5caSJohn Marino 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
694*ee791febSAntonio Huete Jimenez 				&my_prev, line_nr, &explicit_ttl);
695d1b2b5caSJohn Marino #endif
696d1b2b5caSJohn Marino 		switch (status) {
697d1b2b5caSJohn Marino 		case LDNS_STATUS_OK:
698*ee791febSAntonio Huete Jimenez #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
699*ee791febSAntonio Huete Jimenez 			if (explicit_ttl) {
700*ee791febSAntonio Huete Jimenez 				if (!ttl_from_TTL) {
701*ee791febSAntonio Huete Jimenez 					/* No $TTL, so ttl "defaults to the
702*ee791febSAntonio Huete Jimenez 					 * last explicitly stated value"
703*ee791febSAntonio Huete Jimenez 					 * (RFC 1035 Section 5.1)
704*ee791febSAntonio Huete Jimenez 					 */
705*ee791febSAntonio Huete Jimenez 					my_ttl = ldns_rr_ttl(cur_rr);
706*ee791febSAntonio Huete Jimenez 				}
707*ee791febSAntonio Huete Jimenez 			/* When ttl is implicit, try to adhere to the rules as
708*ee791febSAntonio Huete Jimenez 			 * much as possible. (also for compatibility with bind)
709*ee791febSAntonio Huete Jimenez 			 * This was changed when fixing an issue with ZONEMD
710*ee791febSAntonio Huete Jimenez 			 * which hashes the TTL too.
711*ee791febSAntonio Huete Jimenez 			 */
712*ee791febSAntonio Huete Jimenez 			} else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
713*ee791febSAntonio Huete Jimenez 			       ||  ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
714*ee791febSAntonio Huete Jimenez 				if (ldns_rr_rd_count(cur_rr) >= 4
715*ee791febSAntonio Huete Jimenez 				&&  ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32)
716d1b2b5caSJohn Marino 
717*ee791febSAntonio Huete Jimenez 					/* SIG without explicit ttl get ttl
718*ee791febSAntonio Huete Jimenez 					 * from the original_ttl field
719*ee791febSAntonio Huete Jimenez 					 * (RFC 2535 Section 7.2)
720*ee791febSAntonio Huete Jimenez 					 *
721*ee791febSAntonio Huete Jimenez 					 * Similarly for RRSIG, but stated less
722*ee791febSAntonio Huete Jimenez 					 * specifically in the spec.
723*ee791febSAntonio Huete Jimenez 					 * (RFC 4034 Section 3)
724*ee791febSAntonio Huete Jimenez 					 */
725*ee791febSAntonio Huete Jimenez 					ldns_rr_set_ttl(cur_rr,
726*ee791febSAntonio Huete Jimenez 					    ldns_rdf2native_int32(
727*ee791febSAntonio Huete Jimenez 					        ldns_rr_rdf(rr, 3)));
728*ee791febSAntonio Huete Jimenez 
729*ee791febSAntonio Huete Jimenez 			} else if (prev_rr
730*ee791febSAntonio Huete Jimenez 			       &&  ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
731*ee791febSAntonio Huete Jimenez 			       &&  ldns_dname_compare( ldns_rr_owner(prev_rr)
732*ee791febSAntonio Huete Jimenez 			                             , ldns_rr_owner(cur_rr)) == 0)
733*ee791febSAntonio Huete Jimenez 
734*ee791febSAntonio Huete Jimenez 				/* "TTLs of all RRs in an RRSet must be the same"
735*ee791febSAntonio Huete Jimenez 				 * (RFC 2881 Section 5.2)
736*ee791febSAntonio Huete Jimenez 				 */
737*ee791febSAntonio Huete Jimenez 				ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
738*ee791febSAntonio Huete Jimenez 
739*ee791febSAntonio Huete Jimenez 			prev_rr = cur_rr;
740*ee791febSAntonio Huete Jimenez #endif
741d1b2b5caSJohn Marino 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
742d1b2b5caSJohn Marino 			if (status ==
743d1b2b5caSJohn Marino 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
744d1b2b5caSJohn Marino 
745d1b2b5caSJohn Marino 				if (rr_is_rrsig_covering(cur_rr,
746d1b2b5caSJohn Marino 							LDNS_RR_TYPE_NSEC3)){
747d1b2b5caSJohn Marino 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
748d1b2b5caSJohn Marino 							cur_rr);
749d1b2b5caSJohn Marino 				} else {
750d1b2b5caSJohn Marino 					ldns_rr_list_push_rr(todo_nsec3s,
751d1b2b5caSJohn Marino 						       	cur_rr);
752d1b2b5caSJohn Marino 				}
7535340022aSzrj 				status = LDNS_STATUS_OK;
7545340022aSzrj 
755d1b2b5caSJohn Marino 			} else if (status != LDNS_STATUS_OK)
756d1b2b5caSJohn Marino 				goto error;
757d1b2b5caSJohn Marino 
758d1b2b5caSJohn Marino 			break;
759d1b2b5caSJohn Marino 
760*ee791febSAntonio Huete Jimenez 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
761*ee791febSAntonio Huete Jimenez #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
762*ee791febSAntonio Huete Jimenez 			default_ttl = my_ttl;
763*ee791febSAntonio Huete Jimenez 			ttl_from_TTL = true;
764*ee791febSAntonio Huete Jimenez #endif
765*ee791febSAntonio Huete Jimenez 			status = LDNS_STATUS_OK;
766*ee791febSAntonio Huete Jimenez 			break;
767*ee791febSAntonio Huete Jimenez 
768d1b2b5caSJohn Marino 
769d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
770d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
771d1b2b5caSJohn Marino 			status = LDNS_STATUS_OK;
772d1b2b5caSJohn Marino 			break;
773d1b2b5caSJohn Marino 
774d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
775d1b2b5caSJohn Marino 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
776d1b2b5caSJohn Marino 			break;
777d1b2b5caSJohn Marino 
778d1b2b5caSJohn Marino 		default:
779d1b2b5caSJohn Marino 			goto error;
780d1b2b5caSJohn Marino 		}
781d1b2b5caSJohn Marino 	}
782d1b2b5caSJohn Marino 
783d1b2b5caSJohn Marino 	for (i = 0; status == LDNS_STATUS_OK &&
784d1b2b5caSJohn Marino 			i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
785d1b2b5caSJohn Marino 		cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
786d1b2b5caSJohn Marino 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
7875340022aSzrj 		if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
7885340022aSzrj 			if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
7895340022aSzrj 				status = LDNS_STATUS_MEM_ERR;
7905340022aSzrj 				break;
791d1b2b5caSJohn Marino 			}
7925340022aSzrj 			new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
7935340022aSzrj 			new_node->data = cur_rr;
7945340022aSzrj 			if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
7955340022aSzrj 				LDNS_FREE(new_node);
7965340022aSzrj 				status = LDNS_STATUS_MEM_ERR;
7975340022aSzrj 				break;
7985340022aSzrj 			}
7995340022aSzrj 			status = LDNS_STATUS_OK;
8005340022aSzrj 		}
8015340022aSzrj 	}
8025340022aSzrj 	if (todo_nsec3_ents.count > 0)
8035340022aSzrj 		(void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
8045340022aSzrj 				newzone, &todo_nsec3_ents);
805d1b2b5caSJohn Marino 	for (i = 0; status == LDNS_STATUS_OK &&
8065340022aSzrj 			i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
807d1b2b5caSJohn Marino 		cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
808d1b2b5caSJohn Marino 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
809d1b2b5caSJohn Marino 	}
810d1b2b5caSJohn Marino 	if (z) {
811d1b2b5caSJohn Marino 		*z = newzone;
812d1b2b5caSJohn Marino 		newzone = NULL;
813d1b2b5caSJohn Marino 	} else {
814d1b2b5caSJohn Marino 		ldns_dnssec_zone_free(newzone);
815819dec71SDaniel Fojt 		newzone = NULL;
816d1b2b5caSJohn Marino 	}
817d1b2b5caSJohn Marino 
818d1b2b5caSJohn Marino error:
819d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
820d1b2b5caSJohn Marino 	if (zone) {
821d1b2b5caSJohn Marino 		ldns_zone_free(zone);
822d1b2b5caSJohn Marino 	}
823d1b2b5caSJohn Marino #endif
824d1b2b5caSJohn Marino 	ldns_rr_list_free(todo_nsec3_rrsigs);
8255340022aSzrj 	ldns_traverse_postorder(&todo_nsec3_ents,
8265340022aSzrj 			ldns_todo_nsec3_ents_node_free, NULL);
827d1b2b5caSJohn Marino 	ldns_rr_list_free(todo_nsec3s);
828d1b2b5caSJohn Marino 
829d1b2b5caSJohn Marino 	if (my_origin) {
830d1b2b5caSJohn Marino 		ldns_rdf_deep_free(my_origin);
831d1b2b5caSJohn Marino 	}
832d1b2b5caSJohn Marino 	if (my_prev) {
833d1b2b5caSJohn Marino 		ldns_rdf_deep_free(my_prev);
834d1b2b5caSJohn Marino 	}
835d1b2b5caSJohn Marino 	if (newzone) {
836d1b2b5caSJohn Marino 		ldns_dnssec_zone_free(newzone);
837d1b2b5caSJohn Marino 	}
838d1b2b5caSJohn Marino 	return status;
839d1b2b5caSJohn Marino }
840d1b2b5caSJohn Marino 
841d1b2b5caSJohn Marino ldns_status
8425340022aSzrj ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
843d1b2b5caSJohn Marino 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
844d1b2b5caSJohn Marino {
845d1b2b5caSJohn Marino 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
846d1b2b5caSJohn Marino }
847d1b2b5caSJohn Marino 
8485340022aSzrj static void
849825eb42bSJan Lentfer ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
850825eb42bSJan Lentfer 	(void) arg;
851825eb42bSJan Lentfer 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
852d1b2b5caSJohn Marino 	LDNS_FREE(node);
853825eb42bSJan Lentfer }
854825eb42bSJan Lentfer 
8555340022aSzrj static void
856825eb42bSJan Lentfer ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
857825eb42bSJan Lentfer 	(void) arg;
858825eb42bSJan Lentfer 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
859d1b2b5caSJohn Marino 	LDNS_FREE(node);
860825eb42bSJan Lentfer }
861825eb42bSJan Lentfer 
862*ee791febSAntonio Huete Jimenez static void
863*ee791febSAntonio Huete Jimenez ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
864*ee791febSAntonio Huete Jimenez 	(void) arg;
865*ee791febSAntonio Huete Jimenez 	LDNS_FREE(node);
866*ee791febSAntonio Huete Jimenez }
867*ee791febSAntonio Huete Jimenez 
868825eb42bSJan Lentfer void
869825eb42bSJan Lentfer ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
870825eb42bSJan Lentfer {
871825eb42bSJan Lentfer 	if (zone) {
872*ee791febSAntonio Huete Jimenez 		if (zone->hashed_names) {
873*ee791febSAntonio Huete Jimenez 			ldns_traverse_postorder(zone->hashed_names,
874*ee791febSAntonio Huete Jimenez 					ldns_hashed_names_node_free, NULL);
875*ee791febSAntonio Huete Jimenez 			LDNS_FREE(zone->hashed_names);
876*ee791febSAntonio Huete Jimenez 		}
877825eb42bSJan Lentfer 		if (zone->names) {
878825eb42bSJan Lentfer 			/* destroy all name structures within the tree */
879825eb42bSJan Lentfer 			ldns_traverse_postorder(zone->names,
880825eb42bSJan Lentfer 						    ldns_dnssec_name_node_free,
881825eb42bSJan Lentfer 						    NULL);
882d1b2b5caSJohn Marino 			LDNS_FREE(zone->names);
883825eb42bSJan Lentfer 		}
884825eb42bSJan Lentfer 		LDNS_FREE(zone);
885825eb42bSJan Lentfer 	}
886825eb42bSJan Lentfer }
887825eb42bSJan Lentfer 
888825eb42bSJan Lentfer void
889825eb42bSJan Lentfer ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
890825eb42bSJan Lentfer {
891825eb42bSJan Lentfer 	if (zone) {
892*ee791febSAntonio Huete Jimenez 		if (zone->hashed_names) {
893*ee791febSAntonio Huete Jimenez 			ldns_traverse_postorder(zone->hashed_names,
894*ee791febSAntonio Huete Jimenez 					ldns_hashed_names_node_free, NULL);
895*ee791febSAntonio Huete Jimenez 			LDNS_FREE(zone->hashed_names);
896*ee791febSAntonio Huete Jimenez 		}
897825eb42bSJan Lentfer 		if (zone->names) {
898825eb42bSJan Lentfer 			/* destroy all name structures within the tree */
899825eb42bSJan Lentfer 			ldns_traverse_postorder(zone->names,
900825eb42bSJan Lentfer 						    ldns_dnssec_name_node_deep_free,
901825eb42bSJan Lentfer 						    NULL);
902d1b2b5caSJohn Marino 			LDNS_FREE(zone->names);
903825eb42bSJan Lentfer 		}
904825eb42bSJan Lentfer 		LDNS_FREE(zone);
905825eb42bSJan Lentfer 	}
906825eb42bSJan Lentfer }
907825eb42bSJan Lentfer 
908825eb42bSJan Lentfer /* use for dname comparison in tree */
909825eb42bSJan Lentfer int
910825eb42bSJan Lentfer ldns_dname_compare_v(const void *a, const void *b) {
911825eb42bSJan Lentfer 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
912825eb42bSJan Lentfer }
913825eb42bSJan Lentfer 
9145340022aSzrj static void
9155340022aSzrj ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
9165340022aSzrj 		ldns_dnssec_name* name, ldns_rr* nsec3rr);
9175340022aSzrj 
9185340022aSzrj static void
9195340022aSzrj ldns_dnssec_zone_hashed_names_from_nsec3(
9205340022aSzrj 		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
9215340022aSzrj {
9225340022aSzrj 	ldns_rbnode_t* current_node;
923825eb42bSJan Lentfer 	ldns_dnssec_name* current_name;
9245340022aSzrj 
9255340022aSzrj 	assert(zone != NULL);
9265340022aSzrj 	assert(nsec3rr != NULL);
9275340022aSzrj 
9285340022aSzrj 	if (zone->hashed_names) {
9295340022aSzrj 		ldns_traverse_postorder(zone->hashed_names,
9305340022aSzrj 				ldns_hashed_names_node_free, NULL);
9315340022aSzrj 		LDNS_FREE(zone->hashed_names);
9325340022aSzrj 	}
9335340022aSzrj 	zone->_nsec3params = nsec3rr;
9345340022aSzrj 
9355340022aSzrj 	/* So this is a NSEC3 zone.
9365340022aSzrj 	* Calculate hashes for all names already in the zone
9375340022aSzrj 	*/
9385340022aSzrj 	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
9395340022aSzrj 	if (zone->hashed_names == NULL) {
9405340022aSzrj 		return;
9415340022aSzrj 	}
9425340022aSzrj 	for ( current_node  = ldns_rbtree_first(zone->names)
9435340022aSzrj 	    ; current_node != LDNS_RBTREE_NULL
9445340022aSzrj 	    ; current_node  = ldns_rbtree_next(current_node)
9455340022aSzrj 	    ) {
9465340022aSzrj 		current_name = (ldns_dnssec_name *) current_node->data;
9475340022aSzrj 		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
9485340022aSzrj 
9495340022aSzrj 	}
9505340022aSzrj }
9515340022aSzrj 
9525340022aSzrj static void
9535340022aSzrj ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
9545340022aSzrj 		ldns_dnssec_name* name, ldns_rr* nsec3rr)
9555340022aSzrj {
9565340022aSzrj 	ldns_rbnode_t* new_node;
9575340022aSzrj 
9585340022aSzrj 	assert(name != NULL);
9595340022aSzrj 	if (! zone->_nsec3params) {
9605340022aSzrj 		if (! nsec3rr) {
9615340022aSzrj 			return;
9625340022aSzrj 		}
9635340022aSzrj 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
9645340022aSzrj 
9655340022aSzrj 	} else if (! nsec3rr) {
9665340022aSzrj 		nsec3rr = zone->_nsec3params;
9675340022aSzrj 	}
9685340022aSzrj 	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
9695340022aSzrj 
9705340022aSzrj 	/* Also store in zone->hashed_names */
9715340022aSzrj 	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
9725340022aSzrj 
9735340022aSzrj 		new_node->key  = name->hashed_name;
9745340022aSzrj 		new_node->data = name;
9755340022aSzrj 
9765340022aSzrj 		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
9775340022aSzrj 
9785340022aSzrj 				LDNS_FREE(new_node);
9795340022aSzrj 		}
9805340022aSzrj 	}
9815340022aSzrj }
9825340022aSzrj 
9835340022aSzrj 
9845340022aSzrj static ldns_rbnode_t *
9855340022aSzrj ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
986825eb42bSJan Lentfer 	ldns_rdf *hashed_name;
987*ee791febSAntonio Huete Jimenez 	ldns_rbnode_t *to_return;
988825eb42bSJan Lentfer 
9895340022aSzrj 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
990825eb42bSJan Lentfer 
9915340022aSzrj 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
992825eb42bSJan Lentfer 	}
9935340022aSzrj 	if (zone->hashed_names == NULL) {
994825eb42bSJan Lentfer 		return NULL;
995825eb42bSJan Lentfer 	}
996*ee791febSAntonio Huete Jimenez 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
997*ee791febSAntonio Huete Jimenez 	if (hashed_name == NULL) {
998*ee791febSAntonio Huete Jimenez 		return NULL;
999*ee791febSAntonio Huete Jimenez 	}
1000*ee791febSAntonio Huete Jimenez 	to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
1001*ee791febSAntonio Huete Jimenez 	ldns_rdf_deep_free(hashed_name);
1002*ee791febSAntonio Huete Jimenez 	return to_return;
10035340022aSzrj }
1004825eb42bSJan Lentfer 
1005825eb42bSJan Lentfer ldns_status
1006825eb42bSJan Lentfer ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
1007825eb42bSJan Lentfer {
1008825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
1009825eb42bSJan Lentfer 	ldns_dnssec_name *cur_name;
1010825eb42bSJan Lentfer 	ldns_rbnode_t *cur_node;
1011825eb42bSJan Lentfer 	ldns_rr_type type_covered = 0;
1012825eb42bSJan Lentfer 
1013825eb42bSJan Lentfer 	if (!zone || !rr) {
1014825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1015825eb42bSJan Lentfer 	}
1016825eb42bSJan Lentfer 
1017825eb42bSJan Lentfer 	if (!zone->names) {
1018825eb42bSJan Lentfer 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1019fd185f4dSJan Lentfer                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1020825eb42bSJan Lentfer 	}
1021825eb42bSJan Lentfer 
1022825eb42bSJan Lentfer 	/* we need the original of the hashed name if this is
1023825eb42bSJan Lentfer 	   an NSEC3, or an RRSIG that covers an NSEC3 */
1024825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
1025825eb42bSJan Lentfer 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1026825eb42bSJan Lentfer 	}
1027825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
1028825eb42bSJan Lentfer 	    type_covered == LDNS_RR_TYPE_NSEC3) {
10295340022aSzrj 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1030825eb42bSJan Lentfer 		if (!cur_node) {
1031825eb42bSJan Lentfer 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
1032825eb42bSJan Lentfer 		}
1033825eb42bSJan Lentfer 	} else {
1034825eb42bSJan Lentfer 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1035825eb42bSJan Lentfer 	}
1036825eb42bSJan Lentfer 	if (!cur_node) {
1037825eb42bSJan Lentfer 		/* add */
1038825eb42bSJan Lentfer 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
1039fd185f4dSJan Lentfer                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1040825eb42bSJan Lentfer 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
1041fd185f4dSJan Lentfer                 if(!cur_node) {
1042fd185f4dSJan Lentfer                         ldns_dnssec_name_free(cur_name);
1043fd185f4dSJan Lentfer                         return LDNS_STATUS_MEM_ERR;
1044fd185f4dSJan Lentfer                 }
1045825eb42bSJan Lentfer 		cur_node->key = ldns_rr_owner(rr);
1046825eb42bSJan Lentfer 		cur_node->data = cur_name;
1047fd185f4dSJan Lentfer 		(void)ldns_rbtree_insert(zone->names, cur_node);
10485340022aSzrj 		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1049825eb42bSJan Lentfer 	} else {
1050825eb42bSJan Lentfer 		cur_name = (ldns_dnssec_name *) cur_node->data;
1051fd185f4dSJan Lentfer 		result = ldns_dnssec_name_add_rr(cur_name, rr);
1052825eb42bSJan Lentfer 	}
1053825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1054825eb42bSJan Lentfer 		zone->soa = cur_name;
1055825eb42bSJan Lentfer 	}
1056825eb42bSJan Lentfer 	return result;
1057825eb42bSJan Lentfer }
1058825eb42bSJan Lentfer 
1059825eb42bSJan Lentfer void
1060b5dedccaSJan Lentfer ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
10615340022aSzrj 		const ldns_rbtree_t *tree,
1062b5dedccaSJan Lentfer 		bool print_soa)
1063825eb42bSJan Lentfer {
1064825eb42bSJan Lentfer 	ldns_rbnode_t *node;
1065825eb42bSJan Lentfer 	ldns_dnssec_name *name;
1066825eb42bSJan Lentfer 
1067825eb42bSJan Lentfer 	node = ldns_rbtree_first(tree);
1068825eb42bSJan Lentfer 	while (node != LDNS_RBTREE_NULL) {
1069825eb42bSJan Lentfer 		name = (ldns_dnssec_name *) node->data;
1070b5dedccaSJan Lentfer 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1071b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1072825eb42bSJan Lentfer 			fprintf(out, ";\n");
1073825eb42bSJan Lentfer 		node = ldns_rbtree_next(node);
1074825eb42bSJan Lentfer 	}
1075825eb42bSJan Lentfer }
1076825eb42bSJan Lentfer 
1077825eb42bSJan Lentfer void
10785340022aSzrj ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1079b5dedccaSJan Lentfer {
1080b5dedccaSJan Lentfer 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1081b5dedccaSJan Lentfer 		       tree, print_soa);
1082b5dedccaSJan Lentfer }
1083b5dedccaSJan Lentfer 
1084b5dedccaSJan Lentfer void
1085b5dedccaSJan Lentfer ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
10865340022aSzrj 	       const ldns_dnssec_zone *zone)
1087825eb42bSJan Lentfer {
1088825eb42bSJan Lentfer 	if (zone) {
1089825eb42bSJan Lentfer 		if (zone->soa) {
1090b5dedccaSJan Lentfer 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1091825eb42bSJan Lentfer 				fprintf(out, ";; Zone: ");
1092b5dedccaSJan Lentfer 				ldns_rdf_print(out, ldns_dnssec_name_name(
1093b5dedccaSJan Lentfer 							zone->soa));
1094825eb42bSJan Lentfer 				fprintf(out, "\n;\n");
1095b5dedccaSJan Lentfer 			}
1096b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_fmt(out, fmt,
1097b5dedccaSJan Lentfer 					ldns_dnssec_name_find_rrset(
1098b5dedccaSJan Lentfer 						zone->soa,
1099825eb42bSJan Lentfer 						LDNS_RR_TYPE_SOA),
1100825eb42bSJan Lentfer 					false);
1101b5dedccaSJan Lentfer 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1102825eb42bSJan Lentfer 				fprintf(out, ";\n");
1103825eb42bSJan Lentfer 		}
1104825eb42bSJan Lentfer 
1105825eb42bSJan Lentfer 		if (zone->names) {
1106b5dedccaSJan Lentfer 			ldns_dnssec_zone_names_print_fmt(out, fmt,
1107b5dedccaSJan Lentfer 					zone->names, false);
1108825eb42bSJan Lentfer 		}
1109825eb42bSJan Lentfer 	}
1110825eb42bSJan Lentfer }
1111825eb42bSJan Lentfer 
1112b5dedccaSJan Lentfer void
11135340022aSzrj ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1114b5dedccaSJan Lentfer {
1115b5dedccaSJan Lentfer 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1116b5dedccaSJan Lentfer }
1117b5dedccaSJan Lentfer 
11185340022aSzrj static ldns_status
11195340022aSzrj ldns_dnssec_zone_add_empty_nonterminals_nsec3(
11205340022aSzrj 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1121825eb42bSJan Lentfer {
1122825eb42bSJan Lentfer 	ldns_dnssec_name *new_name;
1123825eb42bSJan Lentfer 	ldns_rdf *cur_name;
1124825eb42bSJan Lentfer 	ldns_rdf *next_name;
1125825eb42bSJan Lentfer 	ldns_rbnode_t *cur_node, *next_node, *new_node;
1126825eb42bSJan Lentfer 
1127825eb42bSJan Lentfer 	/* for the detection */
1128825eb42bSJan Lentfer 	uint16_t i, cur_label_count, next_label_count;
1129825eb42bSJan Lentfer 	uint16_t soa_label_count = 0;
1130825eb42bSJan Lentfer 	ldns_rdf *l1, *l2;
1131825eb42bSJan Lentfer 	int lpos;
1132825eb42bSJan Lentfer 
1133825eb42bSJan Lentfer 	if (!zone) {
1134825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
1135825eb42bSJan Lentfer 	}
1136825eb42bSJan Lentfer 	if (zone->soa && zone->soa->name) {
1137825eb42bSJan Lentfer 		soa_label_count = ldns_dname_label_count(zone->soa->name);
1138825eb42bSJan Lentfer 	}
1139825eb42bSJan Lentfer 
1140825eb42bSJan Lentfer 	cur_node = ldns_rbtree_first(zone->names);
1141825eb42bSJan Lentfer 	while (cur_node != LDNS_RBTREE_NULL) {
1142825eb42bSJan Lentfer 		next_node = ldns_rbtree_next(cur_node);
1143825eb42bSJan Lentfer 
1144825eb42bSJan Lentfer 		/* skip glue */
1145825eb42bSJan Lentfer 		while (next_node != LDNS_RBTREE_NULL &&
1146825eb42bSJan Lentfer 		       next_node->data &&
1147825eb42bSJan Lentfer 		       ((ldns_dnssec_name *)next_node->data)->is_glue
1148825eb42bSJan Lentfer 		) {
1149825eb42bSJan Lentfer 			next_node = ldns_rbtree_next(next_node);
1150825eb42bSJan Lentfer 		}
1151825eb42bSJan Lentfer 
1152825eb42bSJan Lentfer 		if (next_node == LDNS_RBTREE_NULL) {
1153825eb42bSJan Lentfer 			next_node = ldns_rbtree_first(zone->names);
1154825eb42bSJan Lentfer 		}
1155d1b2b5caSJohn Marino 		if (! cur_node->data || ! next_node->data) {
1156d1b2b5caSJohn Marino 			return LDNS_STATUS_ERR;
1157d1b2b5caSJohn Marino 		}
1158825eb42bSJan Lentfer 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1159825eb42bSJan Lentfer 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
1160825eb42bSJan Lentfer 		cur_label_count = ldns_dname_label_count(cur_name);
1161825eb42bSJan Lentfer 		next_label_count = ldns_dname_label_count(next_name);
1162825eb42bSJan Lentfer 
1163825eb42bSJan Lentfer 		/* Since the names are in canonical order, we can
1164825eb42bSJan Lentfer 		 * recognize empty non-terminals by their labels;
1165825eb42bSJan Lentfer 		 * every label after the first one on the next owner
1166825eb42bSJan Lentfer 		 * name is a non-terminal if it either does not exist
1167825eb42bSJan Lentfer 		 * in the current name or is different from the same
1168825eb42bSJan Lentfer 		 * label in the current name (counting from the end)
1169825eb42bSJan Lentfer 		 */
1170825eb42bSJan Lentfer 		for (i = 1; i < next_label_count - soa_label_count; i++) {
1171fd185f4dSJan Lentfer 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1172825eb42bSJan Lentfer 			if (lpos >= 0) {
1173b5dedccaSJan Lentfer 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1174825eb42bSJan Lentfer 			} else {
1175825eb42bSJan Lentfer 				l1 = NULL;
1176825eb42bSJan Lentfer 			}
1177b5dedccaSJan Lentfer 			l2 = ldns_dname_clone_from(next_name, i);
1178825eb42bSJan Lentfer 
1179825eb42bSJan Lentfer 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1180825eb42bSJan Lentfer 				/* We have an empty nonterminal, add it to the
1181825eb42bSJan Lentfer 				 * tree
1182825eb42bSJan Lentfer 				 */
11835340022aSzrj 				ldns_rbnode_t *node = NULL;
11845340022aSzrj 				ldns_rdf *ent_name;
11855340022aSzrj 
11865340022aSzrj 				if (!(ent_name = ldns_dname_clone_from(
1187819dec71SDaniel Fojt 						next_name, i))) {
1188819dec71SDaniel Fojt 
1189819dec71SDaniel Fojt 					ldns_rdf_deep_free(l1);
1190819dec71SDaniel Fojt 					ldns_rdf_deep_free(l2);
11915340022aSzrj 					return LDNS_STATUS_MEM_ERR;
1192819dec71SDaniel Fojt 				}
11935340022aSzrj 
11945340022aSzrj 				if (nsec3s && zone->_nsec3params) {
11955340022aSzrj 					ldns_rdf *ent_hashed_name;
11965340022aSzrj 
11975340022aSzrj 					if (!(ent_hashed_name =
11985340022aSzrj 					    ldns_nsec3_hash_name_frm_nsec3(
11995340022aSzrj 							zone->_nsec3params,
1200819dec71SDaniel Fojt 							ent_name))) {
1201819dec71SDaniel Fojt 						ldns_rdf_deep_free(l1);
1202819dec71SDaniel Fojt 						ldns_rdf_deep_free(l2);
1203819dec71SDaniel Fojt 						ldns_rdf_deep_free(ent_name);
12045340022aSzrj 						return LDNS_STATUS_MEM_ERR;
1205819dec71SDaniel Fojt 					}
12065340022aSzrj 					node = ldns_rbtree_search(nsec3s,
12075340022aSzrj 							ent_hashed_name);
1208*ee791febSAntonio Huete Jimenez 					ldns_rdf_deep_free(ent_hashed_name);
12095340022aSzrj 					if (!node) {
12105340022aSzrj 						ldns_rdf_deep_free(l1);
12115340022aSzrj 						ldns_rdf_deep_free(l2);
1212819dec71SDaniel Fojt 						ldns_rdf_deep_free(ent_name);
12135340022aSzrj 						continue;
12145340022aSzrj 					}
12155340022aSzrj 				}
1216825eb42bSJan Lentfer 				new_name = ldns_dnssec_name_new();
1217825eb42bSJan Lentfer 				if (!new_name) {
1218819dec71SDaniel Fojt 					ldns_rdf_deep_free(l1);
1219819dec71SDaniel Fojt 					ldns_rdf_deep_free(l2);
1220819dec71SDaniel Fojt 					ldns_rdf_deep_free(ent_name);
1221825eb42bSJan Lentfer 					return LDNS_STATUS_MEM_ERR;
1222825eb42bSJan Lentfer 				}
12235340022aSzrj 				new_name->name = ent_name;
1224825eb42bSJan Lentfer 				new_name->name_alloced = true;
1225825eb42bSJan Lentfer 				new_node = LDNS_MALLOC(ldns_rbnode_t);
1226825eb42bSJan Lentfer 				if (!new_node) {
1227819dec71SDaniel Fojt 					ldns_rdf_deep_free(l1);
1228819dec71SDaniel Fojt 					ldns_rdf_deep_free(l2);
1229825eb42bSJan Lentfer 					ldns_dnssec_name_free(new_name);
1230825eb42bSJan Lentfer 					return LDNS_STATUS_MEM_ERR;
1231825eb42bSJan Lentfer 				}
1232825eb42bSJan Lentfer 				new_node->key = new_name->name;
1233825eb42bSJan Lentfer 				new_node->data = new_name;
1234fd185f4dSJan Lentfer 				(void)ldns_rbtree_insert(zone->names, new_node);
12355340022aSzrj 				ldns_dnssec_name_make_hashed_name(
12365340022aSzrj 						zone, new_name, NULL);
12375340022aSzrj 				if (node)
12385340022aSzrj 					(void) ldns_dnssec_zone_add_rr(zone,
12395340022aSzrj 							(ldns_rr *)node->data);
1240825eb42bSJan Lentfer 			}
1241825eb42bSJan Lentfer 			ldns_rdf_deep_free(l1);
1242825eb42bSJan Lentfer 			ldns_rdf_deep_free(l2);
1243825eb42bSJan Lentfer 		}
1244825eb42bSJan Lentfer 
1245825eb42bSJan Lentfer 		/* we might have inserted a new node after
1246825eb42bSJan Lentfer 		 * the current one so we can't just use next()
1247825eb42bSJan Lentfer 		 */
1248825eb42bSJan Lentfer 		if (next_node != ldns_rbtree_first(zone->names)) {
1249825eb42bSJan Lentfer 			cur_node = next_node;
1250825eb42bSJan Lentfer 		} else {
1251825eb42bSJan Lentfer 			cur_node = LDNS_RBTREE_NULL;
1252825eb42bSJan Lentfer 		}
1253825eb42bSJan Lentfer 	}
1254825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
1255825eb42bSJan Lentfer }
1256d1b2b5caSJohn Marino 
12575340022aSzrj ldns_status
12585340022aSzrj ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
12595340022aSzrj {
12605340022aSzrj 	return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
12615340022aSzrj }
12625340022aSzrj 
1263d1b2b5caSJohn Marino bool
12645340022aSzrj ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1265d1b2b5caSJohn Marino {
1266d1b2b5caSJohn Marino 	ldns_rr* nsec3;
1267d1b2b5caSJohn Marino 	ldns_rbnode_t* node;
1268d1b2b5caSJohn Marino 
1269d1b2b5caSJohn Marino 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1270d1b2b5caSJohn Marino 		node = ldns_rbtree_first(zone->names);
1271d1b2b5caSJohn Marino 		while (node != LDNS_RBTREE_NULL) {
1272d1b2b5caSJohn Marino 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1273d1b2b5caSJohn Marino 			if (nsec3 &&ldns_rr_get_type(nsec3)
1274d1b2b5caSJohn Marino 					== LDNS_RR_TYPE_NSEC3 &&
1275d1b2b5caSJohn Marino 					ldns_nsec3_optout(nsec3)) {
1276d1b2b5caSJohn Marino 				return true;
1277d1b2b5caSJohn Marino 			}
1278d1b2b5caSJohn Marino 			node = ldns_rbtree_next(node);
1279d1b2b5caSJohn Marino 		}
1280d1b2b5caSJohn Marino 	}
1281d1b2b5caSJohn Marino 	return false;
1282d1b2b5caSJohn Marino }
1283*ee791febSAntonio Huete Jimenez 
1284*ee791febSAntonio Huete Jimenez /*
1285*ee791febSAntonio Huete Jimenez  * Stuff for calculating and verifying zone digests
1286*ee791febSAntonio Huete Jimenez  */
1287*ee791febSAntonio Huete Jimenez typedef enum dnssec_zone_rr_iter_state {
1288*ee791febSAntonio Huete Jimenez 	  DNSSEC_ZONE_RR_ITER_LT_RRSIG
1289*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1290*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_REST
1291*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
1292*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
1293*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_NSEC3
1294*ee791febSAntonio Huete Jimenez 	, DNSSEC_ZONE_RR_ITER_FINI
1295*ee791febSAntonio Huete Jimenez } dnssec_zone_rr_iter_state;
1296*ee791febSAntonio Huete Jimenez 
1297*ee791febSAntonio Huete Jimenez typedef struct dnssec_zone_rr_iter {
1298*ee791febSAntonio Huete Jimenez 	ldns_dnssec_zone         *zone;
1299*ee791febSAntonio Huete Jimenez 	ldns_rbnode_t            *node;
1300*ee791febSAntonio Huete Jimenez 	ldns_dnssec_name         *name;
1301*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets       *rrsets;
1302*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrs          *rrs;
1303*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets       *rrsets4rrsigs;
1304*ee791febSAntonio Huete Jimenez 	ldns_rbnode_t            *nsec3_node;
1305*ee791febSAntonio Huete Jimenez 	ldns_dnssec_name         *nsec3_name;
1306*ee791febSAntonio Huete Jimenez 	dnssec_zone_rr_iter_state state;
1307*ee791febSAntonio Huete Jimenez 	ldns_rdf                 *apex_name;
1308*ee791febSAntonio Huete Jimenez 	uint8_t                   apex_labs;
1309*ee791febSAntonio Huete Jimenez } dnssec_zone_rr_iter;
1310*ee791febSAntonio Huete Jimenez 
1311*ee791febSAntonio Huete Jimenez INLINE void
1312*ee791febSAntonio Huete Jimenez dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1313*ee791febSAntonio Huete Jimenez {
1314*ee791febSAntonio Huete Jimenez 	/* Make sure the i->name is "in zone" (i.e. below the apex) */
1315*ee791febSAntonio Huete Jimenez 	if (i->apex_name) {
1316*ee791febSAntonio Huete Jimenez 		ldns_rdf *name = (ldns_rdf *)i->node->key;
1317*ee791febSAntonio Huete Jimenez 
1318*ee791febSAntonio Huete Jimenez 		while (i->name && name != i->apex_name        /* not apex */
1319*ee791febSAntonio Huete Jimenez 
1320*ee791febSAntonio Huete Jimenez 		&& (  ldns_dname_label_count(name) != i->apex_labs
1321*ee791febSAntonio Huete Jimenez 		   || ldns_dname_compare(name, i->apex_name)) /* not apex */
1322*ee791febSAntonio Huete Jimenez 
1323*ee791febSAntonio Huete Jimenez 		&& !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1324*ee791febSAntonio Huete Jimenez 
1325*ee791febSAntonio Huete Jimenez 			/* next name */
1326*ee791febSAntonio Huete Jimenez 			i->node = ldns_rbtree_next(i->node);
1327*ee791febSAntonio Huete Jimenez 			if (i->node == LDNS_RBTREE_NULL)
1328*ee791febSAntonio Huete Jimenez 				i->name = NULL;
1329*ee791febSAntonio Huete Jimenez 			else {
1330*ee791febSAntonio Huete Jimenez 				i->name = (ldns_dnssec_name *)i->node->data;
1331*ee791febSAntonio Huete Jimenez 				name = (ldns_rdf *)i->node->key;
1332*ee791febSAntonio Huete Jimenez 			}
1333*ee791febSAntonio Huete Jimenez 		}
1334*ee791febSAntonio Huete Jimenez 	}
1335*ee791febSAntonio Huete Jimenez 	/* determine state */
1336*ee791febSAntonio Huete Jimenez 	if (!i->name) {
1337*ee791febSAntonio Huete Jimenez 		if (!i->nsec3_name)
1338*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_FINI;
1339*ee791febSAntonio Huete Jimenez 		else {
1340*ee791febSAntonio Huete Jimenez 			i->rrs = i->nsec3_name->nsec_signatures;
1341*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1342*ee791febSAntonio Huete Jimenez 		}
1343*ee791febSAntonio Huete Jimenez 	} else if (!i->nsec3_name) {
1344*ee791febSAntonio Huete Jimenez 		i->rrsets = i->name->rrsets;
1345*ee791febSAntonio Huete Jimenez 		i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1346*ee791febSAntonio Huete Jimenez 
1347*ee791febSAntonio Huete Jimenez 	} else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec)
1348*ee791febSAntonio Huete Jimenez 	                             , (ldns_rdf *)i->node->key) < 0) {
1349*ee791febSAntonio Huete Jimenez 		i->rrs = i->nsec3_name->nsec_signatures;
1350*ee791febSAntonio Huete Jimenez 		i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1351*ee791febSAntonio Huete Jimenez 	} else {
1352*ee791febSAntonio Huete Jimenez 		i->rrsets = i->name->rrsets;
1353*ee791febSAntonio Huete Jimenez 		i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1354*ee791febSAntonio Huete Jimenez 	}
1355*ee791febSAntonio Huete Jimenez }
1356*ee791febSAntonio Huete Jimenez 
1357*ee791febSAntonio Huete Jimenez /**
1358*ee791febSAntonio Huete Jimenez  * Iterate over the RR's in the ldns_dnssec_zone in canonical order.
1359*ee791febSAntonio Huete Jimenez  * There are three possible paths through the RR's in a ldns_dnssec_name.
1360*ee791febSAntonio Huete Jimenez  *
1361*ee791febSAntonio Huete Jimenez  * 1. There is no NSEC:
1362*ee791febSAntonio Huete Jimenez  *
1363*ee791febSAntonio Huete Jimenez  *    1.1. All the RRs in the name->rrsets with type < RRSIG,
1364*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1365*ee791febSAntonio Huete Jimenez  *
1366*ee791febSAntonio Huete Jimenez  *    1.2. Then all the RRSIGs from name->rrsets (likely none)
1367*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1368*ee791febSAntonio Huete Jimenez  *
1369*ee791febSAntonio Huete Jimenez  *    1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1370*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_REST
1371*ee791febSAntonio Huete Jimenez  *
1372*ee791febSAntonio Huete Jimenez  *
1373*ee791febSAntonio Huete Jimenez  * 2. There is a NSEC of type NSEC with this name:
1374*ee791febSAntonio Huete Jimenez  *
1375*ee791febSAntonio Huete Jimenez  *    2.1. All the RRs in the name->rrsets with type < RRSIG,
1376*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1377*ee791febSAntonio Huete Jimenez  *
1378*ee791febSAntonio Huete Jimenez  *    2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1379*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1380*ee791febSAntonio Huete Jimenez  *
1381*ee791febSAntonio Huete Jimenez  *    2.3. Then the signatures of the NSEC RR, followed by
1382*ee791febSAntonio Huete Jimenez  *         the signatures of the remaining name->rrsets (type > NSEC),
1383*ee791febSAntonio Huete Jimenez  *         followed by the NSEC rr.
1384*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1385*ee791febSAntonio Huete Jimenez  *
1386*ee791febSAntonio Huete Jimenez  *    2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1387*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_REST
1388*ee791febSAntonio Huete Jimenez  *
1389*ee791febSAntonio Huete Jimenez  *
1390*ee791febSAntonio Huete Jimenez  * 3. There is a NSEC of type NSEC3 for this name:
1391*ee791febSAntonio Huete Jimenez  *
1392*ee791febSAntonio Huete Jimenez  *    3.1. If the NSEC3 name is before the name for other RRsets in the zone,
1393*ee791febSAntonio Huete Jimenez  *         Then all signatures of the NSEC3 RR, followed by the NSEC3
1394*ee791febSAntonio Huete Jimenez  *         state: DNSSEC_ZONE_RR_ITER_NSEC3
1395*ee791febSAntonio Huete Jimenez  *
1396*ee791febSAntonio Huete Jimenez  *         otherwise follow path for "no NSEC" for the name for other RRsets
1397*ee791febSAntonio Huete Jimenez  */
1398*ee791febSAntonio Huete Jimenez static ldns_rr *
1399*ee791febSAntonio Huete Jimenez dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1400*ee791febSAntonio Huete Jimenez {
1401*ee791febSAntonio Huete Jimenez 	ldns_rr *nsec3;
1402*ee791febSAntonio Huete Jimenez 
1403*ee791febSAntonio Huete Jimenez 	for (;;) {
1404*ee791febSAntonio Huete Jimenez 		if (i->rrs) {
1405*ee791febSAntonio Huete Jimenez 			ldns_rr *rr = i->rrs->rr;
1406*ee791febSAntonio Huete Jimenez 			i->rrs = i->rrs->next;
1407*ee791febSAntonio Huete Jimenez 			return rr;
1408*ee791febSAntonio Huete Jimenez 		}
1409*ee791febSAntonio Huete Jimenez 		switch (i->state) {
1410*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1411*ee791febSAntonio Huete Jimenez 			if (i->rrsets
1412*ee791febSAntonio Huete Jimenez 			&&  i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1413*ee791febSAntonio Huete Jimenez 
1414*ee791febSAntonio Huete Jimenez 				i->rrs = i->rrsets->rrs;
1415*ee791febSAntonio Huete Jimenez 				i->rrsets = i->rrsets->next;
1416*ee791febSAntonio Huete Jimenez 				break;
1417*ee791febSAntonio Huete Jimenez 			}
1418*ee791febSAntonio Huete Jimenez 			i->rrsets4rrsigs = i->name->rrsets;
1419*ee791febSAntonio Huete Jimenez 			if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1420*ee791febSAntonio Huete Jimenez 			                               == LDNS_RR_TYPE_NSEC) {
1421*ee791febSAntonio Huete Jimenez 
1422*ee791febSAntonio Huete Jimenez 				i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1423*ee791febSAntonio Huete Jimenez 				break;
1424*ee791febSAntonio Huete Jimenez 			}
1425*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1426*ee791febSAntonio Huete Jimenez 			/* fallthrough */
1427*ee791febSAntonio Huete Jimenez 
1428*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC:
1429*ee791febSAntonio Huete Jimenez 			if (i->rrsets4rrsigs) {
1430*ee791febSAntonio Huete Jimenez 				i->rrs = i->rrsets4rrsigs->signatures;
1431*ee791febSAntonio Huete Jimenez 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1432*ee791febSAntonio Huete Jimenez 				break;
1433*ee791febSAntonio Huete Jimenez 			}
1434*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_REST;
1435*ee791febSAntonio Huete Jimenez 			/* fallthrough */
1436*ee791febSAntonio Huete Jimenez 
1437*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_REST:
1438*ee791febSAntonio Huete Jimenez 			if (i->rrsets) {
1439*ee791febSAntonio Huete Jimenez 				i->rrs = i->rrsets->rrs;
1440*ee791febSAntonio Huete Jimenez 				i->rrsets = i->rrsets->next;
1441*ee791febSAntonio Huete Jimenez 				break;
1442*ee791febSAntonio Huete Jimenez 			}
1443*ee791febSAntonio Huete Jimenez 			/* next name */
1444*ee791febSAntonio Huete Jimenez 			i->node = ldns_rbtree_next(i->node);
1445*ee791febSAntonio Huete Jimenez 			i->name = i->node == LDNS_RBTREE_NULL ? NULL
1446*ee791febSAntonio Huete Jimenez 				: (ldns_dnssec_name *)i->node->data;
1447*ee791febSAntonio Huete Jimenez 
1448*ee791febSAntonio Huete Jimenez 			dnssec_zone_rr_iter_set_state_for_next_name(i);
1449*ee791febSAntonio Huete Jimenez 			break;
1450*ee791febSAntonio Huete Jimenez 
1451*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1452*ee791febSAntonio Huete Jimenez 			if (i->rrsets4rrsigs
1453*ee791febSAntonio Huete Jimenez 			&&  i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1454*ee791febSAntonio Huete Jimenez 
1455*ee791febSAntonio Huete Jimenez 				i->rrs = i->rrsets4rrsigs->signatures;
1456*ee791febSAntonio Huete Jimenez 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1457*ee791febSAntonio Huete Jimenez 				break;
1458*ee791febSAntonio Huete Jimenez 			}
1459*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1460*ee791febSAntonio Huete Jimenez 			i->rrs = i->name->nsec_signatures;
1461*ee791febSAntonio Huete Jimenez 			break;
1462*ee791febSAntonio Huete Jimenez 
1463*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST:
1464*ee791febSAntonio Huete Jimenez 			if (i->rrsets4rrsigs) {
1465*ee791febSAntonio Huete Jimenez 				i->rrs = i->rrsets4rrsigs->signatures;
1466*ee791febSAntonio Huete Jimenez 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1467*ee791febSAntonio Huete Jimenez 				break;
1468*ee791febSAntonio Huete Jimenez 			}
1469*ee791febSAntonio Huete Jimenez 			i->state = DNSSEC_ZONE_RR_ITER_REST;
1470*ee791febSAntonio Huete Jimenez 			return i->name->nsec;
1471*ee791febSAntonio Huete Jimenez 
1472*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_NSEC3:
1473*ee791febSAntonio Huete Jimenez 			nsec3 = i->nsec3_name->nsec;
1474*ee791febSAntonio Huete Jimenez 
1475*ee791febSAntonio Huete Jimenez 			/* next nsec3 */
1476*ee791febSAntonio Huete Jimenez 			do {
1477*ee791febSAntonio Huete Jimenez 				i->nsec3_node
1478*ee791febSAntonio Huete Jimenez 				    = ldns_rbtree_next(i->nsec3_node);
1479*ee791febSAntonio Huete Jimenez 				i->nsec3_name
1480*ee791febSAntonio Huete Jimenez 				    = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1481*ee791febSAntonio Huete Jimenez 				    : (ldns_dnssec_name*)i->nsec3_node->data;
1482*ee791febSAntonio Huete Jimenez 
1483*ee791febSAntonio Huete Jimenez 				/* names for glue can be in the hashed_names
1484*ee791febSAntonio Huete Jimenez 				 * tree, but will not have a NSEC3
1485*ee791febSAntonio Huete Jimenez 				 */
1486*ee791febSAntonio Huete Jimenez 			} while (i->nsec3_name && !i->nsec3_name->nsec);
1487*ee791febSAntonio Huete Jimenez 
1488*ee791febSAntonio Huete Jimenez 			dnssec_zone_rr_iter_set_state_for_next_name(i);
1489*ee791febSAntonio Huete Jimenez 			return nsec3;
1490*ee791febSAntonio Huete Jimenez 
1491*ee791febSAntonio Huete Jimenez 		case DNSSEC_ZONE_RR_ITER_FINI:
1492*ee791febSAntonio Huete Jimenez 			return NULL;
1493*ee791febSAntonio Huete Jimenez 		}
1494*ee791febSAntonio Huete Jimenez 	}
1495*ee791febSAntonio Huete Jimenez }
1496*ee791febSAntonio Huete Jimenez 
1497*ee791febSAntonio Huete Jimenez static ldns_rr *
1498*ee791febSAntonio Huete Jimenez dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1499*ee791febSAntonio Huete Jimenez {
1500*ee791febSAntonio Huete Jimenez 	if (!i || !zone)
1501*ee791febSAntonio Huete Jimenez 		return NULL;
1502*ee791febSAntonio Huete Jimenez 
1503*ee791febSAntonio Huete Jimenez 	memset(i, 0, sizeof(*i));
1504*ee791febSAntonio Huete Jimenez 	i->zone = zone;
1505*ee791febSAntonio Huete Jimenez 	if (zone->soa && zone->soa->name) {
1506*ee791febSAntonio Huete Jimenez 		i->apex_name = zone->soa->name;
1507*ee791febSAntonio Huete Jimenez 		i->apex_labs = ldns_dname_label_count(i->apex_name);
1508*ee791febSAntonio Huete Jimenez 	} else
1509*ee791febSAntonio Huete Jimenez 		i->apex_name = NULL;
1510*ee791febSAntonio Huete Jimenez 
1511*ee791febSAntonio Huete Jimenez 
1512*ee791febSAntonio Huete Jimenez 	i->node = ldns_rbtree_first(zone->names);
1513*ee791febSAntonio Huete Jimenez 	i->name = i->node == LDNS_RBTREE_NULL ? NULL
1514*ee791febSAntonio Huete Jimenez 		: (ldns_dnssec_name *)i->node->data;
1515*ee791febSAntonio Huete Jimenez 
1516*ee791febSAntonio Huete Jimenez 	if (zone->hashed_names) {
1517*ee791febSAntonio Huete Jimenez 		do {
1518*ee791febSAntonio Huete Jimenez 			i->nsec3_node = ldns_rbtree_first(zone->hashed_names);
1519*ee791febSAntonio Huete Jimenez 			i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1520*ee791febSAntonio Huete Jimenez 				      : (ldns_dnssec_name*)i->nsec3_node->data;
1521*ee791febSAntonio Huete Jimenez 		} while (i->nsec3_name && !i->nsec3_name->nsec);
1522*ee791febSAntonio Huete Jimenez 	}
1523*ee791febSAntonio Huete Jimenez 	dnssec_zone_rr_iter_set_state_for_next_name(i);
1524*ee791febSAntonio Huete Jimenez 	return dnssec_zone_rr_iter_next(i);
1525*ee791febSAntonio Huete Jimenez }
1526*ee791febSAntonio Huete Jimenez 
1527*ee791febSAntonio Huete Jimenez enum enum_zonemd_scheme {
1528*ee791febSAntonio Huete Jimenez         ZONEMD_SCHEME_FIRST  = 1,
1529*ee791febSAntonio Huete Jimenez         ZONEMD_SCHEME_SIMPLE = 1,
1530*ee791febSAntonio Huete Jimenez         ZONEMD_SCHEME_LAST   = 1
1531*ee791febSAntonio Huete Jimenez };
1532*ee791febSAntonio Huete Jimenez typedef enum enum_zonemd_scheme zonemd_scheme;
1533*ee791febSAntonio Huete Jimenez 
1534*ee791febSAntonio Huete Jimenez enum enum_zonemd_hash {
1535*ee791febSAntonio Huete Jimenez         ZONEMD_HASH_FIRST  = 1,
1536*ee791febSAntonio Huete Jimenez         ZONEMD_HASH_SHA384 = 1,
1537*ee791febSAntonio Huete Jimenez         ZONEMD_HASH_SHA512 = 2,
1538*ee791febSAntonio Huete Jimenez         ZONEMD_HASH_LAST   = 2
1539*ee791febSAntonio Huete Jimenez };
1540*ee791febSAntonio Huete Jimenez typedef enum enum_zonemd_hash zonemd_hash;
1541*ee791febSAntonio Huete Jimenez 
1542*ee791febSAntonio Huete Jimenez struct struct_zone_digester {
1543*ee791febSAntonio Huete Jimenez         ldns_sha384_CTX sha384_CTX;
1544*ee791febSAntonio Huete Jimenez         ldns_sha512_CTX sha512_CTX;
1545*ee791febSAntonio Huete Jimenez         unsigned simple_sha384 : 1;
1546*ee791febSAntonio Huete Jimenez         unsigned simple_sha512 : 1;
1547*ee791febSAntonio Huete Jimenez         unsigned double_sha384 : 1;
1548*ee791febSAntonio Huete Jimenez         unsigned double_sha512 : 1;
1549*ee791febSAntonio Huete Jimenez };
1550*ee791febSAntonio Huete Jimenez typedef struct struct_zone_digester zone_digester;
1551*ee791febSAntonio Huete Jimenez 
1552*ee791febSAntonio Huete Jimenez INLINE bool zone_digester_set(zone_digester *zd)
1553*ee791febSAntonio Huete Jimenez { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1554*ee791febSAntonio Huete Jimenez 
1555*ee791febSAntonio Huete Jimenez INLINE void zone_digester_init(zone_digester *zd)
1556*ee791febSAntonio Huete Jimenez { memset(zd, 0, sizeof(*zd)); }
1557*ee791febSAntonio Huete Jimenez 
1558*ee791febSAntonio Huete Jimenez static ldns_status
1559*ee791febSAntonio Huete Jimenez zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1560*ee791febSAntonio Huete Jimenez {
1561*ee791febSAntonio Huete Jimenez 	if (!zd)
1562*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_NULL;
1563*ee791febSAntonio Huete Jimenez 
1564*ee791febSAntonio Huete Jimenez 	switch (scheme) {
1565*ee791febSAntonio Huete Jimenez 	case ZONEMD_SCHEME_SIMPLE:
1566*ee791febSAntonio Huete Jimenez 		switch (hash) {
1567*ee791febSAntonio Huete Jimenez 		case ZONEMD_HASH_SHA384:
1568*ee791febSAntonio Huete Jimenez 			if (zd->double_sha384)
1569*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1570*ee791febSAntonio Huete Jimenez 
1571*ee791febSAntonio Huete Jimenez 			else if (zd->simple_sha384) {
1572*ee791febSAntonio Huete Jimenez 				zd->simple_sha384 = 0;
1573*ee791febSAntonio Huete Jimenez 				zd->double_sha384 = 1;
1574*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1575*ee791febSAntonio Huete Jimenez 			}
1576*ee791febSAntonio Huete Jimenez 			ldns_sha384_init(&zd->sha384_CTX);
1577*ee791febSAntonio Huete Jimenez 			zd->simple_sha384 = 1;
1578*ee791febSAntonio Huete Jimenez 			break;
1579*ee791febSAntonio Huete Jimenez 
1580*ee791febSAntonio Huete Jimenez 		case ZONEMD_HASH_SHA512:
1581*ee791febSAntonio Huete Jimenez 			if (zd->double_sha512)
1582*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1583*ee791febSAntonio Huete Jimenez 
1584*ee791febSAntonio Huete Jimenez 			else if (zd->simple_sha512) {
1585*ee791febSAntonio Huete Jimenez 				zd->simple_sha512 = 0;
1586*ee791febSAntonio Huete Jimenez 				zd->double_sha512 = 1;
1587*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1588*ee791febSAntonio Huete Jimenez 			}
1589*ee791febSAntonio Huete Jimenez 			ldns_sha512_init(&zd->sha512_CTX);
1590*ee791febSAntonio Huete Jimenez 			zd->simple_sha512 = 1;
1591*ee791febSAntonio Huete Jimenez 			break;
1592*ee791febSAntonio Huete Jimenez 		default:
1593*ee791febSAntonio Huete Jimenez 			return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1594*ee791febSAntonio Huete Jimenez 		}
1595*ee791febSAntonio Huete Jimenez 		break;
1596*ee791febSAntonio Huete Jimenez 	default:
1597*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1598*ee791febSAntonio Huete Jimenez 	}
1599*ee791febSAntonio Huete Jimenez 	return LDNS_STATUS_OK;
1600*ee791febSAntonio Huete Jimenez }
1601*ee791febSAntonio Huete Jimenez 
1602*ee791febSAntonio Huete Jimenez static ldns_status
1603*ee791febSAntonio Huete Jimenez zone_digester_update(zone_digester *zd, ldns_rr *rr)
1604*ee791febSAntonio Huete Jimenez {
1605*ee791febSAntonio Huete Jimenez 	uint8_t data[65536];
1606*ee791febSAntonio Huete Jimenez 	ldns_buffer buf;
1607*ee791febSAntonio Huete Jimenez 	ldns_status st;
1608*ee791febSAntonio Huete Jimenez 
1609*ee791febSAntonio Huete Jimenez 	buf._data = data;
1610*ee791febSAntonio Huete Jimenez 	buf._position = 0;
1611*ee791febSAntonio Huete Jimenez 	buf._limit = sizeof(data);
1612*ee791febSAntonio Huete Jimenez 	buf._capacity = sizeof(data);
1613*ee791febSAntonio Huete Jimenez 	buf._fixed = 1;
1614*ee791febSAntonio Huete Jimenez 	buf._status = LDNS_STATUS_OK;
1615*ee791febSAntonio Huete Jimenez 
1616*ee791febSAntonio Huete Jimenez 	if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1617*ee791febSAntonio Huete Jimenez 		return st;
1618*ee791febSAntonio Huete Jimenez 
1619*ee791febSAntonio Huete Jimenez 	if (zd->simple_sha384)
1620*ee791febSAntonio Huete Jimenez 		ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1621*ee791febSAntonio Huete Jimenez 
1622*ee791febSAntonio Huete Jimenez 	if (zd->simple_sha512)
1623*ee791febSAntonio Huete Jimenez 		ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1624*ee791febSAntonio Huete Jimenez 
1625*ee791febSAntonio Huete Jimenez 	return LDNS_STATUS_OK;
1626*ee791febSAntonio Huete Jimenez }
1627*ee791febSAntonio Huete Jimenez 
1628*ee791febSAntonio Huete Jimenez INLINE ldns_rr *
1629*ee791febSAntonio Huete Jimenez new_zonemd(ldns_rr *soa, zonemd_hash hash)
1630*ee791febSAntonio Huete Jimenez {
1631*ee791febSAntonio Huete Jimenez 	ldns_rr  *rr     = NULL;
1632*ee791febSAntonio Huete Jimenez 	uint8_t  *data   = NULL;
1633*ee791febSAntonio Huete Jimenez 	ldns_rdf *rdf;
1634*ee791febSAntonio Huete Jimenez 	size_t    md_len = hash == ZONEMD_HASH_SHA384
1635*ee791febSAntonio Huete Jimenez 	                 ? LDNS_SHA384_DIGEST_LENGTH
1636*ee791febSAntonio Huete Jimenez 	                 : LDNS_SHA512_DIGEST_LENGTH;
1637*ee791febSAntonio Huete Jimenez 
1638*ee791febSAntonio Huete Jimenez 	if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1639*ee791febSAntonio Huete Jimenez 		return NULL;
1640*ee791febSAntonio Huete Jimenez 
1641*ee791febSAntonio Huete Jimenez 	if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1642*ee791febSAntonio Huete Jimenez 		goto error;
1643*ee791febSAntonio Huete Jimenez 
1644*ee791febSAntonio Huete Jimenez 	ldns_rr_set_owner(rr, rdf);
1645*ee791febSAntonio Huete Jimenez 	ldns_rr_set_class(rr, ldns_rr_get_class(soa));
1646*ee791febSAntonio Huete Jimenez 	ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1647*ee791febSAntonio Huete Jimenez 
1648*ee791febSAntonio Huete Jimenez 	if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1649*ee791febSAntonio Huete Jimenez 		goto error;
1650*ee791febSAntonio Huete Jimenez 	ldns_rr_set_rdf(rr, rdf, 0);
1651*ee791febSAntonio Huete Jimenez 
1652*ee791febSAntonio Huete Jimenez 	if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1653*ee791febSAntonio Huete Jimenez 		goto error;
1654*ee791febSAntonio Huete Jimenez 	ldns_rr_set_rdf(rr, rdf, 1);
1655*ee791febSAntonio Huete Jimenez 
1656*ee791febSAntonio Huete Jimenez 	if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1657*ee791febSAntonio Huete Jimenez 		goto error;
1658*ee791febSAntonio Huete Jimenez 	ldns_rr_set_rdf(rr, rdf, 2);
1659*ee791febSAntonio Huete Jimenez 
1660*ee791febSAntonio Huete Jimenez 	if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1661*ee791febSAntonio Huete Jimenez 		goto error;
1662*ee791febSAntonio Huete Jimenez 
1663*ee791febSAntonio Huete Jimenez 	if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1664*ee791febSAntonio Huete Jimenez 		goto error;
1665*ee791febSAntonio Huete Jimenez 	ldns_rr_set_rdf(rr, rdf, 3);
1666*ee791febSAntonio Huete Jimenez 
1667*ee791febSAntonio Huete Jimenez 	return rr;
1668*ee791febSAntonio Huete Jimenez error:
1669*ee791febSAntonio Huete Jimenez 	if (data)
1670*ee791febSAntonio Huete Jimenez 		LDNS_FREE(data);
1671*ee791febSAntonio Huete Jimenez 	ldns_rr_free(rr);
1672*ee791febSAntonio Huete Jimenez 	return NULL;
1673*ee791febSAntonio Huete Jimenez }
1674*ee791febSAntonio Huete Jimenez 
1675*ee791febSAntonio Huete Jimenez static ldns_rr_list *
1676*ee791febSAntonio Huete Jimenez zone_digester_export(
1677*ee791febSAntonio Huete Jimenez 		zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1678*ee791febSAntonio Huete Jimenez {
1679*ee791febSAntonio Huete Jimenez 	ldns_status st = LDNS_STATUS_OK;
1680*ee791febSAntonio Huete Jimenez 	ldns_rr_list *rr_list = NULL;
1681*ee791febSAntonio Huete Jimenez 	ldns_rr *sha384 = NULL;
1682*ee791febSAntonio Huete Jimenez 	ldns_rr *sha512 = NULL;
1683*ee791febSAntonio Huete Jimenez 
1684*ee791febSAntonio Huete Jimenez 	if (!zd || !soa)
1685*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_NULL;
1686*ee791febSAntonio Huete Jimenez 
1687*ee791febSAntonio Huete Jimenez 	else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1688*ee791febSAntonio Huete Jimenez 	     ||  ldns_rr_rd_count(soa) < 3)
1689*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_ZONEMD_INVALID_SOA;
1690*ee791febSAntonio Huete Jimenez 
1691*ee791febSAntonio Huete Jimenez 	else if (!(rr_list = ldns_rr_list_new()))
1692*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_MEM_ERR;
1693*ee791febSAntonio Huete Jimenez 
1694*ee791febSAntonio Huete Jimenez 	else if (zd->simple_sha384
1695*ee791febSAntonio Huete Jimenez 	     && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1696*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_MEM_ERR;
1697*ee791febSAntonio Huete Jimenez 
1698*ee791febSAntonio Huete Jimenez 	else if (zd->simple_sha512
1699*ee791febSAntonio Huete Jimenez 	     && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1700*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_MEM_ERR;
1701*ee791febSAntonio Huete Jimenez 
1702*ee791febSAntonio Huete Jimenez 	else if (zd->simple_sha384
1703*ee791febSAntonio Huete Jimenez 	     && !ldns_rr_list_push_rr(rr_list, sha384))
1704*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_MEM_ERR;
1705*ee791febSAntonio Huete Jimenez 
1706*ee791febSAntonio Huete Jimenez 	else if (zd->simple_sha512
1707*ee791febSAntonio Huete Jimenez 	     && !ldns_rr_list_push_rr(rr_list, sha512)) {
1708*ee791febSAntonio Huete Jimenez 		if (zd->simple_sha384)
1709*ee791febSAntonio Huete Jimenez 			sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1710*ee791febSAntonio Huete Jimenez 		st = LDNS_STATUS_MEM_ERR;
1711*ee791febSAntonio Huete Jimenez 
1712*ee791febSAntonio Huete Jimenez 	} else {
1713*ee791febSAntonio Huete Jimenez 		if (sha384)
1714*ee791febSAntonio Huete Jimenez 			ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1715*ee791febSAntonio Huete Jimenez 			                 , &zd->sha384_CTX);
1716*ee791febSAntonio Huete Jimenez 		if (sha512)
1717*ee791febSAntonio Huete Jimenez 			ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1718*ee791febSAntonio Huete Jimenez 			                 , &zd->sha512_CTX);
1719*ee791febSAntonio Huete Jimenez 		return rr_list;
1720*ee791febSAntonio Huete Jimenez 	}
1721*ee791febSAntonio Huete Jimenez 	if (ret_st)
1722*ee791febSAntonio Huete Jimenez 		*ret_st = st;
1723*ee791febSAntonio Huete Jimenez 	if (sha384)
1724*ee791febSAntonio Huete Jimenez 		ldns_rr_free(sha384);
1725*ee791febSAntonio Huete Jimenez 	if (sha512)
1726*ee791febSAntonio Huete Jimenez 		ldns_rr_free(sha512);
1727*ee791febSAntonio Huete Jimenez 	if (rr_list)
1728*ee791febSAntonio Huete Jimenez 		ldns_rr_list_deep_free(rr_list);
1729*ee791febSAntonio Huete Jimenez 	return NULL;
1730*ee791febSAntonio Huete Jimenez }
1731*ee791febSAntonio Huete Jimenez 
1732*ee791febSAntonio Huete Jimenez static ldns_status
1733*ee791febSAntonio Huete Jimenez ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1734*ee791febSAntonio Huete Jimenez {
1735*ee791febSAntonio Huete Jimenez 	ldns_status st = LDNS_STATUS_OK;
1736*ee791febSAntonio Huete Jimenez 	dnssec_zone_rr_iter rr_iter;
1737*ee791febSAntonio Huete Jimenez 	ldns_rr *rr;
1738*ee791febSAntonio Huete Jimenez 	ldns_rdf *apex_name; /* name of zone apex */
1739*ee791febSAntonio Huete Jimenez 
1740*ee791febSAntonio Huete Jimenez 	if (!zone || !zd || !zone->soa || !zone->soa->name)
1741*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_NULL;
1742*ee791febSAntonio Huete Jimenez 
1743*ee791febSAntonio Huete Jimenez 	apex_name = zone->soa->name;
1744*ee791febSAntonio Huete Jimenez 	for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1745*ee791febSAntonio Huete Jimenez 	    ; rr && !st
1746*ee791febSAntonio Huete Jimenez 	    ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1747*ee791febSAntonio Huete Jimenez 		/* Skip apex ZONEMD RRs */
1748*ee791febSAntonio Huete Jimenez 		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD
1749*ee791febSAntonio Huete Jimenez 		&& !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1750*ee791febSAntonio Huete Jimenez 			continue;
1751*ee791febSAntonio Huete Jimenez 		/* Skip RRSIGs for apex ZONEMD RRs */
1752*ee791febSAntonio Huete Jimenez 		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
1753*ee791febSAntonio Huete Jimenez 		&&  LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type(
1754*ee791febSAntonio Huete Jimenez 				ldns_rr_rrsig_typecovered(rr))
1755*ee791febSAntonio Huete Jimenez 		&& !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1756*ee791febSAntonio Huete Jimenez 			continue;
1757*ee791febSAntonio Huete Jimenez 		st = zone_digester_update(zd, rr);
1758*ee791febSAntonio Huete Jimenez 	}
1759*ee791febSAntonio Huete Jimenez 	return st;
1760*ee791febSAntonio Huete Jimenez }
1761*ee791febSAntonio Huete Jimenez 
1762*ee791febSAntonio Huete Jimenez ldns_status
1763*ee791febSAntonio Huete Jimenez ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1764*ee791febSAntonio Huete Jimenez {
1765*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets *zonemd, *soa;
1766*ee791febSAntonio Huete Jimenez 	zone_digester zd;
1767*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrs *rrs;
1768*ee791febSAntonio Huete Jimenez 	ldns_rr *soa_rr;
1769*ee791febSAntonio Huete Jimenez 	ldns_status st;
1770*ee791febSAntonio Huete Jimenez 	uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1771*ee791febSAntonio Huete Jimenez 	uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1772*ee791febSAntonio Huete Jimenez 	size_t valid_zonemds;
1773*ee791febSAntonio Huete Jimenez 
1774*ee791febSAntonio Huete Jimenez 	if (!zone)
1775*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_NULL;
1776*ee791febSAntonio Huete Jimenez 
1777*ee791febSAntonio Huete Jimenez 	zonemd = ldns_dnssec_zone_find_rrset(
1778*ee791febSAntonio Huete Jimenez 			zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1779*ee791febSAntonio Huete Jimenez 	if (!zonemd) {
1780*ee791febSAntonio Huete Jimenez 		ldns_rbnode_t *nsec3_node;
1781*ee791febSAntonio Huete Jimenez 
1782*ee791febSAntonio Huete Jimenez 		/* we need proof of non-existence for ZONEMD at the apex */
1783*ee791febSAntonio Huete Jimenez 		if (zone->soa->nsec) {
1784*ee791febSAntonio Huete Jimenez 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1785*ee791febSAntonio Huete Jimenez 							zone->soa->nsec),
1786*ee791febSAntonio Huete Jimenez 					       	LDNS_RR_TYPE_ZONEMD))
1787*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_NO_ZONEMD;
1788*ee791febSAntonio Huete Jimenez 
1789*ee791febSAntonio Huete Jimenez 		} else if (!zone->soa->hashed_name || !zone->hashed_names)
1790*ee791febSAntonio Huete Jimenez 			return LDNS_STATUS_NO_ZONEMD;
1791*ee791febSAntonio Huete Jimenez 
1792*ee791febSAntonio Huete Jimenez 		else if (LDNS_RBTREE_NULL ==
1793*ee791febSAntonio Huete Jimenez 		    (nsec3_node = ldns_rbtree_search( zone->hashed_names
1794*ee791febSAntonio Huete Jimenez 						    , zone->soa->hashed_name)))
1795*ee791febSAntonio Huete Jimenez 			return LDNS_STATUS_NO_ZONEMD;
1796*ee791febSAntonio Huete Jimenez 		else {
1797*ee791febSAntonio Huete Jimenez 			ldns_dnssec_name *nsec3
1798*ee791febSAntonio Huete Jimenez 				= (ldns_dnssec_name *)nsec3_node->data;
1799*ee791febSAntonio Huete Jimenez 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1800*ee791febSAntonio Huete Jimenez 							nsec3->nsec),
1801*ee791febSAntonio Huete Jimenez 						LDNS_RR_TYPE_ZONEMD))
1802*ee791febSAntonio Huete Jimenez 				return LDNS_STATUS_NO_ZONEMD;
1803*ee791febSAntonio Huete Jimenez 		}
1804*ee791febSAntonio Huete Jimenez 		/* ZONEMD at apex does really not exist */
1805*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_OK;
1806*ee791febSAntonio Huete Jimenez 	}
1807*ee791febSAntonio Huete Jimenez 	soa = ldns_dnssec_zone_find_rrset(
1808*ee791febSAntonio Huete Jimenez 			zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1809*ee791febSAntonio Huete Jimenez 	if (!soa || !soa->rrs || !soa->rrs->rr)
1810*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1811*ee791febSAntonio Huete Jimenez 
1812*ee791febSAntonio Huete Jimenez 	soa_rr = soa->rrs->rr;
1813*ee791febSAntonio Huete Jimenez 	if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1814*ee791febSAntonio Huete Jimenez 	||  ldns_rr_rd_count(soa_rr) < 3)
1815*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1816*ee791febSAntonio Huete Jimenez 
1817*ee791febSAntonio Huete Jimenez 	zone_digester_init(&zd);
1818*ee791febSAntonio Huete Jimenez 	for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1819*ee791febSAntonio Huete Jimenez 		if (!rrs->rr
1820*ee791febSAntonio Huete Jimenez 		||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1821*ee791febSAntonio Huete Jimenez 		||  ldns_rr_rd_count(rrs->rr) < 4)
1822*ee791febSAntonio Huete Jimenez 			continue;
1823*ee791febSAntonio Huete Jimenez 
1824*ee791febSAntonio Huete Jimenez 		/* serial should match SOA's serial */
1825*ee791febSAntonio Huete Jimenez 		if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1826*ee791febSAntonio Huete Jimenez 		    != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1827*ee791febSAntonio Huete Jimenez 			continue;
1828*ee791febSAntonio Huete Jimenez 
1829*ee791febSAntonio Huete Jimenez 		/* Add (scheme, hash) to digester */
1830*ee791febSAntonio Huete Jimenez 		zone_digester_add(&zd,
1831*ee791febSAntonio Huete Jimenez 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)),
1832*ee791febSAntonio Huete Jimenez 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2)));
1833*ee791febSAntonio Huete Jimenez 	}
1834*ee791febSAntonio Huete Jimenez 	if (!zone_digester_set(&zd))
1835*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_NO_VALID_ZONEMD;
1836*ee791febSAntonio Huete Jimenez 
1837*ee791febSAntonio Huete Jimenez 	if ((st = ldns_digest_zone(zone, &zd)))
1838*ee791febSAntonio Huete Jimenez 		return st;
1839*ee791febSAntonio Huete Jimenez 
1840*ee791febSAntonio Huete Jimenez 	if (zd.simple_sha384)
1841*ee791febSAntonio Huete Jimenez 		ldns_sha384_final(simple_sha384, &zd.sha384_CTX);
1842*ee791febSAntonio Huete Jimenez 	if (zd.simple_sha512)
1843*ee791febSAntonio Huete Jimenez 		ldns_sha512_final(simple_sha512, &zd.sha512_CTX);
1844*ee791febSAntonio Huete Jimenez 
1845*ee791febSAntonio Huete Jimenez 	valid_zonemds = 0;
1846*ee791febSAntonio Huete Jimenez 	for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1847*ee791febSAntonio Huete Jimenez 		if (!rrs->rr
1848*ee791febSAntonio Huete Jimenez 		||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1849*ee791febSAntonio Huete Jimenez 		||  ldns_rr_rd_count(rrs->rr) < 4)
1850*ee791febSAntonio Huete Jimenez 			continue;
1851*ee791febSAntonio Huete Jimenez 
1852*ee791febSAntonio Huete Jimenez 		/* serial should match SOA's serial */
1853*ee791febSAntonio Huete Jimenez 		if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1854*ee791febSAntonio Huete Jimenez 		    != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1855*ee791febSAntonio Huete Jimenez 			continue;
1856*ee791febSAntonio Huete Jimenez 
1857*ee791febSAntonio Huete Jimenez 		if (ZONEMD_SCHEME_SIMPLE !=
1858*ee791febSAntonio Huete Jimenez 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1859*ee791febSAntonio Huete Jimenez 			continue;
1860*ee791febSAntonio Huete Jimenez 
1861*ee791febSAntonio Huete Jimenez 		if (ZONEMD_HASH_SHA384
1862*ee791febSAntonio Huete Jimenez 				== ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1863*ee791febSAntonio Huete Jimenez 		&&  LDNS_SHA384_DIGEST_LENGTH
1864*ee791febSAntonio Huete Jimenez 				== ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1865*ee791febSAntonio Huete Jimenez 		&&  memcmp( simple_sha384
1866*ee791febSAntonio Huete Jimenez 			  , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1867*ee791febSAntonio Huete Jimenez 		          , LDNS_SHA384_DIGEST_LENGTH) == 0)
1868*ee791febSAntonio Huete Jimenez 
1869*ee791febSAntonio Huete Jimenez 			valid_zonemds += 1;
1870*ee791febSAntonio Huete Jimenez 
1871*ee791febSAntonio Huete Jimenez 		if (ZONEMD_HASH_SHA512
1872*ee791febSAntonio Huete Jimenez 				== ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1873*ee791febSAntonio Huete Jimenez 		&&  LDNS_SHA512_DIGEST_LENGTH
1874*ee791febSAntonio Huete Jimenez 				== ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1875*ee791febSAntonio Huete Jimenez 		&&  memcmp( simple_sha512
1876*ee791febSAntonio Huete Jimenez 			  , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1877*ee791febSAntonio Huete Jimenez 		          , LDNS_SHA512_DIGEST_LENGTH) == 0)
1878*ee791febSAntonio Huete Jimenez 
1879*ee791febSAntonio Huete Jimenez 			valid_zonemds += 1;
1880*ee791febSAntonio Huete Jimenez 	}
1881*ee791febSAntonio Huete Jimenez 	return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1882*ee791febSAntonio Huete Jimenez }
1883*ee791febSAntonio Huete Jimenez 
1884*ee791febSAntonio Huete Jimenez #ifdef HAVE_SSL
1885*ee791febSAntonio Huete Jimenez static ldns_status
1886*ee791febSAntonio Huete Jimenez rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1887*ee791febSAntonio Huete Jimenez 		ldns_rr_list *new_rrs)
1888*ee791febSAntonio Huete Jimenez {
1889*ee791febSAntonio Huete Jimenez 	ldns_rr *rr = NULL;
1890*ee791febSAntonio Huete Jimenez 
1891*ee791febSAntonio Huete Jimenez 	if (!rr_list || !rrs)
1892*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_NULL;
1893*ee791febSAntonio Huete Jimenez 
1894*ee791febSAntonio Huete Jimenez 	if (ldns_rr_list_rr_count(rr_list) == 0)
1895*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_OK;
1896*ee791febSAntonio Huete Jimenez 
1897*ee791febSAntonio Huete Jimenez 	if (!*rrs) {
1898*ee791febSAntonio Huete Jimenez 		if (!(*rrs = ldns_dnssec_rrs_new()))
1899*ee791febSAntonio Huete Jimenez 			return LDNS_STATUS_MEM_ERR;
1900*ee791febSAntonio Huete Jimenez 		(*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1901*ee791febSAntonio Huete Jimenez 		if (new_rrs)
1902*ee791febSAntonio Huete Jimenez 			ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1903*ee791febSAntonio Huete Jimenez 	}
1904*ee791febSAntonio Huete Jimenez 	while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1905*ee791febSAntonio Huete Jimenez 		ldns_status st;
1906*ee791febSAntonio Huete Jimenez 
1907*ee791febSAntonio Huete Jimenez 		if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1908*ee791febSAntonio Huete Jimenez 			ldns_rr_list_push_rr(rr_list, rr);
1909*ee791febSAntonio Huete Jimenez 			return st;
1910*ee791febSAntonio Huete Jimenez 		} else if (new_rrs)
1911*ee791febSAntonio Huete Jimenez 			ldns_rr_list_push_rr(new_rrs, rr);
1912*ee791febSAntonio Huete Jimenez 	}
1913*ee791febSAntonio Huete Jimenez 	return LDNS_STATUS_OK;
1914*ee791febSAntonio Huete Jimenez }
1915*ee791febSAntonio Huete Jimenez 
1916*ee791febSAntonio Huete Jimenez 
1917*ee791febSAntonio Huete Jimenez ldns_status
1918*ee791febSAntonio Huete Jimenez dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1919*ee791febSAntonio Huete Jimenez 		ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1920*ee791febSAntonio Huete Jimenez {
1921*ee791febSAntonio Huete Jimenez 	ldns_status st = LDNS_STATUS_OK;
1922*ee791febSAntonio Huete Jimenez 	zone_digester zd;
1923*ee791febSAntonio Huete Jimenez 	ldns_rr_list *zonemd_rr_list = NULL;
1924*ee791febSAntonio Huete Jimenez 	ldns_rr_list *zonemd_rrsigs = NULL;
1925*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets *soa_rrset;
1926*ee791febSAntonio Huete Jimenez 	ldns_rr *soa_rr = NULL;
1927*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets **rrset_ref;
1928*ee791febSAntonio Huete Jimenez 	ldns_dnssec_rrsets *zonemd_rrset;
1929*ee791febSAntonio Huete Jimenez 
1930*ee791febSAntonio Huete Jimenez 	zone_digester_init(&zd);
1931*ee791febSAntonio Huete Jimenez 	if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384)
1932*ee791febSAntonio Huete Jimenez 		zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1933*ee791febSAntonio Huete Jimenez 		                     , ZONEMD_HASH_SHA384);
1934*ee791febSAntonio Huete Jimenez 
1935*ee791febSAntonio Huete Jimenez 	if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1936*ee791febSAntonio Huete Jimenez 		zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1937*ee791febSAntonio Huete Jimenez 		                     , ZONEMD_HASH_SHA512);
1938*ee791febSAntonio Huete Jimenez 
1939*ee791febSAntonio Huete Jimenez 	if ((st = ldns_digest_zone(zone, &zd)))
1940*ee791febSAntonio Huete Jimenez 		return st;
1941*ee791febSAntonio Huete Jimenez 
1942*ee791febSAntonio Huete Jimenez 	soa_rrset = ldns_dnssec_zone_find_rrset(
1943*ee791febSAntonio Huete Jimenez 			zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1944*ee791febSAntonio Huete Jimenez 	if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1945*ee791febSAntonio Huete Jimenez 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1946*ee791febSAntonio Huete Jimenez 	soa_rr = soa_rrset->rrs->rr;
1947*ee791febSAntonio Huete Jimenez 
1948*ee791febSAntonio Huete Jimenez 	if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1949*ee791febSAntonio Huete Jimenez 		return st;
1950*ee791febSAntonio Huete Jimenez 
1951*ee791febSAntonio Huete Jimenez 	/* - replace or add ZONEMD rrset */
1952*ee791febSAntonio Huete Jimenez 	rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1953*ee791febSAntonio Huete Jimenez 	while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1954*ee791febSAntonio Huete Jimenez 		rrset_ref = &(*rrset_ref)->next;
1955*ee791febSAntonio Huete Jimenez 	if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1956*ee791febSAntonio Huete Jimenez 		/* reuse zonemd rrset */
1957*ee791febSAntonio Huete Jimenez 		zonemd_rrset = *rrset_ref;
1958*ee791febSAntonio Huete Jimenez 		ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1959*ee791febSAntonio Huete Jimenez 		zonemd_rrset->rrs = NULL;
1960*ee791febSAntonio Huete Jimenez 		ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1961*ee791febSAntonio Huete Jimenez 		zonemd_rrset->signatures = NULL;
1962*ee791febSAntonio Huete Jimenez 	} else {
1963*ee791febSAntonio Huete Jimenez 		/* insert zonemd rrset */
1964*ee791febSAntonio Huete Jimenez 		zonemd_rrset = ldns_dnssec_rrsets_new();
1965*ee791febSAntonio Huete Jimenez 		if (!zonemd_rrset) {
1966*ee791febSAntonio Huete Jimenez 			ldns_rr_list_deep_free(zonemd_rr_list);
1967*ee791febSAntonio Huete Jimenez 			return LDNS_STATUS_MEM_ERR;
1968*ee791febSAntonio Huete Jimenez 		}
1969*ee791febSAntonio Huete Jimenez 		zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1970*ee791febSAntonio Huete Jimenez 		zonemd_rrset->next = *rrset_ref;
1971*ee791febSAntonio Huete Jimenez 		*rrset_ref = zonemd_rrset;
1972*ee791febSAntonio Huete Jimenez 	}
1973*ee791febSAntonio Huete Jimenez 	if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1974*ee791febSAntonio Huete Jimenez 		st = rr_list2dnssec_rrs(  zonemd_rrsigs
1975*ee791febSAntonio Huete Jimenez 		                       , &zonemd_rrset->signatures, new_rrs);
1976*ee791febSAntonio Huete Jimenez 	if (!st)
1977*ee791febSAntonio Huete Jimenez 		st = rr_list2dnssec_rrs(  zonemd_rr_list
1978*ee791febSAntonio Huete Jimenez 		                       , &zonemd_rrset->rrs, new_rrs);
1979*ee791febSAntonio Huete Jimenez 	ldns_rr_list_deep_free(zonemd_rr_list);
1980*ee791febSAntonio Huete Jimenez 	ldns_rr_list_deep_free(zonemd_rrsigs);
1981*ee791febSAntonio Huete Jimenez 	return st;
1982*ee791febSAntonio Huete Jimenez }
1983*ee791febSAntonio Huete Jimenez 
1984*ee791febSAntonio Huete Jimenez #endif /* HAVE_SSL */
1985*ee791febSAntonio Huete Jimenez 
1986