use warnings;
use POSIX qw(EINTR);
use IO::Socket::IP;
+use Socket qw(AF_INET AF_INET6 AI_ALL AI_V4MAPPED);
use IO::Select;
use File::Basename;
use File::Path qw(make_path);
}
sub next_unused_port {
- my ($range_start, $range_end) = @_;
+ my ($range_start, $range_end, $family) = @_;
# We use a file to register allocated ports.
# Those registrations expires after $expiretime.
next if $ports->{$p}; # reserved
my $sock = IO::Socket::IP->new(Listen => 5,
- LocalAddr => '0.0.0.0',
LocalPort => $p,
ReuseAddr => 1,
- Proto => 0);
+ Family => $family,
+ Proto => 0,
+ GetAddrInfoFlags => 0);
if ($sock) {
close($sock);
}
sub next_migrate_port {
- return next_unused_port(60000, 60050);
+ my ($family) = @_;
+ return next_unused_port(60000, 60050, $family);
}
sub next_vnc_port {
- return next_unused_port(5900, 6000);
+ my ($family) = @_;
+ return next_unused_port(5900, 6000, $family);
}
sub next_spice_port {
- return next_unused_port(61000, 61099);
+ my ($family) = @_;
+ return next_unused_port(61000, 61099, $family);
}
# NOTE: NFS syscall can't be interrupted, so alarm does
sub fnv31a_hex { return sprintf("%X", fnv31a(@_)); }
+sub unpack_sockaddr_in46 {
+ my ($sin) = @_;
+ my $family = Socket::sockaddr_family($sin);
+ my ($port, $host) = ($family == AF_INET6 ? Socket::unpack_sockaddr_in6($sin)
+ : Socket::unpack_sockaddr_in($sin));
+ return ($family, $port, $host);
+}
+
+sub getaddrinfo_all {
+ my ($hostname, @opts) = @_;
+ my %hints = ( flags => AI_V4MAPPED | AI_ALL,
+ @opts );
+ my ($err, @res) = Socket::getaddrinfo($hostname, '0', \%hints);
+ die "failed to get address info for: $hostname: $err\n" if $err;
+ return @res;
+}
+
+sub get_host_address_family {
+ my ($hostname, $socktype) = @_;
+ my @res = getaddrinfo_all($hostname, socktype => $socktype);
+ return $res[0]->{family};
+}
+
1;