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