commit 5c5707e9684932d7659b4e6166dc1ec9facef317 Author: David Goulet dgoulet@ev0ke.net Date: Sat Jun 22 20:19:50 2013 -0400
Implement the getaddrinfo(3) torsocks call
The tor resolve API does not support IPv6 yet at this commit so getaddrinfo basically only supports IPv4 for now.
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/lib/torsocks.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/torsocks.h | 17 +++++++++++ 2 files changed, 96 insertions(+)
diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c index f6e3501..7793e38 100644 --- a/src/lib/torsocks.c +++ b/src/lib/torsocks.c @@ -362,6 +362,9 @@ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) goto error; }
+ DBG("[connect] Socket family %s and type %d", + __addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type); + /* * 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 @@ -478,3 +481,79 @@ LIBC_GETHOSTBYNAME_DECL { return tsocks_gethostbyname(LIBC_GETHOSTBYNAME_ARGS); } + +/* + * Torsocks call for getaddrinfo(3). + */ +LIBC_GETADDRINFO_RET_TYPE tsocks_getaddrinfo(LIBC_GETADDRINFO_SIG) +{ + int ret, af; + struct in_addr addr4; + struct in6_addr addr6; + void *addr; + char *ip_str, ipv4[INET_ADDRSTRLEN], ipv6[INET6_ADDRSTRLEN]; + socklen_t ip_str_size; + const char *node; + + DBG("[getaddrinfo] Requesting %s hostname", __node); + + if (!__node) { + ret = EAI_NONAME; + goto error; + } + + /* Use right domain for the next step. */ + switch (__hints->ai_family) { + default: + /* Default value is to use IPv4. */ + case AF_INET: + addr = &addr4; + ip_str = ipv4; + ip_str_size = sizeof(ipv4); + af = AF_INET; + break; + case AF_INET6: + addr = &addr6; + ip_str = ipv6; + ip_str_size = sizeof(ipv6); + af = AF_INET6; + break; + } + + ret = inet_pton(af, __node, &addr); + if (ret == 0) { + /* The node most probably is a DNS name. */ + ret = tor_resolve(__node, (uint32_t *) addr); + if (ret < 0) { + ret = EAI_FAIL; + goto error; + } + + (void) inet_ntop(af, addr, ip_str, ip_str_size); + node = ip_str; + DBG("[getaddrinfo] Node %s resolved to %s", __node, node); + } else { + node = __node; + DBG("[getaddrinfo] Node %s will be passed to the libc call", node); + } + + ret = tsocks_libc_getaddrinfo(node, __service, __hints, __res); + if (ret) { + goto error; + } + + return 0; + +error: + return ret; +} + +/* + * Libc hijacked symbol getaddrinfo(3). + */ +LIBC_GETADDRINFO_DECL +{ + tsocks_libc_getaddrinfo = find_libc_symbol(LIBC_GETADDRINFO_NAME_STR, + TSOCKS_SYM_EXIT_NOT_FOUND); + return tsocks_getaddrinfo(LIBC_GETADDRINFO_ARGS); +} diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h index 7581764..adbe67f 100644 --- a/src/lib/torsocks.h +++ b/src/lib/torsocks.h @@ -64,6 +64,17 @@ char tsocks_he_addr[INET_ADDRSTRLEN]; #define LIBC_GETHOSTBYNAME_SIG const char *__name #define LIBC_GETHOSTBYNAME_ARGS __name
+/* getaddrinfo(3) */ +#include <netdb.h> + +#define LIBC_GETADDRINFO_NAME getaddrinfo +#define LIBC_GETADDRINFO_NAME_STR XSTR(LIBC_GETADDRINFO_NAME) +#define LIBC_GETADDRINFO_RET_TYPE int +#define LIBC_GETADDRINFO_SIG \ + const char *__node, const char *__service, const struct addrinfo *__hints,\ + struct addrinfo **__res +#define LIBC_GETADDRINFO_ARGS __node, __service, __hints, __res + #else #error "OS not supported." #endif /* __linux__ , __FreeBSD__, __darwin__ */ @@ -84,6 +95,12 @@ TSOCKS_LIBC_DECL(gethostbyname, LIBC_GETHOSTBYNAME_RET_TYPE, #define LIBC_GETHOSTBYNAME_DECL LIBC_GETHOSTBYNAME_RET_TYPE \ LIBC_GETHOSTBYNAME_NAME(LIBC_GETHOSTBYNAME_SIG)
+/* getaddrinfo(3) */ +TSOCKS_LIBC_DECL(getaddrinfo, LIBC_GETADDRINFO_RET_TYPE, + LIBC_GETADDRINFO_SIG) +#define LIBC_GETADDRINFO_DECL LIBC_GETADDRINFO_RET_TYPE \ + LIBC_GETADDRINFO_NAME(LIBC_GETADDRINFO_SIG) + /* * Those are actions to do during the lookup process of libc symbols. For * instance the connect(2) syscall is essential to Torsocks so the function