use warnings;
use POSIX qw(EINTR EEXIST EOPNOTSUPP);
use IO::Socket::IP;
-use Socket qw(AF_INET AF_INET6 AI_ALL AI_V4MAPPED AI_CANONNAME SOCK_DGRAM);
+use Socket qw(AF_INET AF_INET6 AI_ALL AI_V4MAPPED AI_CANONNAME SOCK_DGRAM
+ IPPROTO_TCP);
use IO::Select;
use File::Basename;
use File::Path qw(make_path);
my $starttime = [gettimeofday];
my $elapsed;
+ my $found;
while (($elapsed = tv_interval($starttime)) < $timeout) {
- if (my $fh = IO::File->new ("/proc/net/tcp", "r")) {
- while (defined (my $line = <$fh>)) {
- if ($line =~ m/^\s*\d+:\s+([0-9A-Fa-f]{8}):([0-9A-Fa-f]{4})\s/) {
- if ($port == hex($2)) {
- close($fh);
- return 1;
- }
- }
+ # -Htln = don't print header, tcp, listening sockets only, numeric ports
+ run_command(['/bin/ss', '-Htln', "sport = :$port"], outfunc => sub {
+ my $line = shift;
+ if ($line =~ m/^LISTEN\s+\d+\s+\d+\s+\S+:(\d+)\s/) {
+ $found = 1 if ($port == $1);
}
- close($fh);
- }
+ });
+ return 1 if $found;
$sleeptime += 100000 if $sleeptime < 1000000;
usleep($sleeptime);
}
}
sub next_unused_port {
- my ($range_start, $range_end, $family) = @_;
+ my ($range_start, $range_end, $family, $address) = @_;
# We use a file to register allocated ports.
# Those registrations expires after $expiretime.
}
my $newport;
+ my %sockargs = (Listen => 5,
+ ReuseAddr => 1,
+ Family => $family,
+ Proto => IPPROTO_TCP,
+ GetAddrInfoFlags => 0);
+ $sockargs{LocalAddr} = $address if defined($address);
for (my $p = $range_start; $p < $range_end; $p++) {
next if $ports->{$p}; # reserved
- my $sock = IO::Socket::IP->new(Listen => 5,
- LocalPort => $p,
- ReuseAddr => 1,
- Family => $family,
- Proto => 0,
- GetAddrInfoFlags => 0);
+ $sockargs{LocalPort} = $p;
+ my $sock = IO::Socket::IP->new(%sockargs);
if ($sock) {
close($sock);
}
sub next_migrate_port {
- my ($family) = @_;
- return next_unused_port(60000, 60050, $family);
+ my ($family, $address) = @_;
+ return next_unused_port(60000, 60050, $family, $address);
}
sub next_vnc_port {
- my ($family) = @_;
- return next_unused_port(5900, 6000, $family);
+ my ($family, $address) = @_;
+ return next_unused_port(5900, 6000, $family, $address);
}
sub next_spice_port {
- my ($family) = @_;
- return next_unused_port(61000, 61099, $family);
+ my ($family, $address) = @_;
+ return next_unused_port(61000, 61099, $family, $address);
}
# NOTE: NFS syscall can't be interrupted, so alarm does