1*f8f8530cSbluhm# $OpenBSD: Remote.pm,v 1.7 2016/05/03 19:13:04 bluhm Exp $ 2bf5ac567Sbluhm 3aa8f1300Sbluhm# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> 4bf5ac567Sbluhm# 5bf5ac567Sbluhm# Permission to use, copy, modify, and distribute this software for any 6bf5ac567Sbluhm# purpose with or without fee is hereby granted, provided that the above 7bf5ac567Sbluhm# copyright notice and this permission notice appear in all copies. 8bf5ac567Sbluhm# 9bf5ac567Sbluhm# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10bf5ac567Sbluhm# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11bf5ac567Sbluhm# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12bf5ac567Sbluhm# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13bf5ac567Sbluhm# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14bf5ac567Sbluhm# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15bf5ac567Sbluhm# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16bf5ac567Sbluhm 17bf5ac567Sbluhmuse strict; 18bf5ac567Sbluhmuse warnings; 19bf5ac567Sbluhm 20bf5ac567Sbluhmpackage Remote; 21bf5ac567Sbluhmuse parent 'Proc'; 22bf5ac567Sbluhmuse Carp; 23bf5ac567Sbluhmuse Cwd; 24bf5ac567Sbluhmuse File::Basename; 25bf5ac567Sbluhm 26bf5ac567Sbluhmmy %PIPES; 27bf5ac567Sbluhm 28bf5ac567Sbluhmsub close_pipes { 29bf5ac567Sbluhm my @pipes = @_ ? @_ : keys %PIPES 30bf5ac567Sbluhm or return; 31bf5ac567Sbluhm foreach (@pipes) { 32bf5ac567Sbluhm # file descriptor cannot be a hash key, so use hash value 33bf5ac567Sbluhm my $fh = $PIPES{$_}; 34bf5ac567Sbluhm # also print new line as close is delayed by forked processes 35bf5ac567Sbluhm print $fh "close\n"; 36bf5ac567Sbluhm close($fh); 37bf5ac567Sbluhm } 38bf5ac567Sbluhm sleep 1; # give other end a chance to finish process 39bf5ac567Sbluhm delete @PIPES{@pipes}; 40bf5ac567Sbluhm} 41bf5ac567Sbluhm 42bf5ac567SbluhmEND { 43bf5ac567Sbluhm close_pipes(); 44bf5ac567Sbluhm} 45bf5ac567Sbluhm 46bf5ac567Sbluhmsub new { 47bf5ac567Sbluhm my $class = shift; 48bf5ac567Sbluhm my %args = @_; 49bf5ac567Sbluhm $args{logfile} ||= "remote.log"; 50aa8f1300Sbluhm $args{up} ||= "listen sock: "; 5170a792e0Sbluhm $args{down} ||= $args{dryrun} ? "relayd.conf" : "parent terminating"; 52bf5ac567Sbluhm $args{func} = sub { Carp::confess "$class func may not be called" }; 53bf5ac567Sbluhm $args{remotessh} 54bf5ac567Sbluhm or croak "$class remote ssh host not given"; 55bf5ac567Sbluhm $args{forward} 56bf5ac567Sbluhm or croak "$class forward not given"; 57bf5ac567Sbluhm my $self = Proc::new($class, %args); 58bf5ac567Sbluhm $self->{listenaddr} 59bf5ac567Sbluhm or croak "$class listen addr not given"; 60bf5ac567Sbluhm $self->{connectaddr} 61bf5ac567Sbluhm or croak "$class connect addr not given"; 62bf5ac567Sbluhm $self->{connectport} 63bf5ac567Sbluhm or croak "$class connect port not given"; 64bf5ac567Sbluhm return $self; 65bf5ac567Sbluhm} 66bf5ac567Sbluhm 67bf5ac567Sbluhmsub run { 68bf5ac567Sbluhm my $self = Proc::run(shift, @_); 69bf5ac567Sbluhm $PIPES{$self->{pipe}} = $self->{pipe}; 70bf5ac567Sbluhm return $self; 71bf5ac567Sbluhm} 72bf5ac567Sbluhm 73bf5ac567Sbluhmsub up { 74bf5ac567Sbluhm my $self = Proc::up(shift, @_); 75aa8f1300Sbluhm my $lsock = $self->loggrep(qr/^listen sock: /) 76aa8f1300Sbluhm or croak ref($self), " no 'listen sock: ' in $self->{logfile}"; 77bf5ac567Sbluhm my($addr, $port) = $lsock =~ /: (\S+) (\S+)$/ 78bf5ac567Sbluhm or croak ref($self), " no listen addr and port in $self->{logfile}"; 79bf5ac567Sbluhm $self->{listenaddr} = $addr; 80bf5ac567Sbluhm $self->{listenport} = $port; 81bf5ac567Sbluhm return $self; 82bf5ac567Sbluhm} 83bf5ac567Sbluhm 84bf5ac567Sbluhmsub child { 85bf5ac567Sbluhm my $self = shift; 86d20a5ce9Sbluhm 87*f8f8530cSbluhm my @opts = $ENV{SSH_OPTIONS} ? split(' ', $ENV{SSH_OPTIONS}) : (); 88bf5ac567Sbluhm my @sudo = $ENV{SUDO} ? "SUDO=$ENV{SUDO}" : (); 89bf5ac567Sbluhm my @ktrace = $ENV{KTRACE} ? "KTRACE=$ENV{KTRACE}" : (); 90bf5ac567Sbluhm my @relayd = $ENV{RELAYD} ? "RELAYD=$ENV{RELAYD}" : (); 91d20a5ce9Sbluhm my $dir = dirname($0); 92d20a5ce9Sbluhm $dir = getcwd() if ! $dir || $dir eq "."; 93aa8f1300Sbluhm my @cmd = ("ssh", @opts, $self->{remotessh}, 94aa8f1300Sbluhm @sudo, @ktrace, @relayd, "perl", 95d20a5ce9Sbluhm "-I", $dir, "$dir/".basename($0), $self->{forward}, 96bf5ac567Sbluhm $self->{listenaddr}, $self->{connectaddr}, $self->{connectport}, 97d20a5ce9Sbluhm ($self->{testfile} ? "$dir/".basename($self->{testfile}) : ())); 98bf5ac567Sbluhm print STDERR "execute: @cmd\n"; 99bf5ac567Sbluhm exec @cmd; 100aa8f1300Sbluhm die ref($self), " exec '@cmd' failed: $!"; 101bf5ac567Sbluhm} 102bf5ac567Sbluhm 103bf5ac567Sbluhmsub close_child { 104bf5ac567Sbluhm my $self = shift; 105bf5ac567Sbluhm close_pipes(delete $self->{pipe}); 106bf5ac567Sbluhm return $self; 107bf5ac567Sbluhm} 108bf5ac567Sbluhm 109bf5ac567Sbluhm1; 110