1 #***************************************************************************
3 # Project ___| | | | _ \| |
5 # | (__| |_| | _ <| |___
6 # \___|\___/|_| \_\_____|
8 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
10 # This software is licensed as described in the file COPYING, which
11 # you should have received as part of this distribution. The terms
12 # are also available at https://curl.se/docs/copyright.html.
14 # You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 # copies of the Software, and permit persons to whom the Software is
16 # furnished to do so, under the terms of the COPYING file.
18 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 # KIND, either express or implied.
21 # SPDX-License-Identifier: curl
23 ###########################################################################
25 # This module contains functions that are useful for managing the lifecycle of
26 # test servers required when running tests. It is not intended for use within
27 # those servers, but rather for starting and stopping them.
36 use base qw(Exporter);
116 my %serverpidfile; # all server pid file names, identified by server id
117 my %serverportfile;# all server port file names, identified by server id
118 my $sshdvernum; # for socks server, ssh daemon version number
119 my $sshdverstr; # for socks server, ssh daemon version string
120 my $sshderror; # for socks server, ssh daemon version error
121 my %doesntrun; # servers that don't work, identified by pidfile
122 my %PORT = (nolisten => 47); # port we use for a local non-listening service
123 my $server_response_maxtime=13;
124 my $httptlssrv = find_httptlssrv();
125 my %run; # running server
126 my %runcert; # cert file currently in use by an ssl running server
127 my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
128 my $CLIENT6IP="[::1]"; # address which curl uses for incoming connections
129 my $posix_pwd=$pwd; # current working directory
130 my $h2cver = "h2c"; # this version is decided by the nghttp2 lib being used
131 my $portrange = 999; # space from which to choose a random port
132 # don't increase without making sure generated port
133 # numbers will always be valid (<=65535)
134 my $HOSTIP="127.0.0.1"; # address on which the test server listens
135 my $HOST6IP="[::1]"; # address on which the test server listens
136 my $HTTPUNIXPATH; # HTTP server Unix domain socket path
137 my $SOCKSUNIXPATH; # socks server Unix domain socket path
138 my $SSHSRVMD5 = "[uninitialized]"; # MD5 of ssh server public key
139 my $SSHSRVSHA256 = "[uninitialized]"; # SHA256 of ssh server public key
140 my $USER; # name of the current user
141 my $sshdid; # for socks server, ssh daemon version id
142 my $ftpchecktime=1; # time it took to verify our test FTP server
144 # Variables shared with runtests.pl
145 our $SOCKSIN="socksd-request.log"; # what curl sent to the SOCKS proxy
146 our $err_unexpected; # error instead of warning on server unexpectedly alive
147 our $debugprotocol; # nonzero for verbose server logs
148 our $stunnel; # path to stunnel command
151 #######################################################################
152 # Check for a command in the PATH of the test server.
155 my ($cmd, @extrapaths)=@_;
157 if ($^O eq 'MSWin32' || $^O eq 'dos' || $^O eq 'os2') {
158 # PATH separator is different
161 my @paths=(split(m/$sep/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
162 "/sbin", "/usr/bin", "/usr/local/bin", @extrapaths);
164 if( -x "$_/$cmd" . exe_ext('SYS') && ! -d "$_/$cmd" . exe_ext('SYS')) {
165 # executable bit but not a directory!
172 #######################################################################
173 # Create a server socket on a random (unused) port, then close it and
174 # return the port number
178 my $server = IO::Socket->new(LocalPort => 0,
179 Domain => $ipnum == 6 ? AF_INET6 : AF_INET,
183 or die "Couldn't create tcp server socket: $@\n";
185 return $server->sockport();
188 use File::Temp qw/ tempfile/;
190 #######################################################################
191 # Initialize configuration variables
192 sub initserverconfig {
193 my ($fh, $socks) = tempfile("/tmp/curl-socksd-XXXXXXXX");
196 my ($f2, $http) = tempfile("/tmp/curl-http-XXXXXXXX");
199 $SOCKSUNIXPATH = $socks; # SOCKS Unix domain socket
200 $HTTPUNIXPATH = $http; # HTTP Unix domain socket
201 $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
203 # get the name of the current user
204 $USER = $ENV{USER}; # Linux
206 $USER = $ENV{USERNAME}; # Windows
208 $USER = $ENV{LOGNAME}; # Some Unix (I think)
211 init_serverpidfile_hash();
214 #######################################################################
215 # Load serverpidfile and serverportfile hashes with file names for all
218 sub init_serverpidfile_hash {
219 for my $proto (('ftp', 'gopher', 'http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
220 for my $ssl (('', 's')) {
221 for my $ipvnum ((4, 6)) {
222 for my $idnum ((1, 2, 3)) {
223 my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
224 my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
226 $serverpidfile{$serv} = $pidf;
227 my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
229 $serverportfile{$serv} = $portf;
234 for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
235 'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
236 for my $ipvnum ((4, 6)) {
237 for my $idnum ((1, 2)) {
238 my $serv = servername_id($proto, $ipvnum, $idnum);
239 my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
241 $serverpidfile{$serv} = $pidf;
242 my $portf = server_portfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
244 $serverportfile{$serv} = $portf;
248 for my $proto (('http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
249 for my $ssl (('', 's')) {
250 my $serv = servername_id("$proto$ssl", "unix", 1);
251 my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
253 $serverpidfile{$serv} = $pidf;
254 my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
256 $serverportfile{$serv} = $portf;
262 #######################################################################
263 # Kill the processes that still have lock files in a directory
270 $dir = sys_native_abs_path($dir);
272 my $handle = "handle";
273 if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) {
274 $handle = "handle64";
276 if(checkcmd($handle)) {
277 my @handles = `$handle $dir -accepteula -nobanner`;
278 for my $tryhandle (@handles) {
279 # Skip the "No matching handles found." warning when returned
280 if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
281 logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
282 # Ignore stunnel since we cannot do anything about its locks
283 if("$3" eq "File" && "$1" ne "tstunnel.exe") {
284 logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
285 system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1");
295 #######################################################################
296 # Check if a given child process has just died. Reaps it if so.
300 if((not defined $pid) || $pid <= 0) {
303 use POSIX ":sys_wait_h";
304 my $rc = pidwait($pid, &WNOHANG);
305 return ($rc == $pid)?1:0;
309 ##############################################################################
310 # This function makes sure the right set of server is running for the
311 # specified test case. This is a useful design when we run single tests as not
312 # all servers need to run then!
314 # Returns: a string, blank if everything is fine or a reason why it failed, and
317 # 1 for an error starting the server
318 # 2 for not the first time getting an error starting the server
319 # 3 for a failure to stop a server in order to restart it
320 # 4 for an unsupported server type
325 for(my $i = scalar(@what) - 1; $i >= 0; $i--) {
326 my $srvrline = $what[$i];
327 chomp $srvrline if($srvrline);
328 if($srvrline =~ /^(\S+)((\s*)(.*))/) {
332 if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) {
333 $server = "${1}${4}${5}";
334 $tlsext = uc("TLS-${3}");
336 if(! grep /^\Q$server\E$/, @protocols) {
337 if(substr($server,0,5) ne "socks") {
339 return ("curl lacks $tlsext support", 4);
342 return ("curl lacks $server server support", 4);
346 $what[$i] = "$server$lnrest" if($tlsext);
350 return &startservers(@what);
354 #######################################################################
355 # Start a new thread/process and run the given command line in there.
356 # Return the pids (yes plural) of the new child process to the parent.
359 my ($cmd, $pidfile, $timeout, $fakepidfile)=@_;
361 logmsg "startnew: $cmd\n" if ($verbose);
365 if(not defined $child) {
366 logmsg "startnew: fork() failure detected\n";
371 # Here we are the child. Run the given command.
376 # Put an "exec" in front of the command so that the child process
377 # keeps this child's process ID.
378 exec("exec $cmd") || die "Can't exec() $cmd: $!";
380 # exec() should never return back here to this process. We protect
381 # ourselves by calling die() just in case something goes really bad.
382 die "error: exec() has returned";
385 # Ugly hack but ssh client and gnutls-serv don't support pid files
387 if(open(my $out, ">", "$pidfile")) {
388 print $out $child . "\n";
389 close($out) || die "Failure writing pidfile";
390 logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
393 logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
395 # could/should do a while connect fails sleep a bit and loop
396 portable_sleep($timeout);
397 if (checkdied($child)) {
398 logmsg "startnew: child process has failed to start\n" if($verbose);
404 my $count = $timeout;
406 $pid2 = pidfromfile($pidfile);
407 if(($pid2 > 0) && pidexists($pid2)) {
408 # if $pid2 is valid, then make sure this pid is alive, as
409 # otherwise it is just likely to be the _previous_ pidfile or
413 if (checkdied($child)) {
414 logmsg "startnew: child process has died, server might start up\n"
416 # We can't just abort waiting for the server with a
418 # because the server might have forked and could still start
419 # up normally. Instead, just reduce the amount of time we remain
426 # Return two PIDs, the one for the child process we spawned and the one
427 # reported by the server itself (in case it forked again on its own).
428 # Both (potentially) need to be killed at the end of the test.
429 return ($child, $pid2);
433 #######################################################################
434 # Return the port to use for the given protocol.
438 return $PORT{$proto} || "[not running]";
442 #######################################################################
443 # Stop a test server along with pids which aren't in the %run hash yet.
444 # This also stops all servers which are relative to the given one.
447 my ($server, $pidlist) = @_;
450 # kill sockfilter processes for pingpong relative server
452 if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
454 my $idnum = ($2 && ($2 > 1)) ? $2 : 1;
455 my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
456 killsockfilters("$LOGDIR/$PIDDIR", $proto, $ipvnum, $idnum, $verbose);
459 # All servers relative to the given one must be stopped also
462 if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
463 # given a stunnel based ssl server, also kill non-ssl underlying one
464 push @killservers, "${1}${2}";
466 elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
467 # given a non-ssl server, also kill stunnel based ssl piggybacking one
468 push @killservers, "${1}s${2}";
470 elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
471 # given a socks server, also kill ssh underlying one
472 push @killservers, "ssh${2}";
474 elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
475 # given a ssh server, also kill socks piggybacking one
476 push @killservers, "socks${2}";
478 if($server eq "http" or $server eq "https") {
479 # since the http2+3 server is a proxy that needs to know about the
480 # dynamic http port it too needs to get restarted when the http server
482 push @killservers, "http/2";
483 push @killservers, "http/3";
485 push @killservers, $server;
487 # kill given pids and server relative ones clearing them in %run hash
489 foreach my $server (@killservers) {
491 # we must prepend a space since $pidlist may already contain a pid
492 $pidlist .= " $run{$server}";
495 $runcert{$server} = 0 if($runcert{$server});
497 killpid($verbose, $pidlist);
499 # cleanup server pid files
502 foreach my $server (@killservers) {
503 my $pidfile = $serverpidfile{$server};
504 my $pid = processexists($pidfile);
506 if($err_unexpected) {
513 logmsg "$server server unexpectedly alive\n";
514 killpid($verbose, $pid);
516 unlink($pidfile) if(-f $pidfile);
523 #######################################################################
524 # Return flags to let curl use an external HTTP proxy
526 sub getexternalproxyflags {
527 return " --proxy $proxy_address ";
530 #######################################################################
531 # Verify that the server that runs on $ip, $port is our server. This also
532 # implies that we can speak with it, as there might be occasions when the
533 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
534 # assign requested address")
537 my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
538 my $server = servername_id($proto, $ipvnum, $idnum);
540 # $port_or_path contains a path for Unix sockets, sws ignores the port
541 my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
543 my $verifyout = "$LOGDIR/".
544 servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
545 unlink($verifyout) if(-f $verifyout);
547 my $verifylog = "$LOGDIR/".
548 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
549 unlink($verifylog) if(-f $verifylog);
551 if($proto eq "gopher") {
556 my $flags = "--max-time $server_response_maxtime ";
557 $flags .= "--output $verifyout ";
558 $flags .= "--silent ";
559 $flags .= "--verbose ";
560 $flags .= "--globoff ";
561 $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
562 $flags .= "--insecure " if($proto eq 'https');
564 $flags .= getexternalproxyflags();
566 $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
568 my $cmd = "$VCURL $flags 2>$verifylog";
570 # verify if our/any server is running on this port
571 logmsg "RUN: $cmd\n" if($verbose);
572 my $res = runclient($cmd);
574 $res >>= 8; # rotate the result
576 logmsg "RUN: curl command died with a coredump\n";
580 if($res && $verbose) {
581 logmsg "RUN: curl command returned $res\n";
582 if(open(my $file, "<", "$verifylog")) {
583 while(my $string = <$file>) {
584 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
591 if(open(my $file, "<", "$verifyout")) {
592 while(my $string = <$file>) {
594 last; # only want first line
600 if($data && ($data =~ /WE ROOLZ: (\d+)/)) {
604 # curl: (6) Couldn't resolve host '::1'
605 logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
608 elsif($data || ($res && ($res != 7))) {
609 logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
615 #######################################################################
616 # Verify that the server that runs on $ip, $port is our server. This also
617 # implies that we can speak with it, as there might be occasions when the
618 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
619 # assign requested address")
622 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
623 my $server = servername_id($proto, $ipvnum, $idnum);
627 my $verifylog = "$LOGDIR/".
628 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
629 unlink($verifylog) if(-f $verifylog);
631 if($proto eq "ftps") {
632 $extra .= "--insecure --ftp-ssl-control ";
635 my $flags = "--max-time $server_response_maxtime ";
636 $flags .= "--silent ";
637 $flags .= "--verbose ";
638 $flags .= "--globoff ";
641 $flags .= getexternalproxyflags();
643 $flags .= "\"$proto://$ip:$port/verifiedserver\"";
645 my $cmd = "$VCURL $flags 2>$verifylog";
647 # check if this is our server running on this port:
648 logmsg "RUN: $cmd\n" if($verbose);
649 my @data = runclientoutput($cmd);
651 my $res = $? >> 8; # rotate the result
653 logmsg "RUN: curl command died with a coredump\n";
658 foreach my $line (@data) {
659 if($line =~ /WE ROOLZ: (\d+)/) {
660 # this is our test server with a known pid!
665 if($pid <= 0 && @data && $data[0]) {
666 # this is not a known server
667 logmsg "RUN: Unknown server on our $server port: $port\n";
670 # we can/should use the time it took to verify the FTP server as a measure
671 # on how fast/slow this host/FTP is.
672 my $took = int(0.5+time()-$time);
675 logmsg "RUN: Verifying our test $server server took $took seconds\n";
677 $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
682 #######################################################################
683 # Verify that the server that runs on $ip, $port is our server. This also
684 # implies that we can speak with it, as there might be occasions when the
685 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
686 # assign requested address")
689 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
690 my $server = servername_id($proto, $ipvnum, $idnum);
692 my $verifyout = "$LOGDIR/".
693 servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
694 unlink($verifyout) if(-f $verifyout);
696 my $verifylog = "$LOGDIR/".
697 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
698 unlink($verifylog) if(-f $verifylog);
700 my $flags = "--max-time $server_response_maxtime ";
701 $flags .= "--output $verifyout ";
702 $flags .= "--silent ";
703 $flags .= "--verbose ";
704 $flags .= "--globoff ";
706 $flags .= getexternalproxyflags();
708 # currently verification is done using http
709 $flags .= "\"http://$ip:$port/verifiedserver\"";
711 my $cmd = "$VCURL $flags 2>$verifylog";
713 # verify if our/any server is running on this port
714 logmsg "RUN: $cmd\n" if($verbose);
715 my $res = runclient($cmd);
717 $res >>= 8; # rotate the result
719 logmsg "RUN: curl command died with a coredump\n";
723 if($res && $verbose) {
724 logmsg "RUN: curl command returned $res\n";
725 if(open(my $file, "<", "$verifylog")) {
726 while(my $string = <$file>) {
727 logmsg "RUN: $string" if($string !~ /^[ \t]*$/);
734 if(open(my $file, "<", "$verifyout")) {
735 while(my $string = <$file>) {
737 last; # only want first line
743 if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) {
747 # curl: (6) Couldn't resolve host '::1'
748 logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
751 elsif($data || ($res != 7)) {
752 logmsg "RUN: Unknown server on our $server port: $port\n";
758 #######################################################################
759 # Verify that the ssh server has written out its pidfile, recovering
760 # the pid from the file and returning it if a process with that pid is
761 # actually alive, or a negative value if the process is dead.
764 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
765 my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
767 my $pid = processexists($pidfile);
769 logmsg "RUN: SSH server has died after starting up\n";
774 #######################################################################
775 # Verify that we can connect to the sftp server, properly authenticate
776 # with generated config and key files and run a simple remote pwd.
779 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
780 my $server = servername_id($proto, $ipvnum, $idnum);
782 # Find out sftp client canonical file name
783 my $sftp = find_sftp();
785 logmsg "RUN: SFTP server cannot find $sftpexe\n";
788 # Find out ssh client canonical file name
789 my $ssh = find_ssh();
791 logmsg "RUN: SFTP server cannot find $sshexe\n";
794 # Connect to sftp server, authenticate and run a remote pwd
795 # command using our generated configuration and key files
796 my $cmd = "\"$sftp\" -b $LOGDIR/$PIDDIR/$sftpcmds -F $LOGDIR/$PIDDIR/$sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1";
797 my $res = runclient($cmd);
798 # Search for pwd command response in log file
799 if(open(my $sftplogfile, "<", "$sftplog")) {
800 while(<$sftplogfile>) {
801 if(/^Remote working directory: /) {
811 #######################################################################
812 # Verify that the non-stunnel HTTP TLS extensions capable server that runs
813 # on $ip, $port is our server. This also implies that we can speak with it,
814 # as there might be occasions when the server runs fine but we cannot talk
815 # to it ("Failed to connect to ::1: Can't assign requested address")
818 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
819 my $server = servername_id($proto, $ipvnum, $idnum);
820 my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
823 my $verifyout = "$LOGDIR/".
824 servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
825 unlink($verifyout) if(-f $verifyout);
827 my $verifylog = "$LOGDIR/".
828 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
829 unlink($verifylog) if(-f $verifylog);
831 my $flags = "--max-time $server_response_maxtime ";
832 $flags .= "--output $verifyout ";
833 $flags .= "--verbose ";
834 $flags .= "--globoff ";
835 $flags .= "--insecure ";
836 $flags .= "--tlsauthtype SRP ";
837 $flags .= "--tlsuser jsmith ";
838 $flags .= "--tlspassword abc ";
840 $flags .= getexternalproxyflags();
842 $flags .= "\"https://$ip:$port/verifiedserver\"";
844 my $cmd = "$VCURL $flags 2>$verifylog";
846 # verify if our/any server is running on this port
847 logmsg "RUN: $cmd\n" if($verbose);
848 my $res = runclient($cmd);
850 $res >>= 8; # rotate the result
852 logmsg "RUN: curl command died with a coredump\n";
856 if($res && $verbose) {
857 logmsg "RUN: curl command returned $res\n";
858 if(open(my $file, "<", "$verifylog")) {
859 while(my $string = <$file>) {
860 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
867 if(open(my $file, "<", "$verifyout")) {
868 while(my $string = <$file>) {
875 if($data && ($data =~ /(GNUTLS|GnuTLS)/) && ($pid = processexists($pidfile))) {
877 logmsg "RUN: $server server has died after starting up\n";
882 # curl: (6) Couldn't resolve host '::1'
883 logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n";
886 elsif($data || ($res && ($res != 7))) {
887 logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
893 #######################################################################
894 # STUB for verifying socks
897 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
898 my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
900 my $pid = processexists($pidfile);
902 logmsg "RUN: SOCKS server has died after starting up\n";
907 #######################################################################
908 # Verify that the server that runs on $ip, $port is our server. This also
909 # implies that we can speak with it, as there might be occasions when the
910 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
911 # assign requested address")
914 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
915 my $server = servername_id($proto, $ipvnum, $idnum);
919 my $verifylog = "$LOGDIR/".
920 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
921 unlink($verifylog) if(-f $verifylog);
923 my $flags = "--max-time $server_response_maxtime ";
924 $flags .= "--silent ";
925 $flags .= "--verbose ";
926 $flags .= "--globoff ";
927 $flags .= "-u 'curltest:curltest' ";
929 $flags .= "\"$proto://$ip:$port/SERVER/verifiedserver\"";
931 my $cmd = "$VCURL $flags 2>$verifylog";
933 # check if this is our server running on this port:
934 logmsg "RUN: $cmd\n" if($verbose);
935 my @data = runclientoutput($cmd);
937 my $res = $? >> 8; # rotate the result
939 logmsg "RUN: curl command died with a coredump\n";
944 foreach my $line (@data) {
945 if($line =~ /WE ROOLZ: (\d+)/) {
946 # this is our test server with a known pid!
951 if($pid <= 0 && @data && $data[0]) {
952 # this is not a known server
953 logmsg "RUN: Unknown server on our $server port: $port\n";
956 # we can/should use the time it took to verify the server as a measure
957 # on how fast/slow this host is.
958 my $took = int(0.5+time()-$time);
961 logmsg "RUN: Verifying our test $server server took $took seconds\n";
967 #######################################################################
968 # Verify that the server that runs on $ip, $port is our server. This also
969 # implies that we can speak with it, as there might be occasions when the
970 # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
971 # assign requested address")
974 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
975 my $server = servername_id($proto, $ipvnum, $idnum);
979 my $verifylog = "$LOGDIR/".
980 servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
981 unlink($verifylog) if(-f $verifylog);
983 my $flags = "--max-time $server_response_maxtime ";
984 $flags .= "--silent ";
985 $flags .= "--verbose ";
986 $flags .= "--globoff ";
987 $flags .= "--upload-file - ";
989 $flags .= "\"$proto://$ip:$port\"";
991 my $cmd = "echo 'verifiedserver' | $VCURL $flags 2>$verifylog";
993 # check if this is our server running on this port:
994 logmsg "RUN: $cmd\n" if($verbose);
995 my @data = runclientoutput($cmd);
997 my $res = $? >> 8; # rotate the result
999 logmsg "RUN: curl command died with a coredump\n";
1004 foreach my $line (@data) {
1005 if($line =~ /WE ROOLZ: (\d+)/) {
1006 # this is our test server with a known pid!
1011 if($pid <= 0 && @data && $data[0]) {
1012 # this is not a known server
1013 logmsg "RUN: Unknown server on our $server port: $port\n";
1016 # we can/should use the time it took to verify the server as a measure
1017 # on how fast/slow this host is.
1018 my $took = int(0.5+time()-$time);
1021 logmsg "RUN: Verifying our test $server server took $took seconds\n";
1027 #######################################################################
1028 # Verify that the server that runs on $ip, $port is our server.
1029 # Retry over several seconds before giving up. The ssh server in
1030 # particular can take a long time to start if it needs to generate
1031 # keys on a slow or loaded host.
1033 # Just for convenience, test harness uses 'https' and 'httptls' literals
1034 # as values for 'proto' variable in order to differentiate different
1035 # servers. 'https' literal is used for stunnel based https test servers,
1036 # and 'httptls' is used for non-stunnel https test servers.
1039 my %protofunc = ('http' => \&verifyhttp,
1040 'https' => \&verifyhttp,
1041 'rtsp' => \&verifyrtsp,
1042 'ftp' => \&verifyftp,
1043 'pop3' => \&verifyftp,
1044 'imap' => \&verifyftp,
1045 'smtp' => \&verifyftp,
1046 'ftps' => \&verifyftp,
1047 'pop3s' => \&verifyftp,
1048 'imaps' => \&verifyftp,
1049 'smtps' => \&verifyftp,
1050 'tftp' => \&verifyftp,
1051 'ssh' => \&verifyssh,
1052 'socks' => \&verifysocks,
1053 'socks5unix' => \&verifysocks,
1054 'gopher' => \&verifyhttp,
1055 'httptls' => \&verifyhttptls,
1056 'dict' => \&verifyftp,
1057 'smb' => \&verifysmb,
1058 'telnet' => \&verifytelnet);
1061 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
1063 my $count = 30; # try for this many seconds
1067 my $fun = $protofunc{$proto};
1069 $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
1075 # a real failure, stop trying and bail out
1083 #######################################################################
1084 # Single shot server responsiveness test. This should only be used
1085 # to verify that a server present in %run hash is still functional
1087 sub responsiveserver {
1088 my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
1089 my $prev_verbose = $verbose;
1092 my $fun = $protofunc{$proto};
1093 my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
1094 $verbose = $prev_verbose;
1097 return 1; # responsive
1100 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1101 logmsg " server precheck FAILED (unresponsive $srvrname server)\n";
1106 #######################################################################
1107 # start the http server
1110 my ($proto, $verb, $alt, $port_or_path) = @_;
1114 my $exe = "$perl $srcdir/http-server.pl";
1115 my $verbose_flag = "--verbose ";
1116 my $keepalive_secs = 30; # forwarded to sws, was 5 by default which
1117 # led to pukes in CI jobs
1119 if($alt eq "ipv6") {
1120 # if IPv6, use a different setup
1124 elsif($alt eq "proxy") {
1125 # basically the same, but another ID
1128 elsif($alt eq "unix") {
1129 # IP (protocol) is mutually exclusive with Unix sockets
1133 my $server = servername_id($proto, $ipvnum, $idnum);
1135 my $pidfile = $serverpidfile{$server};
1137 # don't retry if the server doesn't work
1138 if ($doesntrun{$pidfile}) {
1139 return (2, 0, 0, 0);
1142 my $pid = processexists($pidfile);
1144 stopserver($server, "$pid");
1146 unlink($pidfile) if(-f $pidfile);
1148 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1149 my $portfile = $serverportfile{$server};
1151 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1154 $flags .= "--gopher " if($proto eq "gopher");
1155 $flags .= "--connect $HOSTIP " if($alt eq "proxy");
1156 $flags .= "--keepalive $keepalive_secs ";
1157 $flags .= $verbose_flag if($debugprotocol);
1158 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1159 $flags .= "--logdir \"$LOGDIR\" ";
1160 $flags .= "--portfile $portfile ";
1161 $flags .= "--config $LOGDIR/$SERVERCMD ";
1162 $flags .= "--id $idnum " if($idnum > 1);
1163 if($ipvnum eq "unix") {
1164 $flags .= "--unix-socket '$port_or_path' ";
1166 $flags .= "--ipv$ipvnum --port 0 ";
1168 $flags .= "--srcdir \"$srcdir\"";
1170 my $cmd = "$exe $flags";
1171 my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1173 if($httppid <= 0 || !pidexists($httppid)) {
1175 logmsg "RUN: failed to start the $srvrname server\n";
1176 stopserver($server, "$pid2");
1177 $doesntrun{$pidfile} = 1;
1178 return (1, 0, 0, 0);
1183 if(!$port_or_path) {
1184 $port = $port_or_path = pidfromfile($portfile);
1187 # Server is up. Verify that we can speak to it.
1188 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
1190 logmsg "RUN: $srvrname server failed verification\n";
1191 # failed to talk to it properly. Kill the server and return failure
1192 stopserver($server, "$httppid $pid2");
1193 $doesntrun{$pidfile} = 1;
1194 return (1, 0, 0, 0);
1199 logmsg "RUN: $srvrname server is on PID $httppid port $port_or_path\n";
1202 return (0, $httppid, $pid2, $port);
1206 #######################################################################
1207 # start the http2 server
1209 sub runhttp2server {
1214 my $exe = "$perl $srcdir/http2-server.pl";
1215 my $verbose_flag = "--verbose ";
1217 my $server = servername_id($proto, $ipvnum, $idnum);
1219 my $pidfile = $serverpidfile{$server};
1221 # don't retry if the server doesn't work
1222 if ($doesntrun{$pidfile}) {
1223 return (2, 0, 0, 0, 0);
1226 my $pid = processexists($pidfile);
1228 stopserver($server, "$pid");
1230 unlink($pidfile) if(-f $pidfile);
1232 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1233 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1236 $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
1237 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1238 $flags .= "--logdir \"$LOGDIR\" ";
1239 $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
1240 $flags .= $verbose_flag if($debugprotocol);
1242 my $port = getfreeport($ipvnum);
1243 my $port2 = getfreeport($ipvnum);
1244 my $aflags = "--port $port --port2 $port2 $flags";
1245 my $cmd = "$exe $aflags";
1246 my ($http2pid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1248 if($http2pid <= 0 || !pidexists($http2pid)) {
1250 stopserver($server, "$pid2");
1251 $doesntrun{$pidfile} = 1;
1252 $http2pid = $pid2 = 0;
1253 logmsg "RUN: failed to start the $srvrname server\n";
1254 return (3, 0, 0, 0, 0);
1256 $doesntrun{$pidfile} = 0;
1259 logmsg "RUN: $srvrname server PID $http2pid ".
1260 "http-port $port https-port $port2 ".
1261 "backend $HOSTIP:" . protoport("http") . "\n";
1264 return (0+!$http2pid, $http2pid, $pid2, $port, $port2);
1267 #######################################################################
1268 # start the http3 server
1270 sub runhttp3server {
1271 my ($verb, $cert) = @_;
1275 my $exe = "$perl $srcdir/http3-server.pl";
1276 my $verbose_flag = "--verbose ";
1278 my $server = servername_id($proto, $ipvnum, $idnum);
1280 my $pidfile = $serverpidfile{$server};
1282 # don't retry if the server doesn't work
1283 if ($doesntrun{$pidfile}) {
1284 return (2, 0, 0, 0);
1287 my $pid = processexists($pidfile);
1289 stopserver($server, "$pid");
1291 unlink($pidfile) if(-f $pidfile);
1293 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1294 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1297 $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
1298 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1299 $flags .= "--logdir \"$LOGDIR\" ";
1300 $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
1301 $flags .= "--cert \"$cert\" " if($cert);
1302 $flags .= $verbose_flag if($debugprotocol);
1304 my $port = getfreeport($ipvnum);
1305 my $aflags = "--port $port $flags";
1306 my $cmd = "$exe $aflags";
1307 my ($http3pid, $pid3) = startnew($cmd, $pidfile, 15, 0);
1309 if($http3pid <= 0 || !pidexists($http3pid)) {
1311 stopserver($server, "$pid3");
1312 $doesntrun{$pidfile} = 1;
1313 $http3pid = $pid3 = 0;
1314 logmsg "RUN: failed to start the $srvrname server\n";
1315 return (3, 0, 0, 0);
1317 $doesntrun{$pidfile} = 0;
1320 logmsg "RUN: $srvrname server PID $http3pid port $port\n";
1323 return (0+!$http3pid, $http3pid, $pid3, $port);
1326 #######################################################################
1327 # start the https stunnel based server
1329 sub runhttpsserver {
1330 my ($verb, $proto, $proxy, $certfile) = @_;
1335 if($proxy eq "proxy") {
1336 # the https-proxy runs as https2
1341 return (4, 0, 0, 0);
1344 my $server = servername_id($proto, $ipvnum, $idnum);
1346 my $pidfile = $serverpidfile{$server};
1348 # don't retry if the server doesn't work
1349 if ($doesntrun{$pidfile}) {
1350 return (2, 0, 0, 0);
1353 my $pid = processexists($pidfile);
1355 stopserver($server, "$pid");
1357 unlink($pidfile) if(-f $pidfile);
1359 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1360 $certfile = 'stunnel.pem' unless($certfile);
1361 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1364 $flags .= "--verbose " if($debugprotocol);
1365 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1366 $flags .= "--logdir \"$LOGDIR\" ";
1367 $flags .= "--id $idnum " if($idnum > 1);
1368 $flags .= "--ipv$ipvnum --proto $proto ";
1369 $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
1370 $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
1371 if($proto eq "gophers") {
1372 $flags .= "--connect " . protoport("gopher");
1375 $flags .= "--connect " . protoport("http");
1378 # for HTTPS-proxy we connect to the HTTP proxy
1379 $flags .= "--connect " . protoport("httpproxy");
1382 my $port = getfreeport($ipvnum);
1383 my $options = "$flags --accept $port";
1384 my $cmd = "$perl $srcdir/secureserver.pl $options";
1385 my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1387 if($httpspid <= 0 || !pidexists($httpspid)) {
1389 # don't call stopserver since that will also kill the dependent
1390 # server that has already been started properly
1391 $doesntrun{$pidfile} = 1;
1392 $httpspid = $pid2 = 0;
1393 logmsg "RUN: failed to start the $srvrname server\n";
1394 return (3, 0, 0, 0);
1397 $doesntrun{$pidfile} = 0;
1400 logmsg "RUN: $srvrname server is PID $httpspid port $port\n";
1403 $runcert{$server} = $certfile;
1405 return (0+!$httpspid, $httpspid, $pid2, $port);
1408 #######################################################################
1409 # start the non-stunnel HTTP TLS extensions capable server
1411 sub runhttptlsserver {
1412 my ($verb, $ipv6) = @_;
1413 my $proto = "httptls";
1414 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
1415 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
1422 my $server = servername_id($proto, $ipvnum, $idnum);
1424 my $pidfile = $serverpidfile{$server};
1426 # don't retry if the server doesn't work
1427 if ($doesntrun{$pidfile}) {
1428 return (2, 0, 0, 0);
1431 my $pid = processexists($pidfile);
1433 stopserver($server, "$pid");
1435 unlink($pidfile) if(-f $pidfile);
1437 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1438 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1441 $flags .= "--http ";
1442 $flags .= "--debug 1 " if($debugprotocol);
1443 $flags .= "--priority NORMAL:+SRP ";
1444 $flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
1445 $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
1447 my $port = getfreeport($ipvnum);
1448 my $allflags = "--port $port $flags";
1449 my $cmd = "$httptlssrv $allflags > $logfile 2>&1";
1450 my ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1);
1452 if($httptlspid <= 0 || !pidexists($httptlspid)) {
1454 stopserver($server, "$pid2");
1455 $doesntrun{$pidfile} = 1;
1456 $httptlspid = $pid2 = 0;
1457 logmsg "RUN: failed to start the $srvrname server\n";
1458 return (3, 0, 0, 0);
1460 $doesntrun{$pidfile} = 0;
1463 logmsg "RUN: $srvrname server PID $httptlspid port $port\n";
1465 return (0+!$httptlspid, $httptlspid, $pid2, $port);
1468 #######################################################################
1469 # start the pingpong server (FTP, POP3, IMAP, SMTP)
1471 sub runpingpongserver {
1472 my ($proto, $id, $verb, $ipv6) = @_;
1474 # Check the requested server
1475 if($proto !~ /^(?:ftp|imap|pop3|smtp)$/) {
1476 logmsg "Unsupported protocol $proto!!\n";
1480 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
1481 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
1482 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
1484 my $server = servername_id($proto, $ipvnum, $idnum);
1486 my $pidfile = $serverpidfile{$server};
1487 my $portfile = $serverportfile{$server};
1489 # don't retry if the server doesn't work
1490 if ($doesntrun{$pidfile}) {
1494 my $pid = processexists($pidfile);
1496 stopserver($server, "$pid");
1498 unlink($pidfile) if(-f $pidfile);
1500 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1501 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1504 $flags .= "--verbose " if($debugprotocol);
1505 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1506 $flags .= "--logdir \"$LOGDIR\" ";
1507 $flags .= "--portfile \"$portfile\" ";
1508 $flags .= "--srcdir \"$srcdir\" --proto $proto ";
1509 $flags .= "--id $idnum " if($idnum > 1);
1510 $flags .= "--ipv$ipvnum --port 0 --addr \"$ip\"";
1512 my $cmd = "$perl $srcdir/ftpserver.pl $flags";
1513 my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1515 if($ftppid <= 0 || !pidexists($ftppid)) {
1517 logmsg "RUN: failed to start the $srvrname server\n";
1518 stopserver($server, "$pid2");
1519 $doesntrun{$pidfile} = 1;
1524 my $port = pidfromfile($portfile);
1526 logmsg "PINGPONG runs on port $port ($portfile)\n" if($verb);
1528 # Server is up. Verify that we can speak to it.
1529 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
1531 logmsg "RUN: $srvrname server failed verification\n";
1532 # failed to talk to it properly. Kill the server and return failure
1533 stopserver($server, "$ftppid $pid2");
1534 $doesntrun{$pidfile} = 1;
1539 logmsg "RUN: $srvrname server is PID $ftppid port $port\n" if($verb);
1541 # Assign the correct port variable!
1542 $PORT{$proto . ($ipvnum == 6? '6': '')} = $port;
1544 return (0, $pid2, $ftppid);
1547 #######################################################################
1548 # start the ftps/imaps/pop3s/smtps server (or rather, tunnel)
1550 sub runsecureserver {
1551 my ($verb, $ipv6, $certfile, $proto, $clearport) = @_;
1552 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
1553 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
1557 return (4, 0, 0, 0);
1560 my $server = servername_id($proto, $ipvnum, $idnum);
1562 my $pidfile = $serverpidfile{$server};
1564 # don't retry if the server doesn't work
1565 if ($doesntrun{$pidfile}) {
1566 return (2, 0, 0, 0);
1569 my $pid = processexists($pidfile);
1571 stopserver($server, "$pid");
1573 unlink($pidfile) if(-f $pidfile);
1575 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1576 $certfile = 'stunnel.pem' unless($certfile);
1577 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1580 $flags .= "--verbose " if($debugprotocol);
1581 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
1582 $flags .= "--logdir \"$LOGDIR\" ";
1583 $flags .= "--id $idnum " if($idnum > 1);
1584 $flags .= "--ipv$ipvnum --proto $proto ";
1585 $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
1586 $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
1587 $flags .= "--connect $clearport";
1589 my $port = getfreeport($ipvnum);
1590 my $options = "$flags --accept $port";
1592 my $cmd = "$perl $srcdir/secureserver.pl $options";
1593 my ($protospid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1595 if($protospid <= 0 || !pidexists($protospid)) {
1597 # don't call stopserver since that will also kill the dependent
1598 # server that has already been started properly
1599 $doesntrun{$pidfile} = 1;
1600 $protospid = $pid2 = 0;
1601 logmsg "RUN: failed to start the $srvrname server\n";
1602 return (3, 0, 0, 0);
1605 $doesntrun{$pidfile} = 0;
1606 $runcert{$server} = $certfile;
1609 logmsg "RUN: $srvrname server is PID $protospid port $port\n";
1612 return (0+!$protospid, $protospid, $pid2, $port);
1615 #######################################################################
1616 # start the tftp server
1619 my ($id, $verb, $ipv6) = @_;
1623 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
1626 # if IPv6, use a different setup
1631 my $server = servername_id($proto, $ipvnum, $idnum);
1633 my $pidfile = $serverpidfile{$server};
1635 # don't retry if the server doesn't work
1636 if ($doesntrun{$pidfile}) {
1637 return (2, 0, 0, 0);
1640 my $pid = processexists($pidfile);
1642 stopserver($server, "$pid");
1644 unlink($pidfile) if(-f $pidfile);
1646 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1647 my $portfile = $serverportfile{$server};
1648 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1651 $flags .= "--verbose " if($debugprotocol);
1652 $flags .= "--pidfile \"$pidfile\" ";
1653 $flags .= "--portfile \"$portfile\" ";
1654 $flags .= "--logfile \"$logfile\" ";
1655 $flags .= "--logdir \"$LOGDIR\" ";
1656 $flags .= "--id $idnum " if($idnum > 1);
1657 $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
1659 my $cmd = "$perl $srcdir/tftpserver.pl $flags";
1660 my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1662 if($tftppid <= 0 || !pidexists($tftppid)) {
1664 logmsg "RUN: failed to start the $srvrname server\n";
1665 stopserver($server, "$pid2");
1666 $doesntrun{$pidfile} = 1;
1667 return (1, 0, 0, 0);
1670 my $port = pidfromfile($portfile);
1672 # Server is up. Verify that we can speak to it.
1673 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
1675 logmsg "RUN: $srvrname server failed verification\n";
1676 # failed to talk to it properly. Kill the server and return failure
1677 stopserver($server, "$tftppid $pid2");
1678 $doesntrun{$pidfile} = 1;
1679 return (1, 0, 0, 0);
1684 logmsg "RUN: $srvrname server on PID $tftppid port $port\n";
1687 return (0, $pid2, $tftppid, $port);
1691 #######################################################################
1692 # start the rtsp server
1695 my ($verb, $ipv6) = @_;
1702 # if IPv6, use a different setup
1707 my $server = servername_id($proto, $ipvnum, $idnum);
1709 my $pidfile = $serverpidfile{$server};
1710 my $portfile = $serverportfile{$server};
1712 # don't retry if the server doesn't work
1713 if ($doesntrun{$pidfile}) {
1714 return (2, 0, 0, 0);
1717 my $pid = processexists($pidfile);
1719 stopserver($server, "$pid");
1721 unlink($pidfile) if(-f $pidfile);
1723 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1724 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1727 $flags .= "--verbose " if($debugprotocol);
1728 $flags .= "--pidfile \"$pidfile\" ";
1729 $flags .= "--portfile \"$portfile\" ";
1730 $flags .= "--logfile \"$logfile\" ";
1731 $flags .= "--logdir \"$LOGDIR\" ";
1732 $flags .= "--id $idnum " if($idnum > 1);
1733 $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
1735 my $cmd = "$perl $srcdir/rtspserver.pl $flags";
1736 my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
1738 if($rtsppid <= 0 || !pidexists($rtsppid)) {
1740 logmsg "RUN: failed to start the $srvrname server\n";
1741 stopserver($server, "$pid2");
1742 $doesntrun{$pidfile} = 1;
1743 return (1, 0, 0, 0);
1746 my $port = pidfromfile($portfile);
1748 # Server is up. Verify that we can speak to it.
1749 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
1751 logmsg "RUN: $srvrname server failed verification\n";
1752 # failed to talk to it properly. Kill the server and return failure
1753 stopserver($server, "$rtsppid $pid2");
1754 $doesntrun{$pidfile} = 1;
1755 return (1, 0, 0, 0);
1760 logmsg "RUN: $srvrname server PID $rtsppid port $port\n";
1763 return (0, $rtsppid, $pid2, $port);
1767 #######################################################################
1768 # Start the ssh (scp/sftp) server
1771 my ($id, $verb, $ipv6) = @_;
1775 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
1778 logmsg "Can't start ssh server due to lack of USER name\n";
1779 return (4, 0, 0, 0);
1782 my $server = servername_id($proto, $ipvnum, $idnum);
1784 my $pidfile = $serverpidfile{$server};
1786 # don't retry if the server doesn't work
1787 if ($doesntrun{$pidfile}) {
1788 return (2, 0, 0, 0);
1791 my $sshd = find_sshd();
1793 ($sshdid,$sshdvernum,$sshdverstr,$sshderror) = sshversioninfo($sshd);
1794 logmsg $sshderror if($sshderror);
1797 my $pid = processexists($pidfile);
1799 stopserver($server, "$pid");
1801 unlink($pidfile) if(-f $pidfile);
1803 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1804 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1807 $flags .= "--verbose " if($verb);
1808 $flags .= "--debugprotocol " if($debugprotocol);
1809 $flags .= "--pidfile \"$pidfile\" ";
1810 $flags .= "--logdir \"$LOGDIR\" ";
1811 $flags .= "--id $idnum " if($idnum > 1);
1812 $flags .= "--ipv$ipvnum --addr \"$ip\" ";
1813 $flags .= "--user \"$USER\"";
1816 my $port = getfreeport($ipvnum);
1818 push @tports, $port;
1820 my $options = "$flags --sshport $port";
1822 my $cmd = "$perl $srcdir/sshserver.pl $options";
1823 my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
1825 # on loaded systems sshserver start up can take longer than the
1826 # timeout passed to startnew, when this happens startnew completes
1827 # without being able to read the pidfile and consequently returns a
1829 if($sshpid <= 0 || !pidexists($sshpid)) {
1831 stopserver($server, "$pid2");
1832 $doesntrun{$pidfile} = 1;
1833 $sshpid = $pid2 = 0;
1834 logmsg "RUN: failed to start the $srvrname server on $port\n";
1835 return (3, 0, 0, 0);
1838 # once it is known that the ssh server is alive, sftp server
1839 # verification is performed actually connecting to it, authenticating
1840 # and performing a very simple remote command. This verification is
1841 # tried only one time.
1843 $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
1844 $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
1846 if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
1847 logmsg "RUN: SFTP server failed verification\n";
1848 # failed to talk to it properly. Kill the server and return failure
1850 display_sftpconfig();
1852 display_sshdconfig();
1853 stopserver($server, "$sshpid $pid2");
1854 $doesntrun{$pidfile} = 1;
1855 $sshpid = $pid2 = 0;
1856 logmsg "RUN: failed to verify the $srvrname server on $port\n";
1857 return (5, 0, 0, 0);
1859 # we're happy, no need to loop anymore!
1860 $doesntrun{$pidfile} = 0;
1863 if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubmd5f") ||
1864 (read($hostfile, $SSHSRVMD5, 32) != 32) ||
1865 !close($hostfile) ||
1866 ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
1868 my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
1874 if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubsha256f") ||
1875 (read($hostfile, $SSHSRVSHA256, 48) == 0) ||
1878 my $msg = "Fatal: $srvrname pubkey sha256 missing : \"$hstpubsha256f\" : $!";
1884 logmsg "RUN: $srvrname on PID $pid2 port $port\n" if($verb);
1886 return (0, $pid2, $sshpid, $port);
1889 #######################################################################
1890 # Start the MQTT server
1893 my ($id, $verb, $ipv6) = @_;
1896 my $port = protoport($proto);
1898 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
1900 my $server = servername_id($proto, $ipvnum, $idnum);
1901 my $pidfile = $serverpidfile{$server};
1902 my $portfile = $serverportfile{$server};
1904 # don't retry if the server doesn't work
1905 if ($doesntrun{$pidfile}) {
1909 my $pid = processexists($pidfile);
1911 stopserver($server, "$pid");
1913 unlink($pidfile) if(-f $pidfile);
1915 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1916 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1918 # start our MQTT server - on a random port!
1919 my $cmd="server/mqttd".exe_ext('SRV').
1921 " --pidfile $pidfile".
1922 " --portfile $portfile".
1923 " --config $LOGDIR/$SERVERCMD".
1924 " --logfile $logfile".
1925 " --logdir $LOGDIR";
1926 my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
1928 if($sockspid <= 0 || !pidexists($sockspid)) {
1930 logmsg "RUN: failed to start the $srvrname server\n";
1931 stopserver($server, "$pid2");
1932 $doesntrun{$pidfile} = 1;
1936 my $mqttport = pidfromfile($portfile);
1937 $PORT{"mqtt"} = $mqttport;
1940 logmsg "RUN: $srvrname server is now running PID $pid2 on PORT $mqttport\n";
1943 return (0, $pid2, $sockspid);
1946 #######################################################################
1947 # Start the socks server
1949 sub runsocksserver {
1950 my ($id, $verb, $ipv6, $is_unix) = @_;
1952 my $proto = 'socks';
1954 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
1956 my $server = servername_id($proto, $ipvnum, $idnum);
1958 my $pidfile = $serverpidfile{$server};
1960 # don't retry if the server doesn't work
1961 if ($doesntrun{$pidfile}) {
1962 return (2, 0, 0, 0);
1965 my $pid = processexists($pidfile);
1967 stopserver($server, "$pid");
1969 unlink($pidfile) if(-f $pidfile);
1971 my $srvrname = servername_str($proto, $ipvnum, $idnum);
1972 my $portfile = $serverportfile{$server};
1973 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
1975 # start our socks server, get commands from the FTP cmd file
1978 $cmd="server/socksd".exe_ext('SRV').
1979 " --pidfile $pidfile".
1980 " --reqfile $LOGDIR/$SOCKSIN".
1981 " --logfile $logfile".
1982 " --unix-socket $SOCKSUNIXPATH".
1983 " --backend $HOSTIP".
1984 " --config $LOGDIR/$SERVERCMD";
1986 $cmd="server/socksd".exe_ext('SRV').
1988 " --pidfile $pidfile".
1989 " --portfile $portfile".
1990 " --reqfile $LOGDIR/$SOCKSIN".
1991 " --logfile $logfile".
1992 " --backend $HOSTIP".
1993 " --config $LOGDIR/$SERVERCMD";
1995 my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
1997 if($sockspid <= 0 || !pidexists($sockspid)) {
1999 logmsg "RUN: failed to start the $srvrname server\n";
2000 stopserver($server, "$pid2");
2001 $doesntrun{$pidfile} = 1;
2002 return (1, 0, 0, 0);
2005 my $port = pidfromfile($portfile);
2008 logmsg "RUN: $srvrname server is now running PID $pid2\n";
2011 return (0, $pid2, $sockspid, $port);
2014 #######################################################################
2015 # start the dict server
2018 my ($verb, $alt) = @_;
2024 if($alt eq "ipv6") {
2028 my $server = servername_id($proto, $ipvnum, $idnum);
2030 my $pidfile = $serverpidfile{$server};
2032 # don't retry if the server doesn't work
2033 if ($doesntrun{$pidfile}) {
2034 return (2, 0, 0, 0);
2037 my $pid = processexists($pidfile);
2039 stopserver($server, "$pid");
2041 unlink($pidfile) if(-f $pidfile);
2043 my $srvrname = servername_str($proto, $ipvnum, $idnum);
2044 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
2047 $flags .= "--verbose 1 " if($debugprotocol);
2048 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
2049 $flags .= "--id $idnum " if($idnum > 1);
2050 $flags .= "--srcdir \"$srcdir\" ";
2051 $flags .= "--host $HOSTIP";
2053 my $port = getfreeport($ipvnum);
2054 my $aflags = "--port $port $flags";
2055 my $cmd = "$srcdir/dictserver.py $aflags";
2056 my ($dictpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
2058 if($dictpid <= 0 || !pidexists($dictpid)) {
2060 stopserver($server, "$pid2");
2061 $doesntrun{$pidfile} = 1;
2062 $dictpid = $pid2 = 0;
2063 logmsg "RUN: failed to start the $srvrname server\n";
2064 return (3, 0, 0, 0);
2066 $doesntrun{$pidfile} = 0;
2069 logmsg "RUN: $srvrname server PID $dictpid port $port\n";
2072 return (0+!$dictpid, $dictpid, $pid2, $port);
2075 #######################################################################
2076 # start the SMB server
2079 my ($verb, $alt) = @_;
2085 if($alt eq "ipv6") {
2089 my $server = servername_id($proto, $ipvnum, $idnum);
2091 my $pidfile = $serverpidfile{$server};
2093 # don't retry if the server doesn't work
2094 if ($doesntrun{$pidfile}) {
2095 return (2, 0, 0, 0);
2098 my $pid = processexists($pidfile);
2100 stopserver($server, "$pid");
2102 unlink($pidfile) if(-f $pidfile);
2104 my $srvrname = servername_str($proto, $ipvnum, $idnum);
2105 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
2108 $flags .= "--verbose 1 " if($debugprotocol);
2109 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
2110 $flags .= "--id $idnum " if($idnum > 1);
2111 $flags .= "--srcdir \"$srcdir\" ";
2112 $flags .= "--host $HOSTIP";
2114 my $port = getfreeport($ipvnum);
2115 my $aflags = "--port $port $flags";
2116 my $cmd = "$srcdir/smbserver.py $aflags";
2117 my ($smbpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
2119 if($smbpid <= 0 || !pidexists($smbpid)) {
2121 stopserver($server, "$pid2");
2122 $doesntrun{$pidfile} = 1;
2123 $smbpid = $pid2 = 0;
2124 logmsg "RUN: failed to start the $srvrname server\n";
2125 return (3, 0, 0, 0);
2127 $doesntrun{$pidfile} = 0;
2130 logmsg "RUN: $srvrname server PID $smbpid port $port\n";
2133 return (0+!$smbpid, $smbpid, $pid2, $port);
2136 #######################################################################
2137 # start the telnet server
2139 sub runnegtelnetserver {
2140 my ($verb, $alt) = @_;
2141 my $proto = "telnet";
2146 if($alt eq "ipv6") {
2150 my $server = servername_id($proto, $ipvnum, $idnum);
2152 my $pidfile = $serverpidfile{$server};
2154 # don't retry if the server doesn't work
2155 if ($doesntrun{$pidfile}) {
2156 return (2, 0, 0, 0);
2159 my $pid = processexists($pidfile);
2161 stopserver($server, "$pid");
2163 unlink($pidfile) if(-f $pidfile);
2165 my $srvrname = servername_str($proto, $ipvnum, $idnum);
2166 my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
2169 $flags .= "--verbose 1 " if($debugprotocol);
2170 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
2171 $flags .= "--id $idnum " if($idnum > 1);
2172 $flags .= "--srcdir \"$srcdir\"";
2174 my $port = getfreeport($ipvnum);
2175 my $aflags = "--port $port $flags";
2176 my $cmd = "$srcdir/negtelnetserver.py $aflags";
2177 my ($ntelpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
2179 if($ntelpid <= 0 || !pidexists($ntelpid)) {
2181 stopserver($server, "$pid2");
2182 $doesntrun{$pidfile} = 1;
2183 $ntelpid = $pid2 = 0;
2184 logmsg "RUN: failed to start the $srvrname server\n";
2185 return (3, 0, 0, 0);
2187 $doesntrun{$pidfile} = 0;
2190 logmsg "RUN: $srvrname server PID $ntelpid port $port\n";
2193 return (0+!$ntelpid, $ntelpid, $pid2, $port);
2199 #######################################################################
2200 # Single shot http and gopher server responsiveness test. This should only
2201 # be used to verify that a server present in %run hash is still functional
2203 sub responsive_http_server {
2204 my ($proto, $verb, $alt, $port_or_path) = @_;
2209 if($alt eq "ipv6") {
2210 # if IPv6, use a different setup
2214 elsif($alt eq "proxy") {
2217 elsif($alt eq "unix") {
2218 # IP (protocol) is mutually exclusive with Unix sockets
2222 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
2225 #######################################################################
2226 # Single shot pingpong server responsiveness test. This should only be
2227 # used to verify that a server present in %run hash is still functional
2229 sub responsive_pingpong_server {
2230 my ($proto, $id, $verb, $ipv6) = @_;
2232 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
2233 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
2234 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
2235 my $protoip = $proto . ($ipvnum == 6? '6': '');
2237 if($proto =~ /^(?:ftp|imap|pop3|smtp)$/) {
2238 $port = protoport($protoip);
2241 logmsg "Unsupported protocol $proto!!\n";
2245 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
2248 #######################################################################
2249 # Single shot rtsp server responsiveness test. This should only be
2250 # used to verify that a server present in %run hash is still functional
2252 sub responsive_rtsp_server {
2253 my ($verb, $ipv6) = @_;
2255 my $port = protoport($proto);
2261 # if IPv6, use a different setup
2263 $port = protoport('rtsp6');
2267 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
2270 #######################################################################
2271 # Single shot tftp server responsiveness test. This should only be
2272 # used to verify that a server present in %run hash is still functional
2274 sub responsive_tftp_server {
2275 my ($id, $verb, $ipv6) = @_;
2277 my $port = protoport($proto);
2280 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
2283 # if IPv6, use a different setup
2285 $port = protoport('tftp6');
2289 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
2292 #######################################################################
2293 # Single shot non-stunnel HTTP TLS extensions capable server
2294 # responsiveness test. This should only be used to verify that a
2295 # server present in %run hash is still functional
2297 sub responsive_httptls_server {
2298 my ($verb, $ipv6) = @_;
2299 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
2300 my $proto = "httptls";
2301 my $port = protoport($proto);
2306 $port = protoport("httptls6");
2310 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
2313 #######################################################################
2314 # startservers() starts all the named servers
2316 # Returns: string with error reason or blank for success, and an integer:
2318 # 1 for an error starting the server
2319 # 2 for not the first time getting an error starting the server
2320 # 3 for a failure to stop a server in order to restart it
2321 # 4 for an unsupported server type
2326 my $serr; # error while starting a server (as as the return enumerations)
2328 my (@whatlist) = split(/\s+/,$_);
2329 my $what = lc($whatlist[0]);
2330 $what =~ s/[^a-z0-9\/-]//g;
2333 if($what =~ /^(ftp|gopher|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
2334 $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
2337 if(($what eq "pop3") ||
2339 ($what eq "imap") ||
2340 ($what eq "smtp")) {
2341 if($torture && $run{$what} &&
2342 !responsive_pingpong_server($what, "", $verbose)) {
2343 if(stopserver($what)) {
2344 return ("failed stopping unresponsive ".uc($what)." server", 3);
2348 ($serr, $pid, $pid2) = runpingpongserver($what, "", $verbose);
2350 return ("failed starting ". uc($what) ." server", $serr);
2352 logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2) if($verbose);
2353 $run{$what}="$pid $pid2";
2356 elsif($what eq "ftp-ipv6") {
2357 if($torture && $run{'ftp-ipv6'} &&
2358 !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
2359 if(stopserver('ftp-ipv6')) {
2360 return ("failed stopping unresponsive FTP-IPv6 server", 3);
2363 if(!$run{'ftp-ipv6'}) {
2364 ($serr, $pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6");
2366 return ("failed starting FTP-IPv6 server", $serr);
2368 logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid,
2369 $pid2) if($verbose);
2370 $run{'ftp-ipv6'}="$pid $pid2";
2373 elsif($what eq "gopher") {
2374 if($torture && $run{'gopher'} &&
2375 !responsive_http_server("gopher", $verbose, 0,
2376 protoport("gopher"))) {
2377 if(stopserver('gopher')) {
2378 return ("failed stopping unresponsive GOPHER server", 3);
2381 if(!$run{'gopher'}) {
2382 ($serr, $pid, $pid2, $PORT{'gopher'}) =
2383 runhttpserver("gopher", $verbose, 0);
2385 return ("failed starting GOPHER server", $serr);
2387 logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2)
2389 $run{'gopher'}="$pid $pid2";
2392 elsif($what eq "gopher-ipv6") {
2393 if($torture && $run{'gopher-ipv6'} &&
2394 !responsive_http_server("gopher", $verbose, "ipv6",
2395 protoport("gopher"))) {
2396 if(stopserver('gopher-ipv6')) {
2397 return ("failed stopping unresponsive GOPHER-IPv6 server", 3);
2400 if(!$run{'gopher-ipv6'}) {
2401 ($serr, $pid, $pid2, $PORT{"gopher6"}) =
2402 runhttpserver("gopher", $verbose, "ipv6");
2404 return ("failed starting GOPHER-IPv6 server", $serr);
2406 logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid,
2407 $pid2) if($verbose);
2408 $run{'gopher-ipv6'}="$pid $pid2";
2411 elsif($what eq "http/3") {
2412 if(!$run{'http/3'}) {
2413 ($serr, $pid, $pid2, $PORT{"http3"}) = runhttp3server($verbose);
2415 return ("failed starting HTTP/3 server", $serr);
2417 logmsg sprintf ("* pid http/3 => %d %d\n", $pid, $pid2)
2419 $run{'http/3'}="$pid $pid2";
2422 elsif($what eq "http/2") {
2423 if(!$run{'http/2'}) {
2424 ($serr, $pid, $pid2, $PORT{"http2"}, $PORT{"http2tls"}) =
2425 runhttp2server($verbose);
2427 return ("failed starting HTTP/2 server", $serr);
2429 logmsg sprintf ("* pid http/2 => %d %d\n", $pid, $pid2)
2431 $run{'http/2'}="$pid $pid2";
2434 elsif($what eq "http") {
2435 if($torture && $run{'http'} &&
2436 !responsive_http_server("http", $verbose, 0, protoport('http'))) {
2437 if(stopserver('http')) {
2438 return ("failed stopping unresponsive HTTP server", 3);
2442 ($serr, $pid, $pid2, $PORT{'http'}) =
2443 runhttpserver("http", $verbose, 0);
2445 return ("failed starting HTTP server", $serr);
2447 logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2)
2449 $run{'http'}="$pid $pid2";
2452 elsif($what eq "http-proxy") {
2453 if($torture && $run{'http-proxy'} &&
2454 !responsive_http_server("http", $verbose, "proxy",
2455 protoport("httpproxy"))) {
2456 if(stopserver('http-proxy')) {
2457 return ("failed stopping unresponsive HTTP-proxy server", 3);
2460 if(!$run{'http-proxy'}) {
2461 ($serr, $pid, $pid2, $PORT{"httpproxy"}) =
2462 runhttpserver("http", $verbose, "proxy");
2464 return ("failed starting HTTP-proxy server", $serr);
2466 logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2)
2468 $run{'http-proxy'}="$pid $pid2";
2471 elsif($what eq "http-ipv6") {
2472 if($torture && $run{'http-ipv6'} &&
2473 !responsive_http_server("http", $verbose, "ipv6",
2474 protoport("http6"))) {
2475 if(stopserver('http-ipv6')) {
2476 return ("failed stopping unresponsive HTTP-IPv6 server", 3);
2479 if(!$run{'http-ipv6'}) {
2480 ($serr, $pid, $pid2, $PORT{"http6"}) =
2481 runhttpserver("http", $verbose, "ipv6");
2483 return ("failed starting HTTP-IPv6 server", $serr);
2485 logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2)
2487 $run{'http-ipv6'}="$pid $pid2";
2490 elsif($what eq "rtsp") {
2491 if($torture && $run{'rtsp'} &&
2492 !responsive_rtsp_server($verbose)) {
2493 if(stopserver('rtsp')) {
2494 return ("failed stopping unresponsive RTSP server", 3);
2498 ($serr, $pid, $pid2, $PORT{'rtsp'}) = runrtspserver($verbose);
2500 return ("failed starting RTSP server", $serr);
2502 logmsg sprintf("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose);
2503 $run{'rtsp'}="$pid $pid2";
2506 elsif($what eq "rtsp-ipv6") {
2507 if($torture && $run{'rtsp-ipv6'} &&
2508 !responsive_rtsp_server($verbose, "ipv6")) {
2509 if(stopserver('rtsp-ipv6')) {
2510 return ("failed stopping unresponsive RTSP-IPv6 server", 3);
2513 if(!$run{'rtsp-ipv6'}) {
2514 ($serr, $pid, $pid2, $PORT{'rtsp6'}) = runrtspserver($verbose, "ipv6");
2516 return ("failed starting RTSP-IPv6 server", $serr);
2518 logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2)
2520 $run{'rtsp-ipv6'}="$pid $pid2";
2523 elsif($what =~ /^(ftp|imap|pop3|smtp)s$/) {
2526 # we can't run ftps tests without stunnel
2527 return ("no stunnel", 4);
2529 if($runcert{$what} && ($runcert{$what} ne $certfile)) {
2530 # stop server when running and using a different cert
2531 if(stopserver($what)) {
2532 return ("failed stopping $what server with different cert", 3);
2535 if($torture && $run{$cproto} &&
2536 !responsive_pingpong_server($cproto, "", $verbose)) {
2537 if(stopserver($cproto)) {
2538 return ("failed stopping unresponsive $cproto server", 3);
2541 if(!$run{$cproto}) {
2542 ($serr, $pid, $pid2) = runpingpongserver($cproto, "", $verbose);
2544 return ("failed starting $cproto server", $serr);
2546 logmsg sprintf("* pid $cproto => %d %d\n", $pid, $pid2) if($verbose);
2547 $run{$cproto}="$pid $pid2";
2550 ($serr, $pid, $pid2, $PORT{$what}) =
2551 runsecureserver($verbose, "", $certfile, $what,
2552 protoport($cproto));
2554 return ("failed starting $what server (stunnel)", $serr);
2556 logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2)
2558 $run{$what}="$pid $pid2";
2561 elsif($what eq "file") {
2562 # we support it but have no server!
2564 elsif($what eq "https") {
2566 # we can't run https tests without stunnel
2567 return ("no stunnel", 4);
2569 if($runcert{'https'} && ($runcert{'https'} ne $certfile)) {
2570 # stop server when running and using a different cert
2571 if(stopserver('https')) {
2572 return ("failed stopping HTTPS server with different cert", 3);
2575 if($torture && $run{'http'} &&
2576 !responsive_http_server("http", $verbose, 0,
2577 protoport('http'))) {
2578 if(stopserver('http')) {
2579 return ("failed stopping unresponsive HTTP server", 3);
2583 ($serr, $pid, $pid2, $PORT{'http'}) =
2584 runhttpserver("http", $verbose, 0);
2586 return ("failed starting HTTP server", $serr);
2588 logmsg sprintf("* pid http => %d %d\n", $pid, $pid2) if($verbose);
2589 $run{'http'}="$pid $pid2";
2591 if(!$run{'https'}) {
2592 ($serr, $pid, $pid2, $PORT{'https'}) =
2593 runhttpsserver($verbose, "https", "", $certfile);
2595 return ("failed starting HTTPS server (stunnel)", $serr);
2597 logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
2599 $run{'https'}="$pid $pid2";
2602 elsif($what eq "gophers") {
2604 # we can't run TLS tests without stunnel
2605 return ("no stunnel", 4);
2607 if($runcert{'gophers'} && ($runcert{'gophers'} ne $certfile)) {
2608 # stop server when running and using a different cert
2609 if(stopserver('gophers')) {
2610 return ("failed stopping GOPHERS server with different cert", 3);
2613 if($torture && $run{'gopher'} &&
2614 !responsive_http_server("gopher", $verbose, 0,
2615 protoport('gopher'))) {
2616 if(stopserver('gopher')) {
2617 return ("failed stopping unresponsive GOPHER server", 3);
2620 if(!$run{'gopher'}) {
2622 ($serr, $pid, $pid2, $port) =
2623 runhttpserver("gopher", $verbose, 0);
2624 $PORT{'gopher'} = $port;
2626 return ("failed starting GOPHER server", $serr);
2628 logmsg sprintf("* pid gopher => %d %d\n", $pid, $pid2) if($verbose);
2629 logmsg "GOPHERPORT => $port\n" if($verbose);
2630 $run{'gopher'}="$pid $pid2";
2632 if(!$run{'gophers'}) {
2634 ($serr, $pid, $pid2, $port) =
2635 runhttpsserver($verbose, "gophers", "", $certfile);
2636 $PORT{'gophers'} = $port;
2638 return ("failed starting GOPHERS server (stunnel)", $serr);
2640 logmsg sprintf("* pid gophers => %d %d\n", $pid, $pid2)
2642 logmsg "GOPHERSPORT => $port\n" if($verbose);
2643 $run{'gophers'}="$pid $pid2";
2646 elsif($what eq "https-proxy") {
2648 # we can't run https-proxy tests without stunnel
2649 return ("no stunnel", 4);
2651 if($runcert{'https-proxy'} &&
2652 ($runcert{'https-proxy'} ne $certfile)) {
2653 # stop server when running and using a different cert
2654 if(stopserver('https-proxy')) {
2655 return ("failed stopping HTTPS-proxy with different cert", 3);
2659 # we front the http-proxy with stunnel so we need to make sure the
2660 # proxy runs as well
2661 my ($f, $e) = startservers("http-proxy");
2666 if(!$run{'https-proxy'}) {
2667 ($serr, $pid, $pid2, $PORT{"httpsproxy"}) =
2668 runhttpsserver($verbose, "https", "proxy", $certfile);
2670 return ("failed starting HTTPS-proxy (stunnel)", $serr);
2672 logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
2674 $run{'https-proxy'}="$pid $pid2";
2677 elsif($what eq "httptls") {
2679 # for now, we can't run http TLS-EXT tests without gnutls-serv
2680 return ("no gnutls-serv (with SRP support)", 4);
2682 if($torture && $run{'httptls'} &&
2683 !responsive_httptls_server($verbose, "IPv4")) {
2684 if(stopserver('httptls')) {
2685 return ("failed stopping unresponsive HTTPTLS server", 3);
2688 if(!$run{'httptls'}) {
2689 ($serr, $pid, $pid2, $PORT{'httptls'}) =
2690 runhttptlsserver($verbose, "IPv4");
2692 return ("failed starting HTTPTLS server (gnutls-serv)", $serr);
2694 logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2)
2696 $run{'httptls'}="$pid $pid2";
2699 elsif($what eq "httptls-ipv6") {
2701 # for now, we can't run http TLS-EXT tests without gnutls-serv
2702 return ("no gnutls-serv", 4);
2704 if($torture && $run{'httptls-ipv6'} &&
2705 !responsive_httptls_server($verbose, "ipv6")) {
2706 if(stopserver('httptls-ipv6')) {
2707 return ("failed stopping unresponsive HTTPTLS-IPv6 server", 3);
2710 if(!$run{'httptls-ipv6'}) {
2711 ($serr, $pid, $pid2, $PORT{"httptls6"}) =
2712 runhttptlsserver($verbose, "ipv6");
2714 return ("failed starting HTTPTLS-IPv6 server (gnutls-serv)", $serr);
2716 logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2)
2718 $run{'httptls-ipv6'}="$pid $pid2";
2721 elsif($what eq "tftp") {
2722 if($torture && $run{'tftp'} &&
2723 !responsive_tftp_server("", $verbose)) {
2724 if(stopserver('tftp')) {
2725 return ("failed stopping unresponsive TFTP server", 3);
2729 ($serr, $pid, $pid2, $PORT{'tftp'}) =
2730 runtftpserver("", $verbose);
2732 return ("failed starting TFTP server", $serr);
2734 logmsg sprintf("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
2735 $run{'tftp'}="$pid $pid2";
2738 elsif($what eq "tftp-ipv6") {
2739 if($torture && $run{'tftp-ipv6'} &&
2740 !responsive_tftp_server("", $verbose, "ipv6")) {
2741 if(stopserver('tftp-ipv6')) {
2742 return ("failed stopping unresponsive TFTP-IPv6 server", 3);
2745 if(!$run{'tftp-ipv6'}) {
2746 ($serr, $pid, $pid2, $PORT{'tftp6'}) =
2747 runtftpserver("", $verbose, "ipv6");
2749 return ("failed starting TFTP-IPv6 server", $serr);
2751 logmsg sprintf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
2752 $run{'tftp-ipv6'}="$pid $pid2";
2755 elsif($what eq "sftp" || $what eq "scp") {
2757 ($serr, $pid, $pid2, $PORT{'ssh'}) = runsshserver("", $verbose);
2759 return ("failed starting SSH server", $serr);
2761 logmsg sprintf("* pid ssh => %d %d\n", $pid, $pid2) if($verbose);
2762 $run{'ssh'}="$pid $pid2";
2765 elsif($what eq "socks4" || $what eq "socks5" ) {
2766 if(!$run{'socks'}) {
2767 ($serr, $pid, $pid2, $PORT{"socks"}) = runsocksserver("", $verbose);
2769 return ("failed starting socks server", $serr);
2771 logmsg sprintf("* pid socks => %d %d\n", $pid, $pid2) if($verbose);
2772 $run{'socks'}="$pid $pid2";
2775 elsif($what eq "socks5unix") {
2776 if(!$run{'socks5unix'}) {
2777 ($serr, $pid, $pid2) = runsocksserver("2", $verbose, "", "unix");
2779 return ("failed starting socks5unix server", $serr);
2781 logmsg sprintf("* pid socks5unix => %d %d\n", $pid, $pid2) if($verbose);
2782 $run{'socks5unix'}="$pid $pid2";
2785 elsif($what eq "mqtt" ) {
2787 ($serr, $pid, $pid2) = runmqttserver("", $verbose);
2789 return ("failed starting mqtt server", $serr);
2791 logmsg sprintf("* pid mqtt => %d %d\n", $pid, $pid2) if($verbose);
2792 $run{'mqtt'}="$pid $pid2";
2795 elsif($what eq "http-unix") {
2796 if($torture && $run{'http-unix'} &&
2797 !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
2798 if(stopserver('http-unix')) {
2799 return ("failed stopping unresponsive HTTP-unix server", 3);
2802 if(!$run{'http-unix'}) {
2804 ($serr, $pid, $pid2, $unused) =
2805 runhttpserver("http", $verbose, "unix", $HTTPUNIXPATH);
2807 return ("failed starting HTTP-unix server", $serr);
2809 logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
2811 $run{'http-unix'}="$pid $pid2";
2814 elsif($what eq "dict") {
2816 ($serr, $pid, $pid2, $PORT{"dict"}) = rundictserver($verbose, "");
2818 return ("failed starting DICT server", $serr);
2820 logmsg sprintf ("* pid DICT => %d %d\n", $pid, $pid2)
2822 $run{'dict'}="$pid $pid2";
2825 elsif($what eq "smb") {
2827 ($serr, $pid, $pid2, $PORT{"smb"}) = runsmbserver($verbose, "");
2829 return ("failed starting SMB server", $serr);
2831 logmsg sprintf ("* pid SMB => %d %d\n", $pid, $pid2)
2833 $run{'smb'}="$pid $pid2";
2836 elsif($what eq "telnet") {
2837 if(!$run{'telnet'}) {
2838 ($serr, $pid, $pid2, $PORT{"telnet"}) =
2839 runnegtelnetserver($verbose, "");
2841 return ("failed starting neg TELNET server", $serr);
2843 logmsg sprintf ("* pid neg TELNET => %d %d\n", $pid, $pid2)
2845 $run{'telnet'}="$pid $pid2";
2848 elsif($what eq "none") {
2849 logmsg "* starts no server\n" if ($verbose);
2852 warn "we don't support a server for $what";
2853 return ("no server for $what", 4);
2859 #######################################################################
2860 # Stop all running test servers
2865 # kill sockfilter processes for all pingpong servers
2867 killallsockfilters("$LOGDIR/$PIDDIR", $verb);
2869 # kill all server pids from %run hash clearing them
2872 foreach my $server (keys %run) {
2876 my $pids = $run{$server};
2877 foreach my $pid (split(' ', $pids)) {
2879 logmsg sprintf("* kill pid for %s => %d\n",
2885 $pidlist .= "$run{$server} ";
2888 $runcert{$server} = 0 if($runcert{$server});
2890 killpid($verb, $pidlist);
2892 # cleanup all server pid files
2895 foreach my $server (keys %serverpidfile) {
2896 my $pidfile = $serverpidfile{$server};
2897 my $pid = processexists($pidfile);
2899 if($err_unexpected) {
2906 logmsg "$server server unexpectedly alive\n";
2907 killpid($verb, $pid);
2909 unlink($pidfile) if(-f $pidfile);
2916 #######################################################################
2917 # substitute the variable stuff into either a joined up file or
2918 # a command, in either case passed by reference
2921 my ($thing, $testnum, $prefix) = @_;
2929 # Substitutes variables like %HTTPPORT and %SMTP6PORT with the server ports
2930 foreach my $proto ('DICT',
2931 'FTP', 'FTP6', 'FTPS',
2932 'GOPHER', 'GOPHER6', 'GOPHERS',
2933 'HTTP', 'HTTP6', 'HTTPS',
2934 'HTTPSPROXY', 'HTTPTLS', 'HTTPTLS6',
2935 'HTTP2', 'HTTP2TLS',
2937 'IMAP', 'IMAP6', 'IMAPS',
2940 'POP3', 'POP36', 'POP3S',
2943 'SMTP', 'SMTP6', 'SMTPS',
2948 $port = protoport(lc $proto);
2949 $$thing =~ s/${prefix}(?:$proto)PORT/$port/g;
2951 # Special case: for PROXYPORT substitution, use httpproxy.
2952 $port = protoport('httpproxy');
2953 $$thing =~ s/${prefix}PROXYPORT/$port/g;
2955 # server Unix domain socket paths
2956 $$thing =~ s/${prefix}HTTPUNIXPATH/$HTTPUNIXPATH/g;
2957 $$thing =~ s/${prefix}SOCKSUNIXPATH/$SOCKSUNIXPATH/g;
2959 # client IP addresses
2960 $$thing =~ s/${prefix}CLIENT6IP/$CLIENT6IP/g;
2961 $$thing =~ s/${prefix}CLIENTIP/$CLIENTIP/g;
2963 # server IP addresses
2964 $$thing =~ s/${prefix}HOST6IP/$HOST6IP/g;
2965 $$thing =~ s/${prefix}HOSTIP/$HOSTIP/g;
2968 $$thing =~ s/${prefix}CURL/$CURL/g;
2969 $$thing =~ s/${prefix}LOGDIR/$LOGDIR/g;
2970 $$thing =~ s/${prefix}PWD/$pwd/g;
2971 $$thing =~ s/${prefix}POSIX_PWD/$posix_pwd/g;
2972 $$thing =~ s/${prefix}VERSION/$CURLVERSION/g;
2973 $$thing =~ s/${prefix}TESTNUMBER/$testnum/g;
2975 my $file_pwd = $pwd;
2976 if($file_pwd !~ /^\//) {
2977 $file_pwd = "/$file_pwd";
2979 my $ssh_pwd = $posix_pwd;
2980 # this only works after the SSH server has been started
2981 # TODO: call sshversioninfo early and store $sshdid so this substitution
2983 if ($sshdid && $sshdid =~ /OpenSSH-Windows/) {
2984 $ssh_pwd = $file_pwd;
2987 $$thing =~ s/${prefix}FILE_PWD/$file_pwd/g;
2988 $$thing =~ s/${prefix}SSH_PWD/$ssh_pwd/g;
2989 $$thing =~ s/${prefix}SRCDIR/$srcdir/g;
2990 $$thing =~ s/${prefix}USER/$USER/g;
2992 $$thing =~ s/${prefix}SSHSRVMD5/$SSHSRVMD5/g;
2993 $$thing =~ s/${prefix}SSHSRVSHA256/$SSHSRVSHA256/g;
2995 # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
2996 # used for time-out tests and that would work on most hosts as these
2997 # adjust for the startup/check time for this particular host. We needed to
2998 # do this to make the test suite run better on very slow hosts.
2999 my $ftp2 = $ftpchecktime * 8;
3000 my $ftp3 = $ftpchecktime * 12;
3002 $$thing =~ s/${prefix}FTPTIME2/$ftp2/g;
3003 $$thing =~ s/${prefix}FTPTIME3/$ftp3/g;
3006 $$thing =~ s/${prefix}H2CVER/$h2cver/g;