|
@@ -1484,47 +1484,22 @@ tor_addr_is_multicast(const tor_addr_t *a)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/** Set *<b>addr</b> to the IP address (if any) of whatever interface
|
|
|
- * connects to the Internet. This address should only be used in checking
|
|
|
- * whether our address has changed. Return 0 on success, -1 on failure.
|
|
|
+/** Attempt to retrieve IP address of current host by utilizing some
|
|
|
+ * UDP socket trickery. Only look for address of given <b>family</b>.
|
|
|
+ * Set result to *<b>addr</b>. Return 0 on success, -1 on failure.
|
|
|
*/
|
|
|
-MOCK_IMPL(int,
|
|
|
-get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
|
|
|
+STATIC int
|
|
|
+get_interface_address6_via_udp_socket_hack(int severity,
|
|
|
+ sa_family_t family,
|
|
|
+ tor_addr_t *addr)
|
|
|
{
|
|
|
- /* XXX really, this function should yield a smartlist of addresses. */
|
|
|
- smartlist_t *addrs;
|
|
|
- int sock=-1, r=-1;
|
|
|
struct sockaddr_storage my_addr, target_addr;
|
|
|
+ int sock=-1, r=-1;
|
|
|
socklen_t addr_len;
|
|
|
- tor_assert(addr);
|
|
|
-
|
|
|
- /* Try to do this the smart way if possible. */
|
|
|
- if ((addrs = get_interface_addresses_raw(severity))) {
|
|
|
- int rv = -1;
|
|
|
- SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
|
|
|
- if (family != AF_UNSPEC && family != tor_addr_family(a))
|
|
|
- continue;
|
|
|
- if (tor_addr_is_loopback(a) ||
|
|
|
- tor_addr_is_multicast(a))
|
|
|
- continue;
|
|
|
-
|
|
|
- tor_addr_copy(addr, a);
|
|
|
- rv = 0;
|
|
|
-
|
|
|
- /* If we found a non-internal address, declare success. Otherwise,
|
|
|
- * keep looking. */
|
|
|
- if (!tor_addr_is_internal(a, 0))
|
|
|
- break;
|
|
|
- } SMARTLIST_FOREACH_END(a);
|
|
|
|
|
|
- SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
|
|
|
- smartlist_free(addrs);
|
|
|
- return rv;
|
|
|
- }
|
|
|
-
|
|
|
- /* Okay, the smart way is out. */
|
|
|
memset(addr, 0, sizeof(tor_addr_t));
|
|
|
memset(&target_addr, 0, sizeof(target_addr));
|
|
|
+
|
|
|
/* Don't worry: no packets are sent. We just need to use a real address
|
|
|
* on the actual Internet. */
|
|
|
if (family == AF_INET6) {
|
|
@@ -1546,6 +1521,7 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
|
|
|
} else {
|
|
|
return -1;
|
|
|
}
|
|
|
+
|
|
|
if (sock < 0) {
|
|
|
int e = tor_socket_errno(-1);
|
|
|
log_fn(severity, LD_NET, "unable to create socket: %s",
|
|
@@ -1574,6 +1550,45 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
+/** Set *<b>addr</b> to the IP address (if any) of whatever interface
|
|
|
+ * connects to the Internet. This address should only be used in checking
|
|
|
+ * whether our address has changed. Return 0 on success, -1 on failure.
|
|
|
+ */
|
|
|
+MOCK_IMPL(int,
|
|
|
+get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr))
|
|
|
+{
|
|
|
+ /* XXX really, this function should yield a smartlist of addresses. */
|
|
|
+ smartlist_t *addrs;
|
|
|
+ tor_assert(addr);
|
|
|
+
|
|
|
+ /* Try to do this the smart way if possible. */
|
|
|
+ if ((addrs = get_interface_addresses_raw(severity))) {
|
|
|
+ int rv = -1;
|
|
|
+ SMARTLIST_FOREACH_BEGIN(addrs, tor_addr_t *, a) {
|
|
|
+ if (family != AF_UNSPEC && family != tor_addr_family(a))
|
|
|
+ continue;
|
|
|
+ if (tor_addr_is_loopback(a) ||
|
|
|
+ tor_addr_is_multicast(a))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ tor_addr_copy(addr, a);
|
|
|
+ rv = 0;
|
|
|
+
|
|
|
+ /* If we found a non-internal address, declare success. Otherwise,
|
|
|
+ * keep looking. */
|
|
|
+ if (!tor_addr_is_internal(a, 0))
|
|
|
+ break;
|
|
|
+ } SMARTLIST_FOREACH_END(a);
|
|
|
+
|
|
|
+ SMARTLIST_FOREACH(addrs, tor_addr_t *, a, tor_free(a));
|
|
|
+ smartlist_free(addrs);
|
|
|
+ return rv;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Okay, the smart way is out. */
|
|
|
+ return get_interface_address6_via_udp_socket_hack(severity,family,addr);
|
|
|
+}
|
|
|
+
|
|
|
/* ======
|
|
|
* IPv4 helpers
|
|
|
* XXXX024 IPv6 deprecate some of these.
|