summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-08-03 16:04:46 +1000
committerDamien Miller <djm@mindrot.org>2010-08-03 16:04:46 +1000
commite11e1ea5d475ee8be0038d64aa3e47c776295ac2 (patch)
tree88fa00ef41babbec7cb33e68f400e3a1ff787230 /clientloop.c
parentc4bb91c79c0a05d2bbf2ac68b7be8421fb4957bf (diff)
- djm@cvs.openbsd.org 2010/07/19 09:15:12
[clientloop.c readconf.c readconf.h ssh.c ssh_config.5] add a "ControlPersist" option that automatically starts a background ssh(1) multiplex master when connecting. This connection can stay alive indefinitely, or can be set to automatically close after a user-specified duration of inactivity. bz#1330 - patch by dwmw2 AT infradead.org, but further hacked on by wmertens AT cisco.com, apb AT cequrux.com, martin-mindrot-bugzilla AT earth.li and myself; "looks ok" markus@
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/clientloop.c b/clientloop.c
index 5608bcc2e..de7979366 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.221 2010/06/25 23:15:36 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm 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
@@ -145,6 +145,9 @@ static volatile sig_atomic_t received_signal = 0;
145/* Flag indicating whether the user's terminal is in non-blocking mode. */ 145/* Flag indicating whether the user's terminal is in non-blocking mode. */
146static int in_non_blocking_mode = 0; 146static int in_non_blocking_mode = 0;
147 147
148/* Time when backgrounded control master using ControlPersist should exit */
149static time_t control_persist_exit_time = 0;
150
148/* Common data for the client loop code. */ 151/* Common data for the client loop code. */
149volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ 152volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
150static int escape_char1; /* Escape character. (proto1 only) */ 153static int escape_char1; /* Escape character. (proto1 only) */
@@ -252,6 +255,34 @@ get_current_time(void)
252 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; 255 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
253} 256}
254 257
258/*
259 * Sets control_persist_exit_time to the absolute time when the
260 * backgrounded control master should exit due to expiry of the
261 * ControlPersist timeout. Sets it to 0 if we are not a backgrounded
262 * control master process, or if there is no ControlPersist timeout.
263 */
264static void
265set_control_persist_exit_time(void)
266{
267 if (muxserver_sock == -1 || !options.control_persist
268 || options.control_persist_timeout == 0)
269 /* not using a ControlPersist timeout */
270 control_persist_exit_time = 0;
271 else if (channel_still_open()) {
272 /* some client connections are still open */
273 if (control_persist_exit_time > 0)
274 debug2("%s: cancel scheduled exit", __func__);
275 control_persist_exit_time = 0;
276 } else if (control_persist_exit_time <= 0) {
277 /* a client connection has recently closed */
278 control_persist_exit_time = time(NULL) +
279 (time_t)options.control_persist_timeout;
280 debug2("%s: schedule exit in %d seconds", __func__,
281 options.control_persist_timeout);
282 }
283 /* else we are already counting down to the timeout */
284}
285
255#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" 286#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
256void 287void
257client_x11_get_proto(const char *display, const char *xauth_path, 288client_x11_get_proto(const char *display, const char *xauth_path,
@@ -533,6 +564,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
533 int *maxfdp, u_int *nallocp, int rekeying) 564 int *maxfdp, u_int *nallocp, int rekeying)
534{ 565{
535 struct timeval tv, *tvp; 566 struct timeval tv, *tvp;
567 int timeout_secs;
536 int ret; 568 int ret;
537 569
538 /* Add any selections by the channel mechanism. */ 570 /* Add any selections by the channel mechanism. */
@@ -576,16 +608,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
576 /* 608 /*
577 * Wait for something to happen. This will suspend the process until 609 * Wait for something to happen. This will suspend the process until
578 * some selected descriptor can be read, written, or has some other 610 * some selected descriptor can be read, written, or has some other
579 * event pending. 611 * event pending, or a timeout expires.
580 */ 612 */
581 613
582 if (options.server_alive_interval == 0 || !compat20) 614 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
615 if (options.server_alive_interval > 0 && compat20)
616 timeout_secs = options.server_alive_interval;
617 set_control_persist_exit_time();
618 if (control_persist_exit_time > 0) {
619 timeout_secs = MIN(timeout_secs,
620 control_persist_exit_time - time(NULL));
621 if (timeout_secs < 0)
622 timeout_secs = 0;
623 }
624 if (timeout_secs == INT_MAX)
583 tvp = NULL; 625 tvp = NULL;
584 else { 626 else {
585 tv.tv_sec = options.server_alive_interval; 627 tv.tv_sec = timeout_secs;
586 tv.tv_usec = 0; 628 tv.tv_usec = 0;
587 tvp = &tv; 629 tvp = &tv;
588 } 630 }
631
589 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); 632 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
590 if (ret < 0) { 633 if (ret < 0) {
591 char buf[100]; 634 char buf[100];
@@ -1478,6 +1521,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1478 */ 1521 */
1479 if (FD_ISSET(connection_out, writeset)) 1522 if (FD_ISSET(connection_out, writeset))
1480 packet_write_poll(); 1523 packet_write_poll();
1524
1525 /*
1526 * If we are a backgrounded control master, and the
1527 * timeout has expired without any active client
1528 * connections, then quit.
1529 */
1530 if (control_persist_exit_time > 0) {
1531 if (time(NULL) >= control_persist_exit_time) {
1532 debug("ControlPersist timeout expired");
1533 break;
1534 }
1535 }
1481 } 1536 }
1482 if (readset) 1537 if (readset)
1483 xfree(readset); 1538 xfree(readset);