1/* Copyright 1998 by the Massachusetts Institute of Technology. 2 * 3 * 4 * Permission to use, copy, modify, and distribute this 5 * software and its documentation for any purpose and without 6 * fee is hereby granted, provided that the above copyright 7 * notice appear in all copies and that both that copyright 8 * notice and this permission notice appear in supporting 9 * documentation, and that the name of M.I.T. not be used in 10 * advertising or publicity pertaining to distribution of the 11 * software without specific, written prior permission. 12 * M.I.T. makes no representations about the suitability of 13 * this software for any purpose. It is provided "as is" 14 * without express or implied warranty. 15 */ 16 17#include "ares_setup.h" 18 19#ifdef HAVE_SYS_SOCKET_H 20# include <sys/socket.h> 21#endif 22#ifdef HAVE_NETINET_IN_H 23# include <netinet/in.h> 24#endif 25#ifdef HAVE_ARPA_INET_H 26# include <arpa/inet.h> 27#endif 28#ifdef HAVE_NETDB_H 29# include <netdb.h> 30#endif 31#ifdef HAVE_ARPA_NAMESER_H 32# include <arpa/nameser.h> 33#else 34# include "nameser.h" 35#endif 36#ifdef HAVE_ARPA_NAMESER_COMPAT_H 37# include <arpa/nameser_compat.h> 38#endif 39 40#ifdef HAVE_SYS_TIME_H 41# include <sys/time.h> 42#endif 43#ifdef HAVE_UNISTD_H 44# include <unistd.h> 45#endif 46#ifdef HAVE_STRINGS_H 47# include <strings.h> 48#endif 49 50#include <stdio.h> 51#include <stdlib.h> 52#include <string.h> 53#include <ctype.h> 54 55#include "ares.h" 56#include "ares_dns.h" 57#include "inet_ntop.h" 58#include "inet_net_pton.h" 59#include "ares_getopt.h" 60#include "ares_nowarn.h" 61 62#ifndef HAVE_STRDUP 63# include "ares_strdup.h" 64# define strdup(ptr) ares_strdup(ptr) 65#endif 66 67#ifndef HAVE_STRCASECMP 68# include "ares_strcasecmp.h" 69# define strcasecmp(p1,p2) ares_strcasecmp(p1,p2) 70#endif 71 72#ifndef HAVE_STRNCASECMP 73# include "ares_strcasecmp.h" 74# define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n) 75#endif 76 77#ifdef WATT32 78#undef WIN32 /* Redefined in MingW headers */ 79#endif 80 81#ifndef T_SRV 82# define T_SRV 33 /* Server selection */ 83#endif 84#ifndef T_NAPTR 85# define T_NAPTR 35 /* Naming authority pointer */ 86#endif 87#ifndef T_DS 88# define T_DS 43 /* Delegation Signer (RFC4034) */ 89#endif 90#ifndef T_SSHFP 91# define T_SSHFP 44 /* SSH Key Fingerprint (RFC4255) */ 92#endif 93#ifndef T_RRSIG 94# define T_RRSIG 46 /* Resource Record Signature (RFC4034) */ 95#endif 96#ifndef T_NSEC 97# define T_NSEC 47 /* Next Secure (RFC4034) */ 98#endif 99#ifndef T_DNSKEY 100# define T_DNSKEY 48 /* DNS Public Key (RFC4034) */ 101#endif 102 103struct nv { 104 const char *name; 105 int value; 106}; 107 108static const struct nv flags[] = { 109 { "usevc", ARES_FLAG_USEVC }, 110 { "primary", ARES_FLAG_PRIMARY }, 111 { "igntc", ARES_FLAG_IGNTC }, 112 { "norecurse", ARES_FLAG_NORECURSE }, 113 { "stayopen", ARES_FLAG_STAYOPEN }, 114 { "noaliases", ARES_FLAG_NOALIASES } 115}; 116static const int nflags = sizeof(flags) / sizeof(flags[0]); 117 118static const struct nv classes[] = { 119 { "IN", C_IN }, 120 { "CHAOS", C_CHAOS }, 121 { "HS", C_HS }, 122 { "ANY", C_ANY } 123}; 124static const int nclasses = sizeof(classes) / sizeof(classes[0]); 125 126static const struct nv types[] = { 127 { "A", T_A }, 128 { "NS", T_NS }, 129 { "MD", T_MD }, 130 { "MF", T_MF }, 131 { "CNAME", T_CNAME }, 132 { "SOA", T_SOA }, 133 { "MB", T_MB }, 134 { "MG", T_MG }, 135 { "MR", T_MR }, 136 { "NULL", T_NULL }, 137 { "WKS", T_WKS }, 138 { "PTR", T_PTR }, 139 { "HINFO", T_HINFO }, 140 { "MINFO", T_MINFO }, 141 { "MX", T_MX }, 142 { "TXT", T_TXT }, 143 { "RP", T_RP }, 144 { "AFSDB", T_AFSDB }, 145 { "X25", T_X25 }, 146 { "ISDN", T_ISDN }, 147 { "RT", T_RT }, 148 { "NSAP", T_NSAP }, 149 { "NSAP_PTR", T_NSAP_PTR }, 150 { "SIG", T_SIG }, 151 { "KEY", T_KEY }, 152 { "PX", T_PX }, 153 { "GPOS", T_GPOS }, 154 { "AAAA", T_AAAA }, 155 { "LOC", T_LOC }, 156 { "SRV", T_SRV }, 157 { "AXFR", T_AXFR }, 158 { "MAILB", T_MAILB }, 159 { "MAILA", T_MAILA }, 160 { "NAPTR", T_NAPTR }, 161 { "DS", T_DS }, 162 { "SSHFP", T_SSHFP }, 163 { "RRSIG", T_RRSIG }, 164 { "NSEC", T_NSEC }, 165 { "DNSKEY", T_DNSKEY }, 166 { "ANY", T_ANY } 167}; 168static const int ntypes = sizeof(types) / sizeof(types[0]); 169 170static const char *opcodes[] = { 171 "QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY", 172 "(unknown)", "(unknown)", "(unknown)", "(unknown)", 173 "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA", 174 "ZONEINIT", "ZONEREF" 175}; 176 177static const char *rcodes[] = { 178 "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED", 179 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)", 180 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE" 181}; 182 183static void callback(void *arg, int status, int timeouts, 184 unsigned char *abuf, int alen); 185static const unsigned char *display_question(const unsigned char *aptr, 186 const unsigned char *abuf, 187 int alen); 188static const unsigned char *display_rr(const unsigned char *aptr, 189 const unsigned char *abuf, int alen); 190static const char *type_name(int type); 191static const char *class_name(int dnsclass); 192static void usage(void); 193static void destroy_addr_list(struct ares_addr_node *head); 194static void append_addr_list(struct ares_addr_node **head, 195 struct ares_addr_node *node); 196 197int main(int argc, char **argv) 198{ 199 ares_channel channel; 200 int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A; 201 int status, nfds, count; 202 struct ares_options options; 203 struct hostent *hostent; 204 fd_set read_fds, write_fds; 205 struct timeval *tvp, tv; 206 struct ares_addr_node *srvr, *servers = NULL; 207 208#ifdef USE_WINSOCK 209 WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK); 210 WSADATA wsaData; 211 WSAStartup(wVersionRequested, &wsaData); 212#endif 213 214 status = ares_library_init(ARES_LIB_INIT_ALL); 215 if (status != ARES_SUCCESS) 216 { 217 fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status)); 218 return 1; 219 } 220 221 options.flags = ARES_FLAG_NOCHECKRESP; 222 options.servers = NULL; 223 options.nservers = 0; 224 while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1) 225 { 226 switch (c) 227 { 228 case 'd': 229#ifdef WATT32 230 dbug_init(); 231#endif 232 break; 233 234 case 'f': 235 /* Add a flag. */ 236 for (i = 0; i < nflags; i++) 237 { 238 if (strcmp(flags[i].name, optarg) == 0) 239 break; 240 } 241 if (i < nflags) 242 options.flags |= flags[i].value; 243 else 244 usage(); 245 break; 246 247 case 's': 248 /* User-specified name servers override default ones. */ 249 srvr = malloc(sizeof(struct ares_addr_node)); 250 if (!srvr) 251 { 252 fprintf(stderr, "Out of memory!\n"); 253 destroy_addr_list(servers); 254 return 1; 255 } 256 append_addr_list(&servers, srvr); 257 if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0) 258 srvr->family = AF_INET; 259 else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0) 260 srvr->family = AF_INET6; 261 else 262 { 263 hostent = gethostbyname(optarg); 264 if (!hostent) 265 { 266 fprintf(stderr, "adig: server %s not found.\n", optarg); 267 destroy_addr_list(servers); 268 return 1; 269 } 270 switch (hostent->h_addrtype) 271 { 272 case AF_INET: 273 srvr->family = AF_INET; 274 memcpy(&srvr->addr.addr4, hostent->h_addr, 275 sizeof(srvr->addr.addr4)); 276 break; 277 case AF_INET6: 278 srvr->family = AF_INET6; 279 memcpy(&srvr->addr.addr6, hostent->h_addr, 280 sizeof(srvr->addr.addr6)); 281 break; 282 default: 283 fprintf(stderr, 284 "adig: server %s unsupported address family.\n", optarg); 285 destroy_addr_list(servers); 286 return 1; 287 } 288 } 289 /* Notice that calling ares_init_options() without servers in the 290 * options struct and with ARES_OPT_SERVERS set simultaneously in 291 * the options mask, results in an initialization with no servers. 292 * When alternative name servers have been specified these are set 293 * later calling ares_set_servers() overriding any existing server 294 * configuration. To prevent initial configuration with default 295 * servers that will be discarded later, ARES_OPT_SERVERS is set. 296 * If this flag is not set here the result shall be the same but 297 * ares_init_options() will do needless work. */ 298 optmask |= ARES_OPT_SERVERS; 299 break; 300 301 case 'c': 302 /* Set the query class. */ 303 for (i = 0; i < nclasses; i++) 304 { 305 if (strcasecmp(classes[i].name, optarg) == 0) 306 break; 307 } 308 if (i < nclasses) 309 dnsclass = classes[i].value; 310 else 311 usage(); 312 break; 313 314 case 't': 315 /* Set the query type. */ 316 for (i = 0; i < ntypes; i++) 317 { 318 if (strcasecmp(types[i].name, optarg) == 0) 319 break; 320 } 321 if (i < ntypes) 322 type = types[i].value; 323 else 324 usage(); 325 break; 326 327 case 'T': 328 /* Set the TCP port number. */ 329 if (!ISDIGIT(*optarg)) 330 usage(); 331 options.tcp_port = (unsigned short)strtol(optarg, NULL, 0); 332 optmask |= ARES_OPT_TCP_PORT; 333 break; 334 335 case 'U': 336 /* Set the UDP port number. */ 337 if (!ISDIGIT(*optarg)) 338 usage(); 339 options.udp_port = (unsigned short)strtol(optarg, NULL, 0); 340 optmask |= ARES_OPT_UDP_PORT; 341 break; 342 } 343 } 344 argc -= optind; 345 argv += optind; 346 if (argc == 0) 347 usage(); 348 349 status = ares_init_options(&channel, &options, optmask); 350 351 if (status != ARES_SUCCESS) 352 { 353 fprintf(stderr, "ares_init_options: %s\n", 354 ares_strerror(status)); 355 return 1; 356 } 357 358 if(servers) 359 { 360 status = ares_set_servers(channel, servers); 361 destroy_addr_list(servers); 362 if (status != ARES_SUCCESS) 363 { 364 fprintf(stderr, "ares_init_options: %s\n", 365 ares_strerror(status)); 366 return 1; 367 } 368 } 369 370 /* Initiate the queries, one per command-line argument. If there is 371 * only one query to do, supply NULL as the callback argument; 372 * otherwise, supply the query name as an argument so we can 373 * distinguish responses for the user when printing them out. 374 */ 375 if (argc == 1) 376 ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL); 377 else 378 { 379 for (; *argv; argv++) 380 ares_query(channel, *argv, dnsclass, type, callback, *argv); 381 } 382 383 /* Wait for all queries to complete. */ 384 for (;;) 385 { 386 FD_ZERO(&read_fds); 387 FD_ZERO(&write_fds); 388 nfds = ares_fds(channel, &read_fds, &write_fds); 389 if (nfds == 0) 390 break; 391 tvp = ares_timeout(channel, NULL, &tv); 392 count = select(nfds, &read_fds, &write_fds, NULL, tvp); 393 if (count < 0 && SOCKERRNO != EINVAL) 394 { 395 perror("select"); 396 return 1; 397 } 398 ares_process(channel, &read_fds, &write_fds); 399 } 400 401 ares_destroy(channel); 402 403 ares_library_cleanup(); 404 405#ifdef USE_WINSOCK 406 WSACleanup(); 407#endif 408 409 return 0; 410} 411 412static void callback(void *arg, int status, int timeouts, 413 unsigned char *abuf, int alen) 414{ 415 char *name = (char *) arg; 416 int id, qr, opcode, aa, tc, rd, ra, rcode; 417 unsigned int qdcount, ancount, nscount, arcount, i; 418 const unsigned char *aptr; 419 420 (void) timeouts; 421 422 /* Display the query name if given. */ 423 if (name) 424 printf("Answer for query %s:\n", name); 425 426 /* Display an error message if there was an error, but only stop if 427 * we actually didn't get an answer buffer. 428 */ 429 if (status != ARES_SUCCESS) 430 { 431 printf("%s\n", ares_strerror(status)); 432 if (!abuf) 433 return; 434 } 435 436 /* Won't happen, but check anyway, for safety. */ 437 if (alen < HFIXEDSZ) 438 return; 439 440 /* Parse the answer header. */ 441 id = DNS_HEADER_QID(abuf); 442 qr = DNS_HEADER_QR(abuf); 443 opcode = DNS_HEADER_OPCODE(abuf); 444 aa = DNS_HEADER_AA(abuf); 445 tc = DNS_HEADER_TC(abuf); 446 rd = DNS_HEADER_RD(abuf); 447 ra = DNS_HEADER_RA(abuf); 448 rcode = DNS_HEADER_RCODE(abuf); 449 qdcount = DNS_HEADER_QDCOUNT(abuf); 450 ancount = DNS_HEADER_ANCOUNT(abuf); 451 nscount = DNS_HEADER_NSCOUNT(abuf); 452 arcount = DNS_HEADER_ARCOUNT(abuf); 453 454 /* Display the answer header. */ 455 printf("id: %d\n", id); 456 printf("flags: %s%s%s%s%s\n", 457 qr ? "qr " : "", 458 aa ? "aa " : "", 459 tc ? "tc " : "", 460 rd ? "rd " : "", 461 ra ? "ra " : ""); 462 printf("opcode: %s\n", opcodes[opcode]); 463 printf("rcode: %s\n", rcodes[rcode]); 464 465 /* Display the questions. */ 466 printf("Questions:\n"); 467 aptr = abuf + HFIXEDSZ; 468 for (i = 0; i < qdcount; i++) 469 { 470 aptr = display_question(aptr, abuf, alen); 471 if (aptr == NULL) 472 return; 473 } 474 475 /* Display the answers. */ 476 printf("Answers:\n"); 477 for (i = 0; i < ancount; i++) 478 { 479 aptr = display_rr(aptr, abuf, alen); 480 if (aptr == NULL) 481 return; 482 } 483 484 /* Display the NS records. */ 485 printf("NS records:\n"); 486 for (i = 0; i < nscount; i++) 487 { 488 aptr = display_rr(aptr, abuf, alen); 489 if (aptr == NULL) 490 return; 491 } 492 493 /* Display the additional records. */ 494 printf("Additional records:\n"); 495 for (i = 0; i < arcount; i++) 496 { 497 aptr = display_rr(aptr, abuf, alen); 498 if (aptr == NULL) 499 return; 500 } 501} 502 503static const unsigned char *display_question(const unsigned char *aptr, 504 const unsigned char *abuf, 505 int alen) 506{ 507 char *name; 508 int type, dnsclass, status; 509 long len; 510 511 /* Parse the question name. */ 512 status = ares_expand_name(aptr, abuf, alen, &name, &len); 513 if (status != ARES_SUCCESS) 514 return NULL; 515 aptr += len; 516 517 /* Make sure there's enough data after the name for the fixed part 518 * of the question. 519 */ 520 if (aptr + QFIXEDSZ > abuf + alen) 521 { 522 ares_free_string(name); 523 return NULL; 524 } 525 526 /* Parse the question type and class. */ 527 type = DNS_QUESTION_TYPE(aptr); 528 dnsclass = DNS_QUESTION_CLASS(aptr); 529 aptr += QFIXEDSZ; 530 531 /* Display the question, in a format sort of similar to how we will 532 * display RRs. 533 */ 534 printf("\t%-15s.\t", name); 535 if (dnsclass != C_IN) 536 printf("\t%s", class_name(dnsclass)); 537 printf("\t%s\n", type_name(type)); 538 ares_free_string(name); 539 return aptr; 540} 541 542static const unsigned char *display_rr(const unsigned char *aptr, 543 const unsigned char *abuf, int alen) 544{ 545 const unsigned char *p; 546 int type, dnsclass, ttl, dlen, status; 547 long len; 548 char addr[46]; 549 union { 550 unsigned char * as_uchar; 551 char * as_char; 552 } name; 553 554 /* Parse the RR name. */ 555 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); 556 if (status != ARES_SUCCESS) 557 return NULL; 558 aptr += len; 559 560 /* Make sure there is enough data after the RR name for the fixed 561 * part of the RR. 562 */ 563 if (aptr + RRFIXEDSZ > abuf + alen) 564 { 565 ares_free_string(name.as_char); 566 return NULL; 567 } 568 569 /* Parse the fixed part of the RR, and advance to the RR data 570 * field. */ 571 type = DNS_RR_TYPE(aptr); 572 dnsclass = DNS_RR_CLASS(aptr); 573 ttl = DNS_RR_TTL(aptr); 574 dlen = DNS_RR_LEN(aptr); 575 aptr += RRFIXEDSZ; 576 if (aptr + dlen > abuf + alen) 577 { 578 ares_free_string(name.as_char); 579 return NULL; 580 } 581 582 /* Display the RR name, class, and type. */ 583 printf("\t%-15s.\t%d", name.as_char, ttl); 584 if (dnsclass != C_IN) 585 printf("\t%s", class_name(dnsclass)); 586 printf("\t%s", type_name(type)); 587 ares_free_string(name.as_char); 588 589 /* Display the RR data. Don't touch aptr. */ 590 switch (type) 591 { 592 case T_CNAME: 593 case T_MB: 594 case T_MD: 595 case T_MF: 596 case T_MG: 597 case T_MR: 598 case T_NS: 599 case T_PTR: 600 /* For these types, the RR data is just a domain name. */ 601 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len); 602 if (status != ARES_SUCCESS) 603 return NULL; 604 printf("\t%s.", name.as_char); 605 ares_free_string(name.as_char); 606 break; 607 608 case T_HINFO: 609 /* The RR data is two length-counted character strings. */ 610 p = aptr; 611 len = *p; 612 if (p + len + 1 > aptr + dlen) 613 return NULL; 614 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 615 if (status != ARES_SUCCESS) 616 return NULL; 617 printf("\t%s", name.as_char); 618 ares_free_string(name.as_char); 619 p += len; 620 len = *p; 621 if (p + len + 1 > aptr + dlen) 622 return NULL; 623 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 624 if (status != ARES_SUCCESS) 625 return NULL; 626 printf("\t%s", name.as_char); 627 ares_free_string(name.as_char); 628 break; 629 630 case T_MINFO: 631 /* The RR data is two domain names. */ 632 p = aptr; 633 status = ares_expand_name(p, abuf, alen, &name.as_char, &len); 634 if (status != ARES_SUCCESS) 635 return NULL; 636 printf("\t%s.", name.as_char); 637 ares_free_string(name.as_char); 638 p += len; 639 status = ares_expand_name(p, abuf, alen, &name.as_char, &len); 640 if (status != ARES_SUCCESS) 641 return NULL; 642 printf("\t%s.", name.as_char); 643 ares_free_string(name.as_char); 644 break; 645 646 case T_MX: 647 /* The RR data is two bytes giving a preference ordering, and 648 * then a domain name. 649 */ 650 if (dlen < 2) 651 return NULL; 652 printf("\t%d", DNS__16BIT(aptr)); 653 status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len); 654 if (status != ARES_SUCCESS) 655 return NULL; 656 printf("\t%s.", name.as_char); 657 ares_free_string(name.as_char); 658 break; 659 660 case T_SOA: 661 /* The RR data is two domain names and then five four-byte 662 * numbers giving the serial number and some timeouts. 663 */ 664 p = aptr; 665 status = ares_expand_name(p, abuf, alen, &name.as_char, &len); 666 if (status != ARES_SUCCESS) 667 return NULL; 668 printf("\t%s.\n", name.as_char); 669 ares_free_string(name.as_char); 670 p += len; 671 status = ares_expand_name(p, abuf, alen, &name.as_char, &len); 672 if (status != ARES_SUCCESS) 673 return NULL; 674 printf("\t\t\t\t\t\t%s.\n", name.as_char); 675 ares_free_string(name.as_char); 676 p += len; 677 if (p + 20 > aptr + dlen) 678 return NULL; 679 printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )", 680 (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4), 681 (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12), 682 (unsigned long)DNS__32BIT(p+16)); 683 break; 684 685 case T_TXT: 686 /* The RR data is one or more length-counted character 687 * strings. */ 688 p = aptr; 689 while (p < aptr + dlen) 690 { 691 len = *p; 692 if (p + len + 1 > aptr + dlen) 693 return NULL; 694 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 695 if (status != ARES_SUCCESS) 696 return NULL; 697 printf("\t%s", name.as_char); 698 ares_free_string(name.as_char); 699 p += len; 700 } 701 break; 702 703 case T_A: 704 /* The RR data is a four-byte Internet address. */ 705 if (dlen != 4) 706 return NULL; 707 printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr))); 708 break; 709 710 case T_AAAA: 711 /* The RR data is a 16-byte IPv6 address. */ 712 if (dlen != 16) 713 return NULL; 714 printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr))); 715 break; 716 717 case T_WKS: 718 /* Not implemented yet */ 719 break; 720 721 case T_SRV: 722 /* The RR data is three two-byte numbers representing the 723 * priority, weight, and port, followed by a domain name. 724 */ 725 726 printf("\t%d", DNS__16BIT(aptr)); 727 printf(" %d", DNS__16BIT(aptr + 2)); 728 printf(" %d", DNS__16BIT(aptr + 4)); 729 730 status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len); 731 if (status != ARES_SUCCESS) 732 return NULL; 733 printf("\t%s.", name.as_char); 734 ares_free_string(name.as_char); 735 break; 736 737 case T_NAPTR: 738 739 printf("\t%d", DNS__16BIT(aptr)); /* order */ 740 printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */ 741 742 p = aptr + 4; 743 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 744 if (status != ARES_SUCCESS) 745 return NULL; 746 printf("\t\t\t\t\t\t%s\n", name.as_char); 747 ares_free_string(name.as_char); 748 p += len; 749 750 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 751 if (status != ARES_SUCCESS) 752 return NULL; 753 printf("\t\t\t\t\t\t%s\n", name.as_char); 754 ares_free_string(name.as_char); 755 p += len; 756 757 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len); 758 if (status != ARES_SUCCESS) 759 return NULL; 760 printf("\t\t\t\t\t\t%s\n", name.as_char); 761 ares_free_string(name.as_char); 762 p += len; 763 764 status = ares_expand_name(p, abuf, alen, &name.as_char, &len); 765 if (status != ARES_SUCCESS) 766 return NULL; 767 printf("\t\t\t\t\t\t%s", name.as_char); 768 ares_free_string(name.as_char); 769 break; 770 771 case T_DS: 772 case T_SSHFP: 773 case T_RRSIG: 774 case T_NSEC: 775 case T_DNSKEY: 776 printf("\t[RR type parsing unavailable]"); 777 break; 778 779 default: 780 printf("\t[Unknown RR; cannot parse]"); 781 break; 782 } 783 printf("\n"); 784 785 return aptr + dlen; 786} 787 788static const char *type_name(int type) 789{ 790 int i; 791 792 for (i = 0; i < ntypes; i++) 793 { 794 if (types[i].value == type) 795 return types[i].name; 796 } 797 return "(unknown)"; 798} 799 800static const char *class_name(int dnsclass) 801{ 802 int i; 803 804 for (i = 0; i < nclasses; i++) 805 { 806 if (classes[i].value == dnsclass) 807 return classes[i].name; 808 } 809 return "(unknown)"; 810} 811 812static void usage(void) 813{ 814 fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] " 815 "[-t type] [-p port] name ...\n"); 816 exit(1); 817} 818 819static void destroy_addr_list(struct ares_addr_node *head) 820{ 821 while(head) 822 { 823 struct ares_addr_node *detached = head; 824 head = head->next; 825 free(detached); 826 } 827} 828 829static void append_addr_list(struct ares_addr_node **head, 830 struct ares_addr_node *node) 831{ 832 struct ares_addr_node *last; 833 node->next = NULL; 834 if(*head) 835 { 836 last = *head; 837 while(last->next) 838 last = last->next; 839 last->next = node; 840 } 841 else 842 *head = node; 843} 844