The method for passing the remote address and port to an exec'ed program through getenv() calls in the preloaded libstunnel.so fails for programs that clean the environment initially. This can be circumvented placing getenv() in an _init() function and storing the results in static variables. Here is my alternative env.c (without the copyright and license), which I have been using for more than a year:
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/* getpeername() can't be declared in the following includes */ #define getpeername no_getpeername #include <sys/types.h> #include <sys/socket.h> /* for AF_INET */ #include <netinet/in.h> #include <arpa/inet.h> /* for inet_addr() */ #include <stdlib.h> /* for getenv() */ #ifdef __BEOS__ #include <be/bone/arpa/inet.h> /* for AF_INET */ #include <be/bone/sys/socket.h> /* for AF_INET */ #else #include <sys/socket.h> /* for AF_INET */ #endif #undef getpeername
static uint32_t rem_host=0; static uint16_t rem_port=0;
/* Requires shared-library linking by ld, not cc (except with gcc -nostdlib) */ void _init() { char *value; if((value=getenv("REMOTE_HOST")) && *value != '\0') rem_host = inet_addr(value); if((value=getenv("REMOTE_PORT")) && *value != '\0') rem_port = htons(atoi(value)); }
int getpeername(int s, struct sockaddr_in *name, int *len) { char *value;
name->sin_family = AF_INET; name->sin_addr.s_addr = rem_host; name->sin_port = rem_port; return 0; }
/* End of env.c */