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