[tor-commits] [torsocks/osx] Major refactor of symbol hooking

hoganrobert at torproject.org hoganrobert at torproject.org
Sun Oct 23 18:27:12 UTC 2011


commit fe7bc53fbc81f012343f38271582fea76cafe4f0
Author: Robert Hogan <robert at roberthogan.net>
Date:   Sat Sep 18 12:11:29 2010 +0100

    Major refactor of symbol hooking
    
    Patch by alex at ohmantics.net
    
    Make torsocks fully compatible with Snow Leopard OSX.
    Slim down the symbol hooking code considerably.
    
    Alex's notes:
    
    "http://developer.apple.com/mac/library/releasenotes/Darwin/SymbolVariantsRelNotes/index.html explains the one of the problems that people have run into. 64-bit applications
    don't have the $UNIX2003 variants. For working 10.6 support, we'll need to
    conditionalize the UNIX2003 variants off when compiling for 64-bit."
---
 configure.in       |   42 +++++-
 src/Makefile.am    |    2 +-
 src/darwin_warts.c |   47 ++++++
 src/patch_table.h  |  114 ++++++++++++++
 src/tsocks.c       |  443 ++++++++++++++--------------------------------------
 5 files changed, 313 insertions(+), 335 deletions(-)

diff --git a/configure.in b/configure.in
index 04703e4..06461ff 100644
--- a/configure.in
+++ b/configure.in
@@ -292,6 +292,7 @@ fi
 dnl Find the correct select prototype on this machine 
 AC_MSG_CHECKING(for correct select prototype)
 PROTO=
+NAMES='n, readfds, writefds, exceptfds, timeout'
 for testproto in 'int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout' 
 do
   if test "${PROTO}" = ""; then
@@ -308,11 +309,13 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([select(${PROTO})])
 AC_DEFINE_UNQUOTED([SELECT_SIGNATURE],[${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([SELECT_ARGNAMES],[${NAMES}],[Argument names])
 
 dnl Find the correct connect prototype on this machine 
 AC_MSG_CHECKING(for correct connect prototype)
 PROTO=
-PROTO1='int __fd, const struct sockaddr * __addr, int len'
+NAMES='__fd, __addr, __len'
+PROTO1='int __fd, const struct sockaddr * __addr, int __len'
 PROTO2='int __fd, const struct sockaddr_in * __addr, socklen_t __len'
 PROTO3='int __fd, struct sockaddr * __addr, int __len'
 PROTO4='int __fd, const struct sockaddr * __addr, socklen_t __len'
@@ -334,6 +337,7 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([connect(${PROTO})])
 AC_DEFINE_UNQUOTED([CONNECT_SIGNATURE],[${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([CONNECT_ARGNAMES],[${NAMES}],[Argument names])
 
 dnl Pick which of the sockaddr type arguments we need for
 dnl connect(), we need to cast one of ours to it later 
@@ -348,6 +352,7 @@ AC_DEFINE_UNQUOTED([CONNECT_SOCKARG],[${SOCKETARG}],[Description])
 dnl Find the correct close prototype on this machine 
 AC_MSG_CHECKING(for correct close prototype)
 PROTO=
+NAMES='fd'
 PROTO1='int fd'
 for testproto in "${PROTO1}" 
 do
@@ -363,11 +368,13 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([close(${PROTO})])
 AC_DEFINE_UNQUOTED([CLOSE_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([CLOSE_ARGNAMES],[${NAMES}],[Argument names])
 
 
 dnl Find the correct res_querydomain prototype on this machine
 AC_MSG_CHECKING(for correct res_querydomain prototype)
 PROTO=
+NAMES='name, domain, class, type, answer, anslen'
 PROTO1='const char *name, const char *domain, int class, int type, unsigned char *answer, int anslen'
 for testproto in "${PROTO1}"
 do
@@ -385,10 +392,12 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([res_querydomain(${PROTO})])
 AC_DEFINE_UNQUOTED([RES_QUERYDOMAIN_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([RES_QUERYDOMAIN_ARGNAMES],[${NAMES}],[Argument names])
 
 dnl Find the correct res_send prototype on this machine
 AC_MSG_CHECKING(for correct res_send prototype)
 PROTO=
+NAMES='msg, msglen, answer, anslen'
 PROTO1='const char *msg, int msglen, char *answer, int anslen'
 PROTO2='const unsigned char *msg, int msglen, unsigned char *answer, int anslen'
 for testproto in "${PROTO1}" \
@@ -408,13 +417,15 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([res_send(${PROTO})])
 AC_DEFINE_UNQUOTED([RES_SEND_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([RES_SEND_ARGNAMES],[${NAMES}],[Argument names])
 
 
 dnl Find the correct res_search prototype on this machine
 AC_MSG_CHECKING(for correct res_search prototype)
 PROTO=
-PROTO1='const char *dname, int class, int type,unsigned char *answer, int anslen'
-for testproto in "${PROTO1}" 
+NAMES='dname, class, type, answer, anslen'
+PROTO1='const char *dname, int class, int type, unsigned char *answer, int anslen'
+for testproto in "${PROTO1}"
 do
   if test "${PROTO}" = ""; then
     AC_TRY_COMPILE([
@@ -430,13 +441,15 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([res_search(${PROTO})])
 AC_DEFINE_UNQUOTED([RES_SEARCH_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([RES_SEARCH_ARGNAMES],[${NAMES}],[Argument names])
 
 
 dnl Find the correct res_query prototype on this machine
 AC_MSG_CHECKING(for correct res_query prototype)
 PROTO=
-PROTO1='const char *dname, int class, int type,unsigned char *answer, int anslen'
-for testproto in "${PROTO1}" 
+NAMES='dname, class, type, answer, anslen'
+PROTO1='const char *dname, int class, int type, unsigned char *answer, int anslen'
+for testproto in "${PROTO1}"
 do
   if test "${PROTO}" = ""; then
     AC_TRY_COMPILE([
@@ -452,10 +465,12 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([res_query(${PROTO})])
 AC_DEFINE_UNQUOTED([RES_QUERY_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([RES_QUERY_ARGNAMES],[${NAMES}],[Argument names])
 
 dnl Find the correct getpeername prototype on this machine
 AC_MSG_CHECKING(for correct getpeername prototype)
 PROTO=
+NAMES='__fd, __name, __namelen'
 PROTO1='int __fd, const struct sockaddr * __name, int *__namelen'
 PROTO2='int __fd, const struct sockaddr_in * __name, socklen_t *__namelen'
 PROTO3='int __fd, struct sockaddr * __name, socklen_t *__namelen'
@@ -478,14 +493,16 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([getpeername(${PROTO})])
 AC_DEFINE_UNQUOTED(GETPEERNAME_SIGNATURE, [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([GETPEERNAME_ARGNAMES],[${NAMES}],[Argument names])
 
 
 dnl Find the correct poll prototype on this machine 
 AC_MSG_CHECKING(for correct poll prototype)
 PROTO=
+NAMES='ufds, nfds, timeout'
 for testproto in 'struct pollfd *ufds, unsigned long nfds, int timeout' \
                  'struct pollfd *ufds, nfds_t nfds, int timeout' \
-                 'struct pollfd *pfd, unsigned int nfds, int timeout'
+                 'struct pollfd *ufds, unsigned int nfds, int timeout'
 do
   if test "${PROTO}" = ""; then
     AC_TRY_COMPILE([
@@ -499,30 +516,43 @@ if test "${PROTO}" = ""; then
 fi
 AC_MSG_RESULT([poll(${PROTO})])
 AC_DEFINE_UNQUOTED([POLL_SIGNATURE], [${PROTO}],[Description])
+AC_DEFINE_UNQUOTED([POLL_ARGNAMES],[${NAMES}],[Argument names])
 
 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])
 
 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])
 
 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])
 
 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])
 
 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])
 
 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])
 
 dnl Output the special librarys (libdl etc needed for tsocks)
 SPECIALLIBS=${LIBS}
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e7bb96..d5d1239 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,7 +37,7 @@ torsocksconfmanpage_DATA = torsocks.conf.5
 
 # Install main library to $(prefix)/lib/tor (must match torsocks.in)
 lib_LTLIBRARIES = libtorsocks.la
-libtorsocks_la_SOURCES = tsocks.c common.c parser.c dead_pool.c
+libtorsocks_la_SOURCES = tsocks.c common.c parser.c dead_pool.c darwin_warts.c
 libtorsocks_la_LDFLAGS = -version-info 1:0:0
 #libtorsocks_la_CFLAGS = -nostartfiles
 
diff --git a/src/darwin_warts.c b/src/darwin_warts.c
new file mode 100644
index 0000000..c35ed8b
--- /dev/null
+++ b/src/darwin_warts.c
@@ -0,0 +1,47 @@
+/* Mac OS X 10.6 forces any function named "select" to be named "_select$1050"
+ * in the output to the assembler. We need to patch select as well, so this
+ * isolated code exists without tripping over the Darwin header that causes the
+ * probkem.
+ */
+
+#if defined(__APPLE__) || defined(__darwin__)
+
+#include <AvailabilityMacros.h>
+
+#if defined(MAC_OS_X_VERSION_10_6)
+
+#include <stddef.h>
+#include <stdint.h>
+#include <dlfcn.h>
+#include "common.h"
+
+#define LOAD_ERROR(s,l) { \
+    char *error; \
+    error = dlerror(); \
+    show_msg(l, "The symbol %s() was not found in any shared " \
+                     "library. The error reported was: %s!\n", s, \
+                     (error)?error:"not found"); \
+    dlerror(); \
+    }
+
+#define SELECT_SIGNATURE int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout
+#define SELECT_ARGNAMES n, readfds, writefds, exceptfds, timeout
+
+/* forward declare opaque structures instead of bringing in real Darwin decls. */
+typedef struct fd_set fd_set;
+struct timeval;
+
+int (*realselect)(SELECT_SIGNATURE);
+int tsocks_select_guts(SELECT_SIGNATURE, int (*original_select)(SELECT_SIGNATURE));
+
+int select(SELECT_SIGNATURE) {
+  if (!realselect) {
+	dlerror();
+	if ((realselect = dlsym(RTLD_NEXT, "select")) == NULL)
+	  LOAD_ERROR("select", MSGERR);
+  }
+  return tsocks_select_guts(SELECT_ARGNAMES, realselect);
+}
+
+#endif /* 10.6 */
+#endif /* darwin */
diff --git a/src/patch_table.h b/src/patch_table.h
new file mode 100644
index 0000000..9ebde08
--- /dev/null
+++ b/src/patch_table.h
@@ -0,0 +1,114 @@
+#undef FUNC
+#undef FUNCD
+#undef FUND32
+#undef FUNCD64
+
+#ifdef SUPPORT_RES_API
+	#define RES_FUNC	FUNC
+	#define RES_FUNCD	FUNCD
+	#define RES_FUNCD32	FUNCD32
+	#define RES_FUNCD64	FUNCD64
+#else
+	#define RES_FUNC	EMPTY_FUNC
+	#define RES_FUNCD	EMPTY_FUNC
+	#define RES_FUNCD32	EMPTY_FUNC
+	#define RES_FUNCD64	EMPTY_FUNC
+#endif
+
+#ifdef USE_TOR_DNS
+	#define DNS_FUNC	FUNC
+	#define DNS_FUNCD	FUNCD
+	#define DNS_FUNCD32	FUNCD32
+	#define DNS_FUNCD64	FUNCD64
+#else
+	#define DNS_FUNC	EMPTY_FUNC
+	#define DNS_FUNCD	EMPTY_FUNC
+	#define DNS_FUNCD32	EMPTY_FUNC
+	#define DNS_FUNCD64	EMPTY_FUNC
+#endif
+
+#define EMPTY_FUNC(e,r,s,n,b,m)
+
+#if defined(__APPLE__) || defined(__darwin__)
+	#ifndef DARWIN_EXPANSION
+		#define DARWIN_EXPANSION	   			PATCH_TABLE_EXPANSION
+	#endif                             			
+                                       			
+	#define FUNCD(e,r,s,n,b,m)		   			DARWIN_EXPANSION(e,r,s,n,b,m)
+    #if (__LP64__)                     			
+        #define FUNCD32(e,r,s,n,b,m)   			EMPTY_FUNC(e,r,s,n,b,m)
+		#define	FUNCD64(e,r,s,n,b,m)   			DARWIN_EXPANSION(e,r,s,n,b,m)
+		
+		/* This tests if we're building with 10.6 or later headers, not
+		   if we're running on 10.6. We'd rather do the latter. */
+		#ifdef MAC_OS_X_VERSION_10_6
+			#define	FUNCD64_106(e,r,s,n,b,m)	DARWIN_EXPANSION(e,r,s,n,b,m)
+		#else
+			#define	FUNCD64_106(e,r,s,n,b,m)	EMPTY_FUNC(e,r,s,n,b,m)
+		#endif
+    #else
+        #define FUNCD32(e,r,s,n,b,m)   			DARWIN_EXPANSION(e,r,s,n,b,m)
+		#define	FUNCD64(e,r,s,n,b,m)   			EMPTY_FUNC(e,r,s,n,b,m)
+		#define	FUNCD64_106(e,r,s,n,b,m)   		EMPTY_FUNC(e,r,s,n,b,m)
+    #endif                             		
+#else                                  		
+    #define FUNCD(e,r,s,n,b,m)		   			EMPTY_FUNC(e,r,s,n,b,m)
+    #define FUNCD32(e,r,s,n,b,m)	   			EMPTY_FUNC(e,r,s,n,b,m)
+    #define FUNCD64(e,r,s,n,b,m)	   			EMPTY_FUNC(e,r,s,n,b,m)
+    #define FUNCD64_106(e,r,s,n,b,m)	   		EMPTY_FUNC(e,r,s,n,b,m)
+#endif                                 			
+#define FUNC(e,r,s,n,b,m)			   			PATCH_TABLE_EXPANSION(e,r,s,n,b,m)
+
+/*			dlsym	return type			SIG/ARGS			C name							base name			asm name	*/
+/*RES_FUNC	(ERR,	int,				RES_INIT_,			res_init,						res_init,			"res_init") */
+/* res_init takes void, so we do that one manually. */
+RES_FUNC	(ERR,	int,				RES_QUERY_,			res_query,						res_query,			"res_query")
+RES_FUNC	(ERR,	int,				RES_SEARCH_,		res_search,						res_search,			"res_search")
+RES_FUNC	(ERR,	int,				RES_SEND_,			res_send,						res_send,			"res_send")
+RES_FUNC	(ERR,	int,				RES_QUERYDOMAIN_,	res_querydomain,				res_querydomain,	"res_querydomain")
+                                                                                                            	
+DNS_FUNC	(ERR,	struct hostent *,	GETHOSTBYNAME_,		gethostbyname,					gethostbyname,		"gethostbyname")
+DNS_FUNC	(ERR,	struct hostent *,	GETHOSTBYADDR_,		gethostbyaddr,					gethostbyaddr,		"gethostbyaddr")
+DNS_FUNC	(ERR,	int,				GETADDRINFO_,		getaddrinfo,					getaddrinfo,		"getaddrinfo")
+/* getipnodebyname is deprecated so do not report an error if it is not                                     	
+   available.*/                                                                                             	
+DNS_FUNC	(WARN,	struct hostent *,	GETIPNODEBYNAME_,	getipnodebyname,				getipnodebyname,	"getipnodebyname")
+                                                                                                            	
+DNS_FUNC	(ERR,	ssize_t,			SENDTO_,			sendto,							sendto,				"sendto")
+DNS_FUNCD32 (ERR,	ssize_t,			SENDTO_,			sendto_unix2003,                sendto,         	"sendto$UNIX2003")
+DNS_FUNCD32 (ERR,	ssize_t,			SENDTO_,			sendto_nocancel_unix2003,       sendto,         	"sendto$NOCANCEL$UNIX2003")
+DNS_FUNCD64 (ERR,	ssize_t,			SENDTO_,			sendto_nocancel,                sendto,         	"sendto$NOCANCEL")
+                     			            		                                                        	
+DNS_FUNC    (ERR,	ssize_t,			SENDMSG_,			sendmsg,                        sendmsg,        	"sendmsg")
+DNS_FUNCD32 (ERR,	ssize_t,			SENDMSG_,			sendmsg_unix2003,               sendmsg,        	"sendmsg$UNIX2003")
+DNS_FUNCD32 (ERR,	ssize_t,			SENDMSG_,			sendmsg_nocancel_unix2003,      sendmsg,        	"sendmsg$NOCANCEL$UNIX2003")
+DNS_FUNCD64 (ERR,	ssize_t,			SENDMSG_,			sendmsg_nocancel,               sendmsg,        	"sendmsg$NOCANCEL")
+                     			            		                                                        	
+FUNC   		(ERR,	int,    			CONNECT_,			connect,                        connect,        	"connect")
+FUNCD32		(ERR,	int,    			CONNECT_,			connect_unix2003,               connect,        	"connect$UNIX2003")
+FUNCD32		(ERR,	int,    			CONNECT_,			connect_nocancel_unix2003,      connect,        	"connect$NOCANCEL$UNIX2003")
+FUNCD64		(ERR,	int,    			CONNECT_,			connect_nocancel,               connect,        	"connect$NOCANCEL")
+                     			            		                                                        	
+#if !(defined(__APPLE__) || defined(__darwin__) && defined(MAX_OS_X_VERSION_10_6))
+/* see darwin_warts.c */
+FUNC   		(ERR,	int,    			SELECT_,			select,                         select,         	"select")
+#endif
+FUNCD  		(ERR,	int,    			SELECT_,			select_darwinextsn,             select,         	"select$DARWIN_EXTSN")
+FUNCD  		(ERR,	int,    			SELECT_,			select_darwinextsn_nocancel,    select,         	"select$DARWIN_EXTSN$NOCANCEL")
+FUNCD32		(ERR,	int,    			SELECT_,			select_unix2003,                select,         	"select$UNIX2003")
+FUNCD32		(ERR,	int,    			SELECT_,			select_nocancel_unix2003,		select,         	"select$NOCANCEL$UNIX2003")
+FUNCD64		(ERR,	int,    			SELECT_,			select_nocancel,                select,         	"select$NOCANCEL")
+FUNCD64_106	(ERR,	int,    			SELECT_,			select_1050,                	select,         	"select$1050")
+                     			            		                                                        	
+FUNC   		(ERR,	int,    			POLL_,				poll,                           poll,           	"poll")
+FUNCD32		(ERR,	int,    			POLL_,				poll_unix2003,                  poll,           	"poll$UNIX2003")
+FUNCD32		(ERR,	int,    			POLL_,				poll_nocancel_unix2003,         poll,           	"poll$NOCANCEL$UNIX2003")
+FUNCD64		(ERR,	int,    			POLL_,				poll_nocancel,                  poll,           	"poll$NOCANCEL")
+       		         			            		                                                        	
+FUNC   		(ERR,	int,    			CLOSE_,				close,                          close,          	"close")
+FUNCD32		(ERR,	int,    			CLOSE_,				close_unix2003,                 close,          	"close$UNIX2003")
+FUNCD32		(ERR,	int,    			CLOSE_,				close_nocancel_unix2003,        close,          	"close$NOCANCEL$UNIX2003")
+FUNCD64		(ERR,	int,    			CLOSE_,				close_nocancel,                 close,          	"close$NOCANCEL")
+       		         			            		                                                        	
+FUNC   		(ERR,	int,    			GETPEERNAME_,		getpeername,                    getpeername,    	"getpeername")
+FUNCD32		(ERR,	int,    			GETPEERNAME_,		getpeername_unix2003,           getpeername,    	"getpeername$UNIX2003")
diff --git a/src/tsocks.c b/src/tsocks.c
index 92bca5b..2545e42 100644
--- a/src/tsocks.c
+++ b/src/tsocks.c
@@ -90,6 +90,7 @@ const char *progname = "libtorsocks";         /* Name used in err msgs    */
 #include <errno.h>
 #include <fcntl.h>
 #include <common.h>
+#include <pthread.h>
 #include <stdarg.h>
 #if !defined(__APPLE__) && !defined(__darwin__)
 #include <sys/socket.h>
@@ -101,105 +102,51 @@ const char *progname = "libtorsocks";         /* Name used in err msgs    */
 #include <tsocks.h>
 #include "dead_pool.h"
 
+/* Some function names are macroized on Darwin. Allow those names
+   to expand accordingly. */
+#define EXPAND_GUTS(x) tsocks_##x##_guts
+#define EXPAND_GUTS_NAME(x) EXPAND_GUTS(x)
+
 /* Global Declarations */
-#ifdef SUPPORT_RES_API
-static int (*realresinit)(void);
-static int (*realresquery)(RES_QUERY_SIGNATURE);
-static int (*realressearch)(RES_SEARCH_SIGNATURE);
-static int (*realressend)(RES_SEND_SIGNATURE);
-static int (*realresquerydomain)(RES_QUERYDOMAIN_SIGNATURE);
-#endif /*SUPPORT_RES_API*/
 #ifdef USE_TOR_DNS
 static dead_pool *pool = NULL;
-static struct hostent *(*realgethostbyname)(GETHOSTBYNAME_SIGNATURE);
-static struct hostent *(*realgethostbyaddr)(GETHOSTBYADDR_SIGNATURE);
-int (*realgetaddrinfo)(GETADDRINFO_SIGNATURE);
-static struct hostent *(*realgetipnodebyname)(GETIPNODEBYNAME_SIGNATURE);
-static ssize_t (*realsendto)(SENDTO_SIGNATURE);
-static ssize_t (*realsendmsg)(SENDMSG_SIGNATURE);
-#if defined(__APPLE__) || defined(__darwin__)
-static ssize_t (*realsendto_unix2003)(SENDTO_SIGNATURE);
-static ssize_t (*realsendto_nocancel)(SENDTO_SIGNATURE);
-static ssize_t (*realsendmsg_unix2003)(SENDMSG_SIGNATURE);
-static ssize_t (*realsendmsg_nocancel)(SENDMSG_SIGNATURE);
-#endif
 #endif /*USE_TOR_DNS*/
-int (*realconnect)(CONNECT_SIGNATURE);
-static int (*realselect)(SELECT_SIGNATURE);
-static int (*realpoll)(POLL_SIGNATURE);
-int (*realclose)(CLOSE_SIGNATURE);
-static int (*realgetpeername)(GETPEERNAME_SIGNATURE);
-#if defined(__APPLE__) || defined(__darwin__)
-static int (*realconnect_unix2003)(CONNECT_SIGNATURE);
-static int (*realconnect_nocancel)(CONNECT_SIGNATURE);
-static int (*realselect_darwinextsn)(SELECT_SIGNATURE);
-static int (*realselect_darwinextsn_nocancel)(SELECT_SIGNATURE);
-static int (*realselect_unix2003)(SELECT_SIGNATURE);
-static int (*realselect_nocancel)(SELECT_SIGNATURE);
-static int (*realpoll_unix2003)(POLL_SIGNATURE);
-static int (*realpoll_nocancel)(POLL_SIGNATURE);
-static int (*realclose_unix2003)(CLOSE_SIGNATURE);
-static int (*realclose_nocancel)(CLOSE_SIGNATURE);
-static int (*realgetpeername_unix2003)(GETPEERNAME_SIGNATURE);
+
+/* Function prototypes for original functions that we patch */
+#ifdef SUPPORT_RES_API
+int (*realres_init)(void);
 #endif
+#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r (*real##n)(s##SIGNATURE);
+#include "patch_table.h"
+#undef PATCH_TABLE_EXPANSION
+#undef DARWIN_EXPANSION
 
-static struct parsedfile *config;
+static struct parsedfile config;
 static struct connreq *requests = NULL;
 static int suid = 0;
 static char *conffile = NULL;
-static int tsocks_init_complete = 0;
+static volatile int tsocks_init_complete = 0;
 
 /* Exported Function Prototypes */
 void __attribute__ ((constructor)) tsocks_init(void);
-int connect(CONNECT_SIGNATURE);
-int select(SELECT_SIGNATURE);
-int poll(POLL_SIGNATURE);
-int close(CLOSE_SIGNATURE);
-int getpeername(GETPEERNAME_SIGNATURE);
-#if defined(__APPLE__) || defined(__darwin__)
-int connect_unix2003(CONNECT_SIGNATURE) __asm("_connect$UNIX2003");
-int connect_nocancel(CONNECT_SIGNATURE) __asm("_connect$NOCANCEL$UNIX2003");
-int select_darwinextsn(SELECT_SIGNATURE) __asm("_select$DARWIN_EXTSN");
-int select_darwinextsn_nocancel(SELECT_SIGNATURE) __asm("_select$DARWIN_EXTSN$NOCANCEL");
-int select_unix2003(SELECT_SIGNATURE) __asm("_select$UNIX2003");
-int select_nocancel(SELECT_SIGNATURE) __asm("_select$NOCANCEL$UNIX2003");
-int poll_unix2003(POLL_SIGNATURE) __asm("_poll$UNIX2003");
-int poll_nocancel(POLL_SIGNATURE) __asm("_poll$NOCANCEL$UNIX2003");
-int close_unix2003(CLOSE_SIGNATURE) __asm("_close$UNIX2003");
-int close_nocancel(CLOSE_SIGNATURE) __asm("_close$NOCANCEL$UNIX2003");
-int getpeername_unxi2003(GETPEERNAME_SIGNATURE) __asm("_getpeername$UNIX2003");
-#endif
 
+/* Function prototypes for our patches */
 #ifdef SUPPORT_RES_API
 int res_init(void);
-int res_query(RES_QUERY_SIGNATURE);
-int res_search(RES_SEARCH_SIGNATURE);
-int res_querydomain(RES_QUERYDOMAIN_SIGNATURE);
-int res_send(RES_SEND_SIGNATURE);
-#endif
-#ifdef USE_TOR_DNS
-struct hostent *gethostbyname(GETHOSTBYNAME_SIGNATURE);
-struct hostent *gethostbyaddr(GETHOSTBYADDR_SIGNATURE);
-int getaddrinfo(GETADDRINFO_SIGNATURE);
-struct hostent *getipnodebyname(GETIPNODEBYNAME_SIGNATURE);
-ssize_t sendto(SENDTO_SIGNATURE);
-ssize_t sendmsg(SENDMSG_SIGNATURE);
-#if defined(__APPLE__) || defined(__darwin__)
-ssize_t sendto_unix2003(SENDTO_SIGNATURE) __asm("_sendto$UNIX2003");
-ssize_t sendto_nocancel(SENDTO_SIGNATURE) __asm("_sendto$NOCANCEL$UNIX2003");
-ssize_t sendmsg_unix2003(SENDMSG_SIGNATURE) __asm("_sendmsg$UNIX2003");
-ssize_t sendmsg_nocancel(SENDMSG_SIGNATURE) __asm("_sendmsg$NOCANCEL$UNIX2003");
-#endif
 #endif /*USE_TOR_DNS*/
 
+#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r n(s##SIGNATURE);
+#define DARWIN_EXPANSION(e,r,s,n,b,m)      r n(s##SIGNATURE) __asm("_" m);
+#include "patch_table.h"
+#undef PATCH_TABLE_EXPANSION
+#undef DARWIN_EXPANSION
+
 /* Private Function Prototypes */
-static int tsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNATURE));
-static int tsocks_select_guts(SELECT_SIGNATURE, int (*original_select)(SELECT_SIGNATURE));
-static int tsocks_poll_guts(POLL_SIGNATURE, int (*original_poll)(POLL_SIGNATURE));
-static int tsocks_close_guts(CLOSE_SIGNATURE, int (*original_close)(CLOSE_SIGNATURE));
-static int tsocks_getpeername_guts(GETPEERNAME_SIGNATURE, int (*original_getpeername)(GETPEERNAME_SIGNATURE));
-static ssize_t tsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO_SIGNATURE));
-static ssize_t tsocks_sendmsg_guts(SENDMSG_SIGNATURE, ssize_t (*original_sendmsg)(SENDMSG_SIGNATURE));
+/* no tsocks_res_init_guts */
+#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) r tsocks_##b##_guts(s##SIGNATURE, r (*original_##b)(s##SIGNATURE));
+#include "patch_table.h"
+#undef PATCH_TABLE_EXPANSION
+
 
 static int get_config();
 static int get_environment();
@@ -227,6 +174,8 @@ static int deadpool_init(void);
 static int send_socksv4a_request(struct connreq *conn, const char *onion_host);
 #endif
 
+static pthread_mutex_t tsocks_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 void tsocks_init(void) {
 
 #define LOAD_ERROR(s,l) { \
@@ -238,6 +187,8 @@ void tsocks_init(void) {
     dlerror(); \
     }
 
+    pthread_mutex_lock(&tsocks_init_mutex);
+
     /* We only need to be called once */
     if (tsocks_init_complete) {
       return;
@@ -249,10 +200,10 @@ void tsocks_init(void) {
 
     show_msg(MSGWARN, "In tsocks_init \n");
 
-//     get_environment();
-//     get_config();
-// 
-//     show_msg(MSGWARN, "In tsocks_init after env/config\n");
+    get_environment();
+    get_config();
+
+    show_msg(MSGWARN, "In tsocks_init after env/config\n");
 
 #ifdef USE_OLD_DLSYM
     void *lib;
@@ -267,95 +218,13 @@ void tsocks_init(void) {
 
     dlerror();
 #ifndef USE_OLD_DLSYM
-    if ((realconnect = dlsym(RTLD_NEXT, "connect")) == NULL)
-      LOAD_ERROR("connect", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realconnect_unix2003 = dlsym(RTLD_NEXT, "connect$UNIX2003")) == NULL)
-      LOAD_ERROR("connect$UNIX2003", MSGERR);
-    if ((realconnect_nocancel = dlsym(RTLD_NEXT, "connect$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("connect$NOCANCEL$UNIX2003", MSGERR);
-#endif
-
-    if ((realselect = dlsym(RTLD_NEXT, "select")) == NULL)
-      LOAD_ERROR("select", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realselect_darwinextsn = dlsym(RTLD_NEXT, "select$DARWIN_EXTSN")) == NULL)
-      LOAD_ERROR("select$DARWIN_EXTSN", MSGERR);
-    if ((realselect_darwinextsn_nocancel = dlsym(RTLD_NEXT, "select$DARWIN_EXTSN$NOCANCEL")) == NULL)
-      LOAD_ERROR("select$DARWIN_EXTSN$NOCANCEL", MSGERR);
-    if ((realselect_unix2003 = dlsym(RTLD_NEXT, "select$UNIX2003")) == NULL)
-      LOAD_ERROR("select$UNIX2003", MSGERR);
-    if ((realselect_nocancel = dlsym(RTLD_NEXT, "select$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("select$NOCANCEL$UNIX2003", MSGERR);
-#endif
-
-    if ((realpoll = dlsym(RTLD_NEXT, "poll")) == NULL)
-      LOAD_ERROR("poll", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realpoll_unix2003 = dlsym(RTLD_NEXT, "poll$UNIX2003")) == NULL)
-      LOAD_ERROR("poll$UNIX2003", MSGERR);
-    if ((realpoll_nocancel = dlsym(RTLD_NEXT, "poll$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("poll$NOCANCEL$UNIX2003", MSGERR);
-#endif
-
-    if ((realclose = dlsym(RTLD_NEXT, "close")) == NULL)
-      LOAD_ERROR("close", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realclose_unix2003 = dlsym(RTLD_NEXT, "close$UNIX2003")) == NULL)
-      LOAD_ERROR("close$UNIX2003", MSGERR);
-    if ((realclose_nocancel = dlsym(RTLD_NEXT, "close$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("close$NOCANCEL$UNIX2003", MSGERR);
-#endif
-
-    if ((realgetpeername = dlsym(RTLD_NEXT, "getpeername")) == NULL)
-      LOAD_ERROR("getpeername", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realgetpeername_unix2003 = dlsym(RTLD_NEXT, "getpeername$UNIX2003")) == NULL)
-      LOAD_ERROR("getpeername$UNIX2003", MSGERR);
-#endif
-
-    #ifdef SUPPORT_RES_API
-    if ((realresinit = dlsym(RTLD_NEXT, "res_init")) == NULL)
-      LOAD_ERROR("res_init", MSGERR);
-    if ((realresquery = dlsym(RTLD_NEXT, "res_query")) == NULL)
-      LOAD_ERROR("res_query", MSGERR);
-    if ((realressearch = dlsym(RTLD_NEXT, "res_search")) == NULL)
-      LOAD_ERROR("res_search", MSGERR);
-    if ((realresquerydomain = dlsym(RTLD_NEXT, "res_querydomain")) == NULL)
-      LOAD_ERROR("res_querydomain", MSGERR);
-    if ((realressend = dlsym(RTLD_NEXT, "res_send")) == NULL)
-      LOAD_ERROR("res_send", MSGERR);
-    #endif
-    #ifdef USE_TOR_DNS
-    if ((realgethostbyname = dlsym(RTLD_NEXT, "gethostbyname")) == NULL)
-      LOAD_ERROR("gethostbyname", MSGERR);
-    if ((realgethostbyaddr = dlsym(RTLD_NEXT, "gethostbyaddr")) == NULL)
-      LOAD_ERROR("gethostbyaddr", MSGERR);
-    if ((realgetaddrinfo = dlsym(RTLD_NEXT, "getaddrinfo")) == NULL)
-      LOAD_ERROR("getaddrinfo", MSGERR);
-    /* getipnodebyname is deprecated so do not report an error if it is not
-       available.*/
-    if ((realgetipnodebyname = dlsym(RTLD_NEXT, "getipnodebyname")) == NULL)
-      LOAD_ERROR("getipnodebyname", MSGWARN);
-
-    if ((realsendto = dlsym(RTLD_NEXT, "sendto")) == NULL)
-      LOAD_ERROR("sendto", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realsendto_unix2003 = dlsym(RTLD_NEXT, "sendto$UNIX2003")) == NULL)
-      LOAD_ERROR("sendto$UNIX2003", MSGERR);
-    if ((realsendto_nocancel = dlsym(RTLD_NEXT, "sendto$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("sendto$NOCANCEL$UNIX2003", MSGERR);
-#endif
-
-    if ((realsendmsg = dlsym(RTLD_NEXT, "sendmsg")) == NULL)
-      LOAD_ERROR("sendmsg", MSGERR);
-#if defined(__APPLE__) || defined(__darwin__)
-    if ((realsendmsg_unix2003 = dlsym(RTLD_NEXT, "sendmsg$UNIX2003")) == NULL)
-      LOAD_ERROR("sendmsg$UNIX2003", MSGERR);
-    if ((realsendmsg_nocancel = dlsym(RTLD_NEXT, "sendmsg$NOCANCEL$UNIX2003")) == NULL)
-      LOAD_ERROR("sendmsg$NOCANCEL$UNIX2003", MSGERR);
-#endif
-    #endif /*USE_TOR_DNS*/
+   #ifdef SUPPORT_RES_API
+       if ((realres_init = dlsym(RTLD_NEXT, "res_init")) == NULL)
+         LOAD_ERROR("res_init", MSGERR);
+   #endif
+   #define PATCH_TABLE_EXPANSION(e,r,s,n,b,m)  if ((real##n = dlsym(RTLD_NEXT, m)) == NULL) LOAD_ERROR(m, MSG##e);
+   #include "patch_table.h"
+   #undef PATCH_TABLE_EXPANSION
 #else
     lib = dlopen(LIBCONNECT, RTLD_LAZY);
     realconnect = dlsym(lib, "connect");
@@ -375,7 +244,7 @@ void tsocks_init(void) {
     dlclose(lib);
     #ifdef SUPPORT_RES_API
     lib = dlopen(LIBRESOLV, RTLD_LAZY);
-    realresinit = dlsym(lib, "res_init");
+    realres_init = dlsym(lib, "res_init");
     realresquery = dlsym(lib, "res_query");
     realressend = dlsym(lib, "res_send");
     realresquerydomain = dlsym(lib, "res_querydomain");
@@ -388,7 +257,10 @@ void tsocks_init(void) {
        area won't be shared across fork()s. */
     deadpool_init();
 #endif
+    tsocks_init_complete=1;
+    pthread_mutex_unlock(&tsocks_init_mutex);
 
+    show_msg(MSGWARN, "Exit tsocks_init \n");
 }
 
 static int get_environment() {
@@ -431,123 +303,31 @@ static int get_config () {
   #endif
     
     /* Read in the config file */
-    config = malloc(sizeof(*config));
+/*    config = malloc(sizeof(*config));
     if (!config)
-        return(0);
-    read_config(conffile, config);
-    if (config->paths)
-        show_msg(MSGDEBUG, "First lineno for first path is %d\n", config->paths->lineno);
+        return(0);*/
+    read_config(conffile, &config);
+    if (config.paths)
+        show_msg(MSGDEBUG, "First lineno for first path is %d\n", config.paths->lineno);
 
     done = 1;
 
     return(0);
 }
 
-#define PATCH_CONNECT(funcname, symbolname) \
-  int funcname(CONNECT_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_connect_guts(__fd, __addr, __len, real ## funcname); \
-  }
-PATCH_CONNECT(connect, "connect")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_CONNECT(connect_unix2003, "conncect$UNIX2003")
-PATCH_CONNECT(connect_nocancel, "conncect$NOCANCEL$UNIX2003")
-#endif
-
-#define PATCH_CLOSE(funcname, symbolname) \
-  int funcname(CLOSE_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_close_guts(fd, real ## funcname); \
-  }
-PATCH_CLOSE(close, "close")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_CLOSE(close_unix2003, "close$UNIX2003")
-PATCH_CLOSE(close_nocancel, "close$NOCANCEL$UNIX2003")
-#endif
-
-#define PATCH_SELECT(funcname, symbolname) \
-  int funcname(SELECT_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_select_guts(n, readfds, writefds, exceptfds, timeout, real ## funcname); \
-  }
-PATCH_SELECT(select, "select")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_SELECT(select_darwinextsn, "select$DARWIN_EXTSN")
-PATCH_SELECT(select_darwinextsn_nocancel, "select$DARWIN_EXTSN$NOCANCEL")
-PATCH_SELECT(select_unix2003, "select$UNIX2003")
-PATCH_SELECT(select_nocancel, "select$NOCANCEL$UNIX2003")
-#endif
-
-#define PATCH_POLL(funcname, symbolname) \
-  int funcname(POLL_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_poll_guts(ufds, nfds, timeout, real ## funcname); \
-  }
-PATCH_POLL(poll, "poll")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_POLL(poll_unix2003, "poll$UNIX2003")
-PATCH_POLL(poll_nocancel, "poll$NOCANCEL$UNIX2003")
-#endif
-
-#define PATCH_GETPEERNAME(funcname, symbolname) \
-  int funcname(GETPEERNAME_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_getpeername_guts(__fd, __name, __namelen, real ## funcname); \
-  }
-PATCH_GETPEERNAME(getpeername, "getpeername")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_GETPEERNAME(getpeername_unix2003, "getpeername$UNIX2003")
-#endif
-
-#define PATCH_SENDTO(funcname, symbolname) \
-  ssize_t funcname(SENDTO_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_sendto_guts(s, buf, len, flags, to, tolen, real ## funcname); \
-  }
-PATCH_SENDTO(sendto, "sendto")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_SENDTO(sendto_unix2003, "sendto$UNIX2003")
-PATCH_SENDTO(sendto_nocancel, "sendto$NOCANCEL$UNIX2003")
-#endif
-
-#define PATCH_SENDMSG(funcname, symbolname) \
-  ssize_t funcname(SENDMSG_SIGNATURE) { \
-    if (!real ## funcname) { \
-      dlerror(); \
-      if ((real ## funcname = dlsym(RTLD_NEXT, symbolname)) == NULL) \
-        LOAD_ERROR(symbolname, MSGERR); \
-    } \
-    return tsocks_sendmsg_guts(s, msg, flags, real ## funcname); \
-  }
-PATCH_SENDMSG(sendmsg, "sendmsg")
-#if defined(__APPLE__) || defined(__darwin__)
-PATCH_SENDMSG(sendmsg_unix2003, "sendmsg$UNIX2003")
-PATCH_SENDMSG(sendmsg_nocancel, "sendmsg$NOCANCEL$UNIX2003")
-#endif
+/* Patch trampoline functions */
+/* no tsocks_res_init_guts */
+#define PATCH_TABLE_EXPANSION(e,r,s,n,b,m) \
+   r n(s##SIGNATURE) { \
+     if (!real##n) { \
+       dlerror(); \
+       if ((real##n = dlsym(RTLD_NEXT, m)) == NULL) \
+         LOAD_ERROR(m, MSG##e); \
+     } \
+     return tsocks_##b##_guts(s##ARGNAMES, real##n); \
+   }
+#include "patch_table.h"
+#undef PATCH_TABLE_EXPANSION
 
 int tsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNATURE)) {
     struct sockaddr_in *connaddr;
@@ -662,22 +442,22 @@ int tsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNA
 
     /* If the address is local call original_connect */
 #ifdef USE_TOR_DNS
-    if (!(is_local(config, &(connaddr->sin_addr))) && 
+    if (!(is_local(&config, &(connaddr->sin_addr))) && 
         !is_dead_address(pool, connaddr->sin_addr.s_addr)) {
 #else 
-    if (!(is_local(config, &(connaddr->sin_addr)))) {
+    if (!(is_local(&config, &(connaddr->sin_addr)))) {
 #endif
       show_msg(MSGDEBUG, "Connection for socket %d is local\n", __fd);
       return(original_connect(__fd, __addr, __len));
     }
 
    /* Ok, so its not local, we need a path to the net */
-   pick_server(config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port));
+   pick_server(&config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port));
 
    show_msg(MSGDEBUG, "Picked server %s for connection\n",
             (path->address ? path->address : "(Not Provided)"));
    if (path->address == NULL) {
-      if (path == &(config->defaultserver)) 
+      if (path == &(config.defaultserver))
          show_msg(MSGERR, "Connection needs to be made "
                           "via default server but "
                           "the default server has not "
@@ -701,7 +481,7 @@ int tsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIGNA
       bzero(&(server_address.sin_zero), 8);
 
       /* Complain if this server isn't on a localnet */
-      if (is_local(config, &server_address.sin_addr)) {
+      if (is_local(&config, &server_address.sin_addr)) {
          show_msg(MSGERR, "SOCKS server %s (%s) is not on a local subnet!\n", 
                   path->address, inet_ntoa(server_address.sin_addr));
       } else 
@@ -1078,6 +858,13 @@ int tsocks_close_guts(CLOSE_SIGNATURE, int (*original_close)(CLOSE_SIGNATURE)) {
   int rc;
   struct connreq *conn;
 
+   /* If we're not currently managing any requests we can just
+    * leave here */
+   if (!requests) {
+      show_msg(MSGDEBUG, "No requests waiting, calling real close\n");
+      return(original_close(fd));
+   }
+
   /* If we are called before this symbol has been dlopened then try
      loading symbols now. This is a workaround for a problem I don't
      really understand and have only encountered when using torsocks
@@ -1712,8 +1499,8 @@ static int read_socksv4_req(struct connreq *conn) {
 int res_init(void) {
     int rc;
 
-    if (!realresinit) {
-      if ((realresinit = dlsym(RTLD_NEXT, "res_init")) == NULL)
+    if (!realres_init) {
+      if ((realres_init = dlsym(RTLD_NEXT, "res_init")) == NULL)
         LOAD_ERROR("res_init", MSGERR);
     }
 
@@ -1724,23 +1511,23 @@ int res_init(void) {
       tsocks_init();
     }
 
-    if (realresinit == NULL) {
+    if (realres_init == NULL) {
         show_msg(MSGERR, "Unresolved symbol: res_init\n");
         return(-1);
     }
     /* Call normal res_init */
-    rc = realresinit();
+    rc = realres_init();
 
    /* Force using TCP protocol for DNS queries */
    _res.options |= RES_USEVC;
    return(rc);
 }
 
-int res_query(RES_QUERY_SIGNATURE) {
+int EXPAND_GUTS_NAME(res_query)(RES_QUERY_SIGNATURE, int (*original_res_query)(RES_QUERY_SIGNATURE)) {
     int rc;
 
-    if (!realresquery) {
-      if ((realresquery = dlsym(RTLD_NEXT, "res_query")) == NULL)
+    if (!original_res_query) {
+      if ((original_res_query = dlsym(RTLD_NEXT, "res_query")) == NULL)
         LOAD_ERROR("res_query", MSGERR);
     }
 
@@ -1751,7 +1538,7 @@ int res_query(RES_QUERY_SIGNATURE) {
       tsocks_init();
     }
 
-    if (realresquery == NULL) {
+    if (original_res_query == NULL) {
         show_msg(MSGERR, "Unresolved symbol: res_query\n");
         return(-1);
     }
@@ -1762,16 +1549,16 @@ int res_query(RES_QUERY_SIGNATURE) {
       res_init();
 
     /* Call normal res_query */
-    rc = realresquery(dname, class, type, answer, anslen);
+    rc = original_res_query(dname, class, type, answer, anslen);
 
    return(rc);
 }
 
-int res_querydomain(RES_QUERYDOMAIN_SIGNATURE) {
+int EXPAND_GUTS_NAME(res_querydomain)(RES_QUERYDOMAIN_SIGNATURE, int (*original_res_querydomain)(RES_QUERYDOMAIN_SIGNATURE)) {
     int rc;
 
-    if (!realresquerydomain) {
-      if ((realresquerydomain = dlsym(RTLD_NEXT, "res_querydomain")) == NULL)
+    if (!original_res_querydomain) {
+      if ((original_res_querydomain = dlsym(RTLD_NEXT, "res_querydomain")) == NULL)
         LOAD_ERROR("res_querydoimain", MSGERR);
     }
 
@@ -1782,7 +1569,7 @@ int res_querydomain(RES_QUERYDOMAIN_SIGNATURE) {
       tsocks_init();
     }
 
-    if (realresquerydomain == NULL) {
+    if (original_res_querydomain == NULL) {
         show_msg(MSGERR, "Unresolved symbol: res_querydomain\n");
         return(-1);
     }
@@ -1793,16 +1580,16 @@ int res_querydomain(RES_QUERYDOMAIN_SIGNATURE) {
       res_init();
 
     /* Call normal res_querydomain */
-    rc = realresquerydomain(name, domain, class, type, answer, anslen);
+    rc = original_res_querydomain(name, domain, class, type, answer, anslen);
 
    return(rc);
 }
 
-int res_search(RES_SEARCH_SIGNATURE) {
+int EXPAND_GUTS_NAME(res_search)(RES_SEARCH_SIGNATURE, int (*original_res_search)(RES_SEARCH_SIGNATURE)) {
     int rc;
 
-    if (!realressearch) {
-      if ((realressearch = dlsym(RTLD_NEXT, "res_search")) == NULL)
+    if (!original_res_search) {
+      if ((original_res_search = dlsym(RTLD_NEXT, "res_search")) == NULL)
         LOAD_ERROR("res_search", MSGERR);
     }
 
@@ -1813,7 +1600,7 @@ int res_search(RES_SEARCH_SIGNATURE) {
       tsocks_init();
     }
 
-    if (realressearch == NULL) {
+    if (original_res_search == NULL) {
         show_msg(MSGERR, "Unresolved symbol: res_search\n");
         return(-1);
     }
@@ -1824,16 +1611,16 @@ int res_search(RES_SEARCH_SIGNATURE) {
       res_init();
 
     /* Call normal res_search */
-    rc = realressearch(dname, class, type, answer, anslen);
+    rc = original_res_search(dname, class, type, answer, anslen);
 
    return(rc);
 }
 
-int res_send(RES_SEND_SIGNATURE) {
+int EXPAND_GUTS_NAME(res_send)(RES_SEND_SIGNATURE, int (*original_res_send)(RES_SEND_SIGNATURE)) {
     int rc;
 
-    if (!realressend) {
-      if ((realressend = dlsym(RTLD_NEXT, "res_send")) == NULL)
+    if (!original_res_send) {
+      if ((original_res_send = dlsym(RTLD_NEXT, "res_send")) == NULL)
         LOAD_ERROR("res_send", MSGERR);
     }
 
@@ -1844,7 +1631,7 @@ int res_send(RES_SEND_SIGNATURE) {
       tsocks_init();
     }
 
-    if (realressend == NULL) {
+    if (original_res_send == NULL) {
         show_msg(MSGERR, "Unresolved symbol: res_send\n");
         return(-1);
     }
@@ -1855,7 +1642,7 @@ int res_send(RES_SEND_SIGNATURE) {
       res_init();
 
     /* Call normal res_send */
-    rc = realressend(msg, msglen, answer, anslen);
+    rc = original_res_send(msg, msglen, answer, anslen);
 
    return(rc);
 }
@@ -1866,13 +1653,13 @@ static int deadpool_init(void)
   if(!pool) {
       get_environment();
       get_config();
-      if(config->tordns_enabled) {
+      if(config.tordns_enabled) {
           pool = init_pool(
-              config->tordns_cache_size, 
-              config->tordns_deadpool_range->localip, 
-              config->tordns_deadpool_range->localnet, 
-              config->defaultserver.address,
-              config->defaultserver.port
+              config.tordns_cache_size,
+              config.tordns_deadpool_range->localip,
+              config.tordns_deadpool_range->localnet,
+              config.defaultserver.address,
+              config.defaultserver.port
           );
           if(!pool) {
               show_msg(MSGERR, "failed to initialize deadpool: tordns disabled\n");
@@ -1882,39 +1669,39 @@ static int deadpool_init(void)
   return 0;
 }
 
-struct hostent *gethostbyname(GETHOSTBYNAME_SIGNATURE)
+struct hostent *tsocks_gethostbyname_guts(GETHOSTBYNAME_SIGNATURE, struct hostent *(*original_gethostbyname)(GETHOSTBYNAME_SIGNATURE))
 {
   if(pool) {
       return our_gethostbyname(pool, name);
   } else {
-      return realgethostbyname(name);
+      return original_gethostbyname(name);
   }  
 }
 
-struct hostent *gethostbyaddr(GETHOSTBYADDR_SIGNATURE)
+struct hostent *tsocks_gethostbyaddr_guts(GETHOSTBYADDR_SIGNATURE, struct hostent *(*original_gethostbyaddr)(GETHOSTBYADDR_SIGNATURE))
 {
   if(pool) {
       return our_gethostbyaddr(pool, addr, len, type);
   } else {
-      return realgethostbyaddr(addr, len, type);
+      return original_gethostbyaddr(addr, len, type);
   }  
 }
 
-int getaddrinfo(GETADDRINFO_SIGNATURE)
+int tsocks_getaddrinfo_guts(GETADDRINFO_SIGNATURE, int (*original_getaddrinfo)(GETADDRINFO_SIGNATURE))
 {
   if(pool) {
       return our_getaddrinfo(pool, node, service, hints, res);
   } else {
-      return realgetaddrinfo(node, service, hints, res);
+      return original_getaddrinfo(node, service, hints, res);
   }
 }
 
-struct hostent *getipnodebyname(GETIPNODEBYNAME_SIGNATURE)
+struct hostent *tsocks_getipnodebyname_guts(GETIPNODEBYNAME_SIGNATURE, struct hostent *(*original_getipnodebyname)(GETIPNODEBYNAME_SIGNATURE))
 {
   if(pool) {
       return our_getipnodebyname(pool, name, af, flags, error_num);
   } else {
-      return realgetipnodebyname(name, af, flags, error_num);
+      return original_getipnodebyname(name, af, flags, error_num);
   }
 }
 





More information about the tor-commits mailing list