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