xref: /freebsd/contrib/ldns/drill/drill.c (revision 5afab0e5e56fe90a378fb57249600e7924e1cab2)
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
is_ixfr_with_serial(const char * name,uint32_t * serial)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
usage(FILE * stream,const char * progname)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 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  */
91 static void
version(FILE * stream,const char * progname)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
main(int argc,char * argv[])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 	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