- markus@cvs.openbsd.org 2001/07/25 14:35:18
     [readconf.c ssh.1 ssh.c sshconnect.c]
     cleanup connect(); connection_attempts 4 -> 1; from
eivind@freebsd.org
diff --git a/ChangeLog b/ChangeLog
index a844251..d5f7f66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -32,6 +32,10 @@
    - markus@cvs.openbsd.org 2001/07/25 11:59:35
      [scard.c]
      typo in comment
+   - markus@cvs.openbsd.org 2001/07/25 14:35:18
+     [readconf.c ssh.1 ssh.c sshconnect.c]
+     cleanup connect(); connection_attempts 4 -> 1; from 
+     eivind@freebsd.org
 
 20010803
  - (djm) Fix interrupted read in entropy gatherer. Spotted by markus@ on
@@ -6142,4 +6146,4 @@
  - Wrote replacements for strlcpy and mkdtemp
  - Released 1.0pre1
 
-$Id: ChangeLog,v 1.1435 2001/08/06 21:05:05 mouring Exp $
+$Id: ChangeLog,v 1.1436 2001/08/06 21:07:11 mouring Exp $
diff --git a/readconf.c b/readconf.c
index 36700fb..6519ec6 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.83 2001/07/22 22:04:19 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.84 2001/07/25 14:35:18 markus Exp $");
 
 #include "ssh.h"
 #include "xmalloc.h"
@@ -843,7 +843,7 @@
 	if (options->port == -1)
 		options->port = 0;	/* Filled in ssh_connect. */
 	if (options->connection_attempts == -1)
-		options->connection_attempts = 4;
+		options->connection_attempts = 1;
 	if (options->number_of_password_prompts == -1)
 		options->number_of_password_prompts = 3;
 	/* Selected in ssh_login(). */
diff --git a/ssh.1 b/ssh.1
index b96edea..32d54c3 100644
--- a/ssh.1
+++ b/ssh.1
@@ -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.1,v 1.123 2001/07/23 12:47:05 markus Exp $
+.\" $OpenBSD: ssh.1,v 1.124 2001/07/25 14:35:18 markus Exp $
 .Dd September 25, 1999
 .Dt SSH 1
 .Os
@@ -732,7 +732,7 @@
 back to rsh or exiting.
 The argument must be an integer.
 This may be useful in scripts if the connection sometimes fails.
-The default is 4.
+The default is 1.
 .It Cm EscapeChar
 Sets the escape character (default:
 .Ql ~ ) .
diff --git a/ssh.c b/ssh.c
index 374630f..7810cd1 100644
--- a/ssh.c
+++ b/ssh.c
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.129 2001/07/11 16:29:59 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.130 2001/07/25 14:35:18 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -252,7 +252,7 @@
 int
 main(int ac, char **av)
 {
-	int i, opt, exit_status, ok;
+	int i, opt, exit_status, cerr;
 	u_short fwd_port, fwd_host_port;
 	char *p, *cp, buf[256];
 	struct stat st;
@@ -666,7 +666,7 @@
 
 	/* Open a connection to the remote host. */
 
-	ok = ssh_connect(host, &hostaddr, options.port,
+	cerr = ssh_connect(host, &hostaddr, options.port,
 	    options.connection_attempts,
 	    original_effective_uid != 0 || !options.use_privileged_port,
 	    pw, options.proxy_command);
@@ -679,7 +679,7 @@
 	 */
 	sensitive_data.nkeys = 0;
 	sensitive_data.keys = NULL;
-	if (ok && (options.rhosts_rsa_authentication ||
+	if (!cerr && (options.rhosts_rsa_authentication ||
 	    options.hostbased_authentication)) {
 		sensitive_data.nkeys = 3;
 		sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
@@ -717,20 +717,19 @@
 			error("Could not create directory '%.200s'.", buf);
 
 	/* Check if the connection failed, and try "rsh" if appropriate. */
-	if (!ok) {
+	if (cerr) {
+		if (!options.fallback_to_rsh)
+			exit(1);
 		if (options.port != 0)
-			log("Secure connection to %.100s on port %hu refused%.100s.",
-			    host, options.port,
-			    options.fallback_to_rsh ? "; reverting to insecure method" : "");
+			log("Secure connection to %.100s on port %hu refused; "
+			    "reverting to insecure method",
+			    host, options.port);
 		else
-			log("Secure connection to %.100s refused%.100s.", host,
-			    options.fallback_to_rsh ? "; reverting to insecure method" : "");
+			log("Secure connection to %.100s refused; "
+			    "reverting to insecure method.", host);
 
-		if (options.fallback_to_rsh) {
-			rsh_connect(host, options.user, &command);
-			fatal("rsh_connect returned");
-		}
-		exit(1);
+		rsh_connect(host, options.user, &command);
+		fatal("rsh_connect returned");
 	}
 	/* load options.identity_files */
 	load_public_identity_files();
diff --git a/sshconnect.c b/sshconnect.c
index 745eeb5..27b3387 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshconnect.c,v 1.109 2001/06/23 15:12:21 itojun Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.110 2001/07/25 14:35:18 markus Exp $");
 
 #include <openssl/bn.h>
 
@@ -41,6 +41,27 @@
 /* AF_UNSPEC or AF_INET or AF_INET6 */
 extern int IPv4or6;
 
+static const char *
+sockaddr_ntop(struct sockaddr *sa)
+{
+	void *addr;
+	static char addrbuf[INET6_ADDRSTRLEN];
+
+	switch (sa->sa_family) {
+		case AF_INET:
+			addr = &((struct sockaddr_in *)sa)->sin_addr;
+			break;
+		case AF_INET6:
+			addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
+			break;
+		default:
+			/* This case should be protected against elsewhere */
+			abort();
+	}
+	inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
+	return addrbuf;
+}
+
 /*
  * Connect to the given ssh server using a proxy command.
  */
@@ -138,7 +159,8 @@
 	/* Set the connection file descriptors. */
 	packet_set_connection(pout[0], pin[1]);
 
-	return 1;
+	/* Indicate OK return */
+	return 0;
 }
 
 /*
@@ -208,6 +230,12 @@
  * second).  If proxy_command is non-NULL, it specifies the command (with %h
  * and %p substituted for host and port, respectively) to use to contact
  * the daemon.
+ * Return values:
+ *    0 for OK
+ *    ECONNREFUSED if we got a "Connection Refused" by the peer on any address
+ *    ECONNABORTED if we failed without a "Connection refused"
+ * Suitable error messages for the connection failure will already have been
+ * printed.
  */
 int
 ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
@@ -222,6 +250,12 @@
 	struct addrinfo hints, *ai, *aitop;
 	struct linger linger;
 	struct servent *sp;
+	/*
+	 * Did we get only other errors than "Connection refused" (which
+	 * should block fallback to rsh and similar), or did we get at least
+	 * one "Connection refused"?
+	 */
+	int full_failure = 1;
 
 	debug("ssh_connect: getuid %u geteuid %u anon %d",
 	      (u_int) getuid(), (u_int) geteuid(), anonymous);
@@ -252,8 +286,8 @@
 	 * Try to connect several times.  On some machines, the first time
 	 * will sometimes fail.  In general socket code appears to behave
 	 * quite magically on many machines.
-	 */
-	for (attempt = 0; attempt < connection_attempts; attempt++) {
+		 */
+	for (attempt = 0; ;) {
 		if (attempt > 0)
 			debug("Trying again...");
 
@@ -280,6 +314,7 @@
 #endif
 			    ai->ai_family);
 			if (sock < 0)
+				/* Any error is already output */
 				continue;
 
 			/* Connect to the host.  We use the user's uid in the
@@ -293,7 +328,11 @@
 				restore_uid();
 				break;
 			} else {
-				debug("connect: %.100s", strerror(errno));
+				if (errno == ECONNREFUSED)
+					full_failure = 0;
+				log("ssh: connect to address %s port %s: %s",
+				    sockaddr_ntop(ai->ai_addr), strport,
+				    strerror(errno));
 				restore_uid();
 				/*
 				 * Close the failed socket; there appear to
@@ -308,6 +347,9 @@
 		if (ai)
 			break;	/* Successful connection. */
 
+		attempt++;
+		if (attempt >= connection_attempts)
+			break;
 		/* Sleep a moment before retrying. */
 		sleep(1);
 	}
@@ -316,7 +358,7 @@
 
 	/* Return failure if we didn't get a successful connection. */
 	if (attempt >= connection_attempts)
-		return 0;
+		return full_failure ? ECONNABORTED : ECONNREFUSED;
 
 	debug("Connection established.");
 
@@ -338,7 +380,7 @@
 	/* Set the connection. */
 	packet_set_connection(sock, sock);
 
-	return 1;
+	return 0;
 }
 
 /*