[tor-commits] [torsocks/master] Add support for gethostbyaddr_r(3)

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


commit 450abaddbef2b51ca4b845e6ad86c89051ab17d2
Author: David Goulet <dgoulet at ev0ke.net>
Date:   Mon Jul 15 01:57:33 2013 -0400

    Add support for gethostbyaddr_r(3)
    
    Signed-off-by: David Goulet <dgoulet at ev0ke.net>
---
 src/lib/gethostbyname.c |  195 +++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/torsocks.h      |   16 ++++
 2 files changed, 211 insertions(+)

diff --git a/src/lib/gethostbyname.c b/src/lib/gethostbyname.c
index 3e89e9b..af47e73 100644
--- a/src/lib/gethostbyname.c
+++ b/src/lib/gethostbyname.c
@@ -26,6 +26,98 @@
 #include "torsocks.h"
 
 /*
+ * Free the given hostent structure and all pointers contained inside.
+ */
+static void free_hostent(struct hostent *he)
+{
+	if (!he) {
+		return;
+	}
+
+	if (he->h_name) {
+		free(he->h_name);
+	}
+
+	if (he->h_aliases) {
+		int i = 0;
+
+		while (he->h_aliases[i] != NULL) {
+			free(he->h_aliases[i]);
+			i++;
+		}
+	}
+
+	if (he->h_addr_list) {
+		int i = 0;
+
+		while (he->h_addr_list[i] != NULL) {
+			free(he->h_addr_list[i]);
+			i++;
+		}
+	}
+
+	free(he);
+}
+
+/*
+ * Allocate a hostent structure with the given type.
+ *
+ * On error, return NULL.
+ */
+static struct hostent *alloc_hostent(int af)
+{
+	void *addr = NULL;
+	char **addr_list = NULL, **aliases = NULL;
+	struct hostent *he = NULL;
+	size_t addrlen;
+
+	if (af != AF_INET && af != AF_INET6) {
+		goto error;
+	}
+
+	he = zmalloc(sizeof(*he));
+	addr_list = zmalloc(sizeof(*addr_list) * 2);
+	aliases = zmalloc(sizeof(*aliases));
+	if (!he || !addr_list || !aliases) {
+		PERROR("zmalloc hostent");
+		goto error;
+	}
+
+	switch (af) {
+	case AF_INET:
+		addr = zmalloc(sizeof(struct in_addr));
+		addrlen = sizeof(struct in_addr);
+		break;
+	case AF_INET6:
+		addr = zmalloc(sizeof(struct in6_addr));
+		addrlen = sizeof(struct in6_addr);
+		break;
+	default:
+		assert(0);
+		goto error;
+	}
+	if (!addr) {
+		PERROR("zmalloc addr");
+		goto error;
+	}
+
+	he->h_name = NULL;
+	he->h_addr_list = addr_list;
+	he->h_addr_list[0] = addr;
+	he->h_addr_list[1] = NULL;
+	he->h_aliases = aliases;
+	he->h_aliases[0] = NULL;
+	he->h_length = addrlen;
+	he->h_addrtype = af;
+
+	return he;
+
+error:
+	free_hostent(he);
+	return NULL;
+}
+
+/*
  * Torsocks call for gethostbyname(3).
  *
  * NOTE: This call is OBSOLETE in the glibc.
@@ -179,3 +271,106 @@ LIBC_GETHOSTBYADDR_DECL
 {
 	return tsocks_gethostbyaddr(LIBC_GETHOSTBYADDR_ARGS);
 }
+
+/*
+ * Torsocks call for gethostbyaddr_r(3).
+ *
+ * NOTE: GNU extension. Reentrant version.
+ */
+LIBC_GETHOSTBYADDR_R_RET_TYPE tsocks_gethostbyaddr_r(LIBC_GETHOSTBYADDR_R_SIG)
+{
+	int ret;
+	struct hostent *he = NULL;
+
+	struct data {
+		char *hostname;
+		char *addr_list[2];
+		char padding[];
+	} *data;
+
+	if (__buflen < sizeof(struct data)) {
+		ret = ERANGE;
+		goto error;
+	}
+	data = (struct data *) __buf;
+	memset(data, 0, sizeof(*data));
+
+	/*
+	 * Tor does not allow to resolve to an IPv6 pointer so only accept inet
+	 * return address.
+	 */
+	if (!__addr || __type != AF_INET) {
+		ret = HOST_NOT_FOUND;
+		if (__h_errnop) {
+			*__h_errnop = HOST_NOT_FOUND;
+		}
+		goto error;
+	}
+
+	DBG("[gethostbyaddr_r] Requesting address %s of len %d and type %d",
+			inet_ntoa(*((struct in_addr *) __addr)), __len, __type);
+
+	/* This call allocates hostname. On error, it's untouched. */
+	ret = tsocks_tor_resolve_ptr(__addr, &data->hostname, __type);
+	if (ret < 0) {
+		const char *ret_str;
+
+		ret_str = inet_ntop(__type, __addr, __buf, __buflen);
+		if (!ret_str) {
+			ret = HOST_NOT_FOUND;
+			if (errno == ENOSPC) {
+				ret = ERANGE;
+			}
+			if (__h_errnop) {
+				*__h_errnop = HOST_NOT_FOUND;
+			}
+			goto error;
+		}
+	}
+
+	/* Ease our life a bit. */
+	he = __ret;
+
+	if (!he) {
+		ret = NO_RECOVERY;
+		if (__h_errnop) {
+			*__h_errnop = NO_RECOVERY;
+		}
+		goto error;
+	}
+
+	if (data->hostname) {
+		he->h_name = data->hostname;
+	} else {
+		ret = NO_RECOVERY;
+		if (__h_errnop) {
+			*__h_errnop = NO_RECOVERY;
+		}
+		goto error;
+	}
+
+	he->h_aliases = NULL;
+	he->h_length = strlen(he->h_name);
+	/* Assign the address list within the data of the given buffer. */
+	data->addr_list[0] = (char *) __addr;
+	data->addr_list[1] = NULL;
+	he->h_addr_list = data->addr_list;
+
+	if (__result) {
+		*__result = he;
+	}
+
+	/* Everything went good. */
+	ret = 0;
+
+error:
+	return ret;
+}
+
+/*
+ * Libc hijacked symbol gethostbyaddr_r(3).
+ */
+LIBC_GETHOSTBYADDR_R_DECL
+{
+	return tsocks_gethostbyaddr_r(LIBC_GETHOSTBYADDR_R_ARGS);
+}
diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h
index 4acacff..3cd51d0 100644
--- a/src/lib/torsocks.h
+++ b/src/lib/torsocks.h
@@ -90,6 +90,16 @@ char tsocks_he_name[255];
 #define LIBC_GETHOSTBYADDR_SIG const void *__addr, socklen_t __len, int __type
 #define LIBC_GETHOSTBYADDR_ARGS __addr, __len, __type
 
+/* GNU extension. Reentrant version. */
+#define LIBC_GETHOSTBYADDR_R_NAME gethostbyaddr_r
+#define LIBC_GETHOSTBYADDR_R_NAME_STR XSTR(LIBC_GETHOSTBYADDR_R_NAME)
+#define LIBC_GETHOSTBYADDR_R_RET_TYPE int
+#define LIBC_GETHOSTBYADDR_R_SIG const void *__addr, socklen_t __len, int __type, \
+	struct hostent *__ret, char *__buf, size_t __buflen, \
+	struct hostent **__result, int *__h_errnop
+#define LIBC_GETHOSTBYADDR_R_ARGS __addr, __len, __type, __ret, __buf, \
+	__buflen, __result, __h_errnop
+
 /* getaddrinfo(3) */
 #include <netdb.h>
 
@@ -138,6 +148,12 @@ TSOCKS_LIBC_DECL(gethostbyaddr, LIBC_GETHOSTBYADDR_RET_TYPE,
 #define LIBC_GETHOSTBYADDR_DECL LIBC_GETHOSTBYADDR_RET_TYPE \
 		LIBC_GETHOSTBYADDR_NAME(LIBC_GETHOSTBYADDR_SIG)
 
+/* gethostbyaddr_r(3) */
+TSOCKS_LIBC_DECL(gethostbyaddr_r, LIBC_GETHOSTBYADDR_R_RET_TYPE,
+		LIBC_GETHOSTBYADDR_R_SIG)
+#define LIBC_GETHOSTBYADDR_R_DECL LIBC_GETHOSTBYADDR_R_RET_TYPE \
+		LIBC_GETHOSTBYADDR_R_NAME(LIBC_GETHOSTBYADDR_R_SIG)
+
 /* getaddrinfo(3) */
 TSOCKS_LIBC_DECL(getaddrinfo, LIBC_GETADDRINFO_RET_TYPE,
 		LIBC_GETADDRINFO_SIG)





More information about the tor-commits mailing list