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 36int 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