summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2003-05-15 14:55:26 +0000
committerDamien Miller <djm@cvs.openbsd.org>2003-05-15 14:55:26 +0000
commit4e0284f2e58d40fb42018d1d51372eeaf35ddd8a (patch)
treecbc734c803774857df8eb2112a82992db7cbe699 /usr.bin/ssh
parent686e678ff69aa56b59228870bcf4f45642e35766 (diff)
add a ConnectTimeout option to ssh, based on patch from
Jean-Charles Longuet (jclonguet at free.fr); portable #207 ok markus@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/readconf.c20
-rw-r--r--usr.bin/ssh/readconf.h4
-rw-r--r--usr.bin/ssh/ssh_config3
-rw-r--r--usr.bin/ssh/ssh_config.57
-rw-r--r--usr.bin/ssh/sshconnect.c70
5 files changed, 97 insertions, 7 deletions
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
index adbb13fa435..df769736403 100644
--- a/usr.bin/ssh/readconf.c
+++ b/usr.bin/ssh/readconf.c
@@ -12,7 +12,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.110 2003/05/15 14:02:47 jakob Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.111 2003/05/15 14:55:25 djm Exp $");
#include "ssh.h"
#include "xmalloc.h"
@@ -106,7 +106,7 @@ typedef enum {
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS,
+ oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oDeprecated, oUnsupported
} OpCodes;
@@ -193,6 +193,7 @@ static struct {
#endif
{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
{ "rekeylimit", oRekeyLimit },
+ { "connecttimeout", oConnectTimeout },
{ NULL, oBadOption }
};
@@ -307,6 +308,20 @@ process_config_line(Options *options, const char *host,
/* 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("%s line %d: missing time value.",
+ filename, linenum);
+ if ((value = convtime(arg)) == -1)
+ fatal("%s line %d: invalid time value.",
+ filename, linenum);
+ if (*intptr == -1)
+ *intptr = value;
+ break;
+
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
@@ -806,6 +821,7 @@ initialize_options(Options * options)
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;
diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h
index 991e20091e5..c884de68b76 100644
--- a/usr.bin/ssh/readconf.h
+++ b/usr.bin/ssh/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.49 2003/05/15 01:48:10 jakob Exp $ */
+/* $OpenBSD: readconf.h,v 1.50 2003/05/15 14:55:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -60,6 +60,8 @@ typedef struct {
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. */
diff --git a/usr.bin/ssh/ssh_config b/usr.bin/ssh/ssh_config
index 94cffbf395a..8a0acc17ffd 100644
--- a/usr.bin/ssh/ssh_config
+++ b/usr.bin/ssh/ssh_config
@@ -1,4 +1,4 @@
-# $OpenBSD: ssh_config,v 1.16 2002/07/03 14:21:05 markus Exp $
+# $OpenBSD: ssh_config,v 1.17 2003/05/15 14:55:25 djm Exp $
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
@@ -25,6 +25,7 @@
# HostbasedAuthentication no
# BatchMode no
# CheckHostIP yes
+# ConnectTimeout 0
# StrictHostKeyChecking ask
# IdentityFile ~/.ssh/identity
# IdentityFile ~/.ssh/id_rsa
diff --git a/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5
index 2f33aa3f3fd..c5de4a9de92 100644
--- a/usr.bin/ssh/ssh_config.5
+++ b/usr.bin/ssh/ssh_config.5
@@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.8 2003/05/14 18:16:20 jakob Exp $
+.\" $OpenBSD: ssh_config.5,v 1.9 2003/05/15 14:55:25 djm Exp $
.Dd September 25, 1999
.Dt SSH_CONFIG 5
.Os
@@ -227,6 +227,11 @@ Specifies the number of tries (one per second) to make before exiting.
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 the default system TCP timeout. This value is
+used only when the target is down or really unreachable, not when it
+refuses the connection.
.It Cm DynamicForward
Specifies that a TCP/IP port on the local machine be forwarded
over the secure channel, and the application
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index 20d4c1d0d45..cfc492f5337 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.140 2003/05/14 18:16:21 jakob Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.141 2003/05/15 14:55:25 djm Exp $");
#include <openssl/bn.h>
@@ -214,6 +214,71 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
return sock;
}
+static 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;
+
+ for(;;) {
+ rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
+ if (rc != -1 || errno != EINTR)
+ break;
+ }
+
+ switch(rc) {
+ case 0:
+ /* Timed out */
+ errno = ETIMEDOUT;
+ return (-1);
+ case -1:
+ /* Select error */
+ debug("select: %s", strerror(errno));
+ return (-1);
+ case 1:
+ /* Completed or failed */
+ optval = 0;
+ optlen = sizeof(optval);
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
+ &optlen) == -1)
+ debug("getsockopt: %s", strerror(errno));
+ return (-1);
+ if (optval != 0) {
+ errno = optval;
+ return (-1);
+ }
+ break;
+ default:
+ /* Should not occur */
+ fatal("Bogus return (%d) from select()", rc);
+ }
+
+ return (0);
+}
+
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
@@ -302,7 +367,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
/* 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,
+ options.connection_timeout) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
break;