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 #define IP6_ARPA_MAX_LEN 65 18 19 /* query debug, 2 hex dumps */ 20 int verbosity; 21 22 static void 23 usage(FILE *stream, const char *progname) 24 { 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"); 74 } 75 76 /** 77 * Prints the drill version to stderr 78 */ 79 static void 80 version(FILE *stream, const char *progname) 81 { 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"); 88 } 89 90 91 /** 92 * Main function of drill 93 * parse the arguments and prepare a query 94 */ 95 int 96 main(int argc, char *argv[]) 97 { 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; 130 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; 135 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; 146 147 char *resolv_conf_file = NULL; 148 149 ldns_rdf *trace_start_name = NULL; 150 151 int result = 0; 152 153 #ifdef USE_WINSOCK 154 int r; 155 WSADATA wsa_data; 156 #endif 157 158 int_type = -1; serv = NULL; type = 0; 159 int_clas = -1; name = NULL; clas = 0; 160 qname = NULL; 161 progname = strdup(argv[0]); 162 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; 169 } 170 #endif /* USE_WINSOCK */ 171 172 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; 185 186 ldns_init_random(NULL, 0); 187 188 if (argc == 0) { 189 usage(stdout, progname); 190 result = EXIT_FAILURE; 191 goto exit; 192 } 193 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:" */ 197 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); 217 } 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); 225 } 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); 233 } 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); 257 } 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); 262 } 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"); 272 } 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)); 285 } 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); 292 } 293 if (strstr(optarg, "qr")) { 294 DRILL_OFF(qflags, LDNS_QR); 295 } 296 if (strstr(optarg, "AA")) { 297 DRILL_ON(qflags, LDNS_AA); 298 } 299 if (strstr(optarg, "aa")) { 300 DRILL_OFF(qflags, LDNS_AA); 301 } 302 if (strstr(optarg, "TC")) { 303 DRILL_ON(qflags, LDNS_TC); 304 } 305 if (strstr(optarg, "tc")) { 306 DRILL_OFF(qflags, LDNS_TC); 307 } 308 if (strstr(optarg, "RD")) { 309 DRILL_ON(qflags, LDNS_RD); 310 } 311 if (strstr(optarg, "rd")) { 312 DRILL_OFF(qflags, LDNS_RD); 313 } 314 if (strstr(optarg, "CD")) { 315 DRILL_ON(qflags, LDNS_CD); 316 } 317 if (strstr(optarg, "cd")) { 318 DRILL_OFF(qflags, LDNS_CD); 319 } 320 if (strstr(optarg, "RA")) { 321 DRILL_ON(qflags, LDNS_RA); 322 } 323 if (strstr(optarg, "ra")) { 324 DRILL_OFF(qflags, LDNS_RA); 325 } 326 if (strstr(optarg, "AD")) { 327 DRILL_ON(qflags, LDNS_AD); 328 } 329 if (strstr(optarg, "ad")) { 330 DRILL_OFF(qflags, LDNS_AD); 331 } 332 break; 333 case 'p': 334 qport = (uint16_t)atoi(optarg); 335 if (qport == 0) { 336 error("%s", "<port> could not be converted"); 337 } 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'; 366 } 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'; 374 } 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; 390 } 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; 402 } 403 } 404 argc -= optind; 405 argv += optind; 406 407 if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && 408 ldns_rr_list_rr_count(key_list) == 0) { 409 410 (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); 411 } 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)); 415 } 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!"); 421 } 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 */ 427 } 428 429 /* parse the arguments, with multiple arguments, the last argument 430 * found is used */ 431 for(i = 0; i < argc; i++) { 432 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); 438 } 439 serv = argv[i] + 1; 440 continue; 441 } 442 /* if has a dot, it's a name */ 443 if (strchr(argv[i], '.')) { 444 name = argv[i]; 445 continue; 446 } 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; 453 } 454 } 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; 461 } 462 } 463 /* it all fails assume it's a name */ 464 name = argv[i]; 465 } 466 /* act like dig and use for . NS */ 467 if (!name) { 468 name = "."; 469 int_type = 0; 470 type = LDNS_RR_TYPE_NS; 471 } 472 473 /* defaults if not given */ 474 if (int_clas == -1) { 475 clas = LDNS_RR_CLASS_IN; 476 } 477 if (int_type == -1) { 478 if (PURPOSE != DRILL_REVERSE) { 479 type = LDNS_RR_TYPE_A; 480 } else { 481 type = LDNS_RR_TYPE_PTR; 482 } 483 } 484 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; 495 } 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; 502 } 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); 508 509 if (status != LDNS_STATUS_OK) { 510 error("%s", "@server ip could not be converted"); 511 } 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); 516 517 cmdline_dname = ldns_dname_new_frm_str(serv); 518 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"); 534 } 535 } 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); 541 } 542 } 543 } 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); 550 } 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); 559 } 560 561 if (!name && 562 PURPOSE != DRILL_AFROMFILE && 563 !query_file 564 ) { 565 usage(stdout, progname); 566 result = EXIT_FAILURE; 567 goto exit; 568 } 569 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); 574 } 575 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(); 582 } 583 qname = ldns_dname_new_frm_str(name); 584 if (!qname) { 585 error("%s", "parsing query name"); 586 } 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(); 595 } 596 qname = ldns_dname_new_frm_str(name); 597 if (!qname) { 598 error("%s", "making qname"); 599 } 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"); 610 } 611 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); 617 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); 624 } 625 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"); 638 } 639 result = 0; 640 } else { 641 if (verbosity != -1) { 642 mesg("Chase failed."); 643 } 644 } 645 #endif /* HAVE_SSL */ 646 } 647 ldns_pkt_free(pkt); 648 } 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); 655 } 656 ldns_pkt_free(pkt); 657 } 658 659 break; 660 case DRILL_QTOFILE: 661 qname = ldns_dname_new_frm_str(name); 662 if (!qname) { 663 error("%s", "making qname"); 664 } 665 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)); 670 } 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"); 681 } 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"); 687 } 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++] = '.'; 707 } 708 } 709 } else { 710 name2[c++] = name[i]; 711 name2[c++] = '.'; 712 } 713 } 714 name2[c++] = '\0'; 715 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)); 724 } 725 ldns_rdf_deep_free(qname_tmp); 726 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)); 737 } 738 ldns_rdf_deep_free(qname_tmp); 739 } 740 if (!qname) { 741 error("%s", "-x implies an ip address"); 742 } 743 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); 752 } 753 ldns_pkt_free(pkt); 754 } 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); 770 } 771 } else { 772 /* qpkt was bogus, reset pkt */ 773 pkt = NULL; 774 } 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); 783 } 784 } else { 785 printf("NO BUFFER\n"); 786 pkt = NULL; 787 } 788 } else { 789 qname = ldns_dname_new_frm_str(name); 790 if (!qname) { 791 error("%s", "error in making qname"); 792 } 793 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)); 799 } 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; 806 } 807 while (axfr_rr) { 808 if (verbosity != -1) { 809 ldns_rr_print(stdout, axfr_rr); 810 } 811 ldns_rr_free(axfr_rr); 812 axfr_rr = ldns_axfr_next(res); 813 } 814 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); 819 } 820 } 821 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"); 833 } 834 } 835 if (qds) { 836 if (verbosity != -1) { 837 print_ds_of_keys(pkt); 838 printf("\n"); 839 } 840 } 841 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; 846 847 rrset_verified = ldns_pkt_rr_list_by_name_and_type( 848 pkt, qname, type, 849 LDNS_SECTION_ANY_NOQUESTION); 850 851 if (type == LDNS_RR_TYPE_ANY) { 852 /* don't verify this */ 853 break; 854 } 855 856 if (verbosity != -1) { 857 printf("; "); 858 ldns_rr_list_print(stdout, rrset_verified); 859 } 860 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); 865 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); 876 } 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"); 883 } 884 } 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"); 895 } 896 } 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( 906 907 ldns_rr_list_rr(key_list, 908 key_count))); 909 printf("\n"); 910 } 911 } 912 } 913 ldns_rr_list_free(key_verified); 914 #else 915 (void) key_count; 916 #endif /* HAVE_SSL */ 917 } 918 if (answer_file) { 919 dump_hex(pkt, answer_file); 920 } 921 ldns_pkt_free(pkt); 922 } 923 924 break; 925 } 926 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); 938 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 948 949 return result; 950 } 951