summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/clientloop.c b/clientloop.c
index 42ace7789..2cebea29f 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.344 2020/04/24 02:19:40 dtucker Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.346 2020/09/16 03:07:31 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -166,6 +166,7 @@ static int connection_out; /* Connection to server (output). */
166static int need_rekeying; /* Set to non-zero if rekeying is requested. */ 166static int need_rekeying; /* Set to non-zero if rekeying is requested. */
167static int session_closed; /* In SSH2: login session closed. */ 167static int session_closed; /* In SSH2: login session closed. */
168static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */ 168static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
169static time_t server_alive_time; /* Time to do server_alive_check */
169 170
170static void client_init_dispatch(struct ssh *ssh); 171static void client_init_dispatch(struct ssh *ssh);
171int session_ident = -1; 172int session_ident = -1;
@@ -471,6 +472,13 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
471} 472}
472 473
473static void 474static void
475schedule_server_alive_check(void)
476{
477 if (options.server_alive_interval > 0)
478 server_alive_time = monotime() + options.server_alive_interval;
479}
480
481static void
474server_alive_check(struct ssh *ssh) 482server_alive_check(struct ssh *ssh)
475{ 483{
476 int r; 484 int r;
@@ -486,6 +494,7 @@ server_alive_check(struct ssh *ssh)
486 fatal("%s: send packet: %s", __func__, ssh_err(r)); 494 fatal("%s: send packet: %s", __func__, ssh_err(r));
487 /* Insert an empty placeholder to maintain ordering */ 495 /* Insert an empty placeholder to maintain ordering */
488 client_register_global_confirm(NULL, NULL); 496 client_register_global_confirm(NULL, NULL);
497 schedule_server_alive_check();
489} 498}
490 499
491/* 500/*
@@ -499,7 +508,7 @@ client_wait_until_can_do_something(struct ssh *ssh,
499{ 508{
500 struct timeval tv, *tvp; 509 struct timeval tv, *tvp;
501 int timeout_secs; 510 int timeout_secs;
502 time_t minwait_secs = 0, server_alive_time = 0, now = monotime(); 511 time_t minwait_secs = 0, now = monotime();
503 int r, ret; 512 int r, ret;
504 513
505 /* Add any selections by the channel mechanism. */ 514 /* Add any selections by the channel mechanism. */
@@ -528,10 +537,8 @@ client_wait_until_can_do_something(struct ssh *ssh,
528 */ 537 */
529 538
530 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ 539 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
531 if (options.server_alive_interval > 0) { 540 if (options.server_alive_interval > 0)
532 timeout_secs = options.server_alive_interval; 541 timeout_secs = MAXIMUM(server_alive_time - now, 0);
533 server_alive_time = now + options.server_alive_interval;
534 }
535 if (options.rekey_interval > 0 && !rekeying) 542 if (options.rekey_interval > 0 && !rekeying)
536 timeout_secs = MINIMUM(timeout_secs, 543 timeout_secs = MINIMUM(timeout_secs,
537 ssh_packet_get_rekey_timeout(ssh)); 544 ssh_packet_get_rekey_timeout(ssh));
@@ -561,7 +568,6 @@ client_wait_until_can_do_something(struct ssh *ssh,
561 */ 568 */
562 memset(*readsetp, 0, *nallocp); 569 memset(*readsetp, 0, *nallocp);
563 memset(*writesetp, 0, *nallocp); 570 memset(*writesetp, 0, *nallocp);
564
565 if (errno == EINTR) 571 if (errno == EINTR)
566 return; 572 return;
567 /* Note: we might still have data in the buffers. */ 573 /* Note: we might still have data in the buffers. */
@@ -569,15 +575,14 @@ client_wait_until_can_do_something(struct ssh *ssh,
569 "select: %s\r\n", strerror(errno))) != 0) 575 "select: %s\r\n", strerror(errno))) != 0)
570 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 576 fatal("%s: buffer error: %s", __func__, ssh_err(r));
571 quit_pending = 1; 577 quit_pending = 1;
572 } else if (ret == 0) { 578 } else if (options.server_alive_interval > 0 && !FD_ISSET(connection_in,
579 *readsetp) && monotime() >= server_alive_time)
573 /* 580 /*
574 * Timeout. Could have been either keepalive or rekeying. 581 * ServerAlive check is needed. We can't rely on the select
575 * Keepalive we check here, rekeying is checked in clientloop. 582 * timing out since traffic on the client side such as port
583 * forwards can keep waking it up.
576 */ 584 */
577 if (server_alive_time != 0 && server_alive_time <= monotime()) 585 server_alive_check(ssh);
578 server_alive_check(ssh);
579 }
580
581} 586}
582 587
583static void 588static void
@@ -617,6 +622,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset)
617 * the packet subsystem. 622 * the packet subsystem.
618 */ 623 */
619 if (FD_ISSET(connection_in, readset)) { 624 if (FD_ISSET(connection_in, readset)) {
625 schedule_server_alive_check();
620 /* Read as much as possible. */ 626 /* Read as much as possible. */
621 len = read(connection_in, buf, sizeof(buf)); 627 len = read(connection_in, buf, sizeof(buf));
622 if (len == 0) { 628 if (len == 0) {
@@ -1236,7 +1242,6 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1236 int r, max_fd = 0, max_fd2 = 0, len; 1242 int r, max_fd = 0, max_fd2 = 0, len;
1237 u_int64_t ibytes, obytes; 1243 u_int64_t ibytes, obytes;
1238 u_int nalloc = 0; 1244 u_int nalloc = 0;
1239 char buf[100];
1240 1245
1241 debug("Entering interactive session."); 1246 debug("Entering interactive session.");
1242 1247
@@ -1318,6 +1323,8 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1318 client_channel_closed, 0); 1323 client_channel_closed, 0);
1319 } 1324 }
1320 1325
1326 schedule_server_alive_check();
1327
1321 /* Main loop of the client for the interactive session mode. */ 1328 /* Main loop of the client for the interactive session mode. */
1322 while (!quit_pending) { 1329 while (!quit_pending) {
1323 1330
@@ -1472,7 +1479,6 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1472 } 1479 }
1473 1480
1474 /* Clear and free any buffers. */ 1481 /* Clear and free any buffers. */
1475 explicit_bzero(buf, sizeof(buf));
1476 sshbuf_free(stderr_buffer); 1482 sshbuf_free(stderr_buffer);
1477 1483
1478 /* Report bytes transferred, and transfer rates. */ 1484 /* Report bytes transferred, and transfer rates. */