[PATCH] Connect timeout

Jean-Charles Longuet jclonguet at free.fr
Sun Jan 27 09:45:39 EST 2002


The attached patch adds a new 'ConnectTimeout' option (man page updated
in patch) to avoid wasting time when the target host is down. I needed that
because I was using rsync/rdist over ssh for massive files update and the
default connect() took too long for my purpose.

 The patch was tested on Linux only, but I used a similar one for ssh 1.2.XX
on Linux, Solaris and HP-UX without problems.

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

 PS: I did not suscribe to the list, so please cc: me regarding this patch
-------------- next part --------------
--- includes.h.OK	Thu Sep 20 04:07:51 2001
+++ includes.h	Sat Jan 26 21:44:35 2002
@@ -44,6 +44,8 @@
 #include <grp.h>
 #include <time.h>
 #include <dirent.h>
+#include <setjmp.h>
+#include <signal.h>
 
 #ifdef HAVE_LIMITS_H
 # include <limits.h>
--- readconf.c.OK	Wed Oct  3 19:39:39 2001
+++ readconf.c	Sat Jan 26 21:44:35 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,11 @@
 		/* don't panic, but count bad options */
 		return -1;
 		/* NOTREACHED */
+
+	case oConnectTimeout:
+		intptr = &options->connection_timeout;
+		goto parse_int;
+
 	case oForwardAgent:
 		intptr = &options->forward_agent;
 parse_flag:
@@ -775,6 +782,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;
--- readconf.h.OK	Wed Oct  3 19:39:39 2001
+++ readconf.h	Sat Jan 26 21:44:35 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. */
--- ssh.1.OK	Mon Nov 12 01:05:49 2001
+++ ssh.1	Sat Jan 26 21:44:35 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 (in seconds) 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 waits.
 .It Cm DynamicForward
 Specifies that a TCP/IP port on the local machine be forwarded
 over the secure channel, and the application
--- ssh.c.OK	Mon Nov 12 00:52:04 2001
+++ ssh.c	Sat Jan 26 21:44:35 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);
 
--- sshconnect.c.OK	Wed Oct 10 07:07:45 2001
+++ sshconnect.c	Sat Jan 26 21:44:35 2002
@@ -35,6 +35,8 @@
 char *client_version_string = NULL;
 char *server_version_string = NULL;
 
+static jmp_buf	jmpenv;
+
 extern Options options;
 extern char *__progname;
 
@@ -221,6 +223,43 @@
 	return sock;
 }
 
+/* for alarm() */
+static void
+timeout_sigh(int dummy)
+{
+	errno = ETIMEDOUT;
+	longjmp(jmpenv, !0);
+}
+
+int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+    socklen_t addrlen, int timeout)
+{
+	void (*sigh)(int);
+	int rc;
+
+	if (timeout <= 0)
+		return(connect(sockfd, serv_addr, addrlen));
+
+	if (setjmp(jmpenv) == 0)
+	{
+		debug("ssh: setting connect() timeout to %d s.",
+			timeout);
+		sigh = signal(SIGALRM, timeout_sigh);
+		if (sigh == SIG_ERR)
+			sigh = SIG_IGN; /* For further restore */
+		(void) alarm((unsigned int) timeout);
+		rc = connect(sockfd, serv_addr, addrlen);
+		/* restore previous behaviour */
+		(void) alarm((unsigned int) 0);
+		(void) signal(SIGALRM, sigh);
+		return rc;
+	} else {
+		errno = ETIMEDOUT;
+		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 +279,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 +361,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();
--- sshconnect.h.OK	Wed Oct 10 07:07:45 2001
+++ sshconnect.h	Sat Jan 26 21:44:35 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