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