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