xref: /dragonfly/contrib/ldns/dnssec_zone.c (revision 029e6489)
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 
9 ldns_dnssec_rrs *
10 ldns_dnssec_rrs_new(void)
11 {
12 	ldns_dnssec_rrs *new_rrs;
13 	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
14         if(!new_rrs) return NULL;
15 	new_rrs->rr = NULL;
16 	new_rrs->next = NULL;
17 	return new_rrs;
18 }
19 
20 INLINE void
21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
22 {
23 	ldns_dnssec_rrs *next;
24 	while (rrs) {
25 		next = rrs->next;
26 		if (deep) {
27 			ldns_rr_free(rrs->rr);
28 		}
29 		LDNS_FREE(rrs);
30 		rrs = next;
31 	}
32 }
33 
34 void
35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
36 {
37 	ldns_dnssec_rrs_free_internal(rrs, 0);
38 }
39 
40 void
41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
42 {
43 	ldns_dnssec_rrs_free_internal(rrs, 1);
44 }
45 
46 ldns_status
47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
48 {
49 	int cmp;
50 	ldns_dnssec_rrs *new_rrs;
51 	if (!rrs || !rr) {
52 		return LDNS_STATUS_ERR;
53 	}
54 
55 	/* this could be done more efficiently; name and type should already
56 	   be equal */
57 	cmp = ldns_rr_compare(rrs->rr, rr);
58 	if (cmp < 0) {
59 		if (rrs->next) {
60 			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
61 		} else {
62 			new_rrs = ldns_dnssec_rrs_new();
63 			new_rrs->rr = rr;
64 			rrs->next = new_rrs;
65 		}
66 	} else if (cmp > 0) {
67 		/* put the current old rr in the new next, put the new
68 		   rr in the current container */
69 		new_rrs = ldns_dnssec_rrs_new();
70 		new_rrs->rr = rrs->rr;
71 		new_rrs->next = rrs->next;
72 		rrs->rr = rr;
73 		rrs->next = new_rrs;
74 	}
75 	/* Silently ignore equal rr's */
76 	return LDNS_STATUS_OK;
77 }
78 
79 void
80 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
81 	       const ldns_dnssec_rrs *rrs)
82 {
83 	if (!rrs) {
84 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
85 			fprintf(out, "; <void>");
86 	} else {
87 		if (rrs->rr) {
88 			ldns_rr_print_fmt(out, fmt, rrs->rr);
89 		}
90 		if (rrs->next) {
91 			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
92 		}
93 	}
94 }
95 
96 void
97 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
98 {
99 	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
100 }
101 
102 
103 ldns_dnssec_rrsets *
104 ldns_dnssec_rrsets_new(void)
105 {
106 	ldns_dnssec_rrsets *new_rrsets;
107 	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
108         if(!new_rrsets) return NULL;
109 	new_rrsets->rrs = NULL;
110 	new_rrsets->type = 0;
111 	new_rrsets->signatures = NULL;
112 	new_rrsets->next = NULL;
113 	return new_rrsets;
114 }
115 
116 INLINE void
117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
118 {
119 	if (rrsets) {
120 		if (rrsets->rrs) {
121 			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
122 		}
123 		if (rrsets->next) {
124 			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
125 		}
126 		if (rrsets->signatures) {
127 			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
128 		}
129 		LDNS_FREE(rrsets);
130 	}
131 }
132 
133 void
134 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
135 {
136 	ldns_dnssec_rrsets_free_internal(rrsets, 0);
137 }
138 
139 void
140 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
141 {
142 	ldns_dnssec_rrsets_free_internal(rrsets, 1);
143 }
144 
145 ldns_rr_type
146 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
147 {
148 	if (rrsets) {
149 		return rrsets->type;
150 	} else {
151 		return 0;
152 	}
153 }
154 
155 ldns_status
156 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
157 					   ldns_rr_type type)
158 {
159 	if (rrsets) {
160 		rrsets->type = type;
161 		return LDNS_STATUS_OK;
162 	}
163 	return LDNS_STATUS_ERR;
164 }
165 
166 static ldns_dnssec_rrsets *
167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
168 {
169 	ldns_dnssec_rrsets *new_rrsets;
170 	ldns_rr_type rr_type;
171 	bool rrsig;
172 
173 	new_rrsets = ldns_dnssec_rrsets_new();
174 	rr_type = ldns_rr_get_type(rr);
175 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
176 		rrsig = true;
177 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
178 	} else {
179 		rrsig = false;
180 	}
181 	if (!rrsig) {
182 		new_rrsets->rrs = ldns_dnssec_rrs_new();
183 		new_rrsets->rrs->rr = rr;
184 	} else {
185 		new_rrsets->signatures = ldns_dnssec_rrs_new();
186 		new_rrsets->signatures->rr = rr;
187 	}
188 	new_rrsets->type = rr_type;
189 	return new_rrsets;
190 }
191 
192 ldns_status
193 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
194 {
195 	ldns_dnssec_rrsets *new_rrsets;
196 	ldns_rr_type rr_type;
197 	bool rrsig = false;
198 	ldns_status result = LDNS_STATUS_OK;
199 
200 	if (!rrsets || !rr) {
201 		return LDNS_STATUS_ERR;
202 	}
203 
204 	rr_type = ldns_rr_get_type(rr);
205 
206 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
207 		rrsig = true;
208 		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
209 	}
210 
211 	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
212 		if (!rrsig) {
213 			rrsets->rrs = ldns_dnssec_rrs_new();
214 			rrsets->rrs->rr = rr;
215 			rrsets->type = rr_type;
216 		} else {
217 			rrsets->signatures = ldns_dnssec_rrs_new();
218 			rrsets->signatures->rr = rr;
219 			rrsets->type = rr_type;
220 		}
221 		return LDNS_STATUS_OK;
222 	}
223 
224 	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
225 		if (rrsets->next) {
226 			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
227 		} else {
228 			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
229 			rrsets->next = new_rrsets;
230 		}
231 	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
232 		/* move the current one into the new next,
233 		   replace field of current with data from new rr */
234 		new_rrsets = ldns_dnssec_rrsets_new();
235 		new_rrsets->rrs = rrsets->rrs;
236 		new_rrsets->type = rrsets->type;
237 		new_rrsets->signatures = rrsets->signatures;
238 		new_rrsets->next = rrsets->next;
239 		if (!rrsig) {
240 			rrsets->rrs = ldns_dnssec_rrs_new();
241 			rrsets->rrs->rr = rr;
242 			rrsets->signatures = NULL;
243 		} else {
244 			rrsets->rrs = NULL;
245 			rrsets->signatures = ldns_dnssec_rrs_new();
246 			rrsets->signatures->rr = rr;
247 		}
248 		rrsets->type = rr_type;
249 		rrsets->next = new_rrsets;
250 	} else {
251 		/* equal, add to current rrsets */
252 		if (rrsig) {
253 			if (rrsets->signatures) {
254 				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
255 			} else {
256 				rrsets->signatures = ldns_dnssec_rrs_new();
257 				rrsets->signatures->rr = rr;
258 			}
259 		} else {
260 			if (rrsets->rrs) {
261 				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
262 			} else {
263 				rrsets->rrs = ldns_dnssec_rrs_new();
264 				rrsets->rrs->rr = rr;
265 			}
266 		}
267 	}
268 
269 	return result;
270 }
271 
272 static void
273 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
274 		const ldns_dnssec_rrsets *rrsets,
275 		bool follow,
276 		bool show_soa)
277 {
278 	if (!rrsets) {
279 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
280 			fprintf(out, "; <void>\n");
281 	} else {
282 		if (rrsets->rrs &&
283 		    (show_soa ||
284 			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
285 		    )
286 		   ) {
287 			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
288 			if (rrsets->signatures) {
289 				ldns_dnssec_rrs_print_fmt(out, fmt,
290 						rrsets->signatures);
291 			}
292 		}
293 		if (follow && rrsets->next) {
294 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295 					rrsets->next, follow, show_soa);
296 		}
297 	}
298 }
299 
300 
301 void
302 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
303 		const ldns_dnssec_rrsets *rrsets,
304 		bool follow)
305 {
306 	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
307 }
308 
309 void
310 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
311 {
312 	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
313 			rrsets, follow);
314 }
315 
316 ldns_dnssec_name *
317 ldns_dnssec_name_new(void)
318 {
319 	ldns_dnssec_name *new_name;
320 
321 	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
322 	if (!new_name) {
323 		return NULL;
324 	}
325 	/*
326 	 * not needed anymore because CALLOC initalizes everything to zero.
327 
328 	new_name->name = NULL;
329 	new_name->rrsets = NULL;
330 	new_name->name_alloced = false;
331 	new_name->nsec = NULL;
332 	new_name->nsec_signatures = NULL;
333 
334 	new_name->is_glue = false;
335 	new_name->hashed_name = NULL;
336 
337 	 */
338 	return new_name;
339 }
340 
341 ldns_dnssec_name *
342 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
343 {
344 	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
345 
346 	new_name->name = ldns_rr_owner(rr);
347 	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
348 		ldns_dnssec_name_free(new_name);
349 		return NULL;
350 	}
351 
352 	return new_name;
353 }
354 
355 INLINE void
356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357                                int deep)
358 {
359 	if (name) {
360 		if (name->name_alloced) {
361 			ldns_rdf_deep_free(name->name);
362 		}
363 		if (name->rrsets) {
364 			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
365 		}
366 		if (name->nsec && deep) {
367 			ldns_rr_free(name->nsec);
368 		}
369 		if (name->nsec_signatures) {
370 			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
371 		}
372 		if (name->hashed_name) {
373 			if (deep) {
374 				ldns_rdf_deep_free(name->hashed_name);
375 			}
376 		}
377 		LDNS_FREE(name);
378 	}
379 }
380 
381 void
382 ldns_dnssec_name_free(ldns_dnssec_name *name)
383 {
384   ldns_dnssec_name_free_internal(name, 0);
385 }
386 
387 void
388 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
389 {
390   ldns_dnssec_name_free_internal(name, 1);
391 }
392 
393 ldns_rdf *
394 ldns_dnssec_name_name(const ldns_dnssec_name *name)
395 {
396 	if (name) {
397 		return name->name;
398 	}
399 	return NULL;
400 }
401 
402 bool
403 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
404 {
405 	if (name) {
406 		return name->is_glue;
407 	}
408 	return false;
409 }
410 
411 void
412 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
413 					 ldns_rdf *dname)
414 {
415 	if (rrset && dname) {
416 		rrset->name = dname;
417 	}
418 }
419 
420 
421 void
422 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
423 {
424 	if (rrset && nsec) {
425 		rrset->nsec = nsec;
426 	}
427 }
428 
429 int
430 ldns_dnssec_name_cmp(const void *a, const void *b)
431 {
432 	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
433 	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
434 
435 	if (na && nb) {
436 		return ldns_dname_compare(ldns_dnssec_name_name(na),
437 							 ldns_dnssec_name_name(nb));
438 	} else if (na) {
439 		return 1;
440 	} else if (nb) {
441 		return -1;
442 	} else {
443 		return 0;
444 	}
445 }
446 
447 ldns_status
448 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
449 				    ldns_rr *rr)
450 {
451 	ldns_status result = LDNS_STATUS_OK;
452 	ldns_rr_type rr_type;
453 	ldns_rr_type typecovered = 0;
454 
455 	/* special handling for NSEC3 and NSECX covering RRSIGS */
456 
457 	if (!name || !rr) {
458 		return LDNS_STATUS_ERR;
459 	}
460 
461 	rr_type = ldns_rr_get_type(rr);
462 
463 	if (rr_type == LDNS_RR_TYPE_RRSIG) {
464 		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
465 	}
466 
467 	if (rr_type == LDNS_RR_TYPE_NSEC ||
468 	    rr_type == LDNS_RR_TYPE_NSEC3) {
469 		/* XX check if is already set (and error?) */
470 		name->nsec = rr;
471 	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
472 			 typecovered == LDNS_RR_TYPE_NSEC3) {
473 		if (name->nsec_signatures) {
474 			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
475 		} else {
476 			name->nsec_signatures = ldns_dnssec_rrs_new();
477 			name->nsec_signatures->rr = rr;
478 		}
479 	} else {
480 		/* it's a 'normal' RR, add it to the right rrset */
481 		if (name->rrsets) {
482 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
483 		} else {
484 			name->rrsets = ldns_dnssec_rrsets_new();
485 			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
486 		}
487 	}
488 	return result;
489 }
490 
491 ldns_dnssec_rrsets *
492 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
493 					   ldns_rr_type type) {
494 	ldns_dnssec_rrsets *result;
495 
496 	result = name->rrsets;
497 	while (result) {
498 		if (result->type == type) {
499 			return result;
500 		} else {
501 			result = result->next;
502 		}
503 	}
504 	return NULL;
505 }
506 
507 ldns_dnssec_rrsets *
508 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
509 					   const ldns_rdf *dname,
510 					   ldns_rr_type type)
511 {
512 	ldns_rbnode_t *node;
513 
514 	if (!zone || !dname || !zone->names) {
515 		return NULL;
516 	}
517 
518 	node = ldns_rbtree_search(zone->names, dname);
519 	if (node) {
520 		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
521 									type);
522 	} else {
523 		return NULL;
524 	}
525 }
526 
527 static void
528 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
529 		const ldns_dnssec_name *name,
530 		bool show_soa)
531 {
532 	if (name) {
533 		if(name->rrsets) {
534 			ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
535 					name->rrsets, true, show_soa);
536 		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
537 			fprintf(out, ";; Empty nonterminal: ");
538 			ldns_rdf_print(out, name->name);
539 			fprintf(out, "\n");
540 		}
541 		if(name->nsec) {
542 			ldns_rr_print_fmt(out, fmt, name->nsec);
543 		}
544 		if (name->nsec_signatures) {
545 			ldns_dnssec_rrs_print_fmt(out, fmt,
546 					name->nsec_signatures);
547 		}
548 	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
549 		fprintf(out, "; <void>\n");
550 	}
551 }
552 
553 
554 void
555 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
556 		const ldns_dnssec_name *name)
557 {
558 	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
559 }
560 
561 void
562 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
563 {
564 	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
565 }
566 
567 
568 ldns_dnssec_zone *
569 ldns_dnssec_zone_new(void)
570 {
571 	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
572         if(!zone) return NULL;
573 	zone->soa = NULL;
574 	zone->names = NULL;
575 	zone->hashed_names = NULL;
576 	zone->_nsec3params = NULL;
577 
578 	return zone;
579 }
580 
581 static bool
582 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
583 {
584 	return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
585 		&& ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
586 }
587 
588 /* When the zone is first read into an list and then inserted into an
589  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
590  * to each other. Because ldns-verify-zone (the only program that uses this
591  * function) uses the rbtree mostly for sequentual walking, this results
592  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
593  */
594 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
595 
596 static ldns_status
597 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
598 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
599 
600 static void
601 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
602 	(void) arg;
603 	ldns_rdf_deep_free((ldns_rdf *)node->key);
604 	LDNS_FREE(node);
605 }
606 
607 ldns_status
608 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
609 	       	uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
610 {
611 	ldns_rr* cur_rr;
612 	size_t i;
613 
614 	ldns_rdf *my_origin = NULL;
615 	ldns_rdf *my_prev = NULL;
616 
617 	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
618 	/* NSEC3s may occur before the names they refer to. We must remember
619 	   them and add them to the name later on, after the name is read.
620 	   We track not yet  matching NSEC3s*n the todo_nsec3s list */
621 	ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
622 	/* when reading NSEC3s, there is a chance that we encounter nsecs
623 	   for empty nonterminals, whose nonterminals we cannot derive yet
624 	   because the needed information is to be read later.
625 
626 	   nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
627 	   hold the NSEC3s that still didn't have a matching name in the
628 	   zone tree, even after all names were read.  They can only match
629 	   after the zone is equiped with all the empty non terminals. */
630 	ldns_rbtree_t todo_nsec3_ents;
631 	ldns_rbnode_t *new_node;
632 	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
633 
634 	ldns_status status;
635 
636 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
637 	ldns_zone* zone = NULL;
638 #else
639 	uint32_t  my_ttl = ttl;
640 #endif
641 
642 	ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
643 
644 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
645 	status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr);
646 	if (status != LDNS_STATUS_OK)
647 		goto error;
648 #endif
649 	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
650 		status = LDNS_STATUS_MEM_ERR;
651 		goto error;
652 	}
653 	if (origin) {
654 		if (!(my_origin = ldns_rdf_clone(origin))) {
655 			status = LDNS_STATUS_MEM_ERR;
656 			goto error;
657 		}
658 		if (!(my_prev   = ldns_rdf_clone(origin))) {
659 			status = LDNS_STATUS_MEM_ERR;
660 			goto error;
661 		}
662 	}
663 
664 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
665 	if (ldns_zone_soa(zone)) {
666 		status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
667 		if (status != LDNS_STATUS_OK)
668 			goto error;
669 	}
670 	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
671 		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
672 		status = LDNS_STATUS_OK;
673 #else
674 	while (!feof(fp)) {
675 		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
676 				&my_prev, line_nr);
677 
678 #endif
679 		switch (status) {
680 		case LDNS_STATUS_OK:
681 
682 			status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
683 			if (status ==
684 				LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
685 
686 				if (rr_is_rrsig_covering(cur_rr,
687 							LDNS_RR_TYPE_NSEC3)){
688 					ldns_rr_list_push_rr(todo_nsec3_rrsigs,
689 							cur_rr);
690 				} else {
691 					ldns_rr_list_push_rr(todo_nsec3s,
692 						       	cur_rr);
693 				}
694 				status = LDNS_STATUS_OK;
695 
696 			} else if (status != LDNS_STATUS_OK)
697 				goto error;
698 
699 			break;
700 
701 
702 		case LDNS_STATUS_SYNTAX_EMPTY:	/* empty line was seen */
703 		case LDNS_STATUS_SYNTAX_TTL:	/* the ttl was set*/
704 		case LDNS_STATUS_SYNTAX_ORIGIN:	/* the origin was set*/
705 			status = LDNS_STATUS_OK;
706 			break;
707 
708 		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
709 			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
710 			break;
711 
712 		default:
713 			goto error;
714 		}
715 	}
716 
717 	for (i = 0; status == LDNS_STATUS_OK &&
718 			i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
719 		cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
720 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
721 		if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
722 			if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
723 				status = LDNS_STATUS_MEM_ERR;
724 				break;
725 			}
726 			new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
727 			new_node->data = cur_rr;
728 			if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
729 				LDNS_FREE(new_node);
730 				status = LDNS_STATUS_MEM_ERR;
731 				break;
732 			}
733 			status = LDNS_STATUS_OK;
734 		}
735 	}
736 	if (todo_nsec3_ents.count > 0)
737 		(void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
738 				newzone, &todo_nsec3_ents);
739 	for (i = 0; status == LDNS_STATUS_OK &&
740 			i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
741 		cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
742 		status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
743 	}
744 	if (z) {
745 		*z = newzone;
746 		newzone = NULL;
747 	} else {
748 		ldns_dnssec_zone_free(newzone);
749 		newzone = NULL;
750 	}
751 
752 error:
753 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
754 	if (zone) {
755 		ldns_zone_free(zone);
756 	}
757 #endif
758 	ldns_rr_list_free(todo_nsec3_rrsigs);
759 	ldns_traverse_postorder(&todo_nsec3_ents,
760 			ldns_todo_nsec3_ents_node_free, NULL);
761 	ldns_rr_list_free(todo_nsec3s);
762 
763 	if (my_origin) {
764 		ldns_rdf_deep_free(my_origin);
765 	}
766 	if (my_prev) {
767 		ldns_rdf_deep_free(my_prev);
768 	}
769 	if (newzone) {
770 		ldns_dnssec_zone_free(newzone);
771 	}
772 	return status;
773 }
774 
775 ldns_status
776 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
777 		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
778 {
779 	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
780 }
781 
782 static void
783 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
784 	(void) arg;
785 	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
786 	LDNS_FREE(node);
787 }
788 
789 static void
790 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
791 	(void) arg;
792 	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
793 	LDNS_FREE(node);
794 }
795 
796 void
797 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
798 {
799 	if (zone) {
800 		if (zone->names) {
801 			/* destroy all name structures within the tree */
802 			ldns_traverse_postorder(zone->names,
803 						    ldns_dnssec_name_node_free,
804 						    NULL);
805 			LDNS_FREE(zone->names);
806 		}
807 		LDNS_FREE(zone);
808 	}
809 }
810 
811 void
812 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
813 {
814 	if (zone) {
815 		if (zone->names) {
816 			/* destroy all name structures within the tree */
817 			ldns_traverse_postorder(zone->names,
818 						    ldns_dnssec_name_node_deep_free,
819 						    NULL);
820 			LDNS_FREE(zone->names);
821 		}
822 		LDNS_FREE(zone);
823 	}
824 }
825 
826 /* use for dname comparison in tree */
827 int
828 ldns_dname_compare_v(const void *a, const void *b) {
829 	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
830 }
831 
832 static void
833 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
834 		ldns_dnssec_name* name, ldns_rr* nsec3rr);
835 
836 static void
837 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
838 	(void) arg;
839 	LDNS_FREE(node);
840 }
841 
842 static void
843 ldns_dnssec_zone_hashed_names_from_nsec3(
844 		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
845 {
846 	ldns_rbnode_t* current_node;
847 	ldns_dnssec_name* current_name;
848 
849 	assert(zone != NULL);
850 	assert(nsec3rr != NULL);
851 
852 	if (zone->hashed_names) {
853 		ldns_traverse_postorder(zone->hashed_names,
854 				ldns_hashed_names_node_free, NULL);
855 		LDNS_FREE(zone->hashed_names);
856 	}
857 	zone->_nsec3params = nsec3rr;
858 
859 	/* So this is a NSEC3 zone.
860 	* Calculate hashes for all names already in the zone
861 	*/
862 	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
863 	if (zone->hashed_names == NULL) {
864 		return;
865 	}
866 	for ( current_node  = ldns_rbtree_first(zone->names)
867 	    ; current_node != LDNS_RBTREE_NULL
868 	    ; current_node  = ldns_rbtree_next(current_node)
869 	    ) {
870 		current_name = (ldns_dnssec_name *) current_node->data;
871 		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
872 
873 	}
874 }
875 
876 static void
877 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
878 		ldns_dnssec_name* name, ldns_rr* nsec3rr)
879 {
880 	ldns_rbnode_t* new_node;
881 
882 	assert(name != NULL);
883 	if (! zone->_nsec3params) {
884 		if (! nsec3rr) {
885 			return;
886 		}
887 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
888 
889 	} else if (! nsec3rr) {
890 		nsec3rr = zone->_nsec3params;
891 	}
892 	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
893 
894 	/* Also store in zone->hashed_names */
895 	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
896 
897 		new_node->key  = name->hashed_name;
898 		new_node->data = name;
899 
900 		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
901 
902 				LDNS_FREE(new_node);
903 		}
904 	}
905 }
906 
907 
908 static ldns_rbnode_t *
909 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
910 	ldns_rdf *hashed_name;
911 
912 	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
913 	if (hashed_name == NULL) {
914 		return NULL;
915 	}
916 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
917 
918 		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
919 	}
920 	if (zone->hashed_names == NULL) {
921 		ldns_rdf_deep_free(hashed_name);
922 		return NULL;
923 	}
924 	return  ldns_rbtree_search(zone->hashed_names, hashed_name);
925 }
926 
927 ldns_status
928 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
929 {
930 	ldns_status result = LDNS_STATUS_OK;
931 	ldns_dnssec_name *cur_name;
932 	ldns_rbnode_t *cur_node;
933 	ldns_rr_type type_covered = 0;
934 
935 	if (!zone || !rr) {
936 		return LDNS_STATUS_ERR;
937 	}
938 
939 	if (!zone->names) {
940 		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
941                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
942 	}
943 
944 	/* we need the original of the hashed name if this is
945 	   an NSEC3, or an RRSIG that covers an NSEC3 */
946 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
947 		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
948 	}
949 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
950 	    type_covered == LDNS_RR_TYPE_NSEC3) {
951 		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
952 		if (!cur_node) {
953 			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
954 		}
955 	} else {
956 		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
957 	}
958 	if (!cur_node) {
959 		/* add */
960 		cur_name = ldns_dnssec_name_new_frm_rr(rr);
961                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
962 		cur_node = LDNS_MALLOC(ldns_rbnode_t);
963                 if(!cur_node) {
964                         ldns_dnssec_name_free(cur_name);
965                         return LDNS_STATUS_MEM_ERR;
966                 }
967 		cur_node->key = ldns_rr_owner(rr);
968 		cur_node->data = cur_name;
969 		(void)ldns_rbtree_insert(zone->names, cur_node);
970 		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
971 	} else {
972 		cur_name = (ldns_dnssec_name *) cur_node->data;
973 		result = ldns_dnssec_name_add_rr(cur_name, rr);
974 	}
975 	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
976 		zone->soa = cur_name;
977 	}
978 	return result;
979 }
980 
981 void
982 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
983 		const ldns_rbtree_t *tree,
984 		bool print_soa)
985 {
986 	ldns_rbnode_t *node;
987 	ldns_dnssec_name *name;
988 
989 	node = ldns_rbtree_first(tree);
990 	while (node != LDNS_RBTREE_NULL) {
991 		name = (ldns_dnssec_name *) node->data;
992 		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
993 		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
994 			fprintf(out, ";\n");
995 		node = ldns_rbtree_next(node);
996 	}
997 }
998 
999 void
1000 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1001 {
1002 	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1003 		       tree, print_soa);
1004 }
1005 
1006 void
1007 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1008 	       const ldns_dnssec_zone *zone)
1009 {
1010 	if (zone) {
1011 		if (zone->soa) {
1012 			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1013 				fprintf(out, ";; Zone: ");
1014 				ldns_rdf_print(out, ldns_dnssec_name_name(
1015 							zone->soa));
1016 				fprintf(out, "\n;\n");
1017 			}
1018 			ldns_dnssec_rrsets_print_fmt(out, fmt,
1019 					ldns_dnssec_name_find_rrset(
1020 						zone->soa,
1021 						LDNS_RR_TYPE_SOA),
1022 					false);
1023 			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1024 				fprintf(out, ";\n");
1025 		}
1026 
1027 		if (zone->names) {
1028 			ldns_dnssec_zone_names_print_fmt(out, fmt,
1029 					zone->names, false);
1030 		}
1031 	}
1032 }
1033 
1034 void
1035 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1036 {
1037 	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1038 }
1039 
1040 static ldns_status
1041 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1042 		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1043 {
1044 	ldns_dnssec_name *new_name;
1045 	ldns_rdf *cur_name;
1046 	ldns_rdf *next_name;
1047 	ldns_rbnode_t *cur_node, *next_node, *new_node;
1048 
1049 	/* for the detection */
1050 	uint16_t i, cur_label_count, next_label_count;
1051 	uint16_t soa_label_count = 0;
1052 	ldns_rdf *l1, *l2;
1053 	int lpos;
1054 
1055 	if (!zone) {
1056 		return LDNS_STATUS_ERR;
1057 	}
1058 	if (zone->soa && zone->soa->name) {
1059 		soa_label_count = ldns_dname_label_count(zone->soa->name);
1060 	}
1061 
1062 	cur_node = ldns_rbtree_first(zone->names);
1063 	while (cur_node != LDNS_RBTREE_NULL) {
1064 		next_node = ldns_rbtree_next(cur_node);
1065 
1066 		/* skip glue */
1067 		while (next_node != LDNS_RBTREE_NULL &&
1068 		       next_node->data &&
1069 		       ((ldns_dnssec_name *)next_node->data)->is_glue
1070 		) {
1071 			next_node = ldns_rbtree_next(next_node);
1072 		}
1073 
1074 		if (next_node == LDNS_RBTREE_NULL) {
1075 			next_node = ldns_rbtree_first(zone->names);
1076 		}
1077 		if (! cur_node->data || ! next_node->data) {
1078 			return LDNS_STATUS_ERR;
1079 		}
1080 		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1081 		next_name = ((ldns_dnssec_name *)next_node->data)->name;
1082 		cur_label_count = ldns_dname_label_count(cur_name);
1083 		next_label_count = ldns_dname_label_count(next_name);
1084 
1085 		/* Since the names are in canonical order, we can
1086 		 * recognize empty non-terminals by their labels;
1087 		 * every label after the first one on the next owner
1088 		 * name is a non-terminal if it either does not exist
1089 		 * in the current name or is different from the same
1090 		 * label in the current name (counting from the end)
1091 		 */
1092 		for (i = 1; i < next_label_count - soa_label_count; i++) {
1093 			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1094 			if (lpos >= 0) {
1095 				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1096 			} else {
1097 				l1 = NULL;
1098 			}
1099 			l2 = ldns_dname_clone_from(next_name, i);
1100 
1101 			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1102 				/* We have an empty nonterminal, add it to the
1103 				 * tree
1104 				 */
1105 				ldns_rbnode_t *node = NULL;
1106 				ldns_rdf *ent_name;
1107 
1108 				if (!(ent_name = ldns_dname_clone_from(
1109 						next_name, i))) {
1110 
1111 					ldns_rdf_deep_free(l1);
1112 					ldns_rdf_deep_free(l2);
1113 					return LDNS_STATUS_MEM_ERR;
1114 				}
1115 
1116 				if (nsec3s && zone->_nsec3params) {
1117 					ldns_rdf *ent_hashed_name;
1118 
1119 					if (!(ent_hashed_name =
1120 					    ldns_nsec3_hash_name_frm_nsec3(
1121 							zone->_nsec3params,
1122 							ent_name))) {
1123 						ldns_rdf_deep_free(l1);
1124 						ldns_rdf_deep_free(l2);
1125 						ldns_rdf_deep_free(ent_name);
1126 						return LDNS_STATUS_MEM_ERR;
1127 					}
1128 					node = ldns_rbtree_search(nsec3s,
1129 							ent_hashed_name);
1130 					if (!node) {
1131 						ldns_rdf_deep_free(l1);
1132 						ldns_rdf_deep_free(l2);
1133 						ldns_rdf_deep_free(ent_name);
1134 						continue;
1135 					}
1136 				}
1137 				new_name = ldns_dnssec_name_new();
1138 				if (!new_name) {
1139 					ldns_rdf_deep_free(l1);
1140 					ldns_rdf_deep_free(l2);
1141 					ldns_rdf_deep_free(ent_name);
1142 					return LDNS_STATUS_MEM_ERR;
1143 				}
1144 				new_name->name = ent_name;
1145 				new_name->name_alloced = true;
1146 				new_node = LDNS_MALLOC(ldns_rbnode_t);
1147 				if (!new_node) {
1148 					ldns_rdf_deep_free(l1);
1149 					ldns_rdf_deep_free(l2);
1150 					ldns_dnssec_name_free(new_name);
1151 					return LDNS_STATUS_MEM_ERR;
1152 				}
1153 				new_node->key = new_name->name;
1154 				new_node->data = new_name;
1155 				(void)ldns_rbtree_insert(zone->names, new_node);
1156 				ldns_dnssec_name_make_hashed_name(
1157 						zone, new_name, NULL);
1158 				if (node)
1159 					(void) ldns_dnssec_zone_add_rr(zone,
1160 							(ldns_rr *)node->data);
1161 			}
1162 			ldns_rdf_deep_free(l1);
1163 			ldns_rdf_deep_free(l2);
1164 		}
1165 
1166 		/* we might have inserted a new node after
1167 		 * the current one so we can't just use next()
1168 		 */
1169 		if (next_node != ldns_rbtree_first(zone->names)) {
1170 			cur_node = next_node;
1171 		} else {
1172 			cur_node = LDNS_RBTREE_NULL;
1173 		}
1174 	}
1175 	return LDNS_STATUS_OK;
1176 }
1177 
1178 ldns_status
1179 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1180 {
1181 	return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1182 }
1183 
1184 bool
1185 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1186 {
1187 	ldns_rr* nsec3;
1188 	ldns_rbnode_t* node;
1189 
1190 	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1191 		node = ldns_rbtree_first(zone->names);
1192 		while (node != LDNS_RBTREE_NULL) {
1193 			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1194 			if (nsec3 &&ldns_rr_get_type(nsec3)
1195 					== LDNS_RR_TYPE_NSEC3 &&
1196 					ldns_nsec3_optout(nsec3)) {
1197 				return true;
1198 			}
1199 			node = ldns_rbtree_next(node);
1200 		}
1201 	}
1202 	return false;
1203 }
1204