Connect timeout patch
Jean-Charles Longuet
jclonguet at free.fr
Wed Apr 16 07:40:33 EST 2003
This patch avoids spending too much time during connect() when doing an
ssh()/scp() on a down host. It uses a new client option called
ConnectTimeout and is useful for rsync or rdist commands using ssh().
See http://bugzilla.mindrot.org/show_bug.cgi?id=207 for detailled info.
-------------- next part --------------
--- openssh-3.6.1p1/readconf.c.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/readconf.c Tue Apr 15 23:09:43 2003
@@ -114,7 +114,7 @@
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oEnableSSHKeysign,
+ oEnableSSHKeysign, oConnectTimeout,
oDeprecated
} OpCodes;
@@ -188,6 +188,7 @@
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+ { "connecttimeout", oConnectTimeout },
{ NULL, oBadOption }
};
@@ -297,6 +298,18 @@
/* 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:
@@ -770,6 +783,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.6.1p1/readconf.h.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/readconf.h Tue Apr 15 23:08:28 2003
@@ -66,6 +66,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.6.1p1/ssh.c.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/ssh.c Tue Apr 15 23:08:28 2003
@@ -619,7 +619,7 @@
/* Open a connection to the remote host. */
if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
- options.connection_attempts,
+ options.connection_attempts, options.connection_timeout,
#ifdef HAVE_CYGWIN
options.use_privileged_port,
#else
--- openssh-3.6.1p1/ssh_config.0.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/ssh_config.0 Tue Apr 15 23:11:06 2003
@@ -112,6 +112,13 @@
exiting. The argument must be an integer. This may be useful in
scripts if the connection sometimes fails. The default is 1.
+ ^[[1mConnectTimeout^[[0m
+ 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.
+
^[[1mDynamicForward^[[0m
Specifies that a TCP/IP port on the local machine be forwarded
over the secure channel, and the application protocol is then
--- openssh-3.6.1p1/ssh_config.5.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/ssh_config.5 Tue Apr 15 23:08:28 2003
@@ -227,6 +227,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.6.1p1/sshconnect.c.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/sshconnect.c Tue Apr 15 23:08:28 2003
@@ -212,6 +212,61 @@
return sock;
}
+int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+ socklen_t addrlen, int timeout)
+{
+ fd_set *fdset;
+ struct timeval tv;
+ socklen_t optlen;
+ int fdsetsz, optval, rc;
+
+ 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;
+
+ fdsetsz = howmany(sockfd+1, NFDBITS) * sizeof(fd_mask);
+ fdset = (fd_set *)xmalloc(fdsetsz);
+ memset(fdset, 0, fdsetsz);
+ FD_SET(sockfd, fdset);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ rc=select(sockfd+1, NULL, fdset, NULL, &tv);
+
+ switch(rc) {
+ case 0:
+ errno = ETIMEDOUT;
+ case -1:
+ return -1;
+ break;
+ case 1:
+ optval = 0;
+ optlen = sizeof(optval);
+ 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.
@@ -231,7 +286,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 needpriv, const char *proxy_command)
{
int gaierr;
@@ -300,7 +355,8 @@
/* Any error is already output */
continue;
- 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);
break;
--- openssh-3.6.1p1/sshconnect.h.ORIG Tue Apr 15 23:06:30 2003
+++ openssh-3.6.1p1/sshconnect.h Tue Apr 15 23:08:28 2003
@@ -35,7 +35,7 @@
int
ssh_connect(const char *, struct sockaddr_storage *, u_short, int, int,
- int, const char *);
+ int, int, const char *);
void
ssh_login(Sensitive *, const char *, struct sockaddr *, struct passwd *);
More information about the openssh-unix-dev
mailing list