~ubuntu-branches/ubuntu/trusty/websockify/trusty-updates

« back to all changes in this revision

Viewing changes to rebind.c

  • Committer: Package Import Robot
  • Author(s): Thomas Goirand
  • Date: 2013-02-23 01:22:51 UTC
  • Revision ID: package-import@ubuntu.com-20130223012251-3qkk1n1p93kb3j87
Tags: upstream-0.3.0+dfsg1
ImportĀ upstreamĀ versionĀ 0.3.0+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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)
 
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
 *
 
10
 * This allows a proxy (such as wsproxy) to run on the old port and translate
 
11
 * traffic to/from the new port.
 
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, "rebind: "); \
 
35
    fprintf(stderr, __VA_ARGS__);
 
36
#else
 
37
#define DEBUG(...)
 
38
#endif
 
39
 
 
40
 
 
41
int 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 = (long) 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 = (long) func(sockfd, &addr_tmp, addrlen_tmp);
 
91
 
 
92
    DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
 
93
    return ret;
 
94
}