summaryrefslogtreecommitdiff
path: root/utils/rebind.c
diff options
context:
space:
mode:
authorJoel Martin <jmartin@sentryds.com>2011-08-25 12:24:52 -0500
committerJoel Martin <jmartin@sentryds.com>2011-08-25 12:24:52 -0500
commit65edee7696dc40dbc3e1a068c7767257be1f6bd1 (patch)
treeb7e54cd8a149b4ad3ceaeacc41987e51aeee2d5f /utils/rebind.c
parent1d7af907209f3f1e3a7bad40ff9413b358d2c206 (diff)
downloadnovnc-html5-test.tar.gz
Fix menu. Add web-socket-js and websockify.html5-test
Diffstat (limited to 'utils/rebind.c')
-rw-r--r--utils/rebind.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/utils/rebind.c b/utils/rebind.c
new file mode 100644
index 0000000..c7e83de
--- /dev/null
+++ b/utils/rebind.c
@@ -0,0 +1,94 @@
+/*
+ * rebind: Intercept bind calls and bind to a different port
+ * Copyright 2010 Joel Martin
+ * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
+ *
+ * Overload (LD_PRELOAD) bind system call. If REBIND_PORT_OLD and
+ * REBIND_PORT_NEW environment variables are set then bind on the new
+ * port (of localhost) instead of the old port.
+ *
+ * This allows a proxy (such as wsproxy) to run on the old port and translate
+ * traffic to/from the new port.
+ *
+ * Usage:
+ * LD_PRELOAD=./rebind.so \
+ * REBIND_PORT_OLD=23 \
+ * REBIND_PORT_NEW=2023 \
+ * program
+ */
+
+//#define DO_DEBUG 1
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define __USE_GNU 1 // Pull in RTLD_NEXT
+#include <dlfcn.h>
+
+#include <string.h>
+#include <netinet/in.h>
+
+
+#if defined(DO_DEBUG)
+#define DEBUG(...) \
+ fprintf(stderr, "wswrapper: "); \
+ fprintf(stderr, __VA_ARGS__);
+#else
+#define DEBUG(...)
+#endif
+
+
+int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ static void * (*func)();
+ int do_move = 0;
+ struct sockaddr_in * addr_in = (struct sockaddr_in *)addr;
+ struct sockaddr_in addr_tmp;
+ socklen_t addrlen_tmp;
+ char * PORT_OLD, * PORT_NEW, * end1, * end2;
+ int ret, oldport, newport, askport = htons(addr_in->sin_port);
+ uint32_t askaddr = htons(addr_in->sin_addr.s_addr);
+ if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "bind");
+
+ DEBUG(">> bind(%d, _, %d), askaddr %d, askport %d\n",
+ sockfd, addrlen, askaddr, askport);
+
+ /* Determine if we should move this socket */
+ if (addr_in->sin_family == AF_INET) {
+ // TODO: support IPv6
+ PORT_OLD = getenv("REBIND_OLD_PORT");
+ PORT_NEW = getenv("REBIND_NEW_PORT");
+ if (PORT_OLD && (*PORT_OLD != '\0') &&
+ PORT_NEW && (*PORT_NEW != '\0')) {
+ oldport = strtol(PORT_OLD, &end1, 10);
+ newport = strtol(PORT_NEW, &end2, 10);
+ if (oldport && (*end1 == '\0') &&
+ newport && (*end2 == '\0') &&
+ (oldport == askport)) {
+ do_move = 1;
+ }
+ }
+ }
+
+ if (! do_move) {
+ /* Just pass everything right through to the real bind */
+ ret = (int) func(sockfd, addr, addrlen);
+ DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
+ return ret;
+ }
+
+ DEBUG("binding fd %d on localhost:%d instead of 0x%x:%d\n",
+ sockfd, newport, ntohl(addr_in->sin_addr.s_addr), oldport);
+
+ /* Use a temporary location for the new address information */
+ addrlen_tmp = sizeof(addr_tmp);
+ memcpy(&addr_tmp, addr, addrlen_tmp);
+
+ /* Bind to other port on the loopback instead */
+ addr_tmp.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr_tmp.sin_port = htons(newport);
+ ret = (int) func(sockfd, &addr_tmp, addrlen_tmp);
+
+ DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
+ return ret;
+}