From fe037b7ff606840e4c0356f0b3789c468e8a4217 Mon Sep 17 00:00:00 2001 From: Robert Hogan Date: Sat, 26 Feb 2011 17:08:32 +0000 Subject: wip --- Makefile.am | 2 +- configure.in | 55 +++++- src/Makefile.am | 3 + src/expansion_table.h | 12 +- src/library_table.h | 44 +++++ src/torsocks.c | 63 +++++- src/torsocks.h.in | 64 +++++++ test/API/Makefile.am | 10 + test/test_torsocks.c | 494 ----------------------------------------------- test/test_torsocks.c.in | 496 ++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 742 insertions(+), 501 deletions(-) create mode 100644 src/library_table.h create mode 100644 src/torsocks.h.in create mode 100644 test/API/Makefile.am delete mode 100644 test/test_torsocks.c create mode 100644 test/test_torsocks.c.in diff --git a/Makefile.am b/Makefile.am index 0ef8147..aeb2089 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,4 +2,4 @@ # have all needed files, that a GNU package needs AUTOMAKE_OPTIONS = foreign 1.4 -SUBDIRS = src doc test +SUBDIRS = src doc test test/API diff --git a/configure.in b/configure.in index 75d5e1c..e4af5d9 100644 --- a/configure.in +++ b/configure.in @@ -294,6 +294,8 @@ AC_MSG_RESULT([select(${PROTO})]) AC_DEFINE_UNQUOTED([SELECT_SIGNATURE],[${PROTO}],[Description]) AC_DEFINE_UNQUOTED([SELECT_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([SELECT_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct connect prototype on this machine AC_MSG_CHECKING(for correct connect prototype) @@ -323,6 +325,9 @@ AC_MSG_RESULT([connect(${PROTO})]) AC_DEFINE_UNQUOTED([CONNECT_SIGNATURE],[${PROTO}],[Description]) AC_DEFINE_UNQUOTED([CONNECT_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([CONNECT_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Pick which of the sockaddr type arguments we need for dnl connect(), we need to cast one of ours to it later SOCKETARG="struct sockaddr *" @@ -354,6 +359,8 @@ AC_MSG_RESULT([close(${PROTO})]) AC_DEFINE_UNQUOTED([CLOSE_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([CLOSE_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([CLOSE_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct res_querydomain prototype on this machine AC_MSG_CHECKING(for correct res_querydomain prototype) @@ -378,6 +385,8 @@ AC_MSG_RESULT([res_querydomain(${PROTO})]) AC_DEFINE_UNQUOTED([RES_QUERYDOMAIN_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([RES_QUERYDOMAIN_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([RES_QUERYDOMAIN_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct res_send prototype on this machine AC_MSG_CHECKING(for correct res_send prototype) @@ -404,6 +413,8 @@ AC_MSG_RESULT([res_send(${PROTO})]) AC_DEFINE_UNQUOTED([RES_SEND_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([RES_SEND_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([RES_SEND_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct res_search prototype on this machine AC_MSG_CHECKING(for correct res_search prototype) @@ -428,6 +439,8 @@ AC_MSG_RESULT([res_search(${PROTO})]) AC_DEFINE_UNQUOTED([RES_SEARCH_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([RES_SEARCH_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([RES_SEARCH_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct res_query prototype on this machine AC_MSG_CHECKING(for correct res_query prototype) @@ -452,6 +465,9 @@ AC_MSG_RESULT([res_query(${PROTO})]) AC_DEFINE_UNQUOTED([RES_QUERY_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([RES_QUERY_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([RES_QUERY_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Find the correct getpeername prototype on this machine AC_MSG_CHECKING(for correct getpeername prototype) PROTO= @@ -480,6 +496,8 @@ AC_MSG_RESULT([getpeername(${PROTO})]) AC_DEFINE_UNQUOTED(GETPEERNAME_SIGNATURE, [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([GETPEERNAME_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([GETPEERNAME_FUNCTION_SIGNATURE],[${PROTO}]) dnl Find the correct poll prototype on this machine AC_MSG_CHECKING(for correct poll prototype) @@ -503,42 +521,62 @@ AC_MSG_RESULT([poll(${PROTO})]) AC_DEFINE_UNQUOTED([POLL_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([POLL_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([POLL_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for gethostbyname PROTO="const char *name" NAMES='name' AC_DEFINE_UNQUOTED([GETHOSTBYNAME_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([GETHOSTBYNAME_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([GETHOSTBYNAME_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for getaddrinfo PROTO="const char *node, const char *service, void *hints, void *res" NAMES='node, service, hints, res' AC_DEFINE_UNQUOTED([GETADDRINFO_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([GETADDRINFO_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([GETADDRINFO_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for getipnodebyname PROTO="const char *name, int af, int flags, int *error_num" NAMES='name, af, flags, error_num' AC_DEFINE_UNQUOTED([GETIPNODEBYNAME_SIGNATURE], [${PROTO}],[Description]) AC_DEFINE_UNQUOTED([GETIPNODEBYNAME_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([GETIPNODEBYNAME_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for gethostbyaddr PROTO="const void *addr, socklen_t len, int type" NAMES='addr, len, type' AC_DEFINE_UNQUOTED(GETHOSTBYADDR_SIGNATURE, [${PROTO}], [Description]) AC_DEFINE_UNQUOTED([GETHOSTBYADDR_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([GETHOSTBYADDR_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for sendto PROTO="int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen" NAMES='s, buf, len, flags, to, tolen' AC_DEFINE_UNQUOTED(SENDTO_SIGNATURE, [${PROTO}], [Description]) AC_DEFINE_UNQUOTED([SENDTO_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([SENDTO_FUNCTION_SIGNATURE],[${PROTO}]) + dnl Emit signature for sendmsg PROTO="int s, const struct msghdr *msg, int flags" NAMES='s, msg, flags' AC_DEFINE_UNQUOTED(SENDMSG_SIGNATURE, [${PROTO}], [Description]) AC_DEFINE_UNQUOTED([SENDMSG_ARGNAMES],[${NAMES}],[Argument names]) +# Signature's variable for torsocks.h.in +AC_SUBST([SENDMSG_FUNCTION_SIGNATURE],[${PROTO}]) ############################################################################## # 5. Determine how to preload libtorsocks.so on this system. @@ -640,6 +678,19 @@ AC_SUBST(LIBTOOL_DEPS) AC_ENABLE_SHARED AC_ENABLE_STATIC -AC_CONFIG_FILES([src/usewithtor src/torsocks doc/torsocks.conf.5 doc/torsocks.8 doc/usewithtor.1 doc/torsocks.1]) -AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile test/Makefile) +AC_CONFIG_FILES([src/usewithtor src/torsocks src/torsocks.h doc/torsocks.conf.5 doc/torsocks.8 doc/usewithtor.1 doc/torsocks.1]) +AC_CONFIG_FILES(Makefile src/Makefile doc/Makefile test/API/Makefile test/Makefile) AC_OUTPUT + +############################################################################## +# 9. Generate the source files for testing the API and torsocks itself +############################################################################## +AC_PROG_SED + +AC_MSG_NOTICE(Creating source files for unit tests..) +AC_MSG_NOTICE(Generating test/test_torsocks.c) +sed 's/@FUNCTION_TOKEN@//g' test/test_torsocks.c.in > test/test_torsocks.c +AC_MSG_NOTICE(Generating test/API/test_torsocks_api.c) +sed 's/@FUNCTION_TOKEN@/torsocks_/g;s/\/\*TORSOCKS_INCLUDE\*\//#include \"..\/..\/src\/torsocks\.h\"/g' test/test_torsocks.c.in > test/API/test_torsocks_api.c +AC_MSG_NOTICE(Generating test/API/test_torsocks_real_api.c) +sed 's/@FUNCTION_TOKEN@/torsocks_real_/g;s/\/\*TORSOCKS_INCLUDE\*\//#include \"..\/..\/src\/torsocks\.h\"/g' test/test_torsocks.c.in > test/API/test_torsocks_real_api.c diff --git a/src/Makefile.am b/src/Makefile.am index 5f13f47..5205a26 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,9 @@ libtorsocks_la_LDFLAGS= $(TORSOCKSLDFLAGS) lib_LTLIBRARIES = libtorsocks.la libtorsocks_la_SOURCES = torsocks.c common.c parser.c dead_pool.c darwin_warts.c socks.c +library_includedir=$(includedir)/torsocks +library_include_HEADERS = torsocks.h + DISTCLEANFILES=parser.lo dead_pool.lo common.lo libtorsocks.lo torsocks.lo darwin_warts.lo socks.lo\ config.cache config.log config.h Makefile \ aclocal.m4 config.status usewithtor torsocks \ diff --git a/src/expansion_table.h b/src/expansion_table.h index e981f5d..a925bc1 100644 --- a/src/expansion_table.h +++ b/src/expansion_table.h @@ -70,10 +70,16 @@ #define FUNCD64_106(e,r,s,n,b,m) EMPTY_FUNC(e,r,s,n,b,m) #endif /* defined(__APPLE__) || defined(__darwin__) */ #define FUNC(e,r,s,n,b,m) PATCH_TABLE_EXPANSION(e,r,s,n,b,m) +#define LIBFUNC(e,r,s,n,b,m) LIBRARY_EXPANSION(e,r,s,n,b,m) -/* dlsym return type SIG/ARGS C name base name asm name */ -/* res_init takes void, so we do that one manually. */ -/*RES_FUNC (ERR, int, RES_INIT_, res_init, res_init, "res_init") */ +/* This section calls the PATCH_TABLE_EXPANSION macro for each function we're + overloading and creates a function in torsocks.c that overrides it. + + res_init takes void, so we do that one manually: + +RES_FUNC (ERR, int, RES_INIT_, res_init, res_init, "res_init") + +macro dlsym return type SIG/ARGS C name base name asm name */ RES_FUNC (ERR, int, RES_QUERY_, res_query, res_query, "res_query") RES_FUNC (ERR, int, RES_SEARCH_, res_search, res_search, "res_search") #if defined(__APPLE__) || defined(__darwin__) diff --git a/src/library_table.h b/src/library_table.h new file mode 100644 index 0000000..7c72eeb --- /dev/null +++ b/src/library_table.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * * + * Copyright (C) 2011 Robert Hogan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#define CREATE_FUNC(e,r,s,n,b,m,t) \ + TORSOCKS_API_TORIFIED_FUNCTION(e,r,s,n,b,m,t) \ + TORSOCKS_API_REAL_FUNCTION(e,r,s,n,b,m,t) + +/* This section calls the macros for each function we're + offering in libtorsocks.so (e.g. torsocks_connect()) and creates a function + in torsocks.c that trampolines up to torsocks_*_guts(). + +macro dlsym return type SIG/ARGS C name base name asm name return value if error */ + +CREATE_FUNC (ERR, int, CONNECT_, connect, connect, "connect", -1) +CREATE_FUNC (ERR, int, CLOSE_, close, close, "close", -1) +CREATE_FUNC (ERR, int, POLL_, poll, poll, "poll", -1) +CREATE_FUNC (ERR, ssize_t, SENDMSG_, sendmsg, sendmsg, "sendmsg", -1) +CREATE_FUNC (ERR, ssize_t, SENDTO_, sendto, sendto, "sendto", -1) +CREATE_FUNC (ERR, int, RES_QUERY_, res_query, res_query, "res_query", -1) +CREATE_FUNC (ERR, int, RES_SEARCH_, res_search, res_search, "res_search", -1) +CREATE_FUNC (ERR, int, RES_SEND_, res_send, res_send, "res_send", -1) +CREATE_FUNC (ERR, int, RES_QUERYDOMAIN_, res_querydomain, res_querydomain, "res_querydomain", -1) +CREATE_FUNC (ERR, struct hostent *, GETHOSTBYNAME_, gethostbyname, gethostbyname, "gethostbyname", NULL) +CREATE_FUNC (ERR, struct hostent *, GETHOSTBYADDR_, gethostbyaddr, gethostbyaddr, "gethostbyaddr", NULL) +CREATE_FUNC (ERR, int, GETADDRINFO_, getaddrinfo, getaddrinfo, "getaddrinfo", -1) +/* getipnodebyname is deprecated so do not report an error if it is not available.*/ +CREATE_FUNC (WARN, struct hostent *, GETIPNODEBYNAME_, getipnodebyname, getipnodebyname, "getipnodebyname", NULL) diff --git a/src/torsocks.c b/src/torsocks.c index a7af809..5d5d1ee 100644 --- a/src/torsocks.c +++ b/src/torsocks.c @@ -1,5 +1,4 @@ /*************************************************************************** - * * * * * Copyright (C) 2000-2008 Shaun Clowes * * Copyright (C) 2008-2011 Robert Hogan * @@ -73,6 +72,7 @@ const char *torsocks_progname = "libtorsocks"; /* Name used in err msgs #include "parser.h" #include "socks.h" #include "dead_pool.h" +#include "torsocks.h" /* Some function names are macroized on Darwin. Allow those names to expand accordingly. */ @@ -252,6 +252,67 @@ static int get_config () #include "expansion_table.h" #undef PATCH_TABLE_EXPANSION +/* + API for users linking against libtorsocks. Expands to function definitions for: + + torsocks_connect() + torsocks_close() + torsocks_poll() + torsocks_sendmsg + torsocks_sendto + torsocks_res_query() + torsocks_res_search() + torsocks_res_send() + torsocks_res_querydomain() + torsocks_gethostbyname() + torsocks_gethostbyaddr() + torsocks_getaddrinfo() + torsocks_getipnodebyname() + + See also torsocks.h +*/ +#define TORSOCKS_API_TORIFIED_FUNCTION(e,r,s,n,b,m,t) \ + r torsocks_##n(s##SIGNATURE) { \ + if (!real##n) { \ + dlerror(); \ + if ((real##n = dlsym(RTLD_NEXT, m)) == NULL) \ + LOAD_ERROR(m, MSG##e); \ + } \ + show_msg(MSGTEST, "API: Calling torsocks %s\n", m); \ + return torsocks_##b##_guts(s##ARGNAMES, real##n); \ + } +/* + API for users linking against libtorsocks. Expands to function definitions for: + + torsocks_real_connect() + torsocks_real_close() + torsocks_real_poll() + torsocks_real_sendmsg + torsocks_real_sendto + torsocks_real_res_query() + torsocks_real_res_search() + torsocks_real_res_send() + torsocks_real_res_querydomain() + torsocks_real_gethostbyname() + torsocks_real_gethostbyaddr() + torsocks_real_getaddrinfo() + torsocks_real_getipnodebyname() + + See also torsocks.h +*/ +#define TORSOCKS_API_REAL_FUNCTION(e,r,s,n,b,m,t) \ + r torsocks_real_##n(s##SIGNATURE) { \ + if (!real##n) { \ + show_msg(MSGERR, "Unresolved symbol: %s\n", m); \ + return t; \ + } \ + show_msg(MSGTEST, "API: Calling real %s\n", m); \ + return real##n(s##ARGNAMES); \ + } +#include "library_table.h" +#undef LIBRARY_EXPANSION +#undef REAL_EXPANSION + int torsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNATURE)) { struct sockaddr_in *connaddr; diff --git a/src/torsocks.h.in b/src/torsocks.h.in new file mode 100644 index 0000000..0e48e2d --- /dev/null +++ b/src/torsocks.h.in @@ -0,0 +1,64 @@ +/*************************************************************************** + * * + * Copyright (C) 2011 Robert Hogan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* torsocks.h - API for users linking against torsocks */ + +#ifndef _TORSOCKS_H +#define _TORSOCKS_H 1 + +#include +#include +#include + +/* Calling these functions will ensure the request uses Tor if it is available. + Otherwise the call will fail */ +int torsocks_connect(@CONNECT_FUNCTION_SIGNATURE@); +int torsocks_close(@CLOSE_FUNCTION_SIGNATURE@); +int torsocks_poll(@POLL_FUNCTION_SIGNATURE@); +int torsocks_select(@SELECT_FUNCTION_SIGNATURE@); +int torsocks_res_querydomain(@RES_QUERYDOMAIN_FUNCTION_SIGNATURE@); +int torsocks_res_send(@RES_SEND_FUNCTION_SIGNATURE@); +int torsocks_res_search(@RES_SEARCH_FUNCTION_SIGNATURE@); +int torsocks_res_query(@RES_QUERY_FUNCTION_SIGNATURE@); +int torsocks_getpeername(@GETPEERNAME_FUNCTION_SIGNATURE@); +struct hostent *torsocks_gethostbyname(@GETHOSTBYNAME_FUNCTION_SIGNATURE@); +struct hostent *torsocks_gethostbyaddr(@GETHOSTBYADDR_FUNCTION_SIGNATURE@); +int torsocks_getaddrinfo(@GETADDRINFO_FUNCTION_SIGNATURE@); +struct hostent *torsocks_getipnodebyname(@GETIPNODEBYNAME_FUNCTION_SIGNATURE@); +ssize_t torsocks_sendto(@SENDTO_FUNCTION_SIGNATURE@); +ssize_t torsocks_sendmsg(@SENDMSG_FUNCTION_SIGNATURE@); + +/* Calling these functions will ensure the request bypasses Tor. */ +int torsocks_real_connect(@CONNECT_FUNCTION_SIGNATURE@); +int torsocks_real_close(@CLOSE_FUNCTION_SIGNATURE@); +int torsocks_real_poll(@POLL_FUNCTION_SIGNATURE@); +int torsocks_real_select(@SELECT_FUNCTION_SIGNATURE@); +int torsocks_real_res_querydomain(@RES_QUERYDOMAIN_FUNCTION_SIGNATURE@); +int torsocks_real_res_send(@RES_SEND_FUNCTION_SIGNATURE@); +int torsocks_real_res_search(@RES_SEARCH_FUNCTION_SIGNATURE@); +int torsocks_real_res_query(@RES_QUERY_FUNCTION_SIGNATURE@); +int torsocks_real_getpeername(@GETPEERNAME_FUNCTION_SIGNATURE@); +struct hostent *torsocks_real_gethostbyname(@GETHOSTBYNAME_FUNCTION_SIGNATURE@); +struct hostent *torsocks_real_gethostbyaddr(@GETHOSTBYADDR_FUNCTION_SIGNATURE@); +int torsocks_real_getaddrinfo(@GETADDRINFO_FUNCTION_SIGNATURE@); +struct hostent *torsocks_real_getipnodebyname(@GETIPNODEBYNAME_FUNCTION_SIGNATURE@); +ssize_t torsocks_real_sendto(@SENDTO_FUNCTION_SIGNATURE@); +ssize_t torsocks_real_sendmsg(@SENDMSG_FUNCTION_SIGNATURE@); + +#endif diff --git a/test/API/Makefile.am b/test/API/Makefile.am new file mode 100644 index 0000000..dda0537 --- /dev/null +++ b/test/API/Makefile.am @@ -0,0 +1,10 @@ +noinst_PROGRAMS= test_torsocks_api test_torsocks_real_api + +test_torsocks_api_LDADD = ../../src/libtorsocks.la +test_torsocks_real_api_LDADD = ../../src/libtorsocks.la +test_torsocks_api_LDFLAGS= $(TESTLDFLAGS) +test_torsocks_real_api_LDFLAGS= $(TESTLDFLAGS) + +test_torsocks_api_SOURCES= test_torsocks_api.c +test_torsocks_real_api_SOURCES= test_torsocks_real_api.c +CLEANFILES= test_torsocks_api test_torsocks_real_api diff --git a/test/test_torsocks.c b/test/test_torsocks.c deleted file mode 100644 index d9ea32a..0000000 --- a/test/test_torsocks.c +++ /dev/null @@ -1,494 +0,0 @@ -/*************************************************************************** - * * - * Copyright (c) 2000 Alessandro Iurlano. * - * Copyright (C) 2004 Tomasz Kojm * - * Copyright (C) 2011 Robert Hogan * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* PreProcessor Defines */ -#include - -#include -#include -#include -#ifdef OPENBSD -#include -#endif -#include -#include -#ifndef HAVE_NETINET_IN_H -#include -#endif -#ifndef HAVE_ARPA_INET_H -#include -#endif -#include -#if defined(__APPLE__) || defined(__darwin__) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef OPENBSD -#include -#endif -#include -#include -#include -#include - -#ifndef LINUX -#include -#else -#include "queue.h" -#endif - -#ifndef PACKETSZ -#define PACKETSZ 512 -#endif - -static unsigned short csum (unsigned short *buf, int nwords) -{ - unsigned long sum; - for (sum = 0; nwords > 0; nwords--) - sum += *buf++; - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - return ~sum; -} - -static int icmp_test() -{ - - int sockfd; - char datagram[400]; - struct sockaddr_in dest; - struct ip *iphdr=(struct ip *) datagram; -#if defined(OPENBSD) || defined(FREEBSD) ||defined(__APPLE__) || defined(__darwin__) - struct icmp *icmphdr=(struct icmp *)(iphdr +1); -#else - struct icmphdr *icmphdr=(struct icmphdr *)(iphdr +1); -#endif - char *buff=(char *)(icmphdr +1); - printf("\n----------------icmp() TEST----------------------------\n\n"); - - if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0) - { - perror("socket"); - exit(1); - } - - memset(datagram,0,400); - strcpy(buff,"entzwei"); - dest.sin_family=AF_INET; - dest.sin_addr.s_addr=inet_addr("192.168.1.33"); - - iphdr->ip_v=4; - iphdr->ip_hl=5; - iphdr->ip_len=sizeof(datagram); - iphdr->ip_id=(unsigned char)htonl(54321); - iphdr->ip_off=0; - iphdr->ip_ttl=225; - iphdr->ip_p=1; - iphdr->ip_sum=0; - iphdr->ip_tos=0; - iphdr->ip_src.s_addr=inet_addr("192.168.1.35"); - iphdr->ip_dst.s_addr=dest.sin_addr.s_addr; - iphdr->ip_sum=csum((unsigned short *)datagram,iphdr->ip_len >> 1); - -#if defined(OPENBSD) || defined(FREEBSD) ||defined(__APPLE__) || defined(__darwin__) - icmphdr->icmp_type=130; - icmphdr->icmp_code=0; - icmphdr->icmp_cksum=htons(0xc3b0); -#else - icmphdr->type=130; - icmphdr->code=0; - icmphdr->checksum=htons(0xc3b0); - icmphdr->un.echo.sequence=0; - icmphdr->un.echo.id=0; -#endif - int one=1; - int *val=&one; - if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one))<0) - printf("cannot set HDRINCL!\n"); - - - if(sendto(sockfd,datagram,35,0,(struct sockaddr *)&dest,sizeof(dest))<0) - { - perror("sendto"); - exit(1); - } - - return(0); -} - -static char *txtquery(const char *domain, unsigned int *ttl) -{ - unsigned char answer[PACKETSZ], *answend, *pt; - char *txt, host[128]; - int len, type, qtype; - unsigned int cttl, size, txtlen = 0; - - - *ttl = 0; - if(res_init() < 0) { - printf("^res_init failed\n"); - return NULL; - } - - printf("*Querying %s\n", domain); - - memset(answer, 0, PACKETSZ); - qtype = T_TXT; - if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0 || len > PACKETSZ) { - /* The DNS server in the SpeedTouch Alcatel 510 modem can't - * handle a TXT-query, but it can resolve an ANY-query to a - * TXT-record, so we try an ANY-query now. The thing we try - * to resolve normally only has a TXT-record anyway. - */ - memset(answer, 0, PACKETSZ); - qtype=T_ANY; - if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0) { - printf("^Can't query %s\n", domain); - return NULL; - } - } - - answend = answer + len; - pt = answer + sizeof(HEADER); - - if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) { - printf("^dn_expand failed\n"); - return NULL; - } - - pt += len; - if(pt > answend-4) { - printf("^Bad (too short) DNS reply\n"); - return NULL; - } - - GETSHORT(type, pt); - if(type != qtype) { - printf("^Broken DNS reply.\n"); - return NULL; - } - - pt += INT16SZ; /* class */ - size = 0; - do { /* recurse through CNAME rr's */ - pt += size; - if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) { - printf("^second dn_expand failed\n"); - return NULL; - } - printf("^Host: %s\n", host); - pt += len; - if(pt > answend-10) { - printf("^Bad (too short) DNS reply\n"); - return NULL; - } - GETSHORT(type, pt); - pt += INT16SZ; /* class */ - GETLONG(cttl, pt); - GETSHORT(size, pt); - if(pt + size < answer || pt + size > answend) { - printf("^DNS rr overflow\n"); - return NULL; - } - } while(type == T_CNAME); - - if(type != T_TXT) { - printf("^Not a TXT record\n"); - return NULL; - } - - if(!size || (txtlen = *pt) >= size || !txtlen) { - printf("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); - return NULL; - } - - if(!(txt = (char *) malloc(txtlen + 1))) - return NULL; - - memcpy(txt, pt+1, txtlen); - txt[txtlen] = 0; - *ttl = cttl; - - return txt; -} - -static int res_tests(char *ip, char *test) { - unsigned char dnsreply[1024]; - unsigned char host[128]; - int ret = 0, i; - char buf[16]; - struct sockaddr_in addr; - - memset( dnsreply, '\0', sizeof( dnsreply )); - - printf("\n---------------------- %s res_init() TEST----------------------\n\n", test); - if (res_init() == -1) { - printf("res_init failed\n"); - return -1; - } - - - addr.sin_family=AF_INET; - addr.sin_port=htons(53); - addr.sin_addr.s_addr=inet_addr(ip); - - for (i = 0; i < _res.nscount; i++) - memcpy(&_res.nsaddr_list[i], &addr, sizeof(struct sockaddr_in)); - - inet_ntop(AF_INET, &_res.nsaddr_list[0].sin_addr.s_addr, buf, sizeof(buf)); - printf("nameserver for test: %s\n", buf); - - /* Modifying _res directly doesn't work, so we have to use res_n* where available. - See: http://sourceware.org/ml/libc-help/2009-11/msg00013.html */ - printf("\n---------------------- %s res_query() TEST----------------------\n\n", test); - snprintf((char *)host, 127, "www.google.com"); -#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) - ret = res_nquery(&_res, (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#else - ret = res_query((char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#endif - printf("return code: %i\n", ret); - - printf("\n---------------------- %s res_search() TEST----------------------\n\n", test); - memset( dnsreply, '\0', sizeof( dnsreply )); -#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) - ret = res_nsearch(&_res, (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#else - ret = res_search((char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#endif - printf("return code: %i\n", ret); - - printf("\n--------------- %s res_querydomain() TEST----------------------\n\n", test); - memset( dnsreply, '\0', sizeof( dnsreply )); -#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) - ret = res_nquerydomain(&_res, "www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#else - ret = res_querydomain("www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply )); -#endif - printf("return code: %i\n", ret); - - printf("\n---------------------- %s res_send() TEST----------------------\n\n", test); - memset( dnsreply, '\0', sizeof( dnsreply )); -#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) - ret = res_nsend(&_res, host, 32, dnsreply, sizeof( dnsreply )); -#else - ret = res_send(host, 32, dnsreply, sizeof( dnsreply )); -#endif -printf("return code: %i\n", ret); - - return ret; -} - -static int res_internet_tests() { - char *ip = "8.8.8.8"; - char *test = "internet"; - return res_tests(ip, test); -} - -static int res_local_tests() { - char *ip = "192.168.1.1"; - char *test = "local"; - return res_tests(ip, test); -} - -static int udp_test() { - struct sockaddr_in addr; - char testtext[]="This message should be sent via udp\nThis is row number 2\nAnd then number three\n"; - int sock,ret,wb,flags=0; - char *ip = "6.6.6.6"; - - printf("\n----------------------UDP TEST----------------------\n\n"); - - addr.sin_family=AF_INET; - addr.sin_port=53; - addr.sin_addr.s_addr=inet_addr(ip); - - sock=socket(AF_INET,SOCK_DGRAM,0); - - struct iovec iov; - struct msghdr msg; - - iov.iov_base = (void *)testtext; - iov.iov_len = strlen(testtext); - - msg.msg_name = (struct sockaddr *)&addr; - msg.msg_namelen = sizeof(addr); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - - printf("\n----------------------udp sendmsg() TEST-------------------\n\n"); - wb=0; - ret=sendmsg(sock, &msg, flags); - printf("sendmsg() returned ret=%d wb=%d\n",ret,wb); - - printf("\n----------------------udp sendto() TEST--------------------\n\n"); - wb=0; - ret=sendto(sock,testtext,strlen(testtext)+1,wb, (struct sockaddr*)&addr, sizeof(addr)); - ret=sendto(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb, (struct sockaddr*)&addr, sizeof(addr)); - printf("sendto() returned ret=%d wb=%d\n",ret,wb); - - printf("\n----------------------udp connect() TEST-------------------\n\n"); - ret=connect(sock,(struct sockaddr*)&addr,sizeof(addr)); - printf("Connect returned ret=%d\n",ret); - - printf("\n----------------------udp send() TEST----------------------\n\n"); - wb=0; - ret=send(sock,testtext,strlen(testtext)+1,wb); - ret=send(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb); - printf("Note: no interception by torsocks expected as send() requires a socket in a connected state.\n"); - printf("send() returned ret=%d wb=%d\n",ret,wb); - - return 0; -} - -static int gethostbyname_test() { - struct hostent *foo; - - printf("\n----------------------gethostbyname() TEST-----------------\n\n"); - - foo=gethostbyname("www.torproject.org"); - if (foo) { - int i; - for (i=0; foo->h_addr_list[i]; ++i) - printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i])); -/* for (i=0; foo->h_aliases[i]; ++i) - printf(" also known as %s\n",foo->h_aliases[i]);*/ - } - return 0; -} - -static int gethostbyaddr_test() { - struct in_addr bar; - struct hostent *foo; - - printf("\n----------------------gethostbyaddr() TEST-----------------\n\n"); - - inet_aton("38.229.70.16", &bar); - foo=gethostbyaddr(&bar,4,AF_INET); - if (foo) { - int i; - for (i=0; foo->h_addr_list[i]; ++i) - printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i])); - for (i=0; foo->h_aliases[i]; ++i) - printf(" also known as %s\n",foo->h_aliases[i]); - } - return 0; -} - -static int getaddrinfo_test() { - struct addrinfo hints; - struct addrinfo *result; - int s; - - printf("\n----------------------getaddrinfo() TEST-----------------\n\n"); - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ - hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ - hints.ai_protocol = 0; /* Any protocol */ - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - s = getaddrinfo(NULL, "www.torproject.org", &hints, &result); - if (s != 0) { - printf("getaddrinfo: %s\n", gai_strerror(s)); - } - - return 0; -} - -/* Unavailable in glibc. */ -/* -static int getipnodebyname_test() { - int error; - - printf("\n----------------------getipnodebyname() TEST-----------------\n\n"); - - getipnodebyname("www.torproject.org", AF_INET, 0, &error); - if (error != 0) { - printf("getipnodebyname error: %i\n", error); - } - - return 0; -} -*/ - -static int connect_test(const char *name, const char *ip, int port) -{ - int sock; - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(ip); - addr.sin_port = htons(port); - - printf("\n---------------------- %s connect() TEST----------------------\n\n", name); - - if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - return 1; - - if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) - return 1; - - return 0; -} - -static int connect_local_test() -{ - const char *ip = "192.168.1.1"; - const char *name = "local"; - int port = 80; - return connect_test(name, ip, port); -} - -static int connect_internet_test() -{ - const char *ip = "8.8.8.8"; - int port = 53; - const char *name = "internet"; - return connect_test(name, ip, port); -} - -int main() { - - getaddrinfo_test(); - udp_test(); - gethostbyaddr_test(); - gethostbyname_test(); - connect_local_test(); - connect_internet_test(); - res_internet_tests(); - res_local_tests(); - icmp_test(); - - return 0; -} diff --git a/test/test_torsocks.c.in b/test/test_torsocks.c.in new file mode 100644 index 0000000..ddfa2ea --- /dev/null +++ b/test/test_torsocks.c.in @@ -0,0 +1,496 @@ +/*************************************************************************** + * * + * Copyright (c) 2000 Alessandro Iurlano. * + * Copyright (C) 2004 Tomasz Kojm * + * Copyright (C) 2011 Robert Hogan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* PreProcessor Defines */ +#include + +#include +#include +#include +#ifdef OPENBSD +#include +#endif +#include +#include +#ifndef HAVE_NETINET_IN_H +#include +#endif +#ifndef HAVE_ARPA_INET_H +#include +#endif +#include +#if defined(__APPLE__) || defined(__darwin__) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef OPENBSD +#include +#endif +#include +#include +#include +#include + +#ifndef LINUX +#include +#else +#include "queue.h" +#endif + +#ifndef PACKETSZ +#define PACKETSZ 512 +#endif + +/*TORSOCKS_INCLUDE*/ + +static unsigned short csum (unsigned short *buf, int nwords) +{ + unsigned long sum; + for (sum = 0; nwords > 0; nwords--) + sum += *buf++; + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; +} + +static int icmp_test() +{ + + int sockfd; + char datagram[400]; + struct sockaddr_in dest; + struct ip *iphdr=(struct ip *) datagram; +#if defined(OPENBSD) || defined(FREEBSD) ||defined(__APPLE__) || defined(__darwin__) + struct icmp *icmphdr=(struct icmp *)(iphdr +1); +#else + struct icmphdr *icmphdr=(struct icmphdr *)(iphdr +1); +#endif + char *buff=(char *)(icmphdr +1); + printf("\n----------------icmp() TEST----------------------------\n\n"); + + if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0) + { + perror("socket"); + exit(1); + } + + memset(datagram,0,400); + strcpy(buff,"entzwei"); + dest.sin_family=AF_INET; + dest.sin_addr.s_addr=inet_addr("192.168.1.33"); + + iphdr->ip_v=4; + iphdr->ip_hl=5; + iphdr->ip_len=sizeof(datagram); + iphdr->ip_id=(unsigned char)htonl(54321); + iphdr->ip_off=0; + iphdr->ip_ttl=225; + iphdr->ip_p=1; + iphdr->ip_sum=0; + iphdr->ip_tos=0; + iphdr->ip_src.s_addr=inet_addr("192.168.1.35"); + iphdr->ip_dst.s_addr=dest.sin_addr.s_addr; + iphdr->ip_sum=csum((unsigned short *)datagram,iphdr->ip_len >> 1); + +#if defined(OPENBSD) || defined(FREEBSD) ||defined(__APPLE__) || defined(__darwin__) + icmphdr->icmp_type=130; + icmphdr->icmp_code=0; + icmphdr->icmp_cksum=htons(0xc3b0); +#else + icmphdr->type=130; + icmphdr->code=0; + icmphdr->checksum=htons(0xc3b0); + icmphdr->un.echo.sequence=0; + icmphdr->un.echo.id=0; +#endif + int one=1; + int *val=&one; + if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one))<0) + printf("cannot set HDRINCL!\n"); + + + if(@FUNCTION_TOKEN@sendto(sockfd,datagram,35,0,(struct sockaddr *)&dest,sizeof(dest))<0) + { + perror("sendto"); + exit(1); + } + + return(0); +} + +static char *txtquery(const char *domain, unsigned int *ttl) +{ + unsigned char answer[PACKETSZ], *answend, *pt; + char *txt, host[128]; + int len, type, qtype; + unsigned int cttl, size, txtlen = 0; + + + *ttl = 0; + if(res_init() < 0) { + printf("^res_init failed\n"); + return NULL; + } + + printf("*Querying %s\n", domain); + + memset(answer, 0, PACKETSZ); + qtype = T_TXT; + if((len = @FUNCTION_TOKEN@res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0 || len > PACKETSZ) { + /* The DNS server in the SpeedTouch Alcatel 510 modem can't + * handle a TXT-query, but it can resolve an ANY-query to a + * TXT-record, so we try an ANY-query now. The thing we try + * to resolve normally only has a TXT-record anyway. + */ + memset(answer, 0, PACKETSZ); + qtype=T_ANY; + if((len = @FUNCTION_TOKEN@res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0) { + printf("^Can't query %s\n", domain); + return NULL; + } + } + + answend = answer + len; + pt = answer + sizeof(HEADER); + + if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) { + printf("^dn_expand failed\n"); + return NULL; + } + + pt += len; + if(pt > answend-4) { + printf("^Bad (too short) DNS reply\n"); + return NULL; + } + + GETSHORT(type, pt); + if(type != qtype) { + printf("^Broken DNS reply.\n"); + return NULL; + } + + pt += INT16SZ; /* class */ + size = 0; + do { /* recurse through CNAME rr's */ + pt += size; + if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) { + printf("^second dn_expand failed\n"); + return NULL; + } + printf("^Host: %s\n", host); + pt += len; + if(pt > answend-10) { + printf("^Bad (too short) DNS reply\n"); + return NULL; + } + GETSHORT(type, pt); + pt += INT16SZ; /* class */ + GETLONG(cttl, pt); + GETSHORT(size, pt); + if(pt + size < answer || pt + size > answend) { + printf("^DNS rr overflow\n"); + return NULL; + } + } while(type == T_CNAME); + + if(type != T_TXT) { + printf("^Not a TXT record\n"); + return NULL; + } + + if(!size || (txtlen = *pt) >= size || !txtlen) { + printf("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); + return NULL; + } + + if(!(txt = (char *) malloc(txtlen + 1))) + return NULL; + + memcpy(txt, pt+1, txtlen); + txt[txtlen] = 0; + *ttl = cttl; + + return txt; +} + +static int res_tests(char *ip, char *test) { + unsigned char dnsreply[1024]; + unsigned char host[128]; + int ret = 0, i; + char buf[16]; + struct sockaddr_in addr; + + memset( dnsreply, '\0', sizeof( dnsreply )); + + printf("\n---------------------- %s res_init() TEST----------------------\n\n", test); + if (res_init() == -1) { + printf("res_init failed\n"); + return -1; + } + + + addr.sin_family=AF_INET; + addr.sin_port=htons(53); + addr.sin_addr.s_addr=inet_addr(ip); + + for (i = 0; i < _res.nscount; i++) + memcpy(&_res.nsaddr_list[i], &addr, sizeof(struct sockaddr_in)); + + inet_ntop(AF_INET, &_res.nsaddr_list[0].sin_addr.s_addr, buf, sizeof(buf)); + printf("nameserver for test: %s\n", buf); + + /* Modifying _res directly doesn't work, so we have to use res_n* where available. + See: http://sourceware.org/ml/libc-help/2009-11/msg00013.html */ + printf("\n---------------------- %s res_query() TEST----------------------\n\n", test); + snprintf((char *)host, 127, "www.google.com"); +#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) + ret = res_nquery(&_res, (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#else + ret = @FUNCTION_TOKEN@res_query((char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#endif + printf("return code: %i\n", ret); + + printf("\n---------------------- %s res_search() TEST----------------------\n\n", test); + memset( dnsreply, '\0', sizeof( dnsreply )); +#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) + ret = res_nsearch(&_res, (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#else + ret = @FUNCTION_TOKEN@res_search((char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#endif + printf("return code: %i\n", ret); + + printf("\n--------------- %s res_querydomain() TEST----------------------\n\n", test); + memset( dnsreply, '\0', sizeof( dnsreply )); +#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) + ret = res_nquerydomain(&_res, "www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#else + ret = @FUNCTION_TOKEN@res_querydomain("www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply )); +#endif + printf("return code: %i\n", ret); + + printf("\n---------------------- %s res_send() TEST----------------------\n\n", test); + memset( dnsreply, '\0', sizeof( dnsreply )); +#if !defined(OPENBSD) && !defined(__APPLE__) && !defined(__darwin__) + ret = res_nsend(&_res, host, 32, dnsreply, sizeof( dnsreply )); +#else + ret = @FUNCTION_TOKEN@res_send(host, 32, dnsreply, sizeof( dnsreply )); +#endif +printf("return code: %i\n", ret); + + return ret; +} + +static int res_internet_tests() { + char *ip = "8.8.8.8"; + char *test = "internet"; + return res_tests(ip, test); +} + +static int res_local_tests() { + char *ip = "192.168.1.1"; + char *test = "local"; + return res_tests(ip, test); +} + +static int udp_test() { + struct sockaddr_in addr; + char testtext[]="This message should be sent via udp\nThis is row number 2\nAnd then number three\n"; + int sock,ret,wb,flags=0; + char *ip = "6.6.6.6"; + + printf("\n----------------------UDP TEST----------------------\n\n"); + + addr.sin_family=AF_INET; + addr.sin_port=53; + addr.sin_addr.s_addr=inet_addr(ip); + + sock=socket(AF_INET,SOCK_DGRAM,0); + + struct iovec iov; + struct msghdr msg; + + iov.iov_base = (void *)testtext; + iov.iov_len = strlen(testtext); + + msg.msg_name = (struct sockaddr *)&addr; + msg.msg_namelen = sizeof(addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + + printf("\n----------------------udp sendmsg() TEST-------------------\n\n"); + wb=0; + ret=@FUNCTION_TOKEN@sendmsg(sock, &msg, flags); + printf("sendmsg() returned ret=%d wb=%d\n",ret,wb); + + printf("\n----------------------udp sendto() TEST--------------------\n\n"); + wb=0; + ret=@FUNCTION_TOKEN@sendto(sock,testtext,strlen(testtext)+1,wb, (struct sockaddr*)&addr, sizeof(addr)); + ret=@FUNCTION_TOKEN@sendto(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb, (struct sockaddr*)&addr, sizeof(addr)); + printf("sendto() returned ret=%d wb=%d\n",ret,wb); + + printf("\n----------------------udp connect() TEST-------------------\n\n"); + ret=@FUNCTION_TOKEN@connect(sock,(struct sockaddr*)&addr,sizeof(addr)); + printf("Connect returned ret=%d\n",ret); + + printf("\n----------------------udp send() TEST----------------------\n\n"); + wb=0; + ret=send(sock,testtext,strlen(testtext)+1,wb); + ret=send(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb); + printf("Note: no interception by torsocks expected as send() requires a socket in a connected state.\n"); + printf("send() returned ret=%d wb=%d\n",ret,wb); + + return 0; +} + +static int gethostbyname_test() { + struct hostent *foo; + + printf("\n----------------------gethostbyname() TEST-----------------\n\n"); + + foo=@FUNCTION_TOKEN@gethostbyname("www.torproject.org"); + if (foo) { + int i; + for (i=0; foo->h_addr_list[i]; ++i) + printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i])); +/* for (i=0; foo->h_aliases[i]; ++i) + printf(" also known as %s\n",foo->h_aliases[i]);*/ + } + return 0; +} + +static int gethostbyaddr_test() { + struct in_addr bar; + struct hostent *foo; + + printf("\n----------------------gethostbyaddr() TEST-----------------\n\n"); + + inet_aton("38.229.70.16", &bar); + foo=@FUNCTION_TOKEN@gethostbyaddr(&bar,4,AF_INET); + if (foo) { + int i; + for (i=0; foo->h_addr_list[i]; ++i) + printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i])); + for (i=0; foo->h_aliases[i]; ++i) + printf(" also known as %s\n",foo->h_aliases[i]); + } + return 0; +} + +static int getaddrinfo_test() { + struct addrinfo hints; + struct addrinfo *result; + int s; + + printf("\n----------------------getaddrinfo() TEST-----------------\n\n"); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + s = @FUNCTION_TOKEN@getaddrinfo(NULL, "www.torproject.org", &hints, &result); + if (s != 0) { + printf("getaddrinfo: %s\n", gai_strerror(s)); + } + + return 0; +} + +/* Unavailable in glibc. */ +/* +static int getipnodebyname_test() { + int error; + + printf("\n----------------------getipnodebyname() TEST-----------------\n\n"); + + getipnodebyname("www.torproject.org", AF_INET, 0, &error); + if (error != 0) { + printf("getipnodebyname error: %i\n", error); + } + + return 0; +} +*/ + +static int connect_test(const char *name, const char *ip, int port) +{ + int sock; + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ip); + addr.sin_port = htons(port); + + printf("\n---------------------- %s connect() TEST----------------------\n\n", name); + + if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + return 1; + + if (@FUNCTION_TOKEN@connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) + return 1; + + return 0; +} + +static int connect_local_test() +{ + const char *ip = "192.168.1.1"; + const char *name = "local"; + int port = 80; + return connect_test(name, ip, port); +} + +static int connect_internet_test() +{ + const char *ip = "8.8.8.8"; + int port = 53; + const char *name = "internet"; + return connect_test(name, ip, port); +} + +int main() { + + getaddrinfo_test(); + udp_test(); + gethostbyaddr_test(); + gethostbyname_test(); + connect_local_test(); + connect_internet_test(); + res_internet_tests(); + res_local_tests(); + icmp_test(); + + return 0; +} -- cgit v1.2.1