1#!/usr/bin/perl 2# $OpenBSD: remote.pl,v 1.3 2017/10/27 16:59:14 bluhm Exp $ 3 4# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20use File::Basename; 21use File::Copy; 22use Socket; 23use Socket6; 24 25use Client; 26use Relay; 27use Server; 28use Remote; 29require 'funcs.pl'; 30 31sub usage { 32 die <<"EOF"; 33usage: 34 remote.pl localport remoteaddr remoteport [args-test.pl] 35 Run test with local client and server. Remote relay 36 forwarding from remoteaddr remoteport to server localport 37 has to be started manually. 38 remote.pl copy|splice listenaddr connectaddr connectport [args-test.pl] 39 Only start remote relay. 40 remote.pl copy|splice localaddr remoteaddr remotessh [args-test.pl] 41 Run test with local client and server. Remote relay is 42 started automatically with ssh on remotessh. 43EOF 44} 45 46my $testfile; 47our %args; 48if (@ARGV and -f $ARGV[-1]) { 49 $testfile = pop; 50 do $testfile 51 or die "Do test file $testfile failed: ", $@ || $!; 52} 53my $mode = 54 @ARGV == 3 && $ARGV[0] =~ /^\d+$/ && $ARGV[2] =~ /^\d+$/ ? "manual" : 55 @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] =~ /^\d+$/ ? "relay" : 56 @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] !~ /^\d+$/ ? "auto" : 57 usage(); 58 59my $r; 60if ($mode eq "relay") { 61 $r = Relay->new( 62 forward => $ARGV[0], 63 logfile => dirname($0)."/remote.log", 64 func => \&relay, 65 %{$args{relay}}, 66 listendomain => AF_INET, 67 listenaddr => $ARGV[1], 68 connectdomain => AF_INET, 69 connectaddr => $ARGV[2], 70 connectport => $ARGV[3], 71 ); 72 open(my $log, '<', $r->{logfile}) 73 or die "Remote log file open failed: $!"; 74 $SIG{__DIE__} = sub { 75 die @_ if $^S; 76 copy($log, \*STDERR); 77 warn @_; 78 exit 255; 79 }; 80 copy($log, \*STDERR); 81 $r->run; 82 copy($log, \*STDERR); 83 $r->up; 84 copy($log, \*STDERR); 85 $r->down; 86 copy($log, \*STDERR); 87 88 exit; 89} 90 91my $s = Server->new( 92 func => \&read_stream, 93 oobinline => 1, 94 %{$args{server}}, 95 listendomain => AF_INET, 96 listenaddr => ($mode eq "auto" ? $ARGV[1] : undef), 97 listenport => ($mode eq "manual" ? $ARGV[0] : undef), 98); 99if ($mode eq "auto") { 100 $r = Remote->new( 101 forward => $ARGV[0], 102 logfile => "relay.log", 103 testfile => $testfile, 104 %{$args{relay}}, 105 remotessh => $ARGV[3], 106 listenaddr => $ARGV[2], 107 connectaddr => $ARGV[1], 108 connectport => $s->{listenport}, 109 ); 110 $r->run->up; 111} 112my $c = Client->new( 113 func => \&write_stream, 114 oobinline => 1, 115 %{$args{client}}, 116 connectdomain => AF_INET, 117 connectaddr => ($mode eq "manual" ? $ARGV[1] : $r->{listenaddr}), 118 connectport => ($mode eq "manual" ? $ARGV[2] : $r->{listenport}), 119); 120 121$s->run; 122$c->run->up; 123$s->up; 124 125$c->down; 126$r->down if $r; 127$s->down; 128 129check_logs($c, $r, $s, %args); 130