version 1.109, 2001/06/23 15:12:21 |
version 1.110, 2001/07/25 14:35:18 |
|
|
/* AF_UNSPEC or AF_INET or AF_INET6 */ |
/* AF_UNSPEC or AF_INET or AF_INET6 */ |
extern int IPv4or6; |
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. |
* Connect to the given ssh server using a proxy command. |
*/ |
*/ |
|
|
/* Set the connection file descriptors. */ |
/* Set the connection file descriptors. */ |
packet_set_connection(pout[0], pin[1]); |
packet_set_connection(pout[0], pin[1]); |
|
|
return 1; |
/* Indicate OK return */ |
|
return 0; |
} |
} |
|
|
/* |
/* |
|
|
* second). If proxy_command is non-NULL, it specifies the command (with %h |
* 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 |
* and %p substituted for host and port, respectively) to use to contact |
* the daemon. |
* 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 |
int |
ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
|
|
struct addrinfo hints, *ai, *aitop; |
struct addrinfo hints, *ai, *aitop; |
struct linger linger; |
struct linger linger; |
struct servent *sp; |
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", |
debug("ssh_connect: getuid %u geteuid %u anon %d", |
(u_int) getuid(), (u_int) geteuid(), anonymous); |
(u_int) getuid(), (u_int) geteuid(), anonymous); |
|
|
* Try to connect several times. On some machines, the first time |
* Try to connect several times. On some machines, the first time |
* will sometimes fail. In general socket code appears to behave |
* will sometimes fail. In general socket code appears to behave |
* quite magically on many machines. |
* quite magically on many machines. |
*/ |
*/ |
for (attempt = 0; attempt < connection_attempts; attempt++) { |
for (attempt = 0; ;) { |
if (attempt > 0) |
if (attempt > 0) |
debug("Trying again..."); |
debug("Trying again..."); |
|
|
|
|
!anonymous && geteuid() == 0, |
!anonymous && geteuid() == 0, |
ai->ai_family); |
ai->ai_family); |
if (sock < 0) |
if (sock < 0) |
|
/* Any error is already output */ |
continue; |
continue; |
|
|
/* Connect to the host. We use the user's uid in the |
/* Connect to the host. We use the user's uid in the |
|
|
restore_uid(); |
restore_uid(); |
break; |
break; |
} else { |
} 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(); |
restore_uid(); |
/* |
/* |
* Close the failed socket; there appear to |
* Close the failed socket; there appear to |
|
|
if (ai) |
if (ai) |
break; /* Successful connection. */ |
break; /* Successful connection. */ |
|
|
|
attempt++; |
|
if (attempt >= connection_attempts) |
|
break; |
/* Sleep a moment before retrying. */ |
/* Sleep a moment before retrying. */ |
sleep(1); |
sleep(1); |
} |
} |
|
|
|
|
/* Return failure if we didn't get a successful connection. */ |
/* Return failure if we didn't get a successful connection. */ |
if (attempt >= connection_attempts) |
if (attempt >= connection_attempts) |
return 0; |
return full_failure ? ECONNABORTED : ECONNREFUSED; |
|
|
debug("Connection established."); |
debug("Connection established."); |
|
|
|
|
/* Set the connection. */ |
/* Set the connection. */ |
packet_set_connection(sock, sock); |
packet_set_connection(sock, sock); |
|
|
return 1; |
return 0; |
} |
} |
|
|
/* |
/* |