kernel - Fix races created by a comedy of circumstansces (3)
[dragonfly.git] / contrib / ldns / drill / chasetrace.c
blob0a37ff3017e6fc557410dbae64b6d954b1de859a
1 /*
2 * chasetrace.c
3 * Where all the hard work concerning chasing
4 * and tracing is done
5 * (c) 2005, 2006 NLnet Labs
7 * See the file LICENSE for the license
9 */
11 #include "drill.h"
12 #include <ldns/ldns.h>
14 /**
15 * trace down from the root to name
18 /* same naive method as in drill0.9
19 * We resolver _ALL_ the names, which is ofcourse not needed
20 * We _do_ use the local resolver to do that, so it still is
21 * fast, but it can be made to run much faster
23 ldns_pkt *
24 do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t,
25 ldns_rr_class c)
27 ldns_resolver *res;
28 ldns_pkt *p;
29 ldns_rr_list *new_nss_a;
30 ldns_rr_list *new_nss_aaaa;
31 ldns_rr_list *final_answer;
32 ldns_rr_list *new_nss;
33 ldns_rr_list *ns_addr;
34 uint16_t loop_count;
35 ldns_rdf *pop;
36 ldns_status status;
37 size_t i;
39 loop_count = 0;
40 new_nss_a = NULL;
41 new_nss_aaaa = NULL;
42 new_nss = NULL;
43 ns_addr = NULL;
44 final_answer = NULL;
45 p = ldns_pkt_new();
46 res = ldns_resolver_new();
48 if (!p) {
49 if (res) {
50 ldns_resolver_free(res);
52 error("Memory allocation failed");
53 return NULL;
55 if (!res) {
56 ldns_pkt_free(p);
57 error("Memory allocation failed");
58 return NULL;
61 /* transfer some properties of local_res to res,
62 * because they were given on the commandline */
63 ldns_resolver_set_ip6(res,
64 ldns_resolver_ip6(local_res));
65 ldns_resolver_set_port(res,
66 ldns_resolver_port(local_res));
67 ldns_resolver_set_debug(res,
68 ldns_resolver_debug(local_res));
69 ldns_resolver_set_dnssec(res,
70 ldns_resolver_dnssec(local_res));
71 ldns_resolver_set_fail(res,
72 ldns_resolver_fail(local_res));
73 ldns_resolver_set_usevc(res,
74 ldns_resolver_usevc(local_res));
75 ldns_resolver_set_random(res,
76 ldns_resolver_random(local_res));
77 ldns_resolver_set_recursive(res, false);
79 /* setup the root nameserver in the new resolver */
80 status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root);
81 if (status != LDNS_STATUS_OK) {
82 fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status));
83 ldns_rr_list_print(stdout, global_dns_root);
84 ldns_resolver_free(res);
85 ldns_pkt_free(p);
86 return NULL;
89 /* this must be a real query to local_res */
90 status = ldns_resolver_send(&p, res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0);
91 /* p can still be NULL */
94 if (ldns_pkt_empty(p)) {
95 warning("No root server information received");
98 if (status == LDNS_STATUS_OK) {
99 if (!ldns_pkt_empty(p)) {
100 drill_pkt_print(stdout, local_res, p);
102 } else {
103 error("cannot use local resolver");
104 return NULL;
107 status = ldns_resolver_send(&p, res, name, t, c, 0);
109 while(status == LDNS_STATUS_OK &&
110 ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) {
112 if (!p) {
113 /* some error occurred, bail out */
114 return NULL;
117 new_nss_a = ldns_pkt_rr_list_by_type(p,
118 LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL);
119 new_nss_aaaa = ldns_pkt_rr_list_by_type(p,
120 LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL);
121 new_nss = ldns_pkt_rr_list_by_type(p,
122 LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY);
124 if (verbosity != -1) {
125 ldns_rr_list_print(stdout, new_nss);
127 /* checks itself for verbosity */
128 drill_pkt_print_footer(stdout, local_res, p);
130 /* remove the old nameserver from the resolver */
131 while(ldns_resolver_pop_nameserver(res)) { /* do it */ }
133 /* also check for new_nss emptyness */
135 if (!new_nss_aaaa && !new_nss_a) {
137 * no nameserver found!!!
138 * try to resolve the names we do got
140 for(i = 0; i < ldns_rr_list_rr_count(new_nss); i++) {
141 /* get the name of the nameserver */
142 pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0);
143 if (!pop) {
144 break;
147 ldns_rr_list_print(stdout, new_nss);
148 ldns_rdf_print(stdout, pop);
149 /* retrieve it's addresses */
150 ns_addr = ldns_rr_list_cat_clone(ns_addr,
151 ldns_get_rr_list_addr_by_name(local_res, pop, c, 0));
154 if (ns_addr) {
155 if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) !=
156 LDNS_STATUS_OK) {
157 error("Error adding new nameservers");
158 ldns_pkt_free(p);
159 return NULL;
161 ldns_rr_list_free(ns_addr);
162 } else {
163 ldns_rr_list_print(stdout, ns_addr);
164 error("Could not find the nameserver ip addr; abort");
165 ldns_pkt_free(p);
166 return NULL;
170 /* add the new ones */
171 if (new_nss_aaaa) {
172 if (ldns_resolver_push_nameserver_rr_list(res, new_nss_aaaa) !=
173 LDNS_STATUS_OK) {
174 error("adding new nameservers");
175 ldns_pkt_free(p);
176 return NULL;
179 if (new_nss_a) {
180 if (ldns_resolver_push_nameserver_rr_list(res, new_nss_a) !=
181 LDNS_STATUS_OK) {
182 error("adding new nameservers");
183 ldns_pkt_free(p);
184 return NULL;
188 if (loop_count++ > 20) {
189 /* unlikely that we are doing something usefull */
190 error("Looks like we are looping");
191 ldns_pkt_free(p);
192 return NULL;
195 status = ldns_resolver_send(&p, res, name, t, c, 0);
196 new_nss_aaaa = NULL;
197 new_nss_a = NULL;
198 ns_addr = NULL;
201 status = ldns_resolver_send(&p, res, name, t, c, 0);
203 if (!p) {
204 return NULL;
207 new_nss = ldns_pkt_authority(p);
208 final_answer = ldns_pkt_answer(p);
210 if (verbosity != -1) {
211 ldns_rr_list_print(stdout, final_answer);
212 ldns_rr_list_print(stdout, new_nss);
215 drill_pkt_print_footer(stdout, local_res, p);
216 ldns_pkt_free(p);
217 return NULL;
222 * Chase the given rr to a known and trusted key
224 * Based on drill 0.9
226 * the last argument prev_key_list, if not null, and type == DS, then the ds
227 * rr list we have must all be a ds for the keys in this list
229 #ifdef HAVE_SSL
230 ldns_status
231 do_chase(ldns_resolver *res,
232 ldns_rdf *name,
233 ldns_rr_type type,
234 ldns_rr_class c,
235 ldns_rr_list *trusted_keys,
236 ldns_pkt *pkt_o,
237 uint16_t qflags,
238 ldns_rr_list * ATTR_UNUSED(prev_key_list),
239 int verbosity)
241 ldns_rr_list *rrset = NULL;
242 ldns_status result;
243 ldns_rr *orig_rr = NULL;
246 ldns_rr_list *sigs;
247 ldns_rr *cur_sig;
248 uint16_t sig_i;
249 ldns_rr_list *keys;
251 ldns_pkt *pkt;
252 ldns_status tree_result;
253 ldns_dnssec_data_chain *chain;
254 ldns_dnssec_trust_tree *tree;
256 const ldns_rr_descriptor *descriptor;
257 descriptor = ldns_rr_descript(type);
259 ldns_dname2canonical(name);
261 pkt = ldns_pkt_clone(pkt_o);
262 if (!name) {
263 mesg("No name to chase");
264 ldns_pkt_free(pkt);
265 return LDNS_STATUS_EMPTY_LABEL;
267 if (verbosity != -1) {
268 printf(";; Chasing: ");
269 ldns_rdf_print(stdout, name);
270 if (descriptor && descriptor->_name) {
271 printf(" %s\n", descriptor->_name);
272 } else {
273 printf(" type %d\n", type);
277 if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) {
278 warning("No trusted keys specified");
281 if (pkt) {
282 rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
283 name,
284 type,
285 LDNS_SECTION_ANSWER
287 if (!rrset) {
288 /* nothing in answer, try authority */
289 rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
290 name,
291 type,
292 LDNS_SECTION_AUTHORITY
295 /* answer might be a cname, chase that first, then chase
296 cname target? (TODO) */
297 if (!rrset) {
298 rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
299 name,
300 LDNS_RR_TYPE_CNAME,
301 LDNS_SECTION_ANSWER
303 if (!rrset) {
304 /* nothing in answer, try authority */
305 rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
306 name,
307 LDNS_RR_TYPE_CNAME,
308 LDNS_SECTION_AUTHORITY
312 } else {
313 /* no packet? */
314 if (verbosity >= 0) {
315 fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR));
316 fprintf(stderr, "\n");
318 return LDNS_STATUS_MEM_ERR;
321 if (!rrset) {
322 /* not found in original packet, try again */
323 ldns_pkt_free(pkt);
324 pkt = NULL;
325 pkt = ldns_resolver_query(res, name, type, c, qflags);
327 if (!pkt) {
328 if (verbosity >= 0) {
329 fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR));
330 fprintf(stderr, "\n");
332 return LDNS_STATUS_NETWORK_ERR;
334 if (verbosity >= 5) {
335 ldns_pkt_print(stdout, pkt);
338 rrset = ldns_pkt_rr_list_by_name_and_type(pkt,
339 name,
340 type,
341 LDNS_SECTION_ANSWER
345 orig_rr = ldns_rr_new();
347 /* if the answer had no answer section, we need to construct our own rr (for instance if
348 * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */
349 if (ldns_pkt_ancount(pkt) < 1) {
350 ldns_rr_set_type(orig_rr, type);
351 ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name));
353 chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr));
354 } else {
355 /* chase the first answer */
356 chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL);
359 if (verbosity >= 4) {
360 printf("\n\nDNSSEC Data Chain:\n");
361 ldns_dnssec_data_chain_print(stdout, chain);
364 result = LDNS_STATUS_OK;
366 tree = ldns_dnssec_derive_trust_tree(chain, NULL);
368 if (verbosity >= 2) {
369 printf("\n\nDNSSEC Trust tree:\n");
370 ldns_dnssec_trust_tree_print(stdout, tree, 0, true);
373 if (ldns_rr_list_rr_count(trusted_keys) > 0) {
374 tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys);
376 if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) {
377 if (verbosity >= 1) {
378 printf("Existence denied or verifiably insecure\n");
380 result = LDNS_STATUS_OK;
381 } else if (tree_result != LDNS_STATUS_OK) {
382 if (verbosity >= 1) {
383 printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result));
385 result = tree_result;
388 } else {
389 if (verbosity >= 0) {
390 printf("You have not provided any trusted keys.\n");
394 ldns_rr_free(orig_rr);
395 ldns_dnssec_trust_tree_free(tree);
396 ldns_dnssec_data_chain_deep_free(chain);
398 ldns_rr_list_deep_free(rrset);
399 ldns_pkt_free(pkt);
400 /* ldns_rr_free(orig_rr);*/
402 return result;
404 #endif /* HAVE_SSL */