/src/ares/ares__get_hostent.c

http://github.com/joyent/libuv · C · 263 lines · 181 code · 34 blank · 48 comment · 67 complexity · d21d660bc27e5c08be30fdad222c76af MD5 · raw file

  1. /* Copyright 1998, 2010 by the Massachusetts Institute of Technology.
  2. *
  3. * Permission to use, copy, modify, and distribute this
  4. * software and its documentation for any purpose and without
  5. * fee is hereby granted, provided that the above copyright
  6. * notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting
  8. * documentation, and that the name of M.I.T. not be used in
  9. * advertising or publicity pertaining to distribution of the
  10. * software without specific, written prior permission.
  11. * M.I.T. makes no representations about the suitability of
  12. * this software for any purpose. It is provided "as is"
  13. * without express or implied warranty.
  14. */
  15. #include "ares_setup.h"
  16. #ifdef HAVE_SYS_SOCKET_H
  17. # include <sys/socket.h>
  18. #endif
  19. #ifdef HAVE_NETINET_IN_H
  20. # include <netinet/in.h>
  21. #endif
  22. #ifdef HAVE_NETDB_H
  23. # include <netdb.h>
  24. #endif
  25. #ifdef HAVE_ARPA_INET_H
  26. # include <arpa/inet.h>
  27. #endif
  28. #include "ares.h"
  29. #include "inet_net_pton.h"
  30. #include "ares_private.h"
  31. int ares__get_hostent(FILE *fp, int family, struct hostent **host)
  32. {
  33. char *line = NULL, *p, *q, **alias;
  34. char *txtaddr, *txthost, *txtalias;
  35. int status;
  36. size_t addrlen, linesize, naliases;
  37. struct ares_addr addr;
  38. struct hostent *hostent = NULL;
  39. *host = NULL; /* Assume failure */
  40. /* Validate family */
  41. switch (family) {
  42. case AF_INET:
  43. case AF_INET6:
  44. case AF_UNSPEC:
  45. break;
  46. default:
  47. return ARES_EBADFAMILY;
  48. }
  49. while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)
  50. {
  51. /* Trim line comment. */
  52. p = line;
  53. while (*p && (*p != '#'))
  54. p++;
  55. *p = '\0';
  56. /* Trim trailing whitespace. */
  57. q = p - 1;
  58. while ((q >= line) && ISSPACE(*q))
  59. q--;
  60. *++q = '\0';
  61. /* Skip leading whitespace. */
  62. p = line;
  63. while (*p && ISSPACE(*p))
  64. p++;
  65. if (!*p)
  66. /* Ignore line if empty. */
  67. continue;
  68. /* Pointer to start of IPv4 or IPv6 address part. */
  69. txtaddr = p;
  70. /* Advance past address part. */
  71. while (*p && !ISSPACE(*p))
  72. p++;
  73. if (!*p)
  74. /* Ignore line if reached end of line. */
  75. continue;
  76. /* Null terminate address part. */
  77. *p = '\0';
  78. /* Advance to host name */
  79. p++;
  80. while (*p && ISSPACE(*p))
  81. p++;
  82. if (!*p)
  83. /* Ignore line if reached end of line. */
  84. continue;
  85. /* Pointer to start of host name. */
  86. txthost = p;
  87. /* Advance past host name. */
  88. while (*p && !ISSPACE(*p))
  89. p++;
  90. /* Pointer to start of first alias. */
  91. txtalias = NULL;
  92. if (*p)
  93. {
  94. q = p + 1;
  95. while (*q && ISSPACE(*q))
  96. q++;
  97. if (*q)
  98. txtalias = q;
  99. }
  100. /* Null terminate host name. */
  101. *p = '\0';
  102. /* find out number of aliases. */
  103. naliases = 0;
  104. if (txtalias)
  105. {
  106. p = txtalias;
  107. while (*p)
  108. {
  109. while (*p && !ISSPACE(*p))
  110. p++;
  111. while (*p && ISSPACE(*p))
  112. p++;
  113. naliases++;
  114. }
  115. }
  116. /* Convert address string to network address for the requested family. */
  117. addrlen = 0;
  118. addr.family = AF_UNSPEC;
  119. addr.addrV4.s_addr = INADDR_NONE;
  120. if ((family == AF_INET) || (family == AF_UNSPEC))
  121. {
  122. addr.addrV4.s_addr = inet_addr(txtaddr);
  123. if (addr.addrV4.s_addr != INADDR_NONE)
  124. {
  125. /* Actual network address family and length. */
  126. addr.family = AF_INET;
  127. addrlen = sizeof(addr.addrV4);
  128. }
  129. }
  130. if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen)))
  131. {
  132. if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0)
  133. {
  134. /* Actual network address family and length. */
  135. addr.family = AF_INET6;
  136. addrlen = sizeof(addr.addrV6);
  137. }
  138. }
  139. if (!addrlen)
  140. /* Ignore line if invalid address string for the requested family. */
  141. continue;
  142. /*
  143. ** Actual address family possible values are AF_INET and AF_INET6 only.
  144. */
  145. /* Allocate memory for the hostent structure. */
  146. hostent = malloc(sizeof(struct hostent));
  147. if (!hostent)
  148. break;
  149. /* Initialize fields for out of memory condition. */
  150. hostent->h_aliases = NULL;
  151. hostent->h_addr_list = NULL;
  152. /* Copy official host name. */
  153. hostent->h_name = strdup(txthost);
  154. if (!hostent->h_name)
  155. break;
  156. /* Copy network address. */
  157. hostent->h_addr_list = malloc(2 * sizeof(char *));
  158. if (!hostent->h_addr_list)
  159. break;
  160. hostent->h_addr_list[1] = NULL;
  161. hostent->h_addr_list[0] = malloc(addrlen);
  162. if (!hostent->h_addr_list[0])
  163. break;
  164. if (addr.family == AF_INET)
  165. memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(addr.addrV4));
  166. else
  167. memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
  168. /* Copy aliases. */
  169. hostent->h_aliases = malloc((naliases + 1) * sizeof(char *));
  170. if (!hostent->h_aliases)
  171. break;
  172. alias = hostent->h_aliases;
  173. while (naliases)
  174. *(alias + naliases--) = NULL;
  175. *alias = NULL;
  176. while (txtalias)
  177. {
  178. p = txtalias;
  179. while (*p && !ISSPACE(*p))
  180. p++;
  181. q = p;
  182. while (*q && ISSPACE(*q))
  183. q++;
  184. *p = '\0';
  185. if ((*alias = strdup(txtalias)) == NULL)
  186. break;
  187. alias++;
  188. txtalias = *q ? q : NULL;
  189. }
  190. if (txtalias)
  191. /* Alias memory allocation failure. */
  192. break;
  193. /* Copy actual network address family and length. */
  194. hostent->h_addrtype = addr.family;
  195. hostent->h_length = (int)addrlen;
  196. /* Free line buffer. */
  197. free(line);
  198. /* Return hostent successfully */
  199. *host = hostent;
  200. return ARES_SUCCESS;
  201. }
  202. /* If allocated, free line buffer. */
  203. if (line)
  204. free(line);
  205. if (status == ARES_SUCCESS)
  206. {
  207. /* Memory allocation failure; clean up. */
  208. if (hostent)
  209. {
  210. if (hostent->h_name)
  211. free((char *) hostent->h_name);
  212. if (hostent->h_aliases)
  213. {
  214. for (alias = hostent->h_aliases; *alias; alias++)
  215. free(*alias);
  216. free(hostent->h_aliases);
  217. }
  218. if (hostent->h_addr_list)
  219. {
  220. if (hostent->h_addr_list[0])
  221. free(hostent->h_addr_list[0]);
  222. free(hostent->h_addr_list);
  223. }
  224. free(hostent);
  225. }
  226. return ARES_ENOMEM;
  227. }
  228. return status;
  229. }