3.6 branching and setup.
[dragonfly.git] / contrib / ldns / drill / drill.c
blob574c8b98c856c5867901d40b023c783c75ff9a17
1 /*
2 * drill.c
3 * the main file of drill
4 * (c) 2005-2008 NLnet Labs
6 * See the file LICENSE for the license
8 */
10 #include "drill.h"
11 #include <ldns/ldns.h>
13 #ifdef HAVE_SSL
14 #include <openssl/err.h>
15 #endif
17 #define IP6_ARPA_MAX_LEN 65
19 /* query debug, 2 hex dumps */
20 int verbosity;
22 static void
23 usage(FILE *stream, const char *progname)
25 fprintf(stream, " Usage: %s name [@server] [type] [class]\n", progname);
26 fprintf(stream, "\t<name> can be a domain name or an IP address (-x lookups)\n");
27 fprintf(stream, "\t<type> defaults to A\n");
28 fprintf(stream, "\t<class> defaults to IN\n");
29 fprintf(stream, "\n\targuments may be placed in random order\n");
30 fprintf(stream, "\n Options:\n");
31 fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n");
32 #ifdef HAVE_SSL
33 fprintf(stream, "\t-T\t\ttrace from the root down to <name>\n");
34 fprintf(stream, "\t-S\t\tchase signature(s) from <name> to a know key [*]\n");
35 #endif /*HAVE_SSL*/
36 fprintf(stream, "\t-V <number>\tverbosity (0-5)\n");
37 fprintf(stream, "\t-Q\t\tquiet mode (overrules -V)\n");
38 fprintf(stream, "\n");
39 fprintf(stream, "\t-f file\t\tread packet from file and send it\n");
40 fprintf(stream, "\t-i file\t\tread packet from file and print it\n");
41 fprintf(stream, "\t-w file\t\twrite answer packet to file\n");
42 fprintf(stream, "\t-q file\t\twrite query packet to file\n");
43 fprintf(stream, "\t-h\t\tshow this help\n");
44 fprintf(stream, "\t-v\t\tshow version\n");
45 fprintf(stream, "\n Query options:\n");
46 fprintf(stream, "\t-4\t\tstay on ip4\n");
47 fprintf(stream, "\t-6\t\tstay on ip6\n");
48 fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n");
49 fprintf(stream, "\t-b <bufsize>\tuse <bufsize> as the buffer size (defaults to 512 b)\n");
50 fprintf(stream, "\t-c <file>\tuse file for rescursive nameserver configuration"
51 "\n\t\t\t(/etc/resolv.conf)\n");
52 fprintf(stream, "\t-k <file>\tspecify a file that contains a trusted DNSSEC key [**]\n");
53 fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n");
54 fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n"
55 "\t\t\tchasing (-S) and no key files are given, keys are read\n"
56 "\t\t\tfrom: %s\n",
57 LDNS_TRUST_ANCHOR_FILE);
58 fprintf(stream, "\t-o <mnemonic>\tset flags to:"
59 "\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n");
60 fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n");
61 fprintf(stream, "\t-p <port>\tuse <port> as remote port number\n");
62 fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n");
63 fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n");
64 fprintf(stream, "\t-x\t\tdo a reverse lookup\n");
65 fprintf(stream, "\twhen doing a secure trace:\n");
66 fprintf(stream, "\t-r <file>\tuse file as root servers hint file\n");
67 fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n");
68 fprintf(stream, "\t-d <domain>\tuse domain as the start point for the trace\n");
69 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");
70 fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n");
71 fprintf(stream, "\n [*] = enables/implies DNSSEC\n");
72 fprintf(stream, " [**] = can be given more than once\n");
73 fprintf(stream, "\n ldns-team@nlnetlabs.nl | http://www.nlnetlabs.nl/ldns/\n");
76 /**
77 * Prints the drill version to stderr
79 static void
80 version(FILE *stream, const char *progname)
82 fprintf(stream, "%s version %s (ldns version %s)\n", progname, DRILL_VERSION, ldns_version());
83 fprintf(stream, "Written by NLnet Labs.\n");
84 fprintf(stream, "\nCopyright (c) 2004-2008 NLnet Labs.\n");
85 fprintf(stream, "Licensed under the revised BSD license.\n");
86 fprintf(stream, "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n");
87 fprintf(stream, "FOR A PARTICULAR PURPOSE.\n");
91 /**
92 * Main function of drill
93 * parse the arguments and prepare a query
95 int
96 main(int argc, char *argv[])
98 ldns_resolver *res = NULL;
99 ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */
100 ldns_rr_list *cmdline_rr_list = NULL;
101 ldns_rdf *cmdline_dname = NULL;
102 ldns_rdf *qname, *qname_tmp;
103 ldns_pkt *pkt;
104 ldns_pkt *qpkt;
105 char *serv;
106 const char *name;
107 char *name2;
108 char *progname;
109 char *query_file = NULL;
110 char *answer_file = NULL;
111 ldns_buffer *query_buffer = NULL;
112 ldns_rdf *serv_rdf;
113 ldns_rr_type type;
114 ldns_rr_class clas;
115 #if 0
116 ldns_pkt_opcode opcode = LDNS_PACKET_QUERY;
117 #endif
118 int i, c;
119 int int_type;
120 int int_clas;
121 int PURPOSE;
122 char *tsig_name = NULL;
123 char *tsig_data = NULL;
124 char *tsig_algorithm = NULL;
125 size_t tsig_separator;
126 size_t tsig_separator2;
127 ldns_rr *axfr_rr;
128 ldns_status status;
129 char *type_str;
131 /* list of keys used in dnssec operations */
132 ldns_rr_list *key_list = ldns_rr_list_new();
133 /* what key verify the current answer */
134 ldns_rr_list *key_verified;
136 /* resolver options */
137 uint16_t qflags;
138 uint16_t qbuf;
139 uint16_t qport;
140 uint8_t qfamily;
141 bool qdnssec;
142 bool qfallback;
143 bool qds;
144 bool qusevc;
145 bool qrandom;
147 char *resolv_conf_file = NULL;
149 ldns_rdf *trace_start_name = NULL;
151 int result = 0;
153 #ifdef USE_WINSOCK
154 int r;
155 WSADATA wsa_data;
156 #endif
158 int_type = -1; serv = NULL; type = 0;
159 int_clas = -1; name = NULL; clas = 0;
160 qname = NULL;
161 progname = strdup(argv[0]);
163 #ifdef USE_WINSOCK
164 r = WSAStartup(MAKEWORD(2,2), &wsa_data);
165 if(r != 0) {
166 printf("Failed WSAStartup: %d\n", r);
167 result = EXIT_FAILURE;
168 goto exit;
170 #endif /* USE_WINSOCK */
173 PURPOSE = DRILL_QUERY;
174 qflags = LDNS_RD;
175 qport = LDNS_PORT;
176 verbosity = 2;
177 qdnssec = false;
178 qfamily = LDNS_RESOLV_INETANY;
179 qfallback = false;
180 qds = false;
181 qbuf = 0;
182 qusevc = false;
183 qrandom = true;
184 key_verified = NULL;
186 ldns_init_random(NULL, 0);
188 if (argc == 0) {
189 usage(stdout, progname);
190 result = EXIT_FAILURE;
191 goto exit;
194 /* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */
195 /* global first, query opt next, option with parm's last
196 * and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
198 while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
199 switch(c) {
200 /* global options */
201 case '4':
202 qfamily = LDNS_RESOLV_INET;
203 break;
204 case '6':
205 qfamily = LDNS_RESOLV_INET6;
206 break;
207 case 'D':
208 qdnssec = true;
209 break;
210 case 'I':
211 /* reserved for backward compatibility */
212 break;
213 case 'T':
214 if (PURPOSE == DRILL_CHASE) {
215 fprintf(stderr, "-T and -S cannot be used at the same time.\n");
216 exit(EXIT_FAILURE);
218 PURPOSE = DRILL_TRACE;
219 break;
220 #ifdef HAVE_SSL
221 case 'S':
222 if (PURPOSE == DRILL_TRACE) {
223 fprintf(stderr, "-T and -S cannot be used at the same time.\n");
224 exit(EXIT_FAILURE);
226 PURPOSE = DRILL_CHASE;
227 break;
228 #endif /* HAVE_SSL */
229 case 'V':
230 if (strtok(optarg, "0123456789") != NULL) {
231 fprintf(stderr, "-V expects an number as an argument.\n");
232 exit(EXIT_FAILURE);
234 verbosity = atoi(optarg);
235 break;
236 case 'Q':
237 verbosity = -1;
238 break;
239 case 'f':
240 query_file = optarg;
241 break;
242 case 'i':
243 answer_file = optarg;
244 PURPOSE = DRILL_AFROMFILE;
245 break;
246 case 'w':
247 answer_file = optarg;
248 break;
249 case 'q':
250 query_file = optarg;
251 PURPOSE = DRILL_QTOFILE;
252 break;
253 case 'r':
254 if (global_dns_root) {
255 fprintf(stderr, "There was already a series of root servers set\n");
256 exit(EXIT_FAILURE);
258 global_dns_root = read_root_hints(optarg);
259 if (!global_dns_root) {
260 fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg);
261 exit(EXIT_FAILURE);
263 break;
264 /* query options */
265 case 'a':
266 qfallback = true;
267 break;
268 case 'b':
269 qbuf = (uint16_t)atoi(optarg);
270 if (qbuf == 0) {
271 error("%s", "<bufsize> could not be converted");
273 break;
274 case 'c':
275 resolv_conf_file = optarg;
276 break;
277 case 't':
278 qusevc = true;
279 break;
280 case 'k':
281 status = read_key_file(optarg,
282 key_list, false);
283 if (status != LDNS_STATUS_OK) {
284 error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status));
286 qdnssec = true; /* enable that too */
287 break;
288 case 'o':
289 /* only looks at the first hit: capital=ON, lowercase=OFF*/
290 if (strstr(optarg, "QR")) {
291 DRILL_ON(qflags, LDNS_QR);
293 if (strstr(optarg, "qr")) {
294 DRILL_OFF(qflags, LDNS_QR);
296 if (strstr(optarg, "AA")) {
297 DRILL_ON(qflags, LDNS_AA);
299 if (strstr(optarg, "aa")) {
300 DRILL_OFF(qflags, LDNS_AA);
302 if (strstr(optarg, "TC")) {
303 DRILL_ON(qflags, LDNS_TC);
305 if (strstr(optarg, "tc")) {
306 DRILL_OFF(qflags, LDNS_TC);
308 if (strstr(optarg, "RD")) {
309 DRILL_ON(qflags, LDNS_RD);
311 if (strstr(optarg, "rd")) {
312 DRILL_OFF(qflags, LDNS_RD);
314 if (strstr(optarg, "CD")) {
315 DRILL_ON(qflags, LDNS_CD);
317 if (strstr(optarg, "cd")) {
318 DRILL_OFF(qflags, LDNS_CD);
320 if (strstr(optarg, "RA")) {
321 DRILL_ON(qflags, LDNS_RA);
323 if (strstr(optarg, "ra")) {
324 DRILL_OFF(qflags, LDNS_RA);
326 if (strstr(optarg, "AD")) {
327 DRILL_ON(qflags, LDNS_AD);
329 if (strstr(optarg, "ad")) {
330 DRILL_OFF(qflags, LDNS_AD);
332 break;
333 case 'p':
334 qport = (uint16_t)atoi(optarg);
335 if (qport == 0) {
336 error("%s", "<port> could not be converted");
338 break;
339 case 's':
340 qds = true;
341 break;
342 case 'u':
343 qusevc = false;
344 break;
345 case 'v':
346 version(stdout, progname);
347 result = EXIT_SUCCESS;
348 goto exit;
349 case 'x':
350 PURPOSE = DRILL_REVERSE;
351 break;
352 case 'y':
353 #ifdef HAVE_SSL
354 if (strchr(optarg, ':')) {
355 tsig_separator = (size_t) (strchr(optarg, ':') - optarg);
356 if (strchr(optarg + tsig_separator + 1, ':')) {
357 tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg);
358 tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2);
359 strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2);
360 tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0';
361 } else {
362 tsig_separator2 = strlen(optarg);
363 tsig_algorithm = xmalloc(26);
364 strncpy(tsig_algorithm, "hmac-md5.sig-alg.reg.int.", 25);
365 tsig_algorithm[25] = '\0';
367 tsig_name = xmalloc(tsig_separator + 1);
368 tsig_data = xmalloc(tsig_separator2 - tsig_separator);
369 strncpy(tsig_name, optarg, tsig_separator);
370 strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1);
371 /* strncpy does not append \0 if source is longer than n */
372 tsig_name[tsig_separator] = '\0';
373 tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0';
375 #else
376 fprintf(stderr, "TSIG requested, but SSL is not supported\n");
377 result = EXIT_FAILURE;
378 goto exit;
379 #endif /* HAVE_SSL */
380 break;
381 case 'z':
382 qrandom = false;
383 break;
384 case 'd':
385 trace_start_name = ldns_dname_new_frm_str(optarg);
386 if (!trace_start_name) {
387 fprintf(stderr, "Unable to parse argument for -%c\n", c);
388 result = EXIT_FAILURE;
389 goto exit;
391 break;
392 case 'h':
393 version(stdout, progname);
394 usage(stdout, progname);
395 result = EXIT_SUCCESS;
396 goto exit;
397 break;
398 default:
399 fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c);
400 result = EXIT_FAILURE;
401 goto exit;
404 argc -= optind;
405 argv += optind;
407 if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) &&
408 ldns_rr_list_rr_count(key_list) == 0) {
410 (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true);
412 if (ldns_rr_list_rr_count(key_list) > 0) {
413 printf(";; Number of trusted keys: %d\n",
414 (int) ldns_rr_list_rr_count(key_list));
416 /* do a secure trace when requested */
417 if (PURPOSE == DRILL_TRACE && qdnssec) {
418 #ifdef HAVE_SSL
419 if (ldns_rr_list_rr_count(key_list) == 0) {
420 warning("%s", "No trusted keys were given. Will not be able to verify authenticity!");
422 PURPOSE = DRILL_SECTRACE;
423 #else
424 fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n");
425 exit(1);
426 #endif /* HAVE_SSL */
429 /* parse the arguments, with multiple arguments, the last argument
430 * found is used */
431 for(i = 0; i < argc; i++) {
433 /* if ^@ then it's a server */
434 if (argv[i][0] == '@') {
435 if (strlen(argv[i]) == 1) {
436 warning("%s", "No nameserver given");
437 exit(EXIT_FAILURE);
439 serv = argv[i] + 1;
440 continue;
442 /* if has a dot, it's a name */
443 if (strchr(argv[i], '.')) {
444 name = argv[i];
445 continue;
447 /* if it matches a type, it's a type */
448 if (int_type == -1) {
449 type = ldns_get_rr_type_by_name(argv[i]);
450 if (type != 0) {
451 int_type = 0;
452 continue;
455 /* if it matches a class, it's a class */
456 if (int_clas == -1) {
457 clas = ldns_get_rr_class_by_name(argv[i]);
458 if (clas != 0) {
459 int_clas = 0;
460 continue;
463 /* it all fails assume it's a name */
464 name = argv[i];
466 /* act like dig and use for . NS */
467 if (!name) {
468 name = ".";
469 int_type = 0;
470 type = LDNS_RR_TYPE_NS;
473 /* defaults if not given */
474 if (int_clas == -1) {
475 clas = LDNS_RR_CLASS_IN;
477 if (int_type == -1) {
478 if (PURPOSE != DRILL_REVERSE) {
479 type = LDNS_RR_TYPE_A;
480 } else {
481 type = LDNS_RR_TYPE_PTR;
485 /* set the nameserver to use */
486 if (!serv) {
487 /* no server given make a resolver from /etc/resolv.conf */
488 status = ldns_resolver_new_frm_file(&res, resolv_conf_file);
489 if (status != LDNS_STATUS_OK) {
490 warning("Could not create a resolver structure: %s (%s)\n"
491 "Try drill @localhost if you have a resolver running on your machine.",
492 ldns_get_errorstr_by_id(status), resolv_conf_file);
493 result = EXIT_FAILURE;
494 goto exit;
496 } else {
497 res = ldns_resolver_new();
498 if (!res || strlen(serv) <= 0) {
499 warning("Could not create a resolver structure");
500 result = EXIT_FAILURE;
501 goto exit;
503 /* add the nameserver */
504 serv_rdf = ldns_rdf_new_addr_frm_str(serv);
505 if (!serv_rdf) {
506 /* try to resolv the name if possible */
507 status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file);
509 if (status != LDNS_STATUS_OK) {
510 error("%s", "@server ip could not be converted");
512 ldns_resolver_set_dnssec(cmdline_res, qdnssec);
513 ldns_resolver_set_ip6(cmdline_res, qfamily);
514 ldns_resolver_set_fallback(cmdline_res, qfallback);
515 ldns_resolver_set_usevc(cmdline_res, qusevc);
517 cmdline_dname = ldns_dname_new_frm_str(serv);
519 cmdline_rr_list = ldns_get_rr_list_addr_by_name(
520 cmdline_res,
521 cmdline_dname,
522 LDNS_RR_CLASS_IN,
523 qflags);
524 ldns_rdf_deep_free(cmdline_dname);
525 if (!cmdline_rr_list) {
526 /* This error msg is not always accurate */
527 error("%s `%s\'", "could not find any address for the name:", serv);
528 } else {
529 if (ldns_resolver_push_nameserver_rr_list(
530 res,
531 cmdline_rr_list
532 ) != LDNS_STATUS_OK) {
533 error("%s", "pushing nameserver");
536 } else {
537 if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) {
538 error("%s", "pushing nameserver");
539 } else {
540 ldns_rdf_deep_free(serv_rdf);
544 /* set the resolver options */
545 ldns_resolver_set_port(res, qport);
546 if (verbosity >= 5) {
547 ldns_resolver_set_debug(res, true);
548 } else {
549 ldns_resolver_set_debug(res, false);
551 ldns_resolver_set_dnssec(res, qdnssec);
552 /* ldns_resolver_set_dnssec_cd(res, qdnssec);*/
553 ldns_resolver_set_ip6(res, qfamily);
554 ldns_resolver_set_fallback(res, qfallback);
555 ldns_resolver_set_usevc(res, qusevc);
556 ldns_resolver_set_random(res, qrandom);
557 if (qbuf != 0) {
558 ldns_resolver_set_edns_udp_size(res, qbuf);
561 if (!name &&
562 PURPOSE != DRILL_AFROMFILE &&
563 !query_file
565 usage(stdout, progname);
566 result = EXIT_FAILURE;
567 goto exit;
570 if (tsig_name && tsig_data) {
571 ldns_resolver_set_tsig_keyname(res, tsig_name);
572 ldns_resolver_set_tsig_keydata(res, tsig_data);
573 ldns_resolver_set_tsig_algorithm(res, tsig_algorithm);
576 /* main switching part of drill */
577 switch(PURPOSE) {
578 case DRILL_TRACE:
579 /* do a trace from the root down */
580 if (!global_dns_root) {
581 init_root();
583 qname = ldns_dname_new_frm_str(name);
584 if (!qname) {
585 error("%s", "parsing query name");
587 /* don't care about return packet */
588 (void)do_trace(res, qname, type, clas);
589 clear_root();
590 break;
591 case DRILL_SECTRACE:
592 /* do a secure trace from the root down */
593 if (!global_dns_root) {
594 init_root();
596 qname = ldns_dname_new_frm_str(name);
597 if (!qname) {
598 error("%s", "making qname");
600 /* don't care about return packet */
601 #ifdef HAVE_SSL
602 result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name);
603 #endif /* HAVE_SSL */
604 clear_root();
605 break;
606 case DRILL_CHASE:
607 qname = ldns_dname_new_frm_str(name);
608 if (!qname) {
609 error("%s", "making qname");
612 ldns_resolver_set_dnssec(res, true);
613 ldns_resolver_set_dnssec_cd(res, true);
614 /* set dnssec implies udp_size of 4096 */
615 ldns_resolver_set_edns_udp_size(res, 4096);
616 pkt = ldns_resolver_query(res, qname, type, clas, qflags);
618 if (!pkt) {
619 error("%s", "error pkt sending");
620 result = EXIT_FAILURE;
621 } else {
622 if (verbosity >= 3) {
623 ldns_pkt_print(stdout, pkt);
626 if (!ldns_pkt_answer(pkt)) {
627 mesg("No answer in packet");
628 } else {
629 #ifdef HAVE_SSL
630 ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list));
631 result = do_chase(res, qname, type,
632 clas, key_list,
633 pkt, qflags, NULL,
634 verbosity);
635 if (result == LDNS_STATUS_OK) {
636 if (verbosity != -1) {
637 mesg("Chase successful");
639 result = 0;
640 } else {
641 if (verbosity != -1) {
642 mesg("Chase failed.");
645 #endif /* HAVE_SSL */
647 ldns_pkt_free(pkt);
649 break;
650 case DRILL_AFROMFILE:
651 pkt = read_hex_pkt(answer_file);
652 if (pkt) {
653 if (verbosity != -1) {
654 ldns_pkt_print(stdout, pkt);
656 ldns_pkt_free(pkt);
659 break;
660 case DRILL_QTOFILE:
661 qname = ldns_dname_new_frm_str(name);
662 if (!qname) {
663 error("%s", "making qname");
666 status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags);
667 if(status != LDNS_STATUS_OK) {
668 error("%s", "making query: %s",
669 ldns_get_errorstr_by_id(status));
671 dump_hex(qpkt, query_file);
672 ldns_pkt_free(qpkt);
673 break;
674 case DRILL_NSEC:
675 break;
676 case DRILL_REVERSE:
677 /* ipv4 or ipv6 addr? */
678 if (strchr(name, ':')) {
679 if (strchr(name, '.')) {
680 error("Syntax error: both '.' and ':' seen in address\n");
682 name2 = malloc(IP6_ARPA_MAX_LEN + 20);
683 c = 0;
684 for (i=0; i<(int)strlen(name); i++) {
685 if (i >= IP6_ARPA_MAX_LEN) {
686 error("%s", "reverse argument to long");
688 if (name[i] == ':') {
689 if (i < (int) strlen(name) && name[i + 1] == ':') {
690 error("%s", ":: not supported (yet)");
691 } else {
692 if (i + 2 == (int) strlen(name) || name[i + 2] == ':') {
693 name2[c++] = '0';
694 name2[c++] = '.';
695 name2[c++] = '0';
696 name2[c++] = '.';
697 name2[c++] = '0';
698 name2[c++] = '.';
699 } else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') {
700 name2[c++] = '0';
701 name2[c++] = '.';
702 name2[c++] = '0';
703 name2[c++] = '.';
704 } else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') {
705 name2[c++] = '0';
706 name2[c++] = '.';
709 } else {
710 name2[c++] = name[i];
711 name2[c++] = '.';
714 name2[c++] = '\0';
716 qname = ldns_dname_new_frm_str(name2);
717 qname_tmp = ldns_dname_reverse(qname);
718 ldns_rdf_deep_free(qname);
719 qname = qname_tmp;
720 qname_tmp = ldns_dname_new_frm_str("ip6.arpa.");
721 status = ldns_dname_cat(qname, qname_tmp);
722 if (status != LDNS_STATUS_OK) {
723 error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status));
725 ldns_rdf_deep_free(qname_tmp);
727 free(name2);
728 } else {
729 qname = ldns_dname_new_frm_str(name);
730 qname_tmp = ldns_dname_reverse(qname);
731 ldns_rdf_deep_free(qname);
732 qname = qname_tmp;
733 qname_tmp = ldns_dname_new_frm_str("in-addr.arpa.");
734 status = ldns_dname_cat(qname, qname_tmp);
735 if (status != LDNS_STATUS_OK) {
736 error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status));
738 ldns_rdf_deep_free(qname_tmp);
740 if (!qname) {
741 error("%s", "-x implies an ip address");
744 /* create a packet and set the RD flag on it */
745 pkt = ldns_resolver_query(res, qname, type, clas, qflags);
746 if (!pkt) {
747 error("%s", "pkt sending");
748 result = EXIT_FAILURE;
749 } else {
750 if (verbosity != -1) {
751 ldns_pkt_print(stdout, pkt);
753 ldns_pkt_free(pkt);
755 break;
756 case DRILL_QUERY:
757 default:
758 if (query_file) {
759 /* this old way, the query packet needed
760 to be parseable, but we want to be able
761 to send mangled packets, so we need
762 to do it directly */
763 #if 0
764 qpkt = read_hex_pkt(query_file);
765 if (qpkt) {
766 status = ldns_resolver_send_pkt(&pkt, res, qpkt);
767 if (status != LDNS_STATUS_OK) {
768 printf("Error: %s\n", ldns_get_errorstr_by_id(status));
769 exit(1);
771 } else {
772 /* qpkt was bogus, reset pkt */
773 pkt = NULL;
775 #endif
776 query_buffer = read_hex_buffer(query_file);
777 if (query_buffer) {
778 status = ldns_send_buffer(&pkt, res, query_buffer, NULL);
779 ldns_buffer_free(query_buffer);
780 if (status != LDNS_STATUS_OK) {
781 printf("Error: %s\n", ldns_get_errorstr_by_id(status));
782 exit(1);
784 } else {
785 printf("NO BUFFER\n");
786 pkt = NULL;
788 } else {
789 qname = ldns_dname_new_frm_str(name);
790 if (!qname) {
791 error("%s", "error in making qname");
794 if (type == LDNS_RR_TYPE_AXFR) {
795 status = ldns_axfr_start(res, qname, clas);
796 if(status != LDNS_STATUS_OK) {
797 error("Error starting axfr: %s",
798 ldns_get_errorstr_by_id(status));
800 axfr_rr = ldns_axfr_next(res);
801 if(!axfr_rr) {
802 fprintf(stderr, "AXFR failed.\n");
803 ldns_pkt_print(stdout,
804 ldns_axfr_last_pkt(res));
805 goto exit;
807 while (axfr_rr) {
808 if (verbosity != -1) {
809 ldns_rr_print(stdout, axfr_rr);
811 ldns_rr_free(axfr_rr);
812 axfr_rr = ldns_axfr_next(res);
815 goto exit;
816 } else {
817 /* create a packet and set the RD flag on it */
818 pkt = ldns_resolver_query(res, qname, type, clas, qflags);
822 if (!pkt) {
823 mesg("No packet received");
824 result = EXIT_FAILURE;
825 } else {
826 if (verbosity != -1) {
827 ldns_pkt_print(stdout, pkt);
828 if (ldns_pkt_tc(pkt)) {
829 fprintf(stdout,
830 "\n;; WARNING: The answer packet was truncated; you might want to\n");
831 fprintf(stdout,
832 ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n");
835 if (qds) {
836 if (verbosity != -1) {
837 print_ds_of_keys(pkt);
838 printf("\n");
842 if (ldns_rr_list_rr_count(key_list) > 0) {
843 /* -k's were given on the cmd line */
844 ldns_rr_list *rrset_verified;
845 uint16_t key_count;
847 rrset_verified = ldns_pkt_rr_list_by_name_and_type(
848 pkt, qname, type,
849 LDNS_SECTION_ANY_NOQUESTION);
851 if (type == LDNS_RR_TYPE_ANY) {
852 /* don't verify this */
853 break;
856 if (verbosity != -1) {
857 printf("; ");
858 ldns_rr_list_print(stdout, rrset_verified);
861 /* verify */
862 #ifdef HAVE_SSL
863 key_verified = ldns_rr_list_new();
864 result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified);
866 if (result == LDNS_STATUS_ERR) {
867 /* is the existence denied then? */
868 result = ldns_verify_denial(pkt, qname, type, NULL, NULL);
869 if (result == LDNS_STATUS_OK) {
870 if (verbosity != -1) {
871 printf("Existence denied for ");
872 ldns_rdf_print(stdout, qname);
873 type_str = ldns_rr_type2str(type);
874 printf("\t%s\n", type_str);
875 LDNS_FREE(type_str);
877 } else {
878 if (verbosity != -1) {
879 printf("Bad data; RR for name and "
880 "type not found or failed to "
881 "verify, and denial of "
882 "existence failed.\n");
885 } else if (result == LDNS_STATUS_OK) {
886 for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified);
887 key_count++) {
888 if (verbosity != -1) {
889 printf("; VALIDATED by id = %u, owner = ",
890 (unsigned int)ldns_calc_keytag(
891 ldns_rr_list_rr(key_verified, key_count)));
892 ldns_rdf_print(stdout, ldns_rr_owner(
893 ldns_rr_list_rr(key_list, key_count)));
894 printf("\n");
897 } else {
898 for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list);
899 key_count++) {
900 if (verbosity != -1) {
901 printf("; %s for id = %u, owner = ",
902 ldns_get_errorstr_by_id(result),
903 (unsigned int)ldns_calc_keytag(
904 ldns_rr_list_rr(key_list, key_count)));
905 ldns_rdf_print(stdout, ldns_rr_owner(
907 ldns_rr_list_rr(key_list,
908 key_count)));
909 printf("\n");
913 ldns_rr_list_free(key_verified);
914 #else
915 (void) key_count;
916 #endif /* HAVE_SSL */
918 if (answer_file) {
919 dump_hex(pkt, answer_file);
921 ldns_pkt_free(pkt);
924 break;
927 exit:
928 ldns_rdf_deep_free(qname);
929 ldns_resolver_deep_free(res);
930 ldns_resolver_deep_free(cmdline_res);
931 ldns_rr_list_deep_free(key_list);
932 ldns_rr_list_deep_free(cmdline_rr_list);
933 ldns_rdf_deep_free(trace_start_name);
934 xfree(progname);
935 xfree(tsig_name);
936 xfree(tsig_data);
937 xfree(tsig_algorithm);
939 #ifdef HAVE_SSL
940 ERR_remove_state(0);
941 CRYPTO_cleanup_all_ex_data();
942 ERR_free_strings();
943 EVP_cleanup();
944 #endif
945 #ifdef USE_WINSOCK
946 WSACleanup();
947 #endif
949 return result;