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