[PATCH] Connect timeout

Jean-Charles Longuet jclonguet at free.fr
Fri Feb 22 06:20:31 EST 2002


Here is a new version of this patch, that do not use setjmp() but
a select() call instead. The (expected) behaviour is still the same :
avoiding spending too much time when doing an ssh() on a down host.
Another minor change is the use of the time format in the
ConnectTimeout argument (you can now things like '1m30s' if you want).
I use it mostly with rsync/rdist to fasten updates.

 Patch was tested on Linux and Solaris, and compiled OK on HP-UX 10.20.
Please notify me if things go bad on other platforms.

 The patch can also be found on:
http://charts.free.fr/openssh-3.0.1p1-timeout-1.01.patch

 PS: please cc: me regarding this patch for any suggestion/correction.

--
        Jean-Charles Longuet
-------------- next part --------------
--- openssh-3.0.2p1/readconf.c.ORIG	Wed Oct  3 19:39:39 2001
+++ openssh-3.0.2p1/readconf.c	Wed Feb 20 20:08:20 2002
@@ -115,7 +115,8 @@
 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
-	oClearAllForwardings, oNoHostAuthenticationForLocalhost 
+	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+	oConnectTimeout
 } OpCodes;
 
 /* Textual representations of the tokens. */
@@ -187,6 +188,7 @@
 	{ "smartcarddevice", oSmartcardDevice },
 	{ "clearallforwardings", oClearAllForwardings }, 
 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, 
+	{ "connecttimeout", oConnectTimeout }, 
 	{ NULL, 0 }
 };
 
@@ -294,6 +296,19 @@
 		/* don't panic, but count bad options */
 		return -1;
 		/* NOTREACHED */
+
+	case oConnectTimeout:
+		intptr = &options->connection_timeout;
+parse_time:
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing time argument.", filename, linenum);
+		if ((value = convtime(arg)) == -1)
+			fatal("%.200s line %d: Invalid time argument.", filename, linenum);
+		if (*intptr == -1)
+		*intptr = value;
+		break;
+
 	case oForwardAgent:
 		intptr = &options->forward_agent;
 parse_flag:
@@ -775,6 +790,7 @@
 	options->compression_level = -1;
 	options->port = -1;
 	options->connection_attempts = -1;
+	options->connection_timeout = -1;
 	options->number_of_password_prompts = -1;
 	options->cipher = -1;
 	options->ciphers = NULL;
--- openssh-3.0.2p1/readconf.h.ORIG	Wed Oct  3 19:39:39 2001
+++ openssh-3.0.2p1/readconf.h	Wed Feb 20 20:08:20 2002
@@ -68,6 +68,8 @@
 	int     port;		/* Port to connect. */
 	int     connection_attempts;	/* Max attempts (seconds) before
 					 * giving up */
+	int     connection_timeout;	/* Max time (seconds) before
+					 * aborting connection attempt */
 	int     number_of_password_prompts;	/* Max number of password
 						 * prompts. */
 	int     cipher;		/* Cipher to use. */
--- openssh-3.0.2p1/ssh.1.ORIG	Mon Nov 12 01:05:49 2001
+++ openssh-3.0.2p1/ssh.1	Wed Feb 20 20:08:20 2002
@@ -804,6 +804,12 @@
 The argument must be an integer.
 This may be useful in scripts if the connection sometimes fails.
 The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout used when connecting to the ssh
+server, instead of using default system values. This value is used
+only when the target is down or really unreachable, not when it
+refuses the connection. This may be usefull for tools using ssh
+for communication, as it avoid long TCP timeouts.
 .It Cm DynamicForward
 Specifies that a TCP/IP port on the local machine be forwarded
 over the secure channel, and the application
--- openssh-3.0.2p1/ssh.c.ORIG	Mon Nov 12 00:52:04 2001
+++ openssh-3.0.2p1/ssh.c	Wed Feb 20 20:08:20 2002
@@ -674,7 +674,7 @@
 	/* Open a connection to the remote host. */
 
 	cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,
-	    options.connection_attempts,
+	    options.connection_attempts, options.connection_timeout,
 	    original_effective_uid != 0 || !options.use_privileged_port,
 	    pw, options.proxy_command);
 
--- openssh-3.0.2p1/sshconnect.c.ORIG	Wed Oct 10 07:07:45 2001
+++ openssh-3.0.2p1/sshconnect.c	Wed Feb 20 20:08:52 2002
@@ -221,6 +221,64 @@
 	return sock;
 }
 
+int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+    socklen_t addrlen, int timeout)
+{
+	int rc;
+	fd_set fds;
+
+        int optval = 0;
+        socklen_t optlen = sizeof(optval);
+	struct timeval tv;
+
+
+	if (timeout <= 0)
+		return(connect(sockfd, serv_addr, addrlen));
+
+	if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
+	{
+		return -1;
+	}
+
+	rc = connect(sockfd, serv_addr, addrlen);
+	if (rc == 0)
+		return 0;
+	if (errno != EINPROGRESS)
+		return -1;
+
+	FD_ZERO(&fds);
+	FD_SET(sockfd, &fds);
+	tv.tv_sec = timeout;
+	tv.tv_usec = 0;
+	rc=select(sockfd+1, NULL, &fds, NULL, &tv);
+
+	switch(rc) {
+	case 0:
+		errno = ETIMEDOUT;
+	case -1:
+		return -1;
+		break;
+	case 1:
+		if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1)
+			return -1;
+		if (optval != 0)
+		{
+			errno = optval;
+			return -1;
+		}
+		return 0;
+
+	default:
+		/* Should not occur */
+		return -1;
+		break;
+	}
+
+	return -1;
+
+}
+
 /*
  * Opens a TCP/IP connection to the remote server on the given host.
  * The address of the remote host will be returned in hostaddr.
@@ -240,7 +298,7 @@
  */
 int
 ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
-    u_short port, int family, int connection_attempts,
+    u_short port, int family, int connection_attempts, int connection_timeout,
     int anonymous, struct passwd *pw, const char *proxy_command)
 {
 	int gaierr;
@@ -322,7 +380,8 @@
 			 * the remote uid as root.
 			 */
 			temporarily_use_uid(pw);
-			if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
+			if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
+					connection_timeout) >= 0) {
 				/* Successful connection. */
 				memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
 				restore_uid();
--- openssh-3.0.2p1/sshconnect.h.ORIG	Wed Oct 10 07:07:45 2001
+++ openssh-3.0.2p1/sshconnect.h	Wed Feb 20 20:08:20 2002
@@ -28,7 +28,7 @@
 
 int
 ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int,
-    int, struct passwd *, const char *);
+    int, int, struct passwd *, const char *);
 
 void
 ssh_login(Key **, int, const char *, struct sockaddr *, struct passwd *);


More information about the openssh-unix-dev mailing list