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