diff options
Diffstat (limited to 'regress')
-rw-r--r-- | regress/usr.sbin/syslogd/Client.pm | 62 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/LICENSE | 13 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/Makefile | 86 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/Proc.pm | 197 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/README | 24 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/Server.pm | 83 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/Syslogd.pm | 128 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-client-udp-nodns.pl | 23 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-client-udp.pl | 23 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-client-udp4-nodns.pl | 23 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-client-udp4.pl | 23 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-default.pl | 14 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-sendsyslog.pl | 23 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/args-socket.pl | 27 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/funcs.pl | 183 | ||||
-rw-r--r-- | regress/usr.sbin/syslogd/syslogd.pl | 79 |
16 files changed, 1011 insertions, 0 deletions
diff --git a/regress/usr.sbin/syslogd/Client.pm b/regress/usr.sbin/syslogd/Client.pm new file mode 100644 index 00000000000..0de6e78ca4a --- /dev/null +++ b/regress/usr.sbin/syslogd/Client.pm @@ -0,0 +1,62 @@ +# $OpenBSD: Client.pm,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Client; +use parent 'Proc'; +use Carp; +use IO::Socket::INET6; +use Sys::Syslog qw(:standard :extended :macros); + +sub new { + my $class = shift; + my %args = @_; + $args{ktracefile} ||= "client.ktrace"; + $args{logfile} ||= "client.log"; + $args{up} ||= "Openlog"; + my $self = Proc::new($class, %args); + return $self; +} + +sub child { + my $self = shift; + + if ($self->{connectdomain}) { + my $cs = IO::Socket::INET6->new( + Proto => "udp", + Domain => $self->{connectdomain}, + PeerAddr => $self->{connectaddr}, + PeerPort => $self->{connectport}, + ) or die ref($self), " socket connect failed: $!"; + print STDERR "connect sock: ",$cs->sockhost()," ", + $cs->sockport(),"\n"; + print STDERR "connect peer: ",$cs->peerhost()," ", + $cs->peerport(),"\n"; + + *STDIN = *STDOUT = $self->{cs} = $cs; + } + + if ($self->{logsock}) { + setlogsock($self->{logsock}) + or die ref($self), " setlogsock failed: $!"; + } + # we take LOG_UUCP as it is not used nowadays + openlog("syslogd-regress", "ndelay,perror,pid", LOG_UUCP); +} + +1; diff --git a/regress/usr.sbin/syslogd/LICENSE b/regress/usr.sbin/syslogd/LICENSE new file mode 100644 index 00000000000..a6e1dd38fcf --- /dev/null +++ b/regress/usr.sbin/syslogd/LICENSE @@ -0,0 +1,13 @@ +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/regress/usr.sbin/syslogd/Makefile b/regress/usr.sbin/syslogd/Makefile new file mode 100644 index 00000000000..f3734001a5d --- /dev/null +++ b/regress/usr.sbin/syslogd/Makefile @@ -0,0 +1,86 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# The following ports must be installed for the regression tests: +# p5-IO-Socket-INET6 object interface for AF_INET and AF_INET6 domain sockets +# p5-Socket6 Perl defines relating to AF_INET6 sockets +# p5-IO-Socket-SSL perl interface to SSL sockets +# +# Check wether all required perl packages are installed. If some +# are missing print a warning and skip the tests, but do not fail. + +PERL_REQUIRE != perl -Mstrict -Mwarnings -e ' \ + eval { require IO::Socket::INET6 } or print $@; \ + eval { require Socket6 } or print $@; \ + eval { require IO::Socket::SSL } or print $@; \ +' +.if ! empty (PERL_REQUIRE) +regress: + @echo "${PERL_REQUIRE}" + @echo install these perl packages for additional tests +.endif + +# Automatically generate regress targets from test cases in directory. + +ARGS != cd ${.CURDIR} && ls args-*.pl +TARGETS ?= ${ARGS} +REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/} +CLEANFILES += *.log *.pem *.crt *.key syslogd.conf stamp-* +CLEANFILES += ktrace.out *.ktrace *.fstat + +.MAIN: all + +.if make (regress) || make (all) +.BEGIN: + @echo + [ -z "${SUDO}" ] || ${SUDO} true +.END: + @echo + ${SUDO} /etc/rc.d/syslogd restart +.endif + +# Set variables so that make runs with and without obj directory. +# Only do that if necessary to keep visible output short. + +.if ${.CURDIR} == ${.OBJDIR} +PERLINC = +PERLPATH = +.else +PERLINC = -I${.CURDIR} +PERLPATH = ${.CURDIR}/ +.endif + +# The arg tests take a perl hash with arguments controlling the +# test parameters. Generally they consist of client, syslogd, server. + +.for a in ${ARGS} +run-regress-$a: $a + @echo '\n======== $@ ========' + time SUDO=${SUDO} KTRACE=${KTRACE} SYSLOGD=${SYSLOGD} perl ${PERLINC} ${PERLPATH}syslogd.pl ${PERLPATH}$a +.endfor + +# create the certificates for SSL + +127.0.0.1.crt: + openssl req -batch -new -nodes -newkey rsa -keyout 127.0.0.1.key -subj /CN=127.0.0.1/ -x509 -out $@ + ${SUDO} cp 127.0.0.1.crt /etc/ssl/ + ${SUDO} cp 127.0.0.1.key /etc/ssl/private/ + +server-cert.pem: + openssl req -batch -new -nodes -newkey rsa -keyout server-key.pem -subj /CN=localhost/ -x509 -out $@ + +${REGRESS_TARGETS:M*ssl*} ${REGRESS_TARGETS:M*https*}: server-cert.pem +${REGRESS_TARGETS:M*ssl*} ${REGRESS_TARGETS:M*https*}: 127.0.0.1.crt + +# make perl syntax check for all args files + +.PHONY: syntax + +syntax: stamp-syntax + +stamp-syntax: ${ARGS} +.for a in ${ARGS} + @perl -c ${PERLPATH}$a +.endfor + @date >$@ + +.include <bsd.regress.mk> diff --git a/regress/usr.sbin/syslogd/Proc.pm b/regress/usr.sbin/syslogd/Proc.pm new file mode 100644 index 00000000000..5e8a14f0368 --- /dev/null +++ b/regress/usr.sbin/syslogd/Proc.pm @@ -0,0 +1,197 @@ +# $OpenBSD: Proc.pm,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2014 Florian Riehm <mail@friehm.de> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Proc; +use Carp; +use Errno; +use IO::File; +use POSIX; +use Time::HiRes qw(time alarm sleep); + +my %CHILDREN; + +sub kill_children { + my @pids = @_ ? @_ : keys %CHILDREN + or return; + my @perms; + foreach my $pid (@pids) { + if (kill(TERM => $pid) != 1 and $!{EPERM}) { + push @perms, $pid; + } + } + if (my $sudo = $ENV{SUDO} and @perms) { + local $?; # do not modify during END block + my @cmd = ($sudo, '/bin/kill', '-TERM', @perms); + system(@cmd); + } + delete @CHILDREN{@pids}; +} + +BEGIN { + $SIG{TERM} = $SIG{INT} = sub { + my $sig = shift; + kill_children(); + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; + POSIX::raise($sig); + }; +} + +END { + kill_children(); + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; +} + +sub new { + my $class = shift; + my $self = { @_ }; + $self->{down} ||= "Shutdown"; + $self->{func} && ref($self->{func}) eq 'CODE' + or croak "$class func not given"; + !$self->{ktrace} || $self->{ktracefile} + or croak "$class ktrace file not given"; + $self->{logfile} + or croak "$class log file not given"; + open(my $fh, '>', $self->{logfile}) + or die "$class log file $self->{logfile} create failed: $!"; + $fh->autoflush; + $self->{log} = $fh; + return bless $self, $class; +} + +sub run { + my $self = shift; + + pipe(my $reader, my $writer) + or die ref($self), " pipe to child failed: $!"; + defined(my $pid = fork()) + or die ref($self), " fork child failed: $!"; + if ($pid) { + $CHILDREN{$pid} = 1; + $self->{pid} = $pid; + close($reader); + $self->{pipe} = $writer; + return $self; + } + %CHILDREN = (); + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; + $SIG{__DIE__} = sub { + die @_ if $^S; + warn @_; + IO::Handle::flush(\*STDERR); + POSIX::_exit(255); + }; + open(STDERR, '>&', $self->{log}) + or die ref($self), " dup STDERR failed: $!"; + open(STDOUT, '>&', $self->{log}) + or die ref($self), " dup STDOUT failed: $!"; + close($writer); + open(STDIN, '<&', $reader) + or die ref($self), " dup STDIN failed: $!"; + close($reader); + + if ($self->{ktrace}) { + my @cmd = ("ktrace", "-f", $self->{ktracefile}, "-p", $$); + system(@cmd) + and die ref($self), " system '@cmd' failed: $?"; + } + $self->child(); + print STDERR $self->{up}, "\n"; + $self->{func}->($self); + print STDERR "Shutdown", "\n"; + + IO::Handle::flush(\*STDOUT); + IO::Handle::flush(\*STDERR); + POSIX::_exit(0); +} + +sub wait { + my $self = shift; + my $flags = shift; + + my $pid = $self->{pid} + or croak ref($self), " no child pid"; + my $kid = waitpid($pid, $flags); + if ($kid > 0) { + my $status = $?; + my $code; + $code = "exit: ". WEXITSTATUS($?) if WIFEXITED($?); + $code = "signal: ". WTERMSIG($?) if WIFSIGNALED($?); + $code = "stop: ". WSTOPSIG($?) if WIFSTOPPED($?); + delete $CHILDREN{$pid} if WIFEXITED($?) || WIFSIGNALED($?); + return wantarray ? ($kid, $status, $code) : $kid; + } + return $kid; +} + +sub loggrep { + my $self = shift; + my($regex, $timeout) = @_; + + my $end = time() + $timeout if $timeout; + + do { + my($kid, $status, $code) = $self->wait(WNOHANG); + if ($kid > 0 && $status != 0) { + # child terminated with failure + die ref($self), " child status: $status $code"; + } + open(my $fh, '<', $self->{logfile}) + or die ref($self), " log file open failed: $!"; + my @match = grep { /$regex/ } <$fh>; + return wantarray ? @match : $match[0] if @match; + close($fh); + # pattern not found + if ($kid == 0) { + # child still running, wait for log data + sleep .1; + } else { + # child terminated, no new log data possible + return; + } + } while ($timeout and time() < $end); + + return; +} + +sub up { + my $self = shift; + my $timeout = shift || 10; + $self->loggrep(qr/$self->{up}/, $timeout) + or croak ref($self), " no '$self->{up}' in $self->{logfile} ". + "after $timeout seconds"; + return $self; +} + +sub down { + my $self = shift; + my $timeout = shift || 30; + $self->loggrep(qr/$self->{down}/, $timeout) + or croak ref($self), " no '$self->{down}' in $self->{logfile} ". + "after $timeout seconds"; + return $self; +} + +sub kill_child { + my $self = shift; + kill_children($self->{pid}); + return $self; +} + +1; diff --git a/regress/usr.sbin/syslogd/README b/regress/usr.sbin/syslogd/README new file mode 100644 index 00000000000..4d8234855a5 --- /dev/null +++ b/regress/usr.sbin/syslogd/README @@ -0,0 +1,24 @@ +Run syslogd regressions tests. As only one syslogd can run per +machine, each test kills any syslogd first. At the end the system's +syslogd gets restarted. +The test framework runs a client, and a server, and a syslogd. The +messages are passed via the log socket or via UDP from the client +to syslogd. From there UDP transport is used to reach the server. +All processes write log files where the message has to show up. +The test arguments are kept in the args-*.pl files. +The content of a log file, the data sent to a pipe process and what +the server received are checked. The invocation of the sendsyslog(2) +syscall is checked with ktrace, the open file descriptors of syslogd +are checked with fstat. + +SUDO=sudo +As syslogd needs root privileges either run the tests as root or +set this variable and run make as a regular user. Only the code +that requires it, is run as root. + +KTRACE=ktrace +Set this variable if you want a ktrace output from syslogd. Note that +ktrace is invoked after sudo as sudo would disable it. + +SYSLOGD=/usr/src/usr.sbin/syslogd/obj/syslogd +Start an alternative syslogd program that is not in the path. diff --git a/regress/usr.sbin/syslogd/Server.pm b/regress/usr.sbin/syslogd/Server.pm new file mode 100644 index 00000000000..2b3087b0c89 --- /dev/null +++ b/regress/usr.sbin/syslogd/Server.pm @@ -0,0 +1,83 @@ +# $OpenBSD: Server.pm,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Server; +use parent 'Proc'; +use Carp; +use Socket; +use Socket6; +use IO::Socket; +use IO::Socket::INET6; +use IO::Socket::SSL; + +sub new { + my $class = shift; + my %args = @_; + $args{ktracefile} ||= "server.ktrace"; + $args{logfile} ||= "server.log"; + $args{up} ||= "Accepted"; + my $self = Proc::new($class, %args); + $self->{listenprotocol} ||= "udp"; + $self->{listendomain} + or croak "$class listen domain not given"; + $SSL_ERROR = ""; + my $iosocket = $self->{listenprotocol} eq "tls" ? + "IO::Socket::SSL" : "IO::Socket::INET6"; + my $proto = $self->{listenprotocol}; + $proto = "tcp" if $proto eq "tls"; + my $ls = $iosocket->new( + Proto => $proto, + ReuseAddr => 1, + Domain => $self->{listendomain}, + $self->{listenaddr} ? (LocalAddr => $self->{listenaddr}) : (), + $self->{listenport} ? (LocalPort => $self->{listenport}) : (), + SSL_key_file => "server-key.pem", + SSL_cert_file => "server-cert.pem", + SSL_verify_mode => SSL_VERIFY_NONE, + ) or die ref($self), " $iosocket socket listen failed: $!,$SSL_ERROR"; + if ($self->{listenprotocol} eq "tcp") { + listen($ls, 1) + or die ref($self), " socket failed: $!"; + } + my $log = $self->{log}; + print $log "listen sock: ",$ls->sockhost()," ",$ls->sockport(),"\n"; + $self->{listenaddr} = $ls->sockhost() unless $self->{listenaddr}; + $self->{listenport} = $ls->sockport() unless $self->{listenport}; + $self->{ls} = $ls; + return $self; +} + +sub child { + my $self = shift; + + my $iosocket = $self->{ssl} ? "IO::Socket::SSL" : "IO::Socket::INET6"; + my $as = $self->{ls}; + if ($self->{listenprotocol} ne "udp") { + $as = $self->{ls}->accept() + or die ref($self), " $iosocket socket accept failed: $!"; + print STDERR "accept sock: ",$as->sockhost()," ", + $as->sockport(),"\n"; + print STDERR "accept peer: ",$as->peerhost()," ", + $as->peerport(),"\n"; + } + + *STDIN = *STDOUT = $self->{as} = $as; +} + +1; diff --git a/regress/usr.sbin/syslogd/Syslogd.pm b/regress/usr.sbin/syslogd/Syslogd.pm new file mode 100644 index 00000000000..dfa275c4fb0 --- /dev/null +++ b/regress/usr.sbin/syslogd/Syslogd.pm @@ -0,0 +1,128 @@ +# $OpenBSD: Syslogd.pm,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2014 Florian Riehm <mail@friehm.de> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Syslogd; +use parent 'Proc'; +use Carp; +use Cwd; +use File::Basename; + +sub new { + my $class = shift; + my %args = @_; + $args{fstatfile} ||= "syslogd.fstat"; + $args{logfile} ||= "syslogd.log"; + $args{up} ||= "syslogd: started"; + $args{down} ||= "syslogd: exiting"; + $args{func} = sub { Carp::confess "$class func may not be called" }; + $args{conffile} ||= "syslogd.conf"; + $args{outfile} ||= "file.log"; + $args{outpipe} ||= "pipe.log"; + my $self = Proc::new($class, %args); + $self->{connectaddr} + or croak "$class connect addr not given"; + + _make_abspath(\$self->{$_}) foreach (qw(conffile outfile outpipe)); + + # substitute variables in config file + my $connectprotocol = $self->{connectprotocol}; + my $connectdomain = $self->{connectdomain}; + my $connectaddr = $self->{connectaddr}; + my $connectport = $self->{connectport}; + + open(my $fh, '>', $self->{conffile}) + or die ref($self), " create conf file $self->{conffile} failed: $!"; + print $fh "*.*\t$self->{outfile}\n"; + print $fh "*.*\t|dd of=$self->{outpipe} status=none\n"; + my $loghost = $self->{loghost}; + if ($loghost) { + $loghost =~ s/(\$[a-z]+)/$1/eeg; + } else { + $loghost = "\@$connectaddr"; + $loghost .= ":$connectport" if $connectport; + } + print $fh "*.*\t$loghost\n"; + close $fh; + + open($fh, '>', $self->{outfile}) + or die ref($self), " create log file $self->{outfile} failed: $!"; + close $fh; + + open($fh, '>', $self->{outpipe}) + or die ref($self), " create pipe file $self->{outpipe} failed: $!"; + close $fh; + chmod(0666, $self->{outpipe}) + or die ref($self), " chmod pipe file $self->{outpipe} failed: $!"; + + return $self; +} + +sub child { + my $self = shift; + my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); + + my @pkill = (@sudo, "pkill", "-x", "syslogd"); + my @pgrep = ("pgrep", "-x", "syslogd"); + system(@pkill) && $? != 256 + and die ref($self), " system '@pkill' failed: $?"; + while ($? == 0) { + print STDERR "syslogd still running\n"; + system(@pgrep) && $? != 256 + and die ref($self), " system '@pgrep' failed: $?"; + } + print STDERR "syslogd not running\n"; + + my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : (); + my $syslogd = $ENV{SYSLOGD} ? $ENV{SYSLOGD} : "syslogd"; + my @cmd = (@sudo, @ktrace, $syslogd, "-d", "-f", $self->{conffile}); + push @cmd, @{$self->{options}} if $self->{options}; + print STDERR "execute: @cmd\n"; + exec @cmd; + die ref($self), " exec '@cmd' failed: $!"; +} + +sub up { + my $self = Proc::up(shift, @_); + + if ($self->{fstat}) { + open(my $fh, '>', $self->{fstatfile}) or die ref($self), + " open $self->{fstatfile} for writing failed: $!"; + my @cmd = ("fstat"); + open(my $fs, '-|', @cmd) + or die ref($self), " open pipe from '@cmd' failed: $!"; + print $fh grep { /^\w+ *syslogd *\d+/ } <$fs>; + close($fs) or die ref($self), $! ? + " close pipe from '@cmd' failed: $!" : + " command '@cmd' failed: $?"; + close($fh) + or die ref($self), " close $self->{fstatfile} failed: $!"; + } +} + +sub _make_abspath { + my $file = ref($_[0]) ? ${$_[0]} : $_[0]; + if (substr($file, 0, 1) ne "/") { + $file = getcwd(). "/". $file; + ${$_[0]} = $file if ref($_[0]); + } + return $file; +} + +1; diff --git a/regress/usr.sbin/syslogd/args-client-udp-nodns.pl b/regress/usr.sbin/syslogd/args-client-udp-nodns.pl new file mode 100644 index 00000000000..00d88926a5c --- /dev/null +++ b/regress/usr.sbin/syslogd/args-client-udp-nodns.pl @@ -0,0 +1,23 @@ +# The client writes a message to Sys::Syslog UDP method. +# The syslogd writes it into a file and through a pipe without dns. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Check that the file log contains the 127.0.0.1 address. + +use strict; +use warnings; + +our %args = ( + client => { + logsock => { type => "udp", host => "127.0.0.1", port => 514 }, + }, + syslogd => { + options => ["-un"], + }, + file => { + loggrep => qr/ 127.0.0.1 syslogd-regress\[\d+\]: /. get_log(), + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/args-client-udp.pl b/regress/usr.sbin/syslogd/args-client-udp.pl new file mode 100644 index 00000000000..6f62737fa84 --- /dev/null +++ b/regress/usr.sbin/syslogd/args-client-udp.pl @@ -0,0 +1,23 @@ +# The client writes a message to Sys::Syslog UDP method. +# The syslogd writes it into a file and through a pipe. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Check that the file log contains the localhost name. + +use strict; +use warnings; + +our %args = ( + client => { + logsock => { type => "udp", host => "127.0.0.1", port => 514 }, + }, + syslogd => { + options => ["-u"], + }, + file => { + loggrep => qr/ localhost syslogd-regress\[\d+\]: /. get_log(), + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/args-client-udp4-nodns.pl b/regress/usr.sbin/syslogd/args-client-udp4-nodns.pl new file mode 100644 index 00000000000..c1a7bbc344a --- /dev/null +++ b/regress/usr.sbin/syslogd/args-client-udp4-nodns.pl @@ -0,0 +1,23 @@ +# The client writes a message to a localhost IPv4 UDP socket. +# The syslogd writes it into a file and through a pipe without dns. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Check that the file log contains the 127.0.0.1 address. + +use strict; +use warnings; + +our %args = ( + client => { + connect => { domain => AF_INET, addr => "127.0.0.1", port => 514 }, + }, + syslogd => { + options => ["-un"], + }, + file => { + loggrep => qr/ 127.0.0.1 /. get_log(), + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/args-client-udp4.pl b/regress/usr.sbin/syslogd/args-client-udp4.pl new file mode 100644 index 00000000000..8b16fb16458 --- /dev/null +++ b/regress/usr.sbin/syslogd/args-client-udp4.pl @@ -0,0 +1,23 @@ +# The client writes a message to a localhost IPv4 UDP socket. +# The syslogd writes it into a file and through a pipe. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Check that the file log contains the localhost name. + +use strict; +use warnings; + +our %args = ( + client => { + connect => { domain => AF_INET, addr => "127.0.0.1", port => 514 }, + }, + syslogd => { + options => ["-u"], + }, + file => { + loggrep => qr/ localhost /. get_log(), + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/args-default.pl b/regress/usr.sbin/syslogd/args-default.pl new file mode 100644 index 00000000000..c37ce36f1f9 --- /dev/null +++ b/regress/usr.sbin/syslogd/args-default.pl @@ -0,0 +1,14 @@ +# Test with default values, that is: +# The client writes a message to Sys::Syslog native method. +# The syslogd writes it into a file and through a pipe. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. + +use strict; +use warnings; + +our %args = ( +); + +1; diff --git a/regress/usr.sbin/syslogd/args-sendsyslog.pl b/regress/usr.sbin/syslogd/args-sendsyslog.pl new file mode 100644 index 00000000000..b29b25ac91f --- /dev/null +++ b/regress/usr.sbin/syslogd/args-sendsyslog.pl @@ -0,0 +1,23 @@ +# The client writes a message to Sys::Syslog native method. +# The syslogd writes it into a file and through a pipe. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Create a ktrace dump of the client and check that sendsyslog(2) +# has been used. + +use strict; +use warnings; + +our %args = ( + client => { + ktrace => 1, + kdump => { + qr/CALL sendsyslog/ => 2, + qr/GIO fd -1 wrote \d+ bytes/ => 2, + qr/RET sendsyslog 0/ => 2, + }, + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/args-socket.pl b/regress/usr.sbin/syslogd/args-socket.pl new file mode 100644 index 00000000000..9173a42069e --- /dev/null +++ b/regress/usr.sbin/syslogd/args-socket.pl @@ -0,0 +1,27 @@ +# Test with default values, that is: +# The client writes a message to a localhost IPv4 UDP socket. +# The syslogd writes it into a file and through a pipe. +# The syslogd passes it via UDP to the loghost. +# The server receives the message on its UDP socket. +# Find the message in client, file, pipe, syslogd, server log. +# Check that the syslogd has one IPv4 socket in fstat output. + +use strict; +use warnings; + +our %args = ( + client => { + connect => { domain => AF_INET, addr => "127.0.0.1", port => 514 }, + }, + syslogd => { + fstat => 1, + options => ["-nu"], + }, + fstat => { + loggrep => { + qr/ internet dgram udp \*:514$/ => 1, + }, + }, +); + +1; diff --git a/regress/usr.sbin/syslogd/funcs.pl b/regress/usr.sbin/syslogd/funcs.pl new file mode 100644 index 00000000000..593dd5a5012 --- /dev/null +++ b/regress/usr.sbin/syslogd/funcs.pl @@ -0,0 +1,183 @@ +# $OpenBSD: funcs.pl,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Errno; +use List::Util qw(first); +use Socket; +use Socket6; +use Sys::Syslog qw(:standard :extended :macros); +use IO::Socket; +use IO::Socket::INET6; + +my $testlog = "syslogd regress test log message"; +my $downlog = "syslogd regress client shutdown"; + +######################################################################## +# Client funcs +######################################################################## + +sub write_log { + my $self = shift; + + if ($self->{connectdomain}) { + print $testlog; + print STDERR $testlog, "\n"; + } else { + syslog(LOG_INFO, $testlog); + } + write_shutdown($self, @_); +} + +sub write_shutdown { + my $self = shift; + + setlogsock("native") + or die ref($self), " setlogsock native failed: $!"; + syslog(LOG_NOTICE, $downlog); +} + +######################################################################## +# Server funcs +######################################################################## + +sub read_log { + my $self = shift; + + for (;;) { + defined(sysread(STDIN, my $line, 8194)) + or die ref($self), " read log line failed: $!"; + chomp $line; + print STDERR ">>> $line\n"; + last if $line =~ /$downlog/; + } +} + +######################################################################## +# Script funcs +######################################################################## + +sub get_log { + return $testlog; +} + +sub check_logs { + my ($c, $r, $s, %args) = @_; + + return if $args{nocheck}; + + check_log($c, $r, $s, %args); + check_out($r, %args); + check_stat($r, %args); + check_kdump($c, $s, %args); +} + +sub check_pattern { + my ($name, $proc, $pattern, $func) = @_; + + $pattern = [ $pattern ] unless ref($pattern) eq 'ARRAY'; + foreach my $pat (@$pattern) { + if (ref($pat) eq 'HASH') { + while (my($re, $num) = each %$pat) { + my @matches = $func->($proc, $re); + @matches == $num + or die "$name matches '@matches': ", + "'$re' => $num"; + } + } else { + $func->($proc, $pat) + or die "$name log missing pattern: $pat"; + } + } +} + +sub check_log { + my ($c, $r, $s, %args) = @_; + + my %name2proc = (client => $c, syslogd => $r, server => $s); + foreach my $name (qw(client syslogd server)) { + next if $args{$name}{nocheck}; + my $p = $name2proc{$name} or next; + my $pattern = $args{$name}{loggrep} || $testlog; + check_pattern($name, $p, $pattern, \&loggrep); + } +} + +sub loggrep { + my ($proc, $pattern) = @_; + + return $proc->loggrep($pattern); +} + +sub check_out { + my ($r, %args) = @_; + + foreach my $name (qw(file pipe)) { + next if $args{$name}{nocheck}; + my $file = $r->{"out$name"} or next; + my $pattern = $args{$name}{loggrep} || $testlog; + check_pattern($name, $file, $pattern, \&filegrep); + } +} + +sub check_stat { + my ($r, %args) = @_; + + foreach my $name (qw(fstat)) { + next if $args{$name}{nocheck}; + my $file = $r->{$name} && $r->{"${name}file"} or next; + my $pattern = $args{$name}{loggrep} or next; + check_pattern($name, $file, $pattern, \&filegrep); + } +} + +sub filegrep { + my ($file, $pattern) = @_; + + open(my $fh, '<', $file) + or die "Open file $file for reading failed: $!"; + return wantarray ? + grep { /$pattern/ } <$fh> : first { /$pattern/ } <$fh>; +} + +sub check_kdump { + my ($c, $s, %args) = @_; + + my %name2proc = (client => $c, server => $s); + foreach my $name (qw(client server)) { + next unless $args{$name}{ktrace}; + my $p = $name2proc{$name} or next; + my $file = $p->{ktracefile} or next; + my $pattern = $args{$name}{kdump} or next; + check_pattern($name, $file, $pattern, \&kdumpgrep); + } +} + +sub kdumpgrep { + my ($file, $pattern) = @_; + + my @cmd = ("kdump", "-f", $file); + open(my $fh, '-|', @cmd) + or die "Open pipe from '@cmd' failed: $!"; + my @matches = grep { /$pattern/ } <$fh>; + close($fh) or die $! ? + "Close pipe from '@cmd' failed: $!" : + "Command '@cmd' failed: $?"; + return wantarray ? @matches : $matches[0]; +} + +1; diff --git a/regress/usr.sbin/syslogd/syslogd.pl b/regress/usr.sbin/syslogd/syslogd.pl new file mode 100644 index 00000000000..afe434fcae0 --- /dev/null +++ b/regress/usr.sbin/syslogd/syslogd.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# $OpenBSD: syslogd.pl,v 1.1.1.1 2014/08/20 20:52:14 bluhm Exp $ + +# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Client; +use Syslogd; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: syslogd.pl [test-args.pl]\n"; +} + +my $testfile; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $testfile = pop; + do $testfile + or die "Do test file $testfile failed: ", $@ || $!; +} +@ARGV == 0 or usage(); + +foreach my $name (qw(client syslogd server)) { + foreach my $action (qw(connect listen)) { + my $h = $args{$name}{$action} or next; + foreach my $k (qw(protocol domain addr port)) { + $args{$name}{"$action$k"} = $h->{$k}; + } + } +} +my $s = Server->new( + func => \&read_log, + listendomain => AF_INET, + listenaddr => "127.0.0.1", + %{$args{server}}, + testfile => $testfile, +) unless $args{server}{noserver}; +my $r = Syslogd->new( + connectaddr => "127.0.0.1", + connectport => $s && $s->{listenport}, + %{$args{syslogd}}, + testfile => $testfile, +); +my $c = Client->new( + func => \&write_log, + %{$args{client}}, + testfile => $testfile, +) unless $args{client}{noclient}; + +$s->run unless $args{server}{noserver}; +$r->run; +$r->up; +$c->run->up unless $args{client}{noclient}; +$s->up unless $args{server}{noserver}; + +$c->down unless $args{client}{noclient}; +$s->down unless $args{server}{noserver}; +$r->kill_child; +$r->down; + +check_logs($c, $r, $s, %args); |