3 * Functions for ldns_zone structure
4 * a Net::DNS like library for C
6 * (c) NLnet Labs, 2005-2006
7 * See the file LICENSE for the license
9 #include <ldns/config.h>
11 #include <ldns/ldns.h>
17 ldns_zone_soa(const ldns_zone
*z
)
23 ldns_zone_rr_count(const ldns_zone
*z
)
25 return ldns_rr_list_rr_count(z
->_rrs
);
29 ldns_zone_set_soa(ldns_zone
*z
, ldns_rr
*soa
)
35 ldns_zone_rrs(const ldns_zone
*z
)
41 ldns_zone_set_rrs(ldns_zone
*z
, ldns_rr_list
*rrlist
)
47 ldns_zone_push_rr_list(ldns_zone
*z
, const ldns_rr_list
*list
)
49 return ldns_rr_list_cat(ldns_zone_rrs(z
), list
);
53 ldns_zone_push_rr(ldns_zone
*z
, ldns_rr
*rr
)
55 return ldns_rr_list_push_rr(ldns_zone_rrs(z
), rr
);
60 * Get the list of glue records in a zone
61 * XXX: there should be a way for this to return error, other than NULL,
62 * since NULL is a valid return
65 ldns_zone_glue_rr_list(const ldns_zone
*z
)
67 /* when do we find glue? It means we find an IP address
68 * (AAAA/A) for a nameserver listed in the zone
71 * first find all the zonecuts (NS records)
72 * find all the AAAA or A records (can be done it the
75 * Check if the aaaa/a list are subdomains under the
77 * If yes -> glue, if no -> not glue
80 ldns_rr_list
*zone_cuts
;
84 ldns_rdf
*dname_a
, *ns_owner
;
91 /* we cannot determine glue in a 'zone' without a SOA */
92 if (!ldns_zone_soa(z
)) {
96 zone_cuts
= ldns_rr_list_new();
97 if (!zone_cuts
) goto memory_error
;
98 addr
= ldns_rr_list_new();
99 if (!addr
) goto memory_error
;
100 glue
= ldns_rr_list_new();
101 if (!glue
) goto memory_error
;
103 for(i
= 0; i
< ldns_zone_rr_count(z
); i
++) {
104 r
= ldns_rr_list_rr(ldns_zone_rrs(z
), i
);
105 if (ldns_rr_get_type(r
) == LDNS_RR_TYPE_A
||
106 ldns_rr_get_type(r
) == LDNS_RR_TYPE_AAAA
) {
108 if (!ldns_rr_list_push_rr(addr
, r
)) goto memory_error
;
111 if (ldns_rr_get_type(r
) == LDNS_RR_TYPE_NS
) {
112 /* multiple zones will end up here -
113 * for now; not a problem
115 /* don't add NS records for the current zone itself */
116 if (ldns_rdf_compare(ldns_rr_owner(r
),
117 ldns_rr_owner(ldns_zone_soa(z
))) != 0) {
118 if (!ldns_rr_list_push_rr(zone_cuts
, r
)) goto memory_error
;
124 /* will sorting make it quicker ?? */
125 for(i
= 0; i
< ldns_rr_list_rr_count(zone_cuts
); i
++) {
126 ns
= ldns_rr_list_rr(zone_cuts
, i
);
127 ns_owner
= ldns_rr_owner(ns
);
129 for(j
= 0; j
< ldns_rr_list_rr_count(addr
); j
++) {
130 a
= ldns_rr_list_rr(addr
, j
);
131 dname_a
= ldns_rr_owner(a
);
133 if (ldns_dname_is_subdomain(dname_a
, ns_owner
) ||
134 ldns_dname_compare(dname_a
, ns_owner
) == 0) {
136 if (!ldns_rr_list_push_rr(glue
, a
)) goto memory_error
;
141 ldns_rr_list_free(addr
);
142 ldns_rr_list_free(zone_cuts
);
144 if (ldns_rr_list_rr_count(glue
) == 0) {
145 ldns_rr_list_free(glue
);
153 LDNS_FREE(zone_cuts
);
156 ldns_rr_list_free(addr
);
159 ldns_rr_list_free(glue
);
169 z
= LDNS_MALLOC(ldns_zone
);
174 z
->_rrs
= ldns_rr_list_new();
179 ldns_zone_set_soa(z
, NULL
);
187 ldns_zone_new_frm_fp(ldns_zone
**z
, FILE *fp
, const ldns_rdf
*origin
, uint32_t ttl
, ldns_rr_class c
)
189 return ldns_zone_new_frm_fp_l(z
, fp
, origin
, ttl
, c
, NULL
);
192 ldns_status
_ldns_rr_new_frm_fp_l_internal(ldns_rr
**newrr
, FILE *fp
,
193 uint32_t *default_ttl
, ldns_rdf
**origin
, ldns_rdf
**prev
,
194 int *line_nr
, bool *explicit_ttl
);
196 /* XXX: class is never used */
198 ldns_zone_new_frm_fp_l(ldns_zone
**z
, FILE *fp
, const ldns_rdf
*origin
,
199 uint32_t default_ttl
, ldns_rr_class
ATTR_UNUSED(c
), int *line_nr
)
202 ldns_rr
*rr
, *prev_rr
= NULL
;
206 bool soa_seen
= false; /* 2 soa are an error */
209 /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
210 * to the last explicitly stated values.'
212 bool ttl_from_TTL
= false;
213 bool explicit_ttl
= false;
215 /* most cases of error are memory problems */
216 ret
= LDNS_STATUS_MEM_ERR
;
222 my_ttl
= default_ttl
;
225 my_origin
= ldns_rdf_clone(origin
);
226 if (!my_origin
) goto error
;
227 /* also set the prev */
228 my_prev
= ldns_rdf_clone(origin
);
229 if (!my_prev
) goto error
;
232 newzone
= ldns_zone_new();
233 if (!newzone
) goto error
;
236 /* If ttl came from $TTL line, then it should be the default.
237 * (RFC 2308 Section 4)
238 * Otherwise it "defaults to the last explicitly stated value"
239 * (RFC 1035 Section 5.1)
242 my_ttl
= default_ttl
;
243 s
= _ldns_rr_new_frm_fp_l_internal(&rr
, fp
, &my_ttl
, &my_origin
,
244 &my_prev
, line_nr
, &explicit_ttl
);
249 /* No $TTL, so ttl "defaults to the
250 * last explicitly stated value"
251 * (RFC 1035 Section 5.1)
253 my_ttl
= ldns_rr_ttl(rr
);
255 /* When ttl is implicit, try to adhere to the rules as
256 * much as possible. (also for compatibility with bind)
257 * This was changed when fixing an issue with ZONEMD
258 * which hashes the TTL too.
260 } else if (ldns_rr_get_type(rr
) == LDNS_RR_TYPE_SIG
261 || ldns_rr_get_type(rr
) == LDNS_RR_TYPE_RRSIG
) {
262 if (ldns_rr_rd_count(rr
) >= 4
263 && ldns_rdf_get_type(ldns_rr_rdf(rr
, 3)) == LDNS_RDF_TYPE_INT32
)
265 /* SIG without explicit ttl get ttl
266 * from the original_ttl field
267 * (RFC 2535 Section 7.2)
269 * Similarly for RRSIG, but stated less
270 * specifically in the spec.
271 * (RFC 4034 Section 3)
274 ldns_rdf2native_int32(
275 ldns_rr_rdf(rr
, 3)));
278 && ldns_rr_get_type(prev_rr
) == ldns_rr_get_type(rr
)
279 && ldns_dname_compare( ldns_rr_owner(prev_rr
)
280 , ldns_rr_owner(rr
)) == 0)
282 /* "TTLs of all RRs in an RRSet must be the same"
283 * (RFC 2881 Section 5.2)
285 ldns_rr_set_ttl(rr
, ldns_rr_ttl(prev_rr
));
288 if (ldns_rr_get_type(rr
) == LDNS_RR_TYPE_SOA
) {
291 * just skip, maybe we want to say
297 ldns_zone_set_soa(newzone
, rr
);
298 /* set origin to soa if not specified */
300 my_origin
= ldns_rdf_clone(ldns_rr_owner(rr
));
305 /* a normal RR - as sofar the DNS is normal */
306 if (!ldns_zone_push_rr(newzone
, rr
)) {
312 case LDNS_STATUS_SYNTAX_EMPTY
:
313 /* empty line was seen */
314 case LDNS_STATUS_SYNTAX_TTL
:
315 /* the function set the ttl */
316 default_ttl
= my_ttl
;
319 case LDNS_STATUS_SYNTAX_ORIGIN
:
320 /* the function set the origin */
322 case LDNS_STATUS_SYNTAX_INCLUDE
:
323 ret
= LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL
;
332 ldns_rdf_deep_free(my_origin
);
335 ldns_rdf_deep_free(my_prev
);
340 ldns_zone_free(newzone
);
343 return LDNS_STATUS_OK
;
347 ldns_rdf_deep_free(my_origin
);
350 ldns_rdf_deep_free(my_prev
);
353 ldns_zone_free(newzone
);
359 ldns_zone_sort(ldns_zone
*zone
)
362 assert(zone
!= NULL
);
364 zrr
= ldns_zone_rrs(zone
);
365 ldns_rr_list_sort(zrr
);
369 ldns_zone_free(ldns_zone
*zone
)
371 ldns_rr_list_free(zone
->_rrs
);
376 ldns_zone_deep_free(ldns_zone
*zone
)
378 ldns_rr_free(zone
->_soa
);
379 ldns_rr_list_deep_free(zone
->_rrs
);