commit e9d747f7fe76673b5940dd39e2de3d2caf67132c Author: David Goulet dgoulet@ev0ke.net Date: Thu Feb 20 14:24:23 2014 +0000
Fix: remove the use of IPv4 sockaddr in connect
This modifies the onion find by ip to use generic sockaddr structure. Also, a utils call is added to extract the port from a sockaddr structure depending on the family.
This is a step in the direction of fully supported IPv6 thus removing the use of a cast sockaddr_in.
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/common/onion.c | 16 +++++++++++++--- src/common/onion.h | 2 +- src/common/utils.c | 24 ++++++++++++++++++++++++ src/common/utils.h | 1 + src/lib/connect.c | 8 ++------ src/lib/socket.c | 8 ++------ tests/unit/test_onion.c | 5 ++++- 7 files changed, 47 insertions(+), 17 deletions(-)
diff --git a/src/common/onion.c b/src/common/onion.c index 573ca19..67b4297 100644 --- a/src/common/onion.c +++ b/src/common/onion.c @@ -248,14 +248,24 @@ end: * Return entry on success or else NULL. */ ATTR_HIDDEN -struct onion_entry *onion_entry_find_by_ip(in_addr_t ip, +struct onion_entry *onion_entry_find_by_addr(const struct sockaddr *sa, struct onion_pool *pool) { int i; struct onion_entry *entry = NULL; + const struct sockaddr_in *sin; + + assert(sa); + + /* Onion cookie are only IPv4. */ + if (sa->sa_family == AF_INET6) { + goto end; + } + + sin = (const struct sockaddr_in *) sa;
DBG("[onion] Finding onion entry for IP %s", - inet_ntoa(*((struct in_addr *) &ip))); + inet_ntoa((*((struct in_addr *) &sin->sin_addr.s_addr))));
/* * XXX: This can be improved by simply getting the offset of the IP with @@ -264,7 +274,7 @@ struct onion_entry *onion_entry_find_by_ip(in_addr_t ip, * entries is 45. */ for (i = 0; i < pool->count; i++) { - if (pool->entries[i]->ip == ip) { + if (pool->entries[i]->ip == sin->sin_addr.s_addr) { entry = pool->entries[i]; DBG("[onion] Onion entry name %s found in pool.", entry->hostname); diff --git a/src/common/onion.h b/src/common/onion.h index 90b4d5b..64e8574 100644 --- a/src/common/onion.h +++ b/src/common/onion.h @@ -112,7 +112,7 @@ struct onion_entry *onion_entry_create(struct onion_pool *pool, const char *onion_name); struct onion_entry *onion_entry_find_by_name(const char *onion_name, struct onion_pool *pool); -struct onion_entry *onion_entry_find_by_ip(in_addr_t ip, +struct onion_entry *onion_entry_find_by_addr(const struct sockaddr *sa, struct onion_pool *pool);
static inline void onion_pool_lock(struct onion_pool *pool) diff --git a/src/common/utils.c b/src/common/utils.c index ba34e33..890bbde 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -344,3 +344,27 @@ int utils_is_addr_any(const struct sockaddr *sa) end: return ret; } + +/* + * For a given sockaddr, return the port value considering the address family + * structure. + * + * Return the port number in the sockaddr sa or -1 is family is not unknown. + */ +ATTR_HIDDEN +int utils_get_port_from_addr(const struct sockaddr *sa) +{ + int port; + + assert(sa); + + if (sa->sa_family == AF_INET) { + port = ((const struct sockaddr_in *) sa)->sin_port; + } else if (sa->sa_family == AF_INET6) { + port = ((const struct sockaddr_in6 *) sa)->sin6_port; + } else { + port = -1; + } + + return port; +} diff --git a/src/common/utils.h b/src/common/utils.h index 2f950aa..83ea825 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -33,5 +33,6 @@ int utils_is_address_ipv6(const char *ip); int utils_sockaddr_is_localhost(const struct sockaddr *sa); int utils_localhost_resolve(const char *name, int af, void *buf, size_t len); int utils_is_addr_any(const struct sockaddr *sa); +int utils_get_port_from_addr(const struct sockaddr *sa);
#endif /* TORSOCKS_UTILS_H */ diff --git a/src/lib/connect.c b/src/lib/connect.c index 03f6900..6622119 100644 --- a/src/lib/connect.c +++ b/src/lib/connect.c @@ -38,7 +38,6 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) socklen_t optlen; struct connection *new_conn; struct onion_entry *on_entry; - struct sockaddr_in *inet_addr;
DBG("Connect catched on fd %d", sockfd);
@@ -77,8 +76,6 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) DBG("[connect] Socket family %s and type %d", addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type);
- inet_addr = (struct sockaddr_in *) addr; - /* * Lock registry to get the connection reference if one. In this code path, * if a connection object is found, it will not be used since a double @@ -99,8 +96,7 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) * existing .onion address. */ onion_pool_lock(&tsocks_onion_pool); - on_entry = onion_entry_find_by_ip(inet_addr->sin_addr.s_addr, - &tsocks_onion_pool); + on_entry = onion_entry_find_by_addr(addr, &tsocks_onion_pool); onion_pool_unlock(&tsocks_onion_pool); if (on_entry) { /* @@ -113,7 +109,7 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) goto error; } new_conn->dest_addr.domain = CONNECTION_DOMAIN_NAME; - new_conn->dest_addr.hostname.port = inet_addr->sin_port; + new_conn->dest_addr.hostname.port = utils_get_port_from_addr(addr); new_conn->dest_addr.hostname.addr = strdup(on_entry->hostname); if (!new_conn->dest_addr.hostname.addr) { errno = ENOMEM; diff --git a/src/lib/socket.c b/src/lib/socket.c index 36d2a90..cf080b5 100644 --- a/src/lib/socket.c +++ b/src/lib/socket.c @@ -33,12 +33,7 @@ LIBC_SOCKET_RET_TYPE tsocks_socket(LIBC_SOCKET_SIG) domain, type, protocol);
if (type & SOCK_STREAM) { - if (domain == AF_INET6) { - /* Tor does not handle IPv6 at the moment. Reject it. */ - ERR("Socket is IPv6. Tor does not handle AF_INET6 connection."); - errno = EINVAL; - return -1; - } + goto end; } else { if (domain == AF_INET || domain == AF_INET6) { /* @@ -56,6 +51,7 @@ LIBC_SOCKET_RET_TYPE tsocks_socket(LIBC_SOCKET_SIG) } }
+end: /* Stream socket for INET/INET6 is good so open it. */ return tsocks_libc_socket(domain, type, protocol); } diff --git a/tests/unit/test_onion.c b/tests/unit/test_onion.c index 0c91f71..c29d5e9 100644 --- a/tests/unit/test_onion.c +++ b/tests/unit/test_onion.c @@ -34,6 +34,7 @@ static void test_onion_entry(struct onion_pool *pool) const char *onion_addr1 = "87idq6tnejk5plpn.onion"; const char *onion_addr2 = "97idq6tnejk5plpn.onion"; const char *onion_addr1_typo = "87idq6tnejk5plpn.onio"; + struct sockaddr_in sin;
diag("Onion entry subsystem initialization test");
@@ -71,7 +72,9 @@ static void test_onion_entry(struct onion_pool *pool) inet_ntoa(*((struct in_addr *) &entry->ip))) == 0, "Valid onion entry found by name");
- entry = onion_entry_find_by_ip(inet_addr(DEFAULT_ONION_ADDR_RANGE), pool); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(DEFAULT_ONION_ADDR_RANGE); + entry = onion_entry_find_by_addr((const struct sockaddr *) &sin, pool); ok(entry && pool->count == 1 && strcmp(entry->hostname, onion_addr1) == 0 &&
tor-commits@lists.torproject.org