xref: /dragonfly/contrib/ldns/drill/drill.c (revision 70344474)
1 /*
2  * drill.c
3  * the main file of drill
4  * (c) 2005-2008 NLnet Labs
5  *
6  * See the file LICENSE for the license
7  *
8  */
9 
10 #include "drill.h"
11 #include <ldns/ldns.h>
12 
13 #ifdef HAVE_SSL
14 #include <openssl/err.h>
15 #endif
16 
17 #define IP6_ARPA_MAX_LEN 65
18 
19 /* query debug, 2 hex dumps */
20 int		verbosity;
21 
22 static void
23 usage(FILE *stream, const char *progname)
24 {
25 	fprintf(stream, "  Usage: %s name [@server] [type] [class]\n", progname);
26 	fprintf(stream, "\t<name>  can be a domain name or an IP address (-x lookups)\n");
27 	fprintf(stream, "\t<type>  defaults to A\n");
28 	fprintf(stream, "\t<class> defaults to IN\n");
29 	fprintf(stream, "\n\targuments may be placed in random order\n");
30 	fprintf(stream, "\n  Options:\n");
31 	fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n");
32 #ifdef HAVE_SSL
33 	fprintf(stream, "\t-T\t\ttrace from the root down to <name>\n");
34 	fprintf(stream, "\t-S\t\tchase signature(s) from <name> to a know key [*]\n");
35 #endif /*HAVE_SSL*/
36 	fprintf(stream, "\t-V <number>\tverbosity (0-5)\n");
37 	fprintf(stream, "\t-Q\t\tquiet mode (overrules -V)\n");
38 	fprintf(stream, "\n");
39 	fprintf(stream, "\t-f file\t\tread packet from file and send it\n");
40 	fprintf(stream, "\t-i file\t\tread packet from file and print it\n");
41 	fprintf(stream, "\t-w file\t\twrite answer packet to file\n");
42 	fprintf(stream, "\t-q file\t\twrite query packet to file\n");
43 	fprintf(stream, "\t-h\t\tshow this help\n");
44 	fprintf(stream, "\t-v\t\tshow version\n");
45 	fprintf(stream, "\n  Query options:\n");
46 	fprintf(stream, "\t-4\t\tstay on ip4\n");
47 	fprintf(stream, "\t-6\t\tstay on ip6\n");
48 	fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n");
49 	fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n");
50 	fprintf(stream, "\t-c <file>\tuse file for rescursive nameserver configuration"
51 			"\n\t\t\t(/etc/resolv.conf)\n");
52 	fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n");
53 	fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n");
54 	fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n"
55 			"\t\t\tchasing (-S) and no key files are given, keys are read\n"
56 			"\t\t\tfrom: %s\n",
57 			LDNS_TRUST_ANCHOR_FILE);
58 	fprintf(stream, "\t-o <mnemonic>\tset flags to:"
59 			"\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
60 	fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n");
61 	fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n");
62 	fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n");
63 	fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
64 	fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
65 	fprintf(stream, "\twhen doing a secure trace:\n");
66 	fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n");
67 	fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n");
68 	fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n");
69     fprintf(stream, "\t-y <name:key[:algo]>\tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n");
70 	fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
71 	fprintf(stream, "\n  [*] = enables/implies DNSSEC\n");
72 	fprintf(stream, "  [**] = can be given more than once\n");
73 	fprintf(stream, "\n  ldns-team@nlnetlabs.nl | http://www.nlnetlabs.nl/ldns/\n");
74 }
75 
76 /**
77  * Prints the drill version to stderr
78  */
79 static void
80 version(FILE *stream, const char *progname)
81 {
82         fprintf(stream, "%s version %s (ldns version %s)\n", progname, DRILL_VERSION, ldns_version());
83         fprintf(stream, "Written by NLnet Labs.\n");
84         fprintf(stream, "\nCopyright (c) 2004-2008 NLnet Labs.\n");
85         fprintf(stream, "Licensed under the revised BSD license.\n");
86         fprintf(stream, "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n");
87         fprintf(stream, "FOR A PARTICULAR PURPOSE.\n");
88 }
89 
90 
91 /**
92  * Main function of drill
93  * parse the arguments and prepare a query
94  */
95 int
96 main(int argc, char *argv[])
97 {
98         ldns_resolver	*res = NULL;
99         ldns_resolver   *cmdline_res = NULL; /* only used to resolv @name names */
100 	ldns_rr_list	*cmdline_rr_list = NULL;
101 	ldns_rdf	*cmdline_dname = NULL;
102         ldns_rdf 	*qname, *qname_tmp;
103         ldns_pkt	*pkt;
104         ldns_pkt	*qpkt;
105         char 		*serv;
106         const char 	*name;
107         char 		*name2;
108 	char		*progname;
109 	char 		*query_file = NULL;
110 	char		*answer_file = NULL;
111 	ldns_buffer	*query_buffer = NULL;
112 	ldns_rdf 	*serv_rdf;
113         ldns_rr_type 	type;
114         ldns_rr_class	clas;
115 #if 0
116 	ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
117 #endif
118 	int 		i, c;
119 	int 		int_type;
120 	int		int_clas;
121 	int		PURPOSE;
122 	char		*tsig_name = NULL;
123 	char		*tsig_data = NULL;
124 	char 		*tsig_algorithm = NULL;
125 	size_t		tsig_separator;
126 	size_t		tsig_separator2;
127 	ldns_rr		*axfr_rr;
128 	ldns_status	status;
129 	char *type_str;
130 
131 	/* list of keys used in dnssec operations */
132 	ldns_rr_list	*key_list = ldns_rr_list_new();
133 	/* what key verify the current answer */
134 	ldns_rr_list 	*key_verified;
135 
136 	/* resolver options */
137 	uint16_t	qflags;
138 	uint16_t 	qbuf;
139 	uint16_t	qport;
140 	uint8_t		qfamily;
141 	bool		qdnssec;
142 	bool		qfallback;
143 	bool		qds;
144 	bool		qusevc;
145 	bool 		qrandom;
146 
147 	char		*resolv_conf_file = NULL;
148 
149 	ldns_rdf *trace_start_name = NULL;
150 
151 	int		result = 0;
152 
153 #ifdef USE_WINSOCK
154 	int r;
155 	WSADATA wsa_data;
156 #endif
157 
158 	int_type = -1; serv = NULL; type = 0;
159 	int_clas = -1; name = NULL; clas = 0;
160 	qname = NULL;
161 	progname = strdup(argv[0]);
162 
163 #ifdef USE_WINSOCK
164 	r = WSAStartup(MAKEWORD(2,2), &wsa_data);
165 	if(r != 0) {
166 		printf("Failed WSAStartup: %d\n", r);
167 		result = EXIT_FAILURE;
168 		goto exit;
169 	}
170 #endif /* USE_WINSOCK */
171 
172 
173 	PURPOSE = DRILL_QUERY;
174 	qflags = LDNS_RD;
175 	qport = LDNS_PORT;
176 	verbosity = 2;
177 	qdnssec = false;
178 	qfamily = LDNS_RESOLV_INETANY;
179 	qfallback = false;
180 	qds = false;
181 	qbuf = 0;
182 	qusevc = false;
183 	qrandom = true;
184 	key_verified = NULL;
185 
186 	ldns_init_random(NULL, 0);
187 
188 	if (argc == 0) {
189 		usage(stdout, progname);
190 		result = EXIT_FAILURE;
191 		goto exit;
192 	}
193 
194 	/* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */
195 	/* global first, query opt next, option with parm's last
196 	 * and sorted */ /*  "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
197 
198 	while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
199 		switch(c) {
200 			/* global options */
201 			case '4':
202 				qfamily = LDNS_RESOLV_INET;
203 				break;
204 			case '6':
205 				qfamily = LDNS_RESOLV_INET6;
206 				break;
207 			case 'D':
208 				qdnssec = true;
209 				break;
210 			case 'I':
211 				/* reserved for backward compatibility */
212 				break;
213 			case 'T':
214 				if (PURPOSE == DRILL_CHASE) {
215 					fprintf(stderr, "-T and -S cannot be used at the same time.\n");
216 					exit(EXIT_FAILURE);
217 				}
218 				PURPOSE = DRILL_TRACE;
219 				break;
220 #ifdef HAVE_SSL
221 			case 'S':
222 				if (PURPOSE == DRILL_TRACE) {
223 					fprintf(stderr, "-T and -S cannot be used at the same time.\n");
224 					exit(EXIT_FAILURE);
225 				}
226 				PURPOSE = DRILL_CHASE;
227 				break;
228 #endif /* HAVE_SSL */
229 			case 'V':
230 				if (strtok(optarg, "0123456789") != NULL) {
231 					fprintf(stderr, "-V expects an number as an argument.\n");
232 					exit(EXIT_FAILURE);
233 				}
234 				verbosity = atoi(optarg);
235 				break;
236 			case 'Q':
237 				verbosity = -1;
238 				break;
239 			case 'f':
240 				query_file = optarg;
241 				break;
242 			case 'i':
243 				answer_file = optarg;
244 				PURPOSE = DRILL_AFROMFILE;
245 				break;
246 			case 'w':
247 				answer_file = optarg;
248 				break;
249 			case 'q':
250 				query_file = optarg;
251 				PURPOSE = DRILL_QTOFILE;
252 				break;
253 			case 'r':
254 				if (global_dns_root) {
255 					fprintf(stderr, "There was already a series of root servers set\n");
256 					exit(EXIT_FAILURE);
257 				}
258 				global_dns_root = read_root_hints(optarg);
259 				if (!global_dns_root) {
260 					fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
261 					exit(EXIT_FAILURE);
262 				}
263 				break;
264 			/* query options */
265 			case 'a':
266 				qfallback = true;
267 				break;
268 			case 'b':
269 				qbuf = (uint16_t)atoi(optarg);
270 				if (qbuf == 0) {
271 					error("%s", "<bufsize> could not be converted");
272 				}
273 				break;
274 			case 'c':
275 				resolv_conf_file = optarg;
276 				break;
277 			case 't':
278 				qusevc = true;
279 				break;
280 			case 'k':
281 				status = read_key_file(optarg,
282 						key_list, false);
283 				if (status != LDNS_STATUS_OK) {
284 					error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
285 				}
286 				qdnssec = true; /* enable that too */
287 				break;
288 			case 'o':
289 				/* only looks at the first hit: capital=ON, lowercase=OFF*/
290 				if (strstr(optarg, "QR")) {
291 					DRILL_ON(qflags, LDNS_QR);
292 				}
293 				if (strstr(optarg, "qr")) {
294 					DRILL_OFF(qflags, LDNS_QR);
295 				}
296 				if (strstr(optarg, "AA")) {
297 					DRILL_ON(qflags, LDNS_AA);
298 				}
299 				if (strstr(optarg, "aa")) {
300 					DRILL_OFF(qflags, LDNS_AA);
301 				}
302 				if (strstr(optarg, "TC")) {
303 					DRILL_ON(qflags, LDNS_TC);
304 				}
305 				if (strstr(optarg, "tc")) {
306 					DRILL_OFF(qflags, LDNS_TC);
307 				}
308 				if (strstr(optarg, "RD")) {
309 					DRILL_ON(qflags, LDNS_RD);
310 				}
311 				if (strstr(optarg, "rd")) {
312 					DRILL_OFF(qflags, LDNS_RD);
313 				}
314 				if (strstr(optarg, "CD")) {
315 					DRILL_ON(qflags, LDNS_CD);
316 				}
317 				if (strstr(optarg, "cd")) {
318 					DRILL_OFF(qflags, LDNS_CD);
319 				}
320 				if (strstr(optarg, "RA")) {
321 					DRILL_ON(qflags, LDNS_RA);
322 				}
323 				if (strstr(optarg, "ra")) {
324 					DRILL_OFF(qflags, LDNS_RA);
325 				}
326 				if (strstr(optarg, "AD")) {
327 					DRILL_ON(qflags, LDNS_AD);
328 				}
329 				if (strstr(optarg, "ad")) {
330 					DRILL_OFF(qflags, LDNS_AD);
331 				}
332 				break;
333 			case 'p':
334 				qport = (uint16_t)atoi(optarg);
335 				if (qport == 0) {
336 					error("%s", "<port> could not be converted");
337 				}
338 				break;
339 			case 's':
340 				qds = true;
341 				break;
342 			case 'u':
343 				qusevc = false;
344 				break;
345 			case 'v':
346 				version(stdout, progname);
347 				result = EXIT_SUCCESS;
348 				goto exit;
349 			case 'x':
350 				PURPOSE = DRILL_REVERSE;
351 				break;
352 			case 'y':
353 #ifdef HAVE_SSL
354 				if (strchr(optarg, ':')) {
355 					tsig_separator = (size_t) (strchr(optarg, ':') - optarg);
356 					if (strchr(optarg + tsig_separator + 1, ':')) {
357 						tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg);
358 						tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2);
359 						strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2);
360 						tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0';
361 					} else {
362 						tsig_separator2 = strlen(optarg);
363 						tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
364 					}
365 					tsig_name = xmalloc(tsig_separator + 1);
366 					tsig_data = xmalloc(tsig_separator2 - tsig_separator);
367 					strncpy(tsig_name, optarg, tsig_separator);
368 					strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1);
369 					/* strncpy does not append \0 if source is longer than n */
370 					tsig_name[tsig_separator] = '\0';
371 					tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0';
372 				}
373 #else
374 				fprintf(stderr, "TSIG requested, but SSL is not supported\n");
375 				result = EXIT_FAILURE;
376 				goto exit;
377 #endif /* HAVE_SSL */
378 				break;
379 			case 'z':
380 				qrandom = false;
381 				break;
382 			case 'd':
383 				trace_start_name = ldns_dname_new_frm_str(optarg);
384 				if (!trace_start_name) {
385 					fprintf(stderr, "Unable to parse argument for -%c\n", c);
386 					result = EXIT_FAILURE;
387 					goto exit;
388 				}
389 				break;
390 			case 'h':
391 				version(stdout, progname);
392 				usage(stdout, progname);
393 				result = EXIT_SUCCESS;
394 				goto exit;
395 				break;
396 			default:
397 				fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c);
398 				result = EXIT_FAILURE;
399 				goto exit;
400 		}
401 	}
402 	argc -= optind;
403 	argv += optind;
404 
405 	if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
406 			ldns_rr_list_rr_count(key_list) == 0) {
407 
408 		(void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
409 	}
410 	if (ldns_rr_list_rr_count(key_list) > 0) {
411 		printf(";; Number of trusted keys: %d\n",
412 				(int) ldns_rr_list_rr_count(key_list));
413 	}
414 	/* do a secure trace when requested */
415 	if (PURPOSE == DRILL_TRACE && qdnssec) {
416 #ifdef HAVE_SSL
417 		if (ldns_rr_list_rr_count(key_list) == 0) {
418 			warning("%s", "No trusted keys were given. Will not be able to verify authenticity!");
419 		}
420 		PURPOSE = DRILL_SECTRACE;
421 #else
422 		fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n");
423 		exit(1);
424 #endif /* HAVE_SSL */
425 	}
426 
427 	/* parse the arguments, with multiple arguments, the last argument
428 	 * found is used */
429 	for(i = 0; i < argc; i++) {
430 
431 		/* if ^@ then it's a server */
432 		if (argv[i][0] == '@') {
433 			if (strlen(argv[i]) == 1) {
434 				warning("%s", "No nameserver given");
435 				exit(EXIT_FAILURE);
436 			}
437 			serv = argv[i] + 1;
438 			continue;
439 		}
440 		/* if has a dot, it's a name */
441 		if (strchr(argv[i], '.')) {
442 			name = argv[i];
443 			continue;
444 		}
445 		/* if it matches a type, it's a type */
446 		if (int_type == -1) {
447 			type = ldns_get_rr_type_by_name(argv[i]);
448 			if (type != 0) {
449 				int_type = 0;
450 				continue;
451 			}
452 		}
453 		/* if it matches a class, it's a class */
454 		if (int_clas == -1) {
455 			clas = ldns_get_rr_class_by_name(argv[i]);
456 			if (clas != 0) {
457 				int_clas = 0;
458 				continue;
459 			}
460 		}
461 		/* it all fails assume it's a name */
462 		name = argv[i];
463 	}
464 	/* act like dig and use for . NS */
465 	if (!name) {
466 		name = ".";
467 		int_type = 0;
468 		type = LDNS_RR_TYPE_NS;
469 	}
470 
471 	/* defaults if not given */
472 	if (int_clas == -1) {
473 		clas = LDNS_RR_CLASS_IN;
474 	}
475 	if (int_type == -1) {
476 		if (PURPOSE != DRILL_REVERSE) {
477 			type = LDNS_RR_TYPE_A;
478 		} else {
479 			type = LDNS_RR_TYPE_PTR;
480 		}
481 	}
482 
483 	/* set the nameserver to use */
484 	if (!serv) {
485 		/* no server given make a resolver from /etc/resolv.conf */
486 		status = ldns_resolver_new_frm_file(&res, resolv_conf_file);
487 		if (status != LDNS_STATUS_OK) {
488 			warning("Could not create a resolver structure: %s (%s)\n"
489 					"Try drill @localhost if you have a resolver running on your machine.",
490 				    ldns_get_errorstr_by_id(status), resolv_conf_file);
491 			result = EXIT_FAILURE;
492 			goto exit;
493 		}
494 	} else {
495 		res = ldns_resolver_new();
496 		if (!res || strlen(serv) <= 0) {
497 			warning("Could not create a resolver structure");
498 			result = EXIT_FAILURE;
499 			goto exit;
500 		}
501 		/* add the nameserver */
502 		serv_rdf = ldns_rdf_new_addr_frm_str(serv);
503 		if (!serv_rdf) {
504 			/* try to resolv the name if possible */
505 			status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file);
506 
507 			if (status != LDNS_STATUS_OK) {
508 				error("%s", "@server ip could not be converted");
509 			}
510 			ldns_resolver_set_dnssec(cmdline_res, qdnssec);
511 			ldns_resolver_set_ip6(cmdline_res, qfamily);
512 			ldns_resolver_set_fallback(cmdline_res, qfallback);
513 			ldns_resolver_set_usevc(cmdline_res, qusevc);
514 
515 			cmdline_dname = ldns_dname_new_frm_str(serv);
516 
517 			cmdline_rr_list = ldns_get_rr_list_addr_by_name(
518 						cmdline_res,
519 						cmdline_dname,
520 						LDNS_RR_CLASS_IN,
521 						qflags);
522 			ldns_rdf_deep_free(cmdline_dname);
523 			if (!cmdline_rr_list) {
524 				/* This error msg is not always accurate */
525 				error("%s `%s\'", "could not find any address for the name:", serv);
526 			} else {
527 				if (ldns_resolver_push_nameserver_rr_list(
528 						res,
529 						cmdline_rr_list
530 					) != LDNS_STATUS_OK) {
531 					error("%s", "pushing nameserver");
532 				}
533 			}
534 		} else {
535 			if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
536 				error("%s", "pushing nameserver");
537 			} else {
538 				ldns_rdf_deep_free(serv_rdf);
539 			}
540 		}
541 	}
542 	/* set the resolver options */
543 	ldns_resolver_set_port(res, qport);
544 	if (verbosity >= 5) {
545 		ldns_resolver_set_debug(res, true);
546 	} else {
547 		ldns_resolver_set_debug(res, false);
548 	}
549 	ldns_resolver_set_dnssec(res, qdnssec);
550 /*	ldns_resolver_set_dnssec_cd(res, qdnssec);*/
551 	ldns_resolver_set_ip6(res, qfamily);
552 	ldns_resolver_set_fallback(res, qfallback);
553 	ldns_resolver_set_usevc(res, qusevc);
554 	ldns_resolver_set_random(res, qrandom);
555 	if (qbuf != 0) {
556 		ldns_resolver_set_edns_udp_size(res, qbuf);
557 	}
558 
559 	if (!name &&
560 	    PURPOSE != DRILL_AFROMFILE &&
561 	    !query_file
562 	   ) {
563 		usage(stdout, progname);
564 		result = EXIT_FAILURE;
565 		goto exit;
566 	}
567 
568 	if (tsig_name && tsig_data) {
569 		ldns_resolver_set_tsig_keyname(res, tsig_name);
570 		ldns_resolver_set_tsig_keydata(res, tsig_data);
571 		ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
572 	}
573 
574 	/* main switching part of drill */
575 	switch(PURPOSE) {
576 		case DRILL_TRACE:
577 			/* do a trace from the root down */
578 			if (!global_dns_root) {
579 				init_root();
580 			}
581 			qname = ldns_dname_new_frm_str(name);
582 			if (!qname) {
583 				error("%s", "parsing query name");
584 			}
585 			/* don't care about return packet */
586 			(void)do_trace(res, qname, type, clas);
587 			clear_root();
588 			break;
589 		case DRILL_SECTRACE:
590 			/* do a secure trace from the root down */
591 			if (!global_dns_root) {
592 				init_root();
593 			}
594 			qname = ldns_dname_new_frm_str(name);
595 			if (!qname) {
596 				error("%s", "making qname");
597 			}
598 			/* don't care about return packet */
599 #ifdef HAVE_SSL
600 			result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name);
601 #endif /* HAVE_SSL */
602 			clear_root();
603 			break;
604 		case DRILL_CHASE:
605 			qname = ldns_dname_new_frm_str(name);
606 			if (!qname) {
607 				error("%s", "making qname");
608 			}
609 
610 			ldns_resolver_set_dnssec(res, true);
611 			ldns_resolver_set_dnssec_cd(res, true);
612 			/* set dnssec implies udp_size of 4096 */
613 			ldns_resolver_set_edns_udp_size(res, 4096);
614 			pkt = ldns_resolver_query(res, qname, type, clas, qflags);
615 
616 			if (!pkt) {
617 				error("%s", "error pkt sending");
618 				result = EXIT_FAILURE;
619 			} else {
620 				if (verbosity >= 3) {
621 					ldns_pkt_print(stdout, pkt);
622 				}
623 
624 				if (!ldns_pkt_answer(pkt)) {
625 					mesg("No answer in packet");
626 				} else {
627 #ifdef HAVE_SSL
628 					ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list));
629 					result = do_chase(res, qname, type,
630 					                  clas, key_list,
631 					                  pkt, qflags, NULL,
632 								   verbosity);
633 					if (result == LDNS_STATUS_OK) {
634 						if (verbosity != -1) {
635 							mesg("Chase successful");
636 						}
637 						result = 0;
638 					} else {
639 						if (verbosity != -1) {
640 							mesg("Chase failed.");
641 						}
642 					}
643 #endif /* HAVE_SSL */
644 				}
645 				ldns_pkt_free(pkt);
646 			}
647 			break;
648 		case DRILL_AFROMFILE:
649 			pkt = read_hex_pkt(answer_file);
650 			if (pkt) {
651 				if (verbosity != -1) {
652 					ldns_pkt_print(stdout, pkt);
653 				}
654 				ldns_pkt_free(pkt);
655 			}
656 
657 			break;
658 		case DRILL_QTOFILE:
659 			qname = ldns_dname_new_frm_str(name);
660 			if (!qname) {
661 				error("%s", "making qname");
662 			}
663 
664 			status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags);
665 			if(status != LDNS_STATUS_OK) {
666 				error("%s", "making query: %s",
667 					ldns_get_errorstr_by_id(status));
668 			}
669 			dump_hex(qpkt, query_file);
670 			ldns_pkt_free(qpkt);
671 			break;
672 		case DRILL_NSEC:
673 			break;
674 		case DRILL_REVERSE:
675 			/* ipv4 or ipv6 addr? */
676 			if (strchr(name, ':')) {
677 				if (strchr(name, '.')) {
678 					error("Syntax error: both '.' and ':' seen in address\n");
679 				}
680 				name2 = malloc(IP6_ARPA_MAX_LEN + 20);
681 				c = 0;
682 				for (i=0; i<(int)strlen(name); i++) {
683 					if (i >= IP6_ARPA_MAX_LEN) {
684 						error("%s", "reverse argument to long");
685 					}
686 					if (name[i] == ':') {
687 						if (i < (int) strlen(name) && name[i + 1] == ':') {
688 							error("%s", ":: not supported (yet)");
689 						} else {
690 							if (i + 2 == (int) strlen(name) || name[i + 2] == ':') {
691 								name2[c++] = '0';
692 								name2[c++] = '.';
693 								name2[c++] = '0';
694 								name2[c++] = '.';
695 								name2[c++] = '0';
696 								name2[c++] = '.';
697 							} else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') {
698 								name2[c++] = '0';
699 								name2[c++] = '.';
700 								name2[c++] = '0';
701 								name2[c++] = '.';
702 							} else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') {
703 								name2[c++] = '0';
704 								name2[c++] = '.';
705 							}
706 						}
707 					} else {
708 						name2[c++] = name[i];
709 						name2[c++] = '.';
710 					}
711 				}
712 				name2[c++] = '\0';
713 
714 				qname = ldns_dname_new_frm_str(name2);
715 				qname_tmp = ldns_dname_reverse(qname);
716 				ldns_rdf_deep_free(qname);
717 				qname = qname_tmp;
718 				qname_tmp = ldns_dname_new_frm_str("ip6.arpa.");
719 				status = ldns_dname_cat(qname, qname_tmp);
720 				if (status != LDNS_STATUS_OK) {
721 					error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status));
722 				}
723 				ldns_rdf_deep_free(qname_tmp);
724 
725 				free(name2);
726 			} else {
727 				qname = ldns_dname_new_frm_str(name);
728 				qname_tmp = ldns_dname_reverse(qname);
729 				ldns_rdf_deep_free(qname);
730 				qname = qname_tmp;
731 				qname_tmp = ldns_dname_new_frm_str("in-addr.arpa.");
732 				status = ldns_dname_cat(qname, qname_tmp);
733 				if (status != LDNS_STATUS_OK) {
734 					error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status));
735 				}
736 				ldns_rdf_deep_free(qname_tmp);
737 			}
738 			if (!qname) {
739 				error("%s", "-x implies an ip address");
740 			}
741 
742 			/* create a packet and set the RD flag on it */
743 			pkt = ldns_resolver_query(res, qname, type, clas, qflags);
744 			if (!pkt)  {
745 				error("%s", "pkt sending");
746 				result = EXIT_FAILURE;
747 			} else {
748 				if (verbosity != -1) {
749 					ldns_pkt_print(stdout, pkt);
750 				}
751 				ldns_pkt_free(pkt);
752 			}
753 			break;
754 		case DRILL_QUERY:
755 		default:
756 			if (query_file) {
757 				/* this old way, the query packet needed
758 				   to be parseable, but we want to be able
759 				   to send mangled packets, so we need
760 				   to do it directly */
761 				#if 0
762 				qpkt = read_hex_pkt(query_file);
763 				if (qpkt) {
764 					status = ldns_resolver_send_pkt(&pkt, res, qpkt);
765 					if (status != LDNS_STATUS_OK) {
766 						printf("Error: %s\n", ldns_get_errorstr_by_id(status));
767 						exit(1);
768 					}
769 				} else {
770 					/* qpkt was bogus, reset pkt */
771 					pkt = NULL;
772 				}
773 				#endif
774 				query_buffer = read_hex_buffer(query_file);
775 				if (query_buffer) {
776 					status = ldns_send_buffer(&pkt, res, query_buffer, NULL);
777 					ldns_buffer_free(query_buffer);
778 					if (status != LDNS_STATUS_OK) {
779 						printf("Error: %s\n", ldns_get_errorstr_by_id(status));
780 						exit(1);
781 					}
782 				} else {
783 					printf("NO BUFFER\n");
784 					pkt = NULL;
785 				}
786 			} else {
787 				qname = ldns_dname_new_frm_str(name);
788 				if (!qname) {
789 					error("%s", "error in making qname");
790 				}
791 
792 				if (type == LDNS_RR_TYPE_AXFR) {
793 					status = ldns_axfr_start(res, qname, clas);
794 					if(status != LDNS_STATUS_OK) {
795 						error("Error starting axfr: %s",
796 							ldns_get_errorstr_by_id(status));
797 					}
798 					axfr_rr = ldns_axfr_next(res);
799 					if(!axfr_rr) {
800 						fprintf(stderr, "AXFR failed.\n");
801 						ldns_pkt_print(stdout,
802 							ldns_axfr_last_pkt(res));
803 						goto exit;
804 					}
805 					while (axfr_rr) {
806 						if (verbosity != -1) {
807 							ldns_rr_print(stdout, axfr_rr);
808 						}
809 						ldns_rr_free(axfr_rr);
810 						axfr_rr = ldns_axfr_next(res);
811 					}
812 
813 					goto exit;
814 				} else {
815 					/* create a packet and set the RD flag on it */
816 					pkt = ldns_resolver_query(res, qname, type, clas, qflags);
817 				}
818 			}
819 
820 			if (!pkt)  {
821 				mesg("No packet received");
822 				result = EXIT_FAILURE;
823 			} else {
824 				if (verbosity != -1) {
825 					ldns_pkt_print(stdout, pkt);
826 					if (ldns_pkt_tc(pkt)) {
827 						fprintf(stdout,
828 							"\n;; WARNING: The answer packet was truncated; you might want to\n");
829 						fprintf(stdout,
830 							";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n");
831 					}
832 				}
833 				if (qds) {
834 					if (verbosity != -1) {
835 						print_ds_of_keys(pkt);
836 						printf("\n");
837 					}
838 				}
839 
840 				if (ldns_rr_list_rr_count(key_list) > 0) {
841 					/* -k's were given on the cmd line */
842 					ldns_rr_list *rrset_verified;
843 					uint16_t key_count;
844 
845 					rrset_verified = ldns_pkt_rr_list_by_name_and_type(
846 							pkt, qname, type,
847 							LDNS_SECTION_ANY_NOQUESTION);
848 
849 					if (type == LDNS_RR_TYPE_ANY) {
850 						/* don't verify this */
851 						break;
852 					}
853 
854 					if (verbosity != -1) {
855 						printf("; ");
856 						ldns_rr_list_print(stdout, rrset_verified);
857 					}
858 
859 					/* verify */
860 #ifdef HAVE_SSL
861 					key_verified = ldns_rr_list_new();
862 					result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified);
863 
864 					if (result == LDNS_STATUS_ERR) {
865 						/* is the existence denied then? */
866 						result = ldns_verify_denial(pkt, qname, type, NULL, NULL);
867 						if (result == LDNS_STATUS_OK) {
868 							if (verbosity != -1) {
869 								printf("Existence denied for ");
870 								ldns_rdf_print(stdout, qname);
871 								type_str = ldns_rr_type2str(type);
872 								printf("\t%s\n", type_str);
873 								LDNS_FREE(type_str);
874 							}
875 						} else {
876 							if (verbosity != -1) {
877 								printf("Bad data; RR for name and "
878 								       "type not found or failed to "
879 								       "verify, and denial of "
880 								       "existence failed.\n");
881 							}
882 						}
883 					} else if (result == LDNS_STATUS_OK) {
884 						for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified);
885 								key_count++) {
886 							if (verbosity != -1) {
887 								printf("; VALIDATED by id = %u, owner = ",
888 										(unsigned int)ldns_calc_keytag(
889 												      ldns_rr_list_rr(key_verified, key_count)));
890 								ldns_rdf_print(stdout, ldns_rr_owner(
891 											ldns_rr_list_rr(key_list, key_count)));
892 								printf("\n");
893 							}
894 						}
895 					} else {
896 						for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list);
897 								key_count++) {
898 							if (verbosity != -1) {
899 								printf("; %s for id = %u, owner = ",
900 								       ldns_get_errorstr_by_id(result),
901 								       (unsigned int)ldns_calc_keytag(
902 												      ldns_rr_list_rr(key_list, key_count)));
903 								ldns_rdf_print(stdout, ldns_rr_owner(
904 
905 								ldns_rr_list_rr(key_list,
906 								key_count)));
907 								printf("\n");
908 							}
909 						}
910 					}
911 					ldns_rr_list_free(key_verified);
912 #else
913 					(void) key_count;
914 #endif /* HAVE_SSL */
915 				}
916 				if (answer_file) {
917 					dump_hex(pkt, answer_file);
918 				}
919 				ldns_pkt_free(pkt);
920 			}
921 
922 			break;
923 	}
924 
925 	exit:
926 	ldns_rdf_deep_free(qname);
927 	ldns_resolver_deep_free(res);
928 	ldns_resolver_deep_free(cmdline_res);
929 	ldns_rr_list_deep_free(key_list);
930 	ldns_rr_list_deep_free(cmdline_rr_list);
931 	ldns_rdf_deep_free(trace_start_name);
932 	xfree(progname);
933 	xfree(tsig_name);
934 	xfree(tsig_data);
935 	xfree(tsig_algorithm);
936 
937 #ifdef HAVE_SSL
938 	ERR_remove_state(0);
939 	CRYPTO_cleanup_all_ex_data();
940 	ERR_free_strings();
941 	EVP_cleanup();
942 #endif
943 #ifdef USE_WINSOCK
944 	WSACleanup();
945 #endif
946 
947 	return result;
948 }
949