File Coverage

src/ldns/zone.c
Criterion Covered Total %
statement 57 134 42.5
branch 16 66 24.2
condition n/a
subroutine n/a
pod n/a
total 73 200 36.5


line stmt bran cond sub pod time code
1             /* zone.c
2             *
3             * Functions for ldns_zone structure
4             * a Net::DNS like library for C
5             *
6             * (c) NLnet Labs, 2005-2006
7             * See the file LICENSE for the license
8             */
9             #include
10              
11             #include
12              
13             #include
14             #include
15              
16             ldns_rr *
17 1           ldns_zone_soa(const ldns_zone *z)
18             {
19 1           return z->_soa;
20             }
21              
22             size_t
23 0           ldns_zone_rr_count(const ldns_zone *z)
24             {
25 0           return ldns_rr_list_rr_count(z->_rrs);
26             }
27              
28             void
29 2           ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa)
30             {
31 2           z->_soa = soa;
32 2           }
33              
34             ldns_rr_list *
35 16           ldns_zone_rrs(const ldns_zone *z)
36             {
37 16           return z->_rrs;
38             }
39              
40             void
41 0           ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
42             {
43 0           z->_rrs = rrlist;
44 0           }
45              
46             bool
47 0           ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list)
48             {
49 0           return ldns_rr_list_cat(ldns_zone_rrs(z), list);
50              
51             }
52              
53             bool
54 15           ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
55             {
56 15           return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr);
57             }
58              
59              
60             /*
61             * Get the list of glue records in a zone
62             * XXX: there should be a way for this to return error, other than NULL,
63             * since NULL is a valid return
64             */
65             ldns_rr_list *
66 0           ldns_zone_glue_rr_list(const ldns_zone *z)
67             {
68             /* when do we find glue? It means we find an IP address
69             * (AAAA/A) for a nameserver listed in the zone
70             *
71             * Alg used here:
72             * first find all the zonecuts (NS records)
73             * find all the AAAA or A records (can be done it the
74             * above loop).
75             *
76             * Check if the aaaa/a list are subdomains under the
77             * NS domains.
78             * If yes -> glue, if no -> not glue
79             */
80              
81             ldns_rr_list *zone_cuts;
82             ldns_rr_list *addr;
83             ldns_rr_list *glue;
84             ldns_rr *r, *ns, *a;
85             ldns_rdf *dname_a, *ns_owner;
86             size_t i,j;
87              
88 0           zone_cuts = NULL;
89 0           addr = NULL;
90 0           glue = NULL;
91              
92             /* we cannot determine glue in a 'zone' without a SOA */
93 0 0         if (!ldns_zone_soa(z)) {
94 0           return NULL;
95             }
96              
97 0           zone_cuts = ldns_rr_list_new();
98 0 0         if (!zone_cuts) goto memory_error;
99 0           addr = ldns_rr_list_new();
100 0 0         if (!addr) goto memory_error;
101 0           glue = ldns_rr_list_new();
102 0 0         if (!glue) goto memory_error;
103              
104 0 0         for(i = 0; i < ldns_zone_rr_count(z); i++) {
105 0           r = ldns_rr_list_rr(ldns_zone_rrs(z), i);
106 0           if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
107 0           ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
108             /* possibly glue */
109 0 0         if (!ldns_rr_list_push_rr(addr, r)) goto memory_error;
110 0           continue;
111             }
112 0 0         if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
113             /* multiple zones will end up here -
114             * for now; not a problem
115             */
116             /* don't add NS records for the current zone itself */
117 0 0         if (ldns_rdf_compare(ldns_rr_owner(r),
118 0           ldns_rr_owner(ldns_zone_soa(z))) != 0) {
119 0 0         if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error;
120             }
121 0           continue;
122             }
123             }
124              
125             /* will sorting make it quicker ?? */
126 0 0         for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
127 0           ns = ldns_rr_list_rr(zone_cuts, i);
128 0           ns_owner = ldns_rr_owner(ns);
129              
130 0 0         for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
131 0           a = ldns_rr_list_rr(addr, j);
132 0           dname_a = ldns_rr_owner(a);
133              
134 0           if (ldns_dname_is_subdomain(dname_a, ns_owner) ||
135 0           ldns_dname_compare(dname_a, ns_owner) == 0) {
136             /* GLUE! */
137 0 0         if (!ldns_rr_list_push_rr(glue, a)) goto memory_error;
138             }
139             }
140             }
141            
142 0           ldns_rr_list_free(addr);
143 0           ldns_rr_list_free(zone_cuts);
144              
145 0 0         if (ldns_rr_list_rr_count(glue) == 0) {
146 0           ldns_rr_list_free(glue);
147 0           return NULL;
148             } else {
149 0           return glue;
150             }
151              
152             memory_error:
153 0 0         if (zone_cuts) {
154 0           LDNS_FREE(zone_cuts);
155             }
156 0 0         if (addr) {
157 0           ldns_rr_list_free(addr);
158             }
159 0 0         if (glue) {
160 0           ldns_rr_list_free(glue);
161             }
162 0           return NULL;
163             }
164              
165             ldns_zone *
166 1           ldns_zone_new(void)
167             {
168             ldns_zone *z;
169              
170 1           z = LDNS_MALLOC(ldns_zone);
171 1 50         if (!z) {
172 0           return NULL;
173             }
174              
175 1           z->_rrs = ldns_rr_list_new();
176 1 50         if (!z->_rrs) {
177 0           LDNS_FREE(z);
178 0           return NULL;
179             }
180 1           ldns_zone_set_soa(z, NULL);
181 1           return z;
182             }
183              
184             /* we regocnize:
185             * $TTL, $ORIGIN
186             */
187             ldns_status
188 1           ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c)
189             {
190 1           return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
191             }
192              
193             /* XXX: class is never used */
194             ldns_status
195 1           ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl,
196             ldns_rr_class ATTR_UNUSED(c), int *line_nr)
197             {
198             ldns_zone *newzone;
199             ldns_rr *rr;
200             uint32_t my_ttl;
201             ldns_rdf *my_origin;
202             ldns_rdf *my_prev;
203 1           bool soa_seen = false; /* 2 soa are an error */
204             ldns_status s;
205             ldns_status ret;
206              
207             /* most cases of error are memory problems */
208 1           ret = LDNS_STATUS_MEM_ERR;
209              
210 1           newzone = NULL;
211 1           my_origin = NULL;
212 1           my_prev = NULL;
213              
214 1           my_ttl = ttl;
215            
216 1 50         if (origin) {
217 1           my_origin = ldns_rdf_clone(origin);
218 1 50         if (!my_origin) goto error;
219             /* also set the prev */
220 1           my_prev = ldns_rdf_clone(origin);
221 1 50         if (!my_prev) goto error;
222             }
223              
224 1           newzone = ldns_zone_new();
225 1 50         if (!newzone) goto error;
226              
227 20 100         while(!feof(fp)) {
228 19           s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr);
229 19           switch (s) {
230             case LDNS_STATUS_OK:
231 16 100         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
232 1 50         if (soa_seen) {
233             /* second SOA
234             * just skip, maybe we want to say
235             * something??? */
236 0           ldns_rr_free(rr);
237 0           continue;
238             }
239 1           soa_seen = true;
240 1           ldns_zone_set_soa(newzone, rr);
241             /* set origin to soa if not specified */
242 1 50         if (!my_origin) {
243 0           my_origin = ldns_rdf_clone(ldns_rr_owner(rr));
244             }
245 1           continue;
246             }
247            
248             /* a normal RR - as sofar the DNS is normal */
249 15 50         if (!ldns_zone_push_rr(newzone, rr)) goto error;
250              
251             case LDNS_STATUS_SYNTAX_EMPTY:
252             /* empty line was seen */
253             case LDNS_STATUS_SYNTAX_TTL:
254             /* the function set the ttl */
255 16           break;
256             case LDNS_STATUS_SYNTAX_ORIGIN:
257             /* the function set the origin */
258 2           break;
259             case LDNS_STATUS_SYNTAX_INCLUDE:
260 0           ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
261 0           break;
262             default:
263 0           ret = s;
264 0           goto error;
265             }
266             }
267              
268 1 50         if (my_origin) {
269 1           ldns_rdf_deep_free(my_origin);
270             }
271 1 50         if (my_prev) {
272 1           ldns_rdf_deep_free(my_prev);
273             }
274 1 50         if (z) {
275 1           *z = newzone;
276             } else {
277 0           ldns_zone_free(newzone);
278             }
279              
280 1           return LDNS_STATUS_OK;
281              
282             error:
283 0 0         if (my_origin) {
284 0           ldns_rdf_deep_free(my_origin);
285             }
286 0 0         if (my_prev) {
287 0           ldns_rdf_deep_free(my_prev);
288             }
289 0 0         if (newzone) {
290 0           ldns_zone_free(newzone);
291             }
292 1           return ret;
293             }
294              
295             void
296 0           ldns_zone_sort(ldns_zone *zone)
297             {
298             ldns_rr_list *zrr;
299             assert(zone != NULL);
300              
301 0           zrr = ldns_zone_rrs(zone);
302 0           ldns_rr_list_sort(zrr);
303 0           }
304              
305             void
306 0           ldns_zone_free(ldns_zone *zone)
307             {
308 0           ldns_rr_list_free(zone->_rrs);
309 0           LDNS_FREE(zone);
310 0           }
311              
312             void
313 1           ldns_zone_deep_free(ldns_zone *zone)
314             {
315 1           ldns_rr_free(zone->_soa);
316 1           ldns_rr_list_deep_free(zone->_rrs);
317 1           LDNS_FREE(zone);
318 1           }