X-Git-Url: https://git.distorted.org.uk/~mdw/userv-utils/blobdiff_plain/09966b4959fa31ea3f6746b6b6583907744484e1..7729298ad653ba4e0b10bacc9f27d210b4eaf4e7:/ipif/udptunnel?ds=sidebyside diff --git a/ipif/udptunnel b/ipif/udptunnel index 08b75a3..09595d1 100755 --- a/ipif/udptunnel +++ b/ipif/udptunnel @@ -1,6 +1,10 @@ #!/usr/bin/perl # Simple tunnel for userv-ipif tunnels. # +# Example test invocation +# +# ./udptunnel -e nonce -e timestamp/10/30 -e pkcs5/8 -e blowfish-cbcmac/128 -e blowfish-cbc/128 -m -f ./udptunnel-forwarder davenant,Any anarres,Command 172.30.206.1,172.30.206.2,1000,cslip 15,70 '' '' rsh anarres things/userv-utils/ipif/udptunnel -f things/userv-utils/ipif/udptunnel-forwarder +# # usage: # udptunnel # [ -l[] ... . @@ -15,8 +19,8 @@ # , # , # ,,, -# , -# +# ,[,] +# # [ [ ...] ] # # proto may be slip or cslip @@ -37,8 +41,8 @@ # , # , # ,,, -# , -# +# ,[,] +# # # If it was given Print for , this command's first @@ -63,12 +67,13 @@ # # (-m not specified) (-m specified) # actual addr/port that addr/port `Wait' -# `Wait' the chosen address `Wait' # `Print' the chosen address `Wait' +# `Any' `Wait' for addr, `Wait' +# chosen port for port # # udptunnel will userv ipif locally, as # userv root ipif ,,, -# +# # or, if -l was given, userv root ipif is replaced with the argument(s) # following -l option(s) until `.'. # @@ -159,15 +164,13 @@ sub show_addr_port ($) { return show_addr($s).','.show_port($s); } sub arg_value ($$) { - my ($val,$opt); + my ($val,$opt) = @_; $_= '-'; return $val if length $val; @ARGV or quit("$opt needs value"); return shift @ARGV; } -$|=1; - @lcmd= (); @encryption= (); $masq= 0; @@ -187,14 +190,17 @@ while ($ARGV[0] =~ m/^-/) { $fcmd= arg_value($_,'-f'); } elsif (s/^-e//) { $encrarg= arg_value($_,'-e'); - push @encrargs, "-e$encrarg"; - push @encryption, split m#/#, $encrarg; + push @remoteopts, "-e$encrarg"; + @thisencryption= split m#/#, $encrarg; + $thisencryption[0] =~ s/^/\|/; + push @encryption, @thisencryption; } elsif (s/^-m/-/) { $masq= 1; } elsif (s/^-d/-/) { $dump= 1; } elsif (s/^-Dcrypto$/-/) { $xfwdopts.= 'K'; + push @remoteopts, '-Dcrypto'; } else { quit("unknown option \`$_'"); } @@ -221,8 +227,16 @@ m/^([.0-9]+),([.0-9]+),(\d+),(slip|cslip)$/ ($lva,$rva,$mtu,$proto) = ($1,$2,$3,$4); $_= shift @ARGV; -m/^(\d+),(\d+)$/ or quit("keepalive,timeout missing or bad syntax"); -($keepalive,$timeout)= ($1,$2); +if (m/^(\d+),(\d+)$/) { + ($keepalive,$timeout,$reannounce)= ($1+0,$2+0,0); + $ka_to_ra= "$keepalive,$timeout"; +} elsif (m/^(\d+),(\d+),(\d+)$/) { + ($keepalive,$timeout,$reannounce)= ($1+0,$2+0,$3); + "$keepalive,$timeout", + $ka_to_ra= "$keepalive,$timeout,$reannounce"; +} else { + quit("keepalive,timeout missing or bad syntax"); +} $keepalive && ($timeout > $keepalive*2) or quit("timeout must be < 2*keepalive") if $timeout; @@ -259,22 +273,21 @@ if (@ARGV) { $rad= xform_remote(show_addr($rs),$ras); $rpd= xform_remote(show_port($rs),$rps); @rcmd= (@ARGV, - @encrargs, + @remoteopts, "$rad,$rpd", - $masq ? 'Wait,Wait' : $lapd, + $masq ? 'Wait,Wait' : $las eq 'Any' ? "Wait,$lpd" : $lapd, "$rva,$lva,$mtu,$proto", - "$keepalive,$timeout", + $ka_to_ra, $rexn, $lexn); debug("remote command @rcmd"); if ($rapcmd) { pipe(RAPREAD,RCMDREADSUB) or fail("pipe"); - select(RCMDREADSUB); $|=1; select(STDOUT); } - pipe(DUMPKEYS,RCMDWRITESUB) or fail("pipe"); + pipe(RCMDWRITESUB,DUMPKEYS) or fail("pipe"); defined($c_rcmd= fork) or fail("fork for remote"); if (!$c_rcmd) { - open STDIN, ">&RCMDWRITESUB" or fail("reopen stdin for remote command"); + open STDIN, "<&RCMDWRITESUB" or fail("reopen stdin for remote command"); open STDOUT, ">&RCMDREADSUB" or fail("reopen stdout for remote command") if $rapcmd; close RAPREAD if $rapcmd; @@ -288,30 +301,33 @@ if (@ARGV) { if ($rapcmd) { close RCMDREADSUB if $rapcmd; - $!=0; $_= ; $e="$!"; + $_= ''; + while (!m/\n/) { + $!=0; + defined($nread= sysread(RAPREAD,$_,1,length)) + or fail("read from remote command"); + if (!$nread) { + close DUMPKEYS; + close RAPREAD; + waitpid $c_rcmd,0 or fail("wait for remote command"); + quit($? ? "remote command failed (code $?)" : + "no details received from remote"); + } + } + chomp; + m/^([.0-9]+)\,(\d+)$/ or quit("invalid details from remote end: \`$_'"); + ($rar,$rpr) = ($1,$2); + $ra= conv_host_addr($rar); + $rp= conv_port_number($rpr); defined($c_catremdebug= fork) or fail("fork for cat remote debug"); if (!$c_catremdebug) { open(STDIN,"<&RAPREAD") or fail("redirect remote debug"); - close RAPREAD; close DUMPKEYS; close L; exec "cat"; fail("execute cat"); } close RAPREAD; - - if (!length) { - close DUMPKEYS; - waitpid $c_rcmd,0 or fail("wait for remote command"); - quit($? ? "remote command failed (code $?)" : - $e ? "read error from remote command: $e" : - "no details received from remote"); - } - chomp; - m/^([.0-9]+)\,(\d+)$/ or quit("invalid details from remote end: \`$_'"); - ($rar,$rpr) = ($1,$2); - $ra= conv_host_addr($rar); - $rp= conv_port_number($rpr); } } elsif ($dump) { open DUMPKEYS, ">&STDOUT" or fail("reopen stdout for key material"); @@ -353,14 +369,14 @@ $xfwdopts.= 'w' if $dump; @fcmd= ($fcmd, $xfwdopts, fileno(L), fileno(DW), fileno(UR), fileno(DUMPKEYS), - $mtu, $keepalive, $timeout, + $mtu, $keepalive, $timeout, $reannounce, @rapf, @encryption); debug("forwarding command @fcmd."); defined($c_fwd= fork) or fail("fork for udptunnel-forwarder"); if (!$c_fwd) { - foreach $fd (qw(L DW UR)) { + foreach $fd (qw(L DW UR DUMPKEYS)) { fcntl($fd, F_SETFD, 0) or fail("set no-close-on-exec $fd"); } exec @fcmd; fail("cannot execute $fcmd[0]"); @@ -381,11 +397,12 @@ $estatus= 0; while (keys %procs) { ($c= wait) >0 or fail("wait failed (expecting ". join('; ',keys %procs). ")"); - warning("unexpected child reaped: pid $c, code $?"), next + $status= $?; + warning("unexpected child reaped: pid $c, code $status"), next unless exists $procs{$c}; $str= $procs{$c}; delete $procs{$c}; - $? ? warning("subprocess $str failed with code $?") + $status ? warning("subprocess $str failed with code $status") : debug("subprocess $str finished"); if ($c==$c_lcmd || $c==$c_fwd || $c==$c_rcmd) { kill 15, grep (exists $procs{$_}, $c_fwd, $c_rcmd);