tor  0.4.2.0-alpha-dev
resolve.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
11 #include "lib/net/resolve.h"
12 
13 #include "lib/net/address.h"
14 #include "lib/net/inaddr.h"
15 #include "lib/malloc/malloc.h"
16 #include "lib/string/parse_int.h"
17 #include "lib/string/util_string.h"
18 
19 #include "ext/siphash.h"
20 #include "ext/ht.h"
21 
22 #ifdef HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
27 #endif
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 
32 #include <string.h>
33 
45 tor_lookup_hostname,(const char *name, uint32_t *addr))
46 {
47  tor_addr_t myaddr;
48  int ret;
49 
50  if (BUG(!addr))
51  return -1;
52 
53  *addr = 0;
54 
55  if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
56  return ret;
57 
58  if (tor_addr_family(&myaddr) == AF_INET) {
59  *addr = tor_addr_to_ipv4h(&myaddr);
60  return ret;
61  }
62 
63  return -1;
64 }
65 
66 #ifdef HAVE_GETADDRINFO
67 
68 /* Host lookup helper for tor_addr_lookup(), when getaddrinfo() is
69  * available on this system.
70  *
71  * See tor_addr_lookup() for details.
72  */
73 static int
74 tor_addr_lookup_host_getaddrinfo(const char *name,
75  uint16_t family,
76  tor_addr_t *addr)
77 {
78  int err;
79  struct addrinfo *res=NULL, *res_p;
80  struct addrinfo *best=NULL;
81  struct addrinfo hints;
82  int result = -1;
83  memset(&hints, 0, sizeof(hints));
84  hints.ai_family = family;
85  hints.ai_socktype = SOCK_STREAM;
86  err = tor_getaddrinfo(name, NULL, &hints, &res);
87  /* The check for 'res' here shouldn't be necessary, but it makes static
88  * analysis tools happy. */
89  if (!err && res) {
90  best = NULL;
91  for (res_p = res; res_p; res_p = res_p->ai_next) {
92  if (family == AF_UNSPEC) {
93  if (res_p->ai_family == AF_INET) {
94  best = res_p;
95  break;
96  } else if (res_p->ai_family == AF_INET6 && !best) {
97  best = res_p;
98  }
99  } else if (family == res_p->ai_family) {
100  best = res_p;
101  break;
102  }
103  }
104  if (!best)
105  best = res;
106  if (best->ai_family == AF_INET) {
107  tor_addr_from_in(addr,
108  &((struct sockaddr_in*)best->ai_addr)->sin_addr);
109  result = 0;
110  } else if (best->ai_family == AF_INET6) {
111  tor_addr_from_in6(addr,
112  &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
113  result = 0;
114  }
115  tor_freeaddrinfo(res);
116  return result;
117  }
118  return (err == EAI_AGAIN) ? 1 : -1;
119 }
120 
121 #else /* !(defined(HAVE_GETADDRINFO)) */
122 
123 /* Host lookup helper for tor_addr_lookup(), which calls getaddrinfo().
124  * Used when gethostbyname() is not available on this system.
125  *
126  * See tor_addr_lookup() for details.
127  */
128 static int
129 tor_addr_lookup_host_gethostbyname(const char *name,
130  tor_addr_t *addr)
131 {
132  struct hostent *ent;
133  int err;
134 #ifdef HAVE_GETHOSTBYNAME_R_6_ARG
135  char buf[2048];
136  struct hostent hostent;
137  int r;
138  r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
139 #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
140  char buf[2048];
141  struct hostent hostent;
142  ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
143 #elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
144  struct hostent_data data;
145  struct hostent hent;
146  memset(&data, 0, sizeof(data));
147  err = gethostbyname_r(name, &hent, &data);
148  ent = err ? NULL : &hent;
149 #else
150  ent = gethostbyname(name);
151 #ifdef _WIN32
152  err = WSAGetLastError();
153 #else
154  err = h_errno;
155 #endif /* defined(_WIN32) */
156 #endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
157  if (ent) {
158  if (ent->h_addrtype == AF_INET) {
159  tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
160  } else if (ent->h_addrtype == AF_INET6) {
161  tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
162  } else {
163  tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
164  }
165  return 0;
166  }
167 #ifdef _WIN32
168  return (err == WSATRY_AGAIN) ? 1 : -1;
169 #else
170  return (err == TRY_AGAIN) ? 1 : -1;
171 #endif
172 }
173 
174 #endif /* defined(HAVE_GETADDRINFO) */
175 
188 tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
189 {
190  /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
191  * something.
192  */
193  int parsed_family = 0;
194  int result = -1;
195 
196  tor_assert(name);
197  tor_assert(addr);
198  tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
199 
200  if (!*name) {
201  /* Empty address is an error. */
202  goto permfail;
203  }
204 
205  /* Is it an IP address? */
206  parsed_family = tor_addr_parse(addr, name);
207 
208  if (parsed_family >= 0) {
209  /* If the IP address family matches, or was unspecified */
210  if (parsed_family == family || family == AF_UNSPEC) {
211  goto success;
212  } else {
213  goto permfail;
214  }
215  } else {
216  /* Clear the address after a failed tor_addr_parse(). */
217  memset(addr, 0, sizeof(tor_addr_t));
218 #ifdef HAVE_GETADDRINFO
219  result = tor_addr_lookup_host_getaddrinfo(name, family, addr);
220  goto done;
221 #else /* !(defined(HAVE_GETADDRINFO)) */
222  result = tor_addr_lookup_host_gethostbyname(name, addr);
223  goto done;
224 #endif /* defined(HAVE_GETADDRINFO) */
225  }
226 
227  /* If we weren't successful, and haven't already set the result,
228  * assume it's a permanent failure */
229  permfail:
230  result = -1;
231  goto done;
232  success:
233  result = 0;
234 
235  /* We have set the result, now it's time to clean up */
236  done:
237  if (result) {
238  /* Clear the address on error */
239  memset(addr, 0, sizeof(tor_addr_t));
240  }
241  return result;
242 }
243 
254 int
255 tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
256 {
257  tor_addr_t addr;
258  uint16_t portval = 0;
259  char *tmp = NULL;
260  int rv = 0;
261  int result;
262 
263  tor_assert(s);
264  tor_assert(addr_out);
265 
266  s = eat_whitespace(s);
267 
268  /* Try parsing s as an address:port first, so we don't have to duplicate
269  * the logic that rejects IPv6:Port with no square brackets. */
270  rv = tor_addr_port_parse(LOG_WARN, s, &addr, &portval, 0);
271  /* That was easy, no DNS required. */
272  if (rv == 0)
273  goto success;
274 
275  /* Now let's check for malformed IPv6 addresses and ports:
276  * tor_addr_port_parse() requires squared brackes if there is a port,
277  * and we want tor_addr_port_lookup() to have the same requirement.
278  * But we strip the port using tor_addr_port_split(), so tor_addr_lookup()
279  * only sees the address, and will accept it without square brackets. */
280  int family = tor_addr_parse(&addr, s);
281  /* If tor_addr_parse() succeeds where tor_addr_port_parse() failed, we need
282  * to reject this address as malformed. */
283  if (family >= 0) {
284  /* Double-check it's an IPv6 address. If not, we have a parsing bug.
285  */
286  tor_assertf_nonfatal(family == AF_INET6,
287  "Wrong family: %d (should be IPv6: %d) which "
288  "failed IP:port parsing, but passed IP parsing. "
289  "input string: '%s'; parsed address: '%s'.",
290  family, AF_INET6, s, fmt_addr(&addr));
291  goto err;
292  }
293 
294  /* Now we have a hostname. Let's split off the port, if any. */
295  rv = tor_addr_port_split(LOG_WARN, s, &tmp, &portval);
296  if (rv < 0)
297  goto err;
298 
299  /* And feed the hostname to the lookup function. */
300  if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
301  goto err;
302 
303  success:
304  if (port_out)
305  *port_out = portval;
306  tor_addr_copy(addr_out, &addr);
307  result = 0;
308  goto done;
309 
310  err:
311  /* Clear the address and port on error */
312  memset(addr_out, 0, sizeof(tor_addr_t));
313  if (port_out)
314  *port_out = 0;
315  result = -1;
316 
317  /* We have set the result, now it's time to clean up */
318  done:
319  tor_free(tmp);
320  return result;
321 }
322 
323 #ifdef USE_SANDBOX_GETADDRINFO
324 
325 static int sandbox_getaddrinfo_is_active = 0;
326 
334 typedef struct cached_getaddrinfo_item_t {
335  HT_ENTRY(cached_getaddrinfo_item_t) node;
336  char *name;
337  int family;
339  struct addrinfo *res;
341  int err;
342 } cached_getaddrinfo_item_t;
343 
344 static unsigned
345 cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
346 {
347  return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
348 }
349 
350 static unsigned
351 cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
352  const cached_getaddrinfo_item_t *b)
353 {
354  return (a->family == b->family) && 0 == strcmp(a->name, b->name);
355 }
356 
357 #define cached_getaddrinfo_item_free(item) \
358  FREE_AND_NULL(cached_getaddrinfo_item_t, \
359  cached_getaddrinfo_item_free_, (item))
360 
361 static void
362 cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
363 {
364  if (item == NULL)
365  return;
366 
367  tor_free(item->name);
368  if (item->res)
369  freeaddrinfo(item->res);
370  tor_free(item);
371 }
372 
373 static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
374  getaddrinfo_cache = HT_INITIALIZER();
375 
376 HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
377  cached_getaddrinfo_item_hash,
378  cached_getaddrinfo_items_eq)
379 HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
380  cached_getaddrinfo_item_hash,
381  cached_getaddrinfo_items_eq,
383 
384 
385 static int sandbox_getaddrinfo_cache_disabled = 0;
386 
390 void
391 sandbox_disable_getaddrinfo_cache(void)
392 {
393  sandbox_getaddrinfo_cache_disabled = 1;
394 }
395 
396 void
397 tor_freeaddrinfo(struct addrinfo *ai)
398 {
399  if (sandbox_getaddrinfo_cache_disabled)
400  freeaddrinfo(ai);
401 }
402 
403 int
404 tor_getaddrinfo(const char *name, const char *servname,
405  const struct addrinfo *hints,
406  struct addrinfo **res)
407 {
408  int err;
409  struct cached_getaddrinfo_item_t search, *item;
410 
411  if (sandbox_getaddrinfo_cache_disabled) {
412  return getaddrinfo(name, NULL, hints, res);
413  }
414 
415  if (servname != NULL) {
416  log_warn(LD_BUG, "called with non-NULL servname");
417  return EAI_NONAME;
418  }
419  if (name == NULL) {
420  log_warn(LD_BUG, "called with NULL name");
421  return EAI_NONAME;
422  }
423 
424  *res = NULL;
425 
426  memset(&search, 0, sizeof(search));
427  search.name = (char *) name;
428  search.family = hints ? hints->ai_family : AF_UNSPEC;
429  item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
430 
431  if (! sandbox_getaddrinfo_is_active) {
432  /* If the sandbox is not turned on yet, then getaddrinfo and store the
433  result. */
434 
435  err = getaddrinfo(name, NULL, hints, res);
436  log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
437 
438  if (! item) {
439  item = tor_malloc_zero(sizeof(*item));
440  item->name = tor_strdup(name);
441  item->family = hints ? hints->ai_family : AF_UNSPEC;
442  HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
443  }
444 
445  if (item->res) {
446  freeaddrinfo(item->res);
447  item->res = NULL;
448  }
449  item->res = *res;
450  item->err = err;
451  return err;
452  }
453 
454  /* Otherwise, the sandbox is on. If we have an item, yield its cached
455  result. */
456  if (item) {
457  *res = item->res;
458  return item->err;
459  }
460 
461  /* getting here means something went wrong */
462  log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
463  return EAI_NONAME;
464 }
465 
466 int
467 tor_add_addrinfo(const char *name)
468 {
469  struct addrinfo *res;
470  struct addrinfo hints;
471  int i;
472  static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
473 
474  memset(&hints, 0, sizeof(hints));
475  hints.ai_socktype = SOCK_STREAM;
476  for (i = 0; i < 3; ++i) {
477  hints.ai_family = families[i];
478 
479  res = NULL;
480  (void) tor_getaddrinfo(name, NULL, &hints, &res);
481  if (res)
482  tor_freeaddrinfo(res);
483  }
484 
485  return 0;
486 }
487 
488 void
489 tor_free_getaddrinfo_cache(void)
490 {
491  cached_getaddrinfo_item_t **next, **item, *this;
492 
493  for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
494  item;
495  item = next) {
496  this = *item;
497  next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
498  cached_getaddrinfo_item_free(this);
499  }
500 
501  HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
502 }
503 
504 void
505 tor_make_getaddrinfo_cache_active(void)
506 {
507  sandbox_getaddrinfo_is_active = 1;
508 }
509 #else /* !(defined(USE_SANDBOX_GETADDRINFO)) */
510 void
511 sandbox_disable_getaddrinfo_cache(void)
512 {
513 }
514 void
515 tor_make_getaddrinfo_cache_active(void)
516 {
517 }
518 #endif /* defined(USE_SANDBOX_GETADDRINFO) */
MOCK_IMPL(int, tor_lookup_hostname,(const char *name, uint32_t *addr))
Definition: resolve.c:44
HT_PROTOTYPE(HT_GENERATE2(strmap_impl, HT_GENERATE2(strmap_entry_t, HT_GENERATE2(node, HT_GENERATE2(strmap_entry_hash, HT_GENERATE2(strmap_entries_eq)
Definition: map.c:87
static uint32_t tor_addr_to_ipv4h(const tor_addr_t *a)
Definition: address.h:152
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
Header for inaddr.c.
Headers for util_malloc.c.
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
Definition: resolve.c:255
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
Definition: malloc.c:146
#define tor_addr_from_in(dest, in)
Definition: address.h:291
tor_assert(buffer)
int tor_addr_port_parse(int severity, const char *addrport, tor_addr_t *address_out, uint16_t *port_out, int default_port)
Definition: address.c:1759
Headers for address.h.
const char * eat_whitespace(const char *s)
Definition: util_string.c:268
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1255
#define LOG_WARN
Definition: log.h:51
void tor_free_(void *mem)
Definition: malloc.c:227
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
Definition: address.c:896
#define fmt_addr(a)
Definition: address.h:211
Header for resolve.c.
#define LD_NET
Definition: log.h:64
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:904
Header for parse_int.c.
#define LD_BUG
Definition: log.h:84
static sa_family_t tor_addr_family(const tor_addr_t *a)
Definition: address.h:179
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1818