Home | History | Annotate | Download | only in c-ares
      1 
      2 /* Copyright 1998, 2010 by the Massachusetts Institute of Technology.
      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_NETDB_H
     26 #  include <netdb.h>
     27 #endif
     28 #ifdef HAVE_ARPA_INET_H
     29 #  include <arpa/inet.h>
     30 #endif
     31 
     32 #include "ares.h"
     33 #include "inet_net_pton.h"
     34 #include "ares_private.h"
     35 
     36 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
     37 {
     38   char *line = NULL, *p, *q, **alias;
     39   char *txtaddr, *txthost, *txtalias;
     40   int status;
     41   size_t addrlen, linesize, naliases;
     42   struct ares_addr addr;
     43   struct hostent *hostent = NULL;
     44 
     45   *host = NULL; /* Assume failure */
     46 
     47   /* Validate family */
     48   switch (family) {
     49     case AF_INET:
     50     case AF_INET6:
     51     case AF_UNSPEC:
     52       break;
     53     default:
     54       return ARES_EBADFAMILY;
     55   }
     56 
     57   while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
     58     {
     59 
     60       /* Trim line comment. */
     61       p = line;
     62       while (*p && (*p != '#'))
     63         p++;
     64       *p = '\0';
     65 
     66       /* Trim trailing whitespace. */
     67       q = p - 1;
     68       while ((q >= line) && ISSPACE(*q))
     69         q--;
     70       *++q = '\0';
     71 
     72       /* Skip leading whitespace. */
     73       p = line;
     74       while (*p && ISSPACE(*p))
     75         p++;
     76       if (!*p)
     77         /* Ignore line if empty. */
     78         continue;
     79 
     80       /* Pointer to start of IPv4 or IPv6 address part. */
     81       txtaddr = p;
     82 
     83       /* Advance past address part. */
     84       while (*p && !ISSPACE(*p))
     85         p++;
     86       if (!*p)
     87         /* Ignore line if reached end of line. */
     88         continue;
     89 
     90       /* Null terminate address part. */
     91       *p = '\0';
     92 
     93       /* Advance to host name */
     94       p++;
     95       while (*p && ISSPACE(*p))
     96         p++;
     97       if (!*p)
     98         /* Ignore line if reached end of line. */
     99         continue;
    100 
    101       /* Pointer to start of host name. */
    102       txthost = p;
    103 
    104       /* Advance past host name. */
    105       while (*p && !ISSPACE(*p))
    106         p++;
    107 
    108       /* Pointer to start of first alias. */
    109       txtalias = NULL;
    110       if (*p)
    111         {
    112           q = p + 1;
    113           while (*q && ISSPACE(*q))
    114             q++;
    115           if (*q)
    116             txtalias = q;
    117         }
    118 
    119       /* Null terminate host name. */
    120       *p = '\0';
    121 
    122       /* find out number of aliases. */
    123       naliases = 0;
    124       if (txtalias)
    125         {
    126           p = txtalias;
    127           while (*p)
    128             {
    129               while (*p && !ISSPACE(*p))
    130                 p++;
    131               while (*p && ISSPACE(*p))
    132                 p++;
    133               naliases++;
    134             }
    135         }
    136 
    137       /* Convert address string to network address for the requested family. */
    138       addrlen = 0;
    139       addr.family = AF_UNSPEC;
    140       addr.addrV4.s_addr = INADDR_NONE;
    141       if ((family == AF_INET) || (family == AF_UNSPEC))
    142         {
    143           addr.addrV4.s_addr = inet_addr(txtaddr);
    144           if (addr.addrV4.s_addr != INADDR_NONE)
    145             {
    146               /* Actual network address family and length. */
    147               addr.family = AF_INET;
    148               addrlen = sizeof(addr.addrV4);
    149             }
    150         }
    151       if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
    152         {
    153           if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
    154             {
    155               /* Actual network address family and length. */
    156               addr.family = AF_INET6;
    157               addrlen = sizeof(addr.addrV6);
    158             }
    159         }
    160       if (!addrlen)
    161         /* Ignore line if invalid address string for the requested family. */
    162         continue;
    163 
    164       /*
    165       ** Actual address family possible values are AF_INET and AF_INET6 only.
    166       */
    167 
    168       /* Allocate memory for the hostent structure. */
    169       hostent = malloc(sizeof(struct hostent));
    170       if (!hostent)
    171         break;
    172 
    173       /* Initialize fields for out of memory condition. */
    174       hostent->h_aliases = NULL;
    175       hostent->h_addr_list = NULL;
    176 
    177       /* Copy official host name. */
    178       hostent->h_name = strdup(txthost);
    179       if (!hostent->h_name)
    180         break;
    181 
    182       /* Copy network address. */
    183       hostent->h_addr_list = malloc(2 * sizeof(char *));
    184       if (!hostent->h_addr_list)
    185         break;
    186       hostent->h_addr_list[1] = NULL;
    187       hostent->h_addr_list[0] = malloc(addrlen);
    188       if (!hostent->h_addr_list[0])
    189         break;
    190       if (addr.family == AF_INET)
    191         memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
    192       else
    193         memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
    194 
    195       /* Copy aliases. */
    196       hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
    197       if (!hostent->h_aliases)
    198         break;
    199       alias = hostent->h_aliases;
    200       while (naliases)
    201         *(alias + naliases--) = NULL;
    202       *alias = NULL;
    203       while (txtalias)
    204         {
    205           p = txtalias;
    206           while (*p && !ISSPACE(*p))
    207             p++;
    208           q = p;
    209           while (*q && ISSPACE(*q))
    210             q++;
    211           *p = '\0';
    212           if ((*alias = strdup(txtalias)) == NULL)
    213             break;
    214           alias++;
    215           txtalias = *q ? q : NULL;
    216         }
    217       if (txtalias)
    218         /* Alias memory allocation failure. */
    219         break;
    220 
    221       /* Copy actual network address family and length. */
    222       hostent->h_addrtype = addr.family;
    223       hostent->h_length = (int)addrlen;
    224 
    225       /* Free line buffer. */
    226       free(line);
    227 
    228       /* Return hostent successfully */
    229       *host = hostent;
    230       return ARES_SUCCESS;
    231 
    232     }
    233 
    234   /* If allocated, free line buffer. */
    235   if (line)
    236     free(line);
    237 
    238   if (status == ARES_SUCCESS)
    239     {
    240       /* Memory allocation failure; clean up. */
    241       if (hostent)
    242         {
    243           if (hostent->h_name)
    244             free((char *) hostent->h_name);
    245           if (hostent->h_aliases)
    246             {
    247               for (alias = hostent->h_aliases; *alias; alias++)
    248                 free(*alias);
    249               free(hostent->h_aliases);
    250             }
    251           if (hostent->h_addr_list)
    252             {
    253               if (hostent->h_addr_list[0])
    254                 free(hostent->h_addr_list[0]);
    255               free(hostent->h_addr_list);
    256             }
    257           free(hostent);
    258         }
    259       return ARES_ENOMEM;
    260     }
    261 
    262   return status;
    263 }
    264