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