xref: /freebsd/contrib/ldns/dnssec_zone.c (revision 2008043f386721d58158e37e0d7e50df8095942d)
1 /*
2  * special zone file structures and functions for better dnssec handling
3  */
4 
5 #include <ldns/config.h>
6 
7 #include <ldns/ldns.h>
8 #include <ldns/internal.h>
9 
10 ldns_dnssec_rrs *
11 ldns_dnssec_rrs_new(void)
12 {
13 	ldns_dnssec_rrs *new_rrs;
14 	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
15         if(!new_rrs) return NULL;
16 	new_rrs->rr = NULL;
17 	new_rrs->next = NULL;
18 	return new_rrs;
19 }
20 
21 INLINE void
22 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
23 {
24 	ldns_dnssec_rrs *next;
25 	while (rrs) {
26 		next = rrs->next;
27 		if (deep) {
28 			ldns_rr_free(rrs->rr);
29 		}
30 		LDNS_FREE(rrs);
31 		rrs = next;
32 	}
33 }
34 
35 void
36 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
37 {
38 	ldns_dnssec_rrs_free_internal(rrs, 0);
39 }
40 
41 void
42 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
43 {
44 	ldns_dnssec_rrs_free_internal(rrs, 1);
45 }
46 
47 ldns_status
48 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
49 {
50 	int cmp;
51 	ldns_dnssec_rrs *new_rrs;
52 	if (!rrs || !rr) {
53 		return LDNS_STATUS_ERR;
54 	}
55 
56 	/* this could be done more efficiently; name and type should already
57 	   be equal */
58 	cmp = ldns_rr_compare(rrs->rr, rr);
59 	if (cmp < 0) {
60 		if (rrs->next) {
61 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
62 		} else {
63 			new_rrs = ldns_dnssec_rrs_new();
64 			new_rrs->rr = rr;
65 			rrs->next = new_rrs;
66 		}
67 	} else if (cmp > 0) {
68 		/* put the current old rr in the new next, put the new
69 		   rr in the current container */
70 		new_rrs = ldns_dnssec_rrs_new();
71 		new_rrs->rr = rrs->rr;
72 		new_rrs->next = rrs->next;
73 		rrs->rr = rr;
74 		rrs->next = new_rrs;
75 	}
76 	/* Silently ignore equal rr's */
77 	return LDNS_STATUS_OK;
78 }
79 
80 void
81 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
82 	       const ldns_dnssec_rrs *rrs)
83 {
84 	if (!rrs) {
85 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86 			fprintf(out, "; <void>");
87 	} else {
88 		if (rrs->rr) {
89 			ldns_rr_print_fmt(out, fmt, rrs->rr);
90 		}
91 		if (rrs->next) {
92 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
93 		}
94 	}
95 }
96 
97 void
98 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
99 {
100 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
101 }
102 
103 
104 ldns_dnssec_rrsets *
105 ldns_dnssec_rrsets_new(void)
106 {
107 	ldns_dnssec_rrsets *new_rrsets;
108 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
109         if(!new_rrsets) return NULL;
110 	new_rrsets->rrs = NULL;
111 	new_rrsets->type = 0;
112 	new_rrsets->signatures = NULL;
113 	new_rrsets->next = NULL;
114 	return new_rrsets;
115 }
116 
117 INLINE void
118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119 {
120 	if (rrsets) {
121 		if (rrsets->rrs) {
122 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123 		}
124 		if (rrsets->next) {
125 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126 		}
127 		if (rrsets->signatures) {
128 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129 		}
130 		LDNS_FREE(rrsets);
131 	}
132 }
133 
134 void
135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
136 {
137 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
138 }
139 
140 void
141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
142 {
143 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
144 }
145 
146 ldns_rr_type
147 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
148 {
149 	if (rrsets) {
150 		return rrsets->type;
151 	} else {
152 		return 0;
153 	}
154 }
155 
156 ldns_status
157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
158 					   ldns_rr_type type)
159 {
160 	if (rrsets) {
161 		rrsets->type = type;
162 		return LDNS_STATUS_OK;
163 	}
164 	return LDNS_STATUS_ERR;
165 }
166 
167 static ldns_dnssec_rrsets *
168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169 {
170 	ldns_dnssec_rrsets *new_rrsets;
171 	ldns_rr_type rr_type;
172 	bool rrsig;
173 
174 	new_rrsets = ldns_dnssec_rrsets_new();
175 	rr_type = ldns_rr_get_type(rr);
176 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
177 		rrsig = true;
178 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
179 	} else {
180 		rrsig = false;
181 	}
182 	if (!rrsig) {
183 		new_rrsets->rrs = ldns_dnssec_rrs_new();
184 		new_rrsets->rrs->rr = rr;
185 	} else {
186 		new_rrsets->signatures = ldns_dnssec_rrs_new();
187 		new_rrsets->signatures->rr = rr;
188 	}
189 	new_rrsets->type = rr_type;
190 	return new_rrsets;
191 }
192 
193 ldns_status
194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
195 {
196 	ldns_dnssec_rrsets *new_rrsets;
197 	ldns_rr_type rr_type;
198 	bool rrsig = false;
199 	ldns_status result = LDNS_STATUS_OK;
200 
201 	if (!rrsets || !rr) {
202 		return LDNS_STATUS_ERR;
203 	}
204 
205 	rr_type = ldns_rr_get_type(rr);
206 
207 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
208 		rrsig = true;
209 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
210 	}
211 
212 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213 		if (!rrsig) {
214 			rrsets->rrs = ldns_dnssec_rrs_new();
215 			rrsets->rrs->rr = rr;
216 			rrsets->type = rr_type;
217 		} else {
218 			rrsets->signatures = ldns_dnssec_rrs_new();
219 			rrsets->signatures->rr = rr;
220 			rrsets->type = rr_type;
221 		}
222 		return LDNS_STATUS_OK;
223 	}
224 
225 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226 		if (rrsets->next) {
227 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228 		} else {
229 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230 			rrsets->next = new_rrsets;
231 		}
232 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
233 		/* move the current one into the new next,
234 		   replace field of current with data from new rr */
235 		new_rrsets = ldns_dnssec_rrsets_new();
236 		new_rrsets->rrs = rrsets->rrs;
237 		new_rrsets->type = rrsets->type;
238 		new_rrsets->signatures = rrsets->signatures;
239 		new_rrsets->next = rrsets->next;
240 		if (!rrsig) {
241 			rrsets->rrs = ldns_dnssec_rrs_new();
242 			rrsets->rrs->rr = rr;
243 			rrsets->signatures = NULL;
244 		} else {
245 			rrsets->rrs = NULL;
246 			rrsets->signatures = ldns_dnssec_rrs_new();
247 			rrsets->signatures->rr = rr;
248 		}
249 		rrsets->type = rr_type;
250 		rrsets->next = new_rrsets;
251 	} else {
252 		/* equal, add to current rrsets */
253 		if (rrsig) {
254 			if (rrsets->signatures) {
255 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256 			} else {
257 				rrsets->signatures = ldns_dnssec_rrs_new();
258 				rrsets->signatures->rr = rr;
259 			}
260 		} else {
261 			if (rrsets->rrs) {
262 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263 			} else {
264 				rrsets->rrs = ldns_dnssec_rrs_new();
265 				rrsets->rrs->rr = rr;
266 			}
267 		}
268 	}
269 
270 	return result;
271 }
272 
273 static void
274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275 		const ldns_dnssec_rrsets *rrsets,
276 		bool follow,
277 		bool show_soa)
278 {
279 	if (!rrsets) {
280 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281 			fprintf(out, "; <void>\n");
282 	} else {
283 		if (rrsets->rrs &&
284 		    (show_soa ||
285 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
286 		    )
287 		   ) {
288 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289 			if (rrsets->signatures) {
290 				ldns_dnssec_rrs_print_fmt(out, fmt,
291 						rrsets->signatures);
292 			}
293 		}
294 		if (follow && rrsets->next) {
295 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
296 					rrsets->next, follow, show_soa);
297 		}
298 	}
299 }
300 
301 
302 void
303 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
304 		const ldns_dnssec_rrsets *rrsets,
305 		bool follow)
306 {
307 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
308 }
309 
310 void
311 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
312 {
313 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
314 			rrsets, follow);
315 }
316 
317 ldns_dnssec_name *
318 ldns_dnssec_name_new(void)
319 {
320 	ldns_dnssec_name *new_name;
321 
322 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
323 	if (!new_name) {
324 		return NULL;
325 	}
326 	/*
327 	 * not needed anymore because CALLOC initializes everything to zero.
328 
329 	new_name->name = NULL;
330 	new_name->rrsets = NULL;
331 	new_name->name_alloced = false;
332 	new_name->nsec = NULL;
333 	new_name->nsec_signatures = NULL;
334 
335 	new_name->is_glue = false;
336 	new_name->hashed_name = NULL;
337 
338 	 */
339 	return new_name;
340 }
341 
342 ldns_dnssec_name *
343 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
344 {
345 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
346 
347 	new_name->name = ldns_rr_owner(rr);
348 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
349 		ldns_dnssec_name_free(new_name);
350 		return NULL;
351 	}
352 
353 	return new_name;
354 }
355 
356 INLINE void
357 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
358                                int deep)
359 {
360 	if (name) {
361 		if (name->name_alloced) {
362 			ldns_rdf_deep_free(name->name);
363 		}
364 		if (name->rrsets) {
365 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
366 		}
367 		if (name->nsec && deep) {
368 			ldns_rr_free(name->nsec);
369 		}
370 		if (name->nsec_signatures) {
371 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
372 		}
373 		if (name->hashed_name) {
374 			/* Hashed name is always allocated when signing,
375 			 * so always deep free
376 			 */
377 			ldns_rdf_deep_free(name->hashed_name);
378 		}
379 		LDNS_FREE(name);
380 	}
381 }
382 
383 void
384 ldns_dnssec_name_free(ldns_dnssec_name *name)
385 {
386   ldns_dnssec_name_free_internal(name, 0);
387 }
388 
389 void
390 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
391 {
392   ldns_dnssec_name_free_internal(name, 1);
393 }
394 
395 ldns_rdf *
396 ldns_dnssec_name_name(const ldns_dnssec_name *name)
397 {
398 	if (name) {
399 		return name->name;
400 	}
401 	return NULL;
402 }
403 
404 bool
405 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
406 {
407 	if (name) {
408 		return name->is_glue;
409 	}
410 	return false;
411 }
412 
413 void
414 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
415 					 ldns_rdf *dname)
416 {
417 	if (rrset && dname) {
418 		rrset->name = dname;
419 	}
420 }
421 
422 
423 void
424 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
425 {
426 	if (rrset && nsec) {
427 		rrset->nsec = nsec;
428 	}
429 }
430 
431 int
432 ldns_dnssec_name_cmp(const void *a, const void *b)
433 {
434 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
435 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
436 
437 	if (na && nb) {
438 		return ldns_dname_compare(ldns_dnssec_name_name(na),
439 							 ldns_dnssec_name_name(nb));
440 	} else if (na) {
441 		return 1;
442 	} else if (nb) {
443 		return -1;
444 	} else {
445 		return 0;
446 	}
447 }
448 
449 ldns_status
450 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
451 				    ldns_rr *rr)
452 {
453 	ldns_status result = LDNS_STATUS_OK;
454 	ldns_rr_type rr_type;
455 	ldns_rr_type typecovered = 0;
456 
457 	/* special handling for NSEC3 and NSECX covering RRSIGS */
458 
459 	if (!name || !rr) {
460 		return LDNS_STATUS_ERR;
461 	}
462 
463 	rr_type = ldns_rr_get_type(rr);
464 
465 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
466 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
467 	}
468 
469 	if (rr_type == LDNS_RR_TYPE_NSEC ||
470 	    rr_type == LDNS_RR_TYPE_NSEC3) {
471 		/* XX check if is already set (and error?) */
472 		name->nsec = rr;
473 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
474 			 typecovered == LDNS_RR_TYPE_NSEC3) {
475 		if (name->nsec_signatures) {
476 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
477 		} else {
478 			name->nsec_signatures = ldns_dnssec_rrs_new();
479 			name->nsec_signatures->rr = rr;
480 		}
481 	} else {
482 		/* it's a 'normal' RR, add it to the right rrset */
483 		if (name->rrsets) {
484 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
485 		} else {
486 			name->rrsets = ldns_dnssec_rrsets_new();
487 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
488 		}
489 	}
490 	return result;
491 }
492 
493 ldns_dnssec_rrsets *
494 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
495 					   ldns_rr_type type) {
496 	ldns_dnssec_rrsets *result;
497 
498 	result = name->rrsets;
499 	while (result) {
500 		if (result->type == type) {
501 			return result;
502 		} else {
503 			result = result->next;
504 		}
505 	}
506 	return NULL;
507 }
508 
509 ldns_dnssec_rrsets *
510 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
511 					   const ldns_rdf *dname,
512 					   ldns_rr_type type)
513 {
514 	ldns_rbnode_t *node;
515 
516 	if (!zone || !dname || !zone->names) {
517 		return NULL;
518 	}
519 
520 	node = ldns_rbtree_search(zone->names, dname);
521 	if (node) {
522 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
523 									type);
524 	} else {
525 		return NULL;
526 	}
527 }
528 
529 static void
530 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
531 		const ldns_dnssec_name *name,
532 		bool show_soa)
533 {
534 	if (name) {
535 		if(name->rrsets) {
536 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
537 					name->rrsets, true, show_soa);
538 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
539 			fprintf(out, ";; Empty nonterminal: ");
540 			ldns_rdf_print(out, name->name);
541 			fprintf(out, "\n");
542 		}
543 		if(name->nsec) {
544 			ldns_rr_print_fmt(out, fmt, name->nsec);
545 		}
546 		if (name->nsec_signatures) {
547 			ldns_dnssec_rrs_print_fmt(out, fmt,
548 					name->nsec_signatures);
549 		}
550 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
551 		fprintf(out, "; <void>\n");
552 	}
553 }
554 
555 
556 void
557 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
558 		const ldns_dnssec_name *name)
559 {
560 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
561 }
562 
563 void
564 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
565 {
566 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
567 }
568 
569 
570 ldns_dnssec_zone *
571 ldns_dnssec_zone_new(void)
572 {
573 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
574         if(!zone) return NULL;
575 	zone->soa = NULL;
576 	zone->names = NULL;
577 	zone->hashed_names = NULL;
578 	zone->_nsec3params = NULL;
579 
580 	return zone;
581 }
582 
583 static bool
584 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
585 {
586 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
587 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
588 }
589 
590 /* When the zone is first read into an list and then inserted into an
591  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
592  * to each other. Because ldns-verify-zone (the only program that uses this
593  * function) uses the rbtree mostly for sequential walking, this results
594  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
595  */
596 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
597 
598 static ldns_status
599 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
600 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
601 
602 static void
603 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
604 	(void) arg;
605 	ldns_rdf_deep_free((ldns_rdf *)node->key);
606 	LDNS_FREE(node);
607 }
608 
609 ldns_status
610 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
611 		uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
612 {
613 	ldns_rr* cur_rr;
614 	size_t i;
615 
616 	ldns_rdf *my_origin = NULL;
617 	ldns_rdf *my_prev = NULL;
618 
619 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
620 	/* NSEC3s may occur before the names they refer to. We must remember
621 	   them and add them to the name later on, after the name is read.
622 	   We track not yet  matching NSEC3s*n the todo_nsec3s list */
623 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
624 	/* when reading NSEC3s, there is a chance that we encounter nsecs
625 	   for empty nonterminals, whose nonterminals we cannot derive yet
626 	   because the needed information is to be read later.
627 
628 	   nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
629 	   hold the NSEC3s that still didn't have a matching name in the
630 	   zone tree, even after all names were read.  They can only match
631 	   after the zone is equipped with all the empty non terminals. */
632 	ldns_rbtree_t todo_nsec3_ents;
633 	ldns_rbnode_t *new_node;
634 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
635 
636 	ldns_status status;
637 
638 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
639 	ldns_zone* zone = NULL;
640 #else
641 	ldns_rr  *prev_rr = NULL;
642 	uint32_t   my_ttl = default_ttl;
643 	/* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
644 	 * to the last explicitly stated values.'
645 	 */
646 	bool ttl_from_TTL = false;
647 	bool explicit_ttl = false;
648 #endif
649 
650 	ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
651 
652 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
653 	status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
654 	if (status != LDNS_STATUS_OK)
655 		goto error;
656 #endif
657 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
658 		status = LDNS_STATUS_MEM_ERR;
659 		goto error;
660 	}
661 	if (origin) {
662 		if (!(my_origin = ldns_rdf_clone(origin))) {
663 			status = LDNS_STATUS_MEM_ERR;
664 			goto error;
665 		}
666 		if (!(my_prev   = ldns_rdf_clone(origin))) {
667 			status = LDNS_STATUS_MEM_ERR;
668 			goto error;
669 		}
670 	}
671 
672 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
673 	if (ldns_zone_soa(zone)) {
674 		status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
675 		if (status != LDNS_STATUS_OK)
676 			goto error;
677 	}
678 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680 		status = LDNS_STATUS_OK;
681 #else
682 	while (!feof(fp)) {
683 		/* If ttl came from $TTL line, then it should be the default.
684 		 * (RFC 2308 Section 4)
685 		 * Otherwise it "defaults to the last explicitly stated value"
686 		 * (RFC 1035 Section 5.1)
687 		 */
688 		if (ttl_from_TTL)
689 			my_ttl = default_ttl;
690 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
691 				&my_prev, line_nr, &explicit_ttl);
692 #endif
693 		switch (status) {
694 		case LDNS_STATUS_OK:
695 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
696 			if (explicit_ttl) {
697 				if (!ttl_from_TTL) {
698 					/* No $TTL, so ttl "defaults to the
699 					 * last explicitly stated value"
700 					 * (RFC 1035 Section 5.1)
701 					 */
702 					my_ttl = ldns_rr_ttl(cur_rr);
703 				}
704 			/* When ttl is implicit, try to adhere to the rules as
705 			 * much as possible. (also for compatibility with bind)
706 			 * This was changed when fixing an issue with ZONEMD
707 			 * which hashes the TTL too.
708 			 */
709 			} else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
710 			       ||  ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
711 				if (ldns_rr_rd_count(cur_rr) >= 4
712 				&&  ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32)
713 
714 					/* SIG without explicit ttl get ttl
715 					 * from the original_ttl field
716 					 * (RFC 2535 Section 7.2)
717 					 *
718 					 * Similarly for RRSIG, but stated less
719 					 * specifically in the spec.
720 					 * (RFC 4034 Section 3)
721 					 */
722 					ldns_rr_set_ttl(cur_rr,
723 					    ldns_rdf2native_int32(
724 					        ldns_rr_rdf(rr, 3)));
725 
726 			} else if (prev_rr
727 			       &&  ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
728 			       &&  ldns_dname_compare( ldns_rr_owner(prev_rr)
729 			                             , ldns_rr_owner(cur_rr)) == 0)
730 
731 				/* "TTLs of all RRs in an RRSet must be the same"
732 				 * (RFC 2881 Section 5.2)
733 				 */
734 				ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
735 
736 			prev_rr = cur_rr;
737 #endif
738 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
739 			if (status ==
740 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
741 
742 				if (rr_is_rrsig_covering(cur_rr,
743 							LDNS_RR_TYPE_NSEC3)){
744 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
745 							cur_rr);
746 				} else {
747 					ldns_rr_list_push_rr(todo_nsec3s,
748 						       	cur_rr);
749 				}
750 				status = LDNS_STATUS_OK;
751 
752 			} else if (status != LDNS_STATUS_OK)
753 				goto error;
754 
755 			break;
756 
757 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
758 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
759 			default_ttl = my_ttl;
760 			ttl_from_TTL = true;
761 #endif
762 			status = LDNS_STATUS_OK;
763 			break;
764 
765 
766 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
767 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
768 			status = LDNS_STATUS_OK;
769 			break;
770 
771 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
772 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
773 			break;
774 
775 		default:
776 			goto error;
777 		}
778 	}
779 
780 	for (i = 0; status == LDNS_STATUS_OK &&
781 			i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
782 		cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
783 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
784 		if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
785 			if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
786 				status = LDNS_STATUS_MEM_ERR;
787 				break;
788 			}
789 			new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
790 			new_node->data = cur_rr;
791 			if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
792 				LDNS_FREE(new_node);
793 				status = LDNS_STATUS_MEM_ERR;
794 				break;
795 			}
796 			status = LDNS_STATUS_OK;
797 		}
798 	}
799 	if (todo_nsec3_ents.count > 0)
800 		(void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
801 				newzone, &todo_nsec3_ents);
802 	for (i = 0; status == LDNS_STATUS_OK &&
803 			i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
804 		cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
805 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
806 	}
807 	if (z) {
808 		*z = newzone;
809 		newzone = NULL;
810 	} else {
811 		ldns_dnssec_zone_free(newzone);
812 		newzone = NULL;
813 	}
814 
815 error:
816 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
817 	if (zone) {
818 		ldns_zone_free(zone);
819 	}
820 #endif
821 	ldns_rr_list_free(todo_nsec3_rrsigs);
822 	ldns_traverse_postorder(&todo_nsec3_ents,
823 			ldns_todo_nsec3_ents_node_free, NULL);
824 	ldns_rr_list_free(todo_nsec3s);
825 
826 	if (my_origin) {
827 		ldns_rdf_deep_free(my_origin);
828 	}
829 	if (my_prev) {
830 		ldns_rdf_deep_free(my_prev);
831 	}
832 	if (newzone) {
833 		ldns_dnssec_zone_free(newzone);
834 	}
835 	return status;
836 }
837 
838 ldns_status
839 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
840 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
841 {
842 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
843 }
844 
845 static void
846 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
847 	(void) arg;
848 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
849 	LDNS_FREE(node);
850 }
851 
852 static void
853 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
854 	(void) arg;
855 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
856 	LDNS_FREE(node);
857 }
858 
859 static void
860 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
861 	(void) arg;
862 	LDNS_FREE(node);
863 }
864 
865 void
866 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
867 {
868 	if (zone) {
869 		if (zone->hashed_names) {
870 			ldns_traverse_postorder(zone->hashed_names,
871 					ldns_hashed_names_node_free, NULL);
872 			LDNS_FREE(zone->hashed_names);
873 		}
874 		if (zone->names) {
875 			/* destroy all name structures within the tree */
876 			ldns_traverse_postorder(zone->names,
877 						    ldns_dnssec_name_node_free,
878 						    NULL);
879 			LDNS_FREE(zone->names);
880 		}
881 		LDNS_FREE(zone);
882 	}
883 }
884 
885 void
886 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
887 {
888 	if (zone) {
889 		if (zone->hashed_names) {
890 			ldns_traverse_postorder(zone->hashed_names,
891 					ldns_hashed_names_node_free, NULL);
892 			LDNS_FREE(zone->hashed_names);
893 		}
894 		if (zone->names) {
895 			/* destroy all name structures within the tree */
896 			ldns_traverse_postorder(zone->names,
897 						    ldns_dnssec_name_node_deep_free,
898 						    NULL);
899 			LDNS_FREE(zone->names);
900 		}
901 		LDNS_FREE(zone);
902 	}
903 }
904 
905 /* use for dname comparison in tree */
906 int
907 ldns_dname_compare_v(const void *a, const void *b) {
908 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
909 }
910 
911 static void
912 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
913 		ldns_dnssec_name* name, ldns_rr* nsec3rr);
914 
915 static void
916 ldns_dnssec_zone_hashed_names_from_nsec3(
917 		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
918 {
919 	ldns_rbnode_t* current_node;
920 	ldns_dnssec_name* current_name;
921 
922 	assert(zone != NULL);
923 	assert(nsec3rr != NULL);
924 
925 	if (zone->hashed_names) {
926 		ldns_traverse_postorder(zone->hashed_names,
927 				ldns_hashed_names_node_free, NULL);
928 		LDNS_FREE(zone->hashed_names);
929 	}
930 	zone->_nsec3params = nsec3rr;
931 
932 	/* So this is a NSEC3 zone.
933 	* Calculate hashes for all names already in the zone
934 	*/
935 	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
936 	if (zone->hashed_names == NULL) {
937 		return;
938 	}
939 	for ( current_node  = ldns_rbtree_first(zone->names)
940 	    ; current_node != LDNS_RBTREE_NULL
941 	    ; current_node  = ldns_rbtree_next(current_node)
942 	    ) {
943 		current_name = (ldns_dnssec_name *) current_node->data;
944 		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
945 
946 	}
947 }
948 
949 static void
950 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
951 		ldns_dnssec_name* name, ldns_rr* nsec3rr)
952 {
953 	ldns_rbnode_t* new_node;
954 
955 	assert(name != NULL);
956 	if (! zone->_nsec3params) {
957 		if (! nsec3rr) {
958 			return;
959 		}
960 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
961 
962 	} else if (! nsec3rr) {
963 		nsec3rr = zone->_nsec3params;
964 	}
965 	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
966 
967 	/* Also store in zone->hashed_names */
968 	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
969 
970 		new_node->key  = name->hashed_name;
971 		new_node->data = name;
972 
973 		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
974 
975 				LDNS_FREE(new_node);
976 		}
977 	}
978 }
979 
980 
981 static ldns_rbnode_t *
982 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
983 	ldns_rdf *hashed_name;
984 	ldns_rbnode_t *to_return;
985 
986 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
987 
988 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
989 	}
990 	if (zone->hashed_names == NULL) {
991 		return NULL;
992 	}
993 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
994 	if (hashed_name == NULL) {
995 		return NULL;
996 	}
997 	to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
998 	ldns_rdf_deep_free(hashed_name);
999 	return to_return;
1000 }
1001 
1002 ldns_status
1003 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
1004 {
1005 	ldns_status result = LDNS_STATUS_OK;
1006 	ldns_dnssec_name *cur_name;
1007 	ldns_rbnode_t *cur_node;
1008 	ldns_rr_type type_covered = 0;
1009 
1010 	if (!zone || !rr) {
1011 		return LDNS_STATUS_ERR;
1012 	}
1013 
1014 	if (!zone->names) {
1015 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1016                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1017 	}
1018 
1019 	/* we need the original of the hashed name if this is
1020 	   an NSEC3, or an RRSIG that covers an NSEC3 */
1021 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
1022 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1023 	}
1024 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
1025 	    type_covered == LDNS_RR_TYPE_NSEC3) {
1026 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1027 		if (!cur_node) {
1028 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
1029 		}
1030 	} else {
1031 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1032 	}
1033 	if (!cur_node) {
1034 		/* add */
1035 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
1036                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1037 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
1038                 if(!cur_node) {
1039                         ldns_dnssec_name_free(cur_name);
1040                         return LDNS_STATUS_MEM_ERR;
1041                 }
1042 		cur_node->key = ldns_rr_owner(rr);
1043 		cur_node->data = cur_name;
1044 		(void)ldns_rbtree_insert(zone->names, cur_node);
1045 		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1046 	} else {
1047 		cur_name = (ldns_dnssec_name *) cur_node->data;
1048 		result = ldns_dnssec_name_add_rr(cur_name, rr);
1049 	}
1050 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1051 		zone->soa = cur_name;
1052 	}
1053 	return result;
1054 }
1055 
1056 void
1057 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
1058 		const ldns_rbtree_t *tree,
1059 		bool print_soa)
1060 {
1061 	ldns_rbnode_t *node;
1062 	ldns_dnssec_name *name;
1063 
1064 	node = ldns_rbtree_first(tree);
1065 	while (node != LDNS_RBTREE_NULL) {
1066 		name = (ldns_dnssec_name *) node->data;
1067 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1068 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1069 			fprintf(out, ";\n");
1070 		node = ldns_rbtree_next(node);
1071 	}
1072 }
1073 
1074 void
1075 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1076 {
1077 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1078 		       tree, print_soa);
1079 }
1080 
1081 void
1082 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1083 	       const ldns_dnssec_zone *zone)
1084 {
1085 	if (zone) {
1086 		if (zone->soa) {
1087 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1088 				fprintf(out, ";; Zone: ");
1089 				ldns_rdf_print(out, ldns_dnssec_name_name(
1090 							zone->soa));
1091 				fprintf(out, "\n;\n");
1092 			}
1093 			ldns_dnssec_rrsets_print_fmt(out, fmt,
1094 					ldns_dnssec_name_find_rrset(
1095 						zone->soa,
1096 						LDNS_RR_TYPE_SOA),
1097 					false);
1098 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1099 				fprintf(out, ";\n");
1100 		}
1101 
1102 		if (zone->names) {
1103 			ldns_dnssec_zone_names_print_fmt(out, fmt,
1104 					zone->names, false);
1105 		}
1106 	}
1107 }
1108 
1109 void
1110 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1111 {
1112 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1113 }
1114 
1115 static ldns_status
1116 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1117 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1118 {
1119 	ldns_dnssec_name *new_name;
1120 	ldns_rdf *cur_name;
1121 	ldns_rdf *next_name;
1122 	ldns_rbnode_t *cur_node, *next_node, *new_node;
1123 
1124 	/* for the detection */
1125 	uint16_t i, cur_label_count, next_label_count;
1126 	uint16_t soa_label_count = 0;
1127 	ldns_rdf *l1, *l2;
1128 	int lpos;
1129 
1130 	if (!zone) {
1131 		return LDNS_STATUS_ERR;
1132 	}
1133 	if (zone->soa && zone->soa->name) {
1134 		soa_label_count = ldns_dname_label_count(zone->soa->name);
1135 	}
1136 
1137 	cur_node = ldns_rbtree_first(zone->names);
1138 	while (cur_node != LDNS_RBTREE_NULL) {
1139 		next_node = ldns_rbtree_next(cur_node);
1140 
1141 		/* skip glue */
1142 		while (next_node != LDNS_RBTREE_NULL &&
1143 		       next_node->data &&
1144 		       ((ldns_dnssec_name *)next_node->data)->is_glue
1145 		) {
1146 			next_node = ldns_rbtree_next(next_node);
1147 		}
1148 
1149 		if (next_node == LDNS_RBTREE_NULL) {
1150 			next_node = ldns_rbtree_first(zone->names);
1151 		}
1152 		if (! cur_node->data || ! next_node->data) {
1153 			return LDNS_STATUS_ERR;
1154 		}
1155 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1156 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
1157 		cur_label_count = ldns_dname_label_count(cur_name);
1158 		next_label_count = ldns_dname_label_count(next_name);
1159 
1160 		/* Since the names are in canonical order, we can
1161 		 * recognize empty non-terminals by their labels;
1162 		 * every label after the first one on the next owner
1163 		 * name is a non-terminal if it either does not exist
1164 		 * in the current name or is different from the same
1165 		 * label in the current name (counting from the end)
1166 		 */
1167 		for (i = 1; i < next_label_count - soa_label_count; i++) {
1168 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1169 			if (lpos >= 0) {
1170 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1171 			} else {
1172 				l1 = NULL;
1173 			}
1174 			l2 = ldns_dname_clone_from(next_name, i);
1175 
1176 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1177 				/* We have an empty nonterminal, add it to the
1178 				 * tree
1179 				 */
1180 				ldns_rbnode_t *node = NULL;
1181 				ldns_rdf *ent_name;
1182 
1183 				if (!(ent_name = ldns_dname_clone_from(
1184 						next_name, i))) {
1185 
1186 					ldns_rdf_deep_free(l1);
1187 					ldns_rdf_deep_free(l2);
1188 					return LDNS_STATUS_MEM_ERR;
1189 				}
1190 
1191 				if (nsec3s && zone->_nsec3params) {
1192 					ldns_rdf *ent_hashed_name;
1193 
1194 					if (!(ent_hashed_name =
1195 					    ldns_nsec3_hash_name_frm_nsec3(
1196 							zone->_nsec3params,
1197 							ent_name))) {
1198 						ldns_rdf_deep_free(l1);
1199 						ldns_rdf_deep_free(l2);
1200 						ldns_rdf_deep_free(ent_name);
1201 						return LDNS_STATUS_MEM_ERR;
1202 					}
1203 					node = ldns_rbtree_search(nsec3s,
1204 							ent_hashed_name);
1205 					ldns_rdf_deep_free(ent_hashed_name);
1206 					if (!node) {
1207 						ldns_rdf_deep_free(l1);
1208 						ldns_rdf_deep_free(l2);
1209 						ldns_rdf_deep_free(ent_name);
1210 						continue;
1211 					}
1212 				}
1213 				new_name = ldns_dnssec_name_new();
1214 				if (!new_name) {
1215 					ldns_rdf_deep_free(l1);
1216 					ldns_rdf_deep_free(l2);
1217 					ldns_rdf_deep_free(ent_name);
1218 					return LDNS_STATUS_MEM_ERR;
1219 				}
1220 				new_name->name = ent_name;
1221 				new_name->name_alloced = true;
1222 				new_node = LDNS_MALLOC(ldns_rbnode_t);
1223 				if (!new_node) {
1224 					ldns_rdf_deep_free(l1);
1225 					ldns_rdf_deep_free(l2);
1226 					ldns_dnssec_name_free(new_name);
1227 					return LDNS_STATUS_MEM_ERR;
1228 				}
1229 				new_node->key = new_name->name;
1230 				new_node->data = new_name;
1231 				(void)ldns_rbtree_insert(zone->names, new_node);
1232 				ldns_dnssec_name_make_hashed_name(
1233 						zone, new_name, NULL);
1234 				if (node)
1235 					(void) ldns_dnssec_zone_add_rr(zone,
1236 							(ldns_rr *)node->data);
1237 			}
1238 			ldns_rdf_deep_free(l1);
1239 			ldns_rdf_deep_free(l2);
1240 		}
1241 
1242 		/* we might have inserted a new node after
1243 		 * the current one so we can't just use next()
1244 		 */
1245 		if (next_node != ldns_rbtree_first(zone->names)) {
1246 			cur_node = next_node;
1247 		} else {
1248 			cur_node = LDNS_RBTREE_NULL;
1249 		}
1250 	}
1251 	return LDNS_STATUS_OK;
1252 }
1253 
1254 ldns_status
1255 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1256 {
1257 	return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1258 }
1259 
1260 bool
1261 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1262 {
1263 	ldns_rr* nsec3;
1264 	ldns_rbnode_t* node;
1265 
1266 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1267 		node = ldns_rbtree_first(zone->names);
1268 		while (node != LDNS_RBTREE_NULL) {
1269 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1270 			if (nsec3 &&ldns_rr_get_type(nsec3)
1271 					== LDNS_RR_TYPE_NSEC3 &&
1272 					ldns_nsec3_optout(nsec3)) {
1273 				return true;
1274 			}
1275 			node = ldns_rbtree_next(node);
1276 		}
1277 	}
1278 	return false;
1279 }
1280 
1281 /*
1282  * Stuff for calculating and verifying zone digests
1283  */
1284 typedef enum dnssec_zone_rr_iter_state {
1285 	  DNSSEC_ZONE_RR_ITER_LT_RRSIG
1286 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1287 	, DNSSEC_ZONE_RR_ITER_REST
1288 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
1289 	, DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
1290 	, DNSSEC_ZONE_RR_ITER_NSEC3
1291 	, DNSSEC_ZONE_RR_ITER_FINI
1292 } dnssec_zone_rr_iter_state;
1293 
1294 typedef struct dnssec_zone_rr_iter {
1295 	ldns_dnssec_zone         *zone;
1296 	ldns_rbnode_t            *node;
1297 	ldns_dnssec_name         *name;
1298 	ldns_dnssec_rrsets       *rrsets;
1299 	ldns_dnssec_rrs          *rrs;
1300 	ldns_dnssec_rrsets       *rrsets4rrsigs;
1301 	ldns_rbnode_t            *nsec3_node;
1302 	ldns_dnssec_name         *nsec3_name;
1303 	dnssec_zone_rr_iter_state state;
1304 	ldns_rdf                 *apex_name;
1305 	uint8_t                   apex_labs;
1306 } dnssec_zone_rr_iter;
1307 
1308 INLINE void
1309 dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1310 {
1311 	/* Make sure the i->name is "in zone" (i.e. below the apex) */
1312 	if (i->apex_name) {
1313 		ldns_rdf *name = (ldns_rdf *)i->node->key;
1314 
1315 		while (i->name && name != i->apex_name        /* not apex */
1316 
1317 		&& (  ldns_dname_label_count(name) != i->apex_labs
1318 		   || ldns_dname_compare(name, i->apex_name)) /* not apex */
1319 
1320 		&& !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1321 
1322 			/* next name */
1323 			i->node = ldns_rbtree_next(i->node);
1324 			if (i->node == LDNS_RBTREE_NULL)
1325 				i->name = NULL;
1326 			else {
1327 				i->name = (ldns_dnssec_name *)i->node->data;
1328 				name = (ldns_rdf *)i->node->key;
1329 			}
1330 		}
1331 	}
1332 	/* determine state */
1333 	if (!i->name) {
1334 		if (!i->nsec3_name)
1335 			i->state = DNSSEC_ZONE_RR_ITER_FINI;
1336 		else {
1337 			i->rrs = i->nsec3_name->nsec_signatures;
1338 			i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1339 		}
1340 	} else if (!i->nsec3_name) {
1341 		i->rrsets = i->name->rrsets;
1342 		i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1343 
1344 	} else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec)
1345 	                             , (ldns_rdf *)i->node->key) < 0) {
1346 		i->rrs = i->nsec3_name->nsec_signatures;
1347 		i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1348 	} else {
1349 		i->rrsets = i->name->rrsets;
1350 		i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1351 	}
1352 }
1353 
1354 /**
1355  * Iterate over the RR's in the ldns_dnssec_zone in canonical order.
1356  * There are three possible paths through the RR's in a ldns_dnssec_name.
1357  *
1358  * 1. There is no NSEC:
1359  *
1360  *    1.1. All the RRs in the name->rrsets with type < RRSIG,
1361  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1362  *
1363  *    1.2. Then all the RRSIGs from name->rrsets (likely none)
1364  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1365  *
1366  *    1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1367  *         state: DNSSEC_ZONE_RR_ITER_REST
1368  *
1369  *
1370  * 2. There is a NSEC of type NSEC with this name:
1371  *
1372  *    2.1. All the RRs in the name->rrsets with type < RRSIG,
1373  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1374  *
1375  *    2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1376  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1377  *
1378  *    2.3. Then the signatures of the NSEC RR, followed by
1379  *         the signatures of the remaining name->rrsets (type > NSEC),
1380  *         followed by the NSEC rr.
1381  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1382  *
1383  *    2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1384  *         state: DNSSEC_ZONE_RR_ITER_REST
1385  *
1386  *
1387  * 3. There is a NSEC of type NSEC3 for this name:
1388  *
1389  *    3.1. If the NSEC3 name is before the name for other RRsets in the zone,
1390  *         Then all signatures of the NSEC3 RR, followed by the NSEC3
1391  *         state: DNSSEC_ZONE_RR_ITER_NSEC3
1392  *
1393  *         otherwise follow path for "no NSEC" for the name for other RRsets
1394  */
1395 static ldns_rr *
1396 dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1397 {
1398 	ldns_rr *nsec3;
1399 
1400 	for (;;) {
1401 		if (i->rrs) {
1402 			ldns_rr *rr = i->rrs->rr;
1403 			i->rrs = i->rrs->next;
1404 			return rr;
1405 		}
1406 		switch (i->state) {
1407 		case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1408 			if (i->rrsets
1409 			&&  i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1410 
1411 				i->rrs = i->rrsets->rrs;
1412 				i->rrsets = i->rrsets->next;
1413 				break;
1414 			}
1415 			i->rrsets4rrsigs = i->name->rrsets;
1416 			if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1417 			                               == LDNS_RR_TYPE_NSEC) {
1418 
1419 				i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1420 				break;
1421 			}
1422 			i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1423 			/* fallthrough */
1424 
1425 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC:
1426 			if (i->rrsets4rrsigs) {
1427 				i->rrs = i->rrsets4rrsigs->signatures;
1428 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1429 				break;
1430 			}
1431 			i->state = DNSSEC_ZONE_RR_ITER_REST;
1432 			/* fallthrough */
1433 
1434 		case DNSSEC_ZONE_RR_ITER_REST:
1435 			if (i->rrsets) {
1436 				i->rrs = i->rrsets->rrs;
1437 				i->rrsets = i->rrsets->next;
1438 				break;
1439 			}
1440 			/* next name */
1441 			i->node = ldns_rbtree_next(i->node);
1442 			i->name = i->node == LDNS_RBTREE_NULL ? NULL
1443 				: (ldns_dnssec_name *)i->node->data;
1444 
1445 			dnssec_zone_rr_iter_set_state_for_next_name(i);
1446 			break;
1447 
1448 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1449 			if (i->rrsets4rrsigs
1450 			&&  i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1451 
1452 				i->rrs = i->rrsets4rrsigs->signatures;
1453 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1454 				break;
1455 			}
1456 			i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1457 			i->rrs = i->name->nsec_signatures;
1458 			break;
1459 
1460 		case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST:
1461 			if (i->rrsets4rrsigs) {
1462 				i->rrs = i->rrsets4rrsigs->signatures;
1463 				i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1464 				break;
1465 			}
1466 			i->state = DNSSEC_ZONE_RR_ITER_REST;
1467 			return i->name->nsec;
1468 
1469 		case DNSSEC_ZONE_RR_ITER_NSEC3:
1470 			nsec3 = i->nsec3_name->nsec;
1471 
1472 			/* next nsec3 */
1473 			do {
1474 				i->nsec3_node
1475 				    = ldns_rbtree_next(i->nsec3_node);
1476 				i->nsec3_name
1477 				    = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1478 				    : (ldns_dnssec_name*)i->nsec3_node->data;
1479 
1480 				/* names for glue can be in the hashed_names
1481 				 * tree, but will not have a NSEC3
1482 				 */
1483 			} while (i->nsec3_name && !i->nsec3_name->nsec);
1484 
1485 			dnssec_zone_rr_iter_set_state_for_next_name(i);
1486 			return nsec3;
1487 
1488 		case DNSSEC_ZONE_RR_ITER_FINI:
1489 			return NULL;
1490 		}
1491 	}
1492 }
1493 
1494 static ldns_rr *
1495 dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1496 {
1497 	if (!i || !zone)
1498 		return NULL;
1499 
1500 	memset(i, 0, sizeof(*i));
1501 	i->zone = zone;
1502 	if (zone->soa && zone->soa->name) {
1503 		i->apex_name = zone->soa->name;
1504 		i->apex_labs = ldns_dname_label_count(i->apex_name);
1505 	} else
1506 		i->apex_name = NULL;
1507 
1508 
1509 	i->node = ldns_rbtree_first(zone->names);
1510 	i->name = i->node == LDNS_RBTREE_NULL ? NULL
1511 		: (ldns_dnssec_name *)i->node->data;
1512 
1513 	if (zone->hashed_names) {
1514 		do {
1515 			i->nsec3_node = ldns_rbtree_first(zone->hashed_names);
1516 			i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1517 				      : (ldns_dnssec_name*)i->nsec3_node->data;
1518 		} while (i->nsec3_name && !i->nsec3_name->nsec);
1519 	}
1520 	dnssec_zone_rr_iter_set_state_for_next_name(i);
1521 	return dnssec_zone_rr_iter_next(i);
1522 }
1523 
1524 enum enum_zonemd_scheme {
1525         ZONEMD_SCHEME_FIRST  = 1,
1526         ZONEMD_SCHEME_SIMPLE = 1,
1527         ZONEMD_SCHEME_LAST   = 1
1528 };
1529 typedef enum enum_zonemd_scheme zonemd_scheme;
1530 
1531 enum enum_zonemd_hash {
1532         ZONEMD_HASH_FIRST  = 1,
1533         ZONEMD_HASH_SHA384 = 1,
1534         ZONEMD_HASH_SHA512 = 2,
1535         ZONEMD_HASH_LAST   = 2
1536 };
1537 typedef enum enum_zonemd_hash zonemd_hash;
1538 
1539 struct struct_zone_digester {
1540         ldns_sha384_CTX sha384_CTX;
1541         ldns_sha512_CTX sha512_CTX;
1542         unsigned simple_sha384 : 1;
1543         unsigned simple_sha512 : 1;
1544         unsigned double_sha384 : 1;
1545         unsigned double_sha512 : 1;
1546 };
1547 typedef struct struct_zone_digester zone_digester;
1548 
1549 INLINE bool zone_digester_set(zone_digester *zd)
1550 { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1551 
1552 INLINE void zone_digester_init(zone_digester *zd)
1553 { memset(zd, 0, sizeof(*zd)); }
1554 
1555 static ldns_status
1556 zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1557 {
1558 	if (!zd)
1559 		return LDNS_STATUS_NULL;
1560 
1561 	switch (scheme) {
1562 	case ZONEMD_SCHEME_SIMPLE:
1563 		switch (hash) {
1564 		case ZONEMD_HASH_SHA384:
1565 			if (zd->double_sha384)
1566 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1567 
1568 			else if (zd->simple_sha384) {
1569 				zd->simple_sha384 = 0;
1570 				zd->double_sha384 = 1;
1571 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1572 			}
1573 			ldns_sha384_init(&zd->sha384_CTX);
1574 			zd->simple_sha384 = 1;
1575 			break;
1576 
1577 		case ZONEMD_HASH_SHA512:
1578 			if (zd->double_sha512)
1579 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1580 
1581 			else if (zd->simple_sha512) {
1582 				zd->simple_sha512 = 0;
1583 				zd->double_sha512 = 1;
1584 				return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1585 			}
1586 			ldns_sha512_init(&zd->sha512_CTX);
1587 			zd->simple_sha512 = 1;
1588 			break;
1589 		default:
1590 			return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1591 		}
1592 		break;
1593 	default:
1594 		return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1595 	}
1596 	return LDNS_STATUS_OK;
1597 }
1598 
1599 static ldns_status
1600 zone_digester_update(zone_digester *zd, ldns_rr *rr)
1601 {
1602 	uint8_t data[65536];
1603 	ldns_buffer buf;
1604 	ldns_status st;
1605 
1606 	buf._data = data;
1607 	buf._position = 0;
1608 	buf._limit = sizeof(data);
1609 	buf._capacity = sizeof(data);
1610 	buf._fixed = 1;
1611 	buf._status = LDNS_STATUS_OK;
1612 
1613 	if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1614 		return st;
1615 
1616 	if (zd->simple_sha384)
1617 		ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1618 
1619 	if (zd->simple_sha512)
1620 		ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1621 
1622 	return LDNS_STATUS_OK;
1623 }
1624 
1625 INLINE ldns_rr *
1626 new_zonemd(ldns_rr *soa, zonemd_hash hash)
1627 {
1628 	ldns_rr  *rr     = NULL;
1629 	uint8_t  *data   = NULL;
1630 	ldns_rdf *rdf;
1631 	size_t    md_len = hash == ZONEMD_HASH_SHA384
1632 	                 ? LDNS_SHA384_DIGEST_LENGTH
1633 	                 : LDNS_SHA512_DIGEST_LENGTH;
1634 
1635 	if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1636 		return NULL;
1637 
1638 	if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1639 		goto error;
1640 
1641 	ldns_rr_set_owner(rr, rdf);
1642 	ldns_rr_set_class(rr, ldns_rr_get_class(soa));
1643 	ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1644 
1645 	if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1646 		goto error;
1647 	ldns_rr_set_rdf(rr, rdf, 0);
1648 
1649 	if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1650 		goto error;
1651 	ldns_rr_set_rdf(rr, rdf, 1);
1652 
1653 	if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1654 		goto error;
1655 	ldns_rr_set_rdf(rr, rdf, 2);
1656 
1657 	if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1658 		goto error;
1659 
1660 	if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1661 		goto error;
1662 	ldns_rr_set_rdf(rr, rdf, 3);
1663 
1664 	return rr;
1665 error:
1666 	if (data)
1667 		LDNS_FREE(data);
1668 	ldns_rr_free(rr);
1669 	return NULL;
1670 }
1671 
1672 static ldns_rr_list *
1673 zone_digester_export(
1674 		zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1675 {
1676 	ldns_status st = LDNS_STATUS_OK;
1677 	ldns_rr_list *rr_list = NULL;
1678 	ldns_rr *sha384 = NULL;
1679 	ldns_rr *sha512 = NULL;
1680 
1681 	if (!zd || !soa)
1682 		st = LDNS_STATUS_NULL;
1683 
1684 	else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1685 	     ||  ldns_rr_rd_count(soa) < 3)
1686 		st = LDNS_STATUS_ZONEMD_INVALID_SOA;
1687 
1688 	else if (!(rr_list = ldns_rr_list_new()))
1689 		st = LDNS_STATUS_MEM_ERR;
1690 
1691 	else if (zd->simple_sha384
1692 	     && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1693 		st = LDNS_STATUS_MEM_ERR;
1694 
1695 	else if (zd->simple_sha512
1696 	     && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1697 		st = LDNS_STATUS_MEM_ERR;
1698 
1699 	else if (zd->simple_sha384
1700 	     && !ldns_rr_list_push_rr(rr_list, sha384))
1701 		st = LDNS_STATUS_MEM_ERR;
1702 
1703 	else if (zd->simple_sha512
1704 	     && !ldns_rr_list_push_rr(rr_list, sha512)) {
1705 		if (zd->simple_sha384)
1706 			sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1707 		st = LDNS_STATUS_MEM_ERR;
1708 
1709 	} else {
1710 		if (sha384)
1711 			ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1712 			                 , &zd->sha384_CTX);
1713 		if (sha512)
1714 			ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1715 			                 , &zd->sha512_CTX);
1716 		return rr_list;
1717 	}
1718 	if (ret_st)
1719 		*ret_st = st;
1720 	if (sha384)
1721 		ldns_rr_free(sha384);
1722 	if (sha512)
1723 		ldns_rr_free(sha512);
1724 	if (rr_list)
1725 		ldns_rr_list_deep_free(rr_list);
1726 	return NULL;
1727 }
1728 
1729 static ldns_status
1730 ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1731 {
1732 	ldns_status st = LDNS_STATUS_OK;
1733 	dnssec_zone_rr_iter rr_iter;
1734 	ldns_rr *rr;
1735 	ldns_rdf *apex_name; /* name of zone apex */
1736 
1737 	if (!zone || !zd || !zone->soa || !zone->soa->name)
1738 		return LDNS_STATUS_NULL;
1739 
1740 	apex_name = zone->soa->name;
1741 	for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1742 	    ; rr && !st
1743 	    ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1744 		/* Skip apex ZONEMD RRs */
1745 		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD
1746 		&& !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1747 			continue;
1748 		/* Skip RRSIGs for apex ZONEMD RRs */
1749 		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
1750 		&&  LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type(
1751 				ldns_rr_rrsig_typecovered(rr))
1752 		&& !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1753 			continue;
1754 		st = zone_digester_update(zd, rr);
1755 	}
1756 	return st;
1757 }
1758 
1759 ldns_status
1760 ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1761 {
1762 	ldns_dnssec_rrsets *zonemd, *soa;
1763 	zone_digester zd;
1764 	ldns_dnssec_rrs *rrs;
1765 	ldns_rr *soa_rr;
1766 	ldns_status st;
1767 	uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1768 	uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1769 	size_t valid_zonemds;
1770 
1771 	if (!zone)
1772 		return LDNS_STATUS_NULL;
1773 
1774 	zonemd = ldns_dnssec_zone_find_rrset(
1775 			zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1776 	if (!zonemd) {
1777 		ldns_rbnode_t *nsec3_node;
1778 
1779 		/* we need proof of non-existence for ZONEMD at the apex */
1780 		if (zone->soa->nsec) {
1781 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1782 							zone->soa->nsec),
1783 					       	LDNS_RR_TYPE_ZONEMD))
1784 				return LDNS_STATUS_NO_ZONEMD;
1785 
1786 		} else if (!zone->soa->hashed_name || !zone->hashed_names)
1787 			return LDNS_STATUS_NO_ZONEMD;
1788 
1789 		else if (LDNS_RBTREE_NULL ==
1790 		    (nsec3_node = ldns_rbtree_search( zone->hashed_names
1791 						    , zone->soa->hashed_name)))
1792 			return LDNS_STATUS_NO_ZONEMD;
1793 		else {
1794 			ldns_dnssec_name *nsec3
1795 				= (ldns_dnssec_name *)nsec3_node->data;
1796 			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1797 							nsec3->nsec),
1798 						LDNS_RR_TYPE_ZONEMD))
1799 				return LDNS_STATUS_NO_ZONEMD;
1800 		}
1801 		/* ZONEMD at apex does really not exist */
1802 		return LDNS_STATUS_OK;
1803 	}
1804 	soa = ldns_dnssec_zone_find_rrset(
1805 			zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1806 	if (!soa || !soa->rrs || !soa->rrs->rr)
1807 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1808 
1809 	soa_rr = soa->rrs->rr;
1810 	if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1811 	||  ldns_rr_rd_count(soa_rr) < 3)
1812 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1813 
1814 	zone_digester_init(&zd);
1815 	for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1816 		if (!rrs->rr
1817 		||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1818 		||  ldns_rr_rd_count(rrs->rr) < 4)
1819 			continue;
1820 
1821 		/* serial should match SOA's serial */
1822 		if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1823 		    != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1824 			continue;
1825 
1826 		/* Add (scheme, hash) to digester */
1827 		zone_digester_add(&zd,
1828 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)),
1829 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2)));
1830 	}
1831 	if (!zone_digester_set(&zd))
1832 		return LDNS_STATUS_NO_VALID_ZONEMD;
1833 
1834 	if ((st = ldns_digest_zone(zone, &zd)))
1835 		return st;
1836 
1837 	if (zd.simple_sha384)
1838 		ldns_sha384_final(simple_sha384, &zd.sha384_CTX);
1839 	if (zd.simple_sha512)
1840 		ldns_sha512_final(simple_sha512, &zd.sha512_CTX);
1841 
1842 	valid_zonemds = 0;
1843 	for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1844 		if (!rrs->rr
1845 		||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1846 		||  ldns_rr_rd_count(rrs->rr) < 4)
1847 			continue;
1848 
1849 		/* serial should match SOA's serial */
1850 		if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1851 		    != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1852 			continue;
1853 
1854 		if (ZONEMD_SCHEME_SIMPLE !=
1855 				ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1856 			continue;
1857 
1858 		if (ZONEMD_HASH_SHA384
1859 				== ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1860 		&&  LDNS_SHA384_DIGEST_LENGTH
1861 				== ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1862 		&&  memcmp( simple_sha384
1863 			  , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1864 		          , LDNS_SHA384_DIGEST_LENGTH) == 0)
1865 
1866 			valid_zonemds += 1;
1867 
1868 		if (ZONEMD_HASH_SHA512
1869 				== ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1870 		&&  LDNS_SHA512_DIGEST_LENGTH
1871 				== ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1872 		&&  memcmp( simple_sha512
1873 			  , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1874 		          , LDNS_SHA512_DIGEST_LENGTH) == 0)
1875 
1876 			valid_zonemds += 1;
1877 	}
1878 	return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1879 }
1880 
1881 #ifdef HAVE_SSL
1882 static ldns_status
1883 rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1884 		ldns_rr_list *new_rrs)
1885 {
1886 	ldns_rr *rr = NULL;
1887 
1888 	if (!rr_list || !rrs)
1889 		return LDNS_STATUS_NULL;
1890 
1891 	if (ldns_rr_list_rr_count(rr_list) == 0)
1892 		return LDNS_STATUS_OK;
1893 
1894 	if (!*rrs) {
1895 		if (!(*rrs = ldns_dnssec_rrs_new()))
1896 			return LDNS_STATUS_MEM_ERR;
1897 		(*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1898 		if (new_rrs)
1899 			ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1900 	}
1901 	while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1902 		ldns_status st;
1903 
1904 		if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1905 			ldns_rr_list_push_rr(rr_list, rr);
1906 			return st;
1907 		} else if (new_rrs)
1908 			ldns_rr_list_push_rr(new_rrs, rr);
1909 	}
1910 	return LDNS_STATUS_OK;
1911 }
1912 
1913 
1914 ldns_status
1915 dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1916 		ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1917 {
1918 	ldns_status st = LDNS_STATUS_OK;
1919 	zone_digester zd;
1920 	ldns_rr_list *zonemd_rr_list = NULL;
1921 	ldns_rr_list *zonemd_rrsigs = NULL;
1922 	ldns_dnssec_rrsets *soa_rrset;
1923 	ldns_rr *soa_rr = NULL;
1924 	ldns_dnssec_rrsets **rrset_ref;
1925 	ldns_dnssec_rrsets *zonemd_rrset;
1926 
1927 	zone_digester_init(&zd);
1928 	if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384)
1929 		zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1930 		                     , ZONEMD_HASH_SHA384);
1931 
1932 	if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1933 		zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1934 		                     , ZONEMD_HASH_SHA512);
1935 
1936 	if ((st = ldns_digest_zone(zone, &zd)))
1937 		return st;
1938 
1939 	soa_rrset = ldns_dnssec_zone_find_rrset(
1940 			zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1941 	if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1942 		return LDNS_STATUS_ZONEMD_INVALID_SOA;
1943 	soa_rr = soa_rrset->rrs->rr;
1944 
1945 	if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1946 		return st;
1947 
1948 	/* - replace or add ZONEMD rrset */
1949 	rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1950 	while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1951 		rrset_ref = &(*rrset_ref)->next;
1952 	if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1953 		/* reuse zonemd rrset */
1954 		zonemd_rrset = *rrset_ref;
1955 		ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1956 		zonemd_rrset->rrs = NULL;
1957 		ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1958 		zonemd_rrset->signatures = NULL;
1959 	} else {
1960 		/* insert zonemd rrset */
1961 		zonemd_rrset = ldns_dnssec_rrsets_new();
1962 		if (!zonemd_rrset) {
1963 			ldns_rr_list_deep_free(zonemd_rr_list);
1964 			return LDNS_STATUS_MEM_ERR;
1965 		}
1966 		zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1967 		zonemd_rrset->next = *rrset_ref;
1968 		*rrset_ref = zonemd_rrset;
1969 	}
1970 	if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1971 		st = rr_list2dnssec_rrs(  zonemd_rrsigs
1972 		                       , &zonemd_rrset->signatures, new_rrs);
1973 	if (!st)
1974 		st = rr_list2dnssec_rrs(  zonemd_rr_list
1975 		                       , &zonemd_rrset->rrs, new_rrs);
1976 	ldns_rr_list_deep_free(zonemd_rr_list);
1977 	ldns_rr_list_deep_free(zonemd_rrsigs);
1978 	return st;
1979 }
1980 
1981 #endif /* HAVE_SSL */
1982 
1983