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_NETINET_IN_H
20 # include <netinet/in.h>
25 #ifdef HAVE_ARPA_INET_H
26 # include <arpa/inet.h>
30 #include "ares_inet_net_pton.h"
31 #include "ares_nowarn.h"
32 #include "ares_private.h"
34 int ares__get_hostent(FILE *fp, int family, struct hostent **host)
36 char *line = NULL, *p, *q, **alias;
37 char *txtaddr, *txthost, *txtalias;
39 size_t addrlen, linesize, naliases;
40 struct ares_addr addr;
41 struct hostent *hostent = NULL;
43 *host = NULL; /* Assume failure */
52 return ARES_EBADFAMILY;
55 while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
58 /* Trim line comment. */
60 while (*p && (*p != '#'))
64 /* Trim trailing whitespace. */
66 while ((q >= line) && ISSPACE(*q))
70 /* Skip leading whitespace. */
72 while (*p && ISSPACE(*p))
75 /* Ignore line if empty. */
78 /* Pointer to start of IPv4 or IPv6 address part. */
81 /* Advance past address part. */
82 while (*p && !ISSPACE(*p))
85 /* Ignore line if reached end of line. */
88 /* Null terminate address part. */
91 /* Advance to host name */
93 while (*p && ISSPACE(*p))
96 /* Ignore line if reached end of line. */
99 /* Pointer to start of host name. */
102 /* Advance past host name. */
103 while (*p && !ISSPACE(*p))
106 /* Pointer to start of first alias. */
111 while (*q && ISSPACE(*q))
117 /* Null terminate host name. */
120 /* find out number of aliases. */
127 while (*p && !ISSPACE(*p))
129 while (*p && ISSPACE(*p))
135 /* Convert address string to network address for the requested family. */
137 addr.family = AF_UNSPEC;
138 addr.addrV4.s_addr = INADDR_NONE;
139 if ((family == AF_INET) || (family == AF_UNSPEC))
141 addr.addrV4.s_addr = inet_addr(txtaddr);
142 if (addr.addrV4.s_addr != INADDR_NONE)
144 /* Actual network address family and length. */
145 addr.family = AF_INET;
146 addrlen = sizeof(addr.addrV4);
149 if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
151 if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
153 /* Actual network address family and length. */
154 addr.family = AF_INET6;
155 addrlen = sizeof(addr.addrV6);
159 /* Ignore line if invalid address string for the requested family. */
163 ** Actual address family possible values are AF_INET and AF_INET6 only.
166 /* Allocate memory for the hostent structure. */
167 hostent = malloc(sizeof(struct hostent));
171 /* Initialize fields for out of memory condition. */
172 hostent->h_aliases = NULL;
173 hostent->h_addr_list = NULL;
175 /* Copy official host name. */
176 hostent->h_name = strdup(txthost);
177 if (!hostent->h_name)
180 /* Copy network address. */
181 hostent->h_addr_list = malloc(2 * sizeof(char *));
182 if (!hostent->h_addr_list)
184 hostent->h_addr_list[1] = NULL;
185 hostent->h_addr_list[0] = malloc(addrlen);
186 if (!hostent->h_addr_list[0])
188 if (addr.family == AF_INET)
189 memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
191 memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
194 hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
195 if (!hostent->h_aliases)
197 alias = hostent->h_aliases;
199 *(alias + naliases--) = NULL;
204 while (*p && !ISSPACE(*p))
207 while (*q && ISSPACE(*q))
210 if ((*alias = strdup(txtalias)) == NULL)
213 txtalias = *q ? q : NULL;
216 /* Alias memory allocation failure. */
219 /* Copy actual network address family and length. */
220 hostent->h_addrtype = aresx_sitoss(addr.family);
221 hostent->h_length = aresx_uztoss(addrlen);
223 /* Free line buffer. */
226 /* Return hostent successfully */
232 /* If allocated, free line buffer. */
236 if (status == ARES_SUCCESS)
238 /* Memory allocation failure; clean up. */
242 free((char *) hostent->h_name);
243 if (hostent->h_aliases)
245 for (alias = hostent->h_aliases; *alias; alias++)
247 free(hostent->h_aliases);
249 if (hostent->h_addr_list)
251 if (hostent->h_addr_list[0])
252 free(hostent->h_addr_list[0]);
253 free(hostent->h_addr_list);