2 /* Copyright 1998, 2010 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_private.h"
36 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
38 char *line = NULL, *p, *q, **alias;
39 char *txtaddr, *txthost, *txtalias;
41 size_t addrlen, linesize, naliases;
42 struct ares_addr addr;
43 struct hostent *hostent = NULL;
45 *host = NULL; /* Assume failure */
54 return ARES_EBADFAMILY;
57 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
60 /* Trim line comment. */
62 while (*p && (*p != '#'))
66 /* Trim trailing whitespace. */
68 while ((q >= line) && ISSPACE(*q))
72 /* Skip leading whitespace. */
74 while (*p && ISSPACE(*p))
77 /* Ignore line if empty. */
80 /* Pointer to start of IPv4 or IPv6 address part. */
83 /* Advance past address part. */
84 while (*p && !ISSPACE(*p))
87 /* Ignore line if reached end of line. */
90 /* Null terminate address part. */
93 /* Advance to host name */
95 while (*p && ISSPACE(*p))
98 /* Ignore line if reached end of line. */
101 /* Pointer to start of host name. */
104 /* Advance past host name. */
105 while (*p && !ISSPACE(*p))
108 /* Pointer to start of first alias. */
113 while (*q && ISSPACE(*q))
119 /* Null terminate host name. */
122 /* find out number of aliases. */
129 while (*p && !ISSPACE(*p))
131 while (*p && ISSPACE(*p))
137 /* Convert address string to network address for the requested family. */
139 addr.family = AF_UNSPEC;
140 addr.addrV4.s_addr = INADDR_NONE;
141 if ((family == AF_INET) || (family == AF_UNSPEC))
143 addr.addrV4.s_addr = inet_addr(txtaddr);
144 if (addr.addrV4.s_addr != INADDR_NONE)
146 /* Actual network address family and length. */
147 addr.family = AF_INET;
148 addrlen = sizeof(addr.addrV4);
151 if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
153 if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
155 /* Actual network address family and length. */
156 addr.family = AF_INET6;
157 addrlen = sizeof(addr.addrV6);
161 /* Ignore line if invalid address string for the requested family. */
165 ** Actual address family possible values are AF_INET and AF_INET6 only.
168 /* Allocate memory for the hostent structure. */
169 hostent = malloc(sizeof(struct hostent));
173 /* Initialize fields for out of memory condition. */
174 hostent->h_aliases = NULL;
175 hostent->h_addr_list = NULL;
177 /* Copy official host name. */
178 hostent->h_name = strdup(txthost);
179 if (!hostent->h_name)
182 /* Copy network address. */
183 hostent->h_addr_list = malloc(2 * sizeof(char *));
184 if (!hostent->h_addr_list)
186 hostent->h_addr_list[1] = NULL;
187 hostent->h_addr_list[0] = malloc(addrlen);
188 if (!hostent->h_addr_list[0])
190 if (addr.family == AF_INET)
191 memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
193 memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
196 hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
197 if (!hostent->h_aliases)
199 alias = hostent->h_aliases;
201 *(alias + naliases--) = NULL;
206 while (*p && !ISSPACE(*p))
209 while (*q && ISSPACE(*q))
212 if ((*alias = strdup(txtalias)) == NULL)
215 txtalias = *q ? q : NULL;
218 /* Alias memory allocation failure. */
221 /* Copy actual network address family and length. */
222 hostent->h_addrtype = addr.family;
223 hostent->h_length = (int)addrlen;
225 /* Free line buffer. */
228 /* Return hostent successfully */
234 /* If allocated, free line buffer. */
238 if (status == ARES_SUCCESS)
240 /* Memory allocation failure; clean up. */
244 free((char *) hostent->h_name);
245 if (hostent->h_aliases)
247 for (alias = hostent->h_aliases; *alias; alias++)
249 free(hostent->h_aliases);
251 if (hostent->h_addr_list)
253 if (hostent->h_addr_list[0])
254 free(hostent->h_addr_list[0]);
255 free(hostent->h_addr_list);