1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Use the libc DNS resolver to convert hostnames into addresses.
11 #define RESOLVE_PRIVATE
12 #include "lib/net/resolve.h"
14 #include "lib/net/address.h"
15 #include "lib/net/inaddr.h"
16 #include "lib/malloc/malloc.h"
17 #include "lib/string/parse_int.h"
18 #include "lib/string/util_string.h"
20 #include "ext/siphash.h"
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
26 #ifdef HAVE_SYS_SOCKET_H
27 #include <sys/socket.h>
35 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
36 * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
37 * on success, -1 on failure; 1 on transient failure.
39 * This function only accepts IPv4 addresses.
41 * (This function exists because standard windows gethostbyname
42 * doesn't treat raw IP addresses properly.)
46 tor_lookup_hostname
,(const char *name
, uint32_t *addr
))
56 if ((ret
= tor_addr_lookup(name
, AF_INET
, &myaddr
)))
59 if (tor_addr_family(&myaddr
) == AF_INET
) {
60 *addr
= tor_addr_to_ipv4h(&myaddr
);
67 #ifdef HAVE_GETADDRINFO
69 /* Host lookup helper for tor_addr_lookup(), when getaddrinfo() is
70 * available on this system.
72 * See tor_addr_lookup() for details.
75 tor_addr_lookup_host_impl
,(const char *name
,
80 struct addrinfo
*res
=NULL
, *res_p
;
81 struct addrinfo
*best
=NULL
;
82 struct addrinfo hints
;
84 memset(&hints
, 0, sizeof(hints
));
85 hints
.ai_family
= family
;
86 hints
.ai_socktype
= SOCK_STREAM
;
87 err
= tor_getaddrinfo(name
, NULL
, &hints
, &res
);
88 /* The check for 'res' here shouldn't be necessary, but it makes static
89 * analysis tools happy. */
92 for (res_p
= res
; res_p
; res_p
= res_p
->ai_next
) {
93 if (family
== AF_UNSPEC
) {
94 if (res_p
->ai_family
== AF_INET
) {
97 } else if (res_p
->ai_family
== AF_INET6
&& !best
) {
100 } else if (family
== res_p
->ai_family
) {
107 if (best
->ai_family
== AF_INET
) {
108 tor_addr_from_in(addr
,
109 &((struct sockaddr_in
*)best
->ai_addr
)->sin_addr
);
111 } else if (best
->ai_family
== AF_INET6
) {
112 tor_addr_from_in6(addr
,
113 &((struct sockaddr_in6
*)best
->ai_addr
)->sin6_addr
);
116 tor_freeaddrinfo(res
);
119 return (err
== EAI_AGAIN
) ? 1 : -1;
122 #else /* !defined(HAVE_GETADDRINFO) */
124 /* Host lookup helper for tor_addr_lookup(), which calls gethostbyname().
125 * Used when getaddrinfo() is not available on this system.
127 * See tor_addr_lookup() for details.
129 MOCK_IMPL(STATIC
int,
130 tor_addr_lookup_host_impl
,(const char *name
,
137 #ifdef HAVE_GETHOSTBYNAME_R_6_ARG
139 struct hostent hostent
;
141 r
= gethostbyname_r(name
, &hostent
, buf
, sizeof(buf
), &ent
, &err
);
142 #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
144 struct hostent hostent
;
145 ent
= gethostbyname_r(name
, &hostent
, buf
, sizeof(buf
), &err
);
146 #elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
147 struct hostent_data data
;
149 memset(&data
, 0, sizeof(data
));
150 err
= gethostbyname_r(name
, &hent
, &data
);
151 ent
= err
? NULL
: &hent
;
153 ent
= gethostbyname(name
);
155 err
= WSAGetLastError();
158 #endif /* defined(_WIN32) */
159 #endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
161 if (ent
->h_addrtype
== AF_INET
) {
162 tor_addr_from_in(addr
, (struct in_addr
*) ent
->h_addr
);
163 } else if (ent
->h_addrtype
== AF_INET6
) {
164 tor_addr_from_in6(addr
, (struct in6_addr
*) ent
->h_addr
);
166 tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
171 return (err
== WSATRY_AGAIN
) ? 1 : -1;
173 return (err
== TRY_AGAIN
) ? 1 : -1;
176 #endif /* defined(HAVE_GETADDRINFO) */
178 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
179 * *<b>addr</b> to the proper IP address and family. The <b>family</b>
180 * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
181 * <i>preferred</i> family, though another one may be returned if only one
182 * family is implemented for this address.
184 * Like tor_addr_parse(), this function accepts IPv6 addresses with or without
187 * Return 0 on success, -1 on failure; 1 on transient failure.
190 tor_addr_lookup
,(const char *name
, uint16_t family
, tor_addr_t
*addr
))
192 /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
195 int parsed_family
= 0;
200 tor_assert(family
== AF_INET
|| family
== AF_INET6
|| family
== AF_UNSPEC
);
203 /* Empty address is an error. */
207 /* Is it an IP address? */
208 parsed_family
= tor_addr_parse(addr
, name
);
210 if (parsed_family
>= 0) {
211 /* If the IP address family matches, or was unspecified */
212 if (parsed_family
== family
|| family
== AF_UNSPEC
) {
218 /* Clear the address after a failed tor_addr_parse(). */
219 memset(addr
, 0, sizeof(tor_addr_t
));
220 result
= tor_addr_lookup_host_impl(name
, family
, addr
);
224 /* If we weren't successful, and haven't already set the result,
225 * assume it's a permanent failure */
232 /* We have set the result, now it's time to clean up */
235 /* Clear the address on error */
236 memset(addr
, 0, sizeof(tor_addr_t
));
241 /** Parse an address or address-port combination from <b>s</b>, resolve the
242 * address as needed, and put the result in <b>addr_out</b> and (optionally)
245 * Like tor_addr_port_parse(), this function accepts:
246 * - IPv6 address and port, when the IPv6 address is in square brackets,
247 * - IPv6 address with square brackets,
248 * - IPv6 address without square brackets.
250 * Return 0 on success, negative on failure. */
252 tor_addr_port_lookup(const char *s
, tor_addr_t
*addr_out
, uint16_t *port_out
)
255 uint16_t portval
= 0;
261 tor_assert(addr_out
);
263 s
= eat_whitespace(s
);
265 /* Try parsing s as an address:port first, so we don't have to duplicate
266 * the logic that rejects IPv6:Port with no square brackets. */
267 rv
= tor_addr_port_parse(LOG_WARN
, s
, &addr
, &portval
, 0);
268 /* That was easy, no DNS required. */
272 /* Now let's check for malformed IPv6 addresses and ports:
273 * tor_addr_port_parse() requires squared brackes if there is a port,
274 * and we want tor_addr_port_lookup() to have the same requirement.
275 * But we strip the port using tor_addr_port_split(), so tor_addr_lookup()
276 * only sees the address, and will accept it without square brackets. */
277 int family
= tor_addr_parse(&addr
, s
);
278 /* If tor_addr_parse() succeeds where tor_addr_port_parse() failed, we need
279 * to reject this address as malformed. */
281 /* Double-check it's an IPv6 address. If not, we have a parsing bug.
283 tor_assertf_nonfatal(family
== AF_INET6
,
284 "Wrong family: %d (should be IPv6: %d) which "
285 "failed IP:port parsing, but passed IP parsing. "
286 "input string: '%s'; parsed address: '%s'.",
287 family
, AF_INET6
, s
, fmt_addr(&addr
));
291 /* Now we have a hostname. Let's split off the port, if any. */
292 rv
= tor_addr_port_split(LOG_WARN
, s
, &tmp
, &portval
);
296 /* And feed the hostname to the lookup function. */
297 if (tor_addr_lookup(tmp
, AF_UNSPEC
, &addr
) != 0)
303 tor_addr_copy(addr_out
, &addr
);
308 /* Clear the address and port on error */
309 memset(addr_out
, 0, sizeof(tor_addr_t
));
314 /* We have set the result, now it's time to clean up */
320 #ifdef USE_SANDBOX_GETADDRINFO
321 /** True if we should only return cached values */
322 static int sandbox_getaddrinfo_is_active
= 0;
324 /** Cache entry for getaddrinfo results; used when sandboxing is implemented
325 * so that we can consult the cache when the sandbox prevents us from doing
328 * We support only a limited range of getaddrinfo calls, where servname is null
329 * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
331 typedef struct cached_getaddrinfo_item_t
{
332 HT_ENTRY(cached_getaddrinfo_item_t
) node
;
335 /** set if no error; otherwise NULL */
336 struct addrinfo
*res
;
337 /** 0 for no error; otherwise an EAI_* value */
339 } cached_getaddrinfo_item_t
;
342 cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t
*item
)
344 return (unsigned)siphash24g(item
->name
, strlen(item
->name
)) + item
->family
;
348 cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t
*a
,
349 const cached_getaddrinfo_item_t
*b
)
351 return (a
->family
== b
->family
) && 0 == strcmp(a
->name
, b
->name
);
354 #define cached_getaddrinfo_item_free(item) \
355 FREE_AND_NULL(cached_getaddrinfo_item_t, \
356 cached_getaddrinfo_item_free_, (item))
359 cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t
*item
)
364 tor_free(item
->name
);
366 freeaddrinfo(item
->res
);
370 static HT_HEAD(getaddrinfo_cache
, cached_getaddrinfo_item_t
)
371 getaddrinfo_cache
= HT_INITIALIZER();
373 HT_PROTOTYPE(getaddrinfo_cache
, cached_getaddrinfo_item_t
, node
,
374 cached_getaddrinfo_item_hash
,
375 cached_getaddrinfo_items_eq
);
376 HT_GENERATE2(getaddrinfo_cache
, cached_getaddrinfo_item_t
, node
,
377 cached_getaddrinfo_item_hash
,
378 cached_getaddrinfo_items_eq
,
379 0.6, tor_reallocarray_
, tor_free_
);
381 /** If true, don't try to cache getaddrinfo results. */
382 static int sandbox_getaddrinfo_cache_disabled
= 0;
384 /** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
385 * tor-resolve, when we have no intention of initializing crypto or of
386 * installing the sandbox.*/
388 sandbox_disable_getaddrinfo_cache(void)
390 sandbox_getaddrinfo_cache_disabled
= 1;
394 tor_freeaddrinfo(struct addrinfo
*ai
)
396 if (sandbox_getaddrinfo_cache_disabled
)
401 tor_getaddrinfo(const char *name
, const char *servname
,
402 const struct addrinfo
*hints
,
403 struct addrinfo
**res
)
406 struct cached_getaddrinfo_item_t search
, *item
;
408 if (sandbox_getaddrinfo_cache_disabled
) {
409 return getaddrinfo(name
, NULL
, hints
, res
);
412 if (servname
!= NULL
) {
413 log_warn(LD_BUG
, "called with non-NULL servname");
417 log_warn(LD_BUG
, "called with NULL name");
423 memset(&search
, 0, sizeof(search
));
424 search
.name
= (char *) name
;
425 search
.family
= hints
? hints
->ai_family
: AF_UNSPEC
;
426 item
= HT_FIND(getaddrinfo_cache
, &getaddrinfo_cache
, &search
);
428 if (! sandbox_getaddrinfo_is_active
) {
429 /* If the sandbox is not turned on yet, then getaddrinfo and store the
432 err
= getaddrinfo(name
, NULL
, hints
, res
);
433 log_info(LD_NET
,"(Sandbox) getaddrinfo %s.", err
? "failed" : "succeeded");
436 item
= tor_malloc_zero(sizeof(*item
));
437 item
->name
= tor_strdup(name
);
438 item
->family
= hints
? hints
->ai_family
: AF_UNSPEC
;
439 HT_INSERT(getaddrinfo_cache
, &getaddrinfo_cache
, item
);
443 freeaddrinfo(item
->res
);
451 /* Otherwise, the sandbox is on. If we have an item, yield its cached
458 /* getting here means something went wrong */
459 log_err(LD_BUG
,"(Sandbox) failed to get address %s!", name
);
464 tor_add_addrinfo(const char *name
)
466 struct addrinfo
*res
;
467 struct addrinfo hints
;
469 static const int families
[] = { AF_INET
, AF_INET6
, AF_UNSPEC
};
471 memset(&hints
, 0, sizeof(hints
));
472 hints
.ai_socktype
= SOCK_STREAM
;
473 for (i
= 0; i
< 3; ++i
) {
474 hints
.ai_family
= families
[i
];
477 (void) tor_getaddrinfo(name
, NULL
, &hints
, &res
);
479 tor_freeaddrinfo(res
);
486 tor_free_getaddrinfo_cache(void)
488 cached_getaddrinfo_item_t
**next
, **item
, *this;
490 for (item
= HT_START(getaddrinfo_cache
, &getaddrinfo_cache
);
494 next
= HT_NEXT_RMV(getaddrinfo_cache
, &getaddrinfo_cache
, item
);
495 cached_getaddrinfo_item_free(this);
498 HT_CLEAR(getaddrinfo_cache
, &getaddrinfo_cache
);
502 tor_make_getaddrinfo_cache_active(void)
504 sandbox_getaddrinfo_is_active
= 1;
506 #else /* !defined(USE_SANDBOX_GETADDRINFO) */
508 sandbox_disable_getaddrinfo_cache(void)
512 tor_make_getaddrinfo_cache_active(void)
515 #endif /* defined(USE_SANDBOX_GETADDRINFO) */