/* Address reporting hack v1.0 by nim at nimlabs dot org based on: Transparent IP bind v1.0 by nathan 0x00 org Description: Allows faking an address in getsockname to help with NAT traversal. Compiling: gcc -fPIC -shared -o munge_getsockname.so \ munge_getsockname.c -ldl Usage: (To replace interal 10.1.2.3 IP with external 18.4.5.6 address) export LD_PRELOAD=/path/to/munge_getsockname.so export FROMIP="10.1.2.3" export TOIP="18.4.5.6" command to be munged */ #define _GNU_SOURCE #include #include #include #include #include #include #include #define DEBUGP(format, ...) /*#define DEBUGP(format, ...) fprintf(stderr, format, __VA_ARGS__)*/ static char version[]="munge_getsockname.c v1.0 by nim at nimlabs dot org"; /* static data gets initialized as zero by default. */ static int (*real_getsockname)(int, __SOCKADDR_ARG, socklen_t*); static int init_latch; static in_addr_t from_ip; static in_addr_t to_ip; static int ip_valid; static void latch_init() { if (init_latch) return; real_getsockname = dlsym(RTLD_NEXT, "getsockname"); char *from_ip_str = getenv("FROMIP"); char *to_ip_str = getenv("TOIP"); if (from_ip_str != NULL && to_ip_str != NULL) { from_ip = inet_addr(from_ip_str); to_ip = inet_addr(to_ip_str); ip_valid = 1; DEBUGP("denat: from_ip %x to_ip %x\n", from_ip, to_ip); } init_latch = 1; } int getsockname(int __fd, __SOCKADDR_ARG __addr, socklen_t* __len); int getsockname(int __fd, __SOCKADDR_ARG __addr, socklen_t* __len) { latch_init(); int ret = real_getsockname(__fd, __addr, __len); if (0 != ret || 0 == *__len) { DEBUGP("munge: getsockname failed: ret %d len %d\n", ret, *__len); return ret; } if (AF_INET != __addr.__sockaddr__->sa_family) { DEBUGP("munge: getsockname returned non IPv4: family %d\n", __addr.__sockaddr__->sa_family); return ret; } in_addr_t retaddr = __addr.__sockaddr_in__->sin_addr.s_addr; DEBUGP("munge: intercepted getsockname got: len %d retaddr %x\n", *__len, retaddr); if (ip_valid && from_ip == retaddr) { DEBUGP("munge: REPLACED getsockname output: retaddr %x toaddr %x\n", retaddr, to_ip); __addr.__sockaddr_in__->sin_addr.s_addr = to_ip; } return ret; }