xref: /openbsd-src/regress/usr.sbin/relayd/Relayd.pm (revision d2ef00f263b78d05b376fb6cde385d9378f13603)
1#	$OpenBSD: Relayd.pm,v 1.20 2024/10/28 19:57:02 tb Exp $
2
3# Copyright (c) 2010-2015 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 Cwd;
24use Sys::Hostname;
25use File::Basename;
26
27sub new {
28	my $class = shift;
29	my %args = @_;
30	$args{logfile} ||= "relayd.log";
31	$args{up} ||= $args{dryrun} || "relay_launch: ";
32	$args{down} ||= $args{dryrun} ? "relayd.conf:" : "parent terminating";
33	$args{func} = sub { Carp::confess "$class func may not be called" };
34	$args{conffile} ||= "relayd.conf";
35	$args{forward}
36	    or croak "$class forward not given";
37	my $self = Proc::new($class, %args);
38	ref($self->{protocol}) eq 'ARRAY'
39	    or $self->{protocol} = [ split("\n", $self->{protocol} || "") ];
40	ref($self->{relay}) eq 'ARRAY'
41	    or $self->{relay} = [ split("\n", $self->{relay} || "") ];
42	$self->{listenaddr}
43	    or croak "$class listen addr not given";
44	$self->{listenport}
45	    or croak "$class listen port not given";
46	$self->{connectaddr}
47	    or croak "$class connect addr not given";
48	$self->{connectport}
49	    or croak "$class connect port not given";
50
51	my $test = basename($self->{testfile} || "");
52	# tls does not allow a too long session id, so truncate it
53	substr($test, 25, length($test) - 25, "") if length($test) > 25;
54	open(my $fh, '>', $self->{conffile})
55	    or die ref($self), " conf file $self->{conffile} create failed: $!";
56	print $fh "log state changes\n";
57	print $fh "log host checks\n";
58	print $fh "log connection\n";
59	print $fh "prefork 1\n";  # only crashes of first child are observed
60	print $fh "table <table-$test> { $self->{connectaddr} }\n"
61	    if defined($self->{table});
62
63	# substitute variables in config file
64	my $curdir = dirname($0) || ".";
65	my $objdir = getcwd();
66	my $hostname = hostname();
67	(my $host = $hostname) =~ s/\..*//;
68	my $connectport = $self->{connectport};
69	my $connectaddr = $self->{connectaddr};
70	my $listenaddr = $self->{listenaddr};
71	my $listenport = $self->{listenport};
72
73	my @protocol = @{$self->{protocol}};
74	my $proto = shift @protocol;
75	$proto = defined($proto) ? "$proto " : "";
76	unshift @protocol,
77	    $self->{forward} eq "splice" ? "tcp splice" :
78	    $self->{forward} eq "copy"   ? "tcp no splice" :
79	    die ref($self), " invalid forward $self->{forward}"
80	    unless grep { /splice/ } @protocol;
81	push @protocol, "tcp nodelay";
82	print $fh "${proto}protocol proto-$test {";
83	if ($self->{inspectssl}) {
84		$self->{listenssl} = $self->{forwardssl} = 1;
85		print $fh "\n\ttls ca cert ca.crt";
86		print $fh "\n\ttls ca key ca.key password ''";
87	}
88	if ($self->{verifyclient}) {
89		print $fh "\n\ttls client ca client-ca.crt";
90	}
91	# substitute variables in config file
92	foreach (@protocol) {
93		s/(\$[a-z]+)/$1/eeg;
94	}
95	print $fh  map { "\n\t$_" } @protocol;
96	print $fh  "\n}\n";
97
98	my @relay = @{$self->{relay}};
99	print $fh  "relay relay-$test {";
100	print $fh  "\n\tprotocol proto-$test"
101	    unless grep { /^protocol / } @relay;
102	my $tls = $self->{listenssl} ? " tls" : "";
103	print $fh  "\n\tlisten on $self->{listenaddr} ".
104	    "port $self->{listenport}$tls" unless grep { /^listen / } @relay;
105	my $withtls = $self->{forwardssl} ? " with tls" : "";
106	print $fh  "\n\tforward$withtls to $self->{connectaddr} ".
107	    "port $self->{connectport}" unless grep { /^forward / } @relay;
108	# substitute variables in config file
109	foreach (@relay) {
110		s/(\$[a-z]+)/$1/eeg;
111	}
112	print $fh  map { "\n\t$_" } @relay;
113	print $fh  "\n}\n";
114
115	return $self;
116}
117
118sub child {
119	my $self = shift;
120	my @sudo = $ENV{SUDO} ? split(' ', $ENV{SUDO}) : ();
121	my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : ();
122	my $relayd = $ENV{RELAYD} ? $ENV{RELAYD} : "relayd";
123	my @cmd = (@sudo, @ktrace, $relayd, "-dvv", "-f", $self->{conffile});
124	print STDERR "execute: @cmd\n";
125	exec @cmd;
126	die ref($self), " exec '@cmd' failed: $!";
127}
128
1291;
130