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