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.1p1-timeout.patch Can someone tell we if such a patch can be included in the main tree ? PS: I did not suscribe to the list, so please cc: me regarding this patch -- Jean-Charles Longuet -------------- next part -------------- --- openssh-3.0.1p1/ssh.1.ORIG Sat Nov 17 23:07:02 2001 +++ openssh-3.0.1p1/ssh.1 Sat Nov 17 23:09:39 2001 @@ -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 --- openssh-3.0.1p1/includes.h.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/includes.h Sat Nov 17 22:49:47 2001 @@ -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> --- openssh-3.0.1p1/readconf.c.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/readconf.c Sat Nov 17 22:49:47 2001 @@ -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; --- openssh-3.0.1p1/readconf.h.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/readconf.h Sat Nov 17 22:49:47 2001 @@ -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.1p1/ssh.c.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/ssh.c Sat Nov 17 22:49:47 2001 @@ -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.1p1/sshconnect.c.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/sshconnect.c Sat Nov 17 23:02:27 2001 @@ -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(); --- openssh-3.0.1p1/sshconnect.h.ORIG Sat Nov 17 22:49:09 2001 +++ openssh-3.0.1p1/sshconnect.h Sat Nov 17 22:49:47 2001 @@ -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 *);