X-Git-Url: https://git.distorted.org.uk/~mdw/userv-utils/blobdiff_plain/33b946d92ffbe495aee70d8a49d3314975494a63..caa68336fa6c005906fd0f88e444ce6a350cfa79:/ipif/udptunnel diff --git a/ipif/udptunnel b/ipif/udptunnel index dff18ed..e4ce450 100755 --- a/ipif/udptunnel +++ b/ipif/udptunnel @@ -3,6 +3,7 @@ # # usage: # udptunnel +# [ -l[] ... . ] # , # , # ,,, @@ -24,6 +25,26 @@ # udptunnel will userv ipif locally, as # userv root ipif ,,, # +# or, if -lc was given, userv root ipif is replaced with the argument(s) to +# successive -lc 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; @@ -68,6 +89,19 @@ sub show_addr_port ($) { 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); @@ -134,7 +168,11 @@ $rsp= show_addr_port($rs); 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"); @@ -144,8 +182,8 @@ if (!$c3) { 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; @@ -175,17 +213,17 @@ if ($keepalive) { $nextsendka= now(); } for (;;) { if ($keepalive) { $now= now(); - $timeout= $nextsendka-$now; - if ($timeout < 0) { + $thistimeout= $nextsendka-$now; + if ($thistimeout < 0) { defined(send L,"\300",0,$rs) or warning("transmit keepalive error: $!"); $nextsendka= $now+$keepalive; - $timeout= $keepalive; + $thistimeout= $keepalive; } } else { - $timeout= undef; + $thistimeout= undef; } - select($readfds=$wantreadfds,'','',$timeout); + select($readfds=$wantreadfds,'','',$thistimeout); for (;;) { if (!defined($r= sysread(UR,$upbuf,$mtu*2+3,length($upbuf)))) { $! == EAGAIN || warning("tunnel endpoint read error: $!"); @@ -195,13 +233,16 @@ for (;;) { quit "tunnel endpoint closed by system"; } while (($p= index($upbuf,"\300")) >= 0) { - if (!defined(send L,substr($upbuf,0,$p),0,$rs)) { + if ($p && !defined(send L,substr($upbuf,0,$p),0,$rs)) { warning("transmit error: $!"); - } elsif (!$upyet) { - $upyet= 1; - debug($downyet ? "tunnel open at this end" : "transmit channel open"); + } else { + if (!$upyet) { + $upyet= 1; + debug($downyet ? "tunnel open at this end" : "transmitting"); + } + if ($keepalive) { $nextsendka= now()+$keepalive; } } - $upbuf= substr($upbuf+1,$p); + $upbuf= substr($upbuf,$p+1); } } while (defined($rs_from= recv L,$downbuf,$mtu*2+3,0)) { @@ -210,6 +251,7 @@ for (;;) { 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) { @@ -217,10 +259,11 @@ for (;;) { } else { if (!$downyet) { $downyet= 1; - debug($upyet ? "tunnel open at this end" : "receive channel open"); + debug($upyet ? "tunnel open at this end" : "receiving"); } alarm($timeout) if $timeout; } } + if ($! == ECONNREFUSED) { quit("tunnel closed at remote end"); } $! == EAGAIN || warning("receive error: $!"); }