2 /* Copyright 1998, 2011 by the Massachusetts Institute of Technology.
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.
17 #include "ares_setup.h"
19 #ifdef HAVE_SYS_SOCKET_H
20 # include <sys/socket.h>
22 #ifdef HAVE_NETINET_IN_H
23 # include <netinet/in.h>
28 #ifdef HAVE_ARPA_INET_H
29 # include <arpa/inet.h>
33 #include "inet_net_pton.h"
34 #include "ares_nowarn.h"
35 #include "ares_private.h"
37 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
39 char *line = NULL, *p, *q, **alias;
40 char *txtaddr, *txthost, *txtalias;
42 size_t addrlen, linesize, naliases;
43 struct ares_addr addr;
44 struct hostent *hostent = NULL;
46 *host = NULL; /* Assume failure */
55 return ARES_EBADFAMILY;
58 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
61 /* Trim line comment. */
63 while (*p && (*p != '#'))
67 /* Trim trailing whitespace. */
69 while ((q >= line) && ISSPACE(*q))
73 /* Skip leading whitespace. */
75 while (*p && ISSPACE(*p))
78 /* Ignore line if empty. */
81 /* Pointer to start of IPv4 or IPv6 address part. */
84 /* Advance past address part. */
85 while (*p && !ISSPACE(*p))
88 /* Ignore line if reached end of line. */
91 /* Null terminate address part. */
94 /* Advance to host name */
96 while (*p && ISSPACE(*p))
99 /* Ignore line if reached end of line. */
102 /* Pointer to start of host name. */
105 /* Advance past host name. */
106 while (*p && !ISSPACE(*p))
109 /* Pointer to start of first alias. */
114 while (*q && ISSPACE(*q))
120 /* Null terminate host name. */
123 /* find out number of aliases. */
130 while (*p && !ISSPACE(*p))
132 while (*p && ISSPACE(*p))
138 /* Convert address string to network address for the requested family. */
140 addr.family = AF_UNSPEC;
141 addr.addrV4.s_addr = INADDR_NONE;
142 if ((family == AF_INET) || (family == AF_UNSPEC))
144 addr.addrV4.s_addr = inet_addr(txtaddr);
145 if (addr.addrV4.s_addr != INADDR_NONE)
147 /* Actual network address family and length. */
148 addr.family = AF_INET;
149 addrlen = sizeof(addr.addrV4);
152 if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
154 if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
156 /* Actual network address family and length. */
157 addr.family = AF_INET6;
158 addrlen = sizeof(addr.addrV6);
162 /* Ignore line if invalid address string for the requested family. */
166 ** Actual address family possible values are AF_INET and AF_INET6 only.
169 /* Allocate memory for the hostent structure. */
170 hostent = malloc(sizeof(struct hostent));
174 /* Initialize fields for out of memory condition. */
175 hostent->h_aliases = NULL;
176 hostent->h_addr_list = NULL;
178 /* Copy official host name. */
179 hostent->h_name = strdup(txthost);
180 if (!hostent->h_name)
183 /* Copy network address. */
184 hostent->h_addr_list = malloc(2 * sizeof(char *));
185 if (!hostent->h_addr_list)
187 hostent->h_addr_list[1] = NULL;
188 hostent->h_addr_list[0] = malloc(addrlen);
189 if (!hostent->h_addr_list[0])
191 if (addr.family == AF_INET)
192 memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
194 memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
197 hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
198 if (!hostent->h_aliases)
200 alias = hostent->h_aliases;
202 *(alias + naliases--) = NULL;
207 while (*p && !ISSPACE(*p))
210 while (*q && ISSPACE(*q))
213 if ((*alias = strdup(txtalias)) == NULL)
216 txtalias = *q ? q : NULL;
219 /* Alias memory allocation failure. */
222 /* Copy actual network address family and length. */
223 hostent->h_addrtype = aresx_sitoss(addr.family);
224 hostent->h_length = aresx_uztoss(addrlen);
226 /* Free line buffer. */
229 /* Return hostent successfully */
235 /* If allocated, free line buffer. */
239 if (status == ARES_SUCCESS)
241 /* Memory allocation failure; clean up. */
245 free((char *) hostent->h_name);
246 if (hostent->h_aliases)
248 for (alias = hostent->h_aliases; *alias; alias++)
250 free(hostent->h_aliases);
252 if (hostent->h_addr_list)
254 if (hostent->h_addr_list[0])
255 free(hostent->h_addr_list[0]);
256 free(hostent->h_addr_list);