[tor-commits] [torsocks/master] Fix: remove the use of IPv4 sockaddr in connect

dgoulet at torproject.org dgoulet at torproject.org
Fri Apr 4 22:40:27 UTC 2014


commit e9d747f7fe76673b5940dd39e2de3d2caf67132c
Author: David Goulet <dgoulet at 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 at 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 &&





More information about the tor-commits mailing list