fix compiler warning: implicit conversion shortens 64-bit value into a 32-bit value
[platform/upstream/c-ares.git] / ares__get_hostent.c
1 /* $Id$ */
2
3 /* Copyright 1998 by the Massachusetts Institute of Technology.
4  *
5  * Permission to use, copy, modify, and distribute this
6  * software and its documentation for any purpose and without
7  * fee is hereby granted, provided that the above copyright
8  * notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting
10  * documentation, and that the name of M.I.T. not be used in
11  * advertising or publicity pertaining to distribution of the
12  * software without specific, written prior permission.
13  * M.I.T. makes no representations about the suitability of
14  * this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  */
17
18 #include "setup.h"
19
20 #if !defined(WIN32) || defined(WATT32)
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
23 #endif
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
26 #endif
27 #ifdef HAVE_NETDB_H
28 #include <netdb.h>
29 #endif
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
32 #endif
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39
40 #include "ares.h"
41 #include "inet_net_pton.h"
42 #include "ares_private.h"
43
44 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
45 {
46   char *line = NULL, *p, *q, *canonical, **alias;
47   int status, linesize, end_at_hostname, naliases;
48   struct in_addr addr;
49   struct in6_addr addr6;
50   size_t addrlen = sizeof(struct in_addr);
51   struct hostent *hostent = NULL;
52
53   while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
54     {
55       /* Skip comment lines; terminate line at comment character. */
56       if (*line == '#' || !*line)
57         continue;
58       p = strchr(line, '#');
59       if (p)
60         *p = 0;
61
62       /* Get the address part. */
63       p = line;
64       while (*p && !ISSPACE(*p))
65         p++;
66       if (!*p)
67         continue;
68       *p = 0;
69       addr.s_addr = inet_addr(line);
70       if (addr.s_addr == INADDR_NONE)
71       {
72         /* It wasn't an AF_INET dotted address, then AF_UNSPEC and AF_INET6
73            families are subject for this further check */
74         if ((family != AF_INET) &&
75             (ares_inet_pton(AF_INET6, line, &addr6) > 0)) {
76           addrlen = sizeof(struct in6_addr);
77           family = AF_INET6;
78         }
79         else
80           continue;
81       }
82       else if (family == AF_UNSPEC)
83         family = AF_INET; /* now confirmed! */
84       else if (family != AF_INET)
85         /* unknown, keep moving */
86         continue;
87
88       /* Get the canonical hostname. */
89       p++;
90       while (ISSPACE(*p))
91         p++;
92       if (!*p)
93         continue;
94       q = p;
95       while (*q && !ISSPACE(*q))
96         q++;
97       end_at_hostname = (*q == 0);
98       *q = 0;
99       canonical = p;
100
101       naliases = 0;
102       if (!end_at_hostname)
103         {
104           /* Count the aliases. */
105           p = q + 1;
106           while (ISSPACE(*p))
107             p++;
108           while (*p)
109             {
110               while (*p && !ISSPACE(*p))
111                 p++;
112               while (ISSPACE(*p))
113                 p++;
114               naliases++;
115             }
116         }
117
118       /* Allocate memory for the host structure. */
119       hostent = malloc(sizeof(struct hostent));
120       if (!hostent)
121         break;
122       hostent->h_aliases = NULL;
123       hostent->h_addr_list = NULL;
124       hostent->h_name = strdup(canonical);
125       if (!hostent->h_name)
126         break;
127       hostent->h_addr_list = malloc(2 * sizeof(char *));
128       if (!hostent->h_addr_list)
129         break;
130       hostent->h_addr_list[0] = malloc(addrlen);
131       if (!hostent->h_addr_list[0])
132         break;
133       hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
134       if (!hostent->h_aliases)
135         break;
136
137       /* Copy in aliases. */
138       naliases = 0;
139       if (!end_at_hostname)
140         {
141           p = canonical + strlen(canonical) + 1;
142           while (ISSPACE(*p))
143             p++;
144           while (*p)
145             {
146               q = p;
147               while (*q && !ISSPACE(*q))
148                 q++;
149               hostent->h_aliases[naliases] = malloc(q - p + 1);
150               if (hostent->h_aliases[naliases] == NULL)
151                 break;
152               memcpy(hostent->h_aliases[naliases], p, q - p);
153               hostent->h_aliases[naliases][q - p] = 0;
154               p = q;
155               while (ISSPACE(*p))
156                 p++;
157               naliases++;
158             }
159           if (*p)
160             break;
161         }
162       hostent->h_aliases[naliases] = NULL;
163
164       hostent->h_addrtype = family;
165       hostent->h_length = (int)addrlen;
166       if (family == AF_INET)
167         memcpy(hostent->h_addr_list[0], &addr, addrlen);
168       else if (family == AF_INET6)
169         memcpy(hostent->h_addr_list[0], &addr6, addrlen);
170       hostent->h_addr_list[1] = NULL;
171       *host = hostent;
172       free(line);
173       return ARES_SUCCESS;
174     }
175   if(line)
176     free(line);
177
178   if (status == ARES_SUCCESS)
179     {
180       /* Memory allocation failure; clean up. */
181       if (hostent)
182         {
183           if(hostent->h_name)
184             free((char *) hostent->h_name);
185           if (hostent->h_aliases)
186             {
187               for (alias = hostent->h_aliases; *alias; alias++)
188                 free(*alias);
189             }
190           if(hostent->h_aliases)
191             free(hostent->h_aliases);
192           if (hostent->h_addr_list && hostent->h_addr_list[0])
193             free(hostent->h_addr_list[0]);
194           if(hostent->h_addr_list)
195             free(hostent->h_addr_list);
196           free(hostent);
197         }
198       *host = NULL;
199       return ARES_ENOMEM;
200     }
201
202   return status;
203 }