Blame ares__get_hostent.c

Packit 514978
Packit 514978
/* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
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_NETDB_H
Packit 514978
#  include <netdb.h>
Packit 514978
#endif
Packit 514978
#ifdef HAVE_ARPA_INET_H
Packit 514978
#  include <arpa/inet.h>
Packit 514978
#endif
Packit 514978
Packit 514978
#include "ares.h"
Packit 514978
#include "ares_inet_net_pton.h"
Packit 514978
#include "ares_nowarn.h"
Packit 514978
#include "ares_private.h"
Packit 514978
Packit 514978
int ares__get_hostent(FILE *fp, int family, struct hostent **host)
Packit 514978
{
Packit 514978
  char *line = NULL, *p, *q, **alias;
Packit 514978
  char *txtaddr, *txthost, *txtalias;
Packit 514978
  int status;
Packit 514978
  size_t addrlen, linesize, naliases;
Packit 514978
  struct ares_addr addr;
Packit 514978
  struct hostent *hostent = NULL;
Packit 514978
Packit 514978
  *host = NULL; /* Assume failure */
Packit 514978
Packit 514978
  /* Validate family */
Packit 514978
  switch (family) {
Packit 514978
    case AF_INET:
Packit 514978
    case AF_INET6:
Packit 514978
    case AF_UNSPEC:
Packit 514978
      break;
Packit 514978
    default:
Packit 514978
      return ARES_EBADFAMILY;
Packit 514978
  }
Packit 514978
Packit 514978
  while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
Packit 514978
    {
Packit 514978
Packit 514978
      /* Trim line comment. */
Packit 514978
      p = line;
Packit 514978
      while (*p && (*p != '#'))
Packit 514978
        p++;
Packit 514978
      *p = '\0';
Packit 514978
Packit 514978
      /* Trim trailing whitespace. */
Packit 514978
      q = p - 1;
Packit 514978
      while ((q >= line) && ISSPACE(*q))
Packit 514978
        q--;
Packit 514978
      *++q = '\0';
Packit 514978
Packit 514978
      /* Skip leading whitespace. */
Packit 514978
      p = line;
Packit 514978
      while (*p && ISSPACE(*p))
Packit 514978
        p++;
Packit 514978
      if (!*p)
Packit 514978
        /* Ignore line if empty. */
Packit 514978
        continue;
Packit 514978
Packit 514978
      /* Pointer to start of IPv4 or IPv6 address part. */
Packit 514978
      txtaddr = p;
Packit 514978
Packit 514978
      /* Advance past address part. */
Packit 514978
      while (*p && !ISSPACE(*p))
Packit 514978
        p++;
Packit 514978
      if (!*p)
Packit 514978
        /* Ignore line if reached end of line. */
Packit 514978
        continue;
Packit 514978
Packit 514978
      /* Null terminate address part. */
Packit 514978
      *p = '\0';
Packit 514978
Packit 514978
      /* Advance to host name */
Packit 514978
      p++;
Packit 514978
      while (*p && ISSPACE(*p))
Packit 514978
        p++;
Packit 514978
      if (!*p)
Packit 514978
        /* Ignore line if reached end of line. */
Packit 514978
        continue;  /* LCOV_EXCL_LINE: trailing whitespace already stripped */
Packit 514978
Packit 514978
      /* Pointer to start of host name. */
Packit 514978
      txthost = p;
Packit 514978
Packit 514978
      /* Advance past host name. */
Packit 514978
      while (*p && !ISSPACE(*p))
Packit 514978
        p++;
Packit 514978
Packit 514978
      /* Pointer to start of first alias. */
Packit 514978
      txtalias = NULL;
Packit 514978
      if (*p)
Packit 514978
        {
Packit 514978
          q = p + 1;
Packit 514978
          while (*q && ISSPACE(*q))
Packit 514978
            q++;
Packit 514978
          if (*q)
Packit 514978
            txtalias = q;
Packit 514978
        }
Packit 514978
Packit 514978
      /* Null terminate host name. */
Packit 514978
      *p = '\0';
Packit 514978
Packit 514978
      /* find out number of aliases. */
Packit 514978
      naliases = 0;
Packit 514978
      if (txtalias)
Packit 514978
        {
Packit 514978
          p = txtalias;
Packit 514978
          while (*p)
Packit 514978
            {
Packit 514978
              while (*p && !ISSPACE(*p))
Packit 514978
                p++;
Packit 514978
              while (*p && ISSPACE(*p))
Packit 514978
                p++;
Packit 514978
              naliases++;
Packit 514978
            }
Packit 514978
        }
Packit 514978
Packit 514978
      /* Convert address string to network address for the requested family. */
Packit 514978
      addrlen = 0;
Packit 514978
      addr.family = AF_UNSPEC;
Packit 514978
      addr.addrV4.s_addr = INADDR_NONE;
Packit 514978
      if ((family == AF_INET) || (family == AF_UNSPEC))
Packit 514978
        {
Packit 514978
          addr.addrV4.s_addr = inet_addr(txtaddr);
Packit 514978
          if (addr.addrV4.s_addr != INADDR_NONE)
Packit 514978
            {
Packit 514978
              /* Actual network address family and length. */
Packit 514978
              addr.family = AF_INET;
Packit 514978
              addrlen = sizeof(addr.addrV4);
Packit 514978
            }
Packit 514978
        }
Packit 514978
      if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
Packit 514978
        {
Packit 514978
          if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
Packit 514978
            {
Packit 514978
              /* Actual network address family and length. */
Packit 514978
              addr.family = AF_INET6;
Packit 514978
              addrlen = sizeof(addr.addrV6);
Packit 514978
            }
Packit 514978
        }
Packit 514978
      if (!addrlen)
Packit 514978
        /* Ignore line if invalid address string for the requested family. */
Packit 514978
        continue;
Packit 514978
Packit 514978
      /*
Packit 514978
      ** Actual address family possible values are AF_INET and AF_INET6 only.
Packit 514978
      */
Packit 514978
Packit 514978
      /* Allocate memory for the hostent structure. */
Packit 514978
      hostent = ares_malloc(sizeof(struct hostent));
Packit 514978
      if (!hostent)
Packit 514978
        break;
Packit 514978
Packit 514978
      /* Initialize fields for out of memory condition. */
Packit 514978
      hostent->h_aliases = NULL;
Packit 514978
      hostent->h_addr_list = NULL;
Packit 514978
Packit 514978
      /* Copy official host name. */
Packit 514978
      hostent->h_name = ares_strdup(txthost);
Packit 514978
      if (!hostent->h_name)
Packit 514978
        break;
Packit 514978
Packit 514978
      /* Copy network address. */
Packit 514978
      hostent->h_addr_list = ares_malloc(2 * sizeof(char *));
Packit 514978
      if (!hostent->h_addr_list)
Packit 514978
        break;
Packit 514978
      hostent->h_addr_list[1] = NULL;
Packit 514978
      hostent->h_addr_list[0] = ares_malloc(addrlen);
Packit 514978
      if (!hostent->h_addr_list[0])
Packit 514978
        break;
Packit 514978
      if (addr.family == AF_INET)
Packit 514978
        memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
Packit 514978
      else
Packit 514978
        memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
Packit 514978
Packit 514978
      /* Copy aliases. */
Packit 514978
      hostent->h_aliases = ares_malloc((naliases + 1) * sizeof(char *));
Packit 514978
      if (!hostent->h_aliases)
Packit 514978
        break;
Packit 514978
      alias = hostent->h_aliases;
Packit 514978
      while (naliases)
Packit 514978
        *(alias + naliases--) = NULL;
Packit 514978
      *alias = NULL;
Packit 514978
      while (txtalias)
Packit 514978
        {
Packit 514978
          p = txtalias;
Packit 514978
          while (*p && !ISSPACE(*p))
Packit 514978
            p++;
Packit 514978
          q = p;
Packit 514978
          while (*q && ISSPACE(*q))
Packit 514978
            q++;
Packit 514978
          *p = '\0';
Packit 514978
          if ((*alias = ares_strdup(txtalias)) == NULL)
Packit 514978
            break;
Packit 514978
          alias++;
Packit 514978
          txtalias = *q ? q : NULL;
Packit 514978
        }
Packit 514978
      if (txtalias)
Packit 514978
        /* Alias memory allocation failure. */
Packit 514978
        break;
Packit 514978
Packit 514978
      /* Copy actual network address family and length. */
Packit 514978
      hostent->h_addrtype = aresx_sitoss(addr.family);
Packit 514978
      hostent->h_length = aresx_uztoss(addrlen);
Packit 514978
Packit 514978
      /* Free line buffer. */
Packit 514978
      ares_free(line);
Packit 514978
Packit 514978
      /* Return hostent successfully */
Packit 514978
      *host = hostent;
Packit 514978
      return ARES_SUCCESS;
Packit 514978
Packit 514978
    }
Packit 514978
Packit 514978
  /* If allocated, free line buffer. */
Packit 514978
  if (line)
Packit 514978
    ares_free(line);
Packit 514978
Packit 514978
  if (status == ARES_SUCCESS)
Packit 514978
    {
Packit 514978
      /* Memory allocation failure; clean up. */
Packit 514978
      if (hostent)
Packit 514978
        {
Packit 514978
          if (hostent->h_name)
Packit 514978
            ares_free((char *) hostent->h_name);
Packit 514978
          if (hostent->h_aliases)
Packit 514978
            {
Packit 514978
              for (alias = hostent->h_aliases; *alias; alias++)
Packit 514978
                ares_free(*alias);
Packit 514978
              ares_free(hostent->h_aliases);
Packit 514978
            }
Packit 514978
          if (hostent->h_addr_list)
Packit 514978
            {
Packit 514978
              if (hostent->h_addr_list[0])
Packit 514978
                ares_free(hostent->h_addr_list[0]);
Packit 514978
              ares_free(hostent->h_addr_list);
Packit 514978
            }
Packit 514978
          ares_free(hostent);
Packit 514978
        }
Packit 514978
      return ARES_ENOMEM;
Packit 514978
    }
Packit 514978
Packit 514978
  return status;
Packit 514978
}