App-ReslirpTunnel
view release on metacpan or search on metacpan
lib/App/ReslirpTunnel.pm view on Meta::CPAN
sub _init_config {
my $self = shift;
my $args = $self->{args};
$self->{run_in_foreground} = $args->{run_in_foreground} // 0;
$self->{dont_close_stdio} = $args->{dont_close_stdio} // 0;
$self->{ssh_host} = $args->{ssh_host};
$self->{ssh_port} = $args->{ssh_port};
$self->{ssh_user} = $args->{ssh_user};
$self->{remote_network} = $args->{remote_network} // '10.0.2.0';
is_ipv4($self->{remote_network}) or $self->_die("Invalid remote network address, $self->{remote_network}");
$self->{remote_netmask} = $self->_parse_netmask($args->{remote_netmask} // 24);
$self->{remote_dns} = $self->_parse_ip($args->{remote_dns});
$self->{remote_gw} = $self->_parse_ip($args->{remote_gw});
$self->{local_ip} = $self->_parse_ip($args->{local_ip});
}
sub _parse_netmask {
my ($self, $netmask) = @_;
($netmask =~ /^\d+$/ && $netmask >= 1 && $netmask <= 31) or $self->_die("Invalid netmask", $netmask);
return $netmask;
}
sub _parse_ip {
my ($self, $ip) = @_;
my $network = $self->{remote_network};
my $netmask = $self->{remote_netmask};
if ($ip =~ /^\d+$/) {
$ip = $network =~ s/\d+$/$ip/r;
}
is_ipv4($ip) or $self->_die("Invalid IP address", $ip);
my $ip_int = __ip_to_int($ip);
my $net_int = __ip_to_int($network);
my $bitmask = ~0 << (32 - $netmask);
unless (($ip_int & $bitmask) == ($ip_int & $bitmask)) {
$self->_die("IP address $ip is not inside remote network $network/$netmask");
}
return $ip;
}
sub __ip_to_int {
my $ip = shift;
return unpack("N", pack("C*", split(/\./, $ip)));
}
sub _init_butler {
my $self = shift;
my $butler = $self->{butler} = App::ReslirpTunnel::Butler->new(dont_close_stdio => $self->{dont_close_stdio},
log_level => $self->{log_level},
log_to_stderr => $self->{log_to_stderr},
log_file => $self->{log_file});
$butler->start or $self->_die("Failed to start butler");
$butler->hello
or $self->_die("Failed to say hello to butler");
$self->_log(info => "Elevated slave process started and ready");
}
sub _send_to_background {
my $self = shift;
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;
}
( run in 0.966 second using v1.01-cache-2.11-cpan-54e63673c56 )