Blame adig.c

Packit 514978
/* Copyright 1998 by the Massachusetts Institute of Technology.
Packit 514978
 *
Packit 514978
 *
Packit 514978
 * Permission to use, copy, modify, and distribute this
Packit 514978
 * software and its documentation for any purpose and without
Packit 514978
 * fee is hereby granted, provided that the above copyright
Packit 514978
 * notice appear in all copies and that both that copyright
Packit 514978
 * notice and this permission notice appear in supporting
Packit 514978
 * documentation, and that the name of M.I.T. not be used in
Packit 514978
 * advertising or publicity pertaining to distribution of the
Packit 514978
 * software without specific, written prior permission.
Packit 514978
 * M.I.T. makes no representations about the suitability of
Packit 514978
 * this software for any purpose.  It is provided "as is"
Packit 514978
 * without express or implied warranty.
Packit 514978
 */
Packit 514978
Packit 514978
#include "ares_setup.h"
Packit 514978
Packit 514978
#ifdef HAVE_NETINET_IN_H
Packit 514978
#  include <netinet/in.h>
Packit 514978
#endif
Packit 514978
#ifdef HAVE_ARPA_INET_H
Packit 514978
#  include <arpa/inet.h>
Packit 514978
#endif
Packit 514978
#ifdef HAVE_NETDB_H
Packit 514978
#  include <netdb.h>
Packit 514978
#endif
Packit 514978
#ifdef HAVE_ARPA_NAMESER_H
Packit 514978
#  include <arpa/nameser.h>
Packit 514978
#else
Packit 514978
#  include "nameser.h"
Packit 514978
#endif
Packit 514978
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
Packit 514978
#  include <arpa/nameser_compat.h>
Packit 514978
#endif
Packit 514978
Packit 514978
#ifdef HAVE_STRINGS_H
Packit 514978
#  include <strings.h>
Packit 514978
#endif
Packit 514978
Packit 514978
#include "ares.h"
Packit 514978
#include "ares_dns.h"
Packit 514978
#include "ares_getopt.h"
Packit 514978
#include "ares_nowarn.h"
Packit 514978
Packit 514978
#ifndef HAVE_STRDUP
Packit 514978
#  include "ares_strdup.h"
Packit 514978
#  define strdup(ptr) ares_strdup(ptr)
Packit 514978
#endif
Packit 514978
Packit 514978
#ifndef HAVE_STRCASECMP
Packit 514978
#  include "ares_strcasecmp.h"
Packit 514978
#  define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
Packit 514978
#endif
Packit 514978
Packit 514978
#ifndef HAVE_STRNCASECMP
Packit 514978
#  include "ares_strcasecmp.h"
Packit 514978
#  define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
Packit 514978
#endif
Packit 514978
Packit 514978
#ifdef WATT32
Packit 514978
#undef WIN32  /* Redefined in MingW headers */
Packit 514978
#endif
Packit 514978
Packit 514978
#ifndef T_SRV
Packit 514978
#  define T_SRV     33 /* Server selection */
Packit 514978
#endif
Packit 514978
#ifndef T_NAPTR
Packit 514978
#  define T_NAPTR   35 /* Naming authority pointer */
Packit 514978
#endif
Packit 514978
#ifndef T_DS
Packit 514978
#  define T_DS      43 /* Delegation Signer (RFC4034) */
Packit 514978
#endif
Packit 514978
#ifndef T_SSHFP
Packit 514978
#  define T_SSHFP   44 /* SSH Key Fingerprint (RFC4255) */
Packit 514978
#endif
Packit 514978
#ifndef T_RRSIG
Packit 514978
#  define T_RRSIG   46 /* Resource Record Signature (RFC4034) */
Packit 514978
#endif
Packit 514978
#ifndef T_NSEC
Packit 514978
#  define T_NSEC    47 /* Next Secure (RFC4034) */
Packit 514978
#endif
Packit 514978
#ifndef T_DNSKEY
Packit 514978
#  define T_DNSKEY  48 /* DNS Public Key (RFC4034) */
Packit 514978
#endif
Packit 514978
Packit 514978
struct nv {
Packit 514978
  const char *name;
Packit 514978
  int value;
Packit 514978
};
Packit 514978
Packit 514978
static const struct nv flags[] = {
Packit 514978
  { "usevc",            ARES_FLAG_USEVC },
Packit 514978
  { "primary",          ARES_FLAG_PRIMARY },
Packit 514978
  { "igntc",            ARES_FLAG_IGNTC },
Packit 514978
  { "norecurse",        ARES_FLAG_NORECURSE },
Packit 514978
  { "stayopen",         ARES_FLAG_STAYOPEN },
Packit 514978
  { "noaliases",        ARES_FLAG_NOALIASES }
Packit 514978
};
Packit 514978
static const int nflags = sizeof(flags) / sizeof(flags[0]);
Packit 514978
Packit 514978
static const struct nv classes[] = {
Packit 514978
  { "IN",       C_IN },
Packit 514978
  { "CHAOS",    C_CHAOS },
Packit 514978
  { "HS",       C_HS },
Packit 514978
  { "ANY",      C_ANY }
Packit 514978
};
Packit 514978
static const int nclasses = sizeof(classes) / sizeof(classes[0]);
Packit 514978
Packit 514978
static const struct nv types[] = {
Packit 514978
  { "A",        T_A },
Packit 514978
  { "NS",       T_NS },
Packit 514978
  { "MD",       T_MD },
Packit 514978
  { "MF",       T_MF },
Packit 514978
  { "CNAME",    T_CNAME },
Packit 514978
  { "SOA",      T_SOA },
Packit 514978
  { "MB",       T_MB },
Packit 514978
  { "MG",       T_MG },
Packit 514978
  { "MR",       T_MR },
Packit 514978
  { "NULL",     T_NULL },
Packit 514978
  { "WKS",      T_WKS },
Packit 514978
  { "PTR",      T_PTR },
Packit 514978
  { "HINFO",    T_HINFO },
Packit 514978
  { "MINFO",    T_MINFO },
Packit 514978
  { "MX",       T_MX },
Packit 514978
  { "TXT",      T_TXT },
Packit 514978
  { "RP",       T_RP },
Packit 514978
  { "AFSDB",    T_AFSDB },
Packit 514978
  { "X25",      T_X25 },
Packit 514978
  { "ISDN",     T_ISDN },
Packit 514978
  { "RT",       T_RT },
Packit 514978
  { "NSAP",     T_NSAP },
Packit 514978
  { "NSAP_PTR", T_NSAP_PTR },
Packit 514978
  { "SIG",      T_SIG },
Packit 514978
  { "KEY",      T_KEY },
Packit 514978
  { "PX",       T_PX },
Packit 514978
  { "GPOS",     T_GPOS },
Packit 514978
  { "AAAA",     T_AAAA },
Packit 514978
  { "LOC",      T_LOC },
Packit 514978
  { "SRV",      T_SRV },
Packit 514978
  { "AXFR",     T_AXFR },
Packit 514978
  { "MAILB",    T_MAILB },
Packit 514978
  { "MAILA",    T_MAILA },
Packit 514978
  { "NAPTR",    T_NAPTR },
Packit 514978
  { "DS",       T_DS },
Packit 514978
  { "SSHFP",    T_SSHFP },
Packit 514978
  { "RRSIG",    T_RRSIG },
Packit 514978
  { "NSEC",     T_NSEC },
Packit 514978
  { "DNSKEY",   T_DNSKEY },
Packit 514978
  { "ANY",      T_ANY }
Packit 514978
};
Packit 514978
static const int ntypes = sizeof(types) / sizeof(types[0]);
Packit 514978
Packit 514978
static const char *opcodes[] = {
Packit 514978
  "QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY",
Packit 514978
  "(unknown)", "(unknown)", "(unknown)", "(unknown)",
Packit 514978
  "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA",
Packit 514978
  "ZONEINIT", "ZONEREF"
Packit 514978
};
Packit 514978
Packit 514978
static const char *rcodes[] = {
Packit 514978
  "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
Packit 514978
  "(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
Packit 514978
  "(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
Packit 514978
};
Packit 514978
Packit 514978
static void callback(void *arg, int status, int timeouts,
Packit 514978
                     unsigned char *abuf, int alen);
Packit 514978
static const unsigned char *display_question(const unsigned char *aptr,
Packit 514978
                                             const unsigned char *abuf,
Packit 514978
                                             int alen);
Packit 514978
static const unsigned char *display_rr(const unsigned char *aptr,
Packit 514978
                                       const unsigned char *abuf, int alen);
Packit 514978
static const char *type_name(int type);
Packit 514978
static const char *class_name(int dnsclass);
Packit 514978
static void usage(void);
Packit 514978
static void destroy_addr_list(struct ares_addr_node *head);
Packit 514978
static void append_addr_list(struct ares_addr_node **head,
Packit 514978
                             struct ares_addr_node *node);
Packit 514978
Packit 514978
int main(int argc, char **argv)
Packit 514978
{
Packit 514978
  ares_channel channel;
Packit 514978
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
Packit 514978
  int status, nfds, count;
Packit 514978
  struct ares_options options;
Packit 514978
  struct hostent *hostent;
Packit 514978
  fd_set read_fds, write_fds;
Packit 514978
  struct timeval *tvp, tv;
Packit 514978
  struct ares_addr_node *srvr, *servers = NULL;
Packit 514978
Packit 514978
#ifdef USE_WINSOCK
Packit 514978
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
Packit 514978
  WSADATA wsaData;
Packit 514978
  WSAStartup(wVersionRequested, &wsaData);
Packit 514978
#endif
Packit 514978
Packit 514978
  status = ares_library_init(ARES_LIB_INIT_ALL);
Packit 514978
  if (status != ARES_SUCCESS)
Packit 514978
    {
Packit 514978
      fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
Packit 514978
      return 1;
Packit 514978
    }
Packit 514978
Packit 514978
  options.flags = ARES_FLAG_NOCHECKRESP;
Packit 514978
  options.servers = NULL;
Packit 514978
  options.nservers = 0;
Packit 514978
  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
Packit 514978
    {
Packit 514978
      switch (c)
Packit 514978
        {
Packit 514978
        case 'd':
Packit 514978
#ifdef WATT32
Packit 514978
          dbug_init();
Packit 514978
#endif
Packit 514978
          break;
Packit 514978
Packit 514978
        case 'f':
Packit 514978
          /* Add a flag. */
Packit 514978
          for (i = 0; i < nflags; i++)
Packit 514978
            {
Packit 514978
              if (strcmp(flags[i].name, optarg) == 0)
Packit 514978
                break;
Packit 514978
            }
Packit 514978
          if (i < nflags)
Packit 514978
            options.flags |= flags[i].value;
Packit 514978
          else
Packit 514978
            usage();
Packit 514978
          break;
Packit 514978
Packit 514978
        case 's':
Packit 514978
          /* User-specified name servers override default ones. */
Packit 514978
          srvr = malloc(sizeof(struct ares_addr_node));
Packit 514978
          if (!srvr)
Packit 514978
            {
Packit 514978
              fprintf(stderr, "Out of memory!\n");
Packit 514978
              destroy_addr_list(servers);
Packit 514978
              return 1;
Packit 514978
            }
Packit 514978
          append_addr_list(&servers, srvr);
Packit 514978
          if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
Packit 514978
            srvr->family = AF_INET;
Packit 514978
          else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
Packit 514978
            srvr->family = AF_INET6;
Packit 514978
          else
Packit 514978
            {
Packit 514978
              hostent = gethostbyname(optarg);
Packit 514978
              if (!hostent)
Packit 514978
                {
Packit 514978
                  fprintf(stderr, "adig: server %s not found.\n", optarg);
Packit 514978
                  destroy_addr_list(servers);
Packit 514978
                  return 1;
Packit 514978
                }
Packit 514978
              switch (hostent->h_addrtype)
Packit 514978
                {
Packit 514978
                  case AF_INET:
Packit 514978
                    srvr->family = AF_INET;
Packit 514978
                    memcpy(&srvr->addr.addr4, hostent->h_addr,
Packit 514978
                           sizeof(srvr->addr.addr4));
Packit 514978
                    break;
Packit 514978
                  case AF_INET6:
Packit 514978
                    srvr->family = AF_INET6;
Packit 514978
                    memcpy(&srvr->addr.addr6, hostent->h_addr,
Packit 514978
                           sizeof(srvr->addr.addr6));
Packit 514978
                    break;
Packit 514978
                  default:
Packit 514978
                    fprintf(stderr,
Packit 514978
                      "adig: server %s unsupported address family.\n", optarg);
Packit 514978
                    destroy_addr_list(servers);
Packit 514978
                    return 1;
Packit 514978
                }
Packit 514978
            }
Packit 514978
          /* Notice that calling ares_init_options() without servers in the
Packit 514978
           * options struct and with ARES_OPT_SERVERS set simultaneously in
Packit 514978
           * the options mask, results in an initialization with no servers.
Packit 514978
           * When alternative name servers have been specified these are set
Packit 514978
           * later calling ares_set_servers() overriding any existing server
Packit 514978
           * configuration. To prevent initial configuration with default
Packit 514978
           * servers that will be discarded later, ARES_OPT_SERVERS is set.
Packit 514978
           * If this flag is not set here the result shall be the same but
Packit 514978
           * ares_init_options() will do needless work. */
Packit 514978
          optmask |= ARES_OPT_SERVERS;
Packit 514978
          break;
Packit 514978
Packit 514978
        case 'c':
Packit 514978
          /* Set the query class. */
Packit 514978
          for (i = 0; i < nclasses; i++)
Packit 514978
            {
Packit 514978
              if (strcasecmp(classes[i].name, optarg) == 0)
Packit 514978
                break;
Packit 514978
            }
Packit 514978
          if (i < nclasses)
Packit 514978
            dnsclass = classes[i].value;
Packit 514978
          else
Packit 514978
            usage();
Packit 514978
          break;
Packit 514978
Packit 514978
        case 't':
Packit 514978
          /* Set the query type. */
Packit 514978
          for (i = 0; i < ntypes; i++)
Packit 514978
            {
Packit 514978
              if (strcasecmp(types[i].name, optarg) == 0)
Packit 514978
                break;
Packit 514978
            }
Packit 514978
          if (i < ntypes)
Packit 514978
            type = types[i].value;
Packit 514978
          else
Packit 514978
            usage();
Packit 514978
          break;
Packit 514978
Packit 514978
        case 'T':
Packit 514978
          /* Set the TCP port number. */
Packit 514978
          if (!ISDIGIT(*optarg))
Packit 514978
            usage();
Packit 514978
          options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
Packit 514978
          optmask |= ARES_OPT_TCP_PORT;
Packit 514978
          break;
Packit 514978
Packit 514978
        case 'U':
Packit 514978
          /* Set the UDP port number. */
Packit 514978
          if (!ISDIGIT(*optarg))
Packit 514978
            usage();
Packit 514978
          options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
Packit 514978
          optmask |= ARES_OPT_UDP_PORT;
Packit 514978
          break;
Packit 514978
        }
Packit 514978
    }
Packit 514978
  argc -= optind;
Packit 514978
  argv += optind;
Packit 514978
  if (argc == 0)
Packit 514978
    usage();
Packit 514978
Packit 514978
  status = ares_init_options(&channel, &options, optmask);
Packit 514978
Packit 514978
  if (status != ARES_SUCCESS)
Packit 514978
    {
Packit 514978
      fprintf(stderr, "ares_init_options: %s\n",
Packit 514978
              ares_strerror(status));
Packit 514978
      return 1;
Packit 514978
    }
Packit 514978
Packit 514978
  if(servers)
Packit 514978
    {
Packit 514978
      status = ares_set_servers(channel, servers);
Packit 514978
      destroy_addr_list(servers);
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        {
Packit 514978
          fprintf(stderr, "ares_init_options: %s\n",
Packit 514978
                  ares_strerror(status));
Packit 514978
          return 1;
Packit 514978
        }
Packit 514978
    }
Packit 514978
Packit 514978
  /* Initiate the queries, one per command-line argument.  If there is
Packit 514978
   * only one query to do, supply NULL as the callback argument;
Packit 514978
   * otherwise, supply the query name as an argument so we can
Packit 514978
   * distinguish responses for the user when printing them out.
Packit 514978
   */
Packit 514978
  if (argc == 1)
Packit 514978
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
Packit 514978
  else
Packit 514978
    {
Packit 514978
      for (; *argv; argv++)
Packit 514978
        ares_query(channel, *argv, dnsclass, type, callback, *argv);
Packit 514978
    }
Packit 514978
Packit 514978
  /* Wait for all queries to complete. */
Packit 514978
  for (;;)
Packit 514978
    {
Packit 514978
      FD_ZERO(&read_fds);
Packit 514978
      FD_ZERO(&write_fds);
Packit 514978
      nfds = ares_fds(channel, &read_fds, &write_fds);
Packit 514978
      if (nfds == 0)
Packit 514978
        break;
Packit 514978
      tvp = ares_timeout(channel, NULL, &tv;;
Packit 514978
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
Packit 514978
      if (count < 0 && (status = SOCKERRNO) != EINVAL)
Packit 514978
        {
Packit 514978
          printf("select fail: %d", status);
Packit 514978
          return 1;
Packit 514978
        }
Packit 514978
      ares_process(channel, &read_fds, &write_fds);
Packit 514978
    }
Packit 514978
Packit 514978
  ares_destroy(channel);
Packit 514978
Packit 514978
  ares_library_cleanup();
Packit 514978
Packit 514978
#ifdef USE_WINSOCK
Packit 514978
  WSACleanup();
Packit 514978
#endif
Packit 514978
Packit 514978
  return 0;
Packit 514978
}
Packit 514978
Packit 514978
static void callback(void *arg, int status, int timeouts,
Packit 514978
                     unsigned char *abuf, int alen)
Packit 514978
{
Packit 514978
  char *name = (char *) arg;
Packit 514978
  int id, qr, opcode, aa, tc, rd, ra, rcode;
Packit 514978
  unsigned int qdcount, ancount, nscount, arcount, i;
Packit 514978
  const unsigned char *aptr;
Packit 514978
Packit 514978
  (void) timeouts;
Packit 514978
Packit 514978
  /* Display the query name if given. */
Packit 514978
  if (name)
Packit 514978
    printf("Answer for query %s:\n", name);
Packit 514978
Packit 514978
  /* Display an error message if there was an error, but only stop if
Packit 514978
   * we actually didn't get an answer buffer.
Packit 514978
   */
Packit 514978
  if (status != ARES_SUCCESS)
Packit 514978
    {
Packit 514978
      printf("%s\n", ares_strerror(status));
Packit 514978
      if (!abuf)
Packit 514978
        return;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Won't happen, but check anyway, for safety. */
Packit 514978
  if (alen < HFIXEDSZ)
Packit 514978
    return;
Packit 514978
Packit 514978
  /* Parse the answer header. */
Packit 514978
  id = DNS_HEADER_QID(abuf);
Packit 514978
  qr = DNS_HEADER_QR(abuf);
Packit 514978
  opcode = DNS_HEADER_OPCODE(abuf);
Packit 514978
  aa = DNS_HEADER_AA(abuf);
Packit 514978
  tc = DNS_HEADER_TC(abuf);
Packit 514978
  rd = DNS_HEADER_RD(abuf);
Packit 514978
  ra = DNS_HEADER_RA(abuf);
Packit 514978
  rcode = DNS_HEADER_RCODE(abuf);
Packit 514978
  qdcount = DNS_HEADER_QDCOUNT(abuf);
Packit 514978
  ancount = DNS_HEADER_ANCOUNT(abuf);
Packit 514978
  nscount = DNS_HEADER_NSCOUNT(abuf);
Packit 514978
  arcount = DNS_HEADER_ARCOUNT(abuf);
Packit 514978
Packit 514978
  /* Display the answer header. */
Packit 514978
  printf("id: %d\n", id);
Packit 514978
  printf("flags: %s%s%s%s%s\n",
Packit 514978
         qr ? "qr " : "",
Packit 514978
         aa ? "aa " : "",
Packit 514978
         tc ? "tc " : "",
Packit 514978
         rd ? "rd " : "",
Packit 514978
         ra ? "ra " : "");
Packit 514978
  printf("opcode: %s\n", opcodes[opcode]);
Packit 514978
  printf("rcode: %s\n", rcodes[rcode]);
Packit 514978
Packit 514978
  /* Display the questions. */
Packit 514978
  printf("Questions:\n");
Packit 514978
  aptr = abuf + HFIXEDSZ;
Packit 514978
  for (i = 0; i < qdcount; i++)
Packit 514978
    {
Packit 514978
      aptr = display_question(aptr, abuf, alen);
Packit 514978
      if (aptr == NULL)
Packit 514978
        return;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Display the answers. */
Packit 514978
  printf("Answers:\n");
Packit 514978
  for (i = 0; i < ancount; i++)
Packit 514978
    {
Packit 514978
      aptr = display_rr(aptr, abuf, alen);
Packit 514978
      if (aptr == NULL)
Packit 514978
        return;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Display the NS records. */
Packit 514978
  printf("NS records:\n");
Packit 514978
  for (i = 0; i < nscount; i++)
Packit 514978
    {
Packit 514978
      aptr = display_rr(aptr, abuf, alen);
Packit 514978
      if (aptr == NULL)
Packit 514978
        return;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Display the additional records. */
Packit 514978
  printf("Additional records:\n");
Packit 514978
  for (i = 0; i < arcount; i++)
Packit 514978
    {
Packit 514978
      aptr = display_rr(aptr, abuf, alen);
Packit 514978
      if (aptr == NULL)
Packit 514978
        return;
Packit 514978
    }
Packit 514978
}
Packit 514978
Packit 514978
static const unsigned char *display_question(const unsigned char *aptr,
Packit 514978
                                             const unsigned char *abuf,
Packit 514978
                                             int alen)
Packit 514978
{
Packit 514978
  char *name;
Packit 514978
  int type, dnsclass, status;
Packit 514978
  long len;
Packit 514978
Packit 514978
  /* Parse the question name. */
Packit 514978
  status = ares_expand_name(aptr, abuf, alen, &name, &len;;
Packit 514978
  if (status != ARES_SUCCESS)
Packit 514978
    return NULL;
Packit 514978
  aptr += len;
Packit 514978
Packit 514978
  /* Make sure there's enough data after the name for the fixed part
Packit 514978
   * of the question.
Packit 514978
   */
Packit 514978
  if (aptr + QFIXEDSZ > abuf + alen)
Packit 514978
    {
Packit 514978
      ares_free_string(name);
Packit 514978
      return NULL;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Parse the question type and class. */
Packit 514978
  type = DNS_QUESTION_TYPE(aptr);
Packit 514978
  dnsclass = DNS_QUESTION_CLASS(aptr);
Packit 514978
  aptr += QFIXEDSZ;
Packit 514978
Packit 514978
  /* Display the question, in a format sort of similar to how we will
Packit 514978
   * display RRs.
Packit 514978
   */
Packit 514978
  printf("\t%-15s.\t", name);
Packit 514978
  if (dnsclass != C_IN)
Packit 514978
    printf("\t%s", class_name(dnsclass));
Packit 514978
  printf("\t%s\n", type_name(type));
Packit 514978
  ares_free_string(name);
Packit 514978
  return aptr;
Packit 514978
}
Packit 514978
Packit 514978
static const unsigned char *display_rr(const unsigned char *aptr,
Packit 514978
                                       const unsigned char *abuf, int alen)
Packit 514978
{
Packit 514978
  const unsigned char *p;
Packit 514978
  int type, dnsclass, ttl, dlen, status;
Packit 514978
  long len;
Packit 514978
  char addr[46];
Packit 514978
  union {
Packit 514978
    unsigned char * as_uchar;
Packit 514978
             char * as_char;
Packit 514978
  } name;
Packit 514978
Packit 514978
  /* Parse the RR name. */
Packit 514978
  status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len;;
Packit 514978
  if (status != ARES_SUCCESS)
Packit 514978
    return NULL;
Packit 514978
  aptr += len;
Packit 514978
Packit 514978
  /* Make sure there is enough data after the RR name for the fixed
Packit 514978
   * part of the RR.
Packit 514978
   */
Packit 514978
  if (aptr + RRFIXEDSZ > abuf + alen)
Packit 514978
    {
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      return NULL;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Parse the fixed part of the RR, and advance to the RR data
Packit 514978
   * field. */
Packit 514978
  type = DNS_RR_TYPE(aptr);
Packit 514978
  dnsclass = DNS_RR_CLASS(aptr);
Packit 514978
  ttl = DNS_RR_TTL(aptr);
Packit 514978
  dlen = DNS_RR_LEN(aptr);
Packit 514978
  aptr += RRFIXEDSZ;
Packit 514978
  if (aptr + dlen > abuf + alen)
Packit 514978
    {
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      return NULL;
Packit 514978
    }
Packit 514978
Packit 514978
  /* Display the RR name, class, and type. */
Packit 514978
  printf("\t%-15s.\t%d", name.as_char, ttl);
Packit 514978
  if (dnsclass != C_IN)
Packit 514978
    printf("\t%s", class_name(dnsclass));
Packit 514978
  printf("\t%s", type_name(type));
Packit 514978
  ares_free_string(name.as_char);
Packit 514978
Packit 514978
  /* Display the RR data.  Don't touch aptr. */
Packit 514978
  switch (type)
Packit 514978
    {
Packit 514978
    case T_CNAME:
Packit 514978
    case T_MB:
Packit 514978
    case T_MD:
Packit 514978
    case T_MF:
Packit 514978
    case T_MG:
Packit 514978
    case T_MR:
Packit 514978
    case T_NS:
Packit 514978
    case T_PTR:
Packit 514978
      /* For these types, the RR data is just a domain name. */
Packit 514978
      status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_HINFO:
Packit 514978
      /* The RR data is two length-counted character strings. */
Packit 514978
      p = aptr;
Packit 514978
      len = *p;
Packit 514978
      if (p + len + 1 > aptr + dlen)
Packit 514978
        return NULL;
Packit 514978
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
      len = *p;
Packit 514978
      if (p + len + 1 > aptr + dlen)
Packit 514978
        return NULL;
Packit 514978
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_MINFO:
Packit 514978
      /* The RR data is two domain names. */
Packit 514978
      p = aptr;
Packit 514978
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_MX:
Packit 514978
      /* The RR data is two bytes giving a preference ordering, and
Packit 514978
       * then a domain name.
Packit 514978
       */
Packit 514978
      if (dlen < 2)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%d", (int)DNS__16BIT(aptr));
Packit 514978
      status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_SOA:
Packit 514978
      /* The RR data is two domain names and then five four-byte
Packit 514978
       * numbers giving the serial number and some timeouts.
Packit 514978
       */
Packit 514978
      p = aptr;
Packit 514978
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.\n", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t%s.\n", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
      if (p + 20 > aptr + dlen)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t( %u %u %u %u %u )",
Packit 514978
             DNS__32BIT(p), DNS__32BIT(p+4),
Packit 514978
             DNS__32BIT(p+8), DNS__32BIT(p+12),
Packit 514978
             DNS__32BIT(p+16));
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_TXT:
Packit 514978
      /* The RR data is one or more length-counted character
Packit 514978
       * strings. */
Packit 514978
      p = aptr;
Packit 514978
      while (p < aptr + dlen)
Packit 514978
        {
Packit 514978
          len = *p;
Packit 514978
          if (p + len + 1 > aptr + dlen)
Packit 514978
            return NULL;
Packit 514978
          status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
          if (status != ARES_SUCCESS)
Packit 514978
            return NULL;
Packit 514978
          printf("\t%s", name.as_char);
Packit 514978
          ares_free_string(name.as_char);
Packit 514978
          p += len;
Packit 514978
        }
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_A:
Packit 514978
      /* The RR data is a four-byte Internet address. */
Packit 514978
      if (dlen != 4)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_AAAA:
Packit 514978
      /* The RR data is a 16-byte IPv6 address. */
Packit 514978
      if (dlen != 16)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_WKS:
Packit 514978
      /* Not implemented yet */
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_SRV:
Packit 514978
      /* The RR data is three two-byte numbers representing the
Packit 514978
       * priority, weight, and port, followed by a domain name.
Packit 514978
       */
Packit 514978
Packit 514978
      printf("\t%d", (int)DNS__16BIT(aptr));
Packit 514978
      printf(" %d", (int)DNS__16BIT(aptr + 2));
Packit 514978
      printf(" %d", (int)DNS__16BIT(aptr + 4));
Packit 514978
Packit 514978
      status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t%s.", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_NAPTR:
Packit 514978
Packit 514978
      printf("\t%d", (int)DNS__16BIT(aptr)); /* order */
Packit 514978
      printf(" %d\n", (int)DNS__16BIT(aptr + 2)); /* preference */
Packit 514978
Packit 514978
      p = aptr + 4;
Packit 514978
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t%s\n", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
Packit 514978
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t%s\n", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
Packit 514978
      status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t%s\n", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      p += len;
Packit 514978
Packit 514978
      status = ares_expand_name(p, abuf, alen, &name.as_char, &len;;
Packit 514978
      if (status != ARES_SUCCESS)
Packit 514978
        return NULL;
Packit 514978
      printf("\t\t\t\t\t\t%s", name.as_char);
Packit 514978
      ares_free_string(name.as_char);
Packit 514978
      break;
Packit 514978
Packit 514978
    case T_DS:
Packit 514978
    case T_SSHFP:
Packit 514978
    case T_RRSIG:
Packit 514978
    case T_NSEC:
Packit 514978
    case T_DNSKEY:
Packit 514978
      printf("\t[RR type parsing unavailable]");
Packit 514978
      break;
Packit 514978
Packit 514978
    default:
Packit 514978
      printf("\t[Unknown RR; cannot parse]");
Packit 514978
      break;
Packit 514978
    }
Packit 514978
  printf("\n");
Packit 514978
Packit 514978
  return aptr + dlen;
Packit 514978
}
Packit 514978
Packit 514978
static const char *type_name(int type)
Packit 514978
{
Packit 514978
  int i;
Packit 514978
Packit 514978
  for (i = 0; i < ntypes; i++)
Packit 514978
    {
Packit 514978
      if (types[i].value == type)
Packit 514978
        return types[i].name;
Packit 514978
    }
Packit 514978
  return "(unknown)";
Packit 514978
}
Packit 514978
Packit 514978
static const char *class_name(int dnsclass)
Packit 514978
{
Packit 514978
  int i;
Packit 514978
Packit 514978
  for (i = 0; i < nclasses; i++)
Packit 514978
    {
Packit 514978
      if (classes[i].value == dnsclass)
Packit 514978
        return classes[i].name;
Packit 514978
    }
Packit 514978
  return "(unknown)";
Packit 514978
}
Packit 514978
Packit 514978
static void usage(void)
Packit 514978
{
Packit 514978
  fprintf(stderr, "usage: adig [-f flag] [-s server] [-c class] "
Packit 514978
          "[-t type] [-p port] name ...\n");
Packit 514978
  exit(1);
Packit 514978
}
Packit 514978
Packit 514978
static void destroy_addr_list(struct ares_addr_node *head)
Packit 514978
{
Packit 514978
  while(head)
Packit 514978
    {
Packit 514978
      struct ares_addr_node *detached = head;
Packit 514978
      head = head->next;
Packit 514978
      free(detached);
Packit 514978
    }
Packit 514978
}
Packit 514978
Packit 514978
static void append_addr_list(struct ares_addr_node **head,
Packit 514978
                             struct ares_addr_node *node)
Packit 514978
{
Packit 514978
  struct ares_addr_node *last;
Packit 514978
  node->next = NULL;
Packit 514978
  if(*head)
Packit 514978
    {
Packit 514978
      last = *head;
Packit 514978
      while(last->next)
Packit 514978
        last = last->next;
Packit 514978
      last->next = node;
Packit 514978
    }
Packit 514978
  else
Packit 514978
    *head = node;
Packit 514978
}