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