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 = strdup("hmac-md5.sig-alg.reg.int"); 364 } 365 tsig_name = xmalloc(tsig_separator + 1); 366 tsig_data = xmalloc(tsig_separator2 - tsig_separator); 367 strncpy(tsig_name, optarg, tsig_separator); 368 strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1); 369 /* strncpy does not append \0 if source is longer than n */ 370 tsig_name[tsig_separator] = '\0'; 371 tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0'; 372 } 373 #else 374 fprintf(stderr, "TSIG requested, but SSL is not supported\n"); 375 result = EXIT_FAILURE; 376 goto exit; 377 #endif /* HAVE_SSL */ 378 break; 379 case 'z': 380 qrandom = false; 381 break; 382 case 'd': 383 trace_start_name = ldns_dname_new_frm_str(optarg); 384 if (!trace_start_name) { 385 fprintf(stderr, "Unable to parse argument for -%c\n", c); 386 result = EXIT_FAILURE; 387 goto exit; 388 } 389 break; 390 case 'h': 391 version(stdout, progname); 392 usage(stdout, progname); 393 result = EXIT_SUCCESS; 394 goto exit; 395 break; 396 default: 397 fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c); 398 result = EXIT_FAILURE; 399 goto exit; 400 } 401 } 402 argc -= optind; 403 argv += optind; 404 405 if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && 406 ldns_rr_list_rr_count(key_list) == 0) { 407 408 (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); 409 } 410 if (ldns_rr_list_rr_count(key_list) > 0) { 411 printf(";; Number of trusted keys: %d\n", 412 (int) ldns_rr_list_rr_count(key_list)); 413 } 414 /* do a secure trace when requested */ 415 if (PURPOSE == DRILL_TRACE && qdnssec) { 416 #ifdef HAVE_SSL 417 if (ldns_rr_list_rr_count(key_list) == 0) { 418 warning("%s", "No trusted keys were given. Will not be able to verify authenticity!"); 419 } 420 PURPOSE = DRILL_SECTRACE; 421 #else 422 fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n"); 423 exit(1); 424 #endif /* HAVE_SSL */ 425 } 426 427 /* parse the arguments, with multiple arguments, the last argument 428 * found is used */ 429 for(i = 0; i < argc; i++) { 430 431 /* if ^@ then it's a server */ 432 if (argv[i][0] == '@') { 433 if (strlen(argv[i]) == 1) { 434 warning("%s", "No nameserver given"); 435 exit(EXIT_FAILURE); 436 } 437 serv = argv[i] + 1; 438 continue; 439 } 440 /* if has a dot, it's a name */ 441 if (strchr(argv[i], '.')) { 442 name = argv[i]; 443 continue; 444 } 445 /* if it matches a type, it's a type */ 446 if (int_type == -1) { 447 type = ldns_get_rr_type_by_name(argv[i]); 448 if (type != 0) { 449 int_type = 0; 450 continue; 451 } 452 } 453 /* if it matches a class, it's a class */ 454 if (int_clas == -1) { 455 clas = ldns_get_rr_class_by_name(argv[i]); 456 if (clas != 0) { 457 int_clas = 0; 458 continue; 459 } 460 } 461 /* it all fails assume it's a name */ 462 name = argv[i]; 463 } 464 /* act like dig and use for . NS */ 465 if (!name) { 466 name = "."; 467 int_type = 0; 468 type = LDNS_RR_TYPE_NS; 469 } 470 471 /* defaults if not given */ 472 if (int_clas == -1) { 473 clas = LDNS_RR_CLASS_IN; 474 } 475 if (int_type == -1) { 476 if (PURPOSE != DRILL_REVERSE) { 477 type = LDNS_RR_TYPE_A; 478 } else { 479 type = LDNS_RR_TYPE_PTR; 480 } 481 } 482 483 /* set the nameserver to use */ 484 if (!serv) { 485 /* no server given make a resolver from /etc/resolv.conf */ 486 status = ldns_resolver_new_frm_file(&res, resolv_conf_file); 487 if (status != LDNS_STATUS_OK) { 488 warning("Could not create a resolver structure: %s (%s)\n" 489 "Try drill @localhost if you have a resolver running on your machine.", 490 ldns_get_errorstr_by_id(status), resolv_conf_file); 491 result = EXIT_FAILURE; 492 goto exit; 493 } 494 } else { 495 res = ldns_resolver_new(); 496 if (!res || strlen(serv) <= 0) { 497 warning("Could not create a resolver structure"); 498 result = EXIT_FAILURE; 499 goto exit; 500 } 501 /* add the nameserver */ 502 serv_rdf = ldns_rdf_new_addr_frm_str(serv); 503 if (!serv_rdf) { 504 /* try to resolv the name if possible */ 505 status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file); 506 507 if (status != LDNS_STATUS_OK) { 508 error("%s", "@server ip could not be converted"); 509 } 510 ldns_resolver_set_dnssec(cmdline_res, qdnssec); 511 ldns_resolver_set_ip6(cmdline_res, qfamily); 512 ldns_resolver_set_fallback(cmdline_res, qfallback); 513 ldns_resolver_set_usevc(cmdline_res, qusevc); 514 515 cmdline_dname = ldns_dname_new_frm_str(serv); 516 517 cmdline_rr_list = ldns_get_rr_list_addr_by_name( 518 cmdline_res, 519 cmdline_dname, 520 LDNS_RR_CLASS_IN, 521 qflags); 522 ldns_rdf_deep_free(cmdline_dname); 523 if (!cmdline_rr_list) { 524 /* This error msg is not always accurate */ 525 error("%s `%s\'", "could not find any address for the name:", serv); 526 } else { 527 if (ldns_resolver_push_nameserver_rr_list( 528 res, 529 cmdline_rr_list 530 ) != LDNS_STATUS_OK) { 531 error("%s", "pushing nameserver"); 532 } 533 } 534 } else { 535 if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) { 536 error("%s", "pushing nameserver"); 537 } else { 538 ldns_rdf_deep_free(serv_rdf); 539 } 540 } 541 } 542 /* set the resolver options */ 543 ldns_resolver_set_port(res, qport); 544 if (verbosity >= 5) { 545 ldns_resolver_set_debug(res, true); 546 } else { 547 ldns_resolver_set_debug(res, false); 548 } 549 ldns_resolver_set_dnssec(res, qdnssec); 550 /* ldns_resolver_set_dnssec_cd(res, qdnssec);*/ 551 ldns_resolver_set_ip6(res, qfamily); 552 ldns_resolver_set_fallback(res, qfallback); 553 ldns_resolver_set_usevc(res, qusevc); 554 ldns_resolver_set_random(res, qrandom); 555 if (qbuf != 0) { 556 ldns_resolver_set_edns_udp_size(res, qbuf); 557 } 558 559 if (!name && 560 PURPOSE != DRILL_AFROMFILE && 561 !query_file 562 ) { 563 usage(stdout, progname); 564 result = EXIT_FAILURE; 565 goto exit; 566 } 567 568 if (tsig_name && tsig_data) { 569 ldns_resolver_set_tsig_keyname(res, tsig_name); 570 ldns_resolver_set_tsig_keydata(res, tsig_data); 571 ldns_resolver_set_tsig_algorithm(res, tsig_algorithm); 572 } 573 574 /* main switching part of drill */ 575 switch(PURPOSE) { 576 case DRILL_TRACE: 577 /* do a trace from the root down */ 578 if (!global_dns_root) { 579 init_root(); 580 } 581 qname = ldns_dname_new_frm_str(name); 582 if (!qname) { 583 error("%s", "parsing query name"); 584 } 585 /* don't care about return packet */ 586 (void)do_trace(res, qname, type, clas); 587 clear_root(); 588 break; 589 case DRILL_SECTRACE: 590 /* do a secure trace from the root down */ 591 if (!global_dns_root) { 592 init_root(); 593 } 594 qname = ldns_dname_new_frm_str(name); 595 if (!qname) { 596 error("%s", "making qname"); 597 } 598 /* don't care about return packet */ 599 #ifdef HAVE_SSL 600 result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name); 601 #endif /* HAVE_SSL */ 602 clear_root(); 603 break; 604 case DRILL_CHASE: 605 qname = ldns_dname_new_frm_str(name); 606 if (!qname) { 607 error("%s", "making qname"); 608 } 609 610 ldns_resolver_set_dnssec(res, true); 611 ldns_resolver_set_dnssec_cd(res, true); 612 /* set dnssec implies udp_size of 4096 */ 613 ldns_resolver_set_edns_udp_size(res, 4096); 614 pkt = ldns_resolver_query(res, qname, type, clas, qflags); 615 616 if (!pkt) { 617 error("%s", "error pkt sending"); 618 result = EXIT_FAILURE; 619 } else { 620 if (verbosity >= 3) { 621 ldns_pkt_print(stdout, pkt); 622 } 623 624 if (!ldns_pkt_answer(pkt)) { 625 mesg("No answer in packet"); 626 } else { 627 #ifdef HAVE_SSL 628 ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list)); 629 result = do_chase(res, qname, type, 630 clas, key_list, 631 pkt, qflags, NULL, 632 verbosity); 633 if (result == LDNS_STATUS_OK) { 634 if (verbosity != -1) { 635 mesg("Chase successful"); 636 } 637 result = 0; 638 } else { 639 if (verbosity != -1) { 640 mesg("Chase failed."); 641 } 642 } 643 #endif /* HAVE_SSL */ 644 } 645 ldns_pkt_free(pkt); 646 } 647 break; 648 case DRILL_AFROMFILE: 649 pkt = read_hex_pkt(answer_file); 650 if (pkt) { 651 if (verbosity != -1) { 652 ldns_pkt_print(stdout, pkt); 653 } 654 ldns_pkt_free(pkt); 655 } 656 657 break; 658 case DRILL_QTOFILE: 659 qname = ldns_dname_new_frm_str(name); 660 if (!qname) { 661 error("%s", "making qname"); 662 } 663 664 status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags); 665 if(status != LDNS_STATUS_OK) { 666 error("%s", "making query: %s", 667 ldns_get_errorstr_by_id(status)); 668 } 669 dump_hex(qpkt, query_file); 670 ldns_pkt_free(qpkt); 671 break; 672 case DRILL_NSEC: 673 break; 674 case DRILL_REVERSE: 675 /* ipv4 or ipv6 addr? */ 676 if (strchr(name, ':')) { 677 if (strchr(name, '.')) { 678 error("Syntax error: both '.' and ':' seen in address\n"); 679 } 680 name2 = malloc(IP6_ARPA_MAX_LEN + 20); 681 c = 0; 682 for (i=0; i<(int)strlen(name); i++) { 683 if (i >= IP6_ARPA_MAX_LEN) { 684 error("%s", "reverse argument to long"); 685 } 686 if (name[i] == ':') { 687 if (i < (int) strlen(name) && name[i + 1] == ':') { 688 error("%s", ":: not supported (yet)"); 689 } else { 690 if (i + 2 == (int) strlen(name) || name[i + 2] == ':') { 691 name2[c++] = '0'; 692 name2[c++] = '.'; 693 name2[c++] = '0'; 694 name2[c++] = '.'; 695 name2[c++] = '0'; 696 name2[c++] = '.'; 697 } else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') { 698 name2[c++] = '0'; 699 name2[c++] = '.'; 700 name2[c++] = '0'; 701 name2[c++] = '.'; 702 } else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') { 703 name2[c++] = '0'; 704 name2[c++] = '.'; 705 } 706 } 707 } else { 708 name2[c++] = name[i]; 709 name2[c++] = '.'; 710 } 711 } 712 name2[c++] = '\0'; 713 714 qname = ldns_dname_new_frm_str(name2); 715 qname_tmp = ldns_dname_reverse(qname); 716 ldns_rdf_deep_free(qname); 717 qname = qname_tmp; 718 qname_tmp = ldns_dname_new_frm_str("ip6.arpa."); 719 status = ldns_dname_cat(qname, qname_tmp); 720 if (status != LDNS_STATUS_OK) { 721 error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status)); 722 } 723 ldns_rdf_deep_free(qname_tmp); 724 725 free(name2); 726 } else { 727 qname = ldns_dname_new_frm_str(name); 728 qname_tmp = ldns_dname_reverse(qname); 729 ldns_rdf_deep_free(qname); 730 qname = qname_tmp; 731 qname_tmp = ldns_dname_new_frm_str("in-addr.arpa."); 732 status = ldns_dname_cat(qname, qname_tmp); 733 if (status != LDNS_STATUS_OK) { 734 error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status)); 735 } 736 ldns_rdf_deep_free(qname_tmp); 737 } 738 if (!qname) { 739 error("%s", "-x implies an ip address"); 740 } 741 742 /* create a packet and set the RD flag on it */ 743 pkt = ldns_resolver_query(res, qname, type, clas, qflags); 744 if (!pkt) { 745 error("%s", "pkt sending"); 746 result = EXIT_FAILURE; 747 } else { 748 if (verbosity != -1) { 749 ldns_pkt_print(stdout, pkt); 750 } 751 ldns_pkt_free(pkt); 752 } 753 break; 754 case DRILL_QUERY: 755 default: 756 if (query_file) { 757 /* this old way, the query packet needed 758 to be parseable, but we want to be able 759 to send mangled packets, so we need 760 to do it directly */ 761 #if 0 762 qpkt = read_hex_pkt(query_file); 763 if (qpkt) { 764 status = ldns_resolver_send_pkt(&pkt, res, qpkt); 765 if (status != LDNS_STATUS_OK) { 766 printf("Error: %s\n", ldns_get_errorstr_by_id(status)); 767 exit(1); 768 } 769 } else { 770 /* qpkt was bogus, reset pkt */ 771 pkt = NULL; 772 } 773 #endif 774 query_buffer = read_hex_buffer(query_file); 775 if (query_buffer) { 776 status = ldns_send_buffer(&pkt, res, query_buffer, NULL); 777 ldns_buffer_free(query_buffer); 778 if (status != LDNS_STATUS_OK) { 779 printf("Error: %s\n", ldns_get_errorstr_by_id(status)); 780 exit(1); 781 } 782 } else { 783 printf("NO BUFFER\n"); 784 pkt = NULL; 785 } 786 } else { 787 qname = ldns_dname_new_frm_str(name); 788 if (!qname) { 789 error("%s", "error in making qname"); 790 } 791 792 if (type == LDNS_RR_TYPE_AXFR) { 793 status = ldns_axfr_start(res, qname, clas); 794 if(status != LDNS_STATUS_OK) { 795 error("Error starting axfr: %s", 796 ldns_get_errorstr_by_id(status)); 797 } 798 axfr_rr = ldns_axfr_next(res); 799 if(!axfr_rr) { 800 fprintf(stderr, "AXFR failed.\n"); 801 ldns_pkt_print(stdout, 802 ldns_axfr_last_pkt(res)); 803 goto exit; 804 } 805 while (axfr_rr) { 806 if (verbosity != -1) { 807 ldns_rr_print(stdout, axfr_rr); 808 } 809 ldns_rr_free(axfr_rr); 810 axfr_rr = ldns_axfr_next(res); 811 } 812 813 goto exit; 814 } else { 815 /* create a packet and set the RD flag on it */ 816 pkt = ldns_resolver_query(res, qname, type, clas, qflags); 817 } 818 } 819 820 if (!pkt) { 821 mesg("No packet received"); 822 result = EXIT_FAILURE; 823 } else { 824 if (verbosity != -1) { 825 ldns_pkt_print(stdout, pkt); 826 if (ldns_pkt_tc(pkt)) { 827 fprintf(stdout, 828 "\n;; WARNING: The answer packet was truncated; you might want to\n"); 829 fprintf(stdout, 830 ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n"); 831 } 832 } 833 if (qds) { 834 if (verbosity != -1) { 835 print_ds_of_keys(pkt); 836 printf("\n"); 837 } 838 } 839 840 if (ldns_rr_list_rr_count(key_list) > 0) { 841 /* -k's were given on the cmd line */ 842 ldns_rr_list *rrset_verified; 843 uint16_t key_count; 844 845 rrset_verified = ldns_pkt_rr_list_by_name_and_type( 846 pkt, qname, type, 847 LDNS_SECTION_ANY_NOQUESTION); 848 849 if (type == LDNS_RR_TYPE_ANY) { 850 /* don't verify this */ 851 break; 852 } 853 854 if (verbosity != -1) { 855 printf("; "); 856 ldns_rr_list_print(stdout, rrset_verified); 857 } 858 859 /* verify */ 860 #ifdef HAVE_SSL 861 key_verified = ldns_rr_list_new(); 862 result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified); 863 864 if (result == LDNS_STATUS_ERR) { 865 /* is the existence denied then? */ 866 result = ldns_verify_denial(pkt, qname, type, NULL, NULL); 867 if (result == LDNS_STATUS_OK) { 868 if (verbosity != -1) { 869 printf("Existence denied for "); 870 ldns_rdf_print(stdout, qname); 871 type_str = ldns_rr_type2str(type); 872 printf("\t%s\n", type_str); 873 LDNS_FREE(type_str); 874 } 875 } else { 876 if (verbosity != -1) { 877 printf("Bad data; RR for name and " 878 "type not found or failed to " 879 "verify, and denial of " 880 "existence failed.\n"); 881 } 882 } 883 } else if (result == LDNS_STATUS_OK) { 884 for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified); 885 key_count++) { 886 if (verbosity != -1) { 887 printf("; VALIDATED by id = %u, owner = ", 888 (unsigned int)ldns_calc_keytag( 889 ldns_rr_list_rr(key_verified, key_count))); 890 ldns_rdf_print(stdout, ldns_rr_owner( 891 ldns_rr_list_rr(key_list, key_count))); 892 printf("\n"); 893 } 894 } 895 } else { 896 for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list); 897 key_count++) { 898 if (verbosity != -1) { 899 printf("; %s for id = %u, owner = ", 900 ldns_get_errorstr_by_id(result), 901 (unsigned int)ldns_calc_keytag( 902 ldns_rr_list_rr(key_list, key_count))); 903 ldns_rdf_print(stdout, ldns_rr_owner( 904 905 ldns_rr_list_rr(key_list, 906 key_count))); 907 printf("\n"); 908 } 909 } 910 } 911 ldns_rr_list_free(key_verified); 912 #else 913 (void) key_count; 914 #endif /* HAVE_SSL */ 915 } 916 if (answer_file) { 917 dump_hex(pkt, answer_file); 918 } 919 ldns_pkt_free(pkt); 920 } 921 922 break; 923 } 924 925 exit: 926 ldns_rdf_deep_free(qname); 927 ldns_resolver_deep_free(res); 928 ldns_resolver_deep_free(cmdline_res); 929 ldns_rr_list_deep_free(key_list); 930 ldns_rr_list_deep_free(cmdline_rr_list); 931 ldns_rdf_deep_free(trace_start_name); 932 xfree(progname); 933 xfree(tsig_name); 934 xfree(tsig_data); 935 xfree(tsig_algorithm); 936 937 #ifdef HAVE_SSL 938 ERR_remove_state(0); 939 CRYPTO_cleanup_all_ex_data(); 940 ERR_free_strings(); 941 EVP_cleanup(); 942 #endif 943 #ifdef USE_WINSOCK 944 WSACleanup(); 945 #endif 946 947 return result; 948 } 949