xref: /dragonfly/contrib/ldns/drill/chasetrace.c (revision ee791feb)
1825eb42bSJan Lentfer /*
2825eb42bSJan Lentfer  * chasetrace.c
3825eb42bSJan Lentfer  * Where all the hard work concerning chasing
4825eb42bSJan Lentfer  * and tracing is done
5825eb42bSJan Lentfer  * (c) 2005, 2006 NLnet Labs
6825eb42bSJan Lentfer  *
7825eb42bSJan Lentfer  * See the file LICENSE for the license
8825eb42bSJan Lentfer  *
9825eb42bSJan Lentfer  */
10825eb42bSJan Lentfer 
11825eb42bSJan Lentfer #include "drill.h"
12825eb42bSJan Lentfer #include <ldns/ldns.h>
13825eb42bSJan Lentfer 
145340022aSzrj /* Cache all RRs from rr_list "rr_list" to "referrals" database for lookup
155340022aSzrj  * later on.  Print the NS RRs that were not already present.
165340022aSzrj  */
add_rr_list_to_referrals(ldns_dnssec_zone * referrals,ldns_rr_list * rr_list)175340022aSzrj static void add_rr_list_to_referrals(
185340022aSzrj     ldns_dnssec_zone *referrals, ldns_rr_list *rr_list)
195340022aSzrj {
205340022aSzrj 	size_t i;
215340022aSzrj 	ldns_rr *rr;
225340022aSzrj 	ldns_dnssec_rrsets *rrset;
235340022aSzrj 	ldns_dnssec_rrs *rrs;
245340022aSzrj 
255340022aSzrj 	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
265340022aSzrj 		rr = ldns_rr_list_rr(rr_list, i);
275340022aSzrj 		/* Check if a RR equal to "rr" is present in "referrals" */
285340022aSzrj 		rrset = ldns_dnssec_zone_find_rrset(
295340022aSzrj 		    referrals, ldns_rr_owner(rr), ldns_rr_get_type(rr));
305340022aSzrj 		if (rrset) {
315340022aSzrj 			for (rrs = rrset->rrs; rrs; rrs = rrs->next)
325340022aSzrj 				if (ldns_rr_compare(rr, rrs->rr) == 0)
335340022aSzrj 					break;
345340022aSzrj 			if (rrs) continue; /* "rr" is present, next! */
355340022aSzrj 		}
365340022aSzrj 		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS && verbosity != -1)
375340022aSzrj 			ldns_rr_print(stdout, rr);
385340022aSzrj 		(void) ldns_dnssec_zone_add_rr(referrals, rr);
395340022aSzrj 	}
405340022aSzrj }
415340022aSzrj 
425340022aSzrj /* Cache all RRs from packet "p" to "referrals" database for lookup later on.
435340022aSzrj  * Print the NS RRs that were not already present.
445340022aSzrj  */
add_referrals(ldns_dnssec_zone * referrals,ldns_pkt * p)455340022aSzrj static void add_referrals(ldns_dnssec_zone *referrals, ldns_pkt *p)
465340022aSzrj {
475340022aSzrj 	ldns_rr_list *l = ldns_pkt_all_noquestion(p);
485340022aSzrj 	if (l) {
495340022aSzrj 		add_rr_list_to_referrals(referrals, l);
505340022aSzrj 		ldns_rr_list_free(l);
515340022aSzrj 	}
525340022aSzrj }
535340022aSzrj 
545340022aSzrj /* Equip name-server "res" with the name-servers authoritative for as much
555340022aSzrj  * of "name" as possible.  Lookup addresses if needed.
565340022aSzrj  */
set_nss_for_name(ldns_resolver * res,ldns_dnssec_zone * referrals,ldns_rdf * name,ldns_resolver * local_res,ldns_rr_class c)575340022aSzrj static bool set_nss_for_name(
585340022aSzrj     ldns_resolver *res, ldns_dnssec_zone *referrals, ldns_rdf *name,
595340022aSzrj     ldns_resolver *local_res, ldns_rr_class c)
605340022aSzrj {
615340022aSzrj 	ldns_dnssec_rrsets *nss = NULL;
625340022aSzrj 	ldns_dnssec_rrs *nss_rrs;
635340022aSzrj 	ldns_dnssec_rrsets *as = NULL;
645340022aSzrj 	ldns_dnssec_rrs *as_rrs;
655340022aSzrj 	ldns_rdf *lookup = ldns_rdf_clone(name);
665340022aSzrj 	ldns_rdf *new_lookup;
675340022aSzrj 	ldns_rdf *addr;
685340022aSzrj 	ldns_rr_list *addrs;
695340022aSzrj 
705340022aSzrj 	/* nss will become the rrset of as much of "name" as possible */
715340022aSzrj 	for (;;) {
725340022aSzrj 		nss = ldns_dnssec_zone_find_rrset(
735340022aSzrj 		    referrals, lookup, LDNS_RR_TYPE_NS);
745340022aSzrj 		if (nss != NULL) {
755340022aSzrj 			ldns_rdf_deep_free(lookup);
765340022aSzrj 			break;
775340022aSzrj 		}
785340022aSzrj 		new_lookup = ldns_dname_left_chop(lookup);
795340022aSzrj 		ldns_rdf_deep_free(lookup);
805340022aSzrj 		lookup = new_lookup;
815340022aSzrj 		if (!lookup) {
825340022aSzrj 			error("No referrals for name found");
835340022aSzrj 			return false;
845340022aSzrj 		}
855340022aSzrj 	}
865340022aSzrj 
875340022aSzrj 	/* remove the old nameserver from the resolver */
885340022aSzrj 	while ((addr = ldns_resolver_pop_nameserver(res)))
895340022aSzrj 		ldns_rdf_deep_free(addr);
905340022aSzrj 
915340022aSzrj 	/* Find and add the address records for the rrset as name-servers */
925340022aSzrj 	for (nss_rrs = nss->rrs; nss_rrs; nss_rrs = nss_rrs->next) {
935340022aSzrj 
945340022aSzrj 		if ((as = ldns_dnssec_zone_find_rrset(
955340022aSzrj 		    referrals, ldns_rr_rdf(nss_rrs->rr, 0), LDNS_RR_TYPE_A)))
965340022aSzrj 			for (as_rrs = as->rrs; as_rrs; as_rrs = as_rrs->next)
975340022aSzrj 				(void) ldns_resolver_push_nameserver(
985340022aSzrj 				    res, ldns_rr_rdf(as_rrs->rr, 0));
995340022aSzrj 
1005340022aSzrj 		if ((as = ldns_dnssec_zone_find_rrset(
1015340022aSzrj 		    referrals, ldns_rr_rdf(nss_rrs->rr, 0), LDNS_RR_TYPE_AAAA)))
1025340022aSzrj 			for (as_rrs = as->rrs; as_rrs; as_rrs = as_rrs->next)
1035340022aSzrj 				(void) ldns_resolver_push_nameserver(
1045340022aSzrj 				    res, ldns_rr_rdf(as_rrs->rr, 0));
1055340022aSzrj 	}
1065340022aSzrj 	/* Is our resolver equipped with name-servers? Good! We're done */
1075340022aSzrj 	if (ldns_resolver_nameserver_count(res) > 0)
1085340022aSzrj 		return true;
1095340022aSzrj 
1105340022aSzrj 	/* Lookup addresses with local resolver add add to "referrals" database */
1115340022aSzrj 	addrs = ldns_rr_list_new();
1125340022aSzrj 	for (nss_rrs = nss->rrs; nss_rrs; nss_rrs = nss_rrs->next) {
1135340022aSzrj 		ldns_rr_list *addrs_by_name =
1145340022aSzrj 		    ldns_get_rr_list_addr_by_name(
1155340022aSzrj 			local_res, ldns_rr_rdf(nss_rrs->rr, 0), c, 0);
1165340022aSzrj 		ldns_rr_list_cat(addrs, addrs_by_name);
1175340022aSzrj 		ldns_rr_list_free(addrs_by_name);
1185340022aSzrj 	}
1195340022aSzrj 
1205340022aSzrj 	if (ldns_rr_list_rr_count(addrs) == 0)
1215340022aSzrj 		error("Could not find the nameserver ip addr; abort");
1225340022aSzrj 
1235340022aSzrj 	else if (ldns_resolver_push_nameserver_rr_list(res, addrs) !=
1245340022aSzrj 	    LDNS_STATUS_OK)
1255340022aSzrj 
1265340022aSzrj 		error("Error adding new nameservers");
1275340022aSzrj 	else {
1285340022aSzrj 		ldns_rr_list_deep_free(addrs);
1295340022aSzrj 		return true;
1305340022aSzrj 	}
1315340022aSzrj 	add_rr_list_to_referrals(referrals, addrs);
1325340022aSzrj 	ldns_rr_list_deep_free(addrs);
1335340022aSzrj 	return false;
1345340022aSzrj }
1355340022aSzrj 
136825eb42bSJan Lentfer /**
137825eb42bSJan Lentfer  * trace down from the root to name
138825eb42bSJan Lentfer  */
139825eb42bSJan Lentfer 
140825eb42bSJan Lentfer /* same naive method as in drill0.9
1415340022aSzrj  * We resolve _ALL_ the names, which is of course not needed.
142825eb42bSJan Lentfer  * We _do_ use the local resolver to do that, so it still is
1435340022aSzrj  * fast, but it can be made to run much faster.
144825eb42bSJan Lentfer  */
1455340022aSzrj void
do_trace(ldns_resolver * local_res,ldns_rdf * name,ldns_rr_type t,ldns_rr_class c)146825eb42bSJan Lentfer do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
147825eb42bSJan Lentfer 		ldns_rr_class c)
148825eb42bSJan Lentfer {
1495340022aSzrj 
1505340022aSzrj 	static uint8_t zero[1] = { 0 };
1515340022aSzrj 	static const ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, &zero };
1525340022aSzrj 
1535340022aSzrj 	ldns_resolver *res = NULL;
1545340022aSzrj 	ldns_pkt *p = NULL;
155825eb42bSJan Lentfer 	ldns_rr_list *final_answer;
156825eb42bSJan Lentfer 	ldns_rr_list *new_nss;
1575340022aSzrj 	ldns_rr_list *cname = NULL;
1585340022aSzrj 	ldns_rr_list *answers = NULL;
159825eb42bSJan Lentfer 	uint16_t loop_count;
160825eb42bSJan Lentfer 	ldns_status status;
1615340022aSzrj 	ldns_dnssec_zone* referrals = NULL;
1625340022aSzrj 	ldns_rdf *addr;
163825eb42bSJan Lentfer 
164825eb42bSJan Lentfer 	loop_count = 0;
165825eb42bSJan Lentfer 	final_answer = NULL;
166825eb42bSJan Lentfer 	res = ldns_resolver_new();
167825eb42bSJan Lentfer 
168d1b2b5caSJohn Marino 	if (!res) {
169825eb42bSJan Lentfer                 error("Memory allocation failed");
1705340022aSzrj 		goto cleanup;
171825eb42bSJan Lentfer         }
172825eb42bSJan Lentfer 
173825eb42bSJan Lentfer 	/* transfer some properties of local_res to res,
174825eb42bSJan Lentfer 	 * because they were given on the command line */
175825eb42bSJan Lentfer 	ldns_resolver_set_ip6(res,
176825eb42bSJan Lentfer 			ldns_resolver_ip6(local_res));
177825eb42bSJan Lentfer 	ldns_resolver_set_port(res,
178825eb42bSJan Lentfer 			ldns_resolver_port(local_res));
179825eb42bSJan Lentfer 	ldns_resolver_set_debug(res,
180825eb42bSJan Lentfer 			ldns_resolver_debug(local_res));
181825eb42bSJan Lentfer 	ldns_resolver_set_dnssec(res,
182825eb42bSJan Lentfer 			ldns_resolver_dnssec(local_res));
183825eb42bSJan Lentfer 	ldns_resolver_set_fail(res,
184825eb42bSJan Lentfer 			ldns_resolver_fail(local_res));
185825eb42bSJan Lentfer 	ldns_resolver_set_usevc(res,
186825eb42bSJan Lentfer 			ldns_resolver_usevc(local_res));
187825eb42bSJan Lentfer 	ldns_resolver_set_random(res,
188825eb42bSJan Lentfer 			ldns_resolver_random(local_res));
1895340022aSzrj 	ldns_resolver_set_source(res,
1905340022aSzrj 			ldns_resolver_source(local_res));
191825eb42bSJan Lentfer 	ldns_resolver_set_recursive(res, false);
192825eb42bSJan Lentfer 
193825eb42bSJan Lentfer 	/* setup the root nameserver in the new resolver */
194825eb42bSJan Lentfer 	status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
195825eb42bSJan Lentfer 	if (status != LDNS_STATUS_OK) {
196825eb42bSJan Lentfer 		fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
197825eb42bSJan Lentfer 		ldns_rr_list_print(stdout, global_dns_root);
1985340022aSzrj 		goto cleanup;
199825eb42bSJan Lentfer 	}
200825eb42bSJan Lentfer 
201825eb42bSJan Lentfer 	/* this must be a real query to local_res */
2025340022aSzrj 	status = ldns_resolver_send(&p, res, &root_dname, LDNS_RR_TYPE_NS, c, 0);
203825eb42bSJan Lentfer 	/* p can still be NULL */
204825eb42bSJan Lentfer 
205825eb42bSJan Lentfer 	if (ldns_pkt_empty(p)) {
206825eb42bSJan Lentfer 		warning("No root server information received");
207825eb42bSJan Lentfer 	}
208825eb42bSJan Lentfer 
209825eb42bSJan Lentfer 	if (status == LDNS_STATUS_OK) {
210825eb42bSJan Lentfer 		if (!ldns_pkt_empty(p)) {
211825eb42bSJan Lentfer 			drill_pkt_print(stdout, local_res, p);
212825eb42bSJan Lentfer 		}
2135340022aSzrj 		referrals = ldns_dnssec_zone_new();
2145340022aSzrj 		add_referrals(referrals, p);
215825eb42bSJan Lentfer 	} else {
216825eb42bSJan Lentfer 		error("cannot use local resolver");
2175340022aSzrj 		goto cleanup;
218825eb42bSJan Lentfer 	}
2195340022aSzrj 	if (! set_nss_for_name(res, referrals, name, local_res, c)) {
2205340022aSzrj 		goto cleanup;
2215340022aSzrj 	}
2225340022aSzrj 	ldns_pkt_free(p);
2235340022aSzrj 	p = NULL;
224825eb42bSJan Lentfer 	status = ldns_resolver_send(&p, res, name, t, c, 0);
225825eb42bSJan Lentfer 	while(status == LDNS_STATUS_OK &&
226825eb42bSJan Lentfer 	      ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
227825eb42bSJan Lentfer 
228825eb42bSJan Lentfer 		if (!p) {
2295340022aSzrj 			/* some error occurred -- bail out */
2305340022aSzrj 			goto cleanup;
231825eb42bSJan Lentfer 		}
2325340022aSzrj 		add_referrals(referrals, p);
233825eb42bSJan Lentfer 
234825eb42bSJan Lentfer 		/* checks itself for verbosity */
235825eb42bSJan Lentfer 		drill_pkt_print_footer(stdout, local_res, p);
236825eb42bSJan Lentfer 
2375340022aSzrj 		if (! set_nss_for_name(res, referrals, name, local_res, c)) {
2385340022aSzrj 			goto cleanup;
2395340022aSzrj 		}
2405340022aSzrj 		if (loop_count++ > 20) {
2415340022aSzrj 			/* unlikely that we are doing anything useful */
2425340022aSzrj 			error("Looks like we are looping");
2435340022aSzrj 			goto cleanup;
2445340022aSzrj 		}
2455340022aSzrj 		ldns_pkt_free(p);
2465340022aSzrj 		p = NULL;
2475340022aSzrj 		status = ldns_resolver_send(&p, res, name, t, c, 0);
248825eb42bSJan Lentfer 
2495340022aSzrj 		/* Exit trace on error */
2505340022aSzrj 		if (status != LDNS_STATUS_OK)
2515340022aSzrj 			break;
252825eb42bSJan Lentfer 
2535340022aSzrj 		/* An answer might be the desired answer (and no referral) */
2545340022aSzrj 		if (ldns_pkt_reply_type(p) != LDNS_PACKET_ANSWER)
2555340022aSzrj 			continue;
2565340022aSzrj 
2575340022aSzrj 		/* Exit trace when the requested type is found */
2585340022aSzrj 		answers = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANSWER);
2595340022aSzrj 		if (answers && ldns_rr_list_rr_count(answers) > 0) {
2605340022aSzrj 			ldns_rr_list_free(answers);
2615340022aSzrj 			answers = NULL;
262825eb42bSJan Lentfer 			break;
263825eb42bSJan Lentfer 		}
2645340022aSzrj 		ldns_rr_list_free(answers);
2655340022aSzrj 		answers = NULL;
266825eb42bSJan Lentfer 
2675340022aSzrj 		/* Get the CNAMEs from the answer */
2685340022aSzrj 		cname = ldns_pkt_rr_list_by_type(
2695340022aSzrj 		    p, LDNS_RR_TYPE_CNAME, LDNS_SECTION_ANSWER);
270825eb42bSJan Lentfer 
2715340022aSzrj 		/* No CNAME either: exit trace */
2725340022aSzrj 		if (ldns_rr_list_rr_count(cname) == 0)
2735340022aSzrj 			break;
274825eb42bSJan Lentfer 
2755340022aSzrj 		/* Print CNAME referral */
2765340022aSzrj 		ldns_rr_list_print(stdout, cname);
277825eb42bSJan Lentfer 
2785340022aSzrj 		/* restart with the CNAME */
2795340022aSzrj 		name = ldns_rr_rdf(ldns_rr_list_rr(cname, 0), 0);
2805340022aSzrj 		ldns_rr_list_free(cname);
2815340022aSzrj 		cname = NULL;
282825eb42bSJan Lentfer 
2835340022aSzrj 		/* remove the old nameserver from the resolver */
2845340022aSzrj 		while((addr = ldns_resolver_pop_nameserver(res)))
2855340022aSzrj 			ldns_rdf_deep_free(addr);
2865340022aSzrj 
2875340022aSzrj 		/* Restart trace from the root up */
2885340022aSzrj 		(void) ldns_resolver_push_nameserver_rr_list(
2895340022aSzrj 		    res, global_dns_root);
2905340022aSzrj 
2915340022aSzrj 		ldns_pkt_free(p);
2925340022aSzrj 		p = NULL;
293825eb42bSJan Lentfer 		status = ldns_resolver_send(&p, res, name, t, c, 0);
294825eb42bSJan Lentfer 	}
295825eb42bSJan Lentfer 
2965340022aSzrj 	ldns_pkt_free(p);
2975340022aSzrj 	p = NULL;
298819dec71SDaniel Fojt 	(void) ldns_resolver_send(&p, res, name, t, c, 0);
299825eb42bSJan Lentfer 	if (!p) {
3005340022aSzrj 		goto cleanup;
301825eb42bSJan Lentfer 	}
302825eb42bSJan Lentfer 	new_nss = ldns_pkt_authority(p);
303825eb42bSJan Lentfer 	final_answer = ldns_pkt_answer(p);
304825eb42bSJan Lentfer 
305825eb42bSJan Lentfer 	if (verbosity != -1) {
306825eb42bSJan Lentfer 		ldns_rr_list_print(stdout, final_answer);
307825eb42bSJan Lentfer 		ldns_rr_list_print(stdout, new_nss);
308825eb42bSJan Lentfer 
309825eb42bSJan Lentfer 	}
310825eb42bSJan Lentfer 	drill_pkt_print_footer(stdout, local_res, p);
3115340022aSzrj cleanup:
3125340022aSzrj 	if (res) {
3135340022aSzrj 		while((addr = ldns_resolver_pop_nameserver(res)))
3145340022aSzrj 			ldns_rdf_deep_free(addr);
3155340022aSzrj 		ldns_resolver_free(res);
3165340022aSzrj 	}
3175340022aSzrj 	if (referrals)
3185340022aSzrj 		ldns_dnssec_zone_deep_free(referrals);
3195340022aSzrj 	if (p)
320825eb42bSJan Lentfer 		ldns_pkt_free(p);
321825eb42bSJan Lentfer }
322825eb42bSJan Lentfer 
323825eb42bSJan Lentfer 
324825eb42bSJan Lentfer /**
325825eb42bSJan Lentfer  * Chase the given rr to a known and trusted key
326825eb42bSJan Lentfer  *
327825eb42bSJan Lentfer  * Based on drill 0.9
328825eb42bSJan Lentfer  *
329825eb42bSJan Lentfer  * the last argument prev_key_list, if not null, and type == DS, then the ds
330825eb42bSJan Lentfer  * rr list we have must all be a ds for the keys in this list
331825eb42bSJan Lentfer  */
332825eb42bSJan Lentfer #ifdef HAVE_SSL
333825eb42bSJan Lentfer ldns_status
do_chase(ldns_resolver * res,ldns_rdf * name,ldns_rr_type type,ldns_rr_class c,ldns_rr_list * trusted_keys,ldns_pkt * pkt_o,uint16_t qflags,ldns_rr_list * ATTR_UNUSED (prev_key_list))334825eb42bSJan Lentfer do_chase(ldns_resolver *res,
335825eb42bSJan Lentfer 	    ldns_rdf *name,
336825eb42bSJan Lentfer 	    ldns_rr_type type,
337825eb42bSJan Lentfer 	    ldns_rr_class c,
338825eb42bSJan Lentfer 	    ldns_rr_list *trusted_keys,
339825eb42bSJan Lentfer 	    ldns_pkt *pkt_o,
340825eb42bSJan Lentfer 	    uint16_t qflags,
3415340022aSzrj 	    ldns_rr_list * ATTR_UNUSED(prev_key_list))
342825eb42bSJan Lentfer {
343825eb42bSJan Lentfer 	ldns_rr_list *rrset = NULL;
344825eb42bSJan Lentfer 	ldns_status result;
345825eb42bSJan Lentfer 	ldns_rr *orig_rr = NULL;
346825eb42bSJan Lentfer 
347825eb42bSJan Lentfer /*
348825eb42bSJan Lentfer 	ldns_rr_list *sigs;
349825eb42bSJan Lentfer 	ldns_rr *cur_sig;
350825eb42bSJan Lentfer 	uint16_t sig_i;
351825eb42bSJan Lentfer 	ldns_rr_list *keys;
352825eb42bSJan Lentfer */
353825eb42bSJan Lentfer 	ldns_pkt *pkt;
354825eb42bSJan Lentfer 	ldns_status tree_result;
355825eb42bSJan Lentfer 	ldns_dnssec_data_chain *chain;
356825eb42bSJan Lentfer 	ldns_dnssec_trust_tree *tree;
357825eb42bSJan Lentfer 
358825eb42bSJan Lentfer 	const ldns_rr_descriptor *descriptor;
359825eb42bSJan Lentfer 	descriptor = ldns_rr_descript(type);
360825eb42bSJan Lentfer 
361825eb42bSJan Lentfer 	ldns_dname2canonical(name);
362825eb42bSJan Lentfer 
363825eb42bSJan Lentfer 	pkt = ldns_pkt_clone(pkt_o);
364825eb42bSJan Lentfer 	if (!name) {
365825eb42bSJan Lentfer 		mesg("No name to chase");
366825eb42bSJan Lentfer 		ldns_pkt_free(pkt);
367825eb42bSJan Lentfer 		return LDNS_STATUS_EMPTY_LABEL;
368825eb42bSJan Lentfer 	}
369825eb42bSJan Lentfer 	if (verbosity != -1) {
370825eb42bSJan Lentfer 		printf(";; Chasing: ");
371825eb42bSJan Lentfer 			ldns_rdf_print(stdout, name);
372825eb42bSJan Lentfer 			if (descriptor && descriptor->_name) {
373825eb42bSJan Lentfer 				printf(" %s\n", descriptor->_name);
374825eb42bSJan Lentfer 			} else {
375825eb42bSJan Lentfer 				printf(" type %d\n", type);
376825eb42bSJan Lentfer 			}
377825eb42bSJan Lentfer 	}
378825eb42bSJan Lentfer 
379825eb42bSJan Lentfer 	if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) {
380825eb42bSJan Lentfer 		warning("No trusted keys specified");
381825eb42bSJan Lentfer 	}
382825eb42bSJan Lentfer 
383825eb42bSJan Lentfer 	if (pkt) {
384825eb42bSJan Lentfer 		rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
385825eb42bSJan Lentfer 				name,
386825eb42bSJan Lentfer 				type,
387825eb42bSJan Lentfer 				LDNS_SECTION_ANSWER
388825eb42bSJan Lentfer 				);
389825eb42bSJan Lentfer 		if (!rrset) {
390825eb42bSJan Lentfer 			/* nothing in answer, try authority */
391825eb42bSJan Lentfer 			rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
392825eb42bSJan Lentfer 					name,
393825eb42bSJan Lentfer 					type,
394825eb42bSJan Lentfer 					LDNS_SECTION_AUTHORITY
395825eb42bSJan Lentfer 					);
396825eb42bSJan Lentfer 		}
397825eb42bSJan Lentfer 		/* answer might be a cname, chase that first, then chase
398825eb42bSJan Lentfer 		   cname target? (TODO) */
399825eb42bSJan Lentfer 		if (!rrset) {
400825eb42bSJan Lentfer 			rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
401825eb42bSJan Lentfer 					name,
402825eb42bSJan Lentfer 					LDNS_RR_TYPE_CNAME,
403825eb42bSJan Lentfer 					LDNS_SECTION_ANSWER
404825eb42bSJan Lentfer 					);
405825eb42bSJan Lentfer 			if (!rrset) {
406825eb42bSJan Lentfer 				/* nothing in answer, try authority */
407825eb42bSJan Lentfer 				rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
408825eb42bSJan Lentfer 						name,
409825eb42bSJan Lentfer 						LDNS_RR_TYPE_CNAME,
410825eb42bSJan Lentfer 						LDNS_SECTION_AUTHORITY
411825eb42bSJan Lentfer 						);
412825eb42bSJan Lentfer 			}
413825eb42bSJan Lentfer 		}
414825eb42bSJan Lentfer 	} else {
415825eb42bSJan Lentfer 		/* no packet? */
416825eb42bSJan Lentfer 		if (verbosity >= 0) {
417825eb42bSJan Lentfer 			fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
418825eb42bSJan Lentfer 			fprintf(stderr, "\n");
419825eb42bSJan Lentfer 		}
420825eb42bSJan Lentfer 		return LDNS_STATUS_MEM_ERR;
421825eb42bSJan Lentfer 	}
422825eb42bSJan Lentfer 
423825eb42bSJan Lentfer 	if (!rrset) {
424825eb42bSJan Lentfer 		/* not found in original packet, try again */
425825eb42bSJan Lentfer 		ldns_pkt_free(pkt);
426825eb42bSJan Lentfer 		pkt = NULL;
427825eb42bSJan Lentfer 		pkt = ldns_resolver_query(res, name, type, c, qflags);
428825eb42bSJan Lentfer 
429825eb42bSJan Lentfer 		if (!pkt) {
430825eb42bSJan Lentfer 			if (verbosity >= 0) {
431825eb42bSJan Lentfer 				fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR));
432825eb42bSJan Lentfer 				fprintf(stderr, "\n");
433825eb42bSJan Lentfer 			}
434825eb42bSJan Lentfer 			return LDNS_STATUS_NETWORK_ERR;
435825eb42bSJan Lentfer 		}
436825eb42bSJan Lentfer 		if (verbosity >= 5) {
437825eb42bSJan Lentfer 			ldns_pkt_print(stdout, pkt);
438825eb42bSJan Lentfer 		}
439825eb42bSJan Lentfer 
440825eb42bSJan Lentfer 		rrset =	ldns_pkt_rr_list_by_name_and_type(pkt,
441825eb42bSJan Lentfer 				name,
442825eb42bSJan Lentfer 				type,
443825eb42bSJan Lentfer 				LDNS_SECTION_ANSWER
444825eb42bSJan Lentfer 				);
445825eb42bSJan Lentfer 	}
446825eb42bSJan Lentfer 
447825eb42bSJan Lentfer 	orig_rr = ldns_rr_new();
448825eb42bSJan Lentfer 
449825eb42bSJan Lentfer /* if the answer had no answer section, we need to construct our own rr (for instance if
450825eb42bSJan Lentfer  * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */
451825eb42bSJan Lentfer 	if (ldns_pkt_ancount(pkt) < 1) {
452825eb42bSJan Lentfer 		ldns_rr_set_type(orig_rr, type);
453825eb42bSJan Lentfer 		ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name));
454825eb42bSJan Lentfer 
455825eb42bSJan Lentfer 		chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr));
456825eb42bSJan Lentfer 	} else {
457825eb42bSJan Lentfer 		/* chase the first answer */
458825eb42bSJan Lentfer 		chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL);
459825eb42bSJan Lentfer 	}
460825eb42bSJan Lentfer 
461825eb42bSJan Lentfer 	if (verbosity >= 4) {
462825eb42bSJan Lentfer 		printf("\n\nDNSSEC Data Chain:\n");
463825eb42bSJan Lentfer 		ldns_dnssec_data_chain_print(stdout, chain);
464825eb42bSJan Lentfer 	}
465825eb42bSJan Lentfer 
466825eb42bSJan Lentfer 	result = LDNS_STATUS_OK;
467825eb42bSJan Lentfer 
468825eb42bSJan Lentfer 	tree = ldns_dnssec_derive_trust_tree(chain, NULL);
469825eb42bSJan Lentfer 
470825eb42bSJan Lentfer 	if (verbosity >= 2) {
471825eb42bSJan Lentfer 		printf("\n\nDNSSEC Trust tree:\n");
472825eb42bSJan Lentfer 		ldns_dnssec_trust_tree_print(stdout, tree, 0, true);
473825eb42bSJan Lentfer 	}
474825eb42bSJan Lentfer 
475825eb42bSJan Lentfer 	if (ldns_rr_list_rr_count(trusted_keys) > 0) {
476825eb42bSJan Lentfer 		tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys);
477825eb42bSJan Lentfer 
478825eb42bSJan Lentfer 		if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) {
479825eb42bSJan Lentfer 			if (verbosity >= 1) {
480825eb42bSJan Lentfer 				printf("Existence denied or verifiably insecure\n");
481825eb42bSJan Lentfer 			}
482825eb42bSJan Lentfer 			result = LDNS_STATUS_OK;
483825eb42bSJan Lentfer 		} else if (tree_result != LDNS_STATUS_OK) {
484825eb42bSJan Lentfer 			if (verbosity >= 1) {
485825eb42bSJan Lentfer 				printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result));
486825eb42bSJan Lentfer 			}
487825eb42bSJan Lentfer 			result = tree_result;
488825eb42bSJan Lentfer 		}
489825eb42bSJan Lentfer 
490825eb42bSJan Lentfer 	} else {
491825eb42bSJan Lentfer 		if (verbosity >= 0) {
492825eb42bSJan Lentfer 			printf("You have not provided any trusted keys.\n");
493825eb42bSJan Lentfer 		}
494825eb42bSJan Lentfer 	}
495825eb42bSJan Lentfer 
496825eb42bSJan Lentfer 	ldns_rr_free(orig_rr);
497825eb42bSJan Lentfer 	ldns_dnssec_trust_tree_free(tree);
498825eb42bSJan Lentfer 	ldns_dnssec_data_chain_deep_free(chain);
499825eb42bSJan Lentfer 
500825eb42bSJan Lentfer 	ldns_rr_list_deep_free(rrset);
501825eb42bSJan Lentfer 	ldns_pkt_free(pkt);
502825eb42bSJan Lentfer 	/*	ldns_rr_free(orig_rr);*/
503825eb42bSJan Lentfer 
504825eb42bSJan Lentfer 	return result;
505825eb42bSJan Lentfer }
506825eb42bSJan Lentfer #endif /* HAVE_SSL */
507825eb42bSJan Lentfer 
508