xref: /dragonfly/contrib/ldns/drill/drill.c (revision dc6f5bdf)
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 */
18 int		verbosity;
19 
20 static int
21 is_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 
33 static void
34 usage(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 rescursive 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  */
91 static void
92 version(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  */
107 int
108 main(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 
177 	int_type = -1; serv = NULL; type = 0;
178 	int_clas = -1; name = NULL; clas = 0;
179 	qname = NULL; src = NULL;
180 	progname = strdup(argv[0]);
181 
182 #ifdef USE_WINSOCK
183 	r = WSAStartup(MAKEWORD(2,2), &wsa_data);
184 	if(r != 0) {
185 		printf("Failed WSAStartup: %d\n", r);
186 		result = EXIT_FAILURE;
187 		goto exit;
188 	}
189 #endif /* USE_WINSOCK */
190 
191 
192 	PURPOSE = DRILL_QUERY;
193 	qflags = LDNS_RD;
194 	qport = LDNS_PORT;
195 	verbosity = 2;
196 	qdnssec = false;
197 	qfamily = LDNS_RESOLV_INETANY;
198 	qfallback = false;
199 	qds = false;
200 	qbuf = 0;
201 	qusevc = false;
202 	qrandom = true;
203 	key_verified = NULL;
204 
205 	ldns_init_random(NULL, 0);
206 
207 	/* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */
208 	/* global first, query opt next, option with parm's last
209 	 * and sorted */ /*  "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
210 
211 	while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:I:k:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
212 		switch(c) {
213 			/* global options */
214 			case '4':
215 				qfamily = LDNS_RESOLV_INET;
216 				break;
217 			case '6':
218 				qfamily = LDNS_RESOLV_INET6;
219 				break;
220 			case 'D':
221 				qdnssec = true;
222 				break;
223 			case 'I':
224 				src = optarg;
225 				break;
226 			case 'T':
227 				if (PURPOSE == DRILL_CHASE) {
228 					fprintf(stderr, "-T and -S cannot be used at the same time.\n");
229 					exit(EXIT_FAILURE);
230 				}
231 				PURPOSE = DRILL_TRACE;
232 				break;
233 #ifdef HAVE_SSL
234 			case 'S':
235 				if (PURPOSE == DRILL_TRACE) {
236 					fprintf(stderr, "-T and -S cannot be used at the same time.\n");
237 					exit(EXIT_FAILURE);
238 				}
239 				PURPOSE = DRILL_CHASE;
240 				break;
241 #endif /* HAVE_SSL */
242 			case 'V':
243 				if (strtok(optarg, "0123456789") != NULL) {
244 					fprintf(stderr, "-V expects an number as an argument.\n");
245 					exit(EXIT_FAILURE);
246 				}
247 				verbosity = atoi(optarg);
248 				break;
249 			case 'Q':
250 				verbosity = -1;
251 				break;
252 			case 'f':
253 				query_file = optarg;
254 				break;
255 			case 'i':
256 				answer_file = optarg;
257 				PURPOSE = DRILL_AFROMFILE;
258 				break;
259 			case 'w':
260 				answer_file = optarg;
261 				break;
262 			case 'q':
263 				query_file = optarg;
264 				PURPOSE = DRILL_QTOFILE;
265 				break;
266 			case 'r':
267 				if (global_dns_root) {
268 					fprintf(stderr, "There was already a series of root servers set\n");
269 					exit(EXIT_FAILURE);
270 				}
271 				global_dns_root = read_root_hints(optarg);
272 				if (!global_dns_root) {
273 					fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
274 					exit(EXIT_FAILURE);
275 				}
276 				break;
277 			/* query options */
278 			case 'a':
279 				qfallback = true;
280 				break;
281 			case 'b':
282 				qbuf = (uint16_t)atoi(optarg);
283 				if (qbuf == 0) {
284 					error("%s", "<bufsize> could not be converted");
285 				}
286 				break;
287 			case 'c':
288 				resolv_conf_file = optarg;
289 				break;
290 			case 't':
291 				qusevc = true;
292 				break;
293 			case 'k':
294 				status = read_key_file(optarg,
295 						key_list, false);
296 				if (status != LDNS_STATUS_OK) {
297 					error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
298 				}
299 				qdnssec = true; /* enable that too */
300 				break;
301 			case 'o':
302 				/* only looks at the first hit: capital=ON, lowercase=OFF*/
303 				if (strstr(optarg, "QR")) {
304 					DRILL_ON(qflags, LDNS_QR);
305 				}
306 				if (strstr(optarg, "qr")) {
307 					DRILL_OFF(qflags, LDNS_QR);
308 				}
309 				if (strstr(optarg, "AA")) {
310 					DRILL_ON(qflags, LDNS_AA);
311 				}
312 				if (strstr(optarg, "aa")) {
313 					DRILL_OFF(qflags, LDNS_AA);
314 				}
315 				if (strstr(optarg, "TC")) {
316 					DRILL_ON(qflags, LDNS_TC);
317 				}
318 				if (strstr(optarg, "tc")) {
319 					DRILL_OFF(qflags, LDNS_TC);
320 				}
321 				if (strstr(optarg, "RD")) {
322 					DRILL_ON(qflags, LDNS_RD);
323 				}
324 				if (strstr(optarg, "rd")) {
325 					DRILL_OFF(qflags, LDNS_RD);
326 				}
327 				if (strstr(optarg, "CD")) {
328 					DRILL_ON(qflags, LDNS_CD);
329 				}
330 				if (strstr(optarg, "cd")) {
331 					DRILL_OFF(qflags, LDNS_CD);
332 				}
333 				if (strstr(optarg, "RA")) {
334 					DRILL_ON(qflags, LDNS_RA);
335 				}
336 				if (strstr(optarg, "ra")) {
337 					DRILL_OFF(qflags, LDNS_RA);
338 				}
339 				if (strstr(optarg, "AD")) {
340 					DRILL_ON(qflags, LDNS_AD);
341 				}
342 				if (strstr(optarg, "ad")) {
343 					DRILL_OFF(qflags, LDNS_AD);
344 				}
345 				break;
346 			case 'p':
347 				qport = (uint16_t)atoi(optarg);
348 				if (qport == 0) {
349 					error("%s", "<port> could not be converted");
350 				}
351 				break;
352 			case 's':
353 				qds = true;
354 				break;
355 			case 'u':
356 				qusevc = false;
357 				break;
358 			case 'v':
359 				version(stdout, progname);
360 				result = EXIT_SUCCESS;
361 				goto exit;
362 			case 'x':
363 				drill_reverse = true;
364 				break;
365 			case 'y':
366 #ifdef HAVE_SSL
367 				if (strchr(optarg, ':')) {
368 					tsig_separator = (size_t) (strchr(optarg, ':') - optarg);
369 					if (tsig_algorithm) {
370 						free(tsig_algorithm);
371 						tsig_algorithm = NULL;
372 					}
373 					if (strchr(optarg + tsig_separator + 1, ':')) {
374 						tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg);
375 						tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2);
376 						strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2);
377 						tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0';
378 					} else {
379 						tsig_separator2 = strlen(optarg);
380 						tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
381 					}
382 					tsig_name = xmalloc(tsig_separator + 1);
383 					tsig_data = xmalloc(tsig_separator2 - tsig_separator);
384 					strncpy(tsig_name, optarg, tsig_separator);
385 					strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1);
386 					/* strncpy does not append \0 if source is longer than n */
387 					tsig_name[tsig_separator] = '\0';
388 					tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0';
389 				}
390 #else
391 				fprintf(stderr, "TSIG requested, but SSL is not supported\n");
392 				result = EXIT_FAILURE;
393 				goto exit;
394 #endif /* HAVE_SSL */
395 				break;
396 			case 'z':
397 				qrandom = false;
398 				break;
399 			case 'd':
400 				trace_start_name = ldns_dname_new_frm_str(optarg);
401 				if (!trace_start_name) {
402 					fprintf(stderr, "Unable to parse argument for -%c\n", c);
403 					result = EXIT_FAILURE;
404 					goto exit;
405 				}
406 				break;
407 			case 'h':
408 				version(stdout, progname);
409 				usage(stdout, progname);
410 				result = EXIT_SUCCESS;
411 				goto exit;
412 				break;
413 			default:
414 				fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c);
415 				result = EXIT_FAILURE;
416 				goto exit;
417 		}
418 	}
419 	argc -= optind;
420 	argv += optind;
421 
422 	if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
423 			ldns_rr_list_rr_count(key_list) == 0) {
424 
425 		(void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
426 	}
427 	if (ldns_rr_list_rr_count(key_list) > 0) {
428 		printf(";; Number of trusted keys: %d\n",
429 				(int) ldns_rr_list_rr_count(key_list));
430 	}
431 	/* do a secure trace when requested */
432 	if (PURPOSE == DRILL_TRACE && qdnssec) {
433 #ifdef HAVE_SSL
434 		if (ldns_rr_list_rr_count(key_list) == 0) {
435 			warning("%s", "No trusted keys were given. Will not be able to verify authenticity!");
436 		}
437 		PURPOSE = DRILL_SECTRACE;
438 #else
439 		fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n");
440 		exit(1);
441 #endif /* HAVE_SSL */
442 	}
443 
444 	/* parse the arguments, with multiple arguments, the last argument
445 	 * found is used */
446 	for(i = 0; i < argc; i++) {
447 
448 		/* if ^@ then it's a server */
449 		if (argv[i][0] == '@') {
450 			if (strlen(argv[i]) == 1) {
451 				warning("%s", "No nameserver given");
452 				exit(EXIT_FAILURE);
453 			}
454 			serv = argv[i] + 1;
455 			continue;
456 		}
457 		/* if has a dot, it's a name */
458 		if (strchr(argv[i], '.')) {
459 			name = argv[i];
460 			continue;
461 		}
462 		/* if it matches a type, it's a type */
463 		if (int_type == -1) {
464 			type = ldns_get_rr_type_by_name(argv[i]);
465 			if (type != 0) {
466 				int_type = 0;
467 				continue;
468 			} else if (is_ixfr_with_serial(argv[i], &serial)) {
469 				type = LDNS_RR_TYPE_IXFR;
470 				int_type = 0;
471 				continue;
472 			}
473 		}
474 		/* if it matches a class, it's a class */
475 		if (int_clas == -1) {
476 			clas = ldns_get_rr_class_by_name(argv[i]);
477 			if (clas != 0) {
478 				int_clas = 0;
479 				continue;
480 			}
481 		}
482 		/* it all fails assume it's a name */
483 		name = argv[i];
484 	}
485 	/* act like dig and use for . NS */
486 	if (!name) {
487 		name = ".";
488 		int_type = 0;
489 		type = LDNS_RR_TYPE_NS;
490 	}
491 
492 	/* defaults if not given */
493 	if (int_clas == -1) {
494 		clas = LDNS_RR_CLASS_IN;
495 	}
496 	if (int_type == -1) {
497 		if (!drill_reverse) {
498 			type = LDNS_RR_TYPE_A;
499 		} else {
500 			type = LDNS_RR_TYPE_PTR;
501 		}
502 	}
503 	if (!drill_reverse)
504 		; /* pass */
505 	else if (strchr(name, ':')) { /* ipv4 or ipv6 addr? */
506 		if (!inet_pton(AF_INET6, name, &s6addr)) {
507 			error("Syntax error: cannot parse IPv6 address\n");
508 		}
509 		(void) snprintf(ip6_arpa_str, sizeof(ip6_arpa_str),
510 		    "%x.%x.%x.%x.%x.%x.%x.%x."
511 		    "%x.%x.%x.%x.%x.%x.%x.%x."
512 		    "%x.%x.%x.%x.%x.%x.%x.%x."
513 		    "%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.",
514 		    (unsigned int)(s6addr[15] & 0x0F),
515 		    (unsigned int)(s6addr[15] >> 4),
516 		    (unsigned int)(s6addr[14] & 0x0F),
517 		    (unsigned int)(s6addr[14] >> 4),
518 		    (unsigned int)(s6addr[13] & 0x0F),
519 		    (unsigned int)(s6addr[13] >> 4),
520 		    (unsigned int)(s6addr[12] & 0x0F),
521 		    (unsigned int)(s6addr[12] >> 4),
522 		    (unsigned int)(s6addr[11] & 0x0F),
523 		    (unsigned int)(s6addr[11] >> 4),
524 		    (unsigned int)(s6addr[10] & 0x0F),
525 		    (unsigned int)(s6addr[10] >> 4),
526 		    (unsigned int)(s6addr[9] & 0x0F),
527 		    (unsigned int)(s6addr[9] >> 4),
528 		    (unsigned int)(s6addr[8] & 0x0F),
529 		    (unsigned int)(s6addr[8] >> 4),
530 		    (unsigned int)(s6addr[7] & 0x0F),
531 		    (unsigned int)(s6addr[7] >> 4),
532 		    (unsigned int)(s6addr[6] & 0x0F),
533 		    (unsigned int)(s6addr[6] >> 4),
534 		    (unsigned int)(s6addr[5] & 0x0F),
535 		    (unsigned int)(s6addr[5] >> 4),
536 		    (unsigned int)(s6addr[4] & 0x0F),
537 		    (unsigned int)(s6addr[4] >> 4),
538 		    (unsigned int)(s6addr[3] & 0x0F),
539 		    (unsigned int)(s6addr[3] >> 4),
540 		    (unsigned int)(s6addr[2] & 0x0F),
541 		    (unsigned int)(s6addr[2] >> 4),
542 		    (unsigned int)(s6addr[1] & 0x0F),
543 		    (unsigned int)(s6addr[1] >> 4),
544 		    (unsigned int)(s6addr[0] & 0x0F),
545 		    (unsigned int)(s6addr[0] >> 4));
546 		name = ip6_arpa_str;
547 
548 	} else if (!inet_pton(AF_INET, name, &s4addr)) {
549 		error("Syntax error: cannot parse IPv4 address\n");
550 
551 	} else {
552 		(void) snprintf(in_addr_arpa_str, sizeof(in_addr_arpa_str),
553 		    "%d.%d.%d.%d.in-addr.arpa.", (int)s4addr[3],
554 		    (int)s4addr[2], (int)s4addr[1], (int)s4addr[0]);
555 		name = in_addr_arpa_str;
556 	}
557 
558 	if (src) {
559 		src_rdf = ldns_rdf_new_addr_frm_str(src);
560 		if(!src_rdf) {
561 			fprintf(stderr, "-I must be a valid IP[v6] address.\n");
562 			exit(EXIT_FAILURE);
563 		}
564 		if (ldns_rdf_size(src_rdf) == 4) {
565 			qfamily = LDNS_RESOLV_INET;
566 
567 		} else if (ldns_rdf_size(src_rdf) == 16) {
568 			qfamily = LDNS_RESOLV_INET6;
569 		}
570 	}
571 
572 	/* set the nameserver to use */
573 	if (!serv) {
574 		/* no server given -- make a resolver from /etc/resolv.conf */
575 		status = ldns_resolver_new_frm_file(&res, resolv_conf_file);
576 		if (status != LDNS_STATUS_OK) {
577 			warning("Could not create a resolver structure: %s (%s)\n"
578 					"Try drill @localhost if you have a resolver running on your machine.",
579 				    ldns_get_errorstr_by_id(status), resolv_conf_file);
580 			result = EXIT_FAILURE;
581 			goto exit;
582 		}
583 	} else {
584 		res = ldns_resolver_new();
585 		if (!res || strlen(serv) <= 0) {
586 			warning("Could not create a resolver structure");
587 			result = EXIT_FAILURE;
588 			goto exit;
589 		}
590 		/* add the nameserver */
591 		serv_rdf = ldns_rdf_new_addr_frm_str(serv);
592 		if (!serv_rdf) {
593 			/* try to resolv the name if possible */
594 			status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file);
595 
596 			if (status != LDNS_STATUS_OK) {
597 				error("%s", "@server ip could not be converted");
598 			}
599 			ldns_resolver_set_dnssec(cmdline_res, qdnssec);
600 			ldns_resolver_set_ip6(cmdline_res, qfamily);
601 			ldns_resolver_set_fallback(cmdline_res, qfallback);
602 			ldns_resolver_set_usevc(cmdline_res, qusevc);
603 			ldns_resolver_set_source(cmdline_res, src_rdf);
604 
605 			cmdline_dname = ldns_dname_new_frm_str(serv);
606 
607 			cmdline_rr_list = ldns_get_rr_list_addr_by_name(
608 						cmdline_res,
609 						cmdline_dname,
610 						LDNS_RR_CLASS_IN,
611 						qflags);
612 			ldns_rdf_deep_free(cmdline_dname);
613 			if (!cmdline_rr_list) {
614 				/* This error msg is not always accurate */
615 				error("%s `%s\'", "could not find any address for the name:", serv);
616 			} else {
617 				if (ldns_resolver_push_nameserver_rr_list(
618 						res,
619 						cmdline_rr_list
620 					) != LDNS_STATUS_OK) {
621 					error("%s", "pushing nameserver");
622 				}
623 			}
624 		} else {
625 			if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
626 				error("%s", "pushing nameserver");
627 			} else {
628 				ldns_rdf_deep_free(serv_rdf);
629 			}
630 		}
631 	}
632 	/* set the resolver options */
633 	ldns_resolver_set_ixfr_serial(res, serial);
634 	ldns_resolver_set_port(res, qport);
635 	ldns_resolver_set_source(res, src_rdf);
636 	if (verbosity >= 5) {
637 		ldns_resolver_set_debug(res, true);
638 	} else {
639 		ldns_resolver_set_debug(res, false);
640 	}
641 	ldns_resolver_set_dnssec(res, qdnssec);
642 /*	ldns_resolver_set_dnssec_cd(res, qdnssec);*/
643 	ldns_resolver_set_ip6(res, qfamily);
644 	ldns_resolver_set_fallback(res, qfallback);
645 	ldns_resolver_set_usevc(res, qusevc);
646 	ldns_resolver_set_random(res, qrandom);
647 	if (qbuf != 0) {
648 		ldns_resolver_set_edns_udp_size(res, qbuf);
649 	}
650 
651 	if (!name &&
652 	    PURPOSE != DRILL_AFROMFILE &&
653 	    !query_file
654 	   ) {
655 		usage(stdout, progname);
656 		result = EXIT_FAILURE;
657 		goto exit;
658 	}
659 
660 	if (tsig_name && tsig_data) {
661 		/* With dig TSIG keys are also specified with -y,
662 		 * but format with drill is: -y <name:key[:algo]>
663 		 *             and with dig: -y [hmac:]name:key
664 		 *
665 		 * When we detect an unknown tsig algorithm in algo,
666 		 * but a known algorithm in name, we cane assume dig
667 		 * order was used.
668 		 *
669 		 * Following if statement is to anticipate and correct dig order
670 		 */
671 		if (   strcasecmp(tsig_algorithm, "hmac-md5.sig-alg.reg.int")
672 		    && strcasecmp(tsig_algorithm, "hmac-md5")
673 		    && strcasecmp(tsig_algorithm, "hmac-sha1")
674 		    && strcasecmp(tsig_algorithm, "hmac-sha256")
675 		    && (
676 		       strcasecmp(tsig_name, "hmac-md5.sig-alg.reg.int")  == 0
677 		    || strcasecmp(tsig_name, "hmac-md5")                  == 0
678 		    || strcasecmp(tsig_name, "hmac-sha1")                 == 0
679 		    || strcasecmp(tsig_name, "hmac-sha256")               == 0
680 		       )) {
681 
682 			/* Roll options */
683 			char *tmp_tsig_algorithm = tsig_name;
684 			tsig_name      = tsig_data;
685 			tsig_data      = tsig_algorithm;
686 			tsig_algorithm = tmp_tsig_algorithm;
687 		}
688 
689 		if (strcasecmp(tsig_algorithm, "hmac-md5") == 0) {
690 			free(tsig_algorithm);
691 			tsig_algorithm = strdup("hmac-md5.sig-alg.reg.int");
692 		}
693 
694 		ldns_resolver_set_tsig_keyname(res, tsig_name);
695 		ldns_resolver_set_tsig_keydata(res, tsig_data);
696 		ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
697 	}
698 
699 	/* main switching part of drill */
700 	switch(PURPOSE) {
701 		case DRILL_TRACE:
702 			/* do a trace from the root down */
703 			if (!global_dns_root) {
704 				init_root();
705 			}
706 			qname = ldns_dname_new_frm_str(name);
707 			if (!qname) {
708 				error("%s", "parsing query name");
709 			}
710 			/* don't care about return packet */
711 			do_trace(res, qname, type, clas);
712 			clear_root();
713 			break;
714 		case DRILL_SECTRACE:
715 			/* do a secure trace from the root down */
716 			if (!global_dns_root) {
717 				init_root();
718 			}
719 			qname = ldns_dname_new_frm_str(name);
720 			if (!qname) {
721 				error("%s", "making qname");
722 			}
723 			/* don't care about return packet */
724 #ifdef HAVE_SSL
725 			result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name);
726 #endif /* HAVE_SSL */
727 			clear_root();
728 			break;
729 		case DRILL_CHASE:
730 			qname = ldns_dname_new_frm_str(name);
731 			if (!qname) {
732 				error("%s", "making qname");
733 			}
734 
735 			ldns_resolver_set_dnssec(res, true);
736 			ldns_resolver_set_dnssec_cd(res, true);
737 			/* set dnssec implies udp_size of 4096 */
738 			ldns_resolver_set_edns_udp_size(res, 4096);
739 			pkt = NULL;
740 			status = ldns_resolver_query_status(
741 					&pkt, res, qname, type, clas, qflags);
742 			if (status != LDNS_STATUS_OK) {
743 				error("error sending query: %s",
744 					ldns_get_errorstr_by_id(status));
745 			}
746 			if (!pkt) {
747 				if (status == LDNS_STATUS_OK) {
748 					error("%s", "error pkt sending");
749 				}
750 				result = EXIT_FAILURE;
751 			} else {
752 				if (verbosity >= 3) {
753 					ldns_pkt_print(stdout, pkt);
754 				}
755 
756 				if (!ldns_pkt_answer(pkt)) {
757 					mesg("No answer in packet");
758 				} else {
759 #ifdef HAVE_SSL
760 					ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list));
761 					result = do_chase(res, qname, type,
762 					                  clas, key_list,
763 					                  pkt, qflags, NULL);
764 					if (result == LDNS_STATUS_OK) {
765 						if (verbosity != -1) {
766 							mesg("Chase successful");
767 						}
768 						result = 0;
769 					} else {
770 						if (verbosity != -1) {
771 							mesg("Chase failed.");
772 						}
773 					}
774 #endif /* HAVE_SSL */
775 				}
776 				ldns_pkt_free(pkt);
777 			}
778 			break;
779 		case DRILL_AFROMFILE:
780 			pkt = read_hex_pkt(answer_file);
781 			if (pkt) {
782 				if (verbosity != -1) {
783 					ldns_pkt_print(stdout, pkt);
784 				}
785 				ldns_pkt_free(pkt);
786 			}
787 
788 			break;
789 		case DRILL_QTOFILE:
790 			qname = ldns_dname_new_frm_str(name);
791 			if (!qname) {
792 				error("%s", "making qname");
793 			}
794 			status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags);
795 			if(status != LDNS_STATUS_OK) {
796 				error("%s", "making query: %s",
797 					ldns_get_errorstr_by_id(status));
798 			}
799 			dump_hex(qpkt, query_file);
800 			ldns_pkt_free(qpkt);
801 			break;
802 		case DRILL_NSEC:
803 			break;
804 		case DRILL_QUERY:
805 		default:
806 			if (query_file) {
807 				/* this old way, the query packet needed
808 				   to be parseable, but we want to be able
809 				   to send mangled packets, so we need
810 				   to do it directly */
811 				#if 0
812 				qpkt = read_hex_pkt(query_file);
813 				if (qpkt) {
814 					status = ldns_resolver_send_pkt(&pkt, res, qpkt);
815 					if (status != LDNS_STATUS_OK) {
816 						printf("Error: %s\n", ldns_get_errorstr_by_id(status));
817 						exit(1);
818 					}
819 				} else {
820 					/* qpkt was bogus, reset pkt */
821 					pkt = NULL;
822 				}
823 				#endif
824 				query_buffer = read_hex_buffer(query_file);
825 				if (query_buffer) {
826 					status = ldns_send_buffer(&pkt, res, query_buffer, NULL);
827 					ldns_buffer_free(query_buffer);
828 					if (status != LDNS_STATUS_OK) {
829 						printf("Error: %s\n", ldns_get_errorstr_by_id(status));
830 						exit(1);
831 					}
832 				} else {
833 					printf("NO BUFFER\n");
834 					pkt = NULL;
835 				}
836 			} else {
837 				qname = ldns_dname_new_frm_str(name);
838 				if (!qname) {
839 					error("%s", "error in making qname");
840 				}
841 
842 				if (type == LDNS_RR_TYPE_AXFR) {
843 					status = ldns_axfr_start(res, qname, clas);
844 					if(status != LDNS_STATUS_OK) {
845 						error("Error starting axfr: %s",
846 							ldns_get_errorstr_by_id(status));
847 					}
848 					axfr_rr = ldns_axfr_next(res);
849 					if(!axfr_rr) {
850 						fprintf(stderr, "AXFR failed.\n");
851 						ldns_pkt_print(stdout,
852 							ldns_axfr_last_pkt(res));
853 						goto exit;
854 					}
855 					while (axfr_rr) {
856 						if (verbosity != -1) {
857 							ldns_rr_print(stdout, axfr_rr);
858 						}
859 						ldns_rr_free(axfr_rr);
860 						axfr_rr = ldns_axfr_next(res);
861 					}
862 
863 					goto exit;
864 				} else {
865 					/* create a packet and set the RD flag on it */
866 					pkt = NULL;
867 					status = ldns_resolver_query_status(
868 							&pkt, res, qname,
869 							type, clas, qflags);
870 					if (status != LDNS_STATUS_OK) {
871 						error("error sending query: %s"
872 						     , ldns_get_errorstr_by_id(
873 							     status));
874 					}
875 				}
876 			}
877 
878 			if (!pkt)  {
879 				mesg("No packet received");
880 				result = EXIT_FAILURE;
881 			} else {
882 				if (verbosity != -1) {
883 					ldns_pkt_print(stdout, pkt);
884 					if (ldns_pkt_tc(pkt)) {
885 						fprintf(stdout,
886 							"\n;; WARNING: The answer packet was truncated; you might want to\n");
887 						fprintf(stdout,
888 							";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n");
889 					}
890 				}
891 				if (qds) {
892 					if (verbosity != -1) {
893 						print_ds_of_keys(pkt);
894 						printf("\n");
895 					}
896 				}
897 
898 				if (ldns_rr_list_rr_count(key_list) > 0) {
899 					/* -k's were given on the cmd line */
900 					ldns_rr_list *rrset_verified;
901 					uint16_t key_count;
902 
903 					rrset_verified = ldns_pkt_rr_list_by_name_and_type(
904 							pkt, qname, type,
905 							LDNS_SECTION_ANY_NOQUESTION);
906 
907 					if (type == LDNS_RR_TYPE_ANY) {
908 						/* don't verify this */
909 						break;
910 					}
911 
912 					if (verbosity != -1) {
913 						printf("; ");
914 						ldns_rr_list_print(stdout, rrset_verified);
915 					}
916 
917 					/* verify */
918 #ifdef HAVE_SSL
919 					key_verified = ldns_rr_list_new();
920 					result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified);
921 
922 					if (result == LDNS_STATUS_ERR) {
923 						/* is the existence denied then? */
924 						result = ldns_verify_denial(pkt, qname, type, NULL, NULL);
925 						if (result == LDNS_STATUS_OK) {
926 							if (verbosity != -1) {
927 								printf("Existence denied for ");
928 								ldns_rdf_print(stdout, qname);
929 								type_str = ldns_rr_type2str(type);
930 								printf("\t%s\n", type_str);
931 								LDNS_FREE(type_str);
932 							}
933 						} else {
934 							if (verbosity != -1) {
935 								printf("Bad data; RR for name and "
936 								       "type not found or failed to "
937 								       "verify, and denial of "
938 								       "existence failed.\n");
939 							}
940 						}
941 					} else if (result == LDNS_STATUS_OK) {
942 						for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified);
943 								key_count++) {
944 							if (verbosity != -1) {
945 								printf("; VALIDATED by id = %u, owner = ",
946 										(unsigned int)ldns_calc_keytag(
947 												      ldns_rr_list_rr(key_verified, key_count)));
948 								ldns_rdf_print(stdout, ldns_rr_owner(
949 											ldns_rr_list_rr(key_list, key_count)));
950 								printf("\n");
951 							}
952 						}
953 					} else {
954 						for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list);
955 								key_count++) {
956 							if (verbosity != -1) {
957 								printf("; %s for id = %u, owner = ",
958 								       ldns_get_errorstr_by_id(result),
959 								       (unsigned int)ldns_calc_keytag(
960 												      ldns_rr_list_rr(key_list, key_count)));
961 								ldns_rdf_print(stdout, ldns_rr_owner(
962 
963 								ldns_rr_list_rr(key_list,
964 								key_count)));
965 								printf("\n");
966 							}
967 						}
968 					}
969 					ldns_rr_list_free(key_verified);
970 #else
971 					(void) key_count;
972 #endif /* HAVE_SSL */
973 				}
974 				if (answer_file) {
975 					dump_hex(pkt, answer_file);
976 				}
977 				ldns_pkt_free(pkt);
978 			}
979 
980 			break;
981 	}
982 
983 	exit:
984 	ldns_rdf_deep_free(qname);
985 	ldns_rdf_deep_free(src_rdf);
986 	ldns_resolver_deep_free(res);
987 	ldns_resolver_deep_free(cmdline_res);
988 	ldns_rr_list_deep_free(key_list);
989 	ldns_rr_list_deep_free(cmdline_rr_list);
990 	ldns_rdf_deep_free(trace_start_name);
991 	xfree(progname);
992 	xfree(tsig_name);
993 	xfree(tsig_data);
994 	xfree(tsig_algorithm);
995 
996 #ifdef HAVE_SSL
997 	CRYPTO_cleanup_all_ex_data();
998 	ERR_free_strings();
999 	EVP_cleanup();
1000 #endif
1001 #ifdef USE_WINSOCK
1002 	WSACleanup();
1003 #endif
1004 
1005 	return result;
1006 }
1007