use dynloader to call init() func when gcc is available, and lock it properly

pull/3/head
rofl0r 2012-04-23 22:14:04 +02:00
parent caed782652
commit 88a54e872a
1 changed files with 44 additions and 21 deletions

View File

@ -52,13 +52,16 @@ int proxychains_got_chain_data = 0;
unsigned int proxychains_max_chain = 1; unsigned int proxychains_max_chain = 1;
int proxychains_quiet_mode = 0; int proxychains_quiet_mode = 0;
int proxychains_resolver = 0; int proxychains_resolver = 0;
static int init_l = 0;
localaddr_arg localnet_addr[MAX_LOCALNET]; localaddr_arg localnet_addr[MAX_LOCALNET];
size_t num_localnet_addr = 0; size_t num_localnet_addr = 0;
unsigned int remote_dns_subnet = 224; unsigned int remote_dns_subnet = 224;
#ifdef THREAD_SAFE
pthread_once_t init_once = PTHREAD_ONCE_INIT;
#endif
static int init_l = 0;
static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct); static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct);
static void init_lib(void);
static void load_sym(void** funcptr, char* symname, void* proxyfunc) { static void load_sym(void** funcptr, char* symname, void* proxyfunc) {
@ -76,7 +79,9 @@ static void load_sym(void** funcptr, char* symname, void* proxyfunc) {
} }
} }
static void init_lib(void) { #define INIT() init_lib_wrapper(__FUNCTION__)
static void do_init(void) {
static const struct override_info { static const struct override_info {
void* funcptr; void* funcptr;
char* symname; char* symname;
@ -92,7 +97,6 @@ static void init_lib(void) {
#undef SYM_ENTRY #undef SYM_ENTRY
}; };
unsigned i; unsigned i;
MUTEX_INIT(&internal_ips_lock, NULL); MUTEX_INIT(&internal_ips_lock, NULL);
/* read the config file */ /* read the config file */
get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct); get_chain_data(proxychains_pd, &proxychains_proxy_count, &proxychains_ct);
@ -102,11 +106,37 @@ static void init_lib(void) {
for (i = 0; i < (sizeof(override_symbols) / sizeof(override_symbols[0])); i++) { for (i = 0; i < (sizeof(override_symbols) / sizeof(override_symbols[0])); i++) {
load_sym(override_symbols[i].funcptr, override_symbols[i].symname, override_symbols[i].proxyfunc); load_sym(override_symbols[i].funcptr, override_symbols[i].symname, override_symbols[i].proxyfunc);
} }
init_l = 1; init_l = 1;
} }
static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) { static void init_lib_wrapper(const char* caller) {
#ifndef DEBUG
(void) caller;
#endif
#ifndef THREAD_SAFE
if(init_l) return;
PDEBUG("%s called from %s\n", __FUNCTION__, caller);
do_init();
#else
if(!init_l) PDEBUG("%s called from %s\n", __FUNCTION__, caller);
pthread_once(&init_once, do_init);
#endif
}
/* if we use gcc >= 3, we can instruct the dynamic loader
* to call init_lib at link time. otherwise it gets loaded
* lazily, which has the disadvantage that there's a potential
* race condition if 2 threads call it before init_l is set
* and PTHREAD support was disabled */
#if __GNUC__ > 2
__attribute__((constructor))
static void gcc_init(void) {
INIT();
}
#endif
/* get configuration from config file */
static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_type * ct) {
int count = 0, port_n = 0, list = 0; int count = 0, port_n = 0, list = 0;
char buff[1024], type[1024], host[1024], user[1024]; char buff[1024], type[1024], host[1024], user[1024];
char *env; char *env;
@ -247,7 +277,7 @@ static inline void get_chain_data(proxy_data * pd, unsigned int *proxy_count, ch
proxychains_got_chain_data = 1; proxychains_got_chain_data = 1;
} }
/******* HOOK FUNCTIONS *******/
int connect(int sock, const struct sockaddr *addr, unsigned int len) { int connect(int sock, const struct sockaddr *addr, unsigned int len) {
int socktype = 0, flags = 0, ret = 0; int socktype = 0, flags = 0, ret = 0;
@ -260,9 +290,7 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
unsigned short port; unsigned short port;
size_t i; size_t i;
int remote_dns_connect = 0; int remote_dns_connect = 0;
INIT();
if(!init_l)
init_lib();
optlen = sizeof(socktype); optlen = sizeof(socktype);
getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &optlen); getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
if(!(SOCKFAMILY(*addr) == AF_INET && socktype == SOCK_STREAM)) if(!(SOCKFAMILY(*addr) == AF_INET && socktype == SOCK_STREAM))
@ -309,8 +337,7 @@ int connect(int sock, const struct sockaddr *addr, unsigned int len) {
} }
struct hostent *gethostbyname(const char *name) { struct hostent *gethostbyname(const char *name) {
if(!init_l) INIT();
init_lib();
PDEBUG("gethostbyname: %s\n", name); PDEBUG("gethostbyname: %s\n", name);
@ -325,8 +352,7 @@ struct hostent *gethostbyname(const char *name) {
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
int ret = 0; int ret = 0;
if(!init_l) INIT();
init_lib();
PDEBUG("getaddrinfo: %s %s\n", node, service); PDEBUG("getaddrinfo: %s %s\n", node, service);
@ -339,8 +365,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
} }
void freeaddrinfo(struct addrinfo *res) { void freeaddrinfo(struct addrinfo *res) {
if(!init_l) INIT();
init_lib();
PDEBUG("freeaddrinfo %p \n", res); PDEBUG("freeaddrinfo %p \n", res);
@ -366,9 +391,8 @@ int getnameinfo(const struct sockaddr *sa,
char ip_buf[16]; char ip_buf[16];
int ret = 0; int ret = 0;
if(!init_l) INIT();
init_lib();
PDEBUG("getnameinfo: %s %s\n", host, serv); PDEBUG("getnameinfo: %s %s\n", host, serv);
if(!proxychains_resolver) { if(!proxychains_resolver) {
@ -390,8 +414,7 @@ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
static char *list[2]; static char *list[2];
static struct hostent he; static struct hostent he;
if(!init_l) INIT();
init_lib();
PDEBUG("TODO: proper gethostbyaddr hook\n"); PDEBUG("TODO: proper gethostbyaddr hook\n");