xref: /freebsd/contrib/ldns/zone.c (revision 7b5038d71c5c74ab863c1ff3fec33de94bf35a57)
1*7b5038d7SDag-Erling Smørgrav /* zone.c
2*7b5038d7SDag-Erling Smørgrav  *
3*7b5038d7SDag-Erling Smørgrav  * Functions for ldns_zone structure
4*7b5038d7SDag-Erling Smørgrav  * a Net::DNS like library for C
5*7b5038d7SDag-Erling Smørgrav  *
6*7b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2005-2006
7*7b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
8*7b5038d7SDag-Erling Smørgrav  */
9*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
10*7b5038d7SDag-Erling Smørgrav 
11*7b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
12*7b5038d7SDag-Erling Smørgrav 
13*7b5038d7SDag-Erling Smørgrav #include <strings.h>
14*7b5038d7SDag-Erling Smørgrav #include <limits.h>
15*7b5038d7SDag-Erling Smørgrav 
16*7b5038d7SDag-Erling Smørgrav ldns_rr *
17*7b5038d7SDag-Erling Smørgrav ldns_zone_soa(const ldns_zone *z)
18*7b5038d7SDag-Erling Smørgrav {
19*7b5038d7SDag-Erling Smørgrav         return z->_soa;
20*7b5038d7SDag-Erling Smørgrav }
21*7b5038d7SDag-Erling Smørgrav 
22*7b5038d7SDag-Erling Smørgrav size_t
23*7b5038d7SDag-Erling Smørgrav ldns_zone_rr_count(const ldns_zone *z)
24*7b5038d7SDag-Erling Smørgrav {
25*7b5038d7SDag-Erling Smørgrav 	return ldns_rr_list_rr_count(z->_rrs);
26*7b5038d7SDag-Erling Smørgrav }
27*7b5038d7SDag-Erling Smørgrav 
28*7b5038d7SDag-Erling Smørgrav void
29*7b5038d7SDag-Erling Smørgrav ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa)
30*7b5038d7SDag-Erling Smørgrav {
31*7b5038d7SDag-Erling Smørgrav 	z->_soa = soa;
32*7b5038d7SDag-Erling Smørgrav }
33*7b5038d7SDag-Erling Smørgrav 
34*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
35*7b5038d7SDag-Erling Smørgrav ldns_zone_rrs(const ldns_zone *z)
36*7b5038d7SDag-Erling Smørgrav {
37*7b5038d7SDag-Erling Smørgrav 	return z->_rrs;
38*7b5038d7SDag-Erling Smørgrav }
39*7b5038d7SDag-Erling Smørgrav 
40*7b5038d7SDag-Erling Smørgrav void
41*7b5038d7SDag-Erling Smørgrav ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
42*7b5038d7SDag-Erling Smørgrav {
43*7b5038d7SDag-Erling Smørgrav 	z->_rrs = rrlist;
44*7b5038d7SDag-Erling Smørgrav }
45*7b5038d7SDag-Erling Smørgrav 
46*7b5038d7SDag-Erling Smørgrav bool
47*7b5038d7SDag-Erling Smørgrav ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list)
48*7b5038d7SDag-Erling Smørgrav {
49*7b5038d7SDag-Erling Smørgrav 	return ldns_rr_list_cat(ldns_zone_rrs(z), list);
50*7b5038d7SDag-Erling Smørgrav 
51*7b5038d7SDag-Erling Smørgrav }
52*7b5038d7SDag-Erling Smørgrav 
53*7b5038d7SDag-Erling Smørgrav bool
54*7b5038d7SDag-Erling Smørgrav ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
55*7b5038d7SDag-Erling Smørgrav {
56*7b5038d7SDag-Erling Smørgrav 	return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr);
57*7b5038d7SDag-Erling Smørgrav }
58*7b5038d7SDag-Erling Smørgrav 
59*7b5038d7SDag-Erling Smørgrav /* return a clone of the given rr list, without the glue records
60*7b5038d7SDag-Erling Smørgrav  * rr list should be the complete zone
61*7b5038d7SDag-Erling Smørgrav  * if present, stripped records are added to the list *glue_records
62*7b5038d7SDag-Erling Smørgrav  */
63*7b5038d7SDag-Erling Smørgrav static ldns_rr_list *
64*7b5038d7SDag-Erling Smørgrav ldns_zone_strip_glue_rrs(const ldns_rdf *zone_name, const ldns_rr_list *rrs, ldns_rr_list *glue_rrs)
65*7b5038d7SDag-Erling Smørgrav {
66*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *new_list;
67*7b5038d7SDag-Erling Smørgrav 
68*7b5038d7SDag-Erling Smørgrav 	/* when do we find glue? It means we find an IP address
69*7b5038d7SDag-Erling Smørgrav 	 * (AAAA/A) for a nameserver listed in the zone
70*7b5038d7SDag-Erling Smørgrav 	 *
71*7b5038d7SDag-Erling Smørgrav 	 * Alg used here:
72*7b5038d7SDag-Erling Smørgrav 	 * first find all the zonecuts (NS records)
73*7b5038d7SDag-Erling Smørgrav 	 * find all the AAAA or A records (can be done it the
74*7b5038d7SDag-Erling Smørgrav 	 * above loop).
75*7b5038d7SDag-Erling Smørgrav 	 *
76*7b5038d7SDag-Erling Smørgrav 	 * Check if the aaaa/a list are subdomains under the
77*7b5038d7SDag-Erling Smørgrav 	 * NS domains.
78*7b5038d7SDag-Erling Smørgrav 	 * If yes -> glue, if no -> not glue
79*7b5038d7SDag-Erling Smørgrav 	 */
80*7b5038d7SDag-Erling Smørgrav 
81*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *zone_cuts;
82*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *addr;
83*7b5038d7SDag-Erling Smørgrav 	ldns_rr *r, *ns, *a;
84*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *dname_a, *ns_owner;
85*7b5038d7SDag-Erling Smørgrav 	uint16_t i,j;
86*7b5038d7SDag-Erling Smørgrav 
87*7b5038d7SDag-Erling Smørgrav 	new_list = NULL;
88*7b5038d7SDag-Erling Smørgrav 	zone_cuts = NULL;
89*7b5038d7SDag-Erling Smørgrav 	addr = NULL;
90*7b5038d7SDag-Erling Smørgrav 
91*7b5038d7SDag-Erling Smørgrav 	new_list = ldns_rr_list_new();
92*7b5038d7SDag-Erling Smørgrav 	if (!new_list) goto memory_error;
93*7b5038d7SDag-Erling Smørgrav 	zone_cuts = ldns_rr_list_new();
94*7b5038d7SDag-Erling Smørgrav 	if (!zone_cuts) goto memory_error;
95*7b5038d7SDag-Erling Smørgrav 	addr = ldns_rr_list_new();
96*7b5038d7SDag-Erling Smørgrav 	if (!addr) goto memory_error;
97*7b5038d7SDag-Erling Smørgrav 
98*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
99*7b5038d7SDag-Erling Smørgrav 		r = ldns_rr_list_rr(rrs, i);
100*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
101*7b5038d7SDag-Erling Smørgrav 				ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
102*7b5038d7SDag-Erling Smørgrav 			/* possibly glue */
103*7b5038d7SDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(addr, r)) goto memory_error;
104*7b5038d7SDag-Erling Smørgrav 			continue;
105*7b5038d7SDag-Erling Smørgrav 		}
106*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
107*7b5038d7SDag-Erling Smørgrav 			/* multiple zones will end up here -
108*7b5038d7SDag-Erling Smørgrav 			 * for now; not a problem
109*7b5038d7SDag-Erling Smørgrav 			 */
110*7b5038d7SDag-Erling Smørgrav 			/* don't add NS records for the current zone itself */
111*7b5038d7SDag-Erling Smørgrav 			if (ldns_rdf_compare(ldns_rr_owner(r),
112*7b5038d7SDag-Erling Smørgrav 						zone_name) != 0) {
113*7b5038d7SDag-Erling Smørgrav 				if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error;
114*7b5038d7SDag-Erling Smørgrav 			}
115*7b5038d7SDag-Erling Smørgrav 			continue;
116*7b5038d7SDag-Erling Smørgrav 		}
117*7b5038d7SDag-Erling Smørgrav 	}
118*7b5038d7SDag-Erling Smørgrav 
119*7b5038d7SDag-Erling Smørgrav 	/* will sorting make it quicker ?? */
120*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
121*7b5038d7SDag-Erling Smørgrav 		ns = ldns_rr_list_rr(zone_cuts, i);
122*7b5038d7SDag-Erling Smørgrav 		ns_owner = ldns_rr_owner(ns);
123*7b5038d7SDag-Erling Smørgrav 		for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
124*7b5038d7SDag-Erling Smørgrav 			a = ldns_rr_list_rr(addr, j);
125*7b5038d7SDag-Erling Smørgrav 			dname_a = ldns_rr_owner(a);
126*7b5038d7SDag-Erling Smørgrav 
127*7b5038d7SDag-Erling Smørgrav 			if (ldns_dname_is_subdomain(dname_a, ns_owner)) {
128*7b5038d7SDag-Erling Smørgrav 				/* GLUE! */
129*7b5038d7SDag-Erling Smørgrav 				if (glue_rrs) {
130*7b5038d7SDag-Erling Smørgrav 					if (!ldns_rr_list_push_rr(glue_rrs, a)) goto memory_error;
131*7b5038d7SDag-Erling Smørgrav 				}
132*7b5038d7SDag-Erling Smørgrav 				break;
133*7b5038d7SDag-Erling Smørgrav 			} else {
134*7b5038d7SDag-Erling Smørgrav 				if (!ldns_rr_list_push_rr(new_list, a)) goto memory_error;
135*7b5038d7SDag-Erling Smørgrav 			}
136*7b5038d7SDag-Erling Smørgrav 		}
137*7b5038d7SDag-Erling Smørgrav 	}
138*7b5038d7SDag-Erling Smørgrav 
139*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(addr);
140*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(zone_cuts);
141*7b5038d7SDag-Erling Smørgrav 
142*7b5038d7SDag-Erling Smørgrav 	return new_list;
143*7b5038d7SDag-Erling Smørgrav 
144*7b5038d7SDag-Erling Smørgrav memory_error:
145*7b5038d7SDag-Erling Smørgrav 	if (new_list) {
146*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(new_list);
147*7b5038d7SDag-Erling Smørgrav 	}
148*7b5038d7SDag-Erling Smørgrav 	if (zone_cuts) {
149*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(zone_cuts);
150*7b5038d7SDag-Erling Smørgrav 	}
151*7b5038d7SDag-Erling Smørgrav 	if (addr) {
152*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(addr);
153*7b5038d7SDag-Erling Smørgrav 	}
154*7b5038d7SDag-Erling Smørgrav 	return NULL;
155*7b5038d7SDag-Erling Smørgrav }
156*7b5038d7SDag-Erling Smørgrav 
157*7b5038d7SDag-Erling Smørgrav /*
158*7b5038d7SDag-Erling Smørgrav  * Get the list of glue records in a zone
159*7b5038d7SDag-Erling Smørgrav  * XXX: there should be a way for this to return error, other than NULL,
160*7b5038d7SDag-Erling Smørgrav  *      since NULL is a valid return
161*7b5038d7SDag-Erling Smørgrav  */
162*7b5038d7SDag-Erling Smørgrav ldns_rr_list *
163*7b5038d7SDag-Erling Smørgrav ldns_zone_glue_rr_list(const ldns_zone *z)
164*7b5038d7SDag-Erling Smørgrav {
165*7b5038d7SDag-Erling Smørgrav 	/* when do we find glue? It means we find an IP address
166*7b5038d7SDag-Erling Smørgrav 	 * (AAAA/A) for a nameserver listed in the zone
167*7b5038d7SDag-Erling Smørgrav 	 *
168*7b5038d7SDag-Erling Smørgrav 	 * Alg used here:
169*7b5038d7SDag-Erling Smørgrav 	 * first find all the zonecuts (NS records)
170*7b5038d7SDag-Erling Smørgrav 	 * find all the AAAA or A records (can be done it the
171*7b5038d7SDag-Erling Smørgrav 	 * above loop).
172*7b5038d7SDag-Erling Smørgrav 	 *
173*7b5038d7SDag-Erling Smørgrav 	 * Check if the aaaa/a list are subdomains under the
174*7b5038d7SDag-Erling Smørgrav 	 * NS domains.
175*7b5038d7SDag-Erling Smørgrav 	 * If yes -> glue, if no -> not glue
176*7b5038d7SDag-Erling Smørgrav 	 */
177*7b5038d7SDag-Erling Smørgrav 
178*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *zone_cuts;
179*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *addr;
180*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *glue;
181*7b5038d7SDag-Erling Smørgrav 	ldns_rr *r, *ns, *a;
182*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *dname_a, *ns_owner;
183*7b5038d7SDag-Erling Smørgrav 	size_t i,j;
184*7b5038d7SDag-Erling Smørgrav 
185*7b5038d7SDag-Erling Smørgrav 	zone_cuts = NULL;
186*7b5038d7SDag-Erling Smørgrav 	addr = NULL;
187*7b5038d7SDag-Erling Smørgrav 	glue = NULL;
188*7b5038d7SDag-Erling Smørgrav 
189*7b5038d7SDag-Erling Smørgrav 	/* we cannot determine glue in a 'zone' without a SOA */
190*7b5038d7SDag-Erling Smørgrav 	if (!ldns_zone_soa(z)) {
191*7b5038d7SDag-Erling Smørgrav 		return NULL;
192*7b5038d7SDag-Erling Smørgrav 	}
193*7b5038d7SDag-Erling Smørgrav 
194*7b5038d7SDag-Erling Smørgrav 	zone_cuts = ldns_rr_list_new();
195*7b5038d7SDag-Erling Smørgrav 	if (!zone_cuts) goto memory_error;
196*7b5038d7SDag-Erling Smørgrav 	addr = ldns_rr_list_new();
197*7b5038d7SDag-Erling Smørgrav 	if (!addr) goto memory_error;
198*7b5038d7SDag-Erling Smørgrav 	glue = ldns_rr_list_new();
199*7b5038d7SDag-Erling Smørgrav 	if (!glue) goto memory_error;
200*7b5038d7SDag-Erling Smørgrav 
201*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_zone_rr_count(z); i++) {
202*7b5038d7SDag-Erling Smørgrav 		r = ldns_rr_list_rr(ldns_zone_rrs(z), i);
203*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
204*7b5038d7SDag-Erling Smørgrav 				ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
205*7b5038d7SDag-Erling Smørgrav 			/* possibly glue */
206*7b5038d7SDag-Erling Smørgrav 			if (!ldns_rr_list_push_rr(addr, r)) goto memory_error;
207*7b5038d7SDag-Erling Smørgrav 			continue;
208*7b5038d7SDag-Erling Smørgrav 		}
209*7b5038d7SDag-Erling Smørgrav 		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
210*7b5038d7SDag-Erling Smørgrav 			/* multiple zones will end up here -
211*7b5038d7SDag-Erling Smørgrav 			 * for now; not a problem
212*7b5038d7SDag-Erling Smørgrav 			 */
213*7b5038d7SDag-Erling Smørgrav 			/* don't add NS records for the current zone itself */
214*7b5038d7SDag-Erling Smørgrav 			if (ldns_rdf_compare(ldns_rr_owner(r),
215*7b5038d7SDag-Erling Smørgrav 						ldns_rr_owner(ldns_zone_soa(z))) != 0) {
216*7b5038d7SDag-Erling Smørgrav 				if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error;
217*7b5038d7SDag-Erling Smørgrav 			}
218*7b5038d7SDag-Erling Smørgrav 			continue;
219*7b5038d7SDag-Erling Smørgrav 		}
220*7b5038d7SDag-Erling Smørgrav 	}
221*7b5038d7SDag-Erling Smørgrav 
222*7b5038d7SDag-Erling Smørgrav 	/* will sorting make it quicker ?? */
223*7b5038d7SDag-Erling Smørgrav 	for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
224*7b5038d7SDag-Erling Smørgrav 		ns = ldns_rr_list_rr(zone_cuts, i);
225*7b5038d7SDag-Erling Smørgrav 		ns_owner = ldns_rr_owner(ns);
226*7b5038d7SDag-Erling Smørgrav 
227*7b5038d7SDag-Erling Smørgrav 		for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
228*7b5038d7SDag-Erling Smørgrav 			a = ldns_rr_list_rr(addr, j);
229*7b5038d7SDag-Erling Smørgrav 			dname_a = ldns_rr_owner(a);
230*7b5038d7SDag-Erling Smørgrav 
231*7b5038d7SDag-Erling Smørgrav 			if (ldns_dname_is_subdomain(dname_a, ns_owner) ||
232*7b5038d7SDag-Erling Smørgrav 				ldns_dname_compare(dname_a, ns_owner) == 0) {
233*7b5038d7SDag-Erling Smørgrav 				/* GLUE! */
234*7b5038d7SDag-Erling Smørgrav 				if (!ldns_rr_list_push_rr(glue, a)) goto memory_error;
235*7b5038d7SDag-Erling Smørgrav 			}
236*7b5038d7SDag-Erling Smørgrav 		}
237*7b5038d7SDag-Erling Smørgrav 	}
238*7b5038d7SDag-Erling Smørgrav 
239*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(addr);
240*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(zone_cuts);
241*7b5038d7SDag-Erling Smørgrav 
242*7b5038d7SDag-Erling Smørgrav 	if (ldns_rr_list_rr_count(glue) == 0) {
243*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(glue);
244*7b5038d7SDag-Erling Smørgrav 		return NULL;
245*7b5038d7SDag-Erling Smørgrav 	} else {
246*7b5038d7SDag-Erling Smørgrav 		return glue;
247*7b5038d7SDag-Erling Smørgrav 	}
248*7b5038d7SDag-Erling Smørgrav 
249*7b5038d7SDag-Erling Smørgrav memory_error:
250*7b5038d7SDag-Erling Smørgrav 	if (zone_cuts) {
251*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(zone_cuts);
252*7b5038d7SDag-Erling Smørgrav 	}
253*7b5038d7SDag-Erling Smørgrav 	if (addr) {
254*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(addr);
255*7b5038d7SDag-Erling Smørgrav 	}
256*7b5038d7SDag-Erling Smørgrav 	if (glue) {
257*7b5038d7SDag-Erling Smørgrav 		ldns_rr_list_free(glue);
258*7b5038d7SDag-Erling Smørgrav 	}
259*7b5038d7SDag-Erling Smørgrav 	return NULL;
260*7b5038d7SDag-Erling Smørgrav }
261*7b5038d7SDag-Erling Smørgrav 
262*7b5038d7SDag-Erling Smørgrav ldns_zone *
263*7b5038d7SDag-Erling Smørgrav ldns_zone_new(void)
264*7b5038d7SDag-Erling Smørgrav {
265*7b5038d7SDag-Erling Smørgrav 	ldns_zone *z;
266*7b5038d7SDag-Erling Smørgrav 
267*7b5038d7SDag-Erling Smørgrav 	z = LDNS_MALLOC(ldns_zone);
268*7b5038d7SDag-Erling Smørgrav 	if (!z) {
269*7b5038d7SDag-Erling Smørgrav 		return NULL;
270*7b5038d7SDag-Erling Smørgrav 	}
271*7b5038d7SDag-Erling Smørgrav 
272*7b5038d7SDag-Erling Smørgrav 	z->_rrs = ldns_rr_list_new();
273*7b5038d7SDag-Erling Smørgrav 	if (!z->_rrs) {
274*7b5038d7SDag-Erling Smørgrav 		LDNS_FREE(z);
275*7b5038d7SDag-Erling Smørgrav 		return NULL;
276*7b5038d7SDag-Erling Smørgrav 	}
277*7b5038d7SDag-Erling Smørgrav 	ldns_zone_set_soa(z, NULL);
278*7b5038d7SDag-Erling Smørgrav 	return z;
279*7b5038d7SDag-Erling Smørgrav }
280*7b5038d7SDag-Erling Smørgrav 
281*7b5038d7SDag-Erling Smørgrav /* we regocnize:
282*7b5038d7SDag-Erling Smørgrav  * $TTL, $ORIGIN
283*7b5038d7SDag-Erling Smørgrav  */
284*7b5038d7SDag-Erling Smørgrav ldns_status
285*7b5038d7SDag-Erling Smørgrav ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c)
286*7b5038d7SDag-Erling Smørgrav {
287*7b5038d7SDag-Erling Smørgrav 	return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
288*7b5038d7SDag-Erling Smørgrav }
289*7b5038d7SDag-Erling Smørgrav 
290*7b5038d7SDag-Erling Smørgrav /* XXX: class is never used */
291*7b5038d7SDag-Erling Smørgrav ldns_status
292*7b5038d7SDag-Erling Smørgrav ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl,
293*7b5038d7SDag-Erling Smørgrav         ldns_rr_class ATTR_UNUSED(c), int *line_nr)
294*7b5038d7SDag-Erling Smørgrav {
295*7b5038d7SDag-Erling Smørgrav 	ldns_zone *newzone;
296*7b5038d7SDag-Erling Smørgrav 	ldns_rr *rr;
297*7b5038d7SDag-Erling Smørgrav 	uint32_t my_ttl;
298*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_origin;
299*7b5038d7SDag-Erling Smørgrav 	ldns_rdf *my_prev;
300*7b5038d7SDag-Erling Smørgrav 	bool soa_seen = false; 	/* 2 soa are an error */
301*7b5038d7SDag-Erling Smørgrav 	ldns_status s;
302*7b5038d7SDag-Erling Smørgrav 	ldns_status ret;
303*7b5038d7SDag-Erling Smørgrav 
304*7b5038d7SDag-Erling Smørgrav 	/* most cases of error are memory problems */
305*7b5038d7SDag-Erling Smørgrav 	ret = LDNS_STATUS_MEM_ERR;
306*7b5038d7SDag-Erling Smørgrav 
307*7b5038d7SDag-Erling Smørgrav 	newzone = NULL;
308*7b5038d7SDag-Erling Smørgrav 	my_origin = NULL;
309*7b5038d7SDag-Erling Smørgrav 	my_prev = NULL;
310*7b5038d7SDag-Erling Smørgrav 
311*7b5038d7SDag-Erling Smørgrav 	my_ttl    = ttl;
312*7b5038d7SDag-Erling Smørgrav 
313*7b5038d7SDag-Erling Smørgrav 	if (origin) {
314*7b5038d7SDag-Erling Smørgrav 		my_origin = ldns_rdf_clone(origin);
315*7b5038d7SDag-Erling Smørgrav 		if (!my_origin) goto error;
316*7b5038d7SDag-Erling Smørgrav 		/* also set the prev */
317*7b5038d7SDag-Erling Smørgrav 		my_prev   = ldns_rdf_clone(origin);
318*7b5038d7SDag-Erling Smørgrav 		if (!my_prev) goto error;
319*7b5038d7SDag-Erling Smørgrav 	}
320*7b5038d7SDag-Erling Smørgrav 
321*7b5038d7SDag-Erling Smørgrav 	newzone = ldns_zone_new();
322*7b5038d7SDag-Erling Smørgrav 	if (!newzone) goto error;
323*7b5038d7SDag-Erling Smørgrav 
324*7b5038d7SDag-Erling Smørgrav 	while(!feof(fp)) {
325*7b5038d7SDag-Erling Smørgrav 		s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr);
326*7b5038d7SDag-Erling Smørgrav 		switch (s) {
327*7b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_OK:
328*7b5038d7SDag-Erling Smørgrav 			if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
329*7b5038d7SDag-Erling Smørgrav 				if (soa_seen) {
330*7b5038d7SDag-Erling Smørgrav 					/* second SOA
331*7b5038d7SDag-Erling Smørgrav 					 * just skip, maybe we want to say
332*7b5038d7SDag-Erling Smørgrav 					 * something??? */
333*7b5038d7SDag-Erling Smørgrav 					ldns_rr_free(rr);
334*7b5038d7SDag-Erling Smørgrav 					continue;
335*7b5038d7SDag-Erling Smørgrav 				}
336*7b5038d7SDag-Erling Smørgrav 				soa_seen = true;
337*7b5038d7SDag-Erling Smørgrav 				ldns_zone_set_soa(newzone, rr);
338*7b5038d7SDag-Erling Smørgrav 				/* set origin to soa if not specified */
339*7b5038d7SDag-Erling Smørgrav 				if (!my_origin) {
340*7b5038d7SDag-Erling Smørgrav 					my_origin = ldns_rdf_clone(ldns_rr_owner(rr));
341*7b5038d7SDag-Erling Smørgrav 				}
342*7b5038d7SDag-Erling Smørgrav 				continue;
343*7b5038d7SDag-Erling Smørgrav 			}
344*7b5038d7SDag-Erling Smørgrav 
345*7b5038d7SDag-Erling Smørgrav 			/* a normal RR - as sofar the DNS is normal */
346*7b5038d7SDag-Erling Smørgrav 			if (!ldns_zone_push_rr(newzone, rr)) goto error;
347*7b5038d7SDag-Erling Smørgrav 
348*7b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_EMPTY:
349*7b5038d7SDag-Erling Smørgrav 			/* empty line was seen */
350*7b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_TTL:
351*7b5038d7SDag-Erling Smørgrav 			/* the function set the ttl */
352*7b5038d7SDag-Erling Smørgrav 			break;
353*7b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_ORIGIN:
354*7b5038d7SDag-Erling Smørgrav 			/* the function set the origin */
355*7b5038d7SDag-Erling Smørgrav 			break;
356*7b5038d7SDag-Erling Smørgrav 		case LDNS_STATUS_SYNTAX_INCLUDE:
357*7b5038d7SDag-Erling Smørgrav 			ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
358*7b5038d7SDag-Erling Smørgrav 			break;
359*7b5038d7SDag-Erling Smørgrav 		default:
360*7b5038d7SDag-Erling Smørgrav 			ret = s;
361*7b5038d7SDag-Erling Smørgrav 			goto error;
362*7b5038d7SDag-Erling Smørgrav 		}
363*7b5038d7SDag-Erling Smørgrav 	}
364*7b5038d7SDag-Erling Smørgrav 
365*7b5038d7SDag-Erling Smørgrav 	if (my_origin) {
366*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_origin);
367*7b5038d7SDag-Erling Smørgrav 	}
368*7b5038d7SDag-Erling Smørgrav 	if (my_prev) {
369*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_prev);
370*7b5038d7SDag-Erling Smørgrav 	}
371*7b5038d7SDag-Erling Smørgrav 	if (z) {
372*7b5038d7SDag-Erling Smørgrav 		*z = newzone;
373*7b5038d7SDag-Erling Smørgrav 	} else {
374*7b5038d7SDag-Erling Smørgrav 		ldns_zone_free(newzone);
375*7b5038d7SDag-Erling Smørgrav 	}
376*7b5038d7SDag-Erling Smørgrav 
377*7b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
378*7b5038d7SDag-Erling Smørgrav 
379*7b5038d7SDag-Erling Smørgrav error:
380*7b5038d7SDag-Erling Smørgrav 	if (my_origin) {
381*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_origin);
382*7b5038d7SDag-Erling Smørgrav 	}
383*7b5038d7SDag-Erling Smørgrav 	if (my_prev) {
384*7b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(my_prev);
385*7b5038d7SDag-Erling Smørgrav 	}
386*7b5038d7SDag-Erling Smørgrav 	if (newzone) {
387*7b5038d7SDag-Erling Smørgrav 		ldns_zone_free(newzone);
388*7b5038d7SDag-Erling Smørgrav 	}
389*7b5038d7SDag-Erling Smørgrav 	return ret;
390*7b5038d7SDag-Erling Smørgrav }
391*7b5038d7SDag-Erling Smørgrav 
392*7b5038d7SDag-Erling Smørgrav void
393*7b5038d7SDag-Erling Smørgrav ldns_zone_sort(ldns_zone *zone)
394*7b5038d7SDag-Erling Smørgrav {
395*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list *zrr;
396*7b5038d7SDag-Erling Smørgrav 	assert(zone != NULL);
397*7b5038d7SDag-Erling Smørgrav 
398*7b5038d7SDag-Erling Smørgrav 	zrr = ldns_zone_rrs(zone);
399*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_sort(zrr);
400*7b5038d7SDag-Erling Smørgrav }
401*7b5038d7SDag-Erling Smørgrav 
402*7b5038d7SDag-Erling Smørgrav #if 0
403*7b5038d7SDag-Erling Smørgrav /**
404*7b5038d7SDag-Erling Smørgrav  * ixfr function. Work on a ldns_zone and remove and add
405*7b5038d7SDag-Erling Smørgrav  * the rrs from the rrlist
406*7b5038d7SDag-Erling Smørgrav  * \param[in] z the zone to work on
407*7b5038d7SDag-Erling Smørgrav  * \param[in] del rr_list to remove from the zone
408*7b5038d7SDag-Erling Smørgrav  * \param[in] add rr_list to add to the zone
409*7b5038d7SDag-Erling Smørgrav  * \return Tja, wat zouden we eens returnen TODO
410*7b5038d7SDag-Erling Smørgrav  */
411*7b5038d7SDag-Erling Smørgrav void
412*7b5038d7SDag-Erling Smørgrav ldns_zone_ixfr_del_add(ldns_zone *z, ldns_rr_list *del, ldns_rr_list *add)
413*7b5038d7SDag-Erling Smørgrav {
414*7b5038d7SDag-Erling Smørgrav 
415*7b5038d7SDag-Erling Smørgrav }
416*7b5038d7SDag-Erling Smørgrav #endif
417*7b5038d7SDag-Erling Smørgrav 
418*7b5038d7SDag-Erling Smørgrav void
419*7b5038d7SDag-Erling Smørgrav ldns_zone_free(ldns_zone *zone)
420*7b5038d7SDag-Erling Smørgrav {
421*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_free(zone->_rrs);
422*7b5038d7SDag-Erling Smørgrav 	LDNS_FREE(zone);
423*7b5038d7SDag-Erling Smørgrav }
424*7b5038d7SDag-Erling Smørgrav 
425*7b5038d7SDag-Erling Smørgrav void
426*7b5038d7SDag-Erling Smørgrav ldns_zone_deep_free(ldns_zone *zone)
427*7b5038d7SDag-Erling Smørgrav {
428*7b5038d7SDag-Erling Smørgrav 	ldns_rr_free(zone->_soa);
429*7b5038d7SDag-Erling Smørgrav 	ldns_rr_list_deep_free(zone->_rrs);
430*7b5038d7SDag-Erling Smørgrav 	LDNS_FREE(zone);
431*7b5038d7SDag-Erling Smørgrav }
432