ares_gethostbyaddr.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /* Copyright 1998 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_NETINET_IN_H
  17. # include <netinet/in.h>
  18. #endif
  19. #ifdef HAVE_NETDB_H
  20. # include <netdb.h>
  21. #endif
  22. #ifdef HAVE_ARPA_INET_H
  23. # include <arpa/inet.h>
  24. #endif
  25. #ifdef HAVE_ARPA_NAMESER_H
  26. # include <arpa/nameser.h>
  27. #else
  28. # include "nameser.h"
  29. #endif
  30. #ifdef HAVE_ARPA_NAMESER_COMPAT_H
  31. # include <arpa/nameser_compat.h>
  32. #endif
  33. #include "ares.h"
  34. #include "ares_inet_net_pton.h"
  35. #include "ares_platform.h"
  36. #include "ares_private.h"
  37. #ifdef WATT32
  38. #undef WIN32
  39. #endif
  40. #define next_lookup next_lookup_x
  41. #define file_lookup file_lookup_x
  42. struct addr_query {
  43. /* Arguments passed to ares_gethostbyaddr() */
  44. ares_channel channel;
  45. struct ares_addr addr;
  46. ares_host_callback callback;
  47. void *arg;
  48. const char *remaining_lookups;
  49. int timeouts;
  50. };
  51. static void next_lookup(struct addr_query *aquery);
  52. static void addr_callback(void *arg, int status, int timeouts,
  53. unsigned char *abuf, int alen);
  54. static void end_aquery(struct addr_query *aquery, int status,
  55. struct hostent *host);
  56. static int file_lookup(struct ares_addr *addr, struct hostent **host);
  57. static void ptr_rr_name(char *name, const struct ares_addr *addr);
  58. void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
  59. int family, ares_host_callback callback, void *arg)
  60. {
  61. struct addr_query *aquery;
  62. if (family != AF_INET && family != AF_INET6)
  63. {
  64. callback(arg, ARES_ENOTIMP, 0, NULL);
  65. return;
  66. }
  67. if ((family == AF_INET && addrlen != sizeof(aquery->addr.addrV4)) ||
  68. (family == AF_INET6 && addrlen != sizeof(aquery->addr.addrV6)))
  69. {
  70. callback(arg, ARES_ENOTIMP, 0, NULL);
  71. return;
  72. }
  73. aquery = ares_malloc(sizeof(struct addr_query));
  74. if (!aquery)
  75. {
  76. callback(arg, ARES_ENOMEM, 0, NULL);
  77. return;
  78. }
  79. aquery->channel = channel;
  80. if (family == AF_INET)
  81. memcpy(&aquery->addr.addrV4, addr, sizeof(aquery->addr.addrV4));
  82. else
  83. memcpy(&aquery->addr.addrV6, addr, sizeof(aquery->addr.addrV6));
  84. aquery->addr.family = family;
  85. aquery->callback = callback;
  86. aquery->arg = arg;
  87. aquery->remaining_lookups = channel->lookups;
  88. aquery->timeouts = 0;
  89. next_lookup(aquery);
  90. }
  91. static void next_lookup(struct addr_query *aquery)
  92. {
  93. const char *p;
  94. char name[128];
  95. int status;
  96. struct hostent *host;
  97. for (p = aquery->remaining_lookups; *p; p++)
  98. {
  99. switch (*p)
  100. {
  101. case 'b':
  102. ptr_rr_name(name, &aquery->addr);
  103. aquery->remaining_lookups = p + 1;
  104. ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
  105. aquery);
  106. return;
  107. case 'f':
  108. status = file_lookup(&aquery->addr, &host);
  109. /* this status check below previously checked for !ARES_ENOTFOUND,
  110. but we should not assume that this single error code is the one
  111. that can occur, as that is in fact no longer the case */
  112. if (status == ARES_SUCCESS)
  113. {
  114. end_aquery(aquery, status, host);
  115. return;
  116. }
  117. break;
  118. }
  119. }
  120. end_aquery(aquery, ARES_ENOTFOUND, NULL);
  121. }
  122. static void addr_callback(void *arg, int status, int timeouts,
  123. unsigned char *abuf, int alen)
  124. {
  125. struct addr_query *aquery = (struct addr_query *) arg;
  126. struct hostent *host;
  127. size_t addrlen;
  128. aquery->timeouts += timeouts;
  129. if (status == ARES_SUCCESS)
  130. {
  131. if (aquery->addr.family == AF_INET)
  132. {
  133. addrlen = sizeof(aquery->addr.addrV4);
  134. status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV4,
  135. (int)addrlen, AF_INET, &host, NULL);
  136. }
  137. else
  138. {
  139. addrlen = sizeof(aquery->addr.addrV6);
  140. status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV6,
  141. (int)addrlen, AF_INET6, &host, NULL);
  142. }
  143. end_aquery(aquery, status, host);
  144. }
  145. else if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED)
  146. end_aquery(aquery, status, NULL);
  147. else
  148. next_lookup(aquery);
  149. }
  150. static void end_aquery(struct addr_query *aquery, int status,
  151. struct hostent *host)
  152. {
  153. aquery->callback(aquery->arg, status, aquery->timeouts, host);
  154. if (host)
  155. ares_free_hostent(host);
  156. ares_free(aquery);
  157. }
  158. static int file_lookup(struct ares_addr *addr, struct hostent **host)
  159. {
  160. FILE *fp;
  161. int status;
  162. int error;
  163. #ifdef WIN32
  164. char PATH_HOSTS[MAX_PATH];
  165. win_platform platform;
  166. PATH_HOSTS[0] = '\0';
  167. platform = ares__getplatform();
  168. if (platform == WIN_NT) {
  169. char tmp[MAX_PATH];
  170. HKEY hkeyHosts;
  171. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
  172. &hkeyHosts) == ERROR_SUCCESS)
  173. {
  174. DWORD dwLength = MAX_PATH;
  175. RegQueryValueExA(hkeyHosts, DATABASEPATH, NULL, NULL, (LPBYTE)tmp,
  176. &dwLength);
  177. ExpandEnvironmentStringsA(tmp, PATH_HOSTS, MAX_PATH);
  178. RegCloseKey(hkeyHosts);
  179. }
  180. }
  181. else if (platform == WIN_9X)
  182. GetWindowsDirectoryA(PATH_HOSTS, MAX_PATH);
  183. else
  184. return ARES_ENOTFOUND;
  185. strcat(PATH_HOSTS, WIN_PATH_HOSTS);
  186. #elif defined(WATT32)
  187. extern const char *_w32_GetHostsFile (void);
  188. const char *PATH_HOSTS = _w32_GetHostsFile();
  189. if (!PATH_HOSTS)
  190. return ARES_ENOTFOUND;
  191. #endif
  192. fp = fopen(PATH_HOSTS, "r");
  193. if (!fp)
  194. {
  195. error = ERRNO;
  196. switch(error)
  197. {
  198. case ENOENT:
  199. case ESRCH:
  200. return ARES_ENOTFOUND;
  201. default:
  202. DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
  203. error, strerror(error)));
  204. DEBUGF(fprintf(stderr, "Error opening file: %s\n",
  205. PATH_HOSTS));
  206. *host = NULL;
  207. return ARES_EFILE;
  208. }
  209. }
  210. while ((status = ares__get_hostent(fp, addr->family, host)) == ARES_SUCCESS)
  211. {
  212. if (addr->family != (*host)->h_addrtype)
  213. {
  214. ares_free_hostent(*host);
  215. continue;
  216. }
  217. if (addr->family == AF_INET)
  218. {
  219. if (memcmp((*host)->h_addr, &addr->addrV4,
  220. sizeof(addr->addrV4)) == 0)
  221. break;
  222. }
  223. else if (addr->family == AF_INET6)
  224. {
  225. if (memcmp((*host)->h_addr, &addr->addrV6,
  226. sizeof(addr->addrV6)) == 0)
  227. break;
  228. }
  229. ares_free_hostent(*host);
  230. }
  231. fclose(fp);
  232. if (status == ARES_EOF)
  233. status = ARES_ENOTFOUND;
  234. if (status != ARES_SUCCESS)
  235. *host = NULL;
  236. return status;
  237. }
  238. static void ptr_rr_name(char *name, const struct ares_addr *addr)
  239. {
  240. if (addr->family == AF_INET)
  241. {
  242. unsigned long laddr = ntohl(addr->addrV4.s_addr);
  243. unsigned long a1 = (laddr >> 24UL) & 0xFFUL;
  244. unsigned long a2 = (laddr >> 16UL) & 0xFFUL;
  245. unsigned long a3 = (laddr >> 8UL) & 0xFFUL;
  246. unsigned long a4 = laddr & 0xFFUL;
  247. sprintf(name, "%lu.%lu.%lu.%lu.in-addr.arpa", a4, a3, a2, a1);
  248. }
  249. else
  250. {
  251. unsigned char *bytes = (unsigned char *)&addr->addrV6;
  252. /* There are too many arguments to do this in one line using
  253. * minimally C89-compliant compilers */
  254. sprintf(name,
  255. "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.",
  256. bytes[15]&0xf, bytes[15] >> 4, bytes[14]&0xf, bytes[14] >> 4,
  257. bytes[13]&0xf, bytes[13] >> 4, bytes[12]&0xf, bytes[12] >> 4,
  258. bytes[11]&0xf, bytes[11] >> 4, bytes[10]&0xf, bytes[10] >> 4,
  259. bytes[9]&0xf, bytes[9] >> 4, bytes[8]&0xf, bytes[8] >> 4);
  260. sprintf(name+strlen(name),
  261. "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
  262. bytes[7]&0xf, bytes[7] >> 4, bytes[6]&0xf, bytes[6] >> 4,
  263. bytes[5]&0xf, bytes[5] >> 4, bytes[4]&0xf, bytes[4] >> 4,
  264. bytes[3]&0xf, bytes[3] >> 4, bytes[2]&0xf, bytes[2] >> 4,
  265. bytes[1]&0xf, bytes[1] >> 4, bytes[0]&0xf, bytes[0] >> 4);
  266. }
  267. }
  268. #undef next_lookup
  269. #undef file_lookup