Try all IPs when opening a socket

This commit is contained in:
Jamie Cameron
2021-01-20 20:35:09 -08:00
parent 77ff74a717
commit 04c74877c3

View File

@@ -3124,53 +3124,60 @@ if ($gconfig{'debug_what_net'}) {
&webmin_debug_log('TCP', "host=$host port=$port"); &webmin_debug_log('TCP', "host=$host port=$port");
} }
# Lookup IP address for the host. Try v4 first, and failing that v6 # Lookup all IPv4 and v6 addresses for the host
my $ip; my @ips = &to_ipaddress($host);
my $v6 = &to_ip6address($host);
push(@ips, $v6) if ($v6);
if (!@ips) {
my $msg = "Failed to lookup IP address for $host";
if ($err) { $$err = $msg; return 0; }
else { &error($msg); }
}
# Try each of the resolved IPs
my $msg;
my $proto = getprotobyname("tcp"); my $proto = getprotobyname("tcp");
if ($ip = &to_ipaddress($host)) { foreach my $ip (@ips) {
# Create IPv4 socket and connection $msg = undef;
if (!socket($fh, PF_INET(), SOCK_STREAM, $proto)) { if (&check_ipaddress($ip)) {
my $msg = "Failed to create socket : $!"; # Create IPv4 socket and connection
if ($err) { $$err = $msg; return 0; } if (!socket($fh, PF_INET(), SOCK_STREAM, $proto)) {
else { &error($msg); } $msg = "Failed to create socket : $!";
} next;
my $addr = inet_aton($ip); }
if ($gconfig{'bind_proxy'}) { my $addr = inet_aton($ip);
# BIND to outgoing IP if ($gconfig{'bind_proxy'}) {
if (!bind($fh, pack_sockaddr_in(0, inet_aton($bindip)))) { # BIND to outgoing IP
my $msg = "Failed to bind to source address : $!"; if (!bind($fh, pack_sockaddr_in(0, inet_aton($bindip)))) {
if ($err) { $$err = $msg; return 0; } $msg = "Failed to bind to source address : $!";
else { &error($msg); } next;
}
}
if (!connect($fh, pack_sockaddr_in($port, $addr))) {
$msg = "Failed to connect to $host:$port : $!";
next;
} }
} }
if (!connect($fh, pack_sockaddr_in($port, $addr))) { else {
my $msg = "Failed to connect to $host:$port : $!"; # Create IPv6 socket and connection
if ($err) { $$err = $msg; return 0; } if (!&supports_ipv6()) {
else { &error($msg); } $msg = "IPv6 connections are not supported";
next;
}
if (!socket($fh, PF_INET6(), SOCK_STREAM, $proto)) {
$msg = "Failed to create IPv6 socket : $!";
next;
}
my $addr = inet_pton(AF_INET6(), $ip);
if (!connect($fh, pack_sockaddr_in6($port, $addr))) {
$msg = "Failed to IPv6 connect to $host:$port : $!";
next;
}
} }
last; # If we got this far, it worked
} }
elsif ($ip = &to_ip6address($host)) { if ($msg) {
# Create IPv6 socket and connection # Last attempt failed
if (!&supports_ipv6()) {
$msg = "IPv6 connections are not supported";
if ($err) { $$err = $msg; return 0; }
else { &error($msg); }
}
if (!socket($fh, PF_INET6(), SOCK_STREAM, $proto)) {
my $msg = "Failed to create IPv6 socket : $!";
if ($err) { $$err = $msg; return 0; }
else { &error($msg); }
}
my $addr = inet_pton(AF_INET6(), $ip);
if (!connect($fh, pack_sockaddr_in6($port, $addr))) {
my $msg = "Failed to IPv6 connect to $host:$port : $!";
if ($err) { $$err = $msg; return 0; }
else { &error($msg); }
}
}
else {
# Resolution failed
my $msg = "Failed to lookup IP address for $host";
if ($err) { $$err = $msg; return 0; } if ($err) { $$err = $msg; return 0; }
else { &error($msg); } else { &error($msg); }
} }