App-ReslirpTunnel

 view release on metacpan or  search on metacpan

lib/App/ReslirpTunnel.pm  view on Meta::CPAN

    return if $self->{run_in_foreground};

    $self->_log(info => "Moving to background");
    POSIX::setsid();

    my $pid = fork // $self->_die("Unable to move process into the background", $!);
    if ($pid == 0) {
        $SIG{INT} = $self->{signal_handler};
        $SIG{TERM} = $self->{signal_handler};

        unless ($self->{dont_close_stdio}) {
            open STDIN, '<', '/dev/null';
            open STDOUT, '>', '/dev/null';
            open STDERR, '>', '/dev/null' unless $self->{log_to_stderr};
        }

        $self->{log_prefix} = "ReslirpTunnel::Child";

        return 1; # Return in the child!!!
    }
    else {
        eval {
            syswrite STDERR, "$0 moved to background, PID: $pid\n";
            $self->_log(debug => "First process exiting");
        };

        POSIX::_exit(0);
    }
}

sub _init_ssh {
    my $self = shift;
    my $host = $self->{ssh_host} // $self->_die("No remote host specified");
    my $port = $self->{ssh_port};
    my $user = $self->{ssh_user};
    my $cmd = $self->{args}{ssh_command};
    my $more_args = $self->{args}{more_ssh_args};
    my @args = (host => $host);
    push @args, (port => $port) if defined $port;
    push @args, (user => $user) if defined $user;
    push @args, (ssh_cmd => $cmd) if defined $cmd;
    push @args, (master_opts => $more_args) if defined $more_args;
    $self->{ssh} = my $ssh = Net::OpenSSH->new(@args);
    $ssh->error and
         $self->_die("Unable to connect to remote host", $ssh->error);
    $self->{remote_os} = $self->{args}{remote_os} // $self->_autodetect_remote_os //
        $self->_die("No remote OS specified and unable to autodetect it");
    $self->{remote_shell} = $self->{args}{remote_shell} // $self->_autodetect_remote_shell //
        $self->_die("No remote shell specified and unable to autodetect it");

    $self->{quoting_backend} = (($self->{remote_shell} eq 'windows') ? 'MSWin' : 'ksh');
    my $ssh_master_pid = $self->{ssh}->get_master_pid;
    $self->_log(debug => "SSH master PID", $ssh_master_pid);
    $self->{ssh_master_pid} = $ssh_master_pid;
}

sub _autodetect_remote_os {
    my $self = shift;
    my $ssh = $self->{ssh};
    my $out = $ssh->capture('echo %COMSPEC%');
    my $looks_like_unix = $out =~ /^\%COMSPEC\%$/m;
    if ($looks_like_unix) {
        $self->_log(debug => "Looks like a Unix-like system, let's check it further...");
        my $uname = lc $ssh->capture('uname -s');
        if ($uname =~ /^(Linux|Darwin|FreeBSD|OpenBSD|NetBSD|DragonFly|MidnightBSD|AIX|HP-UX|SunOS|IRIX|OSF1|SCO_SV|QNX)$/i) {
            $self->_log(info => "Remote OS identified as Linux/UNIX ($1)");
            return 'unix';
        }
    }
    else {
        $self->_log(debug => "Looks like Windows, let's check it further...");
        my $ver = $ssh->capture('ver');
        if ($ver =~ /^(Microsoft Windows \[Version.*\])/m) {
            $self->_log(info => "Remote OS identified as Windows ($1)");
            return 'windows';
        }
    }
    $self->_warn("Unable to autodetect remote OS");
    return;
}

sub _autodetect_remote_shell {
    my $self = shift;
    if ($self->{remote_os} eq 'windows') {
        return $self->{remote_shell} = 'windows';
    }
    my $ssh = $self->{ssh};
    my $out = $ssh->capture('echo $SHELL') or return "sh";
    chomp($out);
    return Path::Tiny->new($out)->basename;
}

sub _init_tap_device {
    my $self = shift;
    my $butler = $self->{butler};
    my $device = $self->{tap_device} = $self->{args}{device} // $self->_find_unused_tap_device;
    $self->{tap_fh} = $butler->create_tap($device);
    $butler->device_up($device)
        or $self->_die("Failed to bring up tap device $device");

    my $host = $self->{local_ip};
    my $mask = $self->{remote_netmask};
    $butler->device_addr_add($device, $host, $mask)
        or $self->_die("Failed to add address $host/$mask to tap device $device");
    $self->_log(info => "Tap device $device created and configured");
    1;
}

sub _init_reslirp {
    my $self = shift;
    my $ssh = $self->{ssh};
    my $cmd = $self->{reslirp_command} = $self->{args}{reslirp_command} // $self->_autodetect_reslirp_command;
    my @args = @{$self->{args}{more_reslirp_args}};
    $self->_log(info => "Starting remote reSLIRP process");
    $self->_log(debug => "Remote command: $cmd @args");
    my ($socket, undef, $stderr, $pid) = $ssh->open_ex({stderr_pipe => 1,
                                                        stdinout_socket => 1,
                                                        quote_args => 1,
                                                        remote_shell => $self->{quoting_backend}},
                                                       $cmd, @args);
    $self->{reslirp_socket} = $socket;
    $self->{reslirp_stderr} = $stderr;



( run in 0.992 second using v1.01-cache-2.11-cpan-8dfa8b56332 )