1 /* Copyright 1998 by the Massachusetts Institute of Technology.
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.
17 #include "ares_setup.h"
19 #ifdef HAVE_SYS_SOCKET_H
20 # include <sys/socket.h>
22 #ifdef HAVE_NETINET_IN_H
23 # include <netinet/in.h>
25 #ifdef HAVE_ARPA_INET_H
26 # include <arpa/inet.h>
31 #ifdef HAVE_ARPA_NAMESER_H
32 # include <arpa/nameser.h>
36 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
37 # include <arpa/nameser_compat.h>
40 #ifdef HAVE_SYS_TIME_H
41 # include <sys/time.h>
58 #include "inet_ntop.h"
59 #include "inet_net_pton.h"
60 #include "ares_getopt.h"
63 # include "ares_strdup.h"
64 # define strdup(ptr) ares_strdup(ptr)
67 #ifndef HAVE_STRCASECMP
68 # include "ares_strcasecmp.h"
69 # define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
72 #ifndef HAVE_STRNCASECMP
73 # include "ares_strcasecmp.h"
74 # define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
78 #undef WIN32 /* Redefined in MingW headers */
81 /* Mac OS X portability check */
83 #define T_SRV 33 /* server selection */
86 /* AIX portability check */
88 #define T_NAPTR 35 /* naming authority pointer */
96 static const struct nv flags[] = {
97 { "usevc", ARES_FLAG_USEVC },
98 { "primary", ARES_FLAG_PRIMARY },
99 { "igntc", ARES_FLAG_IGNTC },
100 { "norecurse", ARES_FLAG_NORECURSE },
101 { "stayopen", ARES_FLAG_STAYOPEN },
102 { "noaliases", ARES_FLAG_NOALIASES }
104 static const int nflags = sizeof(flags) / sizeof(flags[0]);
106 static const struct nv classes[] = {
108 { "CHAOS", C_CHAOS },
112 static const int nclasses = sizeof(classes) / sizeof(classes[0]);
114 static const struct nv types[] = {
119 { "CNAME", T_CNAME },
127 { "HINFO", T_HINFO },
128 { "MINFO", T_MINFO },
132 { "AFSDB", T_AFSDB },
137 { "NSAP_PTR", T_NSAP_PTR },
146 { "MAILB", T_MAILB },
147 { "MAILA", T_MAILA },
148 { "NAPTR", T_NAPTR },
151 static const int ntypes = sizeof(types) / sizeof(types[0]);
153 static const char *opcodes[] = {
154 "QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY",
155 "(unknown)", "(unknown)", "(unknown)", "(unknown)",
156 "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA",
157 "ZONEINIT", "ZONEREF"
160 static const char *rcodes[] = {
161 "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
162 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
163 "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
166 static void callback(void *arg, int status, int timeouts,
167 unsigned char *abuf, int alen);
168 static const unsigned char *display_question(const unsigned char *aptr,
169 const unsigned char *abuf,
171 static const unsigned char *display_rr(const unsigned char *aptr,
172 const unsigned char *abuf, int alen);
173 static const char *type_name(int type);
174 static const char *class_name(int dnsclass);
175 static void usage(void);
176 static void destroy_addr_list(struct ares_addr_node *head);
177 static void append_addr_list(struct ares_addr_node **head,
178 struct ares_addr_node *node);
180 int main(int argc, char **argv)
182 ares_channel channel;
183 int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
184 int status, nfds, count;
185 struct ares_options options;
186 struct hostent *hostent;
187 fd_set read_fds, write_fds;
188 struct timeval *tvp, tv;
189 struct ares_addr_node *srvr, *servers = NULL;
192 WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
194 WSAStartup(wVersionRequested, &wsaData);
197 status = ares_library_init(ARES_LIB_INIT_ALL);
198 if (status != ARES_SUCCESS)
200 fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
204 options.flags = ARES_FLAG_NOCHECKRESP;
205 options.servers = NULL;
206 options.nservers = 0;
207 while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
219 for (i = 0; i < nflags; i++)
221 if (strcmp(flags[i].name, optarg) == 0)
225 options.flags |= flags[i].value;
231 /* User-specified name servers override default ones. */
232 srvr = malloc(sizeof(struct ares_addr_node));
235 fprintf(stderr, "Out of memory!\n");
236 destroy_addr_list(servers);
239 append_addr_list(&servers, srvr);
240 if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
241 srvr->family = AF_INET;
242 else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
243 srvr->family = AF_INET6;
246 hostent = gethostbyname(optarg);
249 fprintf(stderr, "adig: server %s not found.\n", optarg);
250 destroy_addr_list(servers);
253 switch (hostent->h_addrtype)
256 srvr->family = AF_INET;
257 memcpy(&srvr->addr.addr4, hostent->h_addr,
258 sizeof(srvr->addr.addr4));
261 srvr->family = AF_INET6;
262 memcpy(&srvr->addr.addr6, hostent->h_addr,
263 sizeof(srvr->addr.addr6));
267 "adig: server %s unsupported address family.\n", optarg);
268 destroy_addr_list(servers);
272 /* Notice that calling ares_init_options() without servers in the
273 * options struct and with ARES_OPT_SERVERS set simultaneously in
274 * the options mask, results in an initialization with no servers.
275 * When alternative name servers have been specified these are set
276 * later calling ares_set_servers() overriding any existing server
277 * configuration. To prevent initial configuration with default
278 * servers that will be discarded later, ARES_OPT_SERVERS is set.
279 * If this flag is not set here the result shall be the same but
280 * ares_init_options() will do needless work. */
281 optmask |= ARES_OPT_SERVERS;
285 /* Set the query class. */
286 for (i = 0; i < nclasses; i++)
288 if (strcasecmp(classes[i].name, optarg) == 0)
292 dnsclass = classes[i].value;
298 /* Set the query type. */
299 for (i = 0; i < ntypes; i++)
301 if (strcasecmp(types[i].name, optarg) == 0)
305 type = types[i].value;
311 /* Set the TCP port number. */
312 if (!ISDIGIT(*optarg))
314 options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
315 optmask |= ARES_OPT_TCP_PORT;
319 /* Set the UDP port number. */
320 if (!ISDIGIT(*optarg))
322 options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
323 optmask |= ARES_OPT_UDP_PORT;
332 status = ares_init_options(&channel, &options, optmask);
334 if (status != ARES_SUCCESS)
336 fprintf(stderr, "ares_init_options: %s\n",
337 ares_strerror(status));
343 status = ares_set_servers(channel, servers);
344 destroy_addr_list(servers);
345 if (status != ARES_SUCCESS)
347 fprintf(stderr, "ares_init_options: %s\n",
348 ares_strerror(status));
353 /* Initiate the queries, one per command-line argument. If there is
354 * only one query to do, supply NULL as the callback argument;
355 * otherwise, supply the query name as an argument so we can
356 * distinguish responses for the user when printing them out.
359 ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
362 for (; *argv; argv++)
363 ares_query(channel, *argv, dnsclass, type, callback, *argv);
366 /* Wait for all queries to complete. */
371 nfds = ares_fds(channel, &read_fds, &write_fds);
374 tvp = ares_timeout(channel, NULL, &tv);
375 count = select(nfds, &read_fds, &write_fds, NULL, tvp);
376 if (count < 0 && SOCKERRNO != EINVAL)
381 ares_process(channel, &read_fds, &write_fds);
384 ares_destroy(channel);
386 ares_library_cleanup();
395 static void callback(void *arg, int status, int timeouts,
396 unsigned char *abuf, int alen)
398 char *name = (char *) arg;
399 int id, qr, opcode, aa, tc, rd, ra, rcode;
400 unsigned int qdcount, ancount, nscount, arcount, i;
401 const unsigned char *aptr;
405 /* Display the query name if given. */
407 printf("Answer for query %s:\n", name);
409 /* Display an error message if there was an error, but only stop if
410 * we actually didn't get an answer buffer.
412 if (status != ARES_SUCCESS)
414 printf("%s\n", ares_strerror(status));
419 /* Won't happen, but check anyway, for safety. */
423 /* Parse the answer header. */
424 id = DNS_HEADER_QID(abuf);
425 qr = DNS_HEADER_QR(abuf);
426 opcode = DNS_HEADER_OPCODE(abuf);
427 aa = DNS_HEADER_AA(abuf);
428 tc = DNS_HEADER_TC(abuf);
429 rd = DNS_HEADER_RD(abuf);
430 ra = DNS_HEADER_RA(abuf);
431 rcode = DNS_HEADER_RCODE(abuf);
432 qdcount = DNS_HEADER_QDCOUNT(abuf);
433 ancount = DNS_HEADER_ANCOUNT(abuf);
434 nscount = DNS_HEADER_NSCOUNT(abuf);
435 arcount = DNS_HEADER_ARCOUNT(abuf);
437 /* Display the answer header. */
438 printf("id: %d\n", id);
439 printf("flags: %s%s%s%s%s\n",
445 printf("opcode: %s\n", opcodes[opcode]);
446 printf("rcode: %s\n", rcodes[rcode]);
448 /* Display the questions. */
449 printf("Questions:\n");
450 aptr = abuf + HFIXEDSZ;
451 for (i = 0; i < qdcount; i++)
453 aptr = display_question(aptr, abuf, alen);
458 /* Display the answers. */
459 printf("Answers:\n");
460 for (i = 0; i < ancount; i++)
462 aptr = display_rr(aptr, abuf, alen);
467 /* Display the NS records. */
468 printf("NS records:\n");
469 for (i = 0; i < nscount; i++)
471 aptr = display_rr(aptr, abuf, alen);
476 /* Display the additional records. */
477 printf("Additional records:\n");
478 for (i = 0; i < arcount; i++)
480 aptr = display_rr(aptr, abuf, alen);
486 static const unsigned char *display_question(const unsigned char *aptr,
487 const unsigned char *abuf,
491 int type, dnsclass, status;
494 /* Parse the question name. */
495 status = ares_expand_name(aptr, abuf, alen, &name, &len);
496 if (status != ARES_SUCCESS)
500 /* Make sure there's enough data after the name for the fixed part
503 if (aptr + QFIXEDSZ > abuf + alen)
505 ares_free_string(name);
509 /* Parse the question type and class. */
510 type = DNS_QUESTION_TYPE(aptr);
511 dnsclass = DNS_QUESTION_CLASS(aptr);
514 /* Display the question, in a format sort of similar to how we will
517 printf("\t%-15s.\t", name);
518 if (dnsclass != C_IN)
519 printf("\t%s", class_name(dnsclass));
520 printf("\t%s\n", type_name(type));
521 ares_free_string(name);
525 static const unsigned char *display_rr(const unsigned char *aptr,
526 const unsigned char *abuf, int alen)
528 const unsigned char *p;
529 int type, dnsclass, ttl, dlen, status;
533 unsigned char * as_uchar;
537 /* Parse the RR name. */
538 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
539 if (status != ARES_SUCCESS)
543 /* Make sure there is enough data after the RR name for the fixed
546 if (aptr + RRFIXEDSZ > abuf + alen)
548 ares_free_string(name.as_char);
552 /* Parse the fixed part of the RR, and advance to the RR data
554 type = DNS_RR_TYPE(aptr);
555 dnsclass = DNS_RR_CLASS(aptr);
556 ttl = DNS_RR_TTL(aptr);
557 dlen = DNS_RR_LEN(aptr);
559 if (aptr + dlen > abuf + alen)
561 ares_free_string(name.as_char);
565 /* Display the RR name, class, and type. */
566 printf("\t%-15s.\t%d", name.as_char, ttl);
567 if (dnsclass != C_IN)
568 printf("\t%s", class_name(dnsclass));
569 printf("\t%s", type_name(type));
570 ares_free_string(name.as_char);
572 /* Display the RR data. Don't touch aptr. */
583 /* For these types, the RR data is just a domain name. */
584 status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
585 if (status != ARES_SUCCESS)
587 printf("\t%s.", name.as_char);
588 ares_free_string(name.as_char);
592 /* The RR data is two length-counted character strings. */
595 if (p + len + 1 > aptr + dlen)
597 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
598 if (status != ARES_SUCCESS)
600 printf("\t%s", name.as_char);
601 ares_free_string(name.as_char);
604 if (p + len + 1 > aptr + dlen)
606 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
607 if (status != ARES_SUCCESS)
609 printf("\t%s", name.as_char);
610 ares_free_string(name.as_char);
614 /* The RR data is two domain names. */
616 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
617 if (status != ARES_SUCCESS)
619 printf("\t%s.", name.as_char);
620 ares_free_string(name.as_char);
622 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
623 if (status != ARES_SUCCESS)
625 printf("\t%s.", name.as_char);
626 ares_free_string(name.as_char);
630 /* The RR data is two bytes giving a preference ordering, and
631 * then a domain name.
635 printf("\t%d", DNS__16BIT(aptr));
636 status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
637 if (status != ARES_SUCCESS)
639 printf("\t%s.", name.as_char);
640 ares_free_string(name.as_char);
644 /* The RR data is two domain names and then five four-byte
645 * numbers giving the serial number and some timeouts.
648 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
649 if (status != ARES_SUCCESS)
651 printf("\t%s.\n", name.as_char);
652 ares_free_string(name.as_char);
654 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
655 if (status != ARES_SUCCESS)
657 printf("\t\t\t\t\t\t%s.\n", name.as_char);
658 ares_free_string(name.as_char);
660 if (p + 20 > aptr + dlen)
662 printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
663 (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4),
664 (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12),
665 (unsigned long)DNS__32BIT(p+16));
669 /* The RR data is one or more length-counted character
672 while (p < aptr + dlen)
675 if (p + len + 1 > aptr + dlen)
677 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
678 if (status != ARES_SUCCESS)
680 printf("\t%s", name.as_char);
681 ares_free_string(name.as_char);
687 /* The RR data is a four-byte Internet address. */
690 printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
694 /* The RR data is a 16-byte IPv6 address. */
697 printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
701 /* Not implemented yet */
705 /* The RR data is three two-byte numbers representing the
706 * priority, weight, and port, followed by a domain name.
709 printf("\t%d", DNS__16BIT(aptr));
710 printf(" %d", DNS__16BIT(aptr + 2));
711 printf(" %d", DNS__16BIT(aptr + 4));
713 status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
714 if (status != ARES_SUCCESS)
716 printf("\t%s.", name.as_char);
717 ares_free_string(name.as_char);
722 printf("\t%d", DNS__16BIT(aptr)); /* order */
723 printf(" %d\n", DNS__16BIT(aptr + 2)); /* preference */
726 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
727 if (status != ARES_SUCCESS)
729 printf("\t\t\t\t\t\t%s\n", name.as_char);
730 ares_free_string(name.as_char);
733 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
734 if (status != ARES_SUCCESS)
736 printf("\t\t\t\t\t\t%s\n", name.as_char);
737 ares_free_string(name.as_char);
740 status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
741 if (status != ARES_SUCCESS)
743 printf("\t\t\t\t\t\t%s\n", name.as_char);
744 ares_free_string(name.as_char);
747 status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
748 if (status != ARES_SUCCESS)
750 printf("\t\t\t\t\t\t%s", name.as_char);
751 ares_free_string(name.as_char);
756 printf("\t[Unknown RR; cannot parse]");
764 static const char *type_name(int type)
768 for (i = 0; i < ntypes; i++)
770 if (types[i].value == type)
771 return types[i].name;
776 static const char *class_name(int dnsclass)
780 for (i = 0; i < nclasses; i++)
782 if (classes[i].value == dnsclass)
783 return classes[i].name;
788 static void usage(void)
790 fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] "
791 "[-t type] [-p port] name ...\n");
795 static void destroy_addr_list(struct ares_addr_node *head)
799 struct ares_addr_node *detached = head;
805 static void append_addr_list(struct ares_addr_node **head,
806 struct ares_addr_node *node)
808 struct ares_addr_node *last;