summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/sshconnect.c b/sshconnect.c
index 32bef7d07..8aac221d3 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect.c,v 1.140 2003/05/14 18:16:21 jakob Exp $"); 16RCSID("$OpenBSD: sshconnect.c,v 1.141 2003/05/15 14:55:25 djm Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19 19
@@ -218,6 +218,71 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
218 return sock; 218 return sock;
219} 219}
220 220
221static int
222timeout_connect(int sockfd, const struct sockaddr *serv_addr,
223 socklen_t addrlen, int timeout)
224{
225 fd_set *fdset;
226 struct timeval tv;
227 socklen_t optlen;
228 int fdsetsz, optval, rc;
229
230 if (timeout <= 0)
231 return (connect(sockfd, serv_addr, addrlen));
232
233 if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
234 return (-1);
235
236 rc = connect(sockfd, serv_addr, addrlen);
237 if (rc == 0)
238 return (0);
239 if (errno != EINPROGRESS)
240 return (-1);
241
242 fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask);
243 fdset = (fd_set *)xmalloc(fdsetsz);
244
245 memset(fdset, '\0', fdsetsz);
246 FD_SET(sockfd, fdset);
247 tv.tv_sec = timeout;
248 tv.tv_usec = 0;
249
250 for(;;) {
251 rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
252 if (rc != -1 || errno != EINTR)
253 break;
254 }
255
256 switch(rc) {
257 case 0:
258 /* Timed out */
259 errno = ETIMEDOUT;
260 return (-1);
261 case -1:
262 /* Select error */
263 debug("select: %s", strerror(errno));
264 return (-1);
265 case 1:
266 /* Completed or failed */
267 optval = 0;
268 optlen = sizeof(optval);
269 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
270 &optlen) == -1)
271 debug("getsockopt: %s", strerror(errno));
272 return (-1);
273 if (optval != 0) {
274 errno = optval;
275 return (-1);
276 }
277 break;
278 default:
279 /* Should not occur */
280 fatal("Bogus return (%d) from select()", rc);
281 }
282
283 return (0);
284}
285
221/* 286/*
222 * Opens a TCP/IP connection to the remote server on the given host. 287 * Opens a TCP/IP connection to the remote server on the given host.
223 * The address of the remote host will be returned in hostaddr. 288 * The address of the remote host will be returned in hostaddr.
@@ -306,7 +371,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
306 /* Any error is already output */ 371 /* Any error is already output */
307 continue; 372 continue;
308 373
309 if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { 374 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
375 options.connection_timeout) >= 0) {
310 /* Successful connection. */ 376 /* Successful connection. */
311 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 377 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
312 break; 378 break;