]> git.proxmox.com Git - mirror_novnc.git/blame - utils/rebind.c
Merge pull request #444 from samhed/extdesktop
[mirror_novnc.git] / utils / rebind.c
CommitLineData
f2538f33
JM
1/*
2 * rebind: Intercept bind calls and bind to a different port
3 * Copyright 2010 Joel Martin
1d728ace 4 * Licensed under MPL-2.0 (see docs/LICENSE.MPL-2.0)
f2538f33
JM
5 *
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.
9 *
7c1cd937
JM
10 * This allows a bridge/proxy (such as websockify) to run on the old port and
11 * translate traffic to/from the new port.
f2538f33
JM
12 *
13 * Usage:
14 * LD_PRELOAD=./rebind.so \
15 * REBIND_PORT_OLD=23 \
16 * REBIND_PORT_NEW=2023 \
17 * program
18 */
19
20//#define DO_DEBUG 1
21
22#include <stdio.h>
23#include <stdlib.h>
24
25#define __USE_GNU 1 // Pull in RTLD_NEXT
26#include <dlfcn.h>
27
28#include <string.h>
29#include <netinet/in.h>
30
31
32#if defined(DO_DEBUG)
33#define DEBUG(...) \
34 fprintf(stderr, "wswrapper: "); \
35 fprintf(stderr, __VA_ARGS__);
36#else
37#define DEBUG(...)
38#endif
39
40
41int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
42{
43 static void * (*func)();
44 int do_move = 0;
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");
52
53 DEBUG(">> bind(%d, _, %d), askaddr %d, askport %d\n",
54 sockfd, addrlen, askaddr, askport);
55
56 /* Determine if we should move this socket */
57 if (addr_in->sin_family == AF_INET) {
58 // TODO: support IPv6
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)) {
68 do_move = 1;
69 }
70 }
71 }
72
73 if (! do_move) {
74 /* Just pass everything right through to the real bind */
75 ret = (int) func(sockfd, addr, addrlen);
76 DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
77 return ret;
78 }
79
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);
82
83 /* Use a temporary location for the new address information */
84 addrlen_tmp = sizeof(addr_tmp);
85 memcpy(&addr_tmp, addr, addrlen_tmp);
86
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 = (int) func(sockfd, &addr_tmp, addrlen_tmp);
91
92 DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
93 return ret;
94}