3 * Where all the hard work concerning chasing
5 * (c) 2005, 2006 NLnet Labs
7 * See the file LICENSE for the license
12 #include <ldns/ldns.h>
14 /* Cache all RRs from rr_list "rr_list" to "referrals" database for lookup
15 * later on. Print the NS RRs that were not already present.
17 static void add_rr_list_to_referrals(
18 ldns_dnssec_zone
*referrals
, ldns_rr_list
*rr_list
)
22 ldns_dnssec_rrsets
*rrset
;
25 for (i
= 0; i
< ldns_rr_list_rr_count(rr_list
); i
++) {
26 rr
= ldns_rr_list_rr(rr_list
, i
);
27 /* Check if a RR equal to "rr" is present in "referrals" */
28 rrset
= ldns_dnssec_zone_find_rrset(
29 referrals
, ldns_rr_owner(rr
), ldns_rr_get_type(rr
));
31 for (rrs
= rrset
->rrs
; rrs
; rrs
= rrs
->next
)
32 if (ldns_rr_compare(rr
, rrs
->rr
) == 0)
34 if (rrs
) continue; /* "rr" is present, next! */
36 if (ldns_rr_get_type(rr
) == LDNS_RR_TYPE_NS
&& verbosity
!= -1)
37 ldns_rr_print(stdout
, rr
);
38 (void) ldns_dnssec_zone_add_rr(referrals
, rr
);
42 /* Cache all RRs from packet "p" to "referrals" database for lookup later on.
43 * Print the NS RRs that were not already present.
45 static void add_referrals(ldns_dnssec_zone
*referrals
, ldns_pkt
*p
)
47 ldns_rr_list
*l
= ldns_pkt_all_noquestion(p
);
49 add_rr_list_to_referrals(referrals
, l
);
54 /* Equip name-server "res" with the name-servers authoritative for as much
55 * of "name" as possible. Lookup addresses if needed.
57 static bool set_nss_for_name(
58 ldns_resolver
*res
, ldns_dnssec_zone
*referrals
, ldns_rdf
*name
,
59 ldns_resolver
*local_res
, ldns_rr_class c
)
61 ldns_dnssec_rrsets
*nss
= NULL
;
62 ldns_dnssec_rrs
*nss_rrs
;
63 ldns_dnssec_rrsets
*as
= NULL
;
64 ldns_dnssec_rrs
*as_rrs
;
65 ldns_rdf
*lookup
= ldns_rdf_clone(name
);
70 /* nss will become the rrset of as much of "name" as possible */
72 nss
= ldns_dnssec_zone_find_rrset(
73 referrals
, lookup
, LDNS_RR_TYPE_NS
);
75 ldns_rdf_deep_free(lookup
);
78 new_lookup
= ldns_dname_left_chop(lookup
);
79 ldns_rdf_deep_free(lookup
);
82 error("No referrals for name found");
87 /* remove the old nameserver from the resolver */
88 while ((addr
= ldns_resolver_pop_nameserver(res
)))
89 ldns_rdf_deep_free(addr
);
91 /* Find and add the address records for the rrset as name-servers */
92 for (nss_rrs
= nss
->rrs
; nss_rrs
; nss_rrs
= nss_rrs
->next
) {
94 if ((as
= ldns_dnssec_zone_find_rrset(
95 referrals
, ldns_rr_rdf(nss_rrs
->rr
, 0), LDNS_RR_TYPE_A
)))
96 for (as_rrs
= as
->rrs
; as_rrs
; as_rrs
= as_rrs
->next
)
97 (void) ldns_resolver_push_nameserver(
98 res
, ldns_rr_rdf(as_rrs
->rr
, 0));
100 if ((as
= ldns_dnssec_zone_find_rrset(
101 referrals
, ldns_rr_rdf(nss_rrs
->rr
, 0), LDNS_RR_TYPE_AAAA
)))
102 for (as_rrs
= as
->rrs
; as_rrs
; as_rrs
= as_rrs
->next
)
103 (void) ldns_resolver_push_nameserver(
104 res
, ldns_rr_rdf(as_rrs
->rr
, 0));
106 /* Is our resolver equipped with name-servers? Good! We're done */
107 if (ldns_resolver_nameserver_count(res
) > 0)
110 /* Lookup addresses with local resolver add add to "referrals" database */
111 addrs
= ldns_rr_list_new();
112 for (nss_rrs
= nss
->rrs
; nss_rrs
; nss_rrs
= nss_rrs
->next
) {
113 ldns_rr_list
*addrs_by_name
=
114 ldns_get_rr_list_addr_by_name(
115 local_res
, ldns_rr_rdf(nss_rrs
->rr
, 0), c
, 0);
116 ldns_rr_list_cat(addrs
, addrs_by_name
);
117 ldns_rr_list_free(addrs_by_name
);
120 if (ldns_rr_list_rr_count(addrs
) == 0)
121 error("Could not find the nameserver ip addr; abort");
123 else if (ldns_resolver_push_nameserver_rr_list(res
, addrs
) !=
126 error("Error adding new nameservers");
128 ldns_rr_list_deep_free(addrs
);
131 add_rr_list_to_referrals(referrals
, addrs
);
132 ldns_rr_list_deep_free(addrs
);
137 * trace down from the root to name
140 /* same naive method as in drill0.9
141 * We resolve _ALL_ the names, which is of course not needed.
142 * We _do_ use the local resolver to do that, so it still is
143 * fast, but it can be made to run much faster.
146 do_trace(ldns_resolver
*local_res
, ldns_rdf
*name
, ldns_rr_type t
,
150 static uint8_t zero
[1] = { 0 };
151 static const ldns_rdf root_dname
= { 1, LDNS_RDF_TYPE_DNAME
, &zero
};
153 ldns_resolver
*res
= NULL
;
155 ldns_rr_list
*final_answer
;
156 ldns_rr_list
*new_nss
;
157 ldns_rr_list
*cname
= NULL
;
158 ldns_rr_list
*answers
= NULL
;
161 ldns_dnssec_zone
* referrals
= NULL
;
166 res
= ldns_resolver_new();
169 error("Memory allocation failed");
173 /* transfer some properties of local_res to res,
174 * because they were given on the command line */
175 ldns_resolver_set_ip6(res
,
176 ldns_resolver_ip6(local_res
));
177 ldns_resolver_set_port(res
,
178 ldns_resolver_port(local_res
));
179 ldns_resolver_set_debug(res
,
180 ldns_resolver_debug(local_res
));
181 ldns_resolver_set_dnssec(res
,
182 ldns_resolver_dnssec(local_res
));
183 ldns_resolver_set_fail(res
,
184 ldns_resolver_fail(local_res
));
185 ldns_resolver_set_usevc(res
,
186 ldns_resolver_usevc(local_res
));
187 ldns_resolver_set_random(res
,
188 ldns_resolver_random(local_res
));
189 ldns_resolver_set_source(res
,
190 ldns_resolver_source(local_res
));
191 ldns_resolver_set_recursive(res
, false);
193 /* setup the root nameserver in the new resolver */
194 status
= ldns_resolver_push_nameserver_rr_list(res
, global_dns_root
);
195 if (status
!= LDNS_STATUS_OK
) {
196 fprintf(stderr
, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status
));
197 ldns_rr_list_print(stdout
, global_dns_root
);
201 /* this must be a real query to local_res */
202 status
= ldns_resolver_send(&p
, res
, &root_dname
, LDNS_RR_TYPE_NS
, c
, 0);
203 /* p can still be NULL */
205 if (ldns_pkt_empty(p
)) {
206 warning("No root server information received");
209 if (status
== LDNS_STATUS_OK
) {
210 if (!ldns_pkt_empty(p
)) {
211 drill_pkt_print(stdout
, local_res
, p
);
213 referrals
= ldns_dnssec_zone_new();
214 add_referrals(referrals
, p
);
216 error("cannot use local resolver");
219 if (! set_nss_for_name(res
, referrals
, name
, local_res
, c
)) {
224 status
= ldns_resolver_send(&p
, res
, name
, t
, c
, 0);
225 while(status
== LDNS_STATUS_OK
&&
226 ldns_pkt_reply_type(p
) == LDNS_PACKET_REFERRAL
) {
229 /* some error occurred -- bail out */
232 add_referrals(referrals
, p
);
234 /* checks itself for verbosity */
235 drill_pkt_print_footer(stdout
, local_res
, p
);
237 if (! set_nss_for_name(res
, referrals
, name
, local_res
, c
)) {
240 if (loop_count
++ > 20) {
241 /* unlikely that we are doing anything useful */
242 error("Looks like we are looping");
247 status
= ldns_resolver_send(&p
, res
, name
, t
, c
, 0);
249 /* Exit trace on error */
250 if (status
!= LDNS_STATUS_OK
)
253 /* An answer might be the desired answer (and no referral) */
254 if (ldns_pkt_reply_type(p
) != LDNS_PACKET_ANSWER
)
257 /* Exit trace when the requested type is found */
258 answers
= ldns_pkt_rr_list_by_type(p
, t
, LDNS_SECTION_ANSWER
);
259 if (answers
&& ldns_rr_list_rr_count(answers
) > 0) {
260 ldns_rr_list_free(answers
);
264 ldns_rr_list_free(answers
);
267 /* Get the CNAMEs from the answer */
268 cname
= ldns_pkt_rr_list_by_type(
269 p
, LDNS_RR_TYPE_CNAME
, LDNS_SECTION_ANSWER
);
271 /* No CNAME either: exit trace */
272 if (ldns_rr_list_rr_count(cname
) == 0)
275 /* Print CNAME referral */
276 ldns_rr_list_print(stdout
, cname
);
278 /* restart with the CNAME */
279 name
= ldns_rr_rdf(ldns_rr_list_rr(cname
, 0), 0);
280 ldns_rr_list_free(cname
);
283 /* remove the old nameserver from the resolver */
284 while((addr
= ldns_resolver_pop_nameserver(res
)))
285 ldns_rdf_deep_free(addr
);
287 /* Restart trace from the root up */
288 (void) ldns_resolver_push_nameserver_rr_list(
289 res
, global_dns_root
);
293 status
= ldns_resolver_send(&p
, res
, name
, t
, c
, 0);
298 (void) ldns_resolver_send(&p
, res
, name
, t
, c
, 0);
302 new_nss
= ldns_pkt_authority(p
);
303 final_answer
= ldns_pkt_answer(p
);
305 if (verbosity
!= -1) {
306 ldns_rr_list_print(stdout
, final_answer
);
307 ldns_rr_list_print(stdout
, new_nss
);
310 drill_pkt_print_footer(stdout
, local_res
, p
);
313 while((addr
= ldns_resolver_pop_nameserver(res
)))
314 ldns_rdf_deep_free(addr
);
315 ldns_resolver_free(res
);
318 ldns_dnssec_zone_deep_free(referrals
);
325 * Chase the given rr to a known and trusted key
329 * the last argument prev_key_list, if not null, and type == DS, then the ds
330 * rr list we have must all be a ds for the keys in this list
334 do_chase(ldns_resolver
*res
,
338 ldns_rr_list
*trusted_keys
,
341 ldns_rr_list
* ATTR_UNUSED(prev_key_list
))
343 ldns_rr_list
*rrset
= NULL
;
345 ldns_rr
*orig_rr
= NULL
;
354 ldns_status tree_result
;
355 ldns_dnssec_data_chain
*chain
;
356 ldns_dnssec_trust_tree
*tree
;
358 const ldns_rr_descriptor
*descriptor
;
359 descriptor
= ldns_rr_descript(type
);
361 ldns_dname2canonical(name
);
363 pkt
= ldns_pkt_clone(pkt_o
);
365 mesg("No name to chase");
367 return LDNS_STATUS_EMPTY_LABEL
;
369 if (verbosity
!= -1) {
370 printf(";; Chasing: ");
371 ldns_rdf_print(stdout
, name
);
372 if (descriptor
&& descriptor
->_name
) {
373 printf(" %s\n", descriptor
->_name
);
375 printf(" type %d\n", type
);
379 if (!trusted_keys
|| ldns_rr_list_rr_count(trusted_keys
) < 1) {
380 warning("No trusted keys specified");
384 rrset
= ldns_pkt_rr_list_by_name_and_type(pkt
,
390 /* nothing in answer, try authority */
391 rrset
= ldns_pkt_rr_list_by_name_and_type(pkt
,
394 LDNS_SECTION_AUTHORITY
397 /* answer might be a cname, chase that first, then chase
398 cname target? (TODO) */
400 rrset
= ldns_pkt_rr_list_by_name_and_type(pkt
,
406 /* nothing in answer, try authority */
407 rrset
= ldns_pkt_rr_list_by_name_and_type(pkt
,
410 LDNS_SECTION_AUTHORITY
416 if (verbosity
>= 0) {
417 fprintf(stderr
, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR
));
418 fprintf(stderr
, "\n");
420 return LDNS_STATUS_MEM_ERR
;
424 /* not found in original packet, try again */
427 pkt
= ldns_resolver_query(res
, name
, type
, c
, qflags
);
430 if (verbosity
>= 0) {
431 fprintf(stderr
, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR
));
432 fprintf(stderr
, "\n");
434 return LDNS_STATUS_NETWORK_ERR
;
436 if (verbosity
>= 5) {
437 ldns_pkt_print(stdout
, pkt
);
440 rrset
= ldns_pkt_rr_list_by_name_and_type(pkt
,
447 orig_rr
= ldns_rr_new();
449 /* if the answer had no answer section, we need to construct our own rr (for instance if
450 * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */
451 if (ldns_pkt_ancount(pkt
) < 1) {
452 ldns_rr_set_type(orig_rr
, type
);
453 ldns_rr_set_owner(orig_rr
, ldns_rdf_clone(name
));
455 chain
= ldns_dnssec_build_data_chain(res
, qflags
, rrset
, pkt
, ldns_rr_clone(orig_rr
));
457 /* chase the first answer */
458 chain
= ldns_dnssec_build_data_chain(res
, qflags
, rrset
, pkt
, NULL
);
461 if (verbosity
>= 4) {
462 printf("\n\nDNSSEC Data Chain:\n");
463 ldns_dnssec_data_chain_print(stdout
, chain
);
466 result
= LDNS_STATUS_OK
;
468 tree
= ldns_dnssec_derive_trust_tree(chain
, NULL
);
470 if (verbosity
>= 2) {
471 printf("\n\nDNSSEC Trust tree:\n");
472 ldns_dnssec_trust_tree_print(stdout
, tree
, 0, true);
475 if (ldns_rr_list_rr_count(trusted_keys
) > 0) {
476 tree_result
= ldns_dnssec_trust_tree_contains_keys(tree
, trusted_keys
);
478 if (tree_result
== LDNS_STATUS_DNSSEC_EXISTENCE_DENIED
) {
479 if (verbosity
>= 1) {
480 printf("Existence denied or verifiably insecure\n");
482 result
= LDNS_STATUS_OK
;
483 } else if (tree_result
!= LDNS_STATUS_OK
) {
484 if (verbosity
>= 1) {
485 printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result
));
487 result
= tree_result
;
491 if (verbosity
>= 0) {
492 printf("You have not provided any trusted keys.\n");
496 ldns_rr_free(orig_rr
);
497 ldns_dnssec_trust_tree_free(tree
);
498 ldns_dnssec_data_chain_deep_free(chain
);
500 ldns_rr_list_deep_free(rrset
);
502 /* ldns_rr_free(orig_rr);*/
506 #endif /* HAVE_SSL */