From 2b1067453eeadfddd4ff1d0a34dd770f7cb7810c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 19 Apr 2020 23:29:21 +0200 Subject: tests: run the TFTP server on a dynamic port Picking an unused one is better than a fixed to avoid collision risk. --- tests/runtests.pl | 27 +++++++++++---------- tests/server/tftpd.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++----- tests/tftpserver.pl | 15 +++++++++--- 3 files changed, 85 insertions(+), 23 deletions(-) diff --git a/tests/runtests.pl b/tests/runtests.pl index 3c568f633..a9227e54c 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -1940,7 +1940,6 @@ sub runftpsserver { # sub runtftpserver { my ($id, $verbose, $ipv6) = @_; - my $port = $TFTPPORT; my $ip = $HOSTIP; my $proto = 'tftp'; my $ipvnum = 4; @@ -1954,13 +1953,13 @@ sub runtftpserver { if($ipv6) { # if IPv6, use a different setup $ipvnum = 6; - $port = $TFTP6PORT; $ip = $HOST6IP; } $server = servername_id($proto, $ipvnum, $idnum); $pidfile = $serverpidfile{$server}; + my $portfile = $serverportfile{$server}; # don't retry if the server doesn't work if ($doesntrun{$pidfile}) { @@ -1978,9 +1977,11 @@ sub runtftpserver { $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); $flags .= "--verbose " if($debugprotocol); - $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; + $flags .= "--pidfile \"$pidfile\" ". + "--portfile \"$portfile\" ". + "--logfile \"$logfile\" "; $flags .= "--id $idnum " if($idnum > 1); - $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; + $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\""; my $cmd = "$perl $srcdir/tftpserver.pl $flags"; my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0); @@ -1994,6 +1995,8 @@ sub runtftpserver { return (0,0); } + my $port = pidfromfile($portfile); + # Server is up. Verify that we can speak to it. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); if(!$pid3) { @@ -2007,12 +2010,12 @@ sub runtftpserver { $pid2 = $pid3; if($verbose) { - logmsg "RUN: $srvrname server is now running PID $tftppid\n"; + logmsg "RUN: $srvrname server on PID $tftppid port $port\n"; } sleep(1); - return ($pid2, $tftppid); + return ($pid2, $tftppid, $port); } @@ -3152,13 +3155,9 @@ sub checksystem { logmsg sprintf("FTPS/%d ", $FTPSPORT); logmsg sprintf("HTTPS/%d ", $HTTPSPORT); } - logmsg sprintf("TFTP/%d ", $TFTPPORT); if($http_ipv6) { logmsg sprintf("RTSP-IPv6/%d ", $RTSP6PORT); } - if($tftp_ipv6) { - logmsg sprintf("TFTP-IPv6/%d ", $TFTP6PORT); - } logmsg sprintf("\n* SSH/%d ", $SSHPORT); logmsg sprintf("SOCKS/%d ", $SOCKSPORT); if($httptlssrv) { @@ -4852,7 +4851,8 @@ sub startservers { stopserver('tftp'); } if(!$run{'tftp'}) { - ($pid, $pid2) = runtftpserver("", $verbose); + ($pid, $pid2, $TFTPPORT) = + runtftpserver("", $verbose); if($pid <= 0) { return "failed starting TFTP server"; } @@ -4866,7 +4866,8 @@ sub startservers { stopserver('tftp-ipv6'); } if(!$run{'tftp-ipv6'}) { - ($pid, $pid2) = runtftpserver("", $verbose, "ipv6"); + ($pid, $pid2, $TFTP6PORT) = + runtftpserver("", $verbose, "ipv6"); if($pid <= 0) { return "failed starting TFTP-IPv6 server"; } @@ -5444,8 +5445,6 @@ if ($gdbthis) { $minport = $base; # original base port number $HTTPSPORT = $base++; # HTTPS (stunnel) server port $FTPSPORT = $base++; # FTPS (stunnel) server port -$TFTPPORT = $base++; # TFTP (UDP) port -$TFTP6PORT = $base++; # TFTP IPv6 (UDP) port $SSHPORT = $base++; # SSH (SCP/SFTP) port $SOCKSPORT = $base++; # SOCKS port $RTSPPORT = $base++; # RTSP server port diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c index 9972ab0e4..46b09b562 100644 --- a/tests/server/tftpd.c +++ b/tests/server/tftpd.c @@ -210,6 +210,7 @@ static const char *ipv_inuse = "IPv4"; const char *serverlogfile = DEFAULT_LOGFILE; static const char *pidname = ".tftpd.pid"; +static const char *portfile = NULL; static int serverlogslocked = 0; static int wrotepidfile = 0; @@ -574,6 +575,11 @@ int main(int argc, char **argv) if(argc>arg) pidname = argv[arg++]; } + else if(!strcmp("--portfile", argv[arg])) { + arg++; + if(argc>arg) + portfile = argv[arg++]; + } else if(!strcmp("--logfile", argv[arg])) { arg++; if(argc>arg) @@ -598,12 +604,6 @@ int main(int argc, char **argv) if(argc>arg) { char *endptr; unsigned long ulnum = strtoul(argv[arg], &endptr, 10); - if((endptr != argv[arg] + strlen(argv[arg])) || - (ulnum < 1025UL) || (ulnum > 65535UL)) { - fprintf(stderr, "tftpd: invalid --port argument (%s)\n", - argv[arg]); - return 0; - } port = curlx_ultous(ulnum); arg++; } @@ -690,12 +690,64 @@ int main(int argc, char **argv) goto tftpd_cleanup; } + if(!port) { + /* The system was supposed to choose a port number, figure out which + port we actually got and update the listener port value with it. */ + curl_socklen_t la_size; + srvr_sockaddr_union_t localaddr; +#ifdef ENABLE_IPV6 + if(!use_ipv6) +#endif + la_size = sizeof(localaddr.sa4); +#ifdef ENABLE_IPV6 + else + la_size = sizeof(localaddr.sa6); +#endif + memset(&localaddr.sa, 0, (size_t)la_size); + if(getsockname(sock, &localaddr.sa, &la_size) < 0) { + error = SOCKERRNO; + logmsg("getsockname() failed with error: (%d) %s", + error, strerror(error)); + sclose(sock); + return CURL_SOCKET_BAD; + } + switch(localaddr.sa.sa_family) { + case AF_INET: + port = ntohs(localaddr.sa4.sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(localaddr.sa6.sin6_port); + break; +#endif + default: + break; + } + if(!port) { + /* Real failure, listener port shall not be zero beyond this point. */ + logmsg("Apparently getsockname() succeeded, with listener port zero."); + logmsg("A valid reason for this failure is a binary built without"); + logmsg("proper network library linkage. This might not be the only"); + logmsg("reason, but double check it before anything else."); + result = 2; + goto tftpd_cleanup; + } + } + wrotepidfile = write_pidfile(pidname); if(!wrotepidfile) { result = 1; goto tftpd_cleanup; } + if(portfile) { + wrotepidfile = write_portfile(portfile, port); + if(!wrotepidfile) { + result = 1; + goto tftpd_cleanup; + } + } + logmsg("Running %s version on port UDP/%d", ipv_inuse, (int)port); for(;;) { @@ -800,6 +852,8 @@ tftpd_cleanup: if(wrotepidfile) unlink(pidname); + if(portfile) + unlink(portfile); if(serverlogslocked) { serverlogslocked = 0; diff --git a/tests/tftpserver.pl b/tests/tftpserver.pl index 523498634..a7b9b39df 100755 --- a/tests/tftpserver.pl +++ b/tests/tftpserver.pl @@ -43,8 +43,9 @@ my $port = 8997; # just a default my $ipvnum = 4; # default IP version of tftp server my $idnum = 1; # default tftp server instance number my $proto = 'tftp'; # protocol the tftp server speaks -my $pidfile; # tftp server pid file -my $logfile; # tftp server log file +my $pidfile; +my $portfile; +my $logfile; my $srcdir; my $fork; @@ -59,6 +60,12 @@ while(@ARGV) { shift @ARGV; } } + elsif($ARGV[0] eq '--portfile') { + if($ARGV[1]) { + $portfile = $ARGV[1]; + shift @ARGV; + } + } elsif($ARGV[0] eq '--logfile') { if($ARGV[1]) { $logfile = $ARGV[1]; @@ -108,7 +115,9 @@ if(!$logfile) { $logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum); } -$flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; +$flags .= "--pidfile \"$pidfile\" ". + "--portfile \"$portfile\" ". + "--logfile \"$logfile\" "; $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; exec("server/tftpd".exe_ext('SRV')." $flags"); -- cgit v1.2.1