resolve.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file resolve.c
  7. * \brief Use the libc DNS resolver to convert hostnames into addresses.
  8. **/
  9. #include "lib/net/resolve.h"
  10. #include "lib/net/address.h"
  11. #include "lib/malloc/util_malloc.h"
  12. #include "siphash.h"
  13. #include "ht.h"
  14. #ifdef HAVE_SYS_TYPES_H
  15. #include <sys/types.h>
  16. #endif
  17. #ifdef HAVE_SYS_SOCKET_H
  18. #include <sys/socket.h>
  19. #endif
  20. #ifdef HAVE_NETDB_H
  21. #include <netdb.h>
  22. #endif
  23. #include <string.h>
  24. /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
  25. * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
  26. * on success, -1 on failure; 1 on transient failure.
  27. *
  28. * (This function exists because standard windows gethostbyname
  29. * doesn't treat raw IP addresses properly.)
  30. */
  31. MOCK_IMPL(int,
  32. tor_lookup_hostname,(const char *name, uint32_t *addr))
  33. {
  34. tor_addr_t myaddr;
  35. int ret;
  36. if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
  37. return ret;
  38. if (tor_addr_family(&myaddr) == AF_INET) {
  39. *addr = tor_addr_to_ipv4h(&myaddr);
  40. return ret;
  41. }
  42. return -1;
  43. }
  44. #ifdef USE_SANDBOX_GETADDRINFO
  45. /** True if we should only return cached values */
  46. static int sandbox_getaddrinfo_is_active = 0;
  47. /** Cache entry for getaddrinfo results; used when sandboxing is implemented
  48. * so that we can consult the cache when the sandbox prevents us from doing
  49. * getaddrinfo.
  50. *
  51. * We support only a limited range of getaddrinfo calls, where servname is null
  52. * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
  53. */
  54. typedef struct cached_getaddrinfo_item_t {
  55. HT_ENTRY(cached_getaddrinfo_item_t) node;
  56. char *name;
  57. int family;
  58. /** set if no error; otherwise NULL */
  59. struct addrinfo *res;
  60. /** 0 for no error; otherwise an EAI_* value */
  61. int err;
  62. } cached_getaddrinfo_item_t;
  63. static unsigned
  64. cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
  65. {
  66. return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
  67. }
  68. static unsigned
  69. cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
  70. const cached_getaddrinfo_item_t *b)
  71. {
  72. return (a->family == b->family) && 0 == strcmp(a->name, b->name);
  73. }
  74. #define cached_getaddrinfo_item_free(item) \
  75. FREE_AND_NULL(cached_getaddrinfo_item_t, \
  76. cached_getaddrinfo_item_free_, (item))
  77. static void
  78. cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
  79. {
  80. if (item == NULL)
  81. return;
  82. tor_free(item->name);
  83. if (item->res)
  84. freeaddrinfo(item->res);
  85. tor_free(item);
  86. }
  87. static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
  88. getaddrinfo_cache = HT_INITIALIZER();
  89. HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
  90. cached_getaddrinfo_item_hash,
  91. cached_getaddrinfo_items_eq)
  92. HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
  93. cached_getaddrinfo_item_hash,
  94. cached_getaddrinfo_items_eq,
  95. 0.6, tor_reallocarray_, tor_free_)
  96. /** If true, don't try to cache getaddrinfo results. */
  97. static int sandbox_getaddrinfo_cache_disabled = 0;
  98. /** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
  99. * tor-resolve, when we have no intention of initializing crypto or of
  100. * installing the sandbox.*/
  101. void
  102. sandbox_disable_getaddrinfo_cache(void)
  103. {
  104. sandbox_getaddrinfo_cache_disabled = 1;
  105. }
  106. void
  107. tor_freeaddrinfo(struct addrinfo *ai)
  108. {
  109. if (sandbox_getaddrinfo_cache_disabled)
  110. freeaddrinfo(ai);
  111. }
  112. int
  113. tor_getaddrinfo(const char *name, const char *servname,
  114. const struct addrinfo *hints,
  115. struct addrinfo **res)
  116. {
  117. int err;
  118. struct cached_getaddrinfo_item_t search, *item;
  119. if (sandbox_getaddrinfo_cache_disabled) {
  120. return getaddrinfo(name, NULL, hints, res);
  121. }
  122. if (servname != NULL) {
  123. log_warn(LD_BUG, "called with non-NULL servname");
  124. return EAI_NONAME;
  125. }
  126. if (name == NULL) {
  127. log_warn(LD_BUG, "called with NULL name");
  128. return EAI_NONAME;
  129. }
  130. *res = NULL;
  131. memset(&search, 0, sizeof(search));
  132. search.name = (char *) name;
  133. search.family = hints ? hints->ai_family : AF_UNSPEC;
  134. item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
  135. if (! sandbox_getaddrinfo_is_active) {
  136. /* If the sandbox is not turned on yet, then getaddrinfo and store the
  137. result. */
  138. err = getaddrinfo(name, NULL, hints, res);
  139. log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
  140. if (! item) {
  141. item = tor_malloc_zero(sizeof(*item));
  142. item->name = tor_strdup(name);
  143. item->family = hints ? hints->ai_family : AF_UNSPEC;
  144. HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
  145. }
  146. if (item->res) {
  147. freeaddrinfo(item->res);
  148. item->res = NULL;
  149. }
  150. item->res = *res;
  151. item->err = err;
  152. return err;
  153. }
  154. /* Otherwise, the sandbox is on. If we have an item, yield its cached
  155. result. */
  156. if (item) {
  157. *res = item->res;
  158. return item->err;
  159. }
  160. /* getting here means something went wrong */
  161. log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
  162. return EAI_NONAME;
  163. }
  164. int
  165. tor_add_addrinfo(const char *name)
  166. {
  167. struct addrinfo *res;
  168. struct addrinfo hints;
  169. int i;
  170. static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
  171. memset(&hints, 0, sizeof(hints));
  172. hints.ai_socktype = SOCK_STREAM;
  173. for (i = 0; i < 3; ++i) {
  174. hints.ai_family = families[i];
  175. res = NULL;
  176. (void) tor_getaddrinfo(name, NULL, &hints, &res);
  177. if (res)
  178. tor_freeaddrinfo(res);
  179. }
  180. return 0;
  181. }
  182. void
  183. tor_free_getaddrinfo_cache(void)
  184. {
  185. cached_getaddrinfo_item_t **next, **item, *this;
  186. for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
  187. item;
  188. item = next) {
  189. this = *item;
  190. next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
  191. cached_getaddrinfo_item_free(this);
  192. }
  193. HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
  194. }
  195. void
  196. tor_make_getaddrinfo_cache_active(void)
  197. {
  198. sandbox_getaddrinfo_is_active = 1;
  199. }
  200. #endif