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