[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