1# $OpenBSD: Relayd.pm,v 1.7 2014/05/02 14:10:03 andre Exp $ 2 3# Copyright (c) 2010-2012 Alexander Bluhm <bluhm@openbsd.org> 4# 5# Permission to use, copy, modify, and distribute this software for any 6# purpose with or without fee is hereby granted, provided that the above 7# copyright notice and this permission notice appear in all copies. 8# 9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 17use strict; 18use warnings; 19 20package Relayd; 21use parent 'Proc'; 22use Carp; 23use File::Basename; 24 25sub new { 26 my $class = shift; 27 my %args = @_; 28 $args{logfile} ||= "relayd.log"; 29 $args{up} ||= "Started"; 30 $args{down} ||= "parent terminating"; 31 $args{func} = sub { Carp::confess "$class func may not be called" }; 32 $args{conffile} ||= "relayd.conf"; 33 $args{forward} 34 or croak "$class forward not given"; 35 my $self = Proc::new($class, %args); 36 ref($self->{protocol}) eq 'ARRAY' 37 or $self->{protocol} = [ split("\n", $self->{protocol} || "") ]; 38 ref($self->{relay}) eq 'ARRAY' 39 or $self->{relay} = [ split("\n", $self->{relay} || "") ]; 40 $self->{listenaddr} 41 or croak "$class listen addr not given"; 42 $self->{listenport} 43 or croak "$class listen port not given"; 44 $self->{connectaddr} 45 or croak "$class connect addr not given"; 46 $self->{connectport} 47 or croak "$class connect port not given"; 48 49 my $test = basename($self->{testfile} || ""); 50 # ssl does not allow a too long session id, so truncate it 51 substr($test, 25, length($test) - 25, "") if length($test) > 25; 52 open(my $fh, '>', $self->{conffile}) 53 or die ref($self), " conf file $self->{conffile} create failed: $!"; 54 print $fh "log all\n"; 55 print $fh "table <table-$test> { $self->{connectaddr} }\n" 56 if defined($self->{table}); 57 58 my @protocol = @{$self->{protocol}}; 59 my $proto = shift @protocol; 60 $proto = defined($proto) ? "$proto " : ""; 61 unshift @protocol, 62 $self->{forward} eq "splice" ? "tcp splice" : 63 $self->{forward} eq "copy" ? "tcp no splice" : 64 die ref($self), " invalid forward $self->{forward}" 65 unless grep { /splice/ } @protocol; 66 print $fh "${proto}protocol proto-$test {"; 67 print $fh map { "\n\t$_" } @protocol; 68 print $fh "\n}\n"; 69 70 my @relay = @{$self->{relay}}; 71 my $connectport = $self->{connectport}; 72 my $connectaddr = $self->{connectaddr}; 73 my $listenaddr = $self->{listenaddr}; 74 my $listenport = $self->{listenport}; 75 print $fh "relay relay-$test {"; 76 print $fh "\n\tprotocol proto-$test" 77 unless grep { /^protocol / } @relay; 78 my $ssl = $self->{listenssl} ? " ssl" : ""; 79 print $fh "\n\tlisten on $self->{listenaddr} ". 80 "port $self->{listenport}$ssl" unless grep { /^listen / } @relay; 81 my $withssl = $self->{forwardssl} ? " with ssl" : ""; 82 print $fh "\n\tforward$withssl to $self->{connectaddr} ". 83 "port $self->{connectport}" unless grep { /^forward / } @relay; 84 my @raux = @relay; 85 @relay = (); 86 foreach my $s (@raux) { 87 $s =~ s/(\$\w+)/$1/eeg; 88 push @relay, $s; 89 } 90 print $fh map { "\n\t$_" } @relay; 91 print $fh "\n}\n"; 92 93 return $self; 94} 95 96sub up { 97 my $self = Proc::up(shift, @_); 98 my $timeout = shift || 10; 99 my $lsock = $self->loggrep(qr/relay_launch: /, $timeout) 100 or croak ref($self), " no relay_launch in $self->{logfile} ". 101 "after $timeout seconds"; 102 return $self; 103} 104 105sub child { 106 my $self = shift; 107 print STDERR $self->{up}, "\n"; 108 my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); 109 my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : (); 110 my $relayd = $ENV{RELAYD} ? $ENV{RELAYD} : "relayd"; 111 my @cmd = (@sudo, @ktrace, $relayd, '-dvv', '-f', $self->{conffile}); 112 print STDERR "execute: @cmd\n"; 113 exec @cmd; 114 die "Exec @cmd failed: $!"; 115} 116 1171; 118