2
* rebind: Intercept bind calls and bind to a different port
3
* Copyright 2010 Joel Martin
4
* Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
6
* Overload (LD_PRELOAD) bind system call. If REBIND_PORT_OLD and
7
* REBIND_PORT_NEW environment variables are set then bind on the new
8
* port (of localhost) instead of the old port.
10
* This allows a proxy (such as wsproxy) to run on the old port and translate
11
* traffic to/from the new port.
14
* LD_PRELOAD=./rebind.so \
15
* REBIND_PORT_OLD=23 \
16
* REBIND_PORT_NEW=2023 \
25
#define __USE_GNU 1 // Pull in RTLD_NEXT
29
#include <netinet/in.h>
34
fprintf(stderr, "rebind: "); \
35
fprintf(stderr, __VA_ARGS__);
41
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
43
static void * (*func)();
45
struct sockaddr_in * addr_in = (struct sockaddr_in *)addr;
46
struct sockaddr_in addr_tmp;
47
socklen_t addrlen_tmp;
48
char * PORT_OLD, * PORT_NEW, * end1, * end2;
49
int ret, oldport, newport, askport = htons(addr_in->sin_port);
50
uint32_t askaddr = htons(addr_in->sin_addr.s_addr);
51
if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "bind");
53
DEBUG(">> bind(%d, _, %d), askaddr %d, askport %d\n",
54
sockfd, addrlen, askaddr, askport);
56
/* Determine if we should move this socket */
57
if (addr_in->sin_family == AF_INET) {
59
PORT_OLD = getenv("REBIND_OLD_PORT");
60
PORT_NEW = getenv("REBIND_NEW_PORT");
61
if (PORT_OLD && (*PORT_OLD != '\0') &&
62
PORT_NEW && (*PORT_NEW != '\0')) {
63
oldport = strtol(PORT_OLD, &end1, 10);
64
newport = strtol(PORT_NEW, &end2, 10);
65
if (oldport && (*end1 == '\0') &&
66
newport && (*end2 == '\0') &&
67
(oldport == askport)) {
74
/* Just pass everything right through to the real bind */
75
ret = (long) func(sockfd, addr, addrlen);
76
DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
80
DEBUG("binding fd %d on localhost:%d instead of 0x%x:%d\n",
81
sockfd, newport, ntohl(addr_in->sin_addr.s_addr), oldport);
83
/* Use a temporary location for the new address information */
84
addrlen_tmp = sizeof(addr_tmp);
85
memcpy(&addr_tmp, addr, addrlen_tmp);
87
/* Bind to other port on the loopback instead */
88
addr_tmp.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
89
addr_tmp.sin_port = htons(newport);
90
ret = (long) func(sockfd, &addr_tmp, addrlen_tmp);
92
DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);