diff options
author | Andreas Schneider <mail@cynapses.org> | 2009-05-05 08:05:03 +0000 |
---|---|---|
committer | Andreas Schneider <mail@cynapses.org> | 2009-05-05 08:05:03 +0000 |
commit | 4bf12aaf56e64eaa9f2894fc18583bff89d2018c (patch) | |
tree | df66a6a1c7ee42ac47112f08ff859f2339f40264 /libssh | |
parent | 7568e42f4edcb53ef02469f12013eb9a6f615020 (diff) | |
download | libssh-4bf12aaf56e64eaa9f2894fc18583bff89d2018c.tar.gz libssh-4bf12aaf56e64eaa9f2894fc18583bff89d2018c.tar.xz libssh-4bf12aaf56e64eaa9f2894fc18583bff89d2018c.zip |
Improve ssh_connect_host().
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@728 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh')
-rw-r--r-- | libssh/connect.c | 148 |
1 files changed, 83 insertions, 65 deletions
diff --git a/libssh/connect.c b/libssh/connect.c index d0307736..89ec9bfa 100644 --- a/libssh/connect.c +++ b/libssh/connect.c @@ -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; + + 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; + } -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)); + 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 (timeout || usec) { + socket_t ret = ssh_connect_ai_timeout(session, host, port, itr, + timeout, usec, s); + leave_function(); + return ret; + } - if(bind_addr){ - struct addrinfo *bind_ai, *bind_ai2; + 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; + } + } - 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; - } + freeaddrinfo(ai); + leave_function(); - 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; - } - } - freeaddrinfo(ai); - leave_function(); - return s; + return s; } /** \addtogroup ssh_session |