1 /*- 2 * (c) Magerya Vitaly 3 * 4 * Copying and distribution of this file, with or without modification, 5 * are permitted in any medium without royalty provided the copyright 6 * notice and this notice are preserved. This file is offered as-is, 7 * without any warranty. 8 */ 9 10 #include <ldns/ldns.h> 11 #include <limits.h> 12 #include <netdb.h> 13 #include <netinet/in.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <unistd.h> 17 18 /* General utilities. 19 */ 20 21 static char *progname; 22 23 #define countof(array) (sizeof(array)/sizeof(*(array))) 24 25 static void 26 die(int code, const char *fmt, ...) { 27 va_list args; 28 29 va_start(args, fmt); 30 fprintf(stderr, "%s: ", progname); 31 vfprintf(stderr, fmt, args); 32 fprintf(stderr, "\n"); 33 va_end(args); 34 exit(code); 35 } 36 37 static int 38 ndots(const char *name) { 39 int n; 40 41 for (n = 0; (name = strchr(name, '.')); n++, name++); 42 return n; 43 } 44 45 /* General LDNS-specific utilities. 46 */ 47 48 static ldns_status 49 ldns_resolver_new_default(ldns_resolver **res) { 50 if (ldns_resolver_new_frm_file(res, NULL) == LDNS_STATUS_OK || 51 (*res = ldns_resolver_new()) != NULL) 52 return LDNS_STATUS_OK; 53 return LDNS_STATUS_MEM_ERR; 54 } 55 56 static ldns_status 57 ldns_resolver_push_default_servers(ldns_resolver *res) { 58 ldns_status status; 59 ldns_rdf *addr; 60 61 if ((status = ldns_str2rdf_a(&addr, "127.0.0.1")) != LDNS_STATUS_OK || 62 (status = ldns_resolver_push_nameserver(res, addr)) != LDNS_STATUS_OK) 63 return ldns_rdf_deep_free(addr), status; 64 ldns_rdf_deep_free(addr); 65 if ((status = ldns_str2rdf_aaaa(&addr, "::1")) != LDNS_STATUS_OK || 66 (status = ldns_resolver_push_nameserver(res, addr)) != LDNS_STATUS_OK) 67 return ldns_rdf_deep_free(addr), status; 68 ldns_rdf_deep_free(addr); 69 return LDNS_STATUS_OK; 70 } 71 72 static ldns_rdf * 73 ldns_rdf_new_addr_frm_str(const char *str) { 74 ldns_rdf *addr; 75 76 if ((addr = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str)) == NULL) 77 addr = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str); 78 return addr; 79 } 80 81 static void 82 ldns_resolver_remove_nameservers(ldns_resolver *res) { 83 while (ldns_resolver_nameserver_count(res) > 0) 84 ldns_rdf_deep_free(ldns_resolver_pop_nameserver(res)); 85 } 86 87 static ldns_rdf * 88 ldns_rdf_reverse_a(ldns_rdf *addr, const char *base) { 89 char *buf; 90 int i, len; 91 92 len = strlen(base); 93 buf = alloca(LDNS_IP4ADDRLEN*4 + len + 1); 94 for (len = i = 0; i < LDNS_IP4ADDRLEN; i++) 95 len += sprintf(&buf[len], "%d.", 96 (int)ldns_rdf_data(addr)[LDNS_IP4ADDRLEN - i - 1]); 97 sprintf(&buf[len], "%s", base); 98 return ldns_dname_new_frm_str(buf); 99 } 100 101 static ldns_rdf * 102 ldns_rdf_reverse_aaaa(ldns_rdf *addr, const char *base) { 103 char *buf; 104 int i, len; 105 106 len = strlen(base); 107 buf = alloca(LDNS_IP6ADDRLEN*4 + len + 1); 108 for (i = 0; i < LDNS_IP6ADDRLEN; i++) { 109 uint8_t byte = ldns_rdf_data(addr)[LDNS_IP6ADDRLEN - i - 1]; 110 sprintf(&buf[i*4], "%x.%x.", byte & 0x0F, byte >> 4); 111 } 112 sprintf(&buf[LDNS_IP6ADDRLEN*4], "%s", base); 113 return ldns_dname_new_frm_str(buf); 114 } 115 116 static ldns_status 117 ldns_pkt_push_rr_soa(ldns_pkt *pkt, ldns_pkt_section sec, 118 const ldns_rdf *name, ldns_rr_class c, uint32_t serial) { 119 ldns_rdf *rdf; 120 ldns_rr *rr; 121 uint32_t n; 122 123 if ((rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_SOA)) == NULL) 124 return LDNS_STATUS_MEM_ERR; 125 ldns_rr_set_class(rr, c); 126 ldns_rr_set_owner(rr, ldns_rdf_clone(name)); 127 ldns_rr_set_ttl(rr, 0); 128 129 n = 0; 130 if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, &n)) == NULL) 131 goto memerr; 132 ldns_rr_set_rdf(rr, rdf, 0); 133 ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 1); 134 135 n = htonl(serial); 136 if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT32, 4, &n)) == NULL) 137 goto memerr; 138 ldns_rr_set_rdf(rr, rdf, 2); 139 140 n = 0; 141 if ((rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_PERIOD, 4, &n)) == NULL) 142 goto memerr; 143 ldns_rr_set_rdf(rr, rdf, 3); 144 ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 4); 145 ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 5); 146 ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), 6); 147 148 if (ldns_rr_rdf(rr, 1) == NULL || ldns_rr_rdf(rr, 4) == NULL || 149 ldns_rr_rdf(rr, 5) == NULL || ldns_rr_rdf(rr, 6) == NULL || 150 !ldns_pkt_push_rr(pkt, sec, rr)) 151 goto memerr; 152 return LDNS_STATUS_OK; 153 154 memerr: 155 ldns_rr_free(rr); 156 return LDNS_STATUS_MEM_ERR; 157 } 158 159 static ldns_status 160 ldns_tcp_start(ldns_resolver *res, ldns_pkt *qpkt, int nameserver) { 161 /* This routine is based on ldns_axfr_start, with the major 162 * difference in that it takes a query packet explicitly. 163 */ 164 struct sockaddr_storage *ns = NULL; 165 size_t ns_len = 0; 166 ldns_buffer *qbuf = NULL; 167 ldns_status status; 168 169 ns = ldns_rdf2native_sockaddr_storage( 170 res->_nameservers[nameserver], ldns_resolver_port(res), &ns_len); 171 if (ns == NULL) { 172 status = LDNS_STATUS_MEM_ERR; 173 goto error; 174 } 175 176 res->_socket = ldns_tcp_connect( 177 ns, (socklen_t)ns_len, ldns_resolver_timeout(res)); 178 if (res->_socket <= 0) { 179 status = LDNS_STATUS_ADDRESS_ERR; 180 goto error; 181 } 182 183 qbuf = ldns_buffer_new(LDNS_MAX_PACKETLEN); 184 if (qbuf == NULL) { 185 status = LDNS_STATUS_MEM_ERR; 186 goto error; 187 } 188 189 status = ldns_pkt2buffer_wire(qbuf, qpkt); 190 if (status != LDNS_STATUS_OK) 191 goto error; 192 193 if (ldns_tcp_send_query(qbuf, res->_socket, ns, (socklen_t)ns_len) == 0) { 194 status = LDNS_STATUS_NETWORK_ERR; 195 goto error; 196 } 197 198 ldns_buffer_free(qbuf); 199 free(ns); 200 return LDNS_STATUS_OK; 201 202 error: 203 ldns_buffer_free(qbuf); 204 free(ns); 205 if (res->_socket > 0) { 206 close(res->_socket); 207 res->_socket = 0; 208 } 209 return status; 210 } 211 212 static ldns_status 213 ldns_tcp_read(ldns_pkt **answer, ldns_resolver *res) { 214 ldns_status status; 215 struct timeval t1, t2; 216 uint8_t *data; 217 size_t size; 218 219 if (res->_socket <= 0) 220 return LDNS_STATUS_ERR; 221 222 gettimeofday(&t1, NULL); 223 data = ldns_tcp_read_wire_timeout( 224 res->_socket, &size, ldns_resolver_timeout(res)); 225 if (data == NULL) 226 goto error; 227 228 status = ldns_wire2pkt(answer, data, size); 229 free(data); 230 if (status != LDNS_STATUS_OK) 231 goto error; 232 233 gettimeofday(&t2, NULL); 234 ldns_pkt_set_querytime(*answer, 235 (uint32_t)((t2.tv_sec - t1.tv_sec)*1000) + 236 (t2.tv_usec - t1.tv_usec)/1000); 237 ldns_pkt_set_timestamp(*answer, t2); 238 return status; 239 240 error: 241 close(res->_socket); 242 res->_socket = 0; 243 return LDNS_STATUS_ERR; 244 } 245 246 static void 247 ldns_tcp_close(ldns_resolver *res) { 248 if (res->_socket > 0) { 249 close(res->_socket); 250 res->_socket = 0; 251 } 252 } 253 254 static ldns_status 255 ldns_resolver_send_to(ldns_pkt **answer, ldns_resolver *res, 256 const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, 257 uint16_t flags, uint32_t ixfr_serial, int nameserver, 258 bool close_tcp) { 259 ldns_status status = LDNS_STATUS_OK; 260 ldns_pkt *qpkt; 261 struct timeval now; 262 263 int nscnt = ldns_resolver_nameserver_count(res); 264 ldns_rdf **ns = ldns_resolver_nameservers(res); 265 size_t *rtt = ldns_resolver_rtt(res); 266 267 ldns_resolver_set_nameservers(res, &ns[nameserver]); 268 ldns_resolver_set_rtt(res, &rtt[nameserver]); 269 ldns_resolver_set_nameserver_count(res, 1); 270 271 /* The next fragment should have been a call to 272 * ldns_resolver_prepare_query_pkt(), but starting with ldns 273 * version 1.6.17 that function tries to add it's own SOA 274 * records when rr_type is LDNS_RR_TYPE_IXFR, and we don't 275 * want that. 276 */ 277 qpkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); 278 if (qpkt == NULL) { 279 status = LDNS_STATUS_ERR; 280 goto done; 281 } 282 now.tv_sec = time(NULL); 283 now.tv_usec = 0; 284 ldns_pkt_set_timestamp(qpkt, now); 285 ldns_pkt_set_random_id(qpkt); 286 287 if (t == LDNS_RR_TYPE_IXFR) { 288 status = ldns_pkt_push_rr_soa(qpkt, 289 LDNS_SECTION_AUTHORITY, name, c, ixfr_serial); 290 if (status != LDNS_STATUS_OK) goto done; 291 } 292 if (close_tcp) { 293 status = ldns_resolver_send_pkt(answer, res, qpkt); 294 } else { 295 status = ldns_tcp_start(res, qpkt, 0); 296 if (status != LDNS_STATUS_OK) goto done; 297 status = ldns_tcp_read(answer, res); 298 if (status != LDNS_STATUS_OK) goto done; 299 ldns_pkt_set_answerfrom(*answer, ldns_rdf_clone(ns[0])); 300 } 301 302 done: 303 ldns_pkt_free(qpkt); 304 305 ldns_resolver_set_nameservers(res, ns); 306 ldns_resolver_set_rtt(res, rtt); 307 ldns_resolver_set_nameserver_count(res, nscnt); 308 return status; 309 } 310 311 static void 312 ldns_pkt_filter_answer(ldns_pkt *pkt, ldns_rr_type type) { 313 int i, j, cnt; 314 ldns_rr_list *rrlist; 315 ldns_rr *rr; 316 ldns_rr_type rrtype; 317 318 rrlist = ldns_pkt_answer(pkt); 319 cnt = ldns_rr_list_rr_count(rrlist); 320 for (i = j = 0; i < cnt; i++) { 321 rr = ldns_rr_list_rr(rrlist, i); 322 rrtype = ldns_rr_get_type(rr); 323 if (type == LDNS_RR_TYPE_ANY || 324 type == rrtype || 325 (type == LDNS_RR_TYPE_AXFR && 326 (rrtype == LDNS_RR_TYPE_A || 327 rrtype == LDNS_RR_TYPE_AAAA || 328 rrtype == LDNS_RR_TYPE_NS || 329 rrtype == LDNS_RR_TYPE_PTR))) 330 ldns_rr_list_set_rr(rrlist, rr, j++); 331 } 332 ldns_rr_list_set_rr_count(rrlist, j); 333 } 334 335 /* Packet content printing. 336 */ 337 338 static struct { 339 ldns_rr_type type; 340 const char *text; 341 } rr_types[] = { 342 {LDNS_RR_TYPE_A, "has address"}, 343 {LDNS_RR_TYPE_NS, "name server"}, 344 {LDNS_RR_TYPE_CNAME, "is an alias for"}, 345 {LDNS_RR_TYPE_WKS, "has well known services"}, 346 {LDNS_RR_TYPE_PTR, "domain name pointer"}, 347 {LDNS_RR_TYPE_HINFO, "host information"}, 348 {LDNS_RR_TYPE_MX, "mail is handled by"}, 349 {LDNS_RR_TYPE_TXT, "descriptive text"}, 350 {LDNS_RR_TYPE_X25, "x25 address"}, 351 {LDNS_RR_TYPE_ISDN, "ISDN address"}, 352 {LDNS_RR_TYPE_SIG, "has signature"}, 353 {LDNS_RR_TYPE_KEY, "has key"}, 354 {LDNS_RR_TYPE_AAAA, "has IPv6 address"}, 355 {LDNS_RR_TYPE_LOC, "location"}, 356 }; 357 358 static void 359 print_opcode(ldns_pkt_opcode opcode) { 360 ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode); 361 362 if (lt && lt->name) 363 printf("%s", lt->name); 364 else 365 printf("RESERVED%d", opcode); 366 } 367 368 static void 369 print_rcode(uint8_t rcode) { 370 ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode); 371 372 if (lt && lt->name) 373 printf("%s", lt->name); 374 else 375 printf("RESERVED%d", rcode); 376 } 377 378 static int 379 print_rr_type(ldns_rr_type type) { 380 char *str; 381 int n; 382 383 str = ldns_rr_type2str(type); 384 n = printf("%s", str); 385 free(str); 386 return n; 387 } 388 389 static int 390 print_rr_class(ldns_rr_class cls) { 391 char *str; 392 int n; 393 394 str = ldns_rr_class2str(cls); 395 n = printf("%s", str); 396 free(str); 397 return n; 398 } 399 400 static int 401 print_rdf(ldns_rdf *rdf) { 402 char *str; 403 int n; 404 405 str = ldns_rdf2str(rdf); 406 n = printf("%s", str); 407 free(str); 408 return n; 409 } 410 411 static int 412 print_rdf_nodot(ldns_rdf *rdf) { 413 char *str; 414 int len, n; 415 416 str = ldns_rdf2str(rdf); 417 len = strlen(str); 418 n = printf("%.*s", str[len-1] == '.' ? len-1 : len, str); 419 free(str); 420 return n; 421 } 422 423 static int 424 print_padding(int fromcol, int tocol) { 425 int col = fromcol, nextcol = fromcol + 8 - fromcol%8; 426 427 if (fromcol + 1 > tocol) tocol = fromcol + 1; 428 for (; nextcol <= tocol; col = nextcol, nextcol += 8) 429 printf("\t"); 430 for (; col < tocol; col++) 431 printf(" "); 432 return col - fromcol; 433 } 434 435 static void 436 print_rr_verbose(ldns_rr *rr) { 437 bool isq = ldns_rr_is_question(rr); 438 int rdcnt = ldns_rr_rd_count(rr); 439 int i, n; 440 441 /* bind9-host does not count the initial ';' here */ 442 n = isq ? printf(";") : 0; 443 n = print_rdf(ldns_rr_owner(rr)); 444 if (!isq) { 445 n += print_padding(n, 24); 446 n += printf("%d", ldns_rr_ttl(rr)); 447 } 448 n += print_padding(n, 32); 449 n += print_rr_class(ldns_rr_get_class(rr)); 450 n += print_padding(n, 40); 451 n += print_rr_type(ldns_rr_get_type(rr)); 452 for (i = 0; i < rdcnt; i++) { 453 if (i == 0) print_padding(n, 48); 454 else printf(" "); 455 print_rdf(ldns_rr_rdf(rr, i)); 456 } 457 printf("\n"); 458 } 459 460 static void 461 print_pkt_section_verbose(const char *name, ldns_rr_list *rrlist) { 462 int i, cnt = ldns_rr_list_rr_count(rrlist); 463 464 if (cnt == 0) 465 return; 466 printf(";; %s SECTION:\n", name); 467 for (i = 0; i < cnt; i++) 468 print_rr_verbose(ldns_rr_list_rr(rrlist, i)); 469 printf("\n"); 470 } 471 472 static void 473 print_pkt_verbose(ldns_pkt *pkt) { 474 int got_flags = 0; 475 476 printf(";; ->>HEADER<<- opcode: "); 477 print_opcode(ldns_pkt_get_opcode(pkt)); 478 printf(", status: "); 479 print_rcode(ldns_pkt_get_rcode(pkt)); 480 printf(", id: %u\n", ldns_pkt_id(pkt)); 481 printf(";; flags:"); 482 if (ldns_pkt_qr(pkt)) printf(" qr"), got_flags = 1; 483 if (ldns_pkt_aa(pkt)) printf(" aa"), got_flags = 1; 484 if (ldns_pkt_tc(pkt)) printf(" tc"), got_flags = 1; 485 if (ldns_pkt_rd(pkt)) printf(" rd"), got_flags = 1; 486 if (ldns_pkt_ra(pkt)) printf(" ra"), got_flags = 1; 487 if (ldns_pkt_ad(pkt)) printf(" ad"), got_flags = 1; 488 if (ldns_pkt_cd(pkt)) printf(" cd"), got_flags = 1; 489 if (!got_flags) printf(" "); 490 printf("; QUERY: %u, ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n", 491 ldns_pkt_qdcount(pkt), ldns_pkt_ancount(pkt), 492 ldns_pkt_nscount(pkt), ldns_pkt_arcount(pkt)); 493 if (ldns_pkt_edns(pkt)) 494 printf(";; EDNS: version: %u, udp=%u\n", 495 ldns_pkt_edns_version(pkt), ldns_pkt_edns_udp_size(pkt)); 496 printf("\n"); 497 print_pkt_section_verbose("QUESTION", ldns_pkt_question(pkt)); 498 print_pkt_section_verbose("ANSWER", ldns_pkt_answer(pkt)); 499 print_pkt_section_verbose("AUTHORITY", ldns_pkt_authority(pkt)); 500 print_pkt_section_verbose("ADDITIONAL", ldns_pkt_additional(pkt)); 501 } 502 503 static void 504 print_rr_short(ldns_rr *rr) { 505 ldns_rr_type type = ldns_rr_get_type(rr); 506 size_t i, rdcnt = ldns_rr_rd_count(rr); 507 508 print_rdf_nodot(ldns_rr_owner(rr)); 509 printf(" "); 510 for (i = 0; i < countof(rr_types); i++) { 511 if (rr_types[i].type == type) { 512 printf("%s", rr_types[i].text); 513 goto found; 514 } 515 } 516 517 printf("has "); 518 print_rr_type(type); 519 printf(" record"); 520 521 found: 522 for (i = 0; i < rdcnt; i++) { 523 printf(" "); 524 print_rdf(ldns_rr_rdf(rr, i)); 525 } 526 printf("\n"); 527 } 528 529 static void 530 print_pkt_short(ldns_pkt *pkt, bool print_rr_server) { 531 ldns_rr_list *rrlist = ldns_pkt_answer(pkt); 532 size_t i; 533 534 for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { 535 if (print_rr_server) { 536 printf("Nameserver "); 537 print_rdf(ldns_pkt_answerfrom(pkt)); 538 printf(":\n\t"); 539 } 540 print_rr_short(ldns_rr_list_rr(rrlist, i)); 541 } 542 } 543 544 static void 545 print_received_line(ldns_resolver *res, ldns_pkt *pkt) { 546 char *from = ldns_rdf2str(ldns_pkt_answerfrom(pkt)); 547 548 printf("Received %zu bytes from %s#%d in %d ms\n", 549 ldns_pkt_size(pkt), from, ldns_resolver_port(res), 550 ldns_pkt_querytime(pkt)); 551 free(from); 552 } 553 554 /* Main program. 555 * 556 * Note that no memory is freed below this line by intention. 557 */ 558 559 #define DEFAULT_TCP_TIMEOUT 10 560 #define DEFAULT_UDP_TIMEOUT 5 561 562 enum operation_mode { M_AXFR, M_IXFR, M_DEFAULT_Q, M_SINGLE_Q, M_SOA }; 563 564 static enum operation_mode o_mode = M_DEFAULT_Q; 565 static bool o_ignore_servfail = true; 566 static bool o_ip6_int = false; 567 static bool o_print_pkt_server = false; 568 static bool o_print_rr_server = false; 569 static bool o_recursive = true; 570 static bool o_tcp = false; 571 static bool o_verbose = false; 572 static char *o_name = NULL; 573 static char *o_server = NULL; 574 static int o_ipversion = LDNS_RESOLV_INETANY; 575 static int o_ndots = 1; 576 static int o_retries = 1; 577 static ldns_rr_class o_rrclass = LDNS_RR_CLASS_IN; 578 static ldns_rr_type o_rrtype = (ldns_rr_type)-1; 579 static time_t o_timeout = 0; 580 static uint32_t o_ixfr_serial = 0; 581 582 static void 583 usage(void) { 584 fprintf(stderr, 585 "Usage: %s [-aCdilrsTvw46] [-c class] [-N ndots] [-R number]\n" 586 " %*c [-t type] [-W wait] name [server]\n" 587 "\t-a same as -v -t ANY\n" 588 "\t-C query SOA records from all authoritative name servers\n" 589 "\t-c use this query class (IN, CH, HS, etc)\n" 590 "\t-d produce verbose output, same as -v\n" 591 "\t-i use IP6.INT for IPv6 reverse lookups\n" 592 "\t-l list records in a zone via AXFR\n" 593 "\t-N consider names with at least this many dots as absolute\n" 594 "\t-R retry UDP queries this many times\n" 595 "\t-r disable recursive query\n" 596 "\t-s do not ignore SERVFAIL responses\n" 597 "\t-T send query via TCP\n" 598 "\t-t use this query type (A, AAAA, MX, etc)\n" 599 "\t-v produce verbose output\n" 600 "\t-w wait forever for a server reply\n" 601 "\t-W wait this many seconds for a reply\n" 602 "\t-4 use IPv4 only\n" 603 "\t-6 use IPv6 only\n", 604 progname, (int)strlen(progname), ' '); 605 exit(1); 606 } 607 608 static void 609 parse_args(int argc, char *argv[]) { 610 int ch; 611 612 progname = argv[0]; 613 while ((ch = getopt(argc, argv, "aCdilrsTvw46c:N:R:t:W:")) != -1) { 614 switch (ch) { 615 case 'a': 616 if (o_mode != M_AXFR) 617 o_mode = M_SINGLE_Q; 618 o_rrtype = LDNS_RR_TYPE_ANY; 619 o_verbose = true; 620 break; 621 case 'C': 622 o_mode = M_SOA; 623 o_print_rr_server = true; 624 o_rrclass = LDNS_RR_CLASS_IN; 625 o_rrtype = LDNS_RR_TYPE_NS; 626 break; 627 case 'c': 628 /* bind9-host sets o_mode to M_SINGLE_Q here */ 629 o_rrclass = ldns_get_rr_class_by_name(optarg); 630 if (o_rrclass <= 0) 631 die(2, "invalid class: %s\n", optarg); 632 break; 633 case 'd': o_verbose = true; break; 634 case 'i': o_ip6_int = true; break; 635 case 'l': 636 o_mode = M_AXFR; 637 if (o_rrtype == (ldns_rr_type)-1) 638 o_rrtype = LDNS_RR_TYPE_AXFR; 639 o_tcp = true; 640 break; 641 case 'N': 642 o_ndots = atoi(optarg); 643 if (o_ndots < 0) o_ndots = 0; 644 break; 645 case 'n': 646 /* bind9-host accepts and ignores this option */ 647 break; 648 case 'r': o_recursive = 0; break; 649 case 'R': 650 o_retries = atoi(optarg); 651 if (o_retries <= 0) o_retries = 1; 652 if (o_retries > 255) o_retries = 255; 653 break; 654 case 's': o_ignore_servfail = false; break; 655 case 'T': o_tcp = true; break; 656 case 't': 657 if (o_mode != M_AXFR) 658 o_mode = M_SINGLE_Q; 659 if (strncasecmp(optarg, "ixfr=", 5) == 0) { 660 o_rrtype = LDNS_RR_TYPE_IXFR; 661 o_ixfr_serial = atol(optarg + 5); 662 } else { 663 o_rrtype = ldns_get_rr_type_by_name(optarg); 664 if (o_rrtype <= 0) 665 die(2, "invalid type: %s\n", optarg); 666 } 667 if (o_rrtype == LDNS_RR_TYPE_AXFR) { 668 o_mode = M_AXFR; 669 o_rrtype = LDNS_RR_TYPE_ANY; 670 o_verbose = true; 671 } 672 if (o_rrtype == LDNS_RR_TYPE_IXFR) { 673 o_mode = M_IXFR; 674 o_rrtype = LDNS_RR_TYPE_ANY; 675 } 676 break; 677 case 'v': o_verbose = true; break; 678 case 'w': 679 o_timeout = (time_t)INT_MAX; 680 break; 681 case 'W': 682 o_timeout = atol(optarg); 683 if (o_timeout <= 0) o_timeout = 1; 684 break; 685 case '4': o_ipversion = LDNS_RESOLV_INET; break; 686 case '6': o_ipversion = LDNS_RESOLV_INET6; break; 687 default: 688 usage(); 689 } 690 } 691 argc -= optind; 692 argv += optind; 693 /* bind9-host ignores arguments after the 2-nd one */ 694 if (argc < 1) 695 usage(); 696 o_name = argv[0]; 697 if (argc > 1) { 698 o_server = argv[1]; 699 o_print_pkt_server = true; 700 } 701 if (o_rrtype == (ldns_rr_type)-1) 702 o_rrtype = LDNS_RR_TYPE_A; 703 } 704 705 static ldns_rdf* 706 safe_str2rdf_dname(const char *name) { 707 ldns_rdf *dname; 708 ldns_status status; 709 710 if ((status = ldns_str2rdf_dname(&dname, name)) != LDNS_STATUS_OK) { 711 die(1, "'%s' is not a legal name (%s)", 712 name, ldns_get_errorstr_by_id(status)); 713 } 714 return dname; 715 } 716 717 static ldns_rdf* 718 safe_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) { 719 ldns_rdf *result = ldns_dname_cat_clone(rd1, rd2); 720 721 if (!result) 722 die(1, "not enought memory for a domain name"); 723 /* Why doesn't ldns_dname_cat_clone check this condition? */ 724 if (ldns_rdf_size(result) > LDNS_MAX_DOMAINLEN) 725 die(1, "'%s' is not a legal name (%s)\n", ldns_rdf2str(result), 726 ldns_get_errorstr_by_id(LDNS_STATUS_DOMAINNAME_OVERFLOW)); 727 return result; 728 } 729 730 static bool 731 query(ldns_resolver *res, ldns_rdf *domain, ldns_pkt **pkt, bool close_tcp) { 732 ldns_status status; 733 ldns_pkt_rcode rcode; 734 int i, cnt; 735 736 if (o_verbose) { 737 printf("Trying \""); 738 print_rdf_nodot(domain); 739 printf("\"\n"); 740 } 741 for (cnt = ldns_resolver_nameserver_count(res), i = 0; i < cnt; i++) { 742 status = ldns_resolver_send_to(pkt, res, domain, o_rrtype, 743 o_rrclass, o_recursive ? LDNS_RD : 0, o_ixfr_serial, i, 744 close_tcp); 745 if (status != LDNS_STATUS_OK) { 746 *pkt = NULL; 747 continue; 748 } 749 if (ldns_pkt_tc(*pkt) && !ldns_resolver_usevc(res)) { 750 if (o_verbose) 751 printf(";; Truncated, retrying in TCP mode.\n"); 752 ldns_resolver_set_usevc(res, true); 753 status = ldns_resolver_send_to(pkt, res, domain, o_rrtype, 754 o_rrclass, o_recursive ? LDNS_RD : 0, o_ixfr_serial, i, 755 close_tcp); 756 ldns_resolver_set_usevc(res, false); 757 if (status != LDNS_STATUS_OK) 758 continue; 759 } 760 rcode = ldns_pkt_get_rcode(*pkt); 761 if (o_ignore_servfail && rcode == LDNS_RCODE_SERVFAIL && cnt > 1) 762 continue; 763 return rcode == LDNS_RCODE_NOERROR; 764 } 765 if (*pkt == NULL) { 766 printf(";; connection timed out; no servers could be reached\n"); 767 exit(1); 768 } 769 return false; 770 } 771 772 static ldns_rdf * 773 search(ldns_resolver *res, ldns_rdf *domain, ldns_pkt **pkt, 774 bool absolute, bool close_tcp) { 775 ldns_rdf *dname, **searchlist; 776 int i, n; 777 778 if (absolute && query(res, domain, pkt, close_tcp)) 779 return domain; 780 781 if ((dname = ldns_resolver_domain(res)) != NULL) { 782 dname = safe_dname_cat_clone(domain, dname); 783 if (query(res, dname, pkt, close_tcp)) 784 return dname; 785 } 786 787 searchlist = ldns_resolver_searchlist(res); 788 n = ldns_resolver_searchlist_count(res); 789 for (i = 0; i < n; i++) { 790 dname = safe_dname_cat_clone(domain, searchlist[i]); 791 if (query(res, dname, pkt, close_tcp)) 792 return dname; 793 } 794 795 if (!absolute && query(res, domain, pkt, close_tcp)) 796 return domain; 797 798 return NULL; 799 } 800 801 static void 802 report(ldns_resolver *res, ldns_rdf *domain, ldns_pkt *pkt) { 803 ldns_pkt_rcode rcode; 804 805 if (o_print_pkt_server) { 806 printf("Using domain server:\nName: %s\nAddress: ", o_server); 807 print_rdf(ldns_pkt_answerfrom(pkt)); 808 printf("#%d\nAliases: \n\n", ldns_resolver_port(res)); 809 o_print_pkt_server = false; 810 } 811 rcode = ldns_pkt_get_rcode(pkt); 812 if (rcode != LDNS_RCODE_NOERROR) { 813 printf("Host "); 814 print_rdf_nodot(domain); 815 printf(" not found: %d(", rcode); 816 print_rcode(rcode); 817 printf(")\n"); 818 } else { 819 if (o_verbose) { 820 print_pkt_verbose(pkt); 821 } else { 822 print_pkt_short(pkt, o_print_rr_server); 823 if (o_mode == M_SINGLE_Q && 824 ldns_rr_list_rr_count(ldns_pkt_answer(pkt)) == 0) { 825 print_rdf_nodot(domain); 826 printf(" has no "); 827 print_rr_type(o_rrtype); 828 printf(" record\n"); 829 } 830 } 831 } 832 if (o_verbose) 833 print_received_line(res, pkt); 834 } 835 836 static bool 837 doquery(ldns_resolver *res, ldns_rdf *domain) { 838 ldns_pkt *pkt; 839 bool q; 840 841 q = query(res, domain, &pkt, true); 842 report(res, domain, pkt); 843 return q; 844 } 845 846 static bool 847 doquery_filtered(ldns_resolver *res, ldns_rdf *domain) { 848 ldns_pkt *pkt; 849 bool q; 850 851 q = query(res, domain, &pkt, true); 852 ldns_pkt_filter_answer(pkt, o_rrtype); 853 report(res, domain, pkt); 854 return q; 855 } 856 857 static bool 858 dosearch(ldns_resolver *res, ldns_rdf *domain, bool absolute) { 859 ldns_pkt *pkt; 860 ldns_rdf *dname; 861 862 dname = search(res, domain, &pkt, absolute, true); 863 report(res, dname != NULL ? dname : domain, pkt); 864 return o_mode != M_DEFAULT_Q ? (dname != NULL) : 865 (dname != NULL) && 866 (o_rrtype = LDNS_RR_TYPE_AAAA, doquery_filtered(res, dname)) && 867 (o_rrtype = LDNS_RR_TYPE_MX, doquery_filtered(res, dname)); 868 } 869 870 static bool 871 dozonetransfer(ldns_resolver *res, ldns_rdf *domain, bool absolute) { 872 ldns_pkt *pkt, *nextpkt; 873 ldns_rdf *dname; 874 ldns_rr_type rrtype; 875 ldns_rr_list *rrl; 876 int i, nsoa = 0; 877 878 rrtype = o_rrtype; 879 o_rrtype = (o_mode == M_AXFR) ? LDNS_RR_TYPE_AXFR : LDNS_RR_TYPE_IXFR; 880 dname = search(res, domain, &pkt, absolute, false); 881 882 for (;;) { 883 rrl = ldns_pkt_answer(pkt); 884 for (i = ldns_rr_list_rr_count(rrl) - 1; i >= 0; i--) { 885 if (ldns_rr_get_type(ldns_rr_list_rr(rrl, i)) == LDNS_RR_TYPE_SOA) 886 nsoa++; 887 } 888 ldns_pkt_filter_answer(pkt, rrtype); 889 report(res, dname != NULL ? dname : domain, pkt); 890 if ((dname == NULL) || 891 (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR)) { 892 printf("; Transfer failed.\n"); 893 ldns_tcp_close(res); 894 return false; 895 } 896 if (nsoa >= 2) { 897 ldns_tcp_close(res); 898 return true; 899 } 900 if (ldns_tcp_read(&nextpkt, res) != LDNS_STATUS_OK) { 901 printf("; Transfer failed.\n"); 902 return false; 903 } 904 ldns_pkt_set_answerfrom(nextpkt, 905 ldns_rdf_clone(ldns_pkt_answerfrom(pkt))); 906 ldns_pkt_free(pkt); 907 pkt = nextpkt; 908 } 909 } 910 911 static bool 912 dosoa(ldns_resolver *res, ldns_rdf *domain, bool absolute) { 913 ldns_rr_list *answer, **nsaddrs; 914 ldns_rdf *dname, *addr; 915 ldns_pkt *pkt; 916 ldns_rr *rr; 917 size_t i, j, n, cnt; 918 919 if ((dname = search(res, domain, &pkt, absolute, true)) == NULL) 920 return false; 921 922 answer = ldns_pkt_answer(pkt); 923 cnt = ldns_rr_list_rr_count(answer); 924 nsaddrs = alloca(cnt*sizeof(*nsaddrs)); 925 for (n = 0, i = 0; i < cnt; i++) 926 if ((addr = ldns_rr_ns_nsdname(ldns_rr_list_rr(answer, i))) != NULL) 927 nsaddrs[n++] = ldns_get_rr_list_addr_by_name(res, 928 addr, LDNS_RR_CLASS_IN, 0); 929 930 o_print_pkt_server = false; 931 o_recursive = false; 932 o_rrtype = LDNS_RR_TYPE_SOA; 933 for (i = 0; i < n; i++) { 934 cnt = ldns_rr_list_rr_count(nsaddrs[i]); 935 for (j = 0; j < cnt; j++) { 936 ldns_resolver_remove_nameservers(res); 937 rr = ldns_rr_list_rr(nsaddrs[i], j); 938 if ((ldns_resolver_ip6(res) == LDNS_RESOLV_INET && 939 ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) || 940 (ldns_resolver_ip6(res) == LDNS_RESOLV_INET6 && 941 ldns_rr_get_type(rr) == LDNS_RR_TYPE_A)) 942 continue; 943 if (ldns_resolver_push_nameserver_rr(res, rr) == LDNS_STATUS_OK) 944 /* bind9-host queries for domain, not dname here */ 945 doquery(res, dname); 946 } 947 } 948 return 0; 949 } 950 951 static void 952 resolver_set_nameserver_hostname(ldns_resolver *res, const char *server) { 953 struct addrinfo hints, *ailist, *ai; 954 ldns_status status; 955 ldns_rdf *rdf; 956 int err; 957 958 memset(&hints, 0, sizeof hints); 959 switch (ldns_resolver_ip6(res)) { 960 case LDNS_RESOLV_INET: hints.ai_family = PF_INET; break; 961 case LDNS_RESOLV_INET6: hints.ai_family = PF_INET6; break; 962 default: hints.ai_family = PF_UNSPEC; break; 963 } 964 hints.ai_socktype = SOCK_STREAM; 965 do err = getaddrinfo(server, NULL, &hints, &ailist); 966 while (err == EAI_AGAIN); 967 if (err != 0) 968 die(1, "couldn't get address for '%s': %s", server, gai_strerror(err)); 969 for (ai = ailist; ai != NULL; ai = ai->ai_next) { 970 if ((rdf = ldns_sockaddr_storage2rdf((void*)ai->ai_addr, NULL)) == NULL) 971 die(1, "couldn't allocate an rdf: %s", 972 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR)); 973 status = ldns_resolver_push_nameserver(res, rdf); 974 if (status != LDNS_STATUS_OK) 975 die(1, "couldn't push a nameserver address: %s", 976 ldns_get_errorstr_by_id(status)); 977 } 978 } 979 980 static void 981 resolver_set_nameserver_str(ldns_resolver *res, const char *server) { 982 ldns_rdf *addr; 983 984 ldns_resolver_remove_nameservers(res); 985 addr = ldns_rdf_new_addr_frm_str(server); 986 if (addr) { 987 if (ldns_resolver_push_nameserver(res, addr) != LDNS_STATUS_OK) 988 die(1, "couldn't push a nameserver address"); 989 } else 990 resolver_set_nameserver_hostname(res, server); 991 } 992 993 int 994 main(int argc, char *argv[]) { 995 ldns_rdf *addr, *dname; 996 ldns_resolver *res; 997 ldns_status status; 998 struct timeval restimeout; 999 1000 parse_args(argc, argv); 1001 1002 status = ldns_resolver_new_default(&res); 1003 if (status != LDNS_STATUS_OK) 1004 die(1, "error creating resolver: %s", ldns_get_errorstr_by_id(status)); 1005 if (ldns_resolver_nameserver_count(res) == 0) 1006 ldns_resolver_push_default_servers(res); 1007 1008 ldns_resolver_set_usevc(res, o_tcp); 1009 restimeout.tv_sec = o_timeout > 0 ? o_timeout : 1010 o_tcp ? DEFAULT_TCP_TIMEOUT : DEFAULT_UDP_TIMEOUT; 1011 restimeout.tv_usec = 0; 1012 ldns_resolver_set_timeout(res, restimeout); 1013 ldns_resolver_set_retry(res, o_retries+1); 1014 ldns_resolver_set_ip6(res, o_ipversion); 1015 ldns_resolver_set_defnames(res, false); 1016 ldns_resolver_set_fallback(res, false); 1017 1018 if (o_server) 1019 resolver_set_nameserver_str(res, o_server); 1020 1021 if (ldns_str2rdf_a(&addr, o_name) == LDNS_STATUS_OK) { 1022 dname = ldns_rdf_reverse_a(addr, "in-addr.arpa"); 1023 if (dname == NULL) 1024 die(1, "can't reverse '%s': %s", o_name, 1025 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR)); 1026 o_mode = M_SINGLE_Q; 1027 o_rrtype = LDNS_RR_TYPE_PTR; 1028 return !doquery(res, dname); 1029 } else if (ldns_str2rdf_aaaa(&addr, o_name) == LDNS_STATUS_OK) { 1030 dname = ldns_rdf_reverse_aaaa(addr, o_ip6_int ? "ip6.int" : "ip6.arpa"); 1031 if (dname == NULL) 1032 die(1, "can't reverse '%s': %s", o_name, 1033 ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR)); 1034 o_mode = M_SINGLE_Q; 1035 o_rrtype = LDNS_RR_TYPE_PTR; 1036 return !doquery(res, dname); 1037 } 1038 return !(o_mode == M_SOA ? dosoa : 1039 o_mode == M_AXFR ? dozonetransfer : 1040 o_mode == M_IXFR ? dozonetransfer : 1041 dosearch) 1042 (res, safe_str2rdf_dname(o_name), ndots(o_name) >= o_ndots); 1043 } 1044