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