mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-03-24 20:40:09 +09:00
connect.c: Try to connect to other host addresses than just the first
When one host has multiple addresses returned by `getaddrinfo` try not just the first address. The scenario where the first address is wrong but the second is good was failing, because the second address was never tried. This applies to ipv6 as well as to ipv4 addresses. As the implementation uses non-blocking sockets it may return EINPROGRESS when error happened as well as just "non-blocking" statement. The socket can not be queried for status code to determine the error if any, because it requires calling blocking functions. Signed-off-by: Norbert Pocs <npocs@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
@@ -168,7 +168,7 @@ static int set_tcp_nodelay(socket_t socket)
|
||||
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
const char *bind_addr, int port)
|
||||
{
|
||||
socket_t s = -1;
|
||||
socket_t s = -1, first = -1;
|
||||
int rc;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *itr = NULL;
|
||||
@@ -258,12 +258,22 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
|
||||
errno = 0;
|
||||
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to connect: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
if (rc == -1) {
|
||||
if ((errno != 0) && (errno != EINPROGRESS)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to connect: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
} else {
|
||||
if (first == -1) {
|
||||
first = s;
|
||||
} else { /* errno == EINPROGRESS */
|
||||
/* save only the first "working" socket */
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -272,6 +282,12 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
|
||||
freeaddrinfo(ai);
|
||||
|
||||
/* first let's go through all the addresses looking for immediate
|
||||
* connection, otherwise return the first address without error or error */
|
||||
if (s == -1) {
|
||||
s = first;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user