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