1#!/usr/bin/perl 2# $OpenBSD: syslogd.pl,v 1.11 2019/09/17 22:24:08 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 Socket; 21use Socket6; 22 23use Client; 24use Syslogd; 25use Server; 26use Syslogc; 27use RSyslogd; 28require 'funcs.pl'; 29 30sub usage { 31 die "usage: syslogd.pl [test-args.pl]\n"; 32} 33 34my $testfile; 35our %args; 36if (@ARGV and -f $ARGV[-1]) { 37 $testfile = pop; 38 do $testfile 39 or die "Do test file $testfile failed: ", $@ || $!; 40} 41@ARGV == 0 or usage(); 42 43create_multifile(@{$args{multifile} || []}); 44foreach my $name (qw(client syslogd server rsyslogd)) { 45 $args{$name} or next; 46 foreach my $action (qw(connect listen)) { 47 my $h = $args{$name}{$action} or next; 48 defined $h->{domain} 49 or die "No domain specified in $name $action"; 50 foreach my $k (qw(domain proto addr port)) { 51 next unless defined $h->{$k}; 52 $args{$name}{"$action$k"} = $h->{$k}; 53 } 54 } 55} 56my($s, $c, $r, $rc, @m); 57$s = RSyslogd->new( 58 %{$args{rsyslogd}}, 59 listenport => scalar find_ports(%{$args{rsyslogd}{listen}}), 60 testfile => $testfile, 61) if $args{rsyslogd}{listen} && !$args{rsyslogd}{connect}; 62$s ||= Server->new( 63 func => \&read_log, 64 listendomain => AF_INET, 65 listenaddr => "127.0.0.1", 66 %{$args{server}}, 67 testfile => $testfile, 68 client => \$c, 69 syslogd => \$r, 70) unless $args{server}{noserver}; 71$args{syslogc} = [ $args{syslogc} ] if ref $args{syslogc} eq 'HASH'; 72my $i = 0; 73@m = map { Syslogc->new( 74 %{$_}, 75 testfile => $testfile, 76 ktracefile => "syslogc-$i.ktrace", 77 logfile => "syslogc-".$i++.".log", 78) } @{$args{syslogc}}; 79$r = Syslogd->new( 80 connectaddr => "127.0.0.1", 81 connectport => $s && $s->{listenport}, 82 ctlsock => @m && $m[0]->{ctlsock}, 83 %{$args{syslogd}}, 84 testfile => $testfile, 85 client => \$c, 86 server => \$s, 87); 88$rc = RSyslogd->new( 89 %{$args{rsyslogd}}, 90 listenport => scalar find_ports(%{$args{rsyslogd}{listen}}), 91 testfile => $testfile, 92) if $args{rsyslogd}{connect}; 93$c = Client->new( 94 func => \&write_log, 95 connectport => $rc && $rc->{listenport}, 96 %{$args{client}}, 97 testfile => $testfile, 98 syslogd => \$r, 99 server => \$s, 100) unless $args{client}{noclient}; 101($rc, $c) = ($c, $rc) if $rc; # chain client -> rsyslogd -> syslogd 102 103if (!$args{client}{noclient} && $c->{early}) { 104 $c->run->up; 105 $c->loggrep(get_firstlog(), 10) 106 or die ref($c), " no first log during early startup"; 107} 108$r->run unless $r->{late}; 109$s->run->up unless $args{server}{noserver}; 110$r->run if $r->{late}; 111$r->up; 112my $control = 0; 113foreach (@m) { 114 if ($_->{early} || $_->{stop}) { 115 $_->run->up; 116 $control++; 117 } 118} 119$r->loggrep("Accepting control connection") if $control; 120foreach (@m) { 121 if ($_->{stop}) { 122 $_->kill('STOP'); 123 } 124} 125$c->run->up if !$args{client}{noclient} && !$c->{early}; 126$rc->run->up if $args{rsyslogd}{connect}; 127 128$rc->down if $args{rsyslogd}{connect}; 129$c->down if !$args{client}{noclient} && !$c->{early}; 130$s->down unless $args{server}{noserver}; 131foreach (@m) { 132 if ($_->{stop}) { 133 $_->kill('CONT'); 134 $_->down; 135 } elsif ($_->{early}) { 136 $_->down; 137 } else { 138 $_->run->up->down; 139 } 140} 141$r->kill_child; 142$r->down; 143$c->down if !$args{client}{noclient} && $c->{early}; 144 145$args{check}->({client => $c, syslogd => $r, server => $s}) if $args{check}; 146check_logs($c, $r, $s, \@m, %args); 147