Create ares_build.h when buidling from Git.
[platform/upstream/c-ares.git] / adig.c
diff --git a/adig.c b/adig.c
index 6a23c51..e112dc0 100644 (file)
--- a/adig.c
+++ b/adig.c
@@ -1,6 +1,5 @@
 /* Copyright 1998 by the Massachusetts Institute of Technology.
  *
- * $Id$
  *
  * Permission to use, copy, modify, and distribute this
  * software and its documentation for any purpose and without
  * without express or implied warranty.
  */
 
-#include "setup.h"
-#include <sys/types.h>
+#include "ares_setup.h"
 
-#if defined(WIN32) && !defined(WATT32)
-#include "nameser.h"
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+#ifdef HAVE_NETINET_IN_H
+#  include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#  include <arpa/inet.h>
 #endif
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#ifdef HAVE_NETDB_H
+#  include <netdb.h>
 #endif
-#include <netdb.h>
+#ifdef HAVE_ARPA_NAMESER_H
+#  include <arpa/nameser.h>
+#else
+#  include "nameser.h"
 #endif
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#  include <arpa/nameser_compat.h>
 #endif
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
+#ifdef HAVE_STRINGS_H
+#  include <strings.h>
+#endif
 
 #include "ares.h"
 #include "ares_dns.h"
-#include "inet_ntop.h"
+#include "ares_getopt.h"
+#include "ares_nowarn.h"
 
-#ifdef WATT32
-#undef WIN32  /* Redefined in MingW headers */
+#ifndef HAVE_STRDUP
+#  include "ares_strdup.h"
+#  define strdup(ptr) ares_strdup(ptr)
 #endif
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
+#ifndef HAVE_STRCASECMP
+#  include "ares_strcasecmp.h"
+#  define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
 #endif
 
-/* Mac OS X portability check */
-#ifndef T_SRV
-#define T_SRV 33 /* server selection */
+#ifndef HAVE_STRNCASECMP
+#  include "ares_strcasecmp.h"
+#  define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
+#endif
+
+#ifdef WATT32
+#undef WIN32  /* Redefined in MingW headers */
 #endif
 
-#ifndef optind
-extern int optind;
-extern char *optarg;
+#ifndef T_SRV
+#  define T_SRV     33 /* Server selection */
+#endif
+#ifndef T_NAPTR
+#  define T_NAPTR   35 /* Naming authority pointer */
+#endif
+#ifndef T_DS
+#  define T_DS      43 /* Delegation Signer (RFC4034) */
+#endif
+#ifndef T_SSHFP
+#  define T_SSHFP   44 /* SSH Key Fingerprint (RFC4255) */
+#endif
+#ifndef T_RRSIG
+#  define T_RRSIG   46 /* Resource Record Signature (RFC4034) */
+#endif
+#ifndef T_NSEC
+#  define T_NSEC    47 /* Next Secure (RFC4034) */
+#endif
+#ifndef T_DNSKEY
+#  define T_DNSKEY  48 /* DNS Public Key (RFC4034) */
 #endif
 
 struct nv {
@@ -122,6 +141,12 @@ static const struct nv types[] = {
   { "AXFR",     T_AXFR },
   { "MAILB",    T_MAILB },
   { "MAILA",    T_MAILA },
+  { "NAPTR",    T_NAPTR },
+  { "DS",       T_DS },
+  { "SSHFP",    T_SSHFP },
+  { "RRSIG",    T_RRSIG },
+  { "NSEC",     T_NSEC },
+  { "DNSKEY",   T_DNSKEY },
   { "ANY",      T_ANY }
 };
 static const int ntypes = sizeof(types) / sizeof(types[0]);
@@ -139,7 +164,8 @@ static const char *rcodes[] = {
   "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
 };
 
-static void callback(void *arg, int status, unsigned char *abuf, int alen);
+static void callback(void *arg, int status, int timeouts,
+                     unsigned char *abuf, int alen);
 static const unsigned char *display_question(const unsigned char *aptr,
                                              const unsigned char *abuf,
                                              int alen);
@@ -148,6 +174,9 @@ static const unsigned char *display_rr(const unsigned char *aptr,
 static const char *type_name(int type);
 static const char *class_name(int dnsclass);
 static void usage(void);
+static void destroy_addr_list(struct ares_addr_node *head);
+static void append_addr_list(struct ares_addr_node **head,
+                             struct ares_addr_node *node);
 
 int main(int argc, char **argv)
 {
@@ -158,6 +187,7 @@ int main(int argc, char **argv)
   struct hostent *hostent;
   fd_set read_fds, write_fds;
   struct timeval *tvp, tv;
+  struct ares_addr_node *srvr, *servers = NULL;
 
 #ifdef USE_WINSOCK
   WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
@@ -165,10 +195,17 @@ int main(int argc, char **argv)
   WSAStartup(wVersionRequested, &wsaData);
 #endif
 
+  status = ares_library_init(ARES_LIB_INIT_ALL);
+  if (status != ARES_SUCCESS)
+    {
+      fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
+      return 1;
+    }
+
   options.flags = ARES_FLAG_NOCHECKRESP;
   options.servers = NULL;
   options.nservers = 0;
-  while ((c = getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
+  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
     {
       switch (c)
         {
@@ -185,29 +222,63 @@ int main(int argc, char **argv)
               if (strcmp(flags[i].name, optarg) == 0)
                 break;
             }
-          if (i == nflags)
+          if (i < nflags)
+            options.flags |= flags[i].value;
+          else
             usage();
-          options.flags |= flags[i].value;
           break;
 
         case 's':
-          /* Add a server, and specify servers in the option mask. */
-          hostent = gethostbyname(optarg);
-          if (!hostent || hostent->h_addrtype != AF_INET)
+          /* User-specified name servers override default ones. */
+          srvr = malloc(sizeof(struct ares_addr_node));
+          if (!srvr)
             {
-              fprintf(stderr, "adig: server %s not found.\n", optarg);
+              fprintf(stderr, "Out of memory!\n");
+              destroy_addr_list(servers);
               return 1;
             }
-          options.servers = realloc(options.servers, (options.nservers + 1)
-                                    * sizeof(struct in_addr));
-          if (!options.servers)
+          append_addr_list(&servers, srvr);
+          if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
+            srvr->family = AF_INET;
+          else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
+            srvr->family = AF_INET6;
+          else
             {
-              fprintf(stderr, "Out of memory!\n");
-              return 1;
+              hostent = gethostbyname(optarg);
+              if (!hostent)
+                {
+                  fprintf(stderr, "adig: server %s not found.\n", optarg);
+                  destroy_addr_list(servers);
+                  return 1;
+                }
+              switch (hostent->h_addrtype)
+                {
+                  case AF_INET:
+                    srvr->family = AF_INET;
+                    memcpy(&srvr->addr.addr4, hostent->h_addr,
+                           sizeof(srvr->addr.addr4));
+                    break;
+                  case AF_INET6:
+                    srvr->family = AF_INET6;
+                    memcpy(&srvr->addr.addr6, hostent->h_addr,
+                           sizeof(srvr->addr.addr6));
+                    break;
+                  default:
+                    fprintf(stderr,
+                      "adig: server %s unsupported address family.\n", optarg);
+                    destroy_addr_list(servers);
+                    return 1;
+                }
             }
-          memcpy(&options.servers[options.nservers], hostent->h_addr,
-                 sizeof(struct in_addr));
-          options.nservers++;
+          /* Notice that calling ares_init_options() without servers in the
+           * options struct and with ARES_OPT_SERVERS set simultaneously in
+           * the options mask, results in an initialization with no servers.
+           * When alternative name servers have been specified these are set
+           * later calling ares_set_servers() overriding any existing server
+           * configuration. To prevent initial configuration with default
+           * servers that will be discarded later, ARES_OPT_SERVERS is set.
+           * If this flag is not set here the result shall be the same but
+           * ares_init_options() will do needless work. */
           optmask |= ARES_OPT_SERVERS;
           break;
 
@@ -218,9 +289,10 @@ int main(int argc, char **argv)
               if (strcasecmp(classes[i].name, optarg) == 0)
                 break;
             }
-          if (i == nclasses)
+          if (i < nclasses)
+            dnsclass = classes[i].value;
+          else
             usage();
-          dnsclass = classes[i].value;
           break;
 
         case 't':
@@ -230,9 +302,10 @@ int main(int argc, char **argv)
               if (strcasecmp(types[i].name, optarg) == 0)
                 break;
             }
-          if (i == ntypes)
+          if (i < ntypes)
+            type = types[i].value;
+          else
             usage();
-          type = types[i].value;
           break;
 
         case 'T':
@@ -266,6 +339,18 @@ int main(int argc, char **argv)
       return 1;
     }
 
+  if(servers)
+    {
+      status = ares_set_servers(channel, servers);
+      destroy_addr_list(servers);
+      if (status != ARES_SUCCESS)
+        {
+          fprintf(stderr, "ares_init_options: %s\n",
+                  ares_strerror(status));
+          return 1;
+        }
+    }
+
   /* Initiate the queries, one per command-line argument.  If there is
    * only one query to do, supply NULL as the callback argument;
    * otherwise, supply the query name as an argument so we can
@@ -280,7 +365,7 @@ int main(int argc, char **argv)
     }
 
   /* Wait for all queries to complete. */
-  while (1)
+  for (;;)
     {
       FD_ZERO(&read_fds);
       FD_ZERO(&write_fds);
@@ -289,25 +374,35 @@ int main(int argc, char **argv)
         break;
       tvp = ares_timeout(channel, NULL, &tv);
       count = select(nfds, &read_fds, &write_fds, NULL, tvp);
-      if (count < 0 && errno != EINVAL)
+      if (count < 0 && (status = SOCKERRNO) != EINVAL)
         {
-          perror("select");
+          printf("select fail: %d", status);
           return 1;
         }
       ares_process(channel, &read_fds, &write_fds);
     }
 
   ares_destroy(channel);
+
+  ares_library_cleanup();
+
+#ifdef USE_WINSOCK
+  WSACleanup();
+#endif
+
   return 0;
 }
 
-static void callback(void *arg, int status, unsigned char *abuf, int alen)
+static void callback(void *arg, int status, int timeouts,
+                     unsigned char *abuf, int alen)
 {
   char *name = (char *) arg;
   int id, qr, opcode, aa, tc, rd, ra, rcode;
   unsigned int qdcount, ancount, nscount, arcount, i;
   const unsigned char *aptr;
 
+  (void) timeouts;
+
   /* Display the query name if given. */
   if (name)
     printf("Answer for query %s:\n", name);
@@ -432,13 +527,16 @@ static const unsigned char *display_rr(const unsigned char *aptr,
                                        const unsigned char *abuf, int alen)
 {
   const unsigned char *p;
-  char *name;
   int type, dnsclass, ttl, dlen, status;
   long len;
   char addr[46];
+  union {
+    unsigned char * as_uchar;
+             char * as_char;
+  } name;
 
   /* Parse the RR name. */
-  status = ares_expand_name(aptr, abuf, alen, &name, &len);
+  status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
   if (status != ARES_SUCCESS)
     return NULL;
   aptr += len;
@@ -448,7 +546,7 @@ static const unsigned char *display_rr(const unsigned char *aptr,
    */
   if (aptr + RRFIXEDSZ > abuf + alen)
     {
-      ares_free_string(name);
+      ares_free_string(name.as_char);
       return NULL;
     }
 
@@ -461,16 +559,16 @@ static const unsigned char *display_rr(const unsigned char *aptr,
   aptr += RRFIXEDSZ;
   if (aptr + dlen > abuf + alen)
     {
-      ares_free_string(name);
+      ares_free_string(name.as_char);
       return NULL;
     }
 
   /* Display the RR name, class, and type. */
-  printf("\t%-15s.\t%d", name, ttl);
+  printf("\t%-15s.\t%d", name.as_char, ttl);
   if (dnsclass != C_IN)
     printf("\t%s", class_name(dnsclass));
   printf("\t%s", type_name(type));
-  ares_free_string(name);
+  ares_free_string(name.as_char);
 
   /* Display the RR data.  Don't touch aptr. */
   switch (type)
@@ -484,11 +582,11 @@ static const unsigned char *display_rr(const unsigned char *aptr,
     case T_NS:
     case T_PTR:
       /* For these types, the RR data is just a domain name. */
-      status = ares_expand_name(aptr, abuf, alen, &name, &len);
+      status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.", name);
-      ares_free_string(name);
+      printf("\t%s.", name.as_char);
+      ares_free_string(name.as_char);
       break;
 
     case T_HINFO:
@@ -497,28 +595,36 @@ static const unsigned char *display_rr(const unsigned char *aptr,
       len = *p;
       if (p + len + 1 > aptr + dlen)
         return NULL;
-      printf("\t%.*s", (int)len, p + 1);
-      p += len + 1;
+      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t%s", name.as_char);
+      ares_free_string(name.as_char);
+      p += len;
       len = *p;
       if (p + len + 1 > aptr + dlen)
         return NULL;
-      printf("\t%.*s", (int)len, p + 1);
+      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t%s", name.as_char);
+      ares_free_string(name.as_char);
       break;
 
     case T_MINFO:
       /* The RR data is two domain names. */
       p = aptr;
-      status = ares_expand_name(p, abuf, alen, &name, &len);
+      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.", name);
-      ares_free_string(name);
+      printf("\t%s.", name.as_char);
+      ares_free_string(name.as_char);
       p += len;
-      status = ares_expand_name(p, abuf, alen, &name, &len);
+      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.", name);
-      ares_free_string(name);
+      printf("\t%s.", name.as_char);
+      ares_free_string(name.as_char);
       break;
 
     case T_MX:
@@ -527,12 +633,12 @@ static const unsigned char *display_rr(const unsigned char *aptr,
        */
       if (dlen < 2)
         return NULL;
-      printf("\t%d", DNS__16BIT(aptr));
-      status = ares_expand_name(aptr + 2, abuf, alen, &name, &len);
+      printf("\t%d", (int)DNS__16BIT(aptr));
+      status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.", name);
-      ares_free_string(name);
+      printf("\t%s.", name.as_char);
+      ares_free_string(name.as_char);
       break;
 
     case T_SOA:
@@ -540,24 +646,24 @@ static const unsigned char *display_rr(const unsigned char *aptr,
        * numbers giving the serial number and some timeouts.
        */
       p = aptr;
-      status = ares_expand_name(p, abuf, alen, &name, &len);
+      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.\n", name);
-      ares_free_string(name);
+      printf("\t%s.\n", name.as_char);
+      ares_free_string(name.as_char);
       p += len;
-      status = ares_expand_name(p, abuf, alen, &name, &len);
+      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t\t\t\t\t\t%s.\n", name);
-      ares_free_string(name);
+      printf("\t\t\t\t\t\t%s.\n", name.as_char);
+      ares_free_string(name.as_char);
       p += len;
       if (p + 20 > aptr + dlen)
         return NULL;
-      printf("\t\t\t\t\t\t( %lu %lu %lu %lu %lu )",
-             (unsigned long)DNS__32BIT(p), (unsigned long)DNS__32BIT(p+4),
-             (unsigned long)DNS__32BIT(p+8), (unsigned long)DNS__32BIT(p+12),
-             (unsigned long)DNS__32BIT(p+16));
+      printf("\t\t\t\t\t\t( %u %u %u %u %u )",
+             DNS__32BIT(p), DNS__32BIT(p+4),
+             DNS__32BIT(p+8), DNS__32BIT(p+12),
+             DNS__32BIT(p+16));
       break;
 
     case T_TXT:
@@ -569,8 +675,12 @@ static const unsigned char *display_rr(const unsigned char *aptr,
           len = *p;
           if (p + len + 1 > aptr + dlen)
             return NULL;
-          printf("\t%.*s", (int)len, p + 1);
-          p += len + 1;
+          status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+          if (status != ARES_SUCCESS)
+            return NULL;
+          printf("\t%s", name.as_char);
+          ares_free_string(name.as_char);
+          p += len;
         }
       break;
 
@@ -597,15 +707,57 @@ static const unsigned char *display_rr(const unsigned char *aptr,
        * priority, weight, and port, followed by a domain name.
        */
 
-      printf("\t%d", DNS__16BIT(aptr));
-      printf(" %d", DNS__16BIT(aptr + 2));
-      printf(" %d", DNS__16BIT(aptr + 4));
+      printf("\t%d", (int)DNS__16BIT(aptr));
+      printf(" %d", (int)DNS__16BIT(aptr + 2));
+      printf(" %d", (int)DNS__16BIT(aptr + 4));
 
-      status = ares_expand_name(aptr + 6, abuf, alen, &name, &len);
+      status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
       if (status != ARES_SUCCESS)
         return NULL;
-      printf("\t%s.", name);
-      ares_free_string(name);
+      printf("\t%s.", name.as_char);
+      ares_free_string(name.as_char);
+      break;
+
+    case T_NAPTR:
+
+      printf("\t%d", (int)DNS__16BIT(aptr)); /* order */
+      printf(" %d\n", (int)DNS__16BIT(aptr + 2)); /* preference */
+
+      p = aptr + 4;
+      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t\t\t\t\t\t%s\n", name.as_char);
+      ares_free_string(name.as_char);
+      p += len;
+
+      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t\t\t\t\t\t%s\n", name.as_char);
+      ares_free_string(name.as_char);
+      p += len;
+
+      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t\t\t\t\t\t%s\n", name.as_char);
+      ares_free_string(name.as_char);
+      p += len;
+
+      status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
+      if (status != ARES_SUCCESS)
+        return NULL;
+      printf("\t\t\t\t\t\t%s", name.as_char);
+      ares_free_string(name.as_char);
+      break;
+
+    case T_DS:
+    case T_SSHFP:
+    case T_RRSIG:
+    case T_NSEC:
+    case T_DNSKEY:
+      printf("\t[RR type parsing unavailable]");
       break;
 
     default:
@@ -647,3 +799,29 @@ static void usage(void)
           "[-t type] [-p port] name ...\n");
   exit(1);
 }
+
+static void destroy_addr_list(struct ares_addr_node *head)
+{
+  while(head)
+    {
+      struct ares_addr_node *detached = head;
+      head = head->next;
+      free(detached);
+    }
+}
+
+static void append_addr_list(struct ares_addr_node **head,
+                             struct ares_addr_node *node)
+{
+  struct ares_addr_node *last;
+  node->next = NULL;
+  if(*head)
+    {
+      last = *head;
+      while(last->next)
+        last = last->next;
+      last->next = node;
+    }
+  else
+    *head = node;
+}