#
# usage:
# udptunnel
-# <public-local-host/addr>,<public-local-port>
-# <public-remote-host/addr>,<public-remote-port>
+# [ -l[<local-command/arg>] ... .
+# -e<encryption-mech>[/<encryption-parameter>...]
+# ...
+# ]
+# <public-local-addr>,<public-local-port>
+# <public-remote-addr>,<public-remote-port>
# <private-local-addr>,<private-remote-addr>,<mtu>,<proto>
# <keepalive>,<timeout>
# <extra-local-nets> <extra-remote-nets>
# [ <remote-command> [<remote-args> ...] ]
#
+#
+# <..-addr> may also be hostname
+#
# <local-public-port> may be number or `print' or `silent'
#
# <remote-public-port> may number or `command', in which case
# <remote-command> must be specified and should run udptunnel at the
# remote end; it will be invoked as
-# <remote-command> <public-remote-host/addr>,print
+# <remote-command> <public-remote-addr>,print
# <public-local-addr>,<public-local-port>
# <private-remote-addr>,<private-local-addr>,<mtu>,<proto>
# <keepalive>,<timeout>
# udptunnel will userv ipif locally, as
# userv root ipif <private-local-addr>,<private-remote-addr>,<mtu>,<proto>
# <extra-local-nets>
+# or, if -l was given, userv root ipif is replaced with the argument(s) to
+# successive -l options.
+
+# Copyright (C) 1999 Ian Jackson
+#
+# This 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.
+#
+# This program 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 userv-utils; if not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
use Socket;
use POSIX;
sub eat_addr_port ($) {
my ($x) = @_;
- @ARGV or quit("<host/addr>,<port> missing");
+ @ARGV or quit("<addr>,<port> missing");
$_= shift(@ARGV);
$_ =~ m/^([^,]+)\,(\d+|$x)$/ or quit("$_: <host/addr>,<port> bad syntax");
return ($1,$2);
return inet_ntoa($s[1]).','.$s[0];
}
+@lcmd= ();
+
+while ($ARGV[0] =~ m/^-/) {
+ $_= shift @ARGV;
+ last if $_ eq '--';
+ if (s/^-l//) {
+ push @lcmd,$_ if length;
+ while (@ARGV && ($_= shift @ARGV) ne '.') { push @lcmd, $_; }
+ } else {
+ quit("unknown option \`$_'");
+ }
+}
+
($las,$lps)= eat_addr_port('print|silent');
$la= conv_host_addr($las);
$lp= conv_port_number($lps);
if ($lps eq 'print') { print($lsp,"\n") or quit("write port to stdout: $!"); }
+@lcmd= qw(userv root ipif) unless @lcmd;
+
debug("using remote $rsp local $lsp");
+push @lcmd, ("$lva,$rva,$mtu,$proto",$lepn);
+debug("local command @lcmd");
pipe(UR,UW) or fail("up pipe");
pipe(DR,DW) or fail("down pipe");
close UR; close DW;
open(STDIN,"<&DR") or fail("reopen stdin for packets");
open(STDOUT,">&UW") or fail("reopen stdout for packets");
- exec "userv","root","ipif","$lva,$rva,$mtu,$proto",$lepn;
- quit("cannot execute userv ipif: $!");
+ exec @lcmd;
+ quit("cannot execute $lcmd[0]: $!");
}
close UW;
close DR;
quit "tunnel endpoint closed by system";
}
while (($p= index($upbuf,"\300")) >= 0) {
- if (!defined(send L,substr($upbuf,0,$p+1),0,$rs)) {
+ if ($p && !defined(send L,substr($upbuf,0,$p),0,$rs)) {
warning("transmit error: $!");
} else {
if (!$upyet) {
warning("got packet from incorrect peer $rsp_from");
next;
}
+ $downbuf= "\300".$downbuf."\300";
if (!defined($r= syswrite(DW,$downbuf,length $downbuf))) {
warning("tunnel endpoint write error: $!");
} elsif ($r != length $downbuf) {
alarm($timeout) if $timeout;
}
}
+ if ($! == ECONNREFUSED) { quit("tunnel closed at remote end"); }
$! == EAGAIN || warning("receive error: $!");
}