xref: /dflybsd-src/contrib/ldns/dnssec_zone.c (revision d1b2b5caec9ab35b37f82c6e75b7f14f9c9103b2)
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 *
10825eb42bSJan Lentfer ldns_dnssec_rrs_new()
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
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
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
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
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 */
57825eb42bSJan Lentfer 	cmp = ldns_rr_compare(rrs->rr,
58825eb42bSJan Lentfer 					  rr);
59825eb42bSJan Lentfer 	/* should we error on equal? */
60825eb42bSJan Lentfer 	if (cmp <= 0) {
61825eb42bSJan Lentfer 		if (rrs->next) {
62ac996e71SJan Lentfer 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
63825eb42bSJan Lentfer 		} else {
64825eb42bSJan Lentfer 			new_rrs = ldns_dnssec_rrs_new();
65825eb42bSJan Lentfer 			new_rrs->rr = rr;
66825eb42bSJan Lentfer 			rrs->next = new_rrs;
67825eb42bSJan Lentfer 		}
68825eb42bSJan Lentfer 	} else if (cmp > 0) {
69825eb42bSJan Lentfer 		/* put the current old rr in the new next, put the new
70825eb42bSJan Lentfer 		   rr in the current container */
71825eb42bSJan Lentfer 		new_rrs = ldns_dnssec_rrs_new();
72825eb42bSJan Lentfer 		new_rrs->rr = rrs->rr;
73825eb42bSJan Lentfer 		new_rrs->next = rrs->next;
74825eb42bSJan Lentfer 		rrs->rr = rr;
75825eb42bSJan Lentfer 		rrs->next = new_rrs;
76825eb42bSJan Lentfer 	}
77825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
78825eb42bSJan Lentfer }
79825eb42bSJan Lentfer 
80825eb42bSJan Lentfer void
81b5dedccaSJan Lentfer ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
82b5dedccaSJan Lentfer 	       ldns_dnssec_rrs *rrs)
83825eb42bSJan Lentfer {
84825eb42bSJan Lentfer 	if (!rrs) {
85b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86b5dedccaSJan Lentfer 			fprintf(out, "; <void>");
87825eb42bSJan Lentfer 	} else {
88825eb42bSJan Lentfer 		if (rrs->rr) {
89b5dedccaSJan Lentfer 			ldns_rr_print_fmt(out, fmt, rrs->rr);
90825eb42bSJan Lentfer 		}
91825eb42bSJan Lentfer 		if (rrs->next) {
92b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
93825eb42bSJan Lentfer 		}
94825eb42bSJan Lentfer 	}
95825eb42bSJan Lentfer }
96825eb42bSJan Lentfer 
97b5dedccaSJan Lentfer void
98b5dedccaSJan Lentfer ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
99b5dedccaSJan Lentfer {
100b5dedccaSJan Lentfer 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
101b5dedccaSJan Lentfer }
102b5dedccaSJan Lentfer 
103b5dedccaSJan Lentfer 
104825eb42bSJan Lentfer ldns_dnssec_rrsets *
105825eb42bSJan Lentfer ldns_dnssec_rrsets_new()
106825eb42bSJan Lentfer {
107825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
108825eb42bSJan Lentfer 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
109fd185f4dSJan Lentfer         if(!new_rrsets) return NULL;
110825eb42bSJan Lentfer 	new_rrsets->rrs = NULL;
111825eb42bSJan Lentfer 	new_rrsets->type = 0;
112825eb42bSJan Lentfer 	new_rrsets->signatures = NULL;
113825eb42bSJan Lentfer 	new_rrsets->next = NULL;
114825eb42bSJan Lentfer 	return new_rrsets;
115825eb42bSJan Lentfer }
116825eb42bSJan Lentfer 
117825eb42bSJan Lentfer INLINE void
118825eb42bSJan Lentfer ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119825eb42bSJan Lentfer {
120825eb42bSJan Lentfer 	if (rrsets) {
121825eb42bSJan Lentfer 		if (rrsets->rrs) {
122825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123825eb42bSJan Lentfer 		}
124825eb42bSJan Lentfer 		if (rrsets->next) {
125825eb42bSJan Lentfer 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126825eb42bSJan Lentfer 		}
127825eb42bSJan Lentfer 		if (rrsets->signatures) {
128825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129825eb42bSJan Lentfer 		}
130825eb42bSJan Lentfer 		LDNS_FREE(rrsets);
131825eb42bSJan Lentfer 	}
132825eb42bSJan Lentfer }
133825eb42bSJan Lentfer 
134825eb42bSJan Lentfer void
135825eb42bSJan Lentfer ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
136825eb42bSJan Lentfer {
137825eb42bSJan Lentfer 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
138825eb42bSJan Lentfer }
139825eb42bSJan Lentfer 
140825eb42bSJan Lentfer void
141825eb42bSJan Lentfer ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
142825eb42bSJan Lentfer {
143825eb42bSJan Lentfer 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
144825eb42bSJan Lentfer }
145825eb42bSJan Lentfer 
146825eb42bSJan Lentfer ldns_rr_type
147825eb42bSJan Lentfer ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
148825eb42bSJan Lentfer {
149825eb42bSJan Lentfer 	if (rrsets) {
150825eb42bSJan Lentfer 		return rrsets->type;
151825eb42bSJan Lentfer 	} else {
152825eb42bSJan Lentfer 		return 0;
153825eb42bSJan Lentfer 	}
154825eb42bSJan Lentfer }
155825eb42bSJan Lentfer 
156825eb42bSJan Lentfer ldns_status
157825eb42bSJan Lentfer ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
158825eb42bSJan Lentfer 					   ldns_rr_type type)
159825eb42bSJan Lentfer {
160825eb42bSJan Lentfer 	if (rrsets) {
161825eb42bSJan Lentfer 		rrsets->type = type;
162825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
163825eb42bSJan Lentfer 	}
164825eb42bSJan Lentfer 	return LDNS_STATUS_ERR;
165825eb42bSJan Lentfer }
166825eb42bSJan Lentfer 
167825eb42bSJan Lentfer ldns_dnssec_rrsets *
168825eb42bSJan Lentfer ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169825eb42bSJan Lentfer {
170825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
171825eb42bSJan Lentfer 	ldns_rr_type rr_type;
172825eb42bSJan Lentfer 	bool rrsig;
173825eb42bSJan Lentfer 
174825eb42bSJan Lentfer 	new_rrsets = ldns_dnssec_rrsets_new();
175825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
176825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
177825eb42bSJan Lentfer 		rrsig = true;
178825eb42bSJan Lentfer 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
179825eb42bSJan Lentfer 	} else {
180825eb42bSJan Lentfer 		rrsig = false;
181825eb42bSJan Lentfer 	}
182825eb42bSJan Lentfer 	if (!rrsig) {
183825eb42bSJan Lentfer 		new_rrsets->rrs = ldns_dnssec_rrs_new();
184825eb42bSJan Lentfer 		new_rrsets->rrs->rr = rr;
185825eb42bSJan Lentfer 	} else {
186825eb42bSJan Lentfer 		new_rrsets->signatures = ldns_dnssec_rrs_new();
187825eb42bSJan Lentfer 		new_rrsets->signatures->rr = rr;
188825eb42bSJan Lentfer 	}
189825eb42bSJan Lentfer 	new_rrsets->type = rr_type;
190825eb42bSJan Lentfer 	return new_rrsets;
191825eb42bSJan Lentfer }
192825eb42bSJan Lentfer 
193825eb42bSJan Lentfer ldns_status
194825eb42bSJan Lentfer ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
195825eb42bSJan Lentfer {
196825eb42bSJan Lentfer 	ldns_dnssec_rrsets *new_rrsets;
197825eb42bSJan Lentfer 	ldns_rr_type rr_type;
198825eb42bSJan Lentfer 	bool rrsig = false;
199825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
200825eb42bSJan Lentfer 
201825eb42bSJan Lentfer 	if (!rrsets || !rr) {
202825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
203825eb42bSJan Lentfer 	}
204825eb42bSJan Lentfer 
205825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
206825eb42bSJan Lentfer 
207825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
208825eb42bSJan Lentfer 		rrsig = true;
209825eb42bSJan Lentfer 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
210825eb42bSJan Lentfer 	}
211825eb42bSJan Lentfer 
212825eb42bSJan Lentfer 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213825eb42bSJan Lentfer 		if (!rrsig) {
214825eb42bSJan Lentfer 			rrsets->rrs = ldns_dnssec_rrs_new();
215825eb42bSJan Lentfer 			rrsets->rrs->rr = rr;
216825eb42bSJan Lentfer 			rrsets->type = rr_type;
217825eb42bSJan Lentfer 		} else {
218825eb42bSJan Lentfer 			rrsets->signatures = ldns_dnssec_rrs_new();
219825eb42bSJan Lentfer 			rrsets->signatures->rr = rr;
220825eb42bSJan Lentfer 			rrsets->type = rr_type;
221825eb42bSJan Lentfer 		}
222825eb42bSJan Lentfer 		return LDNS_STATUS_OK;
223825eb42bSJan Lentfer 	}
224825eb42bSJan Lentfer 
225825eb42bSJan Lentfer 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226825eb42bSJan Lentfer 		if (rrsets->next) {
227825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228825eb42bSJan Lentfer 		} else {
229825eb42bSJan Lentfer 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230825eb42bSJan Lentfer 			rrsets->next = new_rrsets;
231825eb42bSJan Lentfer 		}
232825eb42bSJan Lentfer 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
233825eb42bSJan Lentfer 		/* move the current one into the new next,
234825eb42bSJan Lentfer 		   replace field of current with data from new rr */
235825eb42bSJan Lentfer 		new_rrsets = ldns_dnssec_rrsets_new();
236825eb42bSJan Lentfer 		new_rrsets->rrs = rrsets->rrs;
237825eb42bSJan Lentfer 		new_rrsets->type = rrsets->type;
238825eb42bSJan Lentfer 		new_rrsets->signatures = rrsets->signatures;
239825eb42bSJan Lentfer 		new_rrsets->next = rrsets->next;
240825eb42bSJan Lentfer 		if (!rrsig) {
241825eb42bSJan Lentfer 			rrsets->rrs = ldns_dnssec_rrs_new();
242825eb42bSJan Lentfer 			rrsets->rrs->rr = rr;
243825eb42bSJan Lentfer 			rrsets->signatures = NULL;
244825eb42bSJan Lentfer 		} else {
245825eb42bSJan Lentfer 			rrsets->rrs = NULL;
246825eb42bSJan Lentfer 			rrsets->signatures = ldns_dnssec_rrs_new();
247825eb42bSJan Lentfer 			rrsets->signatures->rr = rr;
248825eb42bSJan Lentfer 		}
249825eb42bSJan Lentfer 		rrsets->type = rr_type;
250825eb42bSJan Lentfer 		rrsets->next = new_rrsets;
251825eb42bSJan Lentfer 	} else {
252825eb42bSJan Lentfer 		/* equal, add to current rrsets */
253825eb42bSJan Lentfer 		if (rrsig) {
254825eb42bSJan Lentfer 			if (rrsets->signatures) {
255825eb42bSJan Lentfer 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256825eb42bSJan Lentfer 			} else {
257825eb42bSJan Lentfer 				rrsets->signatures = ldns_dnssec_rrs_new();
258825eb42bSJan Lentfer 				rrsets->signatures->rr = rr;
259825eb42bSJan Lentfer 			}
260825eb42bSJan Lentfer 		} else {
261825eb42bSJan Lentfer 			if (rrsets->rrs) {
262825eb42bSJan Lentfer 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263825eb42bSJan Lentfer 			} else {
264825eb42bSJan Lentfer 				rrsets->rrs = ldns_dnssec_rrs_new();
265825eb42bSJan Lentfer 				rrsets->rrs->rr = rr;
266825eb42bSJan Lentfer 			}
267825eb42bSJan Lentfer 		}
268825eb42bSJan Lentfer 	}
269825eb42bSJan Lentfer 
270825eb42bSJan Lentfer 	return result;
271825eb42bSJan Lentfer }
272825eb42bSJan Lentfer 
273825eb42bSJan Lentfer void
274b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275825eb42bSJan Lentfer 		ldns_dnssec_rrsets *rrsets,
276825eb42bSJan Lentfer 		bool follow,
277825eb42bSJan Lentfer 		bool show_soa)
278825eb42bSJan Lentfer {
279825eb42bSJan Lentfer 	if (!rrsets) {
280b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281b5dedccaSJan Lentfer 			fprintf(out, "; <void>\n");
282825eb42bSJan Lentfer 	} else {
283825eb42bSJan Lentfer 		if (rrsets->rrs &&
284825eb42bSJan Lentfer 		    (show_soa ||
285825eb42bSJan Lentfer 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
286825eb42bSJan Lentfer 		    )
287825eb42bSJan Lentfer 		   ) {
288b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289825eb42bSJan Lentfer 			if (rrsets->signatures) {
290b5dedccaSJan Lentfer 				ldns_dnssec_rrs_print_fmt(out, fmt,
291b5dedccaSJan Lentfer 						rrsets->signatures);
292825eb42bSJan Lentfer 			}
293825eb42bSJan Lentfer 		}
294825eb42bSJan Lentfer 		if (follow && rrsets->next) {
295b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
296b5dedccaSJan Lentfer 					rrsets->next, follow, show_soa);
297825eb42bSJan Lentfer 		}
298825eb42bSJan Lentfer 	}
299825eb42bSJan Lentfer }
300825eb42bSJan Lentfer 
301825eb42bSJan Lentfer void
302b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_soa(FILE *out,
303b5dedccaSJan Lentfer 		ldns_dnssec_rrsets *rrsets,
304b5dedccaSJan Lentfer 		bool follow,
305b5dedccaSJan Lentfer 		bool show_soa)
306b5dedccaSJan Lentfer {
307b5dedccaSJan Lentfer 	ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default,
308b5dedccaSJan Lentfer 		       	rrsets, follow, show_soa);
309b5dedccaSJan Lentfer }
310b5dedccaSJan Lentfer 
311b5dedccaSJan Lentfer 
312b5dedccaSJan Lentfer void
313b5dedccaSJan Lentfer ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
314b5dedccaSJan Lentfer 		ldns_dnssec_rrsets *rrsets,
315b5dedccaSJan Lentfer 		bool follow)
316b5dedccaSJan Lentfer {
317b5dedccaSJan Lentfer 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
318b5dedccaSJan Lentfer }
319b5dedccaSJan Lentfer 
320b5dedccaSJan Lentfer void
321825eb42bSJan Lentfer ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
322825eb42bSJan Lentfer {
323b5dedccaSJan Lentfer 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
324b5dedccaSJan Lentfer 			rrsets, follow);
325825eb42bSJan Lentfer }
326825eb42bSJan Lentfer 
327825eb42bSJan Lentfer ldns_dnssec_name *
328825eb42bSJan Lentfer ldns_dnssec_name_new()
329825eb42bSJan Lentfer {
330825eb42bSJan Lentfer 	ldns_dnssec_name *new_name;
331825eb42bSJan Lentfer 
332b5dedccaSJan Lentfer 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
333825eb42bSJan Lentfer 	if (!new_name) {
334825eb42bSJan Lentfer 		return NULL;
335825eb42bSJan Lentfer 	}
336b5dedccaSJan Lentfer 	/*
337b5dedccaSJan Lentfer 	 * not needed anymore because CALLOC initalizes everything to zero.
338825eb42bSJan Lentfer 
339825eb42bSJan Lentfer 	new_name->name = NULL;
340825eb42bSJan Lentfer 	new_name->rrsets = NULL;
341825eb42bSJan Lentfer 	new_name->name_alloced = false;
342825eb42bSJan Lentfer 	new_name->nsec = NULL;
343825eb42bSJan Lentfer 	new_name->nsec_signatures = NULL;
344825eb42bSJan Lentfer 
345825eb42bSJan Lentfer 	new_name->is_glue = false;
346825eb42bSJan Lentfer 	new_name->hashed_name = NULL;
347825eb42bSJan Lentfer 
348b5dedccaSJan Lentfer 	 */
349825eb42bSJan Lentfer 	return new_name;
350825eb42bSJan Lentfer }
351825eb42bSJan Lentfer 
352825eb42bSJan Lentfer ldns_dnssec_name *
353825eb42bSJan Lentfer ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
354825eb42bSJan Lentfer {
355825eb42bSJan Lentfer 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
356825eb42bSJan Lentfer 
357825eb42bSJan Lentfer 	new_name->name = ldns_rr_owner(rr);
358fd185f4dSJan Lentfer 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
359fd185f4dSJan Lentfer 		ldns_dnssec_name_free(new_name);
360fd185f4dSJan Lentfer 		return NULL;
361fd185f4dSJan Lentfer 	}
362825eb42bSJan Lentfer 
363825eb42bSJan Lentfer 	return new_name;
364825eb42bSJan Lentfer }
365825eb42bSJan Lentfer 
366825eb42bSJan Lentfer INLINE void
367825eb42bSJan Lentfer ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
368825eb42bSJan Lentfer                                int deep)
369825eb42bSJan Lentfer {
370825eb42bSJan Lentfer 	if (name) {
371825eb42bSJan Lentfer 		if (name->name_alloced) {
372825eb42bSJan Lentfer 			ldns_rdf_deep_free(name->name);
373825eb42bSJan Lentfer 		}
374825eb42bSJan Lentfer 		if (name->rrsets) {
375825eb42bSJan Lentfer 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
376825eb42bSJan Lentfer 		}
377825eb42bSJan Lentfer 		if (name->nsec && deep) {
378825eb42bSJan Lentfer 			ldns_rr_free(name->nsec);
379825eb42bSJan Lentfer 		}
380825eb42bSJan Lentfer 		if (name->nsec_signatures) {
381825eb42bSJan Lentfer 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
382825eb42bSJan Lentfer 		}
383825eb42bSJan Lentfer 		if (name->hashed_name) {
384825eb42bSJan Lentfer 			if (deep) {
385825eb42bSJan Lentfer 				ldns_rdf_deep_free(name->hashed_name);
386825eb42bSJan Lentfer 			}
387825eb42bSJan Lentfer 		}
388825eb42bSJan Lentfer 		LDNS_FREE(name);
389825eb42bSJan Lentfer 	}
390825eb42bSJan Lentfer }
391825eb42bSJan Lentfer 
392825eb42bSJan Lentfer void
393825eb42bSJan Lentfer ldns_dnssec_name_free(ldns_dnssec_name *name)
394825eb42bSJan Lentfer {
395825eb42bSJan Lentfer   ldns_dnssec_name_free_internal(name, 0);
396825eb42bSJan Lentfer }
397825eb42bSJan Lentfer 
398825eb42bSJan Lentfer void
399825eb42bSJan Lentfer ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
400825eb42bSJan Lentfer {
401825eb42bSJan Lentfer   ldns_dnssec_name_free_internal(name, 1);
402825eb42bSJan Lentfer }
403825eb42bSJan Lentfer 
404825eb42bSJan Lentfer ldns_rdf *
405825eb42bSJan Lentfer ldns_dnssec_name_name(ldns_dnssec_name *name)
406825eb42bSJan Lentfer {
407825eb42bSJan Lentfer 	if (name) {
408825eb42bSJan Lentfer 		return name->name;
409825eb42bSJan Lentfer 	}
410825eb42bSJan Lentfer 	return NULL;
411825eb42bSJan Lentfer }
412825eb42bSJan Lentfer 
413b5dedccaSJan Lentfer bool
414b5dedccaSJan Lentfer ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
415b5dedccaSJan Lentfer {
416b5dedccaSJan Lentfer 	if (name) {
417b5dedccaSJan Lentfer 		return name->is_glue;
418b5dedccaSJan Lentfer 	}
419b5dedccaSJan Lentfer 	return false;
420b5dedccaSJan Lentfer }
421b5dedccaSJan Lentfer 
422825eb42bSJan Lentfer void
423825eb42bSJan Lentfer ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
424825eb42bSJan Lentfer 					 ldns_rdf *dname)
425825eb42bSJan Lentfer {
426825eb42bSJan Lentfer 	if (rrset && dname) {
427825eb42bSJan Lentfer 		rrset->name = dname;
428825eb42bSJan Lentfer 	}
429825eb42bSJan Lentfer }
430825eb42bSJan Lentfer 
431825eb42bSJan Lentfer ldns_rr *
432825eb42bSJan Lentfer ldns_dnssec_name_nsec(ldns_dnssec_name *rrset)
433825eb42bSJan Lentfer {
434825eb42bSJan Lentfer 	if (rrset) {
435825eb42bSJan Lentfer 		return rrset->nsec;
436825eb42bSJan Lentfer 	}
437825eb42bSJan Lentfer 	return NULL;
438825eb42bSJan Lentfer }
439825eb42bSJan Lentfer 
440825eb42bSJan Lentfer void
441825eb42bSJan Lentfer ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
442825eb42bSJan Lentfer {
443825eb42bSJan Lentfer 	if (rrset && nsec) {
444825eb42bSJan Lentfer 		rrset->nsec = nsec;
445825eb42bSJan Lentfer 	}
446825eb42bSJan Lentfer }
447825eb42bSJan Lentfer 
448825eb42bSJan Lentfer int
449825eb42bSJan Lentfer ldns_dnssec_name_cmp(const void *a, const void *b)
450825eb42bSJan Lentfer {
451825eb42bSJan Lentfer 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
452825eb42bSJan Lentfer 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
453825eb42bSJan Lentfer 
454825eb42bSJan Lentfer 	if (na && nb) {
455825eb42bSJan Lentfer 		return ldns_dname_compare(ldns_dnssec_name_name(na),
456825eb42bSJan Lentfer 							 ldns_dnssec_name_name(nb));
457825eb42bSJan Lentfer 	} else if (na) {
458825eb42bSJan Lentfer 		return 1;
459825eb42bSJan Lentfer 	} else if (nb) {
460825eb42bSJan Lentfer 		return -1;
461825eb42bSJan Lentfer 	} else {
462825eb42bSJan Lentfer 		return 0;
463825eb42bSJan Lentfer 	}
464825eb42bSJan Lentfer }
465825eb42bSJan Lentfer 
466825eb42bSJan Lentfer ldns_status
467825eb42bSJan Lentfer ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
468825eb42bSJan Lentfer 				    ldns_rr *rr)
469825eb42bSJan Lentfer {
470825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
471825eb42bSJan Lentfer 	ldns_rdf *name_name;
472825eb42bSJan Lentfer 	bool hashed_name = false;
473ac996e71SJan Lentfer 	ldns_rr_type rr_type;
474825eb42bSJan Lentfer 	ldns_rr_type typecovered = 0;
475825eb42bSJan Lentfer 
476825eb42bSJan Lentfer 	/* special handling for NSEC3 and NSECX covering RRSIGS */
477825eb42bSJan Lentfer 
478825eb42bSJan Lentfer 	if (!name || !rr) {
479825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
480825eb42bSJan Lentfer 	}
481825eb42bSJan Lentfer 
482825eb42bSJan Lentfer 	rr_type = ldns_rr_get_type(rr);
483825eb42bSJan Lentfer 
484825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
485825eb42bSJan Lentfer 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
486825eb42bSJan Lentfer 	}
487825eb42bSJan Lentfer 
488825eb42bSJan Lentfer #ifdef HAVE_SSL
489825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_NSEC3 ||
490825eb42bSJan Lentfer 	    typecovered == LDNS_RR_TYPE_NSEC3) {
491825eb42bSJan Lentfer 		name_name = ldns_nsec3_hash_name_frm_nsec3(rr,
492825eb42bSJan Lentfer 										   ldns_dnssec_name_name(name));
493825eb42bSJan Lentfer 		hashed_name = true;
494825eb42bSJan Lentfer 	} else {
495825eb42bSJan Lentfer 		name_name = ldns_dnssec_name_name(name);
496825eb42bSJan Lentfer 	}
497825eb42bSJan Lentfer #else
498825eb42bSJan Lentfer 	name_name = ldns_dnssec_name_name(name);
499825eb42bSJan Lentfer #endif /* HAVE_SSL */
500825eb42bSJan Lentfer 
501825eb42bSJan Lentfer 	if (rr_type == LDNS_RR_TYPE_NSEC ||
502825eb42bSJan Lentfer 	    rr_type == LDNS_RR_TYPE_NSEC3) {
503825eb42bSJan Lentfer 		/* XX check if is already set (and error?) */
504825eb42bSJan Lentfer 		name->nsec = rr;
505825eb42bSJan Lentfer 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
506825eb42bSJan Lentfer 			 typecovered == LDNS_RR_TYPE_NSEC3) {
507825eb42bSJan Lentfer 		if (name->nsec_signatures) {
508fd185f4dSJan Lentfer 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
509825eb42bSJan Lentfer 		} else {
510825eb42bSJan Lentfer 			name->nsec_signatures = ldns_dnssec_rrs_new();
511825eb42bSJan Lentfer 			name->nsec_signatures->rr = rr;
512825eb42bSJan Lentfer 		}
513825eb42bSJan Lentfer 	} else {
514825eb42bSJan Lentfer 		/* it's a 'normal' RR, add it to the right rrset */
515825eb42bSJan Lentfer 		if (name->rrsets) {
516825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
517825eb42bSJan Lentfer 		} else {
518825eb42bSJan Lentfer 			name->rrsets = ldns_dnssec_rrsets_new();
519825eb42bSJan Lentfer 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
520825eb42bSJan Lentfer 		}
521825eb42bSJan Lentfer 	}
522825eb42bSJan Lentfer 
523825eb42bSJan Lentfer 	if (hashed_name) {
524825eb42bSJan Lentfer 		ldns_rdf_deep_free(name_name);
525825eb42bSJan Lentfer 	}
526825eb42bSJan Lentfer 
527825eb42bSJan Lentfer 	return result;
528825eb42bSJan Lentfer }
529825eb42bSJan Lentfer 
530825eb42bSJan Lentfer ldns_dnssec_rrsets *
531825eb42bSJan Lentfer ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
532825eb42bSJan Lentfer 					   ldns_rr_type type) {
533825eb42bSJan Lentfer 	ldns_dnssec_rrsets *result;
534825eb42bSJan Lentfer 
535825eb42bSJan Lentfer 	result = name->rrsets;
536825eb42bSJan Lentfer 	while (result) {
537825eb42bSJan Lentfer 		if (result->type == type) {
538825eb42bSJan Lentfer 			return result;
539825eb42bSJan Lentfer 		} else {
540825eb42bSJan Lentfer 			result = result->next;
541825eb42bSJan Lentfer 		}
542825eb42bSJan Lentfer 	}
543825eb42bSJan Lentfer 	return NULL;
544825eb42bSJan Lentfer }
545825eb42bSJan Lentfer 
546825eb42bSJan Lentfer ldns_dnssec_rrsets *
547825eb42bSJan Lentfer ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
548825eb42bSJan Lentfer 					   ldns_rdf *dname,
549825eb42bSJan Lentfer 					   ldns_rr_type type)
550825eb42bSJan Lentfer {
551825eb42bSJan Lentfer 	ldns_rbnode_t *node;
552825eb42bSJan Lentfer 
553825eb42bSJan Lentfer 	if (!zone || !dname) {
554825eb42bSJan Lentfer 		return NULL;
555825eb42bSJan Lentfer 	}
556825eb42bSJan Lentfer 
557825eb42bSJan Lentfer 	node = ldns_rbtree_search(zone->names, dname);
558825eb42bSJan Lentfer 	if (node) {
559825eb42bSJan Lentfer 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
560825eb42bSJan Lentfer 									type);
561825eb42bSJan Lentfer 	} else {
562825eb42bSJan Lentfer 		return NULL;
563825eb42bSJan Lentfer 	}
564825eb42bSJan Lentfer }
565825eb42bSJan Lentfer 
566825eb42bSJan Lentfer void
567b5dedccaSJan Lentfer ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
568b5dedccaSJan Lentfer 		ldns_dnssec_name *name,
569b5dedccaSJan Lentfer 		bool show_soa)
570825eb42bSJan Lentfer {
571825eb42bSJan Lentfer 	if (name) {
572825eb42bSJan Lentfer 		if(name->rrsets) {
573b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
574b5dedccaSJan Lentfer 					name->rrsets, true, show_soa);
575b5dedccaSJan Lentfer 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
576825eb42bSJan Lentfer 			fprintf(out, ";; Empty nonterminal: ");
577825eb42bSJan Lentfer 			ldns_rdf_print(out, name->name);
578825eb42bSJan Lentfer 			fprintf(out, "\n");
579825eb42bSJan Lentfer 		}
580825eb42bSJan Lentfer 		if(name->nsec) {
581b5dedccaSJan Lentfer 			ldns_rr_print_fmt(out, fmt, name->nsec);
582825eb42bSJan Lentfer 		}
583825eb42bSJan Lentfer 		if (name->nsec_signatures) {
584b5dedccaSJan Lentfer 			ldns_dnssec_rrs_print_fmt(out, fmt,
585b5dedccaSJan Lentfer 					name->nsec_signatures);
586825eb42bSJan Lentfer 		}
587b5dedccaSJan Lentfer 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
588b5dedccaSJan Lentfer 		fprintf(out, "; <void>\n");
589825eb42bSJan Lentfer 	}
590825eb42bSJan Lentfer }
591825eb42bSJan Lentfer 
592825eb42bSJan Lentfer void
593b5dedccaSJan Lentfer ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa)
594b5dedccaSJan Lentfer {
595b5dedccaSJan Lentfer 	ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default,
596b5dedccaSJan Lentfer 		       name, show_soa);
597b5dedccaSJan Lentfer }
598b5dedccaSJan Lentfer 
599b5dedccaSJan Lentfer void
600b5dedccaSJan Lentfer ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
601b5dedccaSJan Lentfer 		ldns_dnssec_name *name)
602b5dedccaSJan Lentfer {
603b5dedccaSJan Lentfer 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
604b5dedccaSJan Lentfer }
605b5dedccaSJan Lentfer 
606b5dedccaSJan Lentfer void
607825eb42bSJan Lentfer ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
608825eb42bSJan Lentfer {
609b5dedccaSJan Lentfer 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
610825eb42bSJan Lentfer }
611825eb42bSJan Lentfer 
612b5dedccaSJan Lentfer 
613825eb42bSJan Lentfer ldns_dnssec_zone *
614825eb42bSJan Lentfer ldns_dnssec_zone_new()
615825eb42bSJan Lentfer {
616825eb42bSJan Lentfer 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
617fd185f4dSJan Lentfer         if(!zone) return NULL;
618825eb42bSJan Lentfer 	zone->soa = NULL;
619825eb42bSJan Lentfer 	zone->names = NULL;
620825eb42bSJan Lentfer 
621825eb42bSJan Lentfer 	return zone;
622825eb42bSJan Lentfer }
623825eb42bSJan Lentfer 
624*d1b2b5caSJohn Marino static bool
625*d1b2b5caSJohn Marino rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
626*d1b2b5caSJohn Marino {
627*d1b2b5caSJohn Marino 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
628*d1b2b5caSJohn Marino 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
629*d1b2b5caSJohn Marino }
630*d1b2b5caSJohn Marino 
631*d1b2b5caSJohn Marino /* When the zone is first read into an list and then inserted into an
632*d1b2b5caSJohn Marino  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
633*d1b2b5caSJohn Marino  * to each other. Because ldns-verify-zone (the only program that uses this
634*d1b2b5caSJohn Marino  * function) uses the rbtree mostly for sequentual walking, this results
635*d1b2b5caSJohn Marino  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
636*d1b2b5caSJohn Marino  */
637*d1b2b5caSJohn Marino #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
638*d1b2b5caSJohn Marino 
639*d1b2b5caSJohn Marino ldns_status
640*d1b2b5caSJohn Marino ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
641*d1b2b5caSJohn Marino 	       	uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
642*d1b2b5caSJohn Marino {
643*d1b2b5caSJohn Marino 	ldns_rr* cur_rr;
644*d1b2b5caSJohn Marino 	size_t i;
645*d1b2b5caSJohn Marino 
646*d1b2b5caSJohn Marino 	ldns_rdf *my_origin = NULL;
647*d1b2b5caSJohn Marino 	ldns_rdf *my_prev = NULL;
648*d1b2b5caSJohn Marino 
649*d1b2b5caSJohn Marino 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
650*d1b2b5caSJohn Marino 	/* when reading NSEC3s, there is a chance that we encounter nsecs
651*d1b2b5caSJohn Marino 	   for empty nonterminals, whose nonterminals we cannot derive yet
652*d1b2b5caSJohn Marino 	   because the needed information is to be read later. in that case
653*d1b2b5caSJohn Marino 	   we keep a list of those nsec3's and retry to add them later */
654*d1b2b5caSJohn Marino 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
655*d1b2b5caSJohn Marino 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
656*d1b2b5caSJohn Marino 
657*d1b2b5caSJohn Marino 	ldns_status status = LDNS_STATUS_MEM_ERR;
658*d1b2b5caSJohn Marino 
659*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
660*d1b2b5caSJohn Marino 	ldns_zone* zone = NULL;
661*d1b2b5caSJohn Marino 	if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr)
662*d1b2b5caSJohn Marino 			!= LDNS_STATUS_OK) goto error;
663*d1b2b5caSJohn Marino #else
664*d1b2b5caSJohn Marino 	uint32_t  my_ttl = ttl;
665*d1b2b5caSJohn Marino #endif
666*d1b2b5caSJohn Marino 
667*d1b2b5caSJohn Marino 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error;
668*d1b2b5caSJohn Marino 
669*d1b2b5caSJohn Marino 	if (origin) {
670*d1b2b5caSJohn Marino 		if (!(my_origin = ldns_rdf_clone(origin))) goto error;
671*d1b2b5caSJohn Marino 		if (!(my_prev   = ldns_rdf_clone(origin))) goto error;
672*d1b2b5caSJohn Marino 	}
673*d1b2b5caSJohn Marino 
674*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
675*d1b2b5caSJohn Marino 	if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone))
676*d1b2b5caSJohn Marino 			!= LDNS_STATUS_OK) goto error;
677*d1b2b5caSJohn Marino 
678*d1b2b5caSJohn Marino 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679*d1b2b5caSJohn Marino 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680*d1b2b5caSJohn Marino 		status = LDNS_STATUS_OK;
681*d1b2b5caSJohn Marino #else
682*d1b2b5caSJohn Marino 	while (!feof(fp)) {
683*d1b2b5caSJohn Marino 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
684*d1b2b5caSJohn Marino 				&my_prev, line_nr);
685*d1b2b5caSJohn Marino 
686*d1b2b5caSJohn Marino #endif
687*d1b2b5caSJohn Marino 		switch (status) {
688*d1b2b5caSJohn Marino 		case LDNS_STATUS_OK:
689*d1b2b5caSJohn Marino 
690*d1b2b5caSJohn Marino 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
691*d1b2b5caSJohn Marino 			if (status ==
692*d1b2b5caSJohn Marino 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
693*d1b2b5caSJohn Marino 
694*d1b2b5caSJohn Marino 				if (rr_is_rrsig_covering(cur_rr,
695*d1b2b5caSJohn Marino 							LDNS_RR_TYPE_NSEC3)){
696*d1b2b5caSJohn Marino 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
697*d1b2b5caSJohn Marino 							cur_rr);
698*d1b2b5caSJohn Marino 				} else {
699*d1b2b5caSJohn Marino 					ldns_rr_list_push_rr(todo_nsec3s,
700*d1b2b5caSJohn Marino 						       	cur_rr);
701*d1b2b5caSJohn Marino 				}
702*d1b2b5caSJohn Marino 			} else if (status != LDNS_STATUS_OK)
703*d1b2b5caSJohn Marino 				goto error;
704*d1b2b5caSJohn Marino 
705*d1b2b5caSJohn Marino 			break;
706*d1b2b5caSJohn Marino 
707*d1b2b5caSJohn Marino 
708*d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
709*d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
710*d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
711*d1b2b5caSJohn Marino 			status = LDNS_STATUS_OK;
712*d1b2b5caSJohn Marino 			break;
713*d1b2b5caSJohn Marino 
714*d1b2b5caSJohn Marino 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
715*d1b2b5caSJohn Marino 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
716*d1b2b5caSJohn Marino 			break;
717*d1b2b5caSJohn Marino 
718*d1b2b5caSJohn Marino 		default:
719*d1b2b5caSJohn Marino 			goto error;
720*d1b2b5caSJohn Marino 		}
721*d1b2b5caSJohn Marino 	}
722*d1b2b5caSJohn Marino 
723*d1b2b5caSJohn Marino 	if (ldns_rr_list_rr_count(todo_nsec3s) > 0) {
724*d1b2b5caSJohn Marino 		(void) ldns_dnssec_zone_add_empty_nonterminals(newzone);
725*d1b2b5caSJohn Marino 		for (i = 0; status == LDNS_STATUS_OK &&
726*d1b2b5caSJohn Marino 				i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
727*d1b2b5caSJohn Marino 			cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
728*d1b2b5caSJohn Marino 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
729*d1b2b5caSJohn Marino 		}
730*d1b2b5caSJohn Marino 		for (i = 0; status == LDNS_STATUS_OK &&
731*d1b2b5caSJohn Marino 				i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
732*d1b2b5caSJohn Marino 			       	i++){
733*d1b2b5caSJohn Marino 			cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
734*d1b2b5caSJohn Marino 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
735*d1b2b5caSJohn Marino 		}
736*d1b2b5caSJohn Marino 	} else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) {
737*d1b2b5caSJohn Marino 		for (i = 0; status == LDNS_STATUS_OK &&
738*d1b2b5caSJohn Marino 				i < ldns_rr_list_rr_count(todo_nsec3_rrsigs);
739*d1b2b5caSJohn Marino 				i++){
740*d1b2b5caSJohn Marino 			cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
741*d1b2b5caSJohn Marino 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
742*d1b2b5caSJohn Marino 		}
743*d1b2b5caSJohn Marino 	}
744*d1b2b5caSJohn Marino 
745*d1b2b5caSJohn Marino 	if (z) {
746*d1b2b5caSJohn Marino 		*z = newzone;
747*d1b2b5caSJohn Marino 		newzone = NULL;
748*d1b2b5caSJohn Marino 	} else {
749*d1b2b5caSJohn Marino 		ldns_dnssec_zone_free(newzone);
750*d1b2b5caSJohn Marino 	}
751*d1b2b5caSJohn Marino 
752*d1b2b5caSJohn Marino error:
753*d1b2b5caSJohn Marino #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
754*d1b2b5caSJohn Marino 	if (zone) {
755*d1b2b5caSJohn Marino 		ldns_zone_free(zone);
756*d1b2b5caSJohn Marino 	}
757*d1b2b5caSJohn Marino #endif
758*d1b2b5caSJohn Marino 	ldns_rr_list_free(todo_nsec3_rrsigs);
759*d1b2b5caSJohn Marino 	ldns_rr_list_free(todo_nsec3s);
760*d1b2b5caSJohn Marino 
761*d1b2b5caSJohn Marino 	if (my_origin) {
762*d1b2b5caSJohn Marino 		ldns_rdf_deep_free(my_origin);
763*d1b2b5caSJohn Marino 	}
764*d1b2b5caSJohn Marino 	if (my_prev) {
765*d1b2b5caSJohn Marino 		ldns_rdf_deep_free(my_prev);
766*d1b2b5caSJohn Marino 	}
767*d1b2b5caSJohn Marino 	if (newzone) {
768*d1b2b5caSJohn Marino 		ldns_dnssec_zone_free(newzone);
769*d1b2b5caSJohn Marino 	}
770*d1b2b5caSJohn Marino 	return status;
771*d1b2b5caSJohn Marino }
772*d1b2b5caSJohn Marino 
773*d1b2b5caSJohn Marino ldns_status
774*d1b2b5caSJohn Marino ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
775*d1b2b5caSJohn Marino 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
776*d1b2b5caSJohn Marino {
777*d1b2b5caSJohn Marino 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
778*d1b2b5caSJohn Marino }
779*d1b2b5caSJohn Marino 
780825eb42bSJan Lentfer void
781825eb42bSJan Lentfer ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
782825eb42bSJan Lentfer 	(void) arg;
783825eb42bSJan Lentfer 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
784*d1b2b5caSJohn Marino 	LDNS_FREE(node);
785825eb42bSJan Lentfer }
786825eb42bSJan Lentfer 
787825eb42bSJan Lentfer void
788825eb42bSJan Lentfer ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
789825eb42bSJan Lentfer 	(void) arg;
790825eb42bSJan Lentfer 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
791*d1b2b5caSJohn Marino 	LDNS_FREE(node);
792825eb42bSJan Lentfer }
793825eb42bSJan Lentfer 
794825eb42bSJan Lentfer void
795825eb42bSJan Lentfer ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
796825eb42bSJan Lentfer {
797825eb42bSJan Lentfer 	if (zone) {
798825eb42bSJan Lentfer 		if (zone->names) {
799825eb42bSJan Lentfer 			/* destroy all name structures within the tree */
800825eb42bSJan Lentfer 			ldns_traverse_postorder(zone->names,
801825eb42bSJan Lentfer 						    ldns_dnssec_name_node_free,
802825eb42bSJan Lentfer 						    NULL);
803*d1b2b5caSJohn Marino 			LDNS_FREE(zone->names);
804825eb42bSJan Lentfer 		}
805825eb42bSJan Lentfer 		LDNS_FREE(zone);
806825eb42bSJan Lentfer 	}
807825eb42bSJan Lentfer }
808825eb42bSJan Lentfer 
809825eb42bSJan Lentfer void
810825eb42bSJan Lentfer ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
811825eb42bSJan Lentfer {
812825eb42bSJan Lentfer 	if (zone) {
813825eb42bSJan Lentfer 		if (zone->names) {
814825eb42bSJan Lentfer 			/* destroy all name structures within the tree */
815825eb42bSJan Lentfer 			ldns_traverse_postorder(zone->names,
816825eb42bSJan Lentfer 						    ldns_dnssec_name_node_deep_free,
817825eb42bSJan Lentfer 						    NULL);
818*d1b2b5caSJohn Marino 			LDNS_FREE(zone->names);
819825eb42bSJan Lentfer 		}
820825eb42bSJan Lentfer 		LDNS_FREE(zone);
821825eb42bSJan Lentfer 	}
822825eb42bSJan Lentfer }
823825eb42bSJan Lentfer 
824825eb42bSJan Lentfer /* use for dname comparison in tree */
825825eb42bSJan Lentfer int
826825eb42bSJan Lentfer ldns_dname_compare_v(const void *a, const void *b) {
827825eb42bSJan Lentfer 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
828825eb42bSJan Lentfer }
829825eb42bSJan Lentfer 
830825eb42bSJan Lentfer ldns_rbnode_t *
831825eb42bSJan Lentfer ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone,
832825eb42bSJan Lentfer                                      ldns_rr *rr) {
833825eb42bSJan Lentfer 	ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names);
834825eb42bSJan Lentfer 	ldns_dnssec_name *current_name;
835825eb42bSJan Lentfer 	ldns_rdf *hashed_name;
836825eb42bSJan Lentfer 
837825eb42bSJan Lentfer 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
838825eb42bSJan Lentfer 
839825eb42bSJan Lentfer 	while (current_node != LDNS_RBTREE_NULL) {
840825eb42bSJan Lentfer 		current_name = (ldns_dnssec_name *) current_node->data;
841825eb42bSJan Lentfer 		if (!current_name->hashed_name) {
842825eb42bSJan Lentfer 			current_name->hashed_name =
843825eb42bSJan Lentfer 				ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name);
844825eb42bSJan Lentfer 		}
845825eb42bSJan Lentfer 		if (ldns_dname_compare(hashed_name,
846825eb42bSJan Lentfer 						   current_name->hashed_name)
847825eb42bSJan Lentfer 		    == 0) {
848825eb42bSJan Lentfer 			ldns_rdf_deep_free(hashed_name);
849825eb42bSJan Lentfer 			return current_node;
850825eb42bSJan Lentfer 		}
851825eb42bSJan Lentfer 		current_node = ldns_rbtree_next(current_node);
852825eb42bSJan Lentfer 	}
853825eb42bSJan Lentfer 	ldns_rdf_deep_free(hashed_name);
854825eb42bSJan Lentfer 	return NULL;
855825eb42bSJan Lentfer }
856825eb42bSJan Lentfer 
857825eb42bSJan Lentfer ldns_status
858825eb42bSJan Lentfer ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
859825eb42bSJan Lentfer {
860825eb42bSJan Lentfer 	ldns_status result = LDNS_STATUS_OK;
861825eb42bSJan Lentfer 	ldns_dnssec_name *cur_name;
862825eb42bSJan Lentfer 	ldns_rbnode_t *cur_node;
863825eb42bSJan Lentfer 	ldns_rr_type type_covered = 0;
864825eb42bSJan Lentfer 
865825eb42bSJan Lentfer 	if (!zone || !rr) {
866825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
867825eb42bSJan Lentfer 	}
868825eb42bSJan Lentfer 
869825eb42bSJan Lentfer 	if (!zone->names) {
870825eb42bSJan Lentfer 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
871fd185f4dSJan Lentfer                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
872825eb42bSJan Lentfer 	}
873825eb42bSJan Lentfer 
874825eb42bSJan Lentfer 	/* we need the original of the hashed name if this is
875825eb42bSJan Lentfer 	   an NSEC3, or an RRSIG that covers an NSEC3 */
876825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
877825eb42bSJan Lentfer 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
878825eb42bSJan Lentfer 	}
879825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
880825eb42bSJan Lentfer 	    type_covered == LDNS_RR_TYPE_NSEC3) {
881825eb42bSJan Lentfer 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone,
882825eb42bSJan Lentfer 					 						   rr);
883825eb42bSJan Lentfer 		if (!cur_node) {
884825eb42bSJan Lentfer 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
885825eb42bSJan Lentfer 		}
886825eb42bSJan Lentfer 	} else {
887825eb42bSJan Lentfer 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
888825eb42bSJan Lentfer 	}
889825eb42bSJan Lentfer 
890825eb42bSJan Lentfer 	if (!cur_node) {
891825eb42bSJan Lentfer 		/* add */
892825eb42bSJan Lentfer 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
893fd185f4dSJan Lentfer                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
894825eb42bSJan Lentfer 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
895fd185f4dSJan Lentfer                 if(!cur_node) {
896fd185f4dSJan Lentfer                         ldns_dnssec_name_free(cur_name);
897fd185f4dSJan Lentfer                         return LDNS_STATUS_MEM_ERR;
898fd185f4dSJan Lentfer                 }
899825eb42bSJan Lentfer 		cur_node->key = ldns_rr_owner(rr);
900825eb42bSJan Lentfer 		cur_node->data = cur_name;
901fd185f4dSJan Lentfer 		(void)ldns_rbtree_insert(zone->names, cur_node);
902825eb42bSJan Lentfer 	} else {
903825eb42bSJan Lentfer 		cur_name = (ldns_dnssec_name *) cur_node->data;
904fd185f4dSJan Lentfer 		result = ldns_dnssec_name_add_rr(cur_name, rr);
905825eb42bSJan Lentfer 	}
906825eb42bSJan Lentfer 
907825eb42bSJan Lentfer 	if (result != LDNS_STATUS_OK) {
908825eb42bSJan Lentfer 		fprintf(stderr, "error adding rr: ");
909825eb42bSJan Lentfer 		ldns_rr_print(stderr, rr);
910825eb42bSJan Lentfer 	}
911825eb42bSJan Lentfer 
912825eb42bSJan Lentfer 	/*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/
913825eb42bSJan Lentfer 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
914825eb42bSJan Lentfer 		zone->soa = cur_name;
915825eb42bSJan Lentfer 	}
916825eb42bSJan Lentfer 
917825eb42bSJan Lentfer 	return result;
918825eb42bSJan Lentfer }
919825eb42bSJan Lentfer 
920825eb42bSJan Lentfer void
921b5dedccaSJan Lentfer ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
922b5dedccaSJan Lentfer 		ldns_rbtree_t *tree,
923b5dedccaSJan Lentfer 		bool print_soa)
924825eb42bSJan Lentfer {
925825eb42bSJan Lentfer 	ldns_rbnode_t *node;
926825eb42bSJan Lentfer 	ldns_dnssec_name *name;
927825eb42bSJan Lentfer 
928825eb42bSJan Lentfer 	node = ldns_rbtree_first(tree);
929825eb42bSJan Lentfer 	while (node != LDNS_RBTREE_NULL) {
930825eb42bSJan Lentfer 		name = (ldns_dnssec_name *) node->data;
931b5dedccaSJan Lentfer 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
932b5dedccaSJan Lentfer 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
933825eb42bSJan Lentfer 			fprintf(out, ";\n");
934825eb42bSJan Lentfer 		node = ldns_rbtree_next(node);
935825eb42bSJan Lentfer 	}
936825eb42bSJan Lentfer }
937825eb42bSJan Lentfer 
938825eb42bSJan Lentfer void
939b5dedccaSJan Lentfer ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
940b5dedccaSJan Lentfer {
941b5dedccaSJan Lentfer 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
942b5dedccaSJan Lentfer 		       tree, print_soa);
943b5dedccaSJan Lentfer }
944b5dedccaSJan Lentfer 
945b5dedccaSJan Lentfer void
946b5dedccaSJan Lentfer ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
947b5dedccaSJan Lentfer 	       ldns_dnssec_zone *zone)
948825eb42bSJan Lentfer {
949825eb42bSJan Lentfer 	if (zone) {
950825eb42bSJan Lentfer 		if (zone->soa) {
951b5dedccaSJan Lentfer 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
952825eb42bSJan Lentfer 				fprintf(out, ";; Zone: ");
953b5dedccaSJan Lentfer 				ldns_rdf_print(out, ldns_dnssec_name_name(
954b5dedccaSJan Lentfer 							zone->soa));
955825eb42bSJan Lentfer 				fprintf(out, "\n;\n");
956b5dedccaSJan Lentfer 			}
957b5dedccaSJan Lentfer 			ldns_dnssec_rrsets_print_fmt(out, fmt,
958b5dedccaSJan Lentfer 					ldns_dnssec_name_find_rrset(
959b5dedccaSJan Lentfer 						zone->soa,
960825eb42bSJan Lentfer 						LDNS_RR_TYPE_SOA),
961825eb42bSJan Lentfer 					false);
962b5dedccaSJan Lentfer 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
963825eb42bSJan Lentfer 				fprintf(out, ";\n");
964825eb42bSJan Lentfer 		}
965825eb42bSJan Lentfer 
966825eb42bSJan Lentfer 		if (zone->names) {
967b5dedccaSJan Lentfer 			ldns_dnssec_zone_names_print_fmt(out, fmt,
968b5dedccaSJan Lentfer 					zone->names, false);
969825eb42bSJan Lentfer 		}
970825eb42bSJan Lentfer 	}
971825eb42bSJan Lentfer }
972825eb42bSJan Lentfer 
973b5dedccaSJan Lentfer void
974b5dedccaSJan Lentfer ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
975b5dedccaSJan Lentfer {
976b5dedccaSJan Lentfer 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
977b5dedccaSJan Lentfer }
978b5dedccaSJan Lentfer 
979825eb42bSJan Lentfer ldns_status
980825eb42bSJan Lentfer ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
981825eb42bSJan Lentfer {
982825eb42bSJan Lentfer 	ldns_dnssec_name *new_name;
983825eb42bSJan Lentfer 	ldns_rdf *cur_name;
984825eb42bSJan Lentfer 	ldns_rdf *next_name;
985825eb42bSJan Lentfer 	ldns_rbnode_t *cur_node, *next_node, *new_node;
986825eb42bSJan Lentfer 
987825eb42bSJan Lentfer 	/* for the detection */
988825eb42bSJan Lentfer 	uint16_t i, cur_label_count, next_label_count;
989825eb42bSJan Lentfer 	uint16_t soa_label_count = 0;
990825eb42bSJan Lentfer 	ldns_rdf *l1, *l2;
991825eb42bSJan Lentfer 	int lpos;
992825eb42bSJan Lentfer 
993825eb42bSJan Lentfer 	if (!zone) {
994825eb42bSJan Lentfer 		return LDNS_STATUS_ERR;
995825eb42bSJan Lentfer 	}
996825eb42bSJan Lentfer 	if (zone->soa && zone->soa->name) {
997825eb42bSJan Lentfer 		soa_label_count = ldns_dname_label_count(zone->soa->name);
998825eb42bSJan Lentfer 	}
999825eb42bSJan Lentfer 
1000825eb42bSJan Lentfer 	cur_node = ldns_rbtree_first(zone->names);
1001825eb42bSJan Lentfer 	while (cur_node != LDNS_RBTREE_NULL) {
1002825eb42bSJan Lentfer 		next_node = ldns_rbtree_next(cur_node);
1003825eb42bSJan Lentfer 
1004825eb42bSJan Lentfer 		/* skip glue */
1005825eb42bSJan Lentfer 		while (next_node != LDNS_RBTREE_NULL &&
1006825eb42bSJan Lentfer 		       next_node->data &&
1007825eb42bSJan Lentfer 		       ((ldns_dnssec_name *)next_node->data)->is_glue
1008825eb42bSJan Lentfer 		) {
1009825eb42bSJan Lentfer 			next_node = ldns_rbtree_next(next_node);
1010825eb42bSJan Lentfer 		}
1011825eb42bSJan Lentfer 
1012825eb42bSJan Lentfer 		if (next_node == LDNS_RBTREE_NULL) {
1013825eb42bSJan Lentfer 			next_node = ldns_rbtree_first(zone->names);
1014825eb42bSJan Lentfer 		}
1015*d1b2b5caSJohn Marino 		if (! cur_node->data || ! next_node->data) {
1016*d1b2b5caSJohn Marino 			return LDNS_STATUS_ERR;
1017*d1b2b5caSJohn Marino 		}
1018825eb42bSJan Lentfer 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1019825eb42bSJan Lentfer 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
1020825eb42bSJan Lentfer 		cur_label_count = ldns_dname_label_count(cur_name);
1021825eb42bSJan Lentfer 		next_label_count = ldns_dname_label_count(next_name);
1022825eb42bSJan Lentfer 
1023825eb42bSJan Lentfer 		/* Since the names are in canonical order, we can
1024825eb42bSJan Lentfer 		 * recognize empty non-terminals by their labels;
1025825eb42bSJan Lentfer 		 * every label after the first one on the next owner
1026825eb42bSJan Lentfer 		 * name is a non-terminal if it either does not exist
1027825eb42bSJan Lentfer 		 * in the current name or is different from the same
1028825eb42bSJan Lentfer 		 * label in the current name (counting from the end)
1029825eb42bSJan Lentfer 		 */
1030825eb42bSJan Lentfer 		for (i = 1; i < next_label_count - soa_label_count; i++) {
1031fd185f4dSJan Lentfer 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1032825eb42bSJan Lentfer 			if (lpos >= 0) {
1033b5dedccaSJan Lentfer 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1034825eb42bSJan Lentfer 			} else {
1035825eb42bSJan Lentfer 				l1 = NULL;
1036825eb42bSJan Lentfer 			}
1037b5dedccaSJan Lentfer 			l2 = ldns_dname_clone_from(next_name, i);
1038825eb42bSJan Lentfer 
1039825eb42bSJan Lentfer 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1040825eb42bSJan Lentfer 				/* We have an empty nonterminal, add it to the
1041825eb42bSJan Lentfer 				 * tree
1042825eb42bSJan Lentfer 				 */
1043825eb42bSJan Lentfer 				new_name = ldns_dnssec_name_new();
1044825eb42bSJan Lentfer 				if (!new_name) {
1045825eb42bSJan Lentfer 					return LDNS_STATUS_MEM_ERR;
1046825eb42bSJan Lentfer 				}
1047825eb42bSJan Lentfer 				new_name->name = ldns_dname_clone_from(next_name,
1048825eb42bSJan Lentfer 				                                       i);
1049b5dedccaSJan Lentfer 				if (!new_name->name) {
1050825eb42bSJan Lentfer 					ldns_dnssec_name_free(new_name);
1051825eb42bSJan Lentfer 					return LDNS_STATUS_MEM_ERR;
1052825eb42bSJan Lentfer 				}
1053825eb42bSJan Lentfer 				new_name->name_alloced = true;
1054825eb42bSJan Lentfer 				new_node = LDNS_MALLOC(ldns_rbnode_t);
1055825eb42bSJan Lentfer 				if (!new_node) {
1056825eb42bSJan Lentfer 					ldns_dnssec_name_free(new_name);
1057825eb42bSJan Lentfer 					return LDNS_STATUS_MEM_ERR;
1058825eb42bSJan Lentfer 				}
1059825eb42bSJan Lentfer 				new_node->key = new_name->name;
1060825eb42bSJan Lentfer 				new_node->data = new_name;
1061fd185f4dSJan Lentfer 				(void)ldns_rbtree_insert(zone->names, new_node);
1062825eb42bSJan Lentfer 			}
1063825eb42bSJan Lentfer 			ldns_rdf_deep_free(l1);
1064825eb42bSJan Lentfer 			ldns_rdf_deep_free(l2);
1065825eb42bSJan Lentfer 		}
1066825eb42bSJan Lentfer 
1067825eb42bSJan Lentfer 		/* we might have inserted a new node after
1068825eb42bSJan Lentfer 		 * the current one so we can't just use next()
1069825eb42bSJan Lentfer 		 */
1070825eb42bSJan Lentfer 		if (next_node != ldns_rbtree_first(zone->names)) {
1071825eb42bSJan Lentfer 			cur_node = next_node;
1072825eb42bSJan Lentfer 		} else {
1073825eb42bSJan Lentfer 			cur_node = LDNS_RBTREE_NULL;
1074825eb42bSJan Lentfer 		}
1075825eb42bSJan Lentfer 	}
1076825eb42bSJan Lentfer 	return LDNS_STATUS_OK;
1077825eb42bSJan Lentfer }
1078*d1b2b5caSJohn Marino 
1079*d1b2b5caSJohn Marino bool
1080*d1b2b5caSJohn Marino ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
1081*d1b2b5caSJohn Marino {
1082*d1b2b5caSJohn Marino 	ldns_rr* nsec3;
1083*d1b2b5caSJohn Marino 	ldns_rbnode_t* node;
1084*d1b2b5caSJohn Marino 
1085*d1b2b5caSJohn Marino 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1086*d1b2b5caSJohn Marino 		node = ldns_rbtree_first(zone->names);
1087*d1b2b5caSJohn Marino 		while (node != LDNS_RBTREE_NULL) {
1088*d1b2b5caSJohn Marino 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1089*d1b2b5caSJohn Marino 			if (nsec3 &&ldns_rr_get_type(nsec3)
1090*d1b2b5caSJohn Marino 					== LDNS_RR_TYPE_NSEC3 &&
1091*d1b2b5caSJohn Marino 					ldns_nsec3_optout(nsec3)) {
1092*d1b2b5caSJohn Marino 				return true;
1093*d1b2b5caSJohn Marino 			}
1094*d1b2b5caSJohn Marino 			node = ldns_rbtree_next(node);
1095*d1b2b5caSJohn Marino 		}
1096*d1b2b5caSJohn Marino 	}
1097*d1b2b5caSJohn Marino 	return false;
1098*d1b2b5caSJohn Marino }
1099