|
Lines 214-219
Link Here
|
| 214 |
return sock; |
214 |
return sock; |
| 215 |
} |
215 |
} |
| 216 |
|
216 |
|
|
|
217 |
int |
| 218 |
timeout_connect(int sockfd, const struct sockaddr *serv_addr, |
| 219 |
socklen_t addrlen, int timeout) |
| 220 |
{ |
| 221 |
fd_set *fdset; |
| 222 |
struct timeval tv; |
| 223 |
socklen_t optlen; |
| 224 |
int fdsetsz, optval, rc; |
| 225 |
|
| 226 |
if (timeout <= 0) |
| 227 |
return connect(sockfd, serv_addr, addrlen); |
| 228 |
|
| 229 |
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) |
| 230 |
return -1; |
| 231 |
|
| 232 |
rc = connect(sockfd, serv_addr, addrlen); |
| 233 |
if (rc == 0) |
| 234 |
return 0; |
| 235 |
if (errno != EINPROGRESS) |
| 236 |
return -1; |
| 237 |
|
| 238 |
fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask); |
| 239 |
fdset = (fd_set *)xmalloc(fdsetsz); |
| 240 |
|
| 241 |
memset(fdset, '\0', fdsetsz); |
| 242 |
FD_SET(sockfd, fdset); |
| 243 |
tv.tv_sec = timeout; |
| 244 |
tv.tv_usec = 0; |
| 245 |
|
| 246 |
for(;;) { |
| 247 |
rc = select(sockfd + 1, NULL, fdset, NULL, &tv); |
| 248 |
if (rc != -1 || errno != EINTR) |
| 249 |
break; |
| 250 |
} |
| 251 |
|
| 252 |
switch(rc) { |
| 253 |
case 0: |
| 254 |
/* Timed out */ |
| 255 |
errno = ETIMEDOUT; |
| 256 |
return -1; |
| 257 |
case -1: |
| 258 |
/* Select error */ |
| 259 |
debug("select: %s", strerror(errno)); |
| 260 |
return -1; |
| 261 |
case 1: |
| 262 |
/* Completed or failed */ |
| 263 |
optval = 0; |
| 264 |
optlen = sizeof(optval); |
| 265 |
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, |
| 266 |
&optlen) == -1) |
| 267 |
debug("getsockopt: %s", strerror(errno)); |
| 268 |
return -1; |
| 269 |
if (optval != 0) { |
| 270 |
errno = optval; |
| 271 |
return -1; |
| 272 |
} |
| 273 |
break; |
| 274 |
default: |
| 275 |
/* Should not occur */ |
| 276 |
fatal("Bogus return (%d) from select()", rc); |
| 277 |
} |
| 278 |
|
| 279 |
return 0; |
| 280 |
} |
| 281 |
|
| 217 |
/* |
282 |
/* |
| 218 |
* Opens a TCP/IP connection to the remote server on the given host. |
283 |
* Opens a TCP/IP connection to the remote server on the given host. |
| 219 |
* The address of the remote host will be returned in hostaddr. |
284 |
* The address of the remote host will be returned in hostaddr. |
|
Lines 233-239
Link Here
|
| 233 |
*/ |
298 |
*/ |
| 234 |
int |
299 |
int |
| 235 |
ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
300 |
ssh_connect(const char *host, struct sockaddr_storage * hostaddr, |
| 236 |
u_short port, int family, int connection_attempts, |
301 |
u_short port, int family, int connection_attempts, int connection_timeout, |
| 237 |
int needpriv, const char *proxy_command) |
302 |
int needpriv, const char *proxy_command) |
| 238 |
{ |
303 |
{ |
| 239 |
int gaierr; |
304 |
int gaierr; |
|
Lines 302-308
Link Here
|
| 302 |
/* Any error is already output */ |
367 |
/* Any error is already output */ |
| 303 |
continue; |
368 |
continue; |
| 304 |
|
369 |
|
| 305 |
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { |
370 |
if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, |
|
|
371 |
connection_timeout) >= 0) { |
| 306 |
/* Successful connection. */ |
372 |
/* Successful connection. */ |
| 307 |
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); |
373 |
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); |
| 308 |
break; |
374 |
break; |