diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-03-31 14:37:09 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-03-31 14:37:09 -0400 |
commit | 30e933b13660e62d10997f4809b3f13235b30325 (patch) | |
tree | 51047f6ec5b72865e0a5fbb0cac60fde115c916a /src/common | |
parent | 732322b710d515a55ebbaa984fa12f19ccb333e8 (diff) | |
parent | b49ffb2a21ccbcf62c3e38b822043b4302d8c26f (diff) | |
download | tor-30e933b13660e62d10997f4809b3f13235b30325.tar.gz tor-30e933b13660e62d10997f4809b3f13235b30325.zip |
Merge branch 'ticket14710_squashed'
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/address.c | 99 | ||||
-rw-r--r-- | src/common/address.h | 3 | ||||
-rw-r--r-- | src/common/compat.c | 20 | ||||
-rw-r--r-- | src/common/compat.h | 10 |
4 files changed, 91 insertions, 41 deletions
diff --git a/src/common/address.c b/src/common/address.c index 42a116a91e..6bd107889a 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -1504,47 +1504,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) { @@ -1566,6 +1541,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", @@ -1573,27 +1549,74 @@ get_interface_address6,(int severity, sa_family_t family, tor_addr_t *addr)) goto err; } - if (connect(sock,(struct sockaddr *)&target_addr, addr_len) < 0) { + if (tor_connect_socket(sock,(struct sockaddr *)&target_addr, + addr_len) < 0) { int e = tor_socket_errno(sock); log_fn(severity, LD_NET, "connect() failed: %s", tor_socket_strerror(e)); goto err; } - if (getsockname(sock,(struct sockaddr*)&my_addr, &addr_len)) { + if (tor_getsockname(sock,(struct sockaddr*)&my_addr, &addr_len)) { int e = tor_socket_errno(sock); log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s", tor_socket_strerror(e)); goto err; } - tor_addr_from_sockaddr(addr, (struct sockaddr*)&my_addr, NULL); - r=0; + if (tor_addr_from_sockaddr(addr, (struct sockaddr*)&my_addr, NULL) == 0) { + if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) { + log_fn(severity, LD_NET, "Address that we determined via UDP socket" + " magic is unsuitable for public comms."); + } else { + r=0; + } + } + err: if (sock >= 0) tor_close_socket(sock); 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. diff --git a/src/common/address.h b/src/common/address.h index df835e917a..cd80615f93 100644 --- a/src/common/address.h +++ b/src/common/address.h @@ -274,6 +274,9 @@ tor_addr_port_t *tor_addr_port_new(const tor_addr_t *addr, uint16_t port); #ifdef ADDRESS_PRIVATE STATIC smartlist_t *get_interface_addresses_raw(int severity); +STATIC int get_interface_address6_via_udp_socket_hack(int severity, + sa_family_t family, + tor_addr_t *addr); #ifdef HAVE_IFADDRS_TO_SMARTLIST STATIC smartlist_t *ifaddrs_to_smartlist(const struct ifaddrs *ifa); diff --git a/src/common/compat.c b/src/common/compat.c index 1788e32ee3..8da7ef3f69 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1156,12 +1156,20 @@ mark_socket_open(tor_socket_t s) /** @} */ /** As socket(), but counts the number of open sockets. */ -tor_socket_t -tor_open_socket(int domain, int type, int protocol) +MOCK_IMPL(tor_socket_t, +tor_open_socket,(int domain, int type, int protocol)) { return tor_open_socket_with_extensions(domain, type, protocol, 1, 0); } +/** Mockable wrapper for connect(). */ +MOCK_IMPL(tor_socket_t, +tor_connect_socket,(tor_socket_t socket,const struct sockaddr *address, + socklen_t address_len)) +{ + return connect(socket,address,address_len); +} + /** As socket(), but creates a nonblocking socket and * counts the number of open sockets. */ tor_socket_t @@ -1308,6 +1316,14 @@ get_n_open_sockets(void) return n; } +/** Mockable wrapper for getsockname(). */ +MOCK_IMPL(int, +tor_getsockname,(tor_socket_t socket, struct sockaddr *address, + socklen_t *address_len)) +{ + return getsockname(socket, address, address_len); +} + /** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1 * on failure. */ diff --git a/src/common/compat.h b/src/common/compat.h index 11b41cded9..5189b7e056 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -463,7 +463,8 @@ int tor_close_socket(tor_socket_t s); tor_socket_t tor_open_socket_with_extensions( int domain, int type, int protocol, int cloexec, int nonblock); -tor_socket_t tor_open_socket(int domain, int type, int protocol); +MOCK_DECL(tor_socket_t, +tor_open_socket,(int domain, int type, int protocol)); tor_socket_t tor_open_socket_nonblocking(int domain, int type, int protocol); tor_socket_t tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len); @@ -474,8 +475,15 @@ tor_socket_t tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len, int cloexec, int nonblock); +MOCK_DECL(tor_socket_t, +tor_connect_socket,(tor_socket_t socket,const struct sockaddr *address, + socklen_t address_len)); int get_n_open_sockets(void); +MOCK_DECL(int, +tor_getsockname,(tor_socket_t socket, struct sockaddr *address, + socklen_t *address_len)); + #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags) #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags) |