1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-08-10 06:23:01 +03:00

Improve ssh_connect_host().

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@728 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
Andreas Schneider
2009-05-05 08:05:03 +00:00
parent 7568e42f4e
commit 4bf12aaf56

View File

@@ -168,80 +168,98 @@ static int ssh_connect_ai_timeout(SSH_SESSION *session, const char *host,
return s;
}
/** \internal
* \brief connect_host connects to an IPv4 (or IPv6) host
* specified by its IP address or hostname.
* \returns file descriptor
* \returns less than 0 value
/**
* @internal
*
* @brief Connect to an IPv4 or IPv6 host specified by its IP address or
* hostname.
*
* @returns A file descriptor, < 0 on error.
*/
socket_t ssh_connect_host(SSH_SESSION *session, const char *host,
const char *bind_addr, int port, long timeout, long usec) {
socket_t s = -1;
int rc;
struct addrinfo *ai;
struct addrinfo *itr;
socket_t ssh_connect_host(SSH_SESSION *session, const char *host, const char
*bind_addr, int port,long timeout, long usec){
socket_t s=-1;
int my_errno;
struct addrinfo *ai, *ai2;
enter_function();
my_errno=getai(host, port, &ai);
if (my_errno){
ssh_set_error(session,SSH_FATAL,"Failed to resolve hostname %s (%s)",host,gai_strerror(my_errno));
enter_function();
rc = getai(host, port, &ai);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
leave_function();
return -1;
}
for (itr = ai; itr != NULL; itr = itr->ai_next){
/* create socket */
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
if (s < 0) {
ssh_set_error(session, SSH_FATAL,
"Socket create failed: %s", strerror(errno));
continue;
}
if (bind_addr) {
struct addrinfo *bind_ai;
struct addrinfo *bind_itr;
ssh_log(session, SSH_LOG_PACKET, "Resolving %s\n", bind_addr);
rc = getai(host, 0, &bind_ai);
if (rc != 0) {
ssh_set_error(session, SSH_FATAL,
"Failed to resolve bind address %s (%s)",
bind_addr,
gai_strerror(rc));
leave_function();
return -1;
}
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL,
"Binding local address: %s", strerror(errno));
continue;
} else {
break;
}
}
freeaddrinfo(bind_ai);
/* Cannot bind to any local addresses */
if (bind_itr == NULL) {
close(s);
s = -1;
continue;
}
}
for(ai2=ai;ai2!=NULL;ai2=ai2->ai_next){
/* create socket */
s=socket(ai2->ai_family,ai2->ai_socktype,ai2->ai_protocol);
if(s<0){
ssh_set_error(session,SSH_FATAL,"socket : %s",strerror(errno));
continue;
}
if(bind_addr){
struct addrinfo *bind_ai, *bind_ai2;
ssh_log(session,SSH_LOG_PACKET,"resolving %s\n",bind_addr);
my_errno=getai(host,0,&bind_ai);
if (my_errno){
ssh_set_error(session,SSH_FATAL,"Failed to resolve bind address %s (%s)",bind_addr,gai_strerror(my_errno));
leave_function();
return -1;
}
for(bind_ai2=bind_ai;bind_ai2!=NULL;bind_ai2=bind_ai2->ai_next){
if(bind(s,bind_ai2->ai_addr,bind_ai2->ai_addrlen)<0){
ssh_set_error(session,SSH_FATAL,"Binding local address : %s",strerror(errno));
continue;
}
else{
break;
}
}
freeaddrinfo(bind_ai);
if(bind_ai2==NULL){ /*cannot bind to any local addresses*/
close(s);
s=-1;
continue;
}
}
if(timeout||usec){
socket_t ret=ssh_connect_ai_timeout(session,host,port,ai2,timeout,usec,s);
leave_function();
return ret;
}
if(connect(s,ai2->ai_addr,ai2->ai_addrlen)<0){
ssh_set_error(session,SSH_FATAL,"connect: %s",strerror(errno));
close(s);
s=-1;
leave_function();
continue;
}
else{ /*we are connected*/
break;
}
if (timeout || usec) {
socket_t ret = ssh_connect_ai_timeout(session, host, port, itr,
timeout, usec, s);
leave_function();
return ret;
}
freeaddrinfo(ai);
leave_function();
return s;
if (connect(s, itr->ai_addr, itr->ai_addrlen) < 0) {
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
close(s);
s = -1;
leave_function();
continue;
} else {
/* We are connected */
break;
}
}
freeaddrinfo(ai);
leave_function();
return s;
}
/** \addtogroup ssh_session