classes/ssl: Many improvements to Java SSL applet, onetimekey

serverCert param, debugging printout, user dialogs, catch
          socket exceptions, autodetect x11vnc for GET=1.
x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl.
          X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and
          can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script,
          autodetect dm on udp6 only.  Queries: pointer_x, pointer_y,
          pointer_same, pointer_root.  Switch on -xkd if keysyms per key >
          4 in all cases.  daemon mode improvements for connect_switch,
          inet6to4, ultravnc_repeater.pl.  Dynamic change of -clip do
          not create new fb if WxH is unchanged.
pull/1/head
runge 14 years ago
parent edb79ae2b1
commit 97540de56c

@ -137,6 +137,15 @@ Both TightVNC and UltraVNC Java viewers:
number, default: 50
Milliseconds delay
PASSWORD
string, default: none
VNC session password in plain text.
ENCPASSWORD
string, default: none
VNC session password in encrypted in DES with KNOWN FIXED
key. It is a hex string. This is like the ~/.vnc/passwd format.
The following are added by x11vnc and/or ssvnc project
@ -173,16 +182,47 @@ Both TightVNC and UltraVNC Java viewers:
oneTimeKey
string, default: none
set a special hex "key" to correspond to an SSL X.509 cert.
See the 'onetimekey' helper script. Can also be PROMPT to
prompt the user to paste the hex key string in.
set a special hex "key" to correspond to an SSL X.509 cert+key.
See the 'onetimekey' helper script. Can also be PROMPT to prompt
the user to paste the hex key string in.
This provides a Client-Side cert+key that the client will use to
authenticate itself by SSL To the VNC Server.
This is to try to work around the problem that the Java applet
cannot keep an SSL keystore on disk, etc. E.g. if they log
into an HTTPS website via password they are authenticated and
encrypted, then the website can safely put oneTimeKey=... on the
URL. The Vncviewer authenticates the VNC server with this key.
Note that there is currently a problem in that if x11vnc requires
Client Certificates the user cannot download the index.vnc HTML
and VncViewer.jar from the same x11vnc. Those need to come from
a different x11vnc or from a web server.
Note that the HTTPS website can also put the VNC Password
(e.g. a temporary/one-time one) in the parameter PASSWORD.
The Java Applet will automatically supply this VNC password
instead of prompting.
serverCert
string, default: none
set a special hex "cert" to correspond to an SSL X.509 cert
See the 'onetimekey -certonly' helper script.
This is to try to work around the problem that the Java
applet cannot keep an SSL keystore on disk, etc.
E.g. if they log into an HTTPS website via password they
are authenticated and encrypted, then the website can
safely put oneTimeKey=... on the URL. The Vncviewer
authenticates the VNC server with this key.
This provides a Server-Side cert that the client will authenticate
the VNC Server against by SSL.
This is to try to work around the problem that the Java applet
cannot keep an SSL keystore on disk, etc. E.g. if they log
into an HTTPS website via password they are authenticated and
encrypted, then the website can safely put serverCert=... on the
URL.
Of course the VNC Server is sending this string to the Java
Applet, so this is only reasonable security if the VNC Viewer
already trusts the HTTPS retrieval of the URL + serverCert param
that it gets. This should be done over HTTPS not HTTP.
proxyHost
string, default: none
@ -238,15 +278,8 @@ TightVNC Java viewer only:
UltraVNC Java viewer only:
PASSWORD
string, default: none
VNC session password in plain text.
None.
ENCPASSWORD
string, default: none
VNC session password in encrypted in DES with KNOWN FIXED
key. It is a hex string. This is like the ~/.vnc/passwd format.
The following are added by x11vnc and/or ssvnc project
ftpDropDown

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,6 +1,7 @@
#!/bin/sh
#
# usage: onetimekey path/to/mycert.pem
# onetimekey -certonly path/to/mycert.pem
#
# Takes an openssl cert+key pem file and turns into a long string
# for the x11vnc SSL VNC Java Viewer.
@ -14,6 +15,19 @@
# in it. Also, as the name implies, an HTTPS server can create
# a one time key to send to the applet (the user has already
# logged in via password to the HTTPS server).
#
# Note oneTimeKey is to provide a CLIENT Certificate for the viewer
# to authenticate itself to the VNC Server.
#
# There is also the serverCert=<str> Applet parameter. This is
# a cert to authenticate the VNC server against. To create that
# string with this tool specify -certonly as the first argument.
certonly=""
if [ "X$1" = "X-certonly" ]; then
shift
certonly=1
fi
in=$1
der=/tmp/1time$$.der
@ -43,5 +57,9 @@ rm -f "$der"
n=`grep -n 'BEGIN CERTIFICATE' $in | awk -F: '{print $1}' | head -1`
str2=`tail +$n $in | $pbinhex`
echo "$str1,$str2"
if [ "X$certonly" = "X1" ]; then
echo "$str2"
else
echo "$str1,$str2"
fi
rm -f $pbinhex

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,3 +1,16 @@
2010-03-20 Karl Runge <runge@karlrunge.com>
* classes/ssl: Many improvements to Java SSL applet, onetimekey
serverCert param, debugging printout, user dialogs, catch
socket exceptions, autodetect x11vnc for GET=1.
* x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl.
X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and
can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script,
autodetect dm on udp6 only. Queries: pointer_x, pointer_y,
pointer_same, pointer_root. Switch on -xkd if keysyms per key >
4 in all cases. daemon mode improvements for connect_switch,
inet6to4, ultravnc_repeater.pl. Dynamic change of -clip do
not create new fb if WxH is unchanged.
2010-02-22 Karl Runge <runge@karlrunge.com>
* classes/ssl: Java SSL applet viewer now works with certificate
chains.

File diff suppressed because it is too large Load Diff

@ -908,6 +908,9 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
*(winfo->res_name) = '\0';
*(winfo->res_class) = '\0';
for (i=0; i < maxtries; i++) {
wins[i] = None;
}
/* some times a window can go away before we get to it */
trapped_xerror = 0;

@ -518,6 +518,11 @@ void print_help(int mode) {
" -stunnel the ssl classes subdirectory is sought.\n"
"-http_ssl As -http, but force lookup for ssl classes subdir.\n"
"\n"
" Note that for HTTPS, single-port Java applet delivery\n"
" you can set X11VNC_HTTPS_DOWNLOAD_WAIT_TIME to the\n"
" max number of seconds to wait for the applet download\n"
" to finish. The default is 15.\n"
"\n"
"-avahi Use the Avahi/mDNS ZeroConf protocol to advertise\n"
" this VNC server to the local network. (Related terms:\n"
" Rendezvous, Bonjour). Depending on your setup, you\n"
@ -965,9 +970,31 @@ void print_help(int mode) {
" the user is allowed, but the option values associated\n"
" with it do apply as normal.\n"
"\n"
" There are also some utilities for testing password\n"
" There are also some utilities for checking passwords\n"
" if [list] starts with the \"%%\" character. See the\n"
" quick_pw() function in the source for details.\n"
" quick_pw() function for more details. Description:\n"
" \"%%-\" or \"%%stdin\" means read one line from stdin.\n"
" \"%%env\" means it is in $UNIXPW env var. A leading\n"
" \"%%/\" or \"%%.\" means read the first line from the\n"
" filename that follows after the %% character. %% by\n"
" itself means prompt for the username and password.\n"
" Otherwise: %%user:pass E.g. -unixpw %%fred:swordfish\n"
" For the other cases user:pass is read from the indicated\n"
" source. If the password is correct 'Y user' is printed\n"
" and the program exit code is 0. If the password is\n"
" incorrect it prints 'N user' and the exit code is 1.\n"
" If there is some other error the exit code is 2.\n"
" This feature enables x11vnc to be a general unix user\n"
" password checking tool; it could be used from scripts\n"
" or other programs. These %% password checks also apply\n"
" to the -unixpw_nis and -unixpw_cmd options.\n"
"\n"
" For the %% password check, if the env. var. UNIXPW_CMD\n"
" is set to a command then it is run as the user (assuming\n"
" the password is correct.) The output of the command is\n"
" not printed, the program or script must manage that by\n"
" some other means. The exit code of x11vnc will depend\n"
" on the exit code of the command that is run.\n"
"\n"
" Use -nounixpw to disable unixpw mode if it was enabled\n"
" earlier in the cmd line (e.g. -svc mode)\n"
@ -1072,8 +1099,11 @@ void print_help(int mode) {
" supplied unixpw_cmd to do user switching if desired\n"
" and if it has the permissions to do so.\n"
"\n"
"-find Find the user's display using FINDDISPLAY. This is an\n"
" alias for \"-display WAIT:cmd=FINDDISPLAY\".\n"
"-find Find the user's display using FINDDISPLAY. This\n"
" is an alias for \"-display WAIT:cmd=FINDDISPLAY\".\n"
"\n"
" Note: if a -display occurs later on the command line\n"
" it will override the -find setting.\n"
"\n"
" For this and the next few options see -display WAIT:...\n"
" below for all of the details.\n"
@ -1111,6 +1141,9 @@ void print_help(int mode) {
" FINDCREATEDISPLAY method. This is an alias for\n"
" \"-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb\".\n"
"\n"
" Note: if a -display occurs later on the command line\n"
" it will override the -create setting.\n"
"\n"
" SSH NOTE: for both -find and -create you can (should!)\n"
" add the \"-localhost\" option to force SSH tunnel access.\n"
"\n"
@ -1128,6 +1161,10 @@ void print_help(int mode) {
" -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users\n"
" unixpw= -ssl SAVE Also \"-service\".\n"
"\n"
" Note: if a -display, -unixpw, -users, or -ssl occurs\n"
" later on the command line it will override the -svc\n"
" setting.\n"
"\n"
"-svc_xdummy As -svc except Xdummy instead of Xvfb.\n"
"-svc_xvnc As -svc except Xvnc instead of Xvfb.\n"
"-svc_xdummy_xvfb As -svc with Xdummy,Xvfb.\n"
@ -1136,6 +1173,10 @@ void print_help(int mode) {
" Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp\n"
" -unixpw -users unixpw= -ssl SAVE Also \"-xdm_service\".\n"
"\n"
" Note: if a -display, -unixpw, -users, or -ssl occurs\n"
" later on the command line it will override the -xdmsvc\n"
" setting.\n"
"\n"
" To create a session a user will have to first log in\n"
" to the -unixpw dialog and then log in again to the\n"
" XDM/GDM/KDM prompt. Subsequent re-connections will\n"
@ -1485,6 +1526,11 @@ void print_help(int mode) {
" X property, that makes FINDDISPLAY only find sessions\n"
" with that tag value.\n"
"\n"
" Set FD_XDMCP_IF to the network interface that the\n"
" display manager is running on; default is 'localhost'\n"
" but you may need to set it to '::1' on some IPv6 only\n"
" systems or misconfigured display managers.\n"
"\n"
" If you want the FINDCREATEDISPLAY session to contact an\n"
" XDMCP login manager (xdm/gdm/kdm) on the same machine,\n"
" then use \"Xvfb.xdmcp\" instead of \"Xvfb\", etc.\n"
@ -2147,7 +2193,7 @@ void print_help(int mode) {
" exits.\n"
"\n"
"\n"
"-stunnel [pem] Use the stunnel(8) (www.stunnel.org) to provide an\n"
"-stunnel [pem] Use the stunnel(8) (stunnel.mirt.net) to provide an\n"
" encrypted SSL tunnel between viewers and x11vnc.\n"
"\n"
" This external tunnel method was implemented prior to the\n"
@ -4980,6 +5026,10 @@ void print_help(int mode) {
" for root window, use +id for children.\n"
" grab_state get state of pointer and keyboard grab.\n"
" pointer_pos print XQueryPointer x,y cursor position.\n"
" pointer_x print XQueryPointer x cursor position.\n"
" pointer_y print XQueryPointer y cursor position.\n"
" pointer_same print XQueryPointer ptr on same screen.\n"
" pointer_root print XQueryPointer curr ptr rootwin.\n"
" mouse_x print x11vnc's idea of cursor position.\n"
" mouse_y print x11vnc's idea of cursor position.\n"
" noop do nothing.\n"
@ -5278,18 +5328,18 @@ void print_help(int mode) {
" http_url auth xauth users rootshift clipshift scale_str\n"
" scaled_x scaled_y scale_numer scale_denom scale_fac_x\n"
" scale_fac_y scaling_blend scaling_nomult4 scaling_pad\n"
" scaling_interpolate inetd privremote unsafe safer\n"
" nocmds passwdfile unixpw unixpw_nis unixpw_list ssl\n"
" ssl_pem sslverify stunnel stunnel_pem https httpsredir\n"
" usepw using_shm logfile o flag rmflag rc norc h help\n"
" V version lastmod bg sigpipe threads readrate netrate\n"
" netlatency pipeinput clients client_count pid ext_xtest\n"
" ext_xtrap ext_xrecord ext_xkb ext_xshm ext_xinerama\n"
" ext_overlay ext_xfixes ext_xdamage ext_xrandr rootwin\n"
" num_buttons button_mask mouse_x mouse_y grab_state\n"
" pointer_pos bpp depth indexed_color dpy_x dpy_y wdpy_x\n"
" wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth\n"
" passwd viewpasswd\n"
" scaling_interpolate inetd privremote unsafe safer nocmds\n"
" passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem\n"
" sslverify stunnel stunnel_pem https httpsredir usepw\n"
" using_shm logfile o flag rmflag rc norc h help V version\n"
" lastmod bg sigpipe threads readrate netrate netlatency\n"
" pipeinput clients client_count pid ext_xtest ext_xtrap\n"
" ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay\n"
" ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons\n"
" button_mask mouse_x mouse_y grab_state pointer_pos\n"
" pointer_x pointer_y pointer_same pointer_root bpp depth\n"
" indexed_color dpy_x dpy_y wdpy_x wdpy_y off_x off_y\n"
" cdpy_x cdpy_y coff_x coff_y rfbauth passwd viewpasswd\n"
"\n"
"-QD variable Just like -query variable, but returns the default\n"
" value for that parameter (no running x11vnc server\n"

@ -1114,7 +1114,8 @@ void switch_to_xkb_if_better(void) {
n = k;
XFree_wr(keymap);
if (missing_noxkb == 0 && syms_gt_4 >= 8) {
if (missing_noxkb == 0 && syms_per_keycode > 4 && syms_gt_4 >= 0) {
/* we used to have syms_gt_4 >= 8, now always on. */
if (! raw_fb_str) {
rfbLog("\n");
rfbLog("XKEYBOARD: number of keysyms per keycode %d is greater\n", syms_per_keycode);
@ -1123,6 +1124,7 @@ void switch_to_xkb_if_better(void) {
rfbLog(" If this makes the key mapping worse you can\n");
rfbLog(" disable it with the \"-noxkb\" option.\n");
rfbLog(" Also, remember \"-remap DEAD\" for accenting characters.\n");
rfbLog("\n");
}
use_xkb_modtweak = 1;
@ -1135,6 +1137,7 @@ void switch_to_xkb_if_better(void) {
rfbLog(" Not automatically switching to -xkb mode.\n");
rfbLog(" If some keys still cannot be typed, try using -xkb.\n");
rfbLog(" Also, remember \"-remap DEAD\" for accenting characters.\n");
rfbLog("\n");
}
return;
}
@ -1217,6 +1220,7 @@ void switch_to_xkb_if_better(void) {
rfbLog(" Also, remember \"-remap DEAD\" for accenting"
" characters.\n");
}
rfbLog("\n");
}
/* sets up all the keymapping info via Xkb API */

@ -1,3 +1,3 @@
SUBDIRS = turbovnc
DIST_SUBDIRS = turbovnc
EXTRA_DIST=README blockdpy.c dtVncPopup rx11vnc rx11vnc.pl shm_clear ranfb.pl slide.pl vcinject.pl x11vnc_loop Xdummy ultravnc_repeater.pl connect_switch
EXTRA_DIST=README blockdpy.c dtVncPopup rx11vnc rx11vnc.pl shm_clear ranfb.pl slide.pl vcinject.pl x11vnc_loop Xdummy ultravnc_repeater.pl connect_switch panner.pl desktop.cgi inet6to4

@ -33,3 +33,14 @@ Misc. scripts:
use Xsetup mechanism.
Xdummy An LD_PRELOAD kludge to run the Xorg "dummy" device driver
like Xvfb.
ultravnc_repeater.pl: Unix script to act as UltraVNC repeater proxy.
connect_switch: Share HTTPS, VNC, SSH, etc. through a single port (e.g. 443)
panner.pl Allows a small rectangle to pan around a desktop more or less.
desktop.cgi CGI script for creating multi-user virtual desktops on a
server. Also can do port-redirection to internal machines.
inet6to4 ipv6 to ipv4 relay (i.e. until libvncserver supports ipv6)

@ -1,6 +1,6 @@
#!/usr/bin/perl
#
# Copyright (c) 2006-2009 by Karl J. Runge <runge@karlrunge.com>
# Copyright (c) 2006-2010 by Karl J. Runge <runge@karlrunge.com>
#
# connect_switch is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -35,10 +35,14 @@
# because the CONNECT request appears to be forwarded encrypted to
# the remote host and so the SSL dies immediately.
#
# It can also be used to redirect ANY protocol, e.g. SSH, not just VNC.
# See CONNECT_SWITCH_APPLY_VNC_OFFSET=0 to disable VNC 5900 shift.
#
# Note: There is no need to use this script for a non-ssl apache webserver
# port because mod_proxy works fine for doing the switching all inside
# apache (see ProxyRequests and AllowCONNECT parameters).
#
#
# Apache configuration:
#
# The mod_ssl configuration is often in a file named ssl.conf. In the
@ -68,6 +72,126 @@
# It is probably a good idea to set $listen_host below to the known
# IP address you want the service to listen on (to avoid localhost where
# apache is listening).
#
####################################################################
# NOTE: For more info on configuration settings, read below for
# all of the CONNECT_SWITCH_* env. var. parameters.
####################################################################
####################################################################
# Allow env vars to also be specified on cmdline:
#
foreach my $arg (@ARGV) {
if ($arg =~ /^(CONNECT_SWITCH.*?)=(.*)$/) {
$ENV{$1} = $2;
}
}
# Set up logging:
#
if (exists $ENV{CONNECT_SWITCH_LOGFILE}) {
close STDOUT;
if (!open(STDOUT, ">>$ENV{CONNECT_SWITCH_LOGFILE}")) {
die "connect_switch: $ENV{CONNECT_SWITCH_LOGFILE} $!\n";
}
close STDERR;
open(STDERR, ">&STDOUT");
}
select(STDERR); $| = 1;
select(STDOUT); $| = 1;
# interrupt handler:
#
my $looppid = '';
my $pidfile = '';
my $listen_sock = ''; # declared here for get_out()
#
sub get_out {
print STDERR "$_[0]:\t$$ looppid=$looppid\n";
close $listen_sock if $listen_sock;
if ($looppid) {
kill 'TERM', $looppid;
fsleep(0.2);
}
unlink $pidfile if $pidfile;
exit 0;
}
$SIG{INT} = \&get_out;
$SIG{TERM} = \&get_out;
# pidfile:
#
sub open_pidfile {
if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
my $pf = $ENV{CONNECT_SWITCH_PIDFILE};
if (open(PID, ">$pf")) {
print PID "$$\n";
close PID;
$pidfile = $pf;
} else {
print STDERR "could not open pidfile: $pf - $! - continuing...\n";
}
delete $ENV{CONNECT_SWITCH_PIDFILE};
}
}
####################################################################
# Set CONNECT_SWITCH_LOOP=1 to have this script create an outer loop
# restarting itself if it ever exits. Set CONNECT_SWITCH_LOOP=BG to
# do this in the background as a daemon.
if (exists $ENV{CONNECT_SWITCH_LOOP}) {
my $csl = $ENV{CONNECT_SWITCH_LOOP};
if ($csl ne 'BG' && $csl ne '1') {
die "connect_switch: invalid CONNECT_SWITCH_LOOP.\n";
}
if ($csl eq 'BG') {
# go into bg as "daemon":
setpgrp(0, 0);
my $pid = fork();
if (! defined $pid) {
die "connect_switch: $!\n";
} elsif ($pid) {
wait;
exit 0;
}
if (fork) {
exit 0;
}
setpgrp(0, 0);
close STDIN;
if (! $ENV{CONNECT_SWITCH_LOGFILE}) {
close STDOUT;
close STDERR;
}
}
delete $ENV{CONNECT_SWITCH_LOOP};
if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
open_pidfile();
}
print STDERR "connect_switch: starting service at ", scalar(localtime), " master-pid=$$\n";
while (1) {
$looppid = fork;
if (! defined $looppid) {
sleep 10;
} elsif ($looppid) {
wait;
} else {
exec $0;
exit 1;
}
print STDERR "connect_switch: re-starting service at ", scalar(localtime), " master-pid=$$\n";
sleep 1;
}
exit 0;
}
if (exists $ENV{CONNECT_SWITCH_PIDFILE}) {
open_pidfile();
}
############################################################################
@ -83,15 +207,29 @@
# CONNECT_SWITCH_VERBOSE
# CONNECT_SWITCH_APPLY_VNC_OFFSET
# CONNECT_SWITCH_VNC_OFFSET
# CONNECT_SWITCH_LISTEN_IPV6
# CONNECT_SWITCH_BUFSIZE
# CONNECT_SWITCH_LOGFILE
# CONNECT_SWITCH_PIDFILE
#
# You can also set these on the cmdline:
# connect_switch CONNECT_SWITCH_LISTEN=X CONNECT_SWITCH_ALLOW_FILE=Y ...
#
# By default we will use hostname and assume it resolves:
#
my $hostname = `hostname`;
chomp $hostname;
my $listen_host = $hostname;
my $listen_port = 443;
# Let user override listening situation, e.g. multihomed:
#
if (exists $ENV{CONNECT_SWITCH_LISTEN}) {
#
# E.g. CONNECT_SWITCH_LISTEN=192.168.0.32:443
#
($listen_host, $listen_port) = split(/:/, $ENV{CONNECT_SWITCH_LISTEN});
}
@ -99,10 +237,21 @@ my $httpd_host = 'localhost';
my $httpd_port = 443;
if (exists $ENV{CONNECT_SWITCH_HTTPD}) {
#
# E.g. CONNECT_SWITCH_HTTPD=127.0.0.1:443
#
($httpd_host, $httpd_port) = split(/:/, $ENV{CONNECT_SWITCH_HTTPD});
}
my $bufsize = 8192;
if (exists $ENV{CONNECT_SWITCH_BUFSIZE}) {
#
# E.g. CONNECT_SWITCH_BUFSIZE=32768
#
$bufsize = $ENV{CONNECT_SWITCH_BUFSIZE};
}
############################################################################
# You can/should override the host/port settings here:
#
@ -113,6 +262,9 @@ if (exists $ENV{CONNECT_SWITCH_HTTPD}) {
# You must set the allowed host:port CONNECT redirection list.
# Only these host:port pairs will be redirected to.
# Port ranges are allowed too: host:5900-5930.
# If there is one entry named ALL all connections are allow.
# You must supply something, default is deny.
#
my @allowed = qw(
machine1:5915
@ -141,6 +293,8 @@ if (exists $ENV{CONNECT_SWITCH_ALLOWED}) {
# fredsbox 15
# rupert 1
# For examply, mine is:
#
my $allow_file = '/dist/apache/2.0/conf/vnc.hosts';
$allow_file = '';
@ -158,25 +312,34 @@ my $apply_vnc_offset = 1;
my $vnc_offset = 5900;
if (exists $ENV{CONNECT_SWITCH_APPLY_VNC_OFFSET}) {
#
# E.g. CONNECT_SWITCH_APPLY_VNC_OFFSET=0
#
$apply_vnc_offset = $ENV{CONNECT_SWITCH_APPLY_VNC_OFFSET};
}
if (exists $ENV{CONNECT_SWITCH_VNC_OFFSET}) {
#
# E.g. CONNECT_SWITCH_VNC_OFFSET=6000
#
$vnc_offset = $ENV{CONNECT_SWITCH_VNC_OFFSET};
}
# Set to 1 for more debugging output:
# Set to 1 or higher for more info output:
#
my $verbose = 0;
if (exists $ENV{CONNECT_SWITCH_VERBOSE}) {
#
# E.g. CONNECT_SWITCH_VERBOSE=1
#
$verbose = $ENV{CONNECT_SWITCH_VERBOSE};
}
############################################################################
#===========================================================================
# No need for any changes below here.
#===========================================================================
use IO::Socket::INET;
use strict;
@ -186,12 +349,29 @@ my $killpid = 1;
setpgrp(0, 0);
my $listen_sock = IO::Socket::INET->new(
Listen => 10,
LocalAddr => $listen_host,
LocalPort => $listen_port,
Proto => "tcp"
);
if (exists $ENV{CONNECT_SWITCH_LISTEN_IPV6}) {
# note we leave out LocalAddr.
my $cmd = '
use IO::Socket::INET6;
$listen_sock = IO::Socket::INET6->new(
Listen => 10,
LocalPort => $listen_port,
ReuseAddr => 1,
Domain => AF_INET6,
Proto => "tcp"
);
';
eval $cmd;
die "$@\n" if $@;
} else {
$listen_sock = IO::Socket::INET->new(
Listen => 10,
LocalAddr => $listen_host,
LocalPort => $listen_port,
ReuseAddr => 1,
Proto => "tcp"
);
}
if (! $listen_sock) {
die "connect_switch: $!\n";
@ -210,7 +390,7 @@ while (1) {
fsleep(0.5);
next;
}
print STDERR "conn: $conn -- ", $client->peerhost(), "\n" if $verbose;
print STDERR "conn: $conn -- ", $client->peerhost(), " at ", scalar(localtime), "\n" if $verbose;
my $pid = fork();
if (! defined $pid) {
@ -237,6 +417,10 @@ sub handle_conn {
my @allow = @allowed;
# read allow file. Note we read it for every connection
# to allow the admin to modify it w/o restarting us.
# better way would be to read in parent and check mtime.
#
if ($allow_file && -f $allow_file) {
if (open(ALLOW, "<$allow_file")) {
while (<ALLOW>) {
@ -259,6 +443,8 @@ sub handle_conn {
}
}
# Read the first 7 bytes of connection, see if it is 'CONNECT'
#
my $str = '';
my $N = 0;
my $isconn = 1;
@ -267,7 +453,7 @@ sub handle_conn {
sysread($client, $b, 1);
$str .= $b;
$N++;
print STDERR "read: '$str'\n" if $verbose;
print STDERR "read: '$str'\n" if $verbose > 1;
my $cstr = substr('CONNECT', 0, $i+1);
if ($str ne $cstr) {
$isconn = 0;
@ -276,28 +462,60 @@ sub handle_conn {
}
my $sock = '';
if ($isconn) {
# it is CONNECT, read rest of HTTP header:
#
while ($str !~ /\r\n\r\n/) {
my $b;
sysread($client, $b, 1);
$str .= $b;
}
print STDERR "read: $str\n" if $verbose;
print STDERR "read: $str\n" if $verbose > 1;
# get http version and host:port
#
my $ok = 0;
my $hostport = '';
my $http_vers = '1.0';
if ($str =~ /^CONNECT\s+(\S+)\s+HTTP\/(\S+)/) {
$hostport = $1;
$http_vers = $2;
foreach my $hp (@allow) {
if ($hp eq $hostport) {
$ok = 1;
last;
my ($h, $p) = split(/:/, $hostport);
if ($p =~ /^\d+$/) {
# check allowed host list:
foreach my $hp (@allow) {
if ($hp eq 'ALL') {
$ok = 1;
}
if ($hp eq $hostport) {
$ok = 1;
}
if ($hp =~ /^(.*):(\d+)-(\d+)$/) {
my $ahost = $1;
my $pmin = $2;
my $pmax = $3;
if ($h eq $ahost) {
if ($p >= $pmin && $p <= $pmax) {
$ok = 1;
}
}
}
last if $ok;
}
}
}
my $msg_1 = "HTTP/$http_vers 200 Connection Established\r\n"
. "Proxy-agent: connect_switch v0.2\r\n\r\n";
my $msg_2 = "HTTP/$http_vers 502 Bad Gateway\r\n"
. "Connection: close\r\n\r\n";
if (! $ok) {
# disallowed. drop with message.
#
syswrite($client, $msg_2, length($msg_2));
close $client;
exit 0;
}
@ -312,18 +530,20 @@ sub handle_conn {
Proto => "tcp"
);
my $msg;
# send the connect proxy reply:
#
if ($sock) {
$msg = "HTTP/$http_vers 200 Connection Established\r\n"
. "Proxy-agent: connect_switch v0.2\r\n\r\n";
$msg = $msg_1;
} else {
$msg = "HTTP/$http_vers 502 Bad Gateway\r\n"
. "Connection: close\r\n\r\n";
$msg = $msg_2;
}
syswrite($client, $msg, length($msg));
$str = '';
} else {
print STDERR "connecting to: $httpd_host:$httpd_port\n"
if $verbose;
# otherwise, redirect to apache for normal https:
#
print STDERR "connecting to: $httpd_host:$httpd_port\n" if $verbose;
$sock = IO::Socket::INET->new(
PeerAddr => $httpd_host,
PeerPort => $httpd_port,
@ -336,6 +556,8 @@ sub handle_conn {
die "connect_switch: $!\n";
}
# get ready for xfer phase:
#
$current_fh1 = $client;
$current_fh2 = $sock;
@ -349,6 +571,8 @@ sub handle_conn {
kill 'TERM', $child;
}
} else {
# write those first bytes if not CONNECT:
#
if ($str ne '' && $N > 0) {
syswrite($sock, $str, $N);
}
@ -358,9 +582,9 @@ sub handle_conn {
kill 'TERM', $parent;
}
}
if ($verbose) {
if ($verbose > 1) {
my $dt = time() - $start;
print STDERR "dt\[$$]: $dt\n";
print STDERR "duration\[$$]: $dt seconds. ", scalar(localtime), "\n";
}
exit 0;
}
@ -380,7 +604,7 @@ sub xfer {
while (! $nf) {
$nf = select($ROUT=$RIN, undef, undef, undef);
}
my $len = sysread($in, $buf, 8192);
my $len = sysread($in, $buf, $bufsize);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
print STDERR "connect_switch\[$lab/$conn/$$]: $!\n";
@ -392,7 +616,7 @@ sub xfer {
}
if (0) {
# verbose debugging of data:
# very verbose debugging of data:
syswrite(STDERR , "\n$lab: ", 6);
syswrite(STDERR , $buf, $len);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,400 @@
#!/usr/bin/perl
#
# inet6to4: Act as an ipv6-to-ipv4 relay for tcp applications that
# do not support ipv6.
#
# Usage: inet6to4 <ipv6-listen-port> <ipv4-host:port>
# inet6to4 -r <ipv4-listen-port> <ipv6-host:port>
#
# Examples: inet6to4 5900 localhost:5900
# inet6to4 8080 web1:80
# inet6to4 -r 5900 fe80::217:f2ff:fee6:6f5a%eth0:5900
#
# The -r option reverses the direction of translation (e.g. for ipv4
# clients that need to connect to ipv6 servers.) Reversing is the default
# if this script is named 'inet4to6' (e.g. by a symlink.)
#
# Use Ctrl-C to stop this program.
#
# You can also set env. vars INET6TO4_LOOP=1 or INET6TO4_LOOP=BG
# to have an outer loop restarting this program (BG means do that
# in the background), and INET6TO4_LOGFILE for a log file.
# Also set INET6TO4_VERBOSE to verbosity level and INET6TO4_WAITTIME
# and INET6TO4_PIDFILE (see below.)
#
#-------------------------------------------------------------------------
# Copyright (c) 2010 by Karl J. Runge <runge@karlrunge.com>
#
# inet6to4 is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# inet6to4 is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with inet6to4; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
# or see <http://www.gnu.org/licenses/>.
#-------------------------------------------------------------------------
# Set up logging:
#
if (exists $ENV{INET6TO4_LOGFILE}) {
close STDOUT;
if (!open(STDOUT, ">>$ENV{INET6TO4_LOGFILE}")) {
die "inet6to4: $ENV{INET6TO4_LOGFILE} $!\n";
}
close STDERR;
open(STDERR, ">&STDOUT");
}
select(STDERR); $| = 1;
select(STDOUT); $| = 1;
# interrupt handler:
#
my $looppid = '';
my $pidfile = '';
my $listen_sock = ''; # declared here for get_out()
#
sub get_out {
print STDERR "$_[0]:\t$$ looppid=$looppid\n";
close $listen_sock if $listen_sock;
if ($looppid) {
kill 'TERM', $looppid;
fsleep(0.2);
}
unlink $pidfile if $pidfile;
exit 0;
}
$SIG{INT} = \&get_out;
$SIG{TERM} = \&get_out;
# pidfile:
#
sub open_pidfile {
if (exists $ENV{INET6TO4_PIDFILE}) {
my $pf = $ENV{INET6TO4_PIDFILE};
if (open(PID, ">$pf")) {
print PID "$$\n";
close PID;
$pidfile = $pf;
} else {
print STDERR "could not open pidfile: $pf - $! - continuing...\n";
}
delete $ENV{INET6TO4_PIDFILE};
}
}
####################################################################
# Set INET6TO4_LOOP=1 to have this script create an outer loop
# restarting itself if it ever exits. Set INET6TO4_LOOP=BG to
# do this in the background as a daemon.
if (exists $ENV{INET6TO4_LOOP}) {
my $csl = $ENV{INET6TO4_LOOP};
if ($csl ne 'BG' && $csl ne '1') {
die "inet6to4: invalid INET6TO4_LOOP.\n";
}
if ($csl eq 'BG') {
# go into bg as "daemon":
setpgrp(0, 0);
my $pid = fork();
if (! defined $pid) {
die "inet6to4: $!\n";
} elsif ($pid) {
wait;
exit 0;
}
if (fork) {
exit 0;
}
setpgrp(0, 0);
close STDIN;
if (! $ENV{INET6TO4_LOGFILE}) {
close STDOUT;
close STDERR;
}
}
delete $ENV{INET6TO4_LOOP};
if (exists $ENV{INET6TO4_PIDFILE}) {
open_pidfile();
}
print STDERR "inet6to4: starting service at ", scalar(localtime), " master-pid=$$\n";
while (1) {
$looppid = fork;
if (! defined $looppid) {
sleep 10;
} elsif ($looppid) {
wait;
} else {
exec $0, @ARGV;
exit 1;
}
print STDERR "inet6to4: re-starting service at ", scalar(localtime), " master-pid=$$\n";
sleep 1;
}
exit 0;
}
if (exists $ENV{INET6TO4_PIDFILE}) {
open_pidfile();
}
use IO::Socket::INET6;
use strict;
use warnings;
# some settings:
#
my $verbose = 1; # set to 0 for no messages, 2 for more.
my $killpid = 1; # does kill(2) at end of connection.
my $waittime = 0.25; # time to wait between connections.
my $reverse = 0; # -r switch (or file named inet4to6)
if (exists $ENV{INET6TO4_VERBOSE}) {
$verbose = $ENV{INET6TO4_VERBOSE};
}
if (exists $ENV{INET6TO4_WAITTIME}) {
$waittime = $ENV{INET6TO4_WAITTIME};
}
# process command line args:
if (! @ARGV || $ARGV[0] =~ '^-+h') { # -help
open(ME, "<$0");
while (<ME>) {
last unless /^#/;
next if /usr.bin.perl/;
$_ =~ s/# ?//;
print;
}
exit;
}
if ($ARGV[0] eq '-r') { # -r
shift;
$reverse = 1;
} elsif ($0 =~ /inet4to6$/) {
$reverse = 1;
}
my $listen_port = shift; # ipv6-listen-port
my $connect_to = shift; # ipv4-host:port
die "no listen port or connect-to-host:port\n" if ! $listen_port || ! $connect_to;
# connect to host:
#
my $host = '';
my $port = '';
if ($connect_to =~ /^(.*):(\d+)$/) {
$host = $1;
$port = $2;
}
die "invalid connect-to-host:port\n" if ! $host || ! $port;
setpgrp(0, 0);
# create listening socket:
#
if (!$reverse) {
$listen_sock = IO::Socket::INET6->new(
Listen => 10,
LocalPort => $listen_port,
Domain => AF_INET6,
ReuseAddr => 1,
Proto => "tcp"
);
} else {
$listen_sock = IO::Socket::INET->new(
Listen => 10,
LocalPort => $listen_port,
ReuseAddr => 1,
Proto => "tcp"
);
}
if (! $listen_sock) {
die "inet6to4: $!\n";
}
# for use by the xfer helper processes' interrupt handlers:
#
my $current_fh1 = '';
my $current_fh2 = '';
# connection counter:
#
my $conn = 0;
# loop forever waiting for connections:
#
while (1) {
$conn++;
print STDERR "listening for connection: $conn\n" if $verbose;
my ($client, $ip) = $listen_sock->accept();
if ($client && !$reverse && $port == $listen_port) {
# This happens on Darwin 'tcp46'
if ($client->peerhost() =~ /^::ffff:/) {
print STDERR "closing client we think is actually us: ",
$client->peerhost(), "\n";
close $client;
$client = undef;
}
}
if (! $client) {
# to throttle runaways
fsleep(2 * $waittime);
next;
}
print STDERR "conn: $conn -- ", $client->peerhost(), " at ", scalar(localtime), "\n" if $verbose;
# spawn helper:
#
my $pid = fork();
if (! defined $pid) {
die "inet6to4: $!\n";
} elsif ($pid) {
wait;
# to throttle runaways
fsleep($waittime);
next;
} else {
# this is to avoid zombies:
close $listen_sock;
if (fork) {
exit 0;
}
setpgrp(0, 0);
handle_conn($client);
}
}
exit 0;
sub handle_conn {
my $client = shift;
my $start = time();
print STDERR "connecting to: $host:$port\n" if $verbose;
my $sock = '';
if (!$reverse) {
$sock = IO::Socket::INET->new(
PeerAddr => $host,
PeerPort => $port,
Proto => "tcp"
);
} else {
$sock = IO::Socket::INET6->new(
PeerAddr => $host,
PeerPort => $port,
Domain => AF_INET6,
Proto => "tcp"
);
}
if (! $sock) {
close $client;
die "inet6to4: $!\n";
}
$current_fh1 = $client;
$current_fh2 = $sock;
# interrupt handler:
#
$SIG{TERM} = sub {print STDERR "got sigterm\[$$]\n" if $verbose; close $current_fh1; close $current_fh2; exit 0};
# spawn another helper and transfer the data:
#
my $parent = $$;
if (my $child = fork()) {
xfer($sock, $client, 'S->C');
if ($killpid) {
fsleep(0.5);
kill 'TERM', $child;
}
} else {
xfer($client, $sock, 'C->S');
if ($killpid) {
fsleep(0.75);
kill 'TERM', $parent;
}
}
# done.
#
if ($verbose > 1) {
my $dt = time() - $start;
print STDERR "dt\[$$]: $dt\n";
}
exit 0;
}
# transfers data in one direction:
#
sub xfer {
my($in, $out, $lab) = @_;
my ($RIN, $WIN, $EIN, $ROUT);
$RIN = $WIN = $EIN = "";
$ROUT = "";
vec($RIN, fileno($in), 1) = 1;
vec($WIN, fileno($in), 1) = 1;
$EIN = $RIN | $WIN;
my $buf;
while (1) {
my $nf = 0;
while (! $nf) {
$nf = select($ROUT=$RIN, undef, undef, undef);
}
my $len = sysread($in, $buf, 8192);
if (! defined($len)) {
next if $! =~ /^Interrupted/;
print STDERR "inet6to4\[$lab/$conn/$$]: $!\n";
last;
} elsif ($len == 0) {
print STDERR "inet6to4\[$lab/$conn/$$]: "
. "Input is EOF.\n";
last;
}
if ($verbose > 4) {
# verbose debugging of data:
syswrite(STDERR , "\n$lab: ", 6);
syswrite(STDERR , $buf, $len);
}
my $offset = 0;
my $quit = 0;
while ($len) {
my $written = syswrite($out, $buf, $len, $offset);
if (! defined $written) {
print STDERR "inet6to4\[$lab/$conn/$$]: "
. "Output is EOF. $!\n";
$quit = 1;
last;
}
$len -= $written;
$offset += $written;
}
last if $quit;
}
close($in);
close($out);
}
# sleep a fraction of a second:
#
sub fsleep {
my ($time) = @_;
select(undef, undef, undef, $time) if $time;
}

@ -0,0 +1,117 @@
#!/usr/bin/perl
#
# panner.pl: start up x11vnc in '-clip' mode viewing a small (WxH)
# rectangular region of the screen. Allow the viewer user
# to 'pan' around the display region by moving the mouse.
#
# Remote interaction with applications, e.g. clicking a
# button though the VNC viewer, will be very difficult.
# This may be useful in a 'demo' mode where the user sitting
# at the physical display is the only one moving the mouse.
# Depending on your usage the following x11vnc options may
# be useful: -nonap
#
# Usage: panner.pl WxH <x11vnc-args> (e.g. -display ...)
# or panner.pl WxH:0.05 <x11vnc-args> (e.g. 0.05 is polling time in secs.)
use strict;
my $WxH = shift;
my $poll_time;
# split off poll time:
#
($WxH, $poll_time) = split(/:/, $WxH);
my ($W, $H) = split(/x/, $WxH);
$poll_time = 0.1 unless $poll_time ne '';
# set to x11vnc command (e.g. full PATH)
#
my $x11vnc = "x11vnc";
# check if display was given:
#
my $query_args = "";
for (my $i=0; $i < @ARGV; $i++) {
if ($ARGV[$i] eq '-display') {
$query_args = "-display $ARGV[$i+1]";
}
}
# find the size of display and the current mouse position:
my %v;
vset("DIRECT:wdpy_x,wdpy_y,pointer_x,pointer_y,pointer_same");
# set a -clip argument based on the above:
#
my $clip = '';
clip_set();
$clip = "${W}x${H}+0+0" unless $v{pointer_same};
# launch x11vnc with -clip in the background:
#
my $cmd = "$x11vnc -clip $clip -bg " . join(" ", @ARGV);
print STDERR "running: $cmd\n";
system $cmd;
# user can hit Ctrl-C or kill this script to quit (and stop x11vnc)
#
sub quit {
system("$x11vnc $query_args -R stop");
exit 0;
}
$SIG{INT} = \&quit;
$SIG{TERM} = \&quit;
# loop forever waiting for mouse position to change, then shift -clip:
#
my $clip_old = $clip;
while (1) {
fsleep($poll_time);
vset("pointer_x,pointer_y,pointer_same");
next unless $v{pointer_same};
clip_set();
if ($clip ne $clip_old) {
system("$x11vnc $query_args -R clip:$clip");
$clip_old = $clip
}
}
exit 0;
# short sleep:
#
sub fsleep {
my ($time) = @_;
select(undef, undef, undef, $time) if $time;
}
# set the -clip string, making sure view doesn't go off edges of display:
#
sub clip_set {
my $x = int($v{pointer_x} - $W/2);
my $y = int($v{pointer_y} - $H/2);
$x = 0 if $x < 0;
$y = 0 if $y < 0;
$x = $v{wdpy_x} - $W if $x + $W > $v{wdpy_x};
$y = $v{wdpy_y} - $H if $y + $H > $v{wdpy_y};
$clip = "${W}x${H}+$x+$y";
}
# query x11vnc for values, put results in the %v hash:
#
sub vset {
my $str = shift;
my $out = `$x11vnc $query_args -Q $str 2>/dev/null`;
chomp $out;
foreach my $pair (split(/,/, $out)) {
$pair =~ s/^a..=//;
my ($k, $v) = split(/:/, $pair, 2);
if ($k ne '' && $v ne '') {
print STDERR "k=$k v=$v\n" if $ENV{DEBUG};
$v{$k} = $v;
}
}
}

@ -1,6 +1,6 @@
#!/usr/bin/env perl
#
# Copyright (c) 2009 by Karl J. Runge <runge@karlrunge.com>
# Copyright (c) 2009-2010 by Karl J. Runge <runge@karlrunge.com>
#
# ultravnc_repeater.pl is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -41,17 +41,137 @@ usage: ultravnc_repeater.pl [-r] [client_port [server_port]]
Use -r to refuse new server/client connections with an existing
server/client ID. The default is to close the previous one.
To write to a log file set the env. var ULTRAVNC_REPEATER_LOGFILE.
To run in a loop restarting the server if it exits set the env. var.
ULTRAVNC_REPEATER_LOOP=1 or ULTRAVNC_REPEATER_LOOP=BG, the latter
forks into the background. Set ULTRAVNC_REPEATER_PIDFILE to a file
to store the master pid in.
Examples:
ultravnc_repeater.pl
ultravnc_repeater.pl -r
ultravnc_repeater.pl 5901
ultravnc_repeater.pl 5901 5501
env ULTRAVNC_REPEATER_LOOP=BG ULTRAVNC_REPEATER_LOGFILE=/tmp/u.log ultravnc_repeater.pl ...
';
use warnings;
use strict;
# Set up logging:
#
if (exists $ENV{ULTRAVNC_REPEATER_LOGFILE}) {
close STDOUT;
if (!open(STDOUT, ">>$ENV{ULTRAVNC_REPEATER_LOGFILE}")) {
die "ultravnc_repeater.pl: $ENV{ULTRAVNC_REPEATER_LOGFILE} $!\n";
}
close STDERR;
open(STDERR, ">&STDOUT");
}
select(STDERR); $| = 1;
select(STDOUT); $| = 1;
# interrupt handler:
#
my $looppid = '';
my $pidfile = '';
#
sub get_out {
print STDERR "$_[0]:\t$$ looppid=$looppid\n";
if ($looppid) {
kill 'TERM', $looppid;
fsleep(0.2);
}
unlink $pidfile if $pidfile;
cleanup();
exit 0;
}
# These are overridden in actual server thread:
#
$SIG{INT} = \&get_out;
$SIG{TERM} = \&get_out;
# pidfile:
#
sub open_pidfile {
if (exists $ENV{ULTRAVNC_REPEATER_PIDFILE}) {
my $pf = $ENV{ULTRAVNC_REPEATER_PIDFILE};
if (open(PID, ">$pf")) {
print PID "$$\n";
close PID;
$pidfile = $pf;
} else {
print STDERR "could not open pidfile: $pf - $! - continuing...\n";
}
delete $ENV{ULTRAVNC_REPEATER_PIDFILE};
}
}
####################################################################
# Set ULTRAVNC_REPEATER_LOOP=1 to have this script create an outer loop
# restarting itself if it ever exits. Set ULTRAVNC_REPEATER_LOOP=BG to
# do this in the background as a daemon.
if (exists $ENV{ULTRAVNC_REPEATER_LOOP}) {
my $csl = $ENV{ULTRAVNC_REPEATER_LOOP};
if ($csl ne 'BG' && $csl ne '1') {
die "ultravnc_repeater.pl: invalid ULTRAVNC_REPEATER_LOOP.\n";
}
if ($csl eq 'BG') {
# go into bg as "daemon":
setpgrp(0, 0);
my $pid = fork();
if (! defined $pid) {
die "ultravnc_repeater.pl: $!\n";
} elsif ($pid) {
wait;
exit 0;
}
if (fork) {
exit 0;
}
setpgrp(0, 0);
close STDIN;
if (! $ENV{ULTRAVNC_REPEATER_LOGFILE}) {
close STDOUT;
close STDERR;
}
}
delete $ENV{ULTRAVNC_REPEATER_LOOP};
if (exists $ENV{ULTRAVNC_REPEATER_PIDFILE}) {
open_pidfile();
}
print STDERR "ultravnc_repeater.pl: starting service at ", scalar(localtime), " master-pid=$$\n";
while (1) {
$looppid = fork;
if (! defined $looppid) {
sleep 10;
} elsif ($looppid) {
wait;
} else {
exec $0, @ARGV;
exit 1;
}
print STDERR "ultravnc_repeater.pl: re-starting service at ", scalar(localtime), " master-pid=$$\n";
sleep 1;
}
exit 0;
}
if (exists $ENV{ULTRAVNC_REPEATER_PIDFILE}) {
open_pidfile();
}
# End of background/daemon stuff.
####################################################################
use warnings;
use IO::Socket::INET;
use IO::Select;
@ -85,6 +205,7 @@ my ($RIN, $WIN, $EIN, $ROUT);
my $client_listen = IO::Socket::INET->new(
Listen => 10,
LocalPort => $client_port,
ReuseAddr => 1,
Proto => "tcp"
);
if (! $client_listen) {
@ -95,6 +216,7 @@ if (! $client_listen) {
my $server_listen = IO::Socket::INET->new(
Listen => 10,
LocalPort => $server_port,
ReuseAddr => 1,
Proto => "tcp"
);
if (! $server_listen) {
@ -103,7 +225,7 @@ if (! $server_listen) {
}
my $select = new IO::Select();
if (! select) {
if (! $select) {
cleanup();
die "$prog: select $!\n";
}