From ef07ae856f4fa23ae2bb8f767bd9c74fd13c81d4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Peter=20=C3=85strand?= Date: Mon, 14 Feb 2005 13:11:35 +0000 Subject: [PATCH] Applied vnc-via.patch from FC3 package. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@183 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- network/TcpSocket.cxx | 23 ++++++++++++ network/TcpSocket.h | 6 +++ vncviewer_unix/vncviewer.cxx | 73 +++++++++++++++++++++++++++++++++++- vncviewer_unix/vncviewer.man | 17 +++++++++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/network/TcpSocket.cxx b/network/TcpSocket.cxx index 4c4e8d3d..3fe4a651 100644 --- a/network/TcpSocket.cxx +++ b/network/TcpSocket.cxx @@ -54,6 +54,29 @@ using namespace rdr; static rfb::LogWriter vlog("TcpSocket"); +/* Tunnelling support. */ +int network::findFreeTcpPort (void) +{ + int sock, port; + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + + if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) + throw SocketException ("unable to create socket", errorNumber); + + for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { + addr.sin_port = htons ((unsigned short) port); + if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) == 0) { + close (sock); + return port; + } + } + throw SocketException ("no free port in range", 0); + return 0; +} + void TcpSocket::initTcpSockets() { diff --git a/network/TcpSocket.h b/network/TcpSocket.h index 95333402..74697829 100644 --- a/network/TcpSocket.h +++ b/network/TcpSocket.h @@ -32,8 +32,14 @@ #include +/* Tunnelling support. */ +#define TUNNEL_PORT_OFFSET 5500 + namespace network { + /* Tunnelling support. */ + int findFreeTcpPort (void); + class TcpSocket : public Socket { public: TcpSocket(int sock, bool close=true); diff --git a/vncviewer_unix/vncviewer.cxx b/vncviewer_unix/vncviewer.cxx index f0c5c981..a3d2fd31 100644 --- a/vncviewer_unix/vncviewer.cxx +++ b/vncviewer_unix/vncviewer.cxx @@ -44,6 +44,7 @@ rfb::LogWriter vlog("main"); using namespace network; using namespace rfb; +using namespace std; IntParameter pointerEventInterval("PointerEventInterval", "Time in milliseconds to rate-limit" @@ -99,6 +100,8 @@ BoolParameter listenMode("listen", "Listen for connections from VNC servers", StringParameter geometry("geometry", "X geometry specification", ""); StringParameter displayname("display", "The X display", ""); +StringParameter via("via", "Gateway to tunnel via", ""); + BoolParameter customCompressLevel("CustomCompressLevel", "Use custom compression level. " "Default if CompressLevel is specified.", false); @@ -179,6 +182,61 @@ static void usage() exit(1); } +/* Tunnelling support. */ +static void +interpretViaParam (char **gatewayHost, char **remoteHost, + int *remotePort, char **vncServerName, + int localPort) +{ + const int SERVER_PORT_OFFSET = 5900; + char *pos = strchr (*vncServerName, ':'); + if (pos == NULL) + *remotePort = SERVER_PORT_OFFSET; + else { + int portOffset = SERVER_PORT_OFFSET; + size_t len; + *pos++ = '\0'; + len = strlen (pos); + if (*pos == ':') { + /* Two colons is an absolute port number, not an offset. */ + pos++; + len--; + portOffset = 0; + } + if (!len || strspn (pos, "-0123456789") != len ) + usage (); + *remotePort = atoi (pos) + portOffset; + } + + if (**vncServerName != '\0') + *remoteHost = *vncServerName; + + *gatewayHost = strDup (via.getValueStr ()); + *vncServerName = new char[50]; + sprintf (*vncServerName, "localhost::%d", localPort); +} + +static void +createTunnel (const char *gatewayHost, const char *remoteHost, + int remotePort, int localPort) +{ + char *cmd = getenv ("VNC_VIA_CMD"); + char *percent; + char lport[10], rport[10]; + sprintf (lport, "%d", localPort); + sprintf (rport, "%d", remotePort); + setenv ("G", gatewayHost, 1); + setenv ("H", remoteHost, 1); + setenv ("R", rport, 1); + setenv ("L", lport, 1); + if (!cmd) + cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20"; + /* Compatibility with TightVNC's method. */ + while ((percent = strchr (cmd, '%')) != NULL) + *percent = '$'; + system (cmd); +} + int main(int argc, char** argv) { setlocale(LC_ALL, ""); @@ -221,8 +279,6 @@ int main(int argc, char** argv) usage(); } - if (vncServerName) - usage(); vncServerName = argv[i]; } @@ -240,6 +296,19 @@ int main(int argc, char** argv) try { TcpSocket::initTcpSockets(); + /* Tunnelling support. */ + if (strlen (via.getValueStr ()) > 0) { + char *gatewayHost = ""; + char *remoteHost = "localhost"; + int localPort = findFreeTcpPort (); + int remotePort; + if (!vncServerName) + usage(); + interpretViaParam (&gatewayHost, &remoteHost, &remotePort, + &vncServerName, localPort); + createTunnel (gatewayHost, remoteHost, remotePort, localPort); + } + Socket* sock = 0; if (listenMode) { diff --git a/vncviewer_unix/vncviewer.man b/vncviewer_unix/vncviewer.man index fc7439c8..b567f0a4 100644 --- a/vncviewer_unix/vncviewer.man +++ b/vncviewer_unix/vncviewer.man @@ -178,6 +178,23 @@ This option specifies the key which brings up the popup menu. The key is specified as an X11 keysym name (these can be obtained by removing the XK_ prefix from the entries in "/usr/include/X11/keysymdef.h"). Default is F8. +.TP +\fB\-via\fR \fIgateway\fR +Automatically create encrypted TCP tunnel to the \fIgateway\fR machine +before connection, connect to the \fIhost\fR through that tunnel +(TightVNC\-specific). By default, this option invokes SSH local port +forwarding, assuming that SSH client binary can be accessed as +/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host +machine name should be specified as known to the gateway machine, e.g. +"localhost" denotes the \fIgateway\fR, not the machine where vncviewer +was launched. The environment variable \fIVNC_VIA_CMD\fR can override +the default tunnel command of +\fB/usr/bin/ssh\ -f\ -L\ "$L":"$H":"$R"\ "$G"\ sleep\ 20\fR. The tunnel +command is executed with the environment variables \fIL\fR, \fIH\fR, +\fIR\fR, and \fIG\fR taken the values of the local port number, the remote +host, the port number on the remote host, and the gateway machine +respectively. + .SH SEE ALSO .BR Xvnc (1) .BR vncconfig (1), -- 2.39.5